/** * Dispatches the node * @param \ride\library\mvc\Request $request * @param \ride\library\mvc\Response $response * @param \ride\library\security\SecurityManager $securityManager * @param \ride\library\cache\pool\CachePool $cache * @return array Array with the region name as key and a view array as * value. The view array has the widget id as key and the dispatched * widget view as value */ public function dispatch(Request $request, Response $response, SecurityManager $securityManager, CachePool $cache = null) { $this->locale = $this->view->getLocale(); // initialize context $context = array('title' => array('site' => $this->node->getRootNode()->getName($this->locale, 'title'), 'node' => $this->node->getName($this->locale, 'title')), 'breadcrumbs' => $this->breadcrumbs, 'styles' => array(), 'scripts' => array()); // prepare and process incoming route arguments $route = $request->getRoute(); $this->routeArguments = $route->getArguments(); unset($this->routeArguments['node']); unset($this->routeArguments['locale']); if (isset($this->routeArguments['site'])) { // preview has site and revision unset($this->routeArguments['site']); unset($this->routeArguments['revision']); } $nodeRoute = $this->node->getRoute($this->locale); $nodeRouteTokens = explode('/', ltrim($nodeRoute, '/')); foreach ($nodeRouteTokens as $tokenIndex => $tokenValue) { if (isset($this->routeArguments[$tokenIndex]) && $this->routeArguments[$tokenIndex] === $tokenValue) { unset($this->routeArguments[$tokenIndex]); } } $route->setPredefinedArguments(array()); $route->setArguments(); $routeArgumentsMatched = false; // check for cache $cacheKey = null; $cacheItem = null; $cachedViews = array(); $dispatchedViews = array(); $nodeCacheTtl = false; if ($cache) { $method = $request->getMethod(); $isCacheable = $method == 'GET' || $method == 'HEAD' ? true : false; $isNoCache = $request->isNoCache(); if ($isCacheable) { $parameters = $this->routeArguments ? '-' . implode('-', $this->routeArguments) : ''; $parameters .= $request->getQueryParametersAsString(); $containsUserContent = false; $nodeCacheTtl = 0; $cacheKey = 'node.view.' . $this->node->getId() . '.' . $this->node->getRevision() . '.' . $this->locale . '.' . substr(md5($parameters), 0, 10); if ($securityManager->getUser()) { $cacheKey .= '.authenticated'; } $cacheItem = $cache->get($cacheKey); if ($cacheItem->isValid()) { $cachedViews = $cacheItem->getValue(); } else { $cachedViews = array(); } } } else { $isCacheable = false; } foreach ($this->widgets as $this->region => $sections) { $dispatchedViews[$this->region] = array(); foreach ($sections as $this->section => $blocks) { $dispatchedViews[$this->region][$this->section] = array(); foreach ($blocks as $this->block => $widgets) { $dispatchedViews[$this->region][$this->section][$this->block] = array(); foreach ($widgets as $widgetId => $widget) { if ($this->log) { $this->log->logDebug('Rendering widget ' . $widget->getName() . '#' . $widgetId . ' for region ' . $this->region, null, ApplicationListener::LOG_SOURCE); } $widgetProperties = $this->node->getWidgetProperties($widgetId); if (!$widgetProperties->isPublished()) { if ($this->log) { $this->log->logDebug('Widget ' . $widget->getName() . '#' . $widgetId . ' is not published', null, ApplicationListener::LOG_SOURCE); } continue; } elseif (!$widgetProperties->isAllowed($securityManager)) { if ($this->log) { $this->log->logDebug('Widget ' . $widget->getName() . '#' . $widgetId . ' is not allowed', null, ApplicationListener::LOG_SOURCE); } continue; } if ($isCacheable) { $widgetCacheKey = $this->region . '.' . $this->section . '.' . $this->block . '.' . $widgetId . '.'; } $isWidgetCache = $widgetProperties->isCacheEnabled() || $widgetProperties->isAutoCache() && $widget->isAutoCache(); if ($isCacheable && !$isNoCache && $isWidgetCache) { if (isset($cachedViews[$this->region][$this->section][$this->block][$widgetId])) { if ($this->log) { $this->log->logDebug('Retrieved widget ' . $widget->getName() . '#' . $widgetId . ' from cache', null, ApplicationListener::LOG_SOURCE); } $cacheView = $cachedViews[$this->region][$this->section][$this->block][$widgetId]; if ($cacheView->areRoutesMatched()) { $widgetMatchedRouteArguments = true; } $cacheContext = $cacheView->getContext(); if ($cacheContext) { foreach ($cacheContext as $key => $value) { if ($value !== null) { $context[$key] = $value; } elseif (isset($context[$key])) { unset($context[$key]); } } } if ($cacheView->isContent()) { $dispatchedViews = null; $this->view->setContentView($view, $widgetId, $this->block, $this->section, $this->region); break 4; } elseif ($cacheView->isRegion()) { $dispatchedViews[$this->region] = array($this->section => array($this->block => array($widgetId => $cacheView->getView()))); break 3; } elseif ($cacheView->isSection()) { $dispatchedViews[$this->region][$this->section] = array($this->block => array($widgetId => $cacheView->getView())); break 2; } elseif ($cacheView->isBlock()) { $dispatchedViews[$this->region][$this->section][$this->block] = array($widgetId => $cacheView->getView()); break; } else { $dispatchedViews[$this->region][$this->section][$this->block][$widgetId] = $cacheView->getView(); continue; } } } $widget->setProperties($widgetProperties); $widget->setContext($context); $widgetMatchedRouteArguments = $this->dispatchWidget($request, $response, $widgetId, $widget); if ($widgetMatchedRouteArguments) { $routeArgumentsMatched = true; } $statusCode = $response->getStatusCode(); if ($statusCode != Response::STATUS_CODE_OK && $statusCode != Response::STATUS_CODE_BAD_REQUEST && $statusCode != Response::STATUS_CODE_UNPROCESSABLE_ENTITY) { return; } $view = $response->getView(); $response->setView(null); $isContent = $widget->isContent(); $isRegion = $widget->isRegion(); $isSection = $widget->isSection(); $isBlock = $widget->isBlock(); if ($isCacheable && !$containsUserContent && $widget->containsUserContent()) { $containsUserContent = true; } $oldContext = $context; $context = $widget->getContext(); if ($isCacheable && $isWidgetCache) { $widgetContext = $this->getContextDifference($context, $oldContext); if (!$widgetContext) { // calculate node cache time based on the least widget cache time $cacheTtl = $widgetProperties->getCacheTtl(); if ($nodeCacheTtl !== false && $cacheTtl) { if ($nodeCacheTtl == 0) { $nodeCacheTtl = $cacheTtl; } else { $nodeCacheTtl = min($nodeCacheTtl, $cacheTtl); } } $widgetCachedView = new WidgetCacheData($widgetContext, $isContent, $isRegion, $isSection, $isBlock, $widgetMatchedRouteArguments); $cachedViews[$this->region][$this->section][$this->block][$widgetId] = $widgetCachedView; } } if ($isContent) { $dispatchedViews = null; $this->view->setContentView($view, $widgetId, $this->block, $this->section, $this->region); break 4; } elseif ($isRegion) { $dispatchedViews[$this->region] = array($this->section => array($this->block => array($widgetId => $view))); break 3; } elseif ($isSection) { $dispatchedViews[$this->region][$this->section] = array($this->block => array($widgetId => $view)); break 2; } elseif ($isBlock) { $dispatchedViews[$this->region][$this->section][$this->block] = array($widgetId => $view); break; } $dispatchedViews[$this->region][$this->section][$this->block][$widgetId] = $view; } if (!$dispatchedViews[$this->region][$this->section][$this->block]) { unset($dispatchedViews[$this->region][$this->section][$this->block]); } } if (!$dispatchedViews[$this->region][$this->section]) { unset($dispatchedViews[$this->region][$this->section]); } } if (!$dispatchedViews[$this->region]) { unset($dispatchedViews[$this->region]); } } if ($this->routeArguments && !$routeArgumentsMatched) { // sub route provided but never matched $response->setStatusCode(Response::STATUS_CODE_NOT_FOUND); $response->setView(null); $dispatchedViews = null; } // if ($this->eventManager && $isCacheable && $nodeCacheTtl !== false) { // if ($user && $containsUserContent) { // $isCacheable = false; // } // if ($isCacheable) { // $this->cache = $cache; // $this->cacheTtl = $nodeCacheTtl; // $this->eventManager->addEventListener(WebApplication::EVENT_POST_RESPONSE, array($this, 'cacheResponse')); // } // } $this->view->setContext($context); if (is_array($dispatchedViews)) { $this->view->setDispatchedViews($dispatchedViews); $this->view->setRegions($this->regions); if ($nodeCacheTtl !== false && $cachedViews) { $cacheItem->setValue($cachedViews); $cacheItem->setTtl($nodeCacheTtl); $this->view->setCachedViews($cache, $cacheItem); } } $response->setView($this->view); }
/** * Perform the advanced node action */ public function indexAction(Cms $cms, SecurityManager $securityManager, $locale, $site, $revision, $node) { if (!$cms->resolveNode($site, $revision, $node)) { return; } $this->setContentLocale($locale); $cms->setLastAction(self::NAME); $translator = $this->getTranslator(); $referer = $this->request->getQueryParameter('referer'); $security = $node->get(Node::PROPERTY_SECURITY, 'inherit', false); switch ($security) { case 'inherit': case Node::AUTHENTICATION_STATUS_EVERYBODY: case Node::AUTHENTICATION_STATUS_ANONYMOUS: $permissions = null; break; case Node::AUTHENTICATION_STATUS_AUTHENTICATED: default: $permissions = array_flip(explode(',', $security)); $security = Node::AUTHENTICATION_STATUS_AUTHENTICATED; break; } $data = array('published' => $node->get(Node::PROPERTY_PUBLISH, 'inherit', false), 'publishStart' => $node->get(Node::PROPERTY_PUBLISH_START, null, false), 'publishStop' => $node->get(Node::PROPERTY_PUBLISH_STOP, null, false), 'security' => $security, 'permissions' => $permissions); $permissions = $securityManager->getSecurityModel()->getPermissions(); $nodeType = $cms->getNodeType($node); $isFrontendNode = $nodeType->getFrontendCallback() || $node->getLevel() === 0 ? true : false; if ($isFrontendNode) { $data['hide'] = array(); if ($node->hideInMenu()) { $data['hide']['menu'] = 'menu'; } if ($node->hideInBreadcrumbs()) { $data['hide']['breadcrumbs'] = 'breadcrumbs'; } if ($node->hideForAnonymousUsers()) { $data['hide']['anonymous'] = 'anonymous'; } if ($node->hideForAuthenticatedUsers()) { $data['hide']['authenticated'] = 'authenticated'; } } $form = $this->createFormBuilder($data); $form->addRow('published', 'option', array('label' => $translator->translate('label.publish'), 'options' => $this->getPublishedOptions($node, $translator))); $form->addRow('publishStart', 'string', array('label' => $translator->translate('label.publish.start'), 'description' => $translator->translate('label.publish.start.description'), 'filters' => array('trim' => array()), 'validators' => array('regex' => array('required' => false, 'regex' => '/2([0-9]){3}-([0-9]){2}-([0-9]){2} ([0-9]){2}:([0-9]){2}:([0-9]){2}/', 'error.regex' => 'error.validation.date.cms')))); $form->addRow('publishStop', 'string', array('label' => $translator->translate('label.publish.stop'), 'filters' => array('trim' => array()), 'validators' => array('regex' => array('required' => false, 'regex' => '/2([0-9]){3}-([0-9]){2}-([0-9]){2} ([0-9]){2}:([0-9]){2}:([0-9]){2}/', 'error.regex' => 'error.validation.date.cms')))); $form->addRow('security', 'option', array('label' => $translator->translate('label.allow'), 'attributes' => array('data-toggle-dependant' => 'option-security'), 'options' => $this->getSecurityOptions($node, $translator), 'validators' => array('required' => array()))); if ($permissions) { $form->addRow('permissions', 'option', array('label' => $translator->translate('label.permissions.required'), 'attributes' => array('class' => 'option-security option-security-authenticated'), 'multiple' => true, 'options' => $permissions)); } if ($isFrontendNode) { $form->addRow('hide', 'option', array('label' => $translator->translate('label.hide'), 'options' => array('menu' => $translator->translate('label.hide.menu'), 'breadcrumbs' => $translator->translate('label.hide.breadcrumbs'), 'anonymous' => $translator->translate('label.hide.anonymous'), 'authenticated' => $translator->translate('label.hide.authenticated')), 'multiple' => true)); } $form = $form->build(); if ($form->isSubmitted()) { try { $form->validate(); $data = $form->getData(); $security = $this->getSecurityValue($data['security']); if ($security == Node::AUTHENTICATION_STATUS_AUTHENTICATED && $permissions && $data['permissions']) { $security = implode(',', $data['permissions']); } $node->set(Node::PROPERTY_PUBLISH, $this->getPublishedValue($data['published'])); $node->set(Node::PROPERTY_PUBLISH_START, $data['publishStart']); $node->set(Node::PROPERTY_PUBLISH_STOP, $data['publishStop']); $node->set(Node::PROPERTY_SECURITY, $security); if ($isFrontendNode) { if ($node->getLevel() === 0) { $inherit = false; } else { $inherit = null; } $node->setHideInMenu(isset($data['hide']['menu']), $inherit); $node->setHideInBreadcrumbs(isset($data['hide']['breadcrumbs']), $inherit); $node->setHideForAnonymousUsers(isset($data['hide']['anonymous']), $inherit); $node->setHideForAuthenticatedUsers(isset($data['hide']['authenticated']), $inherit); } $cms->saveNode($node, 'Set visibility of ' . $node->getName()); $this->addSuccess('success.node.saved', array('node' => $node->getName($locale))); $url = $this->getUrl(self::ROUTE, array('site' => $site->getId(), 'revision' => $node->getRevision(), 'locale' => $locale, 'node' => $node->getId())); if ($referer) { $url .= '?referer=' . urlencode($referer); } $this->response->setRedirect($url); return; } catch (ValidationException $exception) { $validationException = new ValidationException(); $errors = $exception->getAllErrors(); foreach ($errors as $field => $fieldErrors) { if ($field == Node::PROPERTY_PUBLISH) { $validationException->addErrors('published', $fieldErrors); } elseif ($field == Node::PROPERTY_PUBLISH_START) { $validationException->addErrors('publishStart', $fieldErrors); } elseif ($field == Node::PROPERTY_PUBLISH_STOP) { $validationException->addErrors('publishStop', $fieldErrors); } else { $validationException->addErrors($field, $fieldErrors); } } $this->setValidationException($validationException, $form); } } $view = $this->setTemplateView('cms/backend/node.visibility', array('site' => $site, 'node' => $node, 'form' => $form->getView(), 'referer' => $referer, 'locale' => $locale, 'locales' => $cms->getLocales())); $form->processView($view); }
/** * Gets whether the provided user is allowed to view this node * @param ride\library\security\SecurityManager $securityManager * @return boolean True if allowed, false otherwise */ public function isAllowed(SecurityManager $securityManager) { $security = $this->get(self::PROPERTY_SECURITY, self::AUTHENTICATION_STATUS_EVERYBODY); if (!$security || $security === self::AUTHENTICATION_STATUS_EVERYBODY) { return true; } try { $user = $securityManager->getUser(); } catch (AuthenticationException $exception) { $user = null; } if ($security === self::AUTHENTICATION_STATUS_ANONYMOUS) { if ($user) { return false; } else { return true; } } if (!$user) { return false; } if ($security === self::AUTHENTICATION_STATUS_AUTHENTICATED) { return true; } $isAllowed = true; $permissions = explode(',', $security); foreach ($permissions as $permission) { if (!$securityManager->isPermissionGranted($permission)) { $isAllowed = false; break; } } return $isAllowed; }
/** * Action to dispatch to the properties of a widget * @param \ride\web\cms\Cms $cms * @param \ride\library\security\SecurityManager $securityManager * @param string $locale * @param string $site * @param string $revision * @param string $node * @param string $region * @param string $widget * @return null */ public function indexAction(Cms $cms, SecurityManager $securityManager, $locale, $site, $revision, $node, $region, $widget) { if (!$cms->resolveNode($site, $revision, $node) || !$cms->resolveRegion($node, $locale, $region)) { return; } $widgetId = $widget; $widgetProperties = $node->getWidgetProperties($widgetId); $widget = $site->getWidget($widgetId); $widget = clone $cms->getWidget($widget); $widget->setRequest($this->request); $widget->setResponse($this->response); $widget->setProperties($widgetProperties); $widget->setLocale($locale); $widget->setRegion($region); if ($widget instanceof AbstractController) { $widget->setConfig($this->config); $widget->setDependencyInjector($this->dependencyInjector); } $translator = $this->getTranslator(); $referer = $this->request->getQueryParameter('referer'); $security = $widgetProperties->getWidgetProperty(Node::PROPERTY_SECURITY, Node::AUTHENTICATION_STATUS_EVERYBODY); switch ($security) { case 'inherit': case Node::AUTHENTICATION_STATUS_EVERYBODY: case Node::AUTHENTICATION_STATUS_ANONYMOUS: $permissions = null; break; case Node::AUTHENTICATION_STATUS_AUTHENTICATED: default: $permissions = array_flip(explode(',', $security)); $security = Node::AUTHENTICATION_STATUS_AUTHENTICATED; break; } $data = array('published' => $widgetProperties->getWidgetProperty(Node::PROPERTY_PUBLISH, true), 'publishStart' => $widgetProperties->getWidgetProperty(Node::PROPERTY_PUBLISH_START, null), 'publishStop' => $widgetProperties->getWidgetProperty(Node::PROPERTY_PUBLISH_STOP, null), 'security' => $security, 'permissions' => $permissions); $permissions = $securityManager->getSecurityModel()->getPermissions(); $form = $this->createFormBuilder($data); $form->addRow('published', 'option', array('label' => $translator->translate('label.publish'), 'options' => $this->getPublishedOptions($translator))); $form->addRow('publishStart', 'string', array('label' => $translator->translate('label.publish.start'), 'description' => $translator->translate('label.publish.start.description'), 'filters' => array('trim' => array()), 'validators' => array('regex' => array('required' => false, 'regex' => '/2([0-9]){3}-([0-9]){2}-([0-9]){2} ([0-9]){2}:([0-9]){2}:([0-9]){2}/', 'error.regex' => 'error.validation.date.cms')))); $form->addRow('publishStop', 'string', array('label' => $translator->translate('label.publish.stop'), 'filters' => array('trim' => array()), 'validators' => array('regex' => array('required' => false, 'regex' => '/2([0-9]){3}-([0-9]){2}-([0-9]){2} ([0-9]){2}:([0-9]){2}:([0-9]){2}/', 'error.regex' => 'error.validation.date.cms')))); $form->addRow('security', 'option', array('label' => $translator->translate('label.allow'), 'options' => $this->getSecurityOptions($translator), 'validators' => array('required' => array()))); if ($permissions) { $form->addRow('permissions', 'option', array('label' => $translator->translate('label.permissions.required'), 'attributes' => array('class' => 'option-security option-security-authenticated'), 'multiple' => true, 'options' => $permissions)); } $form = $form->build(); if ($form->isSubmitted()) { try { $form->validate(); $data = $form->getData(); if ($data['security'] == Node::AUTHENTICATION_STATUS_AUTHENTICATED && $permissions && $data['permissions']) { $data['security'] = implode(',', $data['permissions']); } $widgetProperties->setWidgetProperty(Node::PROPERTY_PUBLISH, $data['published']); $widgetProperties->setWidgetProperty(Node::PROPERTY_PUBLISH_START, $data['publishStart']); $widgetProperties->setWidgetProperty(Node::PROPERTY_PUBLISH_STOP, $data['publishStop']); $widgetProperties->setWidgetProperty(Node::PROPERTY_SECURITY, $data['security']); $cms->saveNode($node, 'Updated visibility properties for widget ' . $widgetId . ' in ' . $node->getName()); $this->addSuccess('success.widget.saved', array('widget' => $translator->translate('widget.' . $widget->getName()))); $this->response->setRedirect($this->getUrl('cms.node.content.region', array('locale' => $locale, 'site' => $site->getId(), 'revision' => $node->getRevision(), 'node' => $node->getId(), 'region' => $region))); return; } catch (ValidationException $exception) { $validationException = new ValidationException(); $errors = $exception->getAllErrors(); foreach ($errors as $field => $fieldErrors) { if ($field == Node::PROPERTY_PUBLISH) { $validationException->addErrors('published', $fieldErrors); } elseif ($field == Node::PROPERTY_PUBLISH_START) { $validationException->addErrors('publishStart', $fieldErrors); } elseif ($field == Node::PROPERTY_PUBLISH_STOP) { $validationException->addErrors('publishStop', $fieldErrors); } else { $validationException->addErrors($field, $fieldErrors); } } $this->setValidationException($validationException, $form); } } $referer = $this->request->getQueryParameter('referer'); $this->setTemplateView('cms/backend/widget.visibility', array('site' => $site, 'node' => $node, 'referer' => $referer, 'locale' => $locale, 'locales' => $cms->getLocales(), 'region' => $region, 'widget' => $widget, 'widgetId' => $widgetId, 'widgetName' => $translator->translate('widget.' . $widget->getName()), 'form' => $form->getView())); }