/** * Returns a rendered view. If we find html behind the given cache * it returns this directly. This is a couple os ms faster than `renderCached` * since the template engine is never used when there's a valid cache. * * Example: * * return $this->renderFullCached('myCache', 'plugin1/default.tpl', function(){ * return array('items' => heavyDbQuery()); * }); * * Note: The $data callable is only called if the cache needs to regenerate (when it has been * invalidated or empty, or the view file changed). * * If the callable $data returns NULL, then this will return NULL, too, without entering * the actual rendering process. * * You should use this method in your plugins instead of writing your own cache mechanism, * because this method handles PageResponse merging. Means: If templates used in this * $view are changing somehow the PageResponse ({{loadAsset('style.css')}} calls) then * this information (diff to current PageResponse) is stored and restored when we found * a html cache. The diff is beside the actual rendered HTML also stored in the cache * to keep this possible. * * @param string $cacheKey * @param string $view * @param array|callable $data Pass the data as array or a data provider function. * @param integer $lifeTime In seconds. Default is one hour/3600 seconds. * @param bool $force Force to bypass the cache and always call $data. For debuggin purposes. * * @see method `render` to get more information. * * @return string */ public function renderFullCached($cacheKey, $view, $data = null, $lifeTime = null, $force = false) { $cache = $this->cacher->getDistributedCache($cacheKey); $mTime = $this->getViewMTime($view); if (!is_string($cache)) { $cache = null; } else { $cache = @unserialize($cache); } if ($force || !$cache || !$cache['content'] || !is_array($cache) || $mTime != $cache['fileMTime']) { $oldResponse = clone $this->pageStack->getPageResponse(); $data2 = $data; if (is_callable($data)) { $data2 = call_user_func($data, $view); if (null === $data2) { //the data callback returned NULL so this means //we aren't the correct controller for this request //or the request contains invalid input return null; } } $content = $this->templating->render($view, $data2); $response = $this->pageStack->getPageResponse(); $diff = $oldResponse->diff($response); $cache = array('content' => $content, 'fileMTime' => $mTime, 'responseDiff' => $diff); $this->cacher->setDistributedCache($cacheKey, serialize($cache), $lifeTime ?: 3600); } else { if ($cache['responseDiff']) { $this->pageStack->getPageResponse()->patch($cache['responseDiff']); } } return $this->pageResponseFactory->createPluginResponse($cache['content']); }
/** * @ApiDoc( * section="ACL Management", * description="Saves the given rules" * ) * * @Rest\RequestParam(name="targetId", requirements=".+", strict=true, description="Target id") * @Rest\RequestParam(name="targetType", requirements=".+", strict=true, description="Target type") * @Rest\RequestParam(name="rules", strict=false, description="ACL rules array") * * @Rest\Post("/user/acl") * * @param int $targetId * @param int $targetType * @param array $rules * * @return bool */ public function saveAcl($targetId, $targetType, $rules = null) { $targetId += 0; $targetType += 0; AclQuery::create()->filterByTargetId($targetId)->filterByTargetType($targetType)->delete(); if (0 < count($rules)) { $i = 1; if (is_array($rules)) { foreach ($rules as $rule) { $ruleObject = new Acl(); $ruleObject->setPrio($i); $ruleObject->setTargetType($targetType); $ruleObject->setTargetId($targetId); $ruleObject->setTargetId($targetId); $ruleObject->setObject(Objects::normalizeObjectKey(@$rule['object'])); $ruleObject->setSub(filter_var(@$rule['sub'], FILTER_VALIDATE_BOOLEAN)); $ruleObject->setAccess(filter_var(@$rule['access'], FILTER_VALIDATE_BOOLEAN)); $ruleObject->setFields(@$rule['fields']); $ruleObject->setConstraintType(@$rule['constraintType']); $ruleObject->setConstraintCode(@$rule['constraintCode']); $ruleObject->setMode(@$rule['mode'] + 0); $ruleObject->save(); $i++; } } } $this->cacher->invalidateCache('core/acl'); return true; }
/** * Returns a array map url -> nodeId * * @param integer $domainId * * @return array * * @throws \Propel\Runtime\Exception\PropelException */ public function getCachedUrlToPage($domainId) { $cacheKey = 'core/urls/' . $domainId; $urls = $this->cacher->getDistributedCache($cacheKey); if (!$urls) { $nodes = NodeQuery::create()->select(array('id', 'urn', 'lvl', 'type'))->filterByDomainId($domainId)->orderByBranch()->find(); //build urls array $urls = array(); $level = array(); foreach ($nodes as $node) { if ($node['lvl'] == 0) { continue; } //root if ($node['type'] == 3) { continue; } //deposit if ($node['type'] == 2 || $node['urn'] == '') { //folder or empty url $level[$node['lvl'] + 0] = isset($level[$node['lvl'] - 1]) ? $level[$node['lvl'] - 1] : ''; continue; } $url = isset($level[$node['lvl'] - 1]) ? $level[$node['lvl'] - 1] : ''; $url .= '/' . $node['urn']; $level[$node['lvl'] + 0] = $url; $urls[$url] = $node['id']; } $this->cacher->setDistributedCache($cacheKey, $urls); } return $urls; }
/** * @param string $lang * @param bool $force * @return array|null|string * * @throws \Jarves\Exceptions\BundleNotFoundException */ public function loadMessages($lang = 'en', $force = false) { if (!$this->isValidLanguage($lang)) { $lang = 'en'; } if ($this->messages && isset($this->messages['__lang']) && $this->messages['__lang'] == $lang && $force == false) { return null; } if (!$lang) { return null; } $code = 'core/lang/' . $lang; $this->messages = $this->cacher->getFastCache($code); $md5 = ''; $bundles = array(); foreach ($this->jarves->getBundles() as $bundleName => $bundle) { $path = $bundle->getPath(); if ($path) { $path .= "/Resources/translations/{$lang}.po"; if (file_exists($path)) { $md5 .= @filemtime($path); $bundles[] = $bundleName; } } } $md5 = md5($md5); if (!$this->messages || count($this->messages) == 0 || !isset($this->messages['__md5']) || $this->messages['__md5'] != $md5) { $this->messages = array('__md5' => $md5, '__plural' => $this->getPluralForm($lang), '__lang' => $lang); foreach ($bundles as $key) { $file = $this->jarves->resolvePath("@{$key}/{$lang}.po", 'Resources/translations'); $po = $this->getLanguage($file); $this->messages = array_merge($this->messages, $po['translations']); } $this->cacher->setFastCache($code, $this->messages); } include_once $this->getPluralPhpFunctionFile($lang); return $this->messages; }
public function breadcrumb(\Twig_Environment $twig, $view = 'JarvesBundle:Default:breadcrumb.html.twig') { $breadcrumbs = []; $page = $this->pageStack->getCurrentPage(); $cacheKey = 'core/breadcrumbs/' . $page->getCacheKey(); if ($cache = $this->cacher->getDistributedCache($cacheKey)) { if (is_string($cache)) { return $cache; } } foreach ($page->getParents() as $parent) { if ($parent->getLevel() === 0) { continue; } if ($parent->getType() >= 2) { continue; } $breadcrumbs[] = $parent; } $data = ['domain' => $this->pageStack->getCurrentDomain(), 'baseUrl' => $this->pageStack->getPageResponse()->getBaseHref(), 'breadcrumbs' => $breadcrumbs, 'currentPage' => $this->pageStack->getCurrentPage()]; $html = $twig->render($view, $data); $this->cacher->setDistributedCache($cacheKey, $html); return $html; }
/** * * Options: * * //whether the template cache is deactivated. Navigation object is still cached * boolean noCache = false * * //whether the pathInfo is used in the cacheKey instead of the currentUrl. * //Useful when you have in your navigation controller calls that are based on pathInfo like * //pageStack->getCurrentUrlAffix() * boolean pathInfoCache = false * * Example: * getRendered(['noCache' => true]); * * @param array $options * @param \Twig_Environment $twig * @return string * @throws \Exception */ public function getRendered($options, \Twig_Environment $twig) { $options['noCache'] = isset($options['noCache']) ? (bool) $options['noCache'] : false; $options['pathInfoCache'] = isset($options['pathInfoCache']) ? (bool) $options['pathInfoCache'] : false; $view = $options['template'] ?: $options['view']; $cacheKey = 'core/navigation/' . $this->pageStack->getCurrentPage()->getDomainId() . '.' . $this->pageStack->getCurrentPage()->getId() . ($options['pathInfoCache'] ? '_' . md5($this->pageStack->getRequest()->getPathInfo()) : '') . '_' . md5(json_encode($options)); $fromCache = false; $viewPath = $this->jarves->resolvePath($view, 'Resources/views/'); if ('@' === $view[0]) { $view = substr($view, 1); } if (!file_exists($viewPath)) { throw new \Exception(sprintf('View `%s` not found.', $view)); } else { $mtime = filemtime($viewPath); } if (!$options['noCache']) { $cache = $this->cacher->getDistributedCache($cacheKey); if ($cache && isset($cache['html']) && $cache['html'] !== null && $cache['mtime'] == $mtime) { return $cache['html']; } } $cache = $this->cacher->getDistributedCache($cacheKey); if ($cache && isset($cache['object']) && $cache['mtime'] == $mtime) { $navigation = unserialize($cache['object']); $fromCache = true; } else { $navigation = $this->get($options); } $data['navigation'] = $navigation ?: false; if ($navigation !== false) { $html = $twig->render($view, $data); if (!$options['noCache']) { $this->cacher->setDistributedCache($cacheKey, array('mtime' => $mtime, 'html' => $html)); } elseif (!$fromCache) { $this->cacher->setDistributedCache($cacheKey, array('mtime' => $mtime, 'object' => serialize($navigation))); } return $html; } //no navigation found, probably the template just uses the breadcrumb return $twig->render($view, $data); }
/** * @param integer $nodeId * @param integer $slotId * @return Model\Content[] */ public function getSlotContents($nodeId, $slotId) { if ($contents = $this->pageStack->getPageResponse()->getPageContent()) { if (is_array($contents) && $contents[$slotId]) { return $contents[$slotId]; } else { if (is_string($contents)) { return $contents; } } } $cacheKey = 'core/contents/' . $nodeId . '.' . $slotId; $cache = $this->cacher->getDistributedCache($cacheKey); $contents = null; if ($cache) { return unserialize($cache); } $contents = ContentQuery::create()->filterByNodeId($nodeId)->filterByBoxId($slotId)->orderByRank()->find(); $this->cacher->setDistributedCache($cacheKey, serialize($contents)); return $contents; }
/** * @param Event $eventConfig * @param GenericEvent $event */ public function call(Event $eventConfig, $event) { if ($eventConfig->getCalls()) { foreach ($eventConfig->getCalls() as $call) { call_user_func_array($call, [$event]); } } if ($eventConfig->getClearCaches()) { foreach ($eventConfig->getClearCaches() as $cacheKey) { $this->cacher->invalidateCache($cacheKey); } } if ($eventConfig->getServiceCalls()) { foreach ($eventConfig->getServiceCalls() as $serviceCall) { list($service, $method) = explode('::', $serviceCall); if ($this->container->has($service)) { $service = $this->container->get($service); $service->{$method}($event); } } } }
/** * Creates a Node object based on given $routeName or current route. * * @param string|null $routeName * * @return Node */ public function createPageFromRoute($routeName = null) { if (!$routeName) { $routeName = $this->pageStack->getRequest()->attributes->get('_route'); if (!$routeName) { throw new \RuntimeException('Could not detect route name'); } } $reflection = new \ReflectionClass($this->router->getGenerator()); $key = 'jarves_routes'; $cache = $this->cacher->getFastCache($key); $validCache = false; $routes = []; if ($cache) { $validCache = $cache['time'] === filemtime($reflection->getFileName()) && isset($cache['routes']) && is_string($cache['routes']); if ($validCache) { $routes = unserialize($cache['routes']); } } if (!$validCache) { $routes = $this->router->getRouteCollection()->all(); $this->cacher->setFastCache($key, ['time' => filemtime($reflection->getFileName()), 'routes' => serialize($routes)]); } if (!isset($routes[$routeName])) { throw new \RuntimeException("Route with name `{$routeName}` does not exist"); } $route = $routes[$routeName]; $url = $this->router->generate($routeName, $this->pageStack->getRequest()->attributes->all()); $page = Node::createPage($route->getOption('title'), parse_url($url)['path'], $route->getOption('theme'), $route->getOption('layout')); if ($route->getOption('meta')) { foreach ((array) $route->getOption('meta') as $key => $value) { $page->meta->set($key, $value); } } return $page; }
/** * @param ACLRequest $aclRequest * * @return bool */ public function check(ACLRequest $aclRequest) { $objectKey = Objects::normalizeObjectKey($aclRequest->getObjectKey()); $targetType = $aclRequest->getTargetType(); $targetId = $aclRequest->getTargetId(); $pk = $aclRequest->getPrimaryKey(); $field = $aclRequest->getField(); $pk = $this->objects->normalizePkString($objectKey, $pk); if (ACL::TARGET_TYPE_USER === $targetType && null === $targetId) { //0 means guest $targetId = $this->pageStack->getUser() ? $this->pageStack->getUser()->getId() : 0; } $user = $this->pageStack->getUser(); if ($user) { $groupIds = $user->getGroupIds(); if (false !== strpos(',' . $groupIds . ',', ',1,')) { //user is in the admin group, so he has always access. return true; } } if (ACL::TARGET_TYPE_USER === $targetType && 1 === $targetId) { //user admin has always access return true; } if (ACL::TARGET_TYPE_GROUP === $targetType && 1 === $targetId) { //group admin has always access return true; } if (0 === $targetId) { //guests do always have no access return false; } if (ACL::TARGET_TYPE_GROUP === $targetType && !$targetId) { throw new \InvalidArgumentException('For type TARGET_TYPE_GROUP a targetId is required.'); } $cacheKey = null; if ($pk && $this->getCaching()) { $pkString = $this->objects->getObjectUrlId($objectKey, $pk); $cacheKey = md5($targetType . '.' . $targetId . '.' . $objectKey . '/' . $pkString . '/' . json_encode($field)); $cached = $this->cacher->getDistributedCache('core/acl/' . $cacheKey); if (null !== $cached) { return $cached; } } $rules = self::getRules($objectKey, $aclRequest->getMode(), $targetType, $targetId); if (count($rules) === 0) { //no rules found, so we have no access return false; } $access = null; $currentObjectPk = $pk; $definition = $this->objects->getDefinition($objectKey); $not_found = true; //starts directly as if we were in the parent checking. $parent_acl = $aclRequest->isAsParent(); $fCount = null; $fKey = null; $fValue = null; $fIsArray = is_array($field); if ($fIsArray) { $fCount = count($field); $fKey = key($field); $fValue = current($field); if (is_int($fKey)) { $fKey = $fValue; $fValue = null; } } $depth = 0; $match = false; $originObjectItemPk = $currentObjectPk; while ($not_found) { $currentObjectPkString = null; if ($currentObjectPk) { $currentObjectPkString = $this->objects->getObjectUrlId($objectKey, $currentObjectPk); } $depth++; if ($depth > 50) { $not_found = false; break; } foreach ($rules as $aclRule) { if ($parent_acl && !$aclRule['sub']) { //as soon we enter the parent_acl mode we only take acl rules into consideration //that are also valid for children (sub=true) continue; } $match = false; /* * CUSTOM CONSTRAINT */ if ($aclRule['constraint_type'] === ACL::CONSTRAINT_CONDITION) { $objectItem = null; if ($originObjectItemPk === $currentObjectPk && null !== $aclRequest->getPrimaryObjectItem()) { $objectItem = $aclRequest->getPrimaryObjectItem(); } else { if ($originObjectItemPk) { $objectItem = $this->objects->get($objectKey, $currentObjectPk); } } if ($objectItem && $this->conditionOperator->satisfy($aclRule['constraint_code'], $objectItem, $objectKey)) { $match = true; } /* * EXACT */ } else { if ($aclRule['constraint_type'] === ACL::CONSTRAINT_EXACT) { if ($currentObjectPk && $aclRule['constraint_code'] === $currentObjectPkString) { $match = true; } /** * ALL */ } else { $match = true; } } if (!$match && $aclRule['sub'] && $currentObjectPk) { // we need to check if a parent matches this $acl as we have sub=true $parentItem = $this->objects->normalizePkString($objectKey, $currentObjectPk); $parentCondition = Condition::create($aclRule['constraint_code']); $parentOptions['fields'] = $this->conditionOperator->extractFields($parentCondition); while ($parentItem = $this->objects->getParent($objectKey, $this->objects->getObjectPk($objectKey, $parentItem), $parentOptions)) { if ($aclRule['constraint_type'] === ACL::CONSTRAINT_CONDITION && $this->conditionOperator->satisfy($parentCondition, $parentItem)) { $match = true; break; } else { if ($aclRule['constraint_type'] === ACL::CONSTRAINT_EXACT && $aclRule['constraint_code'] === $this->objects->getObjectUrlId($objectKey, $parentItem)) { $match = true; break; } } } } if ($match) { //match, check all $field $field2Key = $field; if ($field) { if ($fIsArray && $fCount === 1) { if (is_string($fKey) && is_array($aclRule['fields'][$fKey])) { //this field has limits if (($field2Acl = $aclRule['fields'][$fKey]) !== null) { if (is_array($field2Acl[0])) { //complex field rule, $field2Acl = ([{access: no, condition: [['id', '>', 2], ..]}, {}, ..]) foreach ($field2Acl as $fRule) { $satisfy = false; if (($f = $definition->getField($fKey)) && $f->getType() === 'object') { $uri = $f->getObject() . '/' . $fValue; $uriObject = $this->objects->getFromUrl($uri); $satisfy = $this->conditionOperator->satisfy($fRule['condition'], $uriObject); } else { if (null !== $fValue) { $satisfy = $this->conditionOperator->satisfy($fRule['condition'], $field); } } if ($satisfy) { return $fRule['access'] === 1 ? true : false; } } //if no field rules fits, we consider the whole rule if ($aclRule['access'] !== 2) { return $aclRule['access'] === 1 ? true : false; } } else { //simple field rule $field2Acl = ({"value1": yes, "value2": no} if ($field2Acl[$fKey] !== null) { return $field2Acl[$fKey] === 1 ? true : false; } else { //current($field) is not exactly defined in $field2Acl, so we set $access to $acl['access'] // //if access = 2 then wo do not know it, cause 2 means 'inherited', so maybe //a other rule has more detailed rule if ($aclRule['access'] !== 2) { $access = $aclRule['access'] === 1 ? true : false; break; } } } } } else { //this field has only true or false $field2Key = $fKey; } } if (!is_array($field2Key)) { if ($aclRule['fields'] && ($field2Acl = $aclRule['fields'][$field2Key]) !== null && !is_array($aclRule['fields'][$field2Key])) { $access = $field2Acl === 1 ? true : false; break; } else { //$field is not exactly defined, so we set $access to $acl['access'] //and maybe a rule with the same code has the field defined // if access = 2 then this rule is only for exactly define fields if ($aclRule['access'] !== 2) { $access = $aclRule['access'] === 1 ? true : false; break; } } } } else { $access = $aclRule['access'] === 1 ? true : false; break; } } } //foreach if (null === $access && $definition->isNested() && $pk) { //$access has not defined yet (no rule matched yet). Check if nested and $pk is given //load its root and check again if (null === ($currentObjectPk = $this->objects->getParentPk($objectKey, $currentObjectPk))) { $access = $aclRequest->isRootHasAccess() ? true : $access; break; } $parent_acl = true; } else { break; } } $access = (bool) $access; if ($pk && $this->getCaching()) { $this->cacher->setDistributedCache('core/acl/' . $cacheKey, $access); } return $access; }
/** * @param string $bundle * @param string $lang * @param array $translation * * @return bool * @throws FileNotWritableException */ public function saveLanguage($bundle, $lang, $translation) { $file = $this->getJarves()->resolvePath("@{$bundle}/{$lang}.po", 'Resources/translations'); @mkdir(dirname($file), 777, true); if (!is_writable($file)) { throw new FileNotWritableException(sprintf('File `%s` is not writable.', $file)); } $translations = json_decode($translation, true); $current = $this->parsePo($file); $fh = fopen($file, 'w'); if ($fh == false) { return false; } $pluralForms = $this->getPluralForm($lang) ?: 'nplurals=2; plural=(n!=1);'; if ($current) { $current['container']['Plural-Forms'] = $pluralForms; $current['container']['PO-Revision-Date'] = date('Y-m-d H:iO'); fwrite($fh, 'msgid ""' . "\n" . 'msgstr ""' . "\n"); foreach ($current['container'] as $k => $v) { fwrite($fh, '"' . $k . ': ' . $v . '\\n"' . "\n"); } fwrite($fh, "\n\n"); } else { //write initial container fwrite($fh, ' msgid "" msgstr "" "Project-Id-Version: Jarves cms - ' . $bundle . '\\n" "PO-Revision-Date: ' . date('Y-m-d H:iO') . '\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" "Language: ' . $lang . '\\n" "Plural-Forms: ' . $pluralForms . '\\n"' . "\n\n"); } if (count($translations) > 0) { foreach ($translations as $key => $translation) { if (strpos($key, "") !== false) { //we have a context $context = self::toPoString(substr($key, 0, strpos($key, ""))); $id = self::toPoString(substr($key, strpos($key, "") + 1)); fwrite($fh, 'msgctxt ' . $context . "\n"); fwrite($fh, 'msgid ' . $id . "\n"); } else { fwrite($fh, 'msgid ' . self::toPoString($key) . "\n"); } if (is_array($translation)) { fwrite($fh, 'msgid_plural ' . self::toPoString($translation['plural']) . "\n"); unset($translation['plural']); foreach ($translation as $k => $v) { fwrite($fh, 'msgstr[' . $k . '] ' . self::toPoString($v) . "\n"); } } else { fwrite($fh, 'msgstr ' . self::toPoString($translation) . "\n"); } fwrite($fh, "\n"); } } fclose($fh); $this->cacher->invalidateCache('core/lang'); return true; }
/** * Loads all configurations from all registered bundles (BundleName/Resources/config/jarves*.xml) * @param Cacher $cacher * * @return null|callable returns a callable that should be called when config stuff have been registered */ public function loadBundleConfigs(Cacher $cacher) { $cached = $cacher->getFastCache('core/configs'); $bundles = array_keys($this->kernel->getBundles()); $configs = new Configuration\Configs($this); $hashes = []; foreach ($bundles as $bundleName) { $hashes[] = $configs->getConfigHash($bundleName); } $hash = md5(implode('.', $hashes)); if ($cached) { $cached = unserialize($cached); if (is_array($cached) && $cached['md5'] == $hash) { $this->configs = $cached['data']; $this->configs->setCore($this); } } if (!$this->configs) { $this->configs = new Configuration\Configs($this, $bundles); return function () use($hash, $cacher) { $cached = serialize(['md5' => $hash, 'data' => $this->configs]); $cacher->setFastCache('core/configs', $cached); }; } }
/** * Returns the domain if found * * @return \Jarves\Model\Domain|null * * @throws \Propel\Runtime\Exception\PropelException */ public function searchDomain() { $request = $this->getRequest(); $dispatcher = $this->eventDispatcher; if ($domainId = $request->get('_jarves_editor_domain')) { $hostname = DomainQuery::create()->select('domain')->findOneById($domainId); } else { $hostname = $request->getHost(); } $title = sprintf('Searching Domain [%s]', $hostname); $this->stopwatch->start($title); /** @var \Jarves\Model\Domain $foundDomain */ $foundDomain = null; $possibleLanguage = $this->getPossibleLanguage(); $hostnameWithLanguage = $hostname . '/' . $possibleLanguage; $cachedDomains = $this->cacher->getDistributedCache('core/domains'); if ($cachedDomains) { $cachedDomains = @unserialize($cachedDomains); } if (!is_array($cachedDomains)) { $cachedDomains = array(); $domains = DomainQuery::create()->find(); foreach ($domains as $domain) { $key = $domain->getDomain(); $langKey = ''; if (!$domain->getMaster()) { $langKey = '/' . $domain->getLang(); } $cachedDomains[$key . $langKey] = $domain; if ($domain->getRedirect()) { $redirects = $domain->getRedirect(); $redirects = explode(',', str_replace(' ', '', $redirects)); foreach ($redirects as $redirectDomain) { $cachedDomains['!redirects'][$redirectDomain . $langKey] = $key . $langKey; } } if ($domain->getAlias()) { $aliases = $domain->getAlias(); $aliases = explode(',', str_replace(' ', '', $aliases)); foreach ($aliases as $aliasDomain) { $cachedDomains['!aliases'][$aliasDomain . $langKey] = $key . $langKey; } } } $this->cacher->setDistributedCache('core/domains', serialize($cachedDomains)); } //search redirect if (isset($cachedDomains['!redirects']) && (isset($cachedDomains['!redirects'][$hostnameWithLanguage]) && ($redirectToDomain = $cachedDomains['!redirects'][$hostnameWithLanguage])) || isset($cachedDomains['!redirects'][$hostname]) && ($redirectToDomain = $cachedDomains['!redirects'][$hostname])) { $foundDomain = $cachedDomains[$redirectToDomain]; $dispatcher->dispatch('core/domain-redirect', new GenericEvent($foundDomain)); return null; } //search alias if (isset($cachedDomains['!aliases']) && (isset($cachedDomains['!aliases'][$hostnameWithLanguage]) && ($aliasHostname = $cachedDomains['!aliases'][$hostnameWithLanguage]) || isset($cachedDomains['!aliases'][$hostname]) && ($aliasHostname = $cachedDomains['!aliases'][$hostname]))) { $foundDomain = $cachedDomains[$aliasHostname]; $hostname = $aliasHostname; } else { if (isset($cachedDomains[$hostname])) { $foundDomain = $cachedDomains[$hostname]; } } if (!$foundDomain) { $dispatcher->dispatch('core/domain-not-found', new GenericEvent($hostname)); $this->stopwatch->stop($title); return null; } $foundDomain->setRealDomain($hostname); $this->stopwatch->stop($title); return $foundDomain; }