[PATCH] Encapsulating themes inside modules.

Hi,

is there anyway to encapsulate themes inside modules? I mean this:


protected/modules/blog/themes/classic/views/layouts

protected/modules/blog/themes/classic/views/default

protected/modules/blog/themes/classic/views/post

protected/modules/blog/themes/classic/views/comments



instead of having every view inside the global theme directory. This seems to be more organised and more according to the concept of a module as a reusable and somehow atomic entity.

If this is not possible in Yii 1.1.8, where in the code should I start looking into in order to add this feature? (and then submit a patch).

Thanks.

You can theme modules by using this structure




themes/<themeName>/views/<moduleName>/<controllerName>/<viewName>

themes/<themeName>/views/<moduleName>/<viewName>



But if I understood you, that is not what you want

To accomplish what you want, you need 2 things:

1.to set your modified theme class in theme manager




//config/main.php

return array(

...

'components'=>array(

  'themeManager'=>array(

	'themeClass'=>'myTheme',

  )

)

);



  1. to extend CTheme class methods that are related with the location of the view files (most of its methods)



class myTheme extends CTheme{

  ...

}



Obrigado, Gustavo. Well, this is a quick and maybe dirty hack, but it’s working fine so far :slight_smile:


<?php


/**

 * ATheme implements theme encapsulation inside modules, so you can have your

 * themed views and layouts inside the module instead of inside a global directory. The 

 * directory must be called themes and inside there should be a directory named 

 * after the theme and then the views directory, with a subdirectory per 

 * controller and a optional layouts directory in case you have a particular 

 * layout for that module:

 * 

 * protected/modules/mymodule/themes/mytheme/views/mycontroller/myview.php

 * protected/modules/mymodule/themes/mytheme/views/layouts

 * 

 * To render a view in an action you must use / like this:

 * 

 * $this->controller->render('/myview');

 * 

 * You must declare the theme class like:

 * 

 * 'themeManager' => array(

 *	'themeClass' => 'ATheme',

 * ),

 *

 * in your application's components, in main.php

 *

 * @author MetaYii

 */

class ATheme extends CTheme

{

   /**

   * Finds the view file for the specified controller's view.

   * @param CController $controller the controller

   * @param string $viewName the view name

   * @return string the view file path. False if the file does not exist.

   */

   public function getViewFile($controller, $viewName)

   {

  	$moduleViewPath = $this->getViewPath();

  	if (($module = $controller->getModule()) !== null) {

 		$moduleViewPath = $module->getBasePath() . '/themes/' . $this->getName() . '/views/' . $controller->getId();

  	}

  	return $controller->resolveViewFile($viewName, $this->getViewPath().'/'.$controller->getUniqueId(), $this->getViewPath(), $moduleViewPath);

   }

   

	/**

 	* Finds the layout file for the specified controller's layout.

 	* @param CController $controller the controller

 	* @param string $layoutName the layout name

 	* @return string the layout file path. False if the file does not exist.

 	*/

	public function getLayoutFile($controller,$layoutName)

	{

		$moduleViewPath = $basePath=$this->getViewPath();

		$module = $controller->getModule();

		if (empty($layoutName)) {

			while ($module !== null) {

				if($module->layout === false)

					return false;

				if(!empty($module->layout))

					break;

				$module = $module->getParentModule();

			}

			if($module === null) {

				$layoutName = Yii::app()->layout;

 		}

			else {

				$layoutName = $module->layout;

            	$moduleViewPath = $module->getBasePath() . '/themes/' . $this->getName() . '/views';

			}

		}

		else if($module !== null) {

 			$moduleViewPath = $module->getBasePath() . '/themes/' . $this->getName() . '/views';

    	}


		return $controller->resolveViewFile($layoutName, $moduleViewPath.'/layouts', $basePath, $moduleViewPath);

	}   

}

Since I’m not using skins, I didn’t try to get them to work under this scheme, but I think it could be done in the same way.

Accepting comments…

Thanks.