Christoffer Niska avatar Christoffer Niska committed 053527c

Moved the node rendering logic to CmsBaseRenderer.

Comments (0)

Files changed (4)

 class CmsModule extends CWebModule
 {
 	/**
-	 * @property string the name of the default controller
+	 * @var string the name of the default controller
 	 */
 	public $defaultController = 'content';
 
 	 */
 	public function init()
 	{
+		// Register module imports.
 		$this->setImport(array(
 			'cms.components.*',
 			'cms.models.*',
 
 	/**
 	 * Performs access check to this module.
-	 * @param CController $controller the controller to be accessed.
-	 * @param CAction $action the action to be accessed.
-	 * @return boolean whether the action should be executed.
+	 * @param CController $controller the controller to be accessed
+	 * @param CAction $action the action to be accessed
+	 * @return boolean whether the action should be executed
 	 */
 	public function beforeControllerAction($controller, $action)
 	{

components/Cms.php

  */
 class Cms extends CApplicationComponent
 {
+	// todo: consider moving the configurations to the module.
 	/**
 	 * @var array the names of the users that are allowed to updated the cms.
 	 */
 	/**
 	 * @var string the template to use for page titles.
 	 */
-	public $pageTitleTemplate = '{title} | {appName}';
+	public $pageTitleTemplate = '{title} - {appName}';
 	/**
 	 * @var string the application layout to use with the cms.
 	 */
 	public $appLayout = 'application.views.layouts.main';
 	/**
+	 * @var array the renderer configuration.
+	 */
+	public $renderer = array('class'=>'cms.components.CmsBaseRenderer');
+	/**
 	 * @var array the HTML purifier options.
 	 */
 	public $htmlPurifierOptions = array();
+	// todo: do something about the flash message categories, an array maybe instead of 4 properties?
 	/**
 	 * @var string the flash message error category.
 	 */
     {
         parent::init();
 
-        Yii::app()->clientScript->registerCssFile($this->getAssetsUrl().'/css/cms.css');
-        Yii::app()->clientScript->registerScriptFile($this->getAssetsUrl().'/js/es5-shim.min.js');
+		// Create the renderer.
+		$this->renderer = Yii::createComponent($this->renderer);
+
+		// Register the assets.
+		$assetsUrl = $this->getAssetsUrl();
+        Yii::app()->clientScript->registerCssFile($assetsUrl.'/css/cms.css');
+        Yii::app()->clientScript->registerScriptFile($assetsUrl.'/js/es5-shim.min.js');
     }
 
     /**
 	public function isActive($name)
 	{
 		$node = $this->loadNode($name);
-		$controller = Yii::app()->controller;
+		$controller = Yii::app()->getController();
 		return $controller->module !== null
 				&& $controller->module->id === 'cms'
 				&& $controller->id === 'node'

components/CmsBaseRenderer.php

+<?php
+/**
+ * CmsBaseRenderer class file.
+ * @author Christoffer Niska <christoffer.niska@nordsoftware.com>
+ * @copyright Copyright &copy; 2011, Nord Software Ltd
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @package cms.components
+ */
+
+/**
+ * Cms renderer base class. All renderers must be extended from this class.
+ */
+class CmsBaseRenderer extends CComponent
+{
+	protected $_patterns = array(
+		'file'=>'/{{file:([\d]+)}}/i',
+		'image'=>'/{{image:([\d]+)}}/i',
+		'link'=>'/{{(#?[\w\d\._-]+|https?:\/\/[\w\d_-]*(\.[\w\d_-]*)+.*)\|([\w\d\s-]+)}}/i',
+		'email'=>'/{{email:([\w\d!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[\w\d!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[\w\d](?:[\w\d-]*[\w\d])?\.)+[\w\d](?:[\w\d-]*[\w\d])?)}}/i',
+		'node'=>'/{{node:([\w\d\._-]+)}}/i',
+	);
+
+	/**
+	 * Renders a specific node.
+	 * @param CmsNode $node the node to render
+	 * @return string the rendered node
+	 */
+	public function render($node)
+	{
+		$heading = str_replace('{heading}', $node->heading, Yii::app()->cms->headingTemplate);
+		$content = $this->renderHeading($heading, $node->body);
+		$content = $this->renderLinks($content);
+		$content = $this->renderEmails($content);
+		$content = $this->renderImages($content);
+		$content = $this->renderAttachments($content);
+		$content = $this->renderNodes($content);
+
+		return $content;
+	}
+
+	/**
+	 * Renders a specific node as a widget.
+	 * @param CmsNode $node the node to render
+	 * @return string the rendered node
+	 */
+	public function renderWidget($node)
+	{
+		$heading = str_replace('{heading}', $node->heading, Yii::app()->cms->widgetHeadingTemplate);
+		$content = $this->renderHeading($heading, $node->body);
+		$content = $this->renderLinks($content);
+		$content = $this->renderEmails($content);
+		$content = $this->renderImages($content);
+		$content = $this->renderAttachments($content);
+		$content = $this->removeNodes($content); // widgets do not render inline nodes
+
+		return $content;
+	}
+
+	/**
+	 * Renders the heading.
+	 * @param string $heading the heading to render
+	 * @param string $content the content being rendered
+	 * @return string the content
+	 */
+	protected function renderHeading($heading, $content)
+	{
+		return str_replace('{{heading}}', $heading, $content);
+	}
+
+	/**
+	 * Renders nodes within the given content.
+	 * @param string $content the content being rendered
+	 * @return string the content
+	 */
+	protected function renderNodes($content)
+	{
+		$matches = array();
+		preg_match_all($this->_patterns['node'], $content, $matches);
+
+		$nodes = array();
+		foreach ($matches[1] as $index => $name)
+		{
+			/** @var CmsNode $node */
+			$node = Yii::app()->cms->loadNode($name);
+			if ($node instanceof CmsNode)
+				$nodes[$index] = $node->renderWidget();
+		}
+
+		if (!empty($nodes))
+			$content = strtr($content, array_combine($matches[0], $nodes));
+
+		return $content;
+	}
+
+	/**
+	 * Renders links within the given content.
+	 * @param string $content the content being rendered
+	 * @return string the content
+	 */
+	protected function renderLinks($content)
+	{
+		$matches = array();
+		preg_match_all($this->_patterns['link'], $content, $matches);
+
+		$links = array();
+		foreach ($matches[1] as $index => $target)
+		{
+			// If the target doesn't include 'http' it's treated as an internal link.
+			if (strpos($target, '#') !== 0 && strpos($target, 'http') === false)
+			{
+				/** @var Cms $cms */
+				$cms = Yii::app()->cms;
+
+				/** @var CmsNode $node */
+				$node = $cms->loadNode($target);
+				if (!$node instanceof CmsNode)
+				{
+					$cms->createNode($target);
+					$node = $cms->loadNode($target);
+				}
+
+				$target = $node->getUrl();
+			}
+
+			$text = $matches[3][$index];
+			$links[$index] = CHtml::link($text, $target);
+		}
+
+		if (!empty($links))
+			$content = strtr($content, array_combine($matches[0], $links));
+
+		return $content;
+	}
+
+	/**
+	 * Renders emails within the given content.
+	 * @param string $content the content being rendered
+	 * @return string the content
+	 */
+	protected function renderEmails($content)
+	{
+		$matches = array();
+		preg_match_all($this->_patterns['email'], $content, $matches);
+
+		$mails = array();
+		foreach ($matches[1] as $index => $id)
+		{
+			$email = str_rot13($matches[1][$index]);
+			$mails[$index] = CHtml::mailto($email, $email, array('class'=>'email', 'rel'=>'nofollow'));
+		}
+
+		if (!empty($mails))
+		{
+			$content = strtr($content, array_combine($matches[0], $mails));
+
+			/** @var CClientScript $cs */
+			$cs = Yii::app()->getClientScript();
+
+			$assetsUrl = Yii::app()->cms->getAssetsUrl();
+			$cs->registerScriptFile($assetsUrl.'/js/cms-rot13.js');
+			$cs->registerScript(__CLASS__.'#'.uniqid(true, true).'_emailObfuscation', "
+				(function($) {
+					$('.email').each(function() {
+						var element = $(this);
+
+						if (!element.attr('data-decoded')) {
+							var	href = $(this).attr('href'),
+								address = Cms.Rot13.decode(href.substring(href.indexOf(':') + 1)),
+								value = Cms.Rot13.decode($(this).text());
+
+							element.attr('href', 'mailto:' + address);
+							element.text(value);
+							element.attr('data-decoded', 1);
+						}
+					});
+				})(jQuery);
+			");
+		}
+
+		return $content;
+	}
+
+	/**
+	 * Renders images within the given content.
+	 * @param string $content the content being rendered
+	 * @return string the content
+	 */
+	protected function renderImages($content)
+	{
+		$matches = array();
+		preg_match_all($this->_patterns['image'], $content, $matches);
+
+		$images = array();
+		foreach ($matches[1] as $index => $id)
+		{
+			/** @var CmsAttachment $attachment */
+			$attachment = CmsAttachment::model()->findByPk($id);
+			if ($attachment instanceof CmsAttachment && strpos($attachment->mimeType, 'image') !== false)
+			{
+				$url = $attachment->getUrl();
+				$name = $attachment->resolveName();
+				$images[$index] = CHtml::image($url, $name);
+			}
+		}
+
+		if (!empty($images))
+			$content = strtr($content, array_combine($matches[0], $images));
+
+		return $content;
+	}
+
+	/**
+	 * Renders attachments within this node.
+	 * @param string $content the content being rendered
+	 * @return string the content
+	 */
+	protected function renderAttachments($content)
+	{
+		$matches = array();
+		preg_match_all($this->_patterns['file'], $content, $matches);
+
+		$attachments = array();
+		foreach ($matches[1] as $index => $id)
+		{
+			/** @var CmsAttachment $attachment */
+			$attachment = CmsAttachment::model()->findByPk($id);
+			if ($attachment instanceof CmsAttachment)
+			{
+				$url = $attachment->getUrl();
+				$name = $attachment->resolveName();
+				$attachments[$index] = CHtml::link($name, $url);
+			}
+		}
+
+		if (!empty($attachments))
+			$content = strtr($content, array_combine($matches[0], $attachments));
+
+		return $content;
+	}
+
+	/**
+	 * Removes the node tags within the given content.
+	 * @param string $content the content being rendered
+	 * @return string the content
+	 */
+	public function removeNodes($content)
+	{
+		return preg_replace($this->_patterns['node'], '', $content);
+	}
+}

models/CmsNode.php

  */
 class CmsNode extends CmsActiveRecord
 {
-	protected $_patterns = array(
-		'file'=>'/{{file:([\d]+)}}/i',
-		'image'=>'/{{image:([\d]+)}}/i',
-		'link'=>'/{{(#?[\w\d\._-]+|https?:\/\/[\w\d_-]*(\.[\w\d_-]*)+.*)\|([\w\d\s-]+)}}/i',
-		'email'=>'/{{email:([\w\d!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[\w\d!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[\w\d](?:[\w\d-]*[\w\d])?\.)+[\w\d](?:[\w\d-]*[\w\d])?)}}/i',
-		'node'=>'/{{node:([\w\d\._-]+)}}/i',
-	);
-
 	/**
 	 * Returns the static model of the specified AR class.
 	 * @param string $className the class name
 	 * Returns the given nodes as a branch.
 	 * @param CmsNode[]$nodes the nodes to process
 	 * @param int $parentId the parent id
-	 * @return array the branch.
+	 * @return array the branch
 	 */
 	protected function getBranch(&$nodes, $parentId = 0)
 	{
 
 	/**
 	 * Renders a single branch in the node tree.
-	 * @param $branch the branch.
+	 * @param $branch the branch
 	 */
 	protected function renderBranch($branch)
 	{
 	}
 
 	/**
-	 * Renders this node.
-	 * @return string the rendered node.
-	 */
-	public function render()
-	{
-		$heading = str_replace('{heading}', $this->heading, Yii::app()->cms->headingTemplate);
-		$content = $this->renderHeading($heading, $this->body);
-		$content = $this->renderLinks($content);
-		$content = $this->renderEmails($content);
-		$content = $this->renderImages($content);
-		$content = $this->renderAttachments($content);
-		$content = $this->renderNodes($content);
-
-		return $content;
-	}
-
-	/**
-	 * Renders this node as a widget.
-	 * @return string the rendered node.
-	 */
-	public function renderWidget()
-	{
-		$heading = str_replace('{heading}', $this->heading, Yii::app()->cms->widgetHeadingTemplate);
-		$content = $this->renderHeading($heading, $this->body);
-		$content = $this->renderLinks($content);
-		$content = $this->renderEmails($content);
-		$content = $this->renderImages($content);
-		$content = $this->renderAttachments($content);
-		$content = preg_replace($this->_patterns['node'], '', $content); // widgets do not render inline nodes
-
-		return $content;
-	}
-
-	/**
-	 * Renders the heading for this node.
-	 * @param string $heading the heading to render
-	 * @param string $content the content being rendered
-	 * @return string the content
-	 */
-	protected function renderHeading($heading, $content)
-	{
-		return str_replace('{{heading}}', $heading, $content);
-	}
-
-	/**
-	 * Renders nodes within this node.
-	 * @param string $content the content being rendered
-	 * @return string the content
-	 */
-	protected function renderNodes($content)
-	{
-		$matches = array();
-		preg_match_all($this->_patterns['node'], $content, $matches);
-
-		$nodes = array();
-		foreach ($matches[1] as $index => $name)
-		{
-			/** @var CmsNode $node */
-			$node = Yii::app()->cms->loadNode($name);
-			if ($node instanceof CmsNode)
-				$nodes[$index] = $node->renderWidget();
-		}
-
-		if (!empty($nodes))
-			$content = strtr($content, array_combine($matches[0], $nodes));
-
-		return $content;
-	}
-
-	/**
-	 * Renders links within this node.
-	 * @param string $content the content being rendered
-	 * @return string the content
-	 */
-	protected function renderLinks($content)
-	{
-		$matches = array();
-		preg_match_all($this->_patterns['link'], $content, $matches);
-
-		$links = array();
-		foreach ($matches[1] as $index => $target)
-		{
-			// If the target doesn't include 'http' it's treated as an internal link.
-			if (strpos($target, '#') !== 0 && strpos($target, 'http') === false)
-			{
-				/** @var Cms $cms */
-				$cms = Yii::app()->cms;
-
-				/** @var CmsNode $node */
-				$node = $cms->loadNode($target);
-				if (!$node instanceof CmsNode)
-				{
-					$cms->createNode($target);
-					$node = $cms->loadNode($target);
-				}
-
-				$target = $node->getUrl();
-			}
-
-			$text = $matches[3][$index];
-			$links[$index] = CHtml::link($text, $target);
-		}
-
-		if (!empty($links))
-			$content = strtr($content, array_combine($matches[0], $links));
-
-		return $content;
-	}
-
-	protected function renderEmails($content)
-	{
-		$matches = array();
-		preg_match_all($this->_patterns['email'], $content, $matches);
-
-		$mails = array();
-		foreach ($matches[1] as $index => $id)
-		{
-			$email = str_rot13($matches[1][$index]);
-			$mails[$index] = CHtml::mailto($email, $email, array(
-				'class'=>'email',
-				'rel'=>'nofollow',
-			));
-		}
-
-		if (!empty($mails))
-		{
-			$content = strtr($content, array_combine($matches[0], $mails));
-
-			$assetsUrl = Yii::app()->cms->getAssetsUrl();
-			Yii::app()->clientScript->registerScriptFile($assetsUrl.'/js/cms-rot13.js');
-			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'_emailObfuscation', "
-				(function($) {
-					$('.email').each(function() {
-						var element = $(this),
-							href = $(this).attr('href'),
-							address = Cms.Rot13.decode(href.substring(href.indexOf(':') + 1)),
-							value = Cms.Rot13.decode($(this).text());
-
-						element.attr('href', 'mailto:' + address);
-						element.text(value);
-					});
-				})(jQuery);
-			");
-		}
-
-		return $content;
-	}
-
-	/**
-	 * Renders images within this node.
-	 * @param string $content the content being rendered
-	 * @return string the content
-	 */
-	protected function renderImages($content)
-	{
-		$matches = array();
-		preg_match_all($this->_patterns['image'], $content, $matches);
-
-		$images = array();
-		foreach ($matches[1] as $index => $id)
-		{
-			/** @var CmsAttachment $attachment */
-			$attachment = CmsAttachment::model()->findByPk($id);
-			if ($attachment instanceof CmsAttachment && strpos($attachment->mimeType, 'image') !== false)
-			{
-				$url = $attachment->getUrl();
-				$name = $attachment->resolveName();
-				$images[$index] = CHtml::image($url, $name);
-			}
-		}
-
-		if (!empty($images))
-			$content = strtr($content, array_combine($matches[0], $images));
-
-		return $content;
-	}
-
-	/**
-	 * Renders attachments within this node.
-	 * @param string $content the content being rendered
-	 * @return string the content
-	 */
-	protected function renderAttachments($content)
-	{
-		$matches = array();
-		preg_match_all($this->_patterns['file'], $content, $matches);
-
-		$attachments = array();
-		foreach ($matches[1] as $index => $id)
-		{
-			/** @var CmsAttachment $attachment */
-			$attachment = CmsAttachment::model()->findByPk($id);
-			if ($attachment instanceof CmsAttachment)
-			{
-				$url = $attachment->getUrl();
-				$name = $attachment->resolveName();
-				$attachments[$index] = CHtml::link($name, $url);
-			}
-		}
-
-		if (!empty($attachments))
-			$content = strtr($content, array_combine($matches[0], $attachments));
-
-		return $content;
-	}
-
-	/**
 	 * Creates content for this node.
 	 * @param string $locale the locale id, e.g. 'en_us'
 	 * @return CmsContent the content model
 	{
 		$breadcrumbs = array();
 
-		if ($this->parent === null) {
-			$breadcrumbs[Yii::t('CmsModule.core','Cms')] = array('admin/index');
-			$breadcrumbs[Yii::t('CmsModule.core','Nodes')] = array('node/index');
+		if ($this->parent !== null)
+			$breadcrumbs = $this->parent->getBreadcrumbs(true); // get the parent as a link
+		else
+		{
+			// Do not include the module breadcrumbs for pages.
+			if (Yii::app()->controller->route !== 'cms/node/page')
+			{
+				$breadcrumbs[Yii::t('CmsModule.core','Cms')] = array('admin/index');
+				$breadcrumbs[Yii::t('CmsModule.core','Nodes')] = array('node/index');
+			}
 		}
-		else
-			$breadcrumbs = $this->parent->getBreadcrumbs(true); // get the parent as a link
 
 		if ($this->content !== null && !empty($this->content->breadcrumb))
 			$text = $this->content->breadcrumb;
 
 		return $pageTitle;
 	}
+
+	/**
+	 * Renders this node.
+	 * @return string the rendered node
+	 */
+	public function render()
+	{
+		return Yii::app()->cms->renderer->render($this);
+	}
+
+	/**
+	 * Renders this node as a widget.
+	 * @return string the rendered widget
+	 */
+	public function renderWidget()
+	{
+		return Yii::app()->cms->renderer->renderWidget($this);
+	}
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.