PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/extensions/pogostick/commands/CPSControllerCommand.php

https://github.com/Pogostick/ps-yii-extensions
PHP | 326 lines | 183 code | 61 blank | 82 comment | 14 complexity | c4c1a70bc4cb068af3422c7cb3ac83c5 MD5 | raw file
  1. <?php
  2. /**
  3. * CPSControllerCommand class file.
  4. *
  5. * @filesource
  6. * @author Jerry Ablan <jablan@pogostick.com>
  7. * @copyright Copyright (c) 2009-2011 Pogostick, LLC.
  8. * @link http://www.pogostick.com Pogostick, LLC.
  9. * @package psYiiExtensions
  10. * @subpackage commands
  11. * @since v1.0.6
  12. * @version SVN: $Revision: 380 $
  13. * @modifiedby $LastChangedBy: jerryablan@gmail.com $
  14. * @lastmodified $Date: 2010-04-05 07:20:21 -0400 (Mon, 05 Apr 2010) $
  15. */
  16. // Imports for me...
  17. Yii::import( 'pogostick.commands.CPSConsoleCommand' );
  18. /**
  19. * Command that generates a Pogostick Yii Controller
  20. */
  21. class CPSControllerCommand extends CPSConsoleCommand
  22. {
  23. //********************************************************************************
  24. //* Constants
  25. //********************************************************************************
  26. /**
  27. * Our version
  28. */
  29. const VERSION = '1.0.6';
  30. //********************************************************************************
  31. //* Public Methods
  32. //********************************************************************************
  33. /**
  34. * Initialize the command
  35. *
  36. */
  37. public function init()
  38. {
  39. parent::init();
  40. // Add our options
  41. $this->addOptions( self::getBaseOptions() );
  42. // Set base values
  43. $this->templatePath = Yii::getPathOfAlias( 'pogostick.templates.crud' );
  44. $this->controllerBaseClass = 'CPSController';
  45. $this->controllerTemplateName = 'controller.php';
  46. $this->name = 'pscontroller';
  47. }
  48. /**
  49. * Runs the command
  50. *
  51. * @param array $arArgs Command line parameters specific for this command
  52. */
  53. public function run( $arArgs )
  54. {
  55. // Process arguments...
  56. $arArgs = $this->processArguments( $arArgs );
  57. // Check args...
  58. if ( ! ( $_sControllerId = array_shift( $arArgs ) ) )
  59. {
  60. echo "\033[1mError\033[0m: controller name is required.\n";
  61. echo $this->getHelp();
  62. return;
  63. }
  64. // Get actions from arguments...
  65. $_arActions = array( 'index' );
  66. // The rest of the arguments are actions...
  67. while ( $_sAction = array_shift( $arArgs ) )
  68. array_push( $_arActions, $_sAction );
  69. // Set our actions...
  70. $this->actions = $_arActions;
  71. // Load the module
  72. $_oModule = Yii::app();
  73. $_sModuleId = ( $_oModule instanceof CWebModule ) ? $_oModule->id . '/' : '';
  74. // Get controller stuff
  75. list( $_sControllerClass, $_sControllerFile, $_sControllerId ) = $this->parseControllerId( $_sControllerId, $_oModule );
  76. // Build our parameter array
  77. $_sClasses = $this->boldEchoString( '(' . $_sControllerFile . ')', $_sControllerClass, true );
  78. $_arList = array(
  79. basename( $_sControllerFile ) => array(
  80. 'source' => $this->templatePath . DIRECTORY_SEPARATOR . $this->controllerTemplateName,
  81. 'target' => $_sControllerFile,
  82. 'callback' => array( $this, 'generateController' ),
  83. 'params' => array( $_sControllerClass, $this->actions ),
  84. ),
  85. );
  86. $_sViewPath = $_oModule->viewPath . DIRECTORY_SEPARATOR . str_replace( '/', DIRECTORY_SEPARATOR, $_sControllerId );
  87. // Actions
  88. foreach ( $this->actions as $_sAction )
  89. {
  90. $_arList[ $_sAction . '.php' ] = array(
  91. 'source' => $this->templatePath . DIRECTORY_SEPARATOR . $this->viewTemplateName,
  92. 'target' => $_sViewPath . DIRECTORY_SEPARATOR . $_sAction . '.php',
  93. 'callback' => array( $this, 'generateAction' ),
  94. 'params' => array(),
  95. );
  96. $_sClasses .= $this->boldEchoString( '(' . $_sViewPath . DIRECTORY_SEPARATOR . $_sAction . '.php' . ')', $_sAction, true );
  97. }
  98. $this->displayParameters( 'Controller Generator', array( 'Output Path' => $_sViewPath ) );
  99. $_sPrompt = "Do you want to generate the above classes? [\033[1mY\033[0mes|\033[1mN\033[0mo] ";
  100. // Generate
  101. $_arList = $this->copyFiles( $_arList );
  102. // Display results...
  103. echo $this->getResultDisplay( $_arList );
  104. }
  105. /**
  106. * Generate a controller, ingore lack of PK for views
  107. *
  108. * @param mixed $sSourceFile
  109. * @param mixed $arParams
  110. * @return string
  111. */
  112. public function generateController( $sSourceFile, $arParams )
  113. {
  114. if ( ! is_file( $sSourceFile ) ) $sSourceFile = YII_PATH . '/cli/views/shell/controller/' . basename( $sSourceFile );
  115. return $this->renderFile(
  116. $sSourceFile,
  117. array(
  118. 'className' => $arParams[ 0 ],
  119. 'actions' => $arParams[ 1 ],
  120. 'baseClass' => $this->controllerBaseClass
  121. ),
  122. true
  123. );
  124. }
  125. /**
  126. * Generate an action file
  127. *
  128. * @param string $sSourceFile
  129. * @param array $arParams
  130. * @return string
  131. */
  132. public function generateAction( $sSourceFile, $arParams )
  133. {
  134. if ( ! is_file( $sSourceFile ) ) $sSourceFile = YII_PATH . '/cli/views/shell/controller/' . basename( $sSourceFile );
  135. return $this->renderFile( $sSourceFile, array(), true );
  136. }
  137. /**
  138. * Generates an input field
  139. *
  140. * @param string $sModelClass
  141. * @param CDbColumnSchema $oColumn
  142. */
  143. public function generateInputField( $sModelClass, $oColumn )
  144. {
  145. if ( $oColumn->type === 'boolean' ) return "PS::field( PS::CHECK, \$model, '{$oColumn->name}' )";
  146. if ( false !== stripos( $oColumn->dbType, 'text' ) )
  147. return "PS::field( PS::TEXTAREA, \$model, '{$oColumn->name}', array( 'rows' => 6, 'cols' => 50 ) )";
  148. $_sType = ( preg_match( '/^(password|pass|passwd|passcode)$/i', $oColumn->name ) ) ? 'PS::PASSWORD' : 'PS::TEXT';
  149. if ( $oColumn->type !== 'string' || $oColumn->size === null )
  150. return "PS::field( {$_sType}, \$model, '{$_oColumn->name}' )";
  151. if ( ( $_iSize = $_iMaxLength = $oColumn->size ) > 60 ) $_iSize = 60;
  152. return "PS::field( {$_sType}, $model, '{$oColumn->name}', array( 'size' => $_iSize, 'maxlength' => $_iMaxLength ) )";
  153. }
  154. /**
  155. * Display help
  156. *
  157. */
  158. public function getHelp()
  159. {
  160. $_sName = $this->bold( $this->name );
  161. $_sOptions = $this->getDisplayOptions();
  162. return <<<EOD
  163. USAGE
  164. \033[1m{$_sName}\033[0m <\033[1mcontroller-ID\033[0m> [\033[1maction-ID\033[0m]... [options]
  165. DESCRIPTION
  166. This command generates a controller and views associated with
  167. the specified actions.
  168. PARAMETERS
  169. * controller-ID: required, controller ID, e.g., 'post'.
  170. If the controller should be located under a subdirectory,
  171. please specify the controller ID as 'path/to/ControllerID',
  172. e.g., 'admin/user'.
  173. If the controller belongs to a module, please specify
  174. the controller ID as 'ModuleID/ControllerID' or
  175. 'ModuleID/path/to/Controller' (assuming the controller is
  176. under a subdirectory of that module).
  177. * action-ID: optional, action ID. You may supply one or several
  178. action IDs. A default 'index' action will always be generated.
  179. OPTIONS
  180. -f, --force if the files exists, you will be able to
  181. optionally overwrite them.
  182. -d, --database The database component to use.
  183. Defaults to 'db'
  184. -b, --base-class The base class to use for generated controllers.
  185. Defaults to 'CPSController'
  186. -t, --template-path The template path to use.
  187. -n, --template-name The name of the template to use.
  188. Defaults to 'controller.php'
  189. {$_sOptions}
  190. EXAMPLES
  191. * Generates the 'post' controller:
  192. {$_sName} post
  193. * Generates the 'post' controller with additional actions 'contact'
  194. and 'about':
  195. {$_sName} post contact about
  196. * Generates the 'post' controller which should be located under
  197. the 'admin' subdirectory of the base controller path:
  198. {$_sName} admin/post
  199. * Generates the 'post' controller which should belong to
  200. the 'admin' module:
  201. {$_sName} admin/post
  202. NOTE: in the last two examples, the commands are the same, but
  203. the generated controller file is located under different directories.
  204. Yii is able to detect whether 'admin' refers to a module or a subdirectory.
  205. EOD;
  206. }
  207. //********************************************************************************
  208. //* Private Methods
  209. //********************************************************************************
  210. protected function parseControllerId( $sModelClass, $sControllerId, $oModule )
  211. {
  212. if ( empty( $sControllerId ) )
  213. {
  214. $sControllerId = $sModelClass;
  215. $_sControllerClass = ucfirst( $sControllerId ) . 'Controller';
  216. $_sControllerFile = $oModule->controllerPath . DIRECTORY_SEPARATOR . $_sControllerClass . '.php';
  217. $sControllerId[ 0 ] = strtolower( $sControllerId[ 0 ] );
  218. }
  219. else
  220. {
  221. // Build the controller
  222. if ( false === ( $_iPos = strrpos( $sControllerId, '/' ) ) )
  223. {
  224. $_sControllerClass = ucfirst( $sControllerId ) . 'Controller';
  225. $_sControllerFile = $oModule->controllerPath . DIRECTORY_SEPARATOR . $_sControllerClass . '.php';
  226. $sControllerId[ 0 ] = strtolower( $sControllerId[ 0 ] );
  227. }
  228. else
  229. {
  230. $_sLast = substr( $sControllerId, $_iPos + 1 );
  231. $_sLast[ 0 ] = strtolower( $_sLast );
  232. $_iPos2 = strpos( $sControllerId, '/' );
  233. $_sFirst = substr( $sControllerId, 0, $_iPos2 );
  234. $_sMiddle = $_iPos === $_iPos2 ? '' : substr( $sControllerId, $_iPos2 + 1, $_iPos - $_iPos2 );
  235. $_sControllerClass = ucfirst( $_sLast ) . 'Controller';
  236. $_sControllerFile = ( $_sMiddle === '' ? '' : $_sMiddle . '/' ) . $_sControllerClass . '.php';
  237. $sControllerId = empty( $_sMiddle ) ? $_sLast : $_sMiddle . '/' . $_sLast;
  238. if ( null !== ( $_oNewModule = Yii::app()->getModule( $_sFirst ) ) )
  239. $oModule = $_oNewModule;
  240. else
  241. {
  242. $_sControllerFile = $_sFirst . '/' . $_sControllerFile;
  243. $sControllerId = $_sFirst . '/' . $sControllerId;
  244. }
  245. $_sControllerFile = $oModule->controllerPath . DIRECTORY_SEPARATOR . str_replace( '/', DIRECTORY_SEPARATOR, $_sControllerFile );
  246. }
  247. }
  248. return array( $_sControllerClass, $_sControllerFile, $sControllerId );
  249. }
  250. /**
  251. * Easier on the eyes
  252. *
  253. * @access private
  254. */
  255. private function getBaseOptions()
  256. {
  257. return(
  258. array(
  259. 'viewTemplateName' => 'string:view.php',
  260. 'controllerBaseClass' => 'string:CPSController',
  261. 'controllerTemplateName' => 'string:controller.php',
  262. )
  263. );
  264. }
  265. }