/** * Render content from modules * this is where caching is implemented * TODO Possible refactoring, many leves of nesting * TODO Reconsider the solution with passing in extra tpl data * to renderModules() as an argument. Smells bad * * @access protected * @return string * @param array $tplVars */ protected function renderModules($tplVars = array()) { try { // Timer $timer = $this->sl->get('timer'); $timer->start('module_run'); } catch (Exception $e) { // No timing, we're in prod } $config = $this->sl->get('aetherConfig'); if ($this->sl->has("cache")) { $cache = $this->sl->get("cache"); } else { $cache = false; } $cacheable = true; /** * Decide cache name for rule based cache * If the option cacheas is set, we will use the cache name * $domainname_$cacheas */ $url = $this->sl->get('parsedUrl'); if ($cache) { $cacheas = $config->getCacheName(); if ($cacheas != false) { $cacheName = $url->get('host') . '_' . $cacheas; } else { $cacheName = $url->cacheName(); } $pageCacheTime = $config->getCacheTime(); if ($pageCacheTime === false) { $pageCacheTime = 0; } if ($url->get('query') != "") { $cacheable = false; } } else { $pageCacheTime = 0; } /** * If one object requests no cache of this request * then we need to take that into consideration. * If the application frontend and adminpanel lives * at the same URL, its crucial that the admin part is * not cached and later on displayed to an end user */ $options = $config->getOptions(); // Support i18n $locale = isset($options['locale']) ? $options['locale'] : "nb_NO.UTF-8"; setlocale(LC_ALL, $locale); $lc_numeric = isset($options['lc_numeric']) ? $options['lc_numeric'] : 'C'; setlocale(LC_NUMERIC, $lc_numeric); // Support custom searchpaths $searchPath = isset($options['searchpath']) ? $options['searchpath'] : $this->sl->get("aetherPath"); AetherModuleFactory::$path = $searchPath; $modules = $config->getModules(); foreach ($modules as &$module) { if (!isset($module['options'])) { $module['options'] = array(); } // Get module object $object = AetherModuleFactory::create($module['name'], $this->sl, $module['options']); // If the module, in this setting, blocks caching, accept if ($cache && ($cachetime = $object->getCacheTime()) !== null) { $module['cache'] = $cachetime; // Reset page cache time to module since we ask for stuff // to be updated at an earlier interval $pageCacheTime = min($pageCacheTime, $module['cache']); } $module['obj'] = $object; } /** * If we have a timer, end this timing * we're in test mode and thus showing timing * information */ if (isset($timer) and is_object($timer)) { $timer->tick('module_run', 'read_config'); } /** * Render page */ $cacheable = $cacheable && is_object($cache); if (!$cacheable || $pageCacheTime === 0 || $cache->get($cacheName) == false) { /* Load controller template * This template knows where all modules should be placed * and have internal wrapping html for this section */ $tplInfo = $config->getTemplate(); $tpl = $this->sl->getTemplate(); if (is_array($modules)) { $tpl->set("extras", $tplVars); $modulesOut = array(); foreach ($modules as &$module) { // If module should be cached, handle it if ($cache && array_key_exists('cache', $module) && $module['cache'] > 0) { $mCacheName = $cacheName . $module['name']; if ($module['provides']) { $mCacheName .= $module['provides']; } if (array_key_exists('cacheas', $module)) { $mCacheName = $url->get('host') . $module['cacheas']; } // Try to read from cache, else generate and cache if (($mOut = $cache->get($mCacheName)) == false) { $mCacheTime = $module['cache']; $mod = $module['obj']; try { $mOut = $mod->run(); if (is_numeric($mCacheTime) && $mCacheTime > 0) { $cache->set($mCacheName, $mOut, $mCacheTime); } else { $pageCacheTime = 0; } } catch (Exception $e) { $pageCacheTime = 0; $this->logerror($e); } } } else { // Module shouldn't be cached, just render it without // saving to cache $mod = $module['obj']; try { $mOut = $mod->run(); } catch (Exception $e) { $pageCacheTime = 0; $this->logerror($e); continue; } } /** * If this module provides some service * make sure we actually push it */ if (array_key_exists('provides', $module)) { $this->provide($module['provides'], $mOut); } /** * Support multiple modules of same type by * specificaly naming them with a surname when * duplicates are encountered */ $modName = $module['name']; if (!isset($modulesOut[$modName])) { $modulesOut[$modName] = array(); } if (array_key_exists('provides', $module)) { $modulesOut[$modName][$module['provides']] = $mOut; } else { $modulesOut[$modName][] = $mOut; } /** * If we have a timer, end this timing * we're in test mode and thus showing timing * information */ if (isset($timer) and is_object($timer)) { if (array_key_exists('provides', $module)) { $timerMsg = $module['provides']; } else { $timerMsg = $modName; } $timer->tick('module_run', $timerMsg); } } // Export rendered modules to template foreach ($modulesOut as $name => $mod) { $name = str_replace('/', '_', $name); if (count($mod) > 1) { $tpl->set($name, $mod); } else { $tpl->set($name, current($mod)); } } } if (!isset($tplInfo['name']) || strlen($tplInfo['name']) === 0) { throw new AetherConfigErrorException("Template not specified for url: " . (string) $url); } else { $output = $tpl->fetch($tplInfo['name']); } if ($cacheable && $pageCacheTime > 0) { $cache->set($cacheName, $output, $pageCacheTime); } } else { $output = $cache->get($cacheName); } if ($cacheable) { header("Cache-Control: max-age={$pageCacheTime}"); } /** * If we have a timer, end this timing * we're in test mode and thus showing timing * information */ if (isset($timer) and is_object($timer)) { $timer->end('module_run'); } // Return output return $output; }
/** * Render content from modules * this is where caching is implemented * TODO Possible refactoring, many leves of nesting * TODO Reconsider the solution with passing in extra tpl data * to renderModules() as an argument. Smells bad * * @access protected * @return string * @param array $tplVars */ protected function renderModules($tplVars = array()) { try { // Timer $timer = $this->sl->get('timer'); $timer->start('module_run'); } catch (Exception $e) { // No timing, we're in prod } $config = $this->sl->get('aetherConfig'); $this->cache = $this->sl->has("cache") ? $this->sl->get("cache") : false; $cacheable = true; /** * Decide cache name for rule based cache * If the option cacheas is set, we will use the cache name * $domainname_$cacheas */ $url = $this->sl->get('parsedUrl'); if ($this->cache) { $cacheas = $config->getCacheName(); if ($cacheas != false) { $this->cacheName = $url->get('host') . '_' . $cacheas; } else { $this->cacheName = $url->cacheName(); } $this->pageCacheTime = $config->getCacheTime(); if ($this->pageCacheTime === false) { $this->pageCacheTime = 0; } if ($url->get('query') != "") { $cacheable = false; } } else { $this->pageCacheTime = 0; } /** * If one object requests no cache of this request * then we need to take that into consideration. * If the application frontend and adminpanel lives * at the same URL, its crucial that the admin part is * not cached and later on displayed to an end user */ $options = $config->getOptions(); // Support i18n $locale = isset($options['locale']) ? $options['locale'] : "nb_NO.UTF-8"; setlocale(LC_ALL, $locale); // Cache complete pages in Aether. Does not affect module cache if (isset($options['cachePages']) && $options['cachePages'] == 'false') { $cachePages = false; } else { $cachePages = true; } $lc_numeric = isset($options['lc_numeric']) ? $options['lc_numeric'] : 'C'; setlocale(LC_NUMERIC, $lc_numeric); if (isset($options['lc_messages'])) { $localeDomain = "messages"; setlocale(LC_MESSAGES, $options['lc_messages']); bindtextdomain($localeDomain, $this->sl->get('projectRoot') . "locale"); bind_textdomain_codeset($localeDomain, 'UTF-8'); textdomain($localeDomain); } // Support custom searchpaths $searchPath = isset($options['searchpath']) ? $options['searchpath'] : $this->sl->get("aetherPath"); AetherModuleFactory::$path = $searchPath; $modules = $this->preloadModules($config->getModules(), $options); /** * If we have a timer, end this timing * we're in test mode and thus showing timing * information */ if (isset($timer) and is_object($timer)) { $timer->tick('module_run', 'read_config'); } /** * Render page */ $cacheable = $cacheable && is_object($this->cache); if (!$cachePages || !$cacheable || $this->pageCacheTime === 0 || $this->cache->get($this->cacheName) == false) { /* Load controller template * This template knows where all modules should be placed * and have internal wrapping html for this section */ $tplInfo = $config->getTemplate(); $tpl = $this->sl->getTemplate(); if (is_array($modules)) { $tpl->set("extras", $tplVars); foreach ($modules as &$module) { // If module should be cached, handle it $module = $this->loadModule($module); if (!$module) { continue; } /** * Support multiple modules of same type by * specificaly naming them with a surname when * duplicates are encountered */ $modId = isset($module['provides']) ? $module['provides'] : $module['name']; $this->provide($modId, $module['output']); // DEPRECATED: direct access to $ModuleName in template $tpl->set($module['name'], $module['output']); /** * If we have a timer, end this timing * we're in test mode and thus showing timing * information */ if (isset($timer) and is_object($timer)) { $timer->tick('module_run', $modId); } } } foreach ($config->getFragments() as $frag) { foreach (array_keys($frag['modules']) as $mod) { $tpl->set($modules[$mod]['provides'], $modules[$mod]['output']); } $this->provide($frag['provides'], $tpl->fetch($frag['template'])); } if (!isset($tplInfo['name']) || strlen($tplInfo['name']) === 0) { throw new AetherConfigErrorException("Template not specified for url: " . (string) $url); } else { $output = $tpl->fetch($tplInfo['name']); } if ($cachePages && $cacheable && $this->pageCacheTime > 0) { $this->cache->set($this->cacheName, $output, $this->pageCacheTime); } } else { $output = $this->cache->get($this->cacheName); } // Page is cacheable even with cachePages off since we want headers for // browser and ex. varnish etc. if (is_numeric($this->pageCacheTime)) { header("Cache-Control: s-maxage={$this->pageCacheTime}"); } /** * If we have a timer, end this timing * we're in test mode and thus showing timing * information */ if (isset($timer) and is_object($timer)) { $timer->end('module_run'); } // Return output return $output; }