/**
  * 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;
 }