31 private static $instance;
32 private static $isEnabled =
false;
33 private static $useHTMLCache =
false;
34 private static $onBeforeHandleKey =
false;
35 private static $onRestartBufferHandleKey =
false;
36 private static $onBeforeLocalRedirect =
false;
37 private static $autoUpdate =
true;
38 private static $autoUpdateTTL = 0;
39 private static $isCompositeInjected =
false;
40 private static $isRedirect =
false;
41 private static $isBufferRestarted =
false;
46 private function __construct()
54 private function __clone()
66 if (is_null(self::$instance))
68 self::$instance =
new Engine();
71 return self::$instance;
83 if ($isEnabled && !self::$isEnabled)
87 "OnBeforeEndBufferContent",
88 array(__CLASS__,
"onBeforeEndBufferContent")
92 "OnBeforeRestartBuffer",
93 array(__CLASS__,
"onBeforeRestartBuffer")
97 "OnBeforeLocalRedirect",
98 array(__CLASS__,
"onBeforeLocalRedirect"),
101 self::$isEnabled =
true;
102 \CJSCore::init(
array(
"fc"));
104 elseif (!$isEnabled && self::$isEnabled)
106 if (self::$onBeforeHandleKey >= 0)
111 if (self::$onRestartBufferHandleKey >= 0)
116 if (self::$onBeforeLocalRedirect >= 0)
121 self::$isEnabled =
false;
132 return self::$isEnabled;
144 if (self::getUseAppCache())
146 self::setUseHTMLCache(
false);
149 $appCache->setEnabled($useAppCache);
161 return $appCache->isEnabled();
173 self::$useHTMLCache = $useHTMLCache;
184 return self::$useHTMLCache;
194 return Helper::isAjaxRequest();
199 return self::isAjaxRequest() && Context::getCurrent()->getServer()->get(
"HTTP_BX_INVALIDATE_CACHE") ===
"Y";
208 return Option::get(
"main",
"~show_composite_banner",
"Y") ==
"Y";
220 self::$autoUpdate = $flag ===
false ?
false :
true;
229 return self::$autoUpdate;
241 self::$autoUpdateTTL = intval($ttl);
250 return self::$autoUpdateTTL;
262 if (self::getUseAppCache())
265 $params = $manifest->OnBeforeEndBufferContent();
266 $params[
"CACHE_MODE"] =
"APPCACHE";
267 $params[
"PAGE_URL"] = Context::getCurrent()->getServer()->getRequestUri();
269 elseif (self::getUseHTMLCache())
272 $page->onBeforeEndBufferContent();
274 if (
$page->isCacheable())
276 $params[
"CACHE_MODE"] =
"HTMLCACHE";
278 if (self::isBannerEnabled())
283 "text" =>
GetMessage(
"COMPOSITE_BANNER_TEXT"),
284 "bgcolor" =>
$options[
"BANNER_BGCOLOR"] ??
"",
285 "style" =>
$options[
"BANNER_STYLE"] ??
""
298 foreach ($dynamicAreas as $id => $dynamicArea)
300 $stub = $dynamicArea->getStub();
301 self::replaceSessid($stub);
303 $params[
"dynamicBlocks"][$dynamicArea->getId()] = mb_substr(md5($stub), 0, 12);
304 if ($dynamicArea->getBrowserStorage())
306 $realId = $dynamicArea->getContainerId() !==
null ? $dynamicArea->getContainerId() :
"bxdynamic_".$id;
307 $params[
"storageBlocks"][] = $realId;
311 $params[
"AUTO_UPDATE"] = self::getAutoUpdate();
312 $params[
"AUTO_UPDATE_TTL"] = self::getAutoUpdateTTL();
315 Asset::getInstance()->addString(
318 AssetLocation::BEFORE_CSS,
319 self::getUseHTMLCache() ? AssetMode::COMPOSITE : AssetMode::ALL
322 self::$isCompositeInjected =
true;
333 if (!self::isEnabled() || !is_object(
$GLOBALS[
"APPLICATION"]) || !self::$isCompositeInjected)
338 if (defined(
"BX_BUFFER_SHUTDOWN") || !defined(
"B_EPILOG_INCLUDED"))
342 "TYPE" => Logger::TYPE_PHP_SHUTDOWN,
349 $newBuffer =
$GLOBALS[
"APPLICATION"]->buffer_content;
352 Asset::getInstance()->setMode(AssetMode::COMPOSITE);
354 self::$isCompositeInjected =
false;
355 for (
$i = 0;
$i < $cnt;
$i++)
363 if (in_array(
$method[1],
array(
"GetCSS",
"GetHeadScripts",
"GetHeadStrings")))
365 $newBuffer[
$i * 2 + 1] = call_user_func_array(
367 $GLOBALS[
"APPLICATION"]->buffer_content_type[
$i][
"P"]
369 if (self::$isCompositeInjected !==
true &&
$method[1] ===
"GetHeadStrings")
371 self::$isCompositeInjected =
372 str_contains($newBuffer[
$i * 2 + 1],
"w.frameRequestStart");
377 Asset::getInstance()->setMode(AssetMode::STANDARD);
379 if (!self::$isCompositeInjected)
383 "TYPE" => Logger::TYPE_COMPOSITE_NOT_INJECTED,
388 return self::$isCompositeInjected ? implode(
"", $newBuffer).$content :
null;
400 public static function endBuffering(&$originalContent, $compositeContent)
402 if (!self::isEnabled() || $compositeContent ===
null || defined(
"BX_BUFFER_SHUTDOWN") || !defined(
"B_EPILOG_INCLUDED"))
405 if (self::isAjaxRequest() && self::$isRedirect ===
false)
407 $originalContent = self::getAjaxError();
416 if (function_exists(
"getmoduleevents"))
418 foreach (
GetModuleEvents(
"main",
"OnEndBufferContent",
true) as $arEvent)
424 $compositeContent = self::processPageContent($compositeContent);
425 if (self::isAjaxRequest() || self::getUseAppCache())
427 $originalContent = $compositeContent;
449 private static function processPageContent(
$content)
453 $dividedData = self::getDividedPageData(
$content);
454 $htmlCacheChanged =
false;
456 if (self::getUseHTMLCache())
459 if (
$page->isCacheable())
461 $cacheExists =
$page->exists();
462 $rewriteCache =
$page->getMd5() !== $dividedData[
"md5"];
463 if (self::getAutoUpdate() && self::getAutoUpdateTTL() > 0 && $cacheExists)
465 $mtime =
$page->getLastModified();
466 if ($mtime !==
false && ($mtime + self::getAutoUpdateTTL()) > time())
468 $rewriteCache =
false;
472 $invalidateCache = self::getAutoUpdate() ===
false && self::isInvalidationRequest();
475 if (!$cacheExists || $rewriteCache || $invalidateCache)
477 if ($invalidateCache || Locker::lock(
$page->getCacheKey()))
479 if ($cacheExists && Logger::isOn())
481 $oldContent =
$page->read();
484 if (
$page->getStorage() instanceof Data\FileStorage)
486 $freeSpace = strlen($dividedData[
"static"]) + strlen($dividedData[
"md5"]);
487 self::ensureFileQuota($freeSpace);
490 $success =
$page->write($dividedData[
"static"], $dividedData[
"md5"]);
494 $htmlCacheChanged =
true;
495 $page->setUserPrivateKey();
498 Locker::unlock(
$page->getCacheKey());
502 $pageId = PageManager::register(
503 $page->getCacheKey(),
505 "CHANGED" => $htmlCacheChanged,
506 "SIZE" =>
$page->getSize()
510 if ($oldContent !==
null)
514 "TYPE" => Logger::TYPE_CACHE_REWRITING,
515 "MESSAGE" => $oldContent,
525 return self::getAjaxError();
529 if (self::getUseAppCache() ==
true)
531 AppCache::getInstance()->generate($dividedData[
"static"]);
535 AppCache::checkObsoleteManifest();
538 if (self::isAjaxRequest())
540 self::sendRandHeader();
542 header(
"Content-Type: application/x-javascript; charset=".
SITE_CHARSET);
543 header(
"X-Bitrix-Composite: Ajax ".($htmlCacheChanged ?
"(changed)" :
"(stable)"));
549 "htmlCacheChanged" => $htmlCacheChanged,
550 "isManifestUpdated" => AppCache::getInstance()->getIsModified(),
551 "dynamicBlocks" => $dividedData[
"dynamic"],
552 "spread" => array_map(
array(
"CUtil",
"JSEscape"),
$APPLICATION->GetSpreadCookieUrls()),
555 $content = Json::encode(
$content, Json::DEFAULT_OPTIONS & ~JSON_HEX_QUOT & ~JSON_HEX_TAG);
582 private static function getDividedPageData(
$content)
585 "dynamic" =>
array(),
590 $dynamicAreas = StaticArea::getDynamicAreas();
591 if (!empty($dynamicAreas) && ($areas = self::getFrameIndexes(
$content)) !==
false)
594 $pageBlocks = self::getPageBlocks();
595 foreach ($areas as $area)
597 $dynamicArea = StaticArea::getDynamicArea($area->id);
598 if ($dynamicArea ===
null)
603 $realId = $dynamicArea->getContainerId() !==
null ? $dynamicArea->getContainerId() :
"bxdynamic_".$area->id;
604 $assets = Asset::getInstance()->getAssetInfo($dynamicArea->getAssetId(), $dynamicArea->getAssetMode());
605 $areaContent = substr(
$content, $area->openTagEnd, $area->closingTagStart - $area->openTagEnd);
606 $areaContentMd5 = substr(md5($areaContent), 0, 12);
608 $blockId = $dynamicArea->getId();
609 $hasSameContent = isset($pageBlocks[$blockId]) && $pageBlocks[$blockId] === $areaContentMd5;
611 if (!$hasSameContent)
615 "CONTENT" => $areaContent,
616 "HASH" => $areaContentMd5,
619 "CONTAINER_ID" => $dynamicArea->getContainerId(),
620 "USE_BROWSER_STORAGE" => $dynamicArea->getBrowserStorage(),
621 "AUTO_UPDATE" => $dynamicArea->getAutoUpdate(),
622 "USE_ANIMATION" => $dynamicArea->getAnimation(),
623 "CSS" => $assets[
"CSS"],
624 "JS" => $assets[
"JS"],
625 "BUNDLE_JS" => $assets[
"BUNDLE_JS"],
626 "BUNDLE_CSS" => $assets[
"BUNDLE_CSS"],
627 "STRINGS" => $assets[
"STRINGS"],
632 $data[
"static"] .= substr(
$content, $offset, $area->openTagStart - $offset);
634 if ($dynamicArea->getContainerId() ===
null)
637 '<div id="bxdynamic_'.$area->id.
'_start" style="display:none"></div>'.
638 $dynamicArea->getStub().
639 '<div id="bxdynamic_'.$area->id.
'_end" style="display:none"></div>';
643 $data[
"static"] .= $dynamicArea->getStub();
646 $offset = $area->closingTagEnd;
656 self::replaceSessid(
$data[
"static"]);
657 Asset::getInstance()->moveJsToBody(
$data[
"static"]);
669 private static function getFrameIndexes(
$content)
671 $openTag =
"<!--'start_frame_cache_";
672 $closingTag =
"<!--'end_frame_cache_";
677 while (($openTagStart = strpos(
$content, $openTag, $offset)) !==
false)
679 $endingPos = strpos(
$content, $ending, $openTagStart);
680 if ($endingPos ===
false)
685 $idStart = $openTagStart + mb_strlen($openTag);
686 $idLength = $endingPos - $idStart;
687 $areaId = substr(
$content, $idStart, $idLength);
688 $openTagEnd = $endingPos + mb_strlen($ending);
690 $realClosingTag = $closingTag.$areaId.$ending;
691 $closingTagStart = strpos(
$content, $realClosingTag, $openTagEnd);
692 if ($closingTagStart ===
false)
694 $offset = $openTagEnd;
698 $closingTagEnd = $closingTagStart + mb_strlen($realClosingTag);
700 $area = new \stdClass();
702 $area->openTagStart = $openTagStart;
703 $area->openTagEnd = $openTagEnd;
704 $area->closingTagStart = $closingTagStart;
705 $area->closingTagEnd = $closingTagEnd;
708 $offset = $closingTagEnd;
711 return !empty($areas) ? $areas :
false;
714 private static function getPageBlocks()
717 $json = Context::getCurrent()->getServer()->get(
"HTTP_BX_CACHE_BLOCKS");
718 if ($json !==
null && $json <>
'')
720 $blocks = json_decode($json,
true);
721 if ($blocks ===
null)
735 private static function replaceSessid(&
$content)
738 if ($methodInvocations > 0)
752 self::$isBufferRestarted =
true;
753 self::setEnable(
false);
757 "TYPE" => Logger::TYPE_BUFFER_RESTART,
767 if (!self::isAjaxRequest() || ($isExternal && $skip_security_check !==
true))
774 "reason" =>
"redirect",
775 "redirect_url" =>
$url,
778 self::setEnable(
false);
782 "TYPE" => Logger::TYPE_LOCAL_REDIRECT,
786 "Redirect Url: ".
$url
790 self::$isRedirect =
true;
794 $response->addHeader(
'X-Bitrix-Composite',
'Ajax (error:redirect)');
796 $bxRandom = Helper::getAjaxRandom();
797 if ($bxRandom !==
false)
799 $response->addHeader(
'BX-RAND', $bxRandom);
805 private static function ensureFileQuota($requiredFreeSpace = 0)
808 if (Helper::checkQuota($requiredFreeSpace) || $tries <= 0)
813 $records = PageTable::getList(
815 "select" =>
array(
"ID",
"CACHE_KEY"),
816 "order" =>
array(
"LAST_VIEWED" =>
"ASC",
"ID" =>
"ASC"),
817 "limit" => self::getDeletionLimit()
822 $compositeOptions = Helper::getOptions();
824 while ($record = $records->fetch())
826 $ids[] = $record[
"ID"];
827 $fileStorage =
new Data\FileStorage($record[
"CACHE_KEY"],
array(), $compositeOptions);
828 $deletedSize += doubleval($fileStorage->delete());
831 PageTable::deleteBatch(
array(
"ID" => $ids));
833 Helper::updateCacheFileSize(-$deletedSize);
836 "TYPE" => Logger::TYPE_CACHE_RESET,
838 "Pages: ".
count($ids).
"\n".
839 "Size: ".\CFile::formatSize($deletedSize)
842 if (!Helper::checkQuota($requiredFreeSpace))
845 self::ensureFileQuota($requiredFreeSpace);
852 private static function getDeletionLimit()
855 if (isset(
$options[
"PAGE_DELETION_LIMIT"]) && intval(
$options[
"PAGE_DELETION_LIMIT"]) > 0)
857 return intval(
$options[
"PAGE_DELETION_LIMIT"]);
861 return self::PAGE_DELETION_LIMIT;
865 private static function getAjaxError(
$errorMsg =
null)
872 elseif (self::$isBufferRestarted)
874 $error =
"buffer_restarted";
876 elseif (!self::isEnabled())
880 elseif (defined(
"BX_BUFFER_SHUTDOWN"))
888 elseif (!self::$isCompositeInjected)
893 header(
"X-Bitrix-Composite: Ajax (error:".
$error.
")");
894 self::sendRandHeader();
907 private static function sendRandHeader()
909 $bxRandom = Helper::getAjaxRandom();
910 if ($bxRandom !==
false)
912 header(
"BX-RAND: ".$bxRandom);
924 private static function getInjectedJs(
$params =
array())
931 var v = w.frameCacheVars = $vars;
933 if (v.AUTO_UPDATE ===
false)
935 if (v.AUTO_UPDATE_TTL && v.AUTO_UPDATE_TTL > 0)
937 var lm = Date.parse(d.lastModified);
940 var td =
new Date().getTime();
941 if ((lm + v.AUTO_UPDATE_TTL * 1000) >= td)
943 w.frameRequestStart =
false;
944 w.preventAutoUpdate =
true;
952 w.frameRequestStart =
false;
953 w.preventAutoUpdate =
true;
958 var r = w.XMLHttpRequest ?
new XMLHttpRequest() : (w.ActiveXObject ? new w.ActiveXObject(
"Microsoft.XMLHTTP") : null);
961 w.frameRequestStart =
true;
963 var m = v.CACHE_MODE; var l = w.location; var x =
new Date().getTime();
964 var q =
"?bxrand=" + x + (l.search.length > 0 ?
"&" + l.search.substring(1) :
"");
965 var u = l.protocol +
"//" + l.host + l.pathname + q;
967 r.open(
"GET", u,
true);
968 r.setRequestHeader(
"BX-ACTION-TYPE",
"get_dynamic");
969 r.setRequestHeader(
"X-Bitrix-Composite",
"get_dynamic");
970 r.setRequestHeader(
"BX-CACHE-MODE", m);
971 r.setRequestHeader(
"BX-CACHE-BLOCKS", v.dynamicBlocks ? JSON.stringify(v.dynamicBlocks) :
"");
974 r.setRequestHeader(
"BX-INVALIDATE-CACHE",
"Y");
977 try { r.setRequestHeader(
"BX-REF", d.referrer ||
"");}
catch(e) {}
979 if (m ===
"APPCACHE")
981 r.setRequestHeader(
"BX-APPCACHE-PARAMS", JSON.stringify(v.PARAMS));
982 r.setRequestHeader(
"BX-APPCACHE-URL", v.PAGE_URL ? v.PAGE_URL :
"");
985 r.onreadystatechange =
function() {
986 if (r.readyState != 4) {
return; }
987 var a = r.getResponseHeader(
"BX-RAND");
988 var b = w.BX && w.BX.frameCache ? w.BX.frameCache :
false;
989 if (a != x || !((r.status >= 200 && r.status < 300) || r.status === 304 || r.status === 1223 || r.status === 0))
991 var f = {error:
true, reason:a!=x?
"bad_rand":
"bad_status", url:u, xhr:r, status:r.status};
992 if (w.BX && w.BX.ready && b)
994 BX.ready(
function() {
995 setTimeout(
function(){
996 BX.onCustomEvent(
"onFrameDataRequestFail", [f]);
1001 w.frameRequestFail = f;
1008 b.onFrameDataReceived(r.responseText);
1009 if (!w.frameUpdateInvoked)
1013 w.frameUpdateInvoked =
true;
1017 w.frameDataString = r.responseText;
1023 var p = w.performance;
1024 if (p && p.addEventListener && p.getEntries && p.setResourceTimingBufferSize)
1026 var e =
'resourcetimingbufferfull';
1027 var h =
function() {
1028 if (w.BX && w.BX.frameCache && w.BX.frameCache.frameDataInserted)
1030 p.removeEventListener(e, h);
1034 p.setResourceTimingBufferSize(p.getEntries().length + 50);
1037 p.addEventListener(e, h);
1040 })(window, document);
1044 if (self::isBannerEnabled())
1046 $html .=
'<style type="text/css">'.str_replace(
array(
"\n",
"\t"),
"", self::getInjectedCSS()).
"</style>\n";
1049 $html .=
'<script data-skip-moving="true">'.
1050 str_replace(
array(
"\n",
"\t"),
"", $inlineJS).
1069 background: url(/bitrix/images/main/composite/sprite-1x.png) no-
repeat right 0 #e94524;
1071 color: #fff !important;
1074 font-family:
"Helvetica Neue", Helvetica, Arial, sans-serif !important;
1075 font-
size: 12px !important;
1076 font-weight: bold !important;
1078 padding: 0 42px 0 17px !important;
1079 vertical-
align: middle !important;
1080 text-decoration: none !important;
1084 and (min-device-
width: 1200px)
1085 and (max-device-
width: 1600px)
1086 and (-webkit-min-device-pixel-ratio: 2)
1087 and (min-resolution: 192dpi) {
1089 background-image: url(/bitrix/images/main/composite/sprite-2x.png);
1090 background-
size: 42px 124px;
1094 .bx-composite-btn-fixed {
1103 color: #fff !important;
1108 color: #000 !important;
1113 color: #555 !important;
1118 color: #657b89 !important;
1122 border: 1px solid #d4d4d4;
1124 line-
height: 29px !important;
1127 .bx-composite-loading {
1131 background: url(/bitrix/images/main/composite/loading.gif);
1144 if (self::isSelfHostedPortal())
1149 if (defined(
"USE_HTML_STATIC_CACHE") && USE_HTML_STATIC_CACHE ===
true)
1152 !defined(
"BX_SKIP_SESSION_EXPAND") &&
1153 (!defined(
"ADMIN_SECTION") || (defined(
"ADMIN_SECTION") &&
ADMIN_SECTION !=
"Y"))
1156 if (self::isInvalidationRequest())
1158 $cacheKey = Helper::convertUriToPath(
1159 Helper::getRequestUri(),
1160 Helper::getHttpHost(),
1166 die(Engine::getAjaxError(
"invalidation_request_locked"));
1170 self::setUseHTMLCache();
1175 self::setAutoUpdate(
false);
1178 if (isset(
$options[
"AUTO_UPDATE_TTL"]))
1180 self::setAutoUpdateTTL(
$options[
"AUTO_UPDATE_TTL"]);
1183 define(
"BX_SKIP_SESSION_EXPAND",
true);
1198 $eventManager->addEventHandler(
"main",
"OnEpilog",
function() use($recordId) {
1199 if (is_object(
$GLOBALS[
"APPLICATION"]))
1201 Debug\Model\LogTable::update($recordId,
array(
1202 "TITLE" =>
$GLOBALS[
"APPLICATION"]->getTitle()
1210 (defined(
"ENABLE_HTML_STATIC_CACHE_JS") && ENABLE_HTML_STATIC_CACHE_JS ===
true) &&
1214 \CJSCore::init(
array(
"fc"));
1230 $GLOBALS[
"APPLICATION"]->showPanelWasInvoked ===
true &&
1231 self::getUseHTMLCache() &&
1232 !self::isAjaxRequest() &&
1236 self::setEnable(
false);
1240 "TYPE" => Logger::TYPE_ADMIN_PANEL,
1252 if (Configuration::getValue(
"force_enable_self_hosted_composite") ===
true)
1262 public static function install($setDefaults =
true)
1266 $eventManager->registerEventHandler(
"main",
"OnEpilog",
"main",
"\\".__CLASS__,
"onEpilog");
1267 $eventManager->registerEventHandler(
"main",
"OnLocalRedirect",
"main",
"\\".__CLASS__,
"onEpilog");
1268 $eventManager->registerEventHandler(
"main",
"OnChangeFile",
"main",
"\\".__CLASS__,
"onChangeFile");
1271 if ($setDefaults ===
true)
1273 Helper::setOptions();
1276 $file =
new File(Helper::getEnabledFilePath());
1277 if (!$file->isExists())
1279 $file->putContents(
"");
1287 $eventManager->unRegisterEventHandler(
"main",
"OnEpilog",
"main",
"\\".__CLASS__,
"onEpilog");
1288 $eventManager->unRegisterEventHandler(
"main",
"OnLocalRedirect",
"main",
"\\".__CLASS__,
"onEpilog");
1289 $eventManager->unRegisterEventHandler(
"main",
"OnChangeFile",
"main",
"\\".__CLASS__,
"onChangeFile");
1291 $file =
new File(Helper::getEnabledFilePath());
1302 return Helper::isOn();
1319 if (is_object(
$USER) &&
$USER->IsAuthorized())
1321 if (self::isCurrentUserCC())
1340 self::deleteCompositeCookies();
1346 $server = Context::getCurrent()->getServer();
1351 "clear_cache_session",
1352 "bitrix_include_areas",
1354 "show_page_exec_time",
1355 "show_include_exec_time",
1363 $uri =
new Uri($server->getRequestUri());
1364 $refinedUri = $queryString !=
"" ?
$uri->getPath().
"?".$queryString :
$uri->getPath();
1366 $cacheStorage =
new Page($refinedUri, Helper::getHttpHost());
1367 $cacheStorage->delete();
1380 $domains = Helper::getDomains();
1382 foreach ($domains as $domain)
1384 $cacheStorage =
new Page(
$path, $domain);
1385 $cacheStorage->delete();
1388 Helper::updateQuota(-
$bytes);
1401 if (self::isCurrentUserCC())
1418 self::deleteCompositeCookies();
1430 $diff = array_diff(
$USER->GetUserGroupArray(),
$groups);
1432 return empty($diff);
1443 Helper::deleteUserPrivateKey();
1456 $page->setUserPrivateKey();
1467 Helper::deleteUserPrivateKey();
1482 self::$autoUpdate = !$preventAutoUpdate;
1493 return !self::$autoUpdate;
1535 $id,
$content, $stub =
"", $containerId =
null, $useBrowserStorage =
false,
1536 $autoUpdate =
true, $useAnimation =
false
1540 $area->setStub($stub);
1541 $area->setContainerId($containerId);
1542 $area->setBrowserStorage($useBrowserStorage);
1543 $area->setAutoUpdate($autoUpdate);
1544 $area->setAnimation($useAnimation);
1561 return $dynamicArea->startDynamicArea();
1580 $id, $stub =
"", $containerId =
null, $useBrowserStorage =
false,
1581 $autoUpdate =
true, $useAnimation =
false)
1584 if ($curDynamicArea ===
null || $curDynamicArea->getId() !== $id)
1589 $curDynamicArea->setStub($stub);
1590 $curDynamicArea->setContainerId($containerId);
1591 $curDynamicArea->setBrowserStorage($useBrowserStorage);
1592 $curDynamicArea->setAutoUpdate($autoUpdate);
1593 $curDynamicArea->setAnimation($useAnimation);
1595 return $curDynamicArea->finishDynamicArea();
addDynamicData( $id, $content, $stub="", $containerId=null, $useBrowserStorage=false, $autoUpdate=true, $useAnimation=false)