/** * Reads the content mappers for the content detail widgets * @return array */ public function readContentMappers() { $this->mappers = array(); $this->defaultMappers = array(); $entryFormatter = $this->orm->getEntryFormatter(); $nodes = $this->nodeModel->getNodesForWidget('orm.detail'); foreach ($nodes as $node) { $widgetId = $node->getWidgetId(); if (!$widgetId) { continue; } $widgetProperties = $node->getWidgetProperties($widgetId); $modelName = $widgetProperties->getWidgetProperty(ContentProperties::PROPERTY_MODEL_NAME); if (!$modelName) { continue; } if (!isset($mappers[$modelName])) { $mappers[$modelName] = array(); } $model = $this->orm->getModel($modelName); $mapperId = $node->getId() . '-' . $widgetId; $this->mappers[$modelName][$mapperId] = new GenericOrmContentMapper($this->nodeModel, $node, $model, $entryFormatter, $widgetProperties, $this->routerService); if ($widgetProperties->getWidgetProperty(ContentProperties::PROPERTY_PRIMARY)) { $this->defaultMappers[$modelName] = $mapperId; } } foreach ($this->mappers as $modelName => $modelMappers) { if (!isset($this->defaultMappers[$modelName])) { reset($modelMappers); $this->defaultMappers[$modelName] = key($modelMappers); } } return $this->mappers; }
/** * Parses the provided variable * @param string $variable Full variable * @return mixed Value of the variable if resolved, null otherwise */ public function parseVariable($variable) { $tokens = explode('.', $variable); $node = null; switch ($tokens[0]) { case 'year': if (count($tokens) !== 1) { return null; } return date('Y'); case 'node': if (count($tokens) < 3) { return null; } try { $selfNode = $this->textParser->getNode(); $node = $this->nodeModel->getNode($selfNode->getRootNodeId(), $selfNode->getRevision(), $tokens[1]); } catch (NodeNotFoundException $exception) { return null; } $locale = isset($tokens[3]) ? $tokens[3] : $this->textParser->getLocale(); $variable = $tokens[2]; break; case 'page': if (count($tokens) < 4) { return null; } try { $selfNode = $this->textParser->getNode(); $node = $this->nodeModel->getNode($tokens[1], $selfNode->getRevision(), $tokens[2]); } catch (NodeNotFoundException $exception) { return null; } $locale = isset($tokens[4]) ? $tokens[4] : $this->textParser->getLocale(); $variable = $tokens[3]; break; case 'site': if (count($tokens) < 2) { return null; } $node = $this->textParser->getNode()->getRootNode(); $locale = isset($tokens[2]) ? $tokens[2] : $this->textParser->getLocale(); $variable = $tokens[1]; } if (!$node) { return null; } switch ($variable) { case self::VARIABLE_URL: return $node->getUrl($locale, $this->textParser->getSiteUrl()); case self::VARIABLE_NAME: return $node->getName($locale); case self::VARIABLE_LINK: return '<a href="' . $node->getUrl($locale, $this->textParser->getSiteUrl()) . '">' . $node->getName($locale) . '</a>'; } return null; }
/** * Gets the route container from a data source * @return \ride\library\router\RouteContainer */ public function getRouteContainer() { $container = new RouteContainer(); $nodeTypeManager = $this->nodeModel->getNodeTypeManager(); $nodeTypes = $nodeTypeManager->getNodeTypes(); $defaultRevision = $this->nodeModel->getDefaultRevision(); $registeredPaths = array(); $expiredCallback = array('ride\\web\\cms\\controller\\frontend\\ExpiredController', 'indexAction'); $sites = $this->nodeModel->getSites(); foreach ($sites as $siteId => $site) { $nodes = $this->nodeModel->getNodes($siteId, $defaultRevision); foreach ($this->locales as $locale) { $baseUrl = $site->getBaseUrl($locale); foreach ($nodes as $nodeId => $node) { if (!$node->getParent()) { continue; } $nodeType = $nodeTypes[$node->getType()]; $callback = $nodeType->getFrontendCallback(); if (!$callback) { continue; } if (!$node->isAvailableInLocale($locale)) { continue; } $path = $node->getRoute($locale); $route = new Route($path, $callback, 'cms.front.' . $siteId . '.' . $nodeId . '.' . $locale); $route->setIsDynamic(true); $route->setPredefinedArguments(array('site' => $siteId, 'node' => $nodeId)); $route->setLocale($locale); if ($baseUrl) { $route->setBaseUrl($baseUrl); } $container->addRoute($route); $registeredPaths[$path] = true; } } $expiredRoutes = $this->expiredRouteModel->getExpiredRoutes($siteId); foreach ($expiredRoutes as $expiredRoute) { $path = $expiredRoute->getPath(); if (isset($registeredPaths[$path]) || $path == '/') { continue; } $route = new Route($path, $expiredCallback); $route->setIsDynamic(true); $route->setPredefinedArguments(array('site' => $siteId, 'node' => $expiredRoute->getNode())); $route->setLocale($expiredRoute->getLocale()); $baseUrl = $expiredRoute->getBaseUrl(); if ($baseUrl) { $route->setBaseUrl($baseUrl); } $container->addRoute($route); } } return $container; }
/** * Creates a node dispatcher for the provided node * @param \ride\library\cms\node\SiteNode $site * @param string $nodeId Id of the node * @param string $baseUrl * @param string $locale * @return \ride\web\cms\node\dispatcher\NodeDispatcher */ public function createNodeDispatcher(SiteNode $site, $nodeId, $baseUrl, $locale) { if ($this->cachePool) { $cacheKey = 'node.dispatcher.' . $site->getId() . '.' . $nodeId . '.' . $locale; $cacheItem = $this->cachePool->get($cacheKey); if ($cacheItem->isValid()) { $nodeDispatcher = $cacheItem->getValue(); $this->processNodeDispatcher($nodeDispatcher); return $nodeDispatcher; } } try { $node = $this->nodeModel->getNode($site->getId(), $site->getRevision(), $nodeId); } catch (NodeNotFoundException $exception) { return null; } $theme = $this->themeModel->getTheme($node->getTheme()); $nodeView = new NodeTemplateView($node, $theme, $locale); $router = new GenericRouter(new RouteContainer()); $breadcrumbs = $this->nodeModel->getBreadcrumbsForNode($node, $baseUrl, $locale); $nodeDispatcher = new GenericNodeDispatcher($node, $nodeView, $router, $breadcrumbs); $nodeDispatcher->loadWidgets($this->widgetModel, $theme->getRegions()); if ($this->cachePool) { $cacheItem->setValue($nodeDispatcher); $this->cachePool->set($cacheItem); } $this->processNodeDispatcher($nodeDispatcher); return $nodeDispatcher; }
/** * Adds a warning to the response if the provided text is used in another * widget instance * @param \ride\library\widget\WidgetProperties $widgetProperties * @param \ride\web\cms\orm\model\TextModel $textModel * @param \ride\web\cms\text\Text $text Instance of the text * @param string $warning * @return null */ protected function warnAboutUsedText(WidgetProperties $widgetProperties, TextModel $textModel, Text $text, $warning) { if (!$text->id) { return; } $widgetId = $widgetProperties->getWidgetId(); $node = $widgetProperties->getNode(); $rootNode = $node->getRootNode(); $nodes = $this->nodeModel->getNodesForWidget(TextWidget::NAME, $rootNode->getId()); foreach ($nodes as $node) { $nodeWidgetId = $node->getWidgetId(); if ($nodeWidgetId == $widgetId) { continue; } $nodeWidgetProperties = $node->getWidgetProperties($nodeWidgetId); if ($nodeWidgetProperties->getWidgetProperty(TextWidget::PROPERTY_IO) !== self::NAME) { continue; } if ($nodeWidgetProperties->getWidgetProperty(TextWidget::PROPERTY_TEXT) !== $text->id) { continue; } $message = new Message($warning, Message::TYPE_WARNING); $this->response->addMessage($message); break; } }
/** * Redirects the current node * @return null */ public function indexAction(NodeModel $nodeModel) { $node = $this->properties->getNode(); $url = $this->properties->getLocalizedWidgetProperty($this->locale, self::PROPERTY_URL); if ($url) { $url = $node->resolveUrl($this->locale, $this->request->getBaseScript(), $url); } else { $nodeId = $this->properties->getWidgetProperty(self::PROPERTY_NODE); if (!$nodeId) { return; } try { $node = $nodeModel->getNode($node->getRootNodeId(), $node->getRevision(), $nodeId); } catch (NodeNotFoundException $exception) { $this->getLog()->logException($exception); return; } $url = $node->getUrl($this->locale, $this->request->getBaseScript()); } $this->response->setRedirect($url); }
/** * Saves the node in the model * @param string $locale Locale of the structure * @param \ride\library\cms\node\SiteNode $site Site node * @param \ride\library\cms\node\NodeModel $nodeModel * @param array $nodeArray * @return \ride\library\cms\node\Node */ protected function saveNode($locale, SiteNode $site, NodeModel $nodeModel, array $nodeArray, $isUniqueTree) { if (isset($nodeArray['id']) && $nodeArray['id']) { $node = $nodeModel->getNode($site->getId(), $site->getRevision(), $nodeArray['id']); } else { $type = $nodeArray['type']; if (!$type) { $type = PageNodeType::NAME; } $node = $nodeModel->createNode($type); $node->setParentNode($site); $node->setRevision($site->getRevision()); if ($isUniqueTree) { $node->setAvailableLocales($locale); } } $node->setName($locale, $nodeArray['name']); if ($nodeArray['route'] && $nodeArray['route'] != '/nodes/' . $node->getId() . '/' . $locale) { $node->setRoute($locale, $nodeArray['route']); } $nodeModel->setNode($node, 'Updated structure of ' . $site->getName()); return $node; }
/** * Parses the provided variable * @param string $variable Full variable * @return mixed Value of the variable if resolved, null otherwise */ public function parseVariable($variable) { $tokens = explode('.', $variable); $numTokens = count($tokens); if ($numTokens < 2) { return null; } $node = $this->textParser->getNode(); if ($numTokens === 2 || $tokens[0] === 'node' && $tokens[1] === 'var') { while ($node && !$node instanceof EntryNode) { $node = $node->getParentNode(); } if (!$node) { return null; } } $value = null; if ($tokens[0] === 'entry' && $numTokens === 2) { switch ($tokens[1]) { case NodeVariableParser::VARIABLE_URL: $value = $this->textParser->getSiteUrl() . $node->getRoute($this->textParser->getLocale()); break; case NodeVariableParser::VARIABLE_NAME: $value = $node->getName($this->textParser->getLocale()); break; } return $value; } elseif ($tokens[0] === 'node' && $tokens[1] === 'var' && $numTokens > 2) { $value = $node->getEntry(); for ($i = 2; $i < $numTokens; $i++) { $value = $this->reflectionHelper->getProperty($value, $tokens[$i]); if ($value === null) { break; } } } elseif ($tokens[0] === 'entry') { // lookup entry node $modelName = ucfirst($tokens[1]); $entryId = $tokens[2]; $nodes = $this->nodeModel->getNodes($node->getRootNodeId(), $node->getRevision()); foreach ($nodes as $node) { if ($node->getType() !== EntryNodeType::NAME || $node->getEntryModel() !== $modelName || $node->getEntryId() !== $entryId) { continue; } $locale = isset($tokens[4]) ? $tokens[4] : $this->textParser->getLocale(); switch ($tokens[3]) { case NodeVariableParser::VARIABLE_URL: $value = $this->textParser->getSiteUrl() . $node->getRoute($locale); break 2; case NodeVariableParser::VARIABLE_NAME: $value = $node->getName($locale); break 2; case NodeVariableParser::VARIABLE_LINK: $value = '<a href="' . $this->textParser->getSiteUrl() . $node->getRoute($locale) . '">' . $node->getName($locale) . '</a>'; break 2; } break; } } return $value; }
/** * Sets a text view to the response * @return null */ public function indexAction(NodeModel $nodeModel) { $propertiesNode = $this->properties->getNode(); $text = $this->getTextIO()->getText($this->properties, $this->locale); $textFormat = $this->getTextFormat($text->getFormat()); $html = $textFormat->getHtml($text->getBody()); $callToActions = $text->getCallToActions(); foreach ($callToActions as $index => $callToAction) { $node = $callToAction->getNode(); $url = $callToAction->getUrl(); $suffix = $callToAction->getSuffix(); if ($node) { try { $node = $nodeModel->getNode($propertiesNode->getRootNodeId(), $propertiesNode->getRevision(), $node); $callToAction->setUrl($node->getUrl($this->locale, $this->request->getBaseUrl()) . $callToAction->getSuffix()); } catch (NodeNotFoundException $exception) { $this->getLog()->logException($exception); unset($callToActions[$index]); } } elseif ($url) { $callToAction->setUrl($this->properties->getNode()->resolveUrl($this->locale, $this->request->getBaseUrl(), $url)); } elseif (!$suffix) { unset($callToActions[$index]); } } $this->setTemplateView($this->getTemplate(static::TEMPLATE_NAMESPACE . '/' . static::TEMPLATE_DEFAULT), array('text' => $text, 'title' => $text->getTitle(), 'subtitle' => $text->getSubtitle(), 'html' => $html, 'image' => $text->getImage(), 'imageAlignment' => $text->getImageAlignment(), 'callToActions' => $callToActions)); }
/** * Constructs a new decorator * @return null */ public function __construct(NodeModel $nodeModel, $locale, $nodeUrl) { $this->nodes = $nodeModel->getNodesForWidget('text'); $this->locale = $locale; $this->url = $nodeUrl; }
/** * Validates the route of the node * @param \ride\library\cms\node\Node $node Node to be validated * @param \ride\library\cms\node\NodeModel $nodeModel Model of the nodes * @param \ride\library\validation\exception\ValidationException $exception * @return null */ protected function validateRoute(Node $node, NodeModel $nodeModel, ValidationException $exception) { if (!$node->getParent()) { return; } $rootNode = $node->getRootNode(); $rootNodeId = $rootNode->getId(); $nodeId = $node->getId(); $modelNodes = $nodeModel->getNodes($rootNodeId, $node->getRevision()); $propertyPrefix = Node::PROPERTY_ROUTE . '.'; $lengthPropertyPrefix = strlen($propertyPrefix); // loop all properties $properties = $node->getProperties(); foreach ($properties as $key => $property) { if (strpos($key, $propertyPrefix) !== 0) { // we're only interested in route properties continue; } $routeLocale = substr($key, $lengthPropertyPrefix); $route = $property->getValue(); // normalize route $route = trim($route, '/'); $baseUrls[$routeLocale] = $rootNode->getBaseUrl($routeLocale); $tokens = explode('/', $route); foreach ($tokens as $index => $token) { if ($token) { $token = StringHelper::safeString($token); } if (empty($token)) { unset($tokens[$index]); } else { $tokens[$index] = $token; } } $route = '/' . implode('/', $tokens); // check for duplicate routes $errors = array(); foreach ($modelNodes as $modelNode) { $modelNodeId = $modelNode->getId(); if ($modelNodeId == $nodeId || $modelNode->getRootNodeId() != $rootNodeId || !$modelNode->hasParent() || $modelNode->getType() == ReferenceNodeType::NAME) { // same node, different site or root node or a reference node continue; } $modelNodeRoutes = $modelNode->getRoutes(); foreach ($modelNodeRoutes as $locale => $modelNodeRoute) { if (!array_key_exists($locale, $baseUrls)) { $baseUrls[$locale] = $rootNode->getBaseUrl($locale); } if ($baseUrls[$routeLocale] . $route != $baseUrls[$locale] . $modelNodeRoute) { continue; } $errors[$modelNodeId] = new ValidationError('error.route.used.node', "Route '%route%' is already used by node %node% in locale %locale%", array('route' => $route, 'node' => $modelNodeId, 'locale' => $locale)); } } foreach ($errors as $error) { $exception->addErrors(Node::PROPERTY_ROUTE, array($error)); } // update property with normalized route $property->setValue($route); } }
/** * Gets a list of frontend nodes * @param \ride\library\cms\node\NodeModel $nodeModel Instance of the node * model * @param boolean $includeRootNode Set to false to omit the root node * @return array Array with the id of node as key and the localized name of * the node as value */ public function getNodeList(NodeModel $nodeModel, $includeRootNode = true) { $node = $this->properties->getNode(); $rootNodeId = $node->getRootNodeId(); $rootNode = $nodeModel->getNode($rootNodeId, $node->getRevision(), $rootNodeId, null, true); $nodeList = $nodeModel->getListFromNodes(array($rootNode), $this->locale, true); if ($includeRootNode) { $nodeList = array($rootNode->getId() => '/' . $rootNode->getName($this->locale)) + $nodeList; } return array('' => '---') + $nodeList; }