diff --git a/framework/cli/commands/shell/CrudCommand.php b/framework/cli/commands/shell/CrudCommand.php index d384851ef..6cf048392 100644 --- a/framework/cli/commands/shell/CrudCommand.php +++ b/framework/cli/commands/shell/CrudCommand.php @@ -164,13 +164,21 @@ EOD; return "CHtml::activeCheckBox(\${$modelVar},'{$column->name}')"; else if(stripos($column->dbType,'text')!==false) return "CHtml::activeTextArea(\${$modelVar},'{$column->name}',array('rows'=>6, 'cols'=>50))"; - else if($column->type!=='string' || $column->size===null) - return "CHtml::activeTextField(\${$modelVar},'{$column->name}')"; else { - if(($size=$maxLength=$column->size)>60) - $size=60; - return "CHtml::activeTextField(\${$modelVar},'{$column->name}',array('size'=>$size,'maxlength'=>$maxLength))"; + if(preg_match('/^(password|pass|passwd|passcode)$/i',$column->name)) + $inputField='activePasswordField'; + else + $inputField='activeTextField'; + + if($column->type!=='string' || $column->size===null) + return "CHtml::{$inputField}(\${$modelVar},'{$column->name}')"; + else + { + if(($size=$maxLength=$column->size)>60) + $size=60; + return "CHtml::{$inputField}(\${$modelVar},'{$column->name}',array('size'=>$size,'maxlength'=>$maxLength))"; + } } } } diff --git a/framework/cli/views/shell/crud/controller.php b/framework/cli/views/shell/crud/controller.php index f49bc78cd..b5e9a2830 100644 --- a/framework/cli/views/shell/crud/controller.php +++ b/framework/cli/views/shell/crud/controller.php @@ -10,8 +10,11 @@ class {ClassName} extends CController public $defaultAction='list'; /** - * Specifies the action filters. - * This method overrides the parent implementation. + * @var CActiveRecord the currently loaded data model instance. + */ + private $_{ModelVar}; + + /** * @return array action filters */ public function filters() @@ -23,23 +26,25 @@ class {ClassName} extends CController /** * Specifies the access control rules. - * This method overrides the parent implementation. - * It is only effective when 'accessControl' filter is enabled. + * This method is used by the 'accessControl' filter. * @return array access control rules */ public function accessRules() { return array( - array('deny', // deny access to create, update, delete operations for guest users - 'actions'=>array('create','update','delete'), - 'users'=>array('?'), + array('allow', // allow all users to perform 'list' and 'show' actions + 'actions'=>array('list','show'), + 'users'=>array('*'), ), - array('allow', // allow access to admin operation for admin user - 'actions'=>array('admin'), + array('allow', // allow authenticated user to perform 'create' and 'update' actions + 'actions'=>array('create','update'), + 'users'=>array('@'), + ), + array('allow', // allow admin user to perform 'admin' and 'delete' actions + 'actions'=>array('admin','delete'), 'users'=>array('admin'), ), - array('deny', // deny access to admin operation for all users - 'actions'=>array('admin'), + array('deny', // deny all users 'users'=>array('*'), ), ); @@ -50,7 +55,7 @@ class {ClassName} extends CController */ public function actionShow() { - $this->render('show',array('{ModelVar}'=>$this->load{ModelClass}())); + $this->render('show',array('{ModelVar}'=>$this->get{ModelClass}())); } /** @@ -75,7 +80,7 @@ class {ClassName} extends CController */ public function actionUpdate() { - ${ModelVar}=$this->load{ModelClass}(); + ${ModelVar}=$this->get{ModelClass}(); if(isset($_POST['{ModelClass}'])) { ${ModelVar}->attributes=$_POST['{ModelClass}']; @@ -94,7 +99,7 @@ class {ClassName} extends CController if(Yii::app()->request->isPostRequest) { // we only allow deletion via POST request - $this->load{ModelClass}()->delete(); + $this->get{ModelClass}()->delete(); $this->redirect(array('list')); } else @@ -106,7 +111,8 @@ class {ClassName} extends CController */ public function actionList() { - $pages=$this->paginate({ModelClass}::model()->count(), self::PAGE_SIZE); + $pages=new CPagination({ModelClass}::model()->count()); + $pages->pageSize=self::PAGE_SIZE; ${ModelVar}List={ModelClass}::model()->findAll($this->getListCriteria($pages)); $this->render('list',array( @@ -121,7 +127,8 @@ class {ClassName} extends CController { $this->processAdminCommand(); - $pages=$this->paginate({ModelClass}::model()->count(), self::PAGE_SIZE); + $pages=new CPagination({ModelClass}::model()->count()); + $pages->pageSize=self::PAGE_SIZE; ${ModelVar}List={ModelClass}::model()->findAll($this->getListCriteria($pages)); $this->render('admin',array( @@ -130,17 +137,20 @@ class {ClassName} extends CController } /** - * Loads the data model based on the primary key given in the GET variable. + * Returns the data model based on the primary key given in the GET variable. * If the data model is not found, an HTTP exception will be raised. + * @param integer the primary key value. Defaults to null, meaning using the 'id' GET variable */ - protected function load{ModelClass}() + public function get{ModelClass}($id=null) { - if(isset($_GET['id'])) - ${ModelVar}={ModelClass}::model()->findbyPk($_GET['id']); - if(isset(${ModelVar})) - return ${ModelVar}; - else - throw new CHttpException(500,'The requested {ModelName} does not exist.'); + if($this->_{ModelVar}===null) + { + if($id!==null || isset($_GET['id'])) + $this->_{ModelVar}={ModelClass}::model()->findbyPk($id!==null ? $id : $_GET['id']); + if($this->_{ModelVar}===null) + throw new CHttpException(500,'The requested {ModelName} does not exist.'); + } + return $this->_{ModelVar}; } /** @@ -196,17 +206,9 @@ class {ClassName} extends CController { if(isset($_POST['command'], $_POST['id']) && $_POST['command']==='delete') { - if(Yii::app()->user->isGuest) - Yii::app()->user->loginRequired(); - - if((${ModelVar}={ModelClass}::model()->findbyPk($_POST['id']))!==null) - { - ${ModelVar}->delete(); - // reload the current page to avoid duplicated delete actions - $this->refresh(); - } - else - throw new CHttpException(500,'The requested {ModelName} does not exist.'); + $this->get{ModelClass}($_POST['id'])->delete(); + // reload the current page to avoid duplicated delete actions + $this->refresh(); } } } diff --git a/framework/cli/views/shell/model/model.php b/framework/cli/views/shell/model/model.php index f1124fe9d..065408dca 100644 --- a/framework/cli/views/shell/model/model.php +++ b/framework/cli/views/shell/model/model.php @@ -4,7 +4,6 @@ class {ClassName} extends CActiveRecord { /** * Returns the static model of the specified AR class. - * This method is required by all child classes of CActiveRecord. * @return CActiveRecord the static model class */ public static function model($className=__CLASS__) @@ -29,29 +28,33 @@ class {ClassName} extends CActiveRecord ); } - - // ----------------------------------------------------------- - // Uncomment the following methods to override them if needed - /* + /** + * @return array relational rules. + */ public function relations() { return array( - 'author'=>array(self::BELONGS_TO, 'User', 'authorId'), - 'comments'=>array(self::HAS_MANY, 'Comment', 'postId', 'with'=>'author', 'order'=>'createTime DESC'), - 'tags'=>array(self::MANY_MANY, 'Tag', 'PostTag(postId, tagId)', 'order'=>'name'), ); } + /** + * @return array customized attribute labels (name=>label) + */ public function attributeLabels() { return array( - 'authorID'=>'Author', ); } + /** + * Returns the list of attributes that should not be massively assigned. + * You may also override safeAttributes() to specify the list of attributes + * that CAN be massively assigned. Do not override both, though. + * @return array list of attributes that should not be massively assigned. + */ public function protectedAttributes() { - return array(); + return array( + ); } - */ } \ No newline at end of file diff --git a/framework/cli/views/webapp/protected/controllers/SiteController.php b/framework/cli/views/webapp/protected/controllers/SiteController.php index 8cf15ca5b..f5b9ef07e 100644 --- a/framework/cli/views/webapp/protected/controllers/SiteController.php +++ b/framework/cli/views/webapp/protected/controllers/SiteController.php @@ -32,17 +32,17 @@ class SiteController extends CController */ public function actionLogin() { - $user=new LoginForm; + $form=new LoginForm; // collect user input data if(isset($_POST['LoginForm'])) { - $user->attributes=$_POST['LoginForm']; + $form->attributes=$_POST['LoginForm']; // validate user input and redirect to previous page if valid - if($user->validate()) + if($form->validate()) $this->redirect(Yii::app()->user->returnUrl); } // display the login form - $this->render('login',array('user'=>$user)); + $this->render('login',array('form'=>$form)); } /** diff --git a/framework/cli/views/webapp/protected/views/site/index.php b/framework/cli/views/webapp/protected/views/site/index.php index 5bfd53800..c4f0ae9e3 100644 --- a/framework/cli/views/webapp/protected/views/site/index.php +++ b/framework/cli/views/webapp/protected/views/site/index.php @@ -18,19 +18,19 @@ This is the homepage of name; ?>. You may modify

What's Next

diff --git a/framework/cli/views/webapp/protected/views/site/login.php b/framework/cli/views/webapp/protected/views/site/login.php index 7d083425e..ba5aea55b 100644 --- a/framework/cli/views/webapp/protected/views/site/login.php +++ b/framework/cli/views/webapp/protected/views/site/login.php @@ -3,16 +3,16 @@
- +
- - + +
- - + +

Hint: You may login with demo/demo or admin/admin.

@@ -20,11 +20,11 @@ Hint: You may login with demo/demo or admin/admin.
- +
widget('CCaptcha'); ?>
- +

Please enter the letters as they are shown in the image above.
Letters are not case-sensitive.

@@ -32,7 +32,7 @@ Hint: You may login with demo/demo or admin/admin.
- Remember me next time
+ Remember me next time
diff --git a/framework/web/CController.php b/framework/web/CController.php index ccd988a33..a1055d4db 100644 --- a/framework/web/CController.php +++ b/framework/web/CController.php @@ -802,6 +802,10 @@ class CController extends CBaseController * This method can be used to generate pagination information given item count * and page size. The pagination information can then be passed to {@link CBasePager pagers} * for corresponding rendering. + * + * Note: this method has been deprecated since version 1.0.1. + * You should directly use "new CPagination" to create a pagination object. + * * @param integer the total item count * @param integer the page size. See {@link CPagination} for default value. * @param string the name of the GET variable storing the current page index. See {@link CPagination} for default value. @@ -809,8 +813,7 @@ class CController extends CBaseController */ public function paginate($itemCount,$pageSize=null,$pageVar=null) { - $pages=new CPagination; - $pages->setItemCount($itemCount); + $pages=new CPagination($itemCount); if($pageSize!==null) $pages->pageSize=$pageSize; if($pageVar!==null) diff --git a/framework/web/CPagination.php b/framework/web/CPagination.php index 7542f7a2c..d696a589d 100644 --- a/framework/web/CPagination.php +++ b/framework/web/CPagination.php @@ -43,6 +43,16 @@ class CPagination extends CComponent private $_itemCount=0; private $_currentPage; + /** + * Constructor. + * @param integer total number of items. + * @since 1.0.1 + */ + public function __construct($itemCount) + { + $this->setItemCount($itemCount); + } + /** * @return integer number of items in each page. Defaults to 10. */ @@ -118,8 +128,13 @@ class CPagination extends CComponent /** * Creates the URL suitable for pagination. + * This method is mainly called by pagers when creating URLs used to + * perform pagination. The default implementation is to call + * the controller's createUrl method with the page information. + * You may override this method if your URL scheme is not the same as + * the one supported by the controller's createUrl method. * @param CController the controller that will create the actual URL - * @param integer the page that the URL should point to. + * @param integer the page that the URL should point to. This is a zero-based index. * @return string the created URL */ public function createPageUrl($controller,$page) diff --git a/framework/web/widgets/CAutoComplete.php b/framework/web/widgets/CAutoComplete.php index 9d8e72407..af12295b1 100644 --- a/framework/web/widgets/CAutoComplete.php +++ b/framework/web/widgets/CAutoComplete.php @@ -191,6 +191,23 @@ class CAutoComplete extends CInputWidget { list($name,$id)=$this->resolveNameID(); $this->htmlOptions['id']=$id; + + $this->registerClientScript(); + + if($this->hasModel()) + echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions); + else + echo CHtml::textField($name,$this->value,$this->htmlOptions); + } + + /** + * Registers the needed CSS and JavaScript. + * @since 1.0.1 + */ + public function registerClientScript() + { + $id=$this->htmlOptions['id']; + $acOptions=$this->getClientOptions(); $options=$acOptions===array()?'{}' : CJavaScript::encode($acOptions); @@ -208,11 +225,6 @@ class CAutoComplete extends CInputWidget $cs->registerCssFile($cs->getCoreScriptUrl().'/autocomplete/jquery.autocomplete.css'); else if($this->cssFile!==false) $cs->registerCssFile($this->cssFile); - - if($this->hasModel()) - echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions); - else - echo CHtml::textField($name,$this->value,$this->htmlOptions); } /** diff --git a/framework/web/widgets/CFlexWidget.php b/framework/web/widgets/CFlexWidget.php index e1cd4c00e..c351c2e6f 100644 --- a/framework/web/widgets/CFlexWidget.php +++ b/framework/web/widgets/CFlexWidget.php @@ -81,6 +81,17 @@ class CFlexWidget extends CWidget if($this->altHtmlContent===null) $this->altHtmlContent=Yii::t('yii','This content requires the Adobe Flash Player.'); + $this->registerClientScript(); + + $this->render('flexWidget'); + } + + /** + * Registers the needed CSS and JavaScript. + * @since 1.0.1 + */ + public function registerClientScript() + { $cs=Yii::app()->getClientScript(); $cs->registerScriptFile($this->baseUrl.'/AC_OETags.js'); @@ -89,8 +100,6 @@ class CFlexWidget extends CWidget $cs->registerCssFile($this->baseUrl.'/history/history.css'); $cs->registerScriptFile($this->baseUrl.'/history/history.js'); } - - $this->render('flexWidget'); } /** diff --git a/framework/web/widgets/CMarkdown.php b/framework/web/widgets/CMarkdown.php index 48d0f154d..32676ec35 100644 --- a/framework/web/widgets/CMarkdown.php +++ b/framework/web/widgets/CMarkdown.php @@ -41,6 +41,8 @@ class CMarkdown extends COutputProcessor */ public $purifyOutput=false; + private $_parser; + /** * Processes the captured output. * This method converts the content in markdown syntax to HTML code. @@ -66,14 +68,36 @@ class CMarkdown extends COutputProcessor * @return string the converted content */ public function transform($output) + { + $this->registerClientScript(); + return $this->getMarkdownParser()->transform($output); + } + + /** + * Registers the needed CSS and JavaScript. + * @since 1.0.1 + */ + public function registerClientScript() { $cs=Yii::app()->getClientScript(); - $parser=$this->createMarkdownParser(); if($this->cssFile===null) - $cs->registerCssFile(CHtml::asset($parser->getDefaultCssFile())); + $cs->registerCssFile(CHtml::asset($this->getMarkdownParser()->getDefaultCssFile())); else if($this->cssFile!==false) $cs->registerCssFile($this->cssFile); - return $parser->transform($output); + } + + /** + * Returns the markdown parser instance. + * This method calls {@link createMarkdownParser} to create the parser instance. + * Call this method multipe times will only return the same instance. + * @param CMarkdownParser the parser instance + * @since 1.0.1 + */ + public function getMarkdownParser() + { + if($this->_parser===null) + $this->_parser=$this->createMarkdownParser(); + return $this->_parser; } /** diff --git a/framework/web/widgets/CMaskedTextField.php b/framework/web/widgets/CMaskedTextField.php index 35035a32c..b1c4fa624 100644 --- a/framework/web/widgets/CMaskedTextField.php +++ b/framework/web/widgets/CMaskedTextField.php @@ -57,6 +57,22 @@ class CMaskedTextField extends CInputWidget { list($name,$id)=$this->resolveNameID(); $this->htmlOptions['id']=$id; + + $this->registerClientScript(); + + if($this->hasModel()) + echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions); + else + echo CHtml::textField($name,$this->value,$this->htmlOptions); + } + + /** + * Registers the needed CSS and JavaScript. + * @since 1.0.1 + */ + public function registerClientScript() + { + $id=$this->htmlOptions['id']; $miOptions=$this->getClientOptions(); $options=$miOptions!==array() ? ','.CJavaScript::encode($miOptions) : ''; $js=''; @@ -67,11 +83,6 @@ class CMaskedTextField extends CInputWidget $cs=Yii::app()->getClientScript(); $cs->registerCoreScript('maskedinput'); $cs->registerScript('Yii.CMaskedTextField#'.$id,$js); - - if($this->hasModel()) - echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions); - else - echo CHtml::textField($name,$this->value,$this->htmlOptions); } /** diff --git a/framework/web/widgets/CMultiFileUpload.php b/framework/web/widgets/CMultiFileUpload.php index ae5cd7fba..8be703a1a 100644 --- a/framework/web/widgets/CMultiFileUpload.php +++ b/framework/web/widgets/CMultiFileUpload.php @@ -81,6 +81,18 @@ class CMultiFileUpload extends CWidget } $this->htmlOptions['id']=$id; + $this->registerClientScript(); + + echo CHtml::fileField($name,'',$this->htmlOptions); + } + + /** + * Registers the needed CSS and JavaScript. + * @since 1.0.1 + */ + public function registerClientScript() + { + $id=$this->htmlOptions['id']; $mfOptions=array(); if($this->accept!==null) $mfOptions['accept']=$this->accept; @@ -99,7 +111,5 @@ class CMultiFileUpload extends CWidget $cs=Yii::app()->getClientScript(); $cs->registerCoreScript('multifile'); $cs->registerScript('Yii.CMultiFileUpload#'.$id,"jQuery(\"#{$id}\").MultiFile({$options});"); - - echo CHtml::fileField($name,'',$this->htmlOptions); } } diff --git a/framework/web/widgets/CStarRating.php b/framework/web/widgets/CStarRating.php index ebb47826d..dcec13a1a 100644 --- a/framework/web/widgets/CStarRating.php +++ b/framework/web/widgets/CStarRating.php @@ -115,7 +115,7 @@ class CStarRating extends CInputWidget * Registers the necessary javascript and css scripts. * @param string the ID of the container */ - protected function registerClientScript($id) + public function registerClientScript($id) { $jsOptions=$this->getClientOptions(); $jsOptions=empty($jsOptions) ? '' : CJavaScript::encode($jsOptions); diff --git a/framework/web/widgets/CTabView.php b/framework/web/widgets/CTabView.php index fd1437efe..4671670f6 100644 --- a/framework/web/widgets/CTabView.php +++ b/framework/web/widgets/CTabView.php @@ -142,7 +142,7 @@ class CTabView extends CWidget /** * Registers the needed CSS and JavaScript. */ - protected function registerClientScript() + public function registerClientScript() { $cs=Yii::app()->getClientScript(); $cs->registerCoreScript('yiitab'); diff --git a/framework/web/widgets/CTextHighlighter.php b/framework/web/widgets/CTextHighlighter.php index 32b9f2f39..0d2492f20 100644 --- a/framework/web/widgets/CTextHighlighter.php +++ b/framework/web/widgets/CTextHighlighter.php @@ -84,23 +84,14 @@ class CTextHighlighter extends COutputProcessor */ public function highlight($content) { + $this->registerClientScript(); + $options['use_language']=true; $options['tabsize']=$this->tabSize; if($this->showLineNumbers) $options['numbers']=($this->lineNumberStyle==='list')?HL_NUMBERS_LI:HL_NUMBERS_TABLE; - $cs=Yii::app()->getClientScript(); - - if($this->cssFile===null) - { - $cssFile=Yii::getPathOfAlias('system.vendors.TextHighlighter.highlight').'.css'; - $cs->registerCssFile(CHtml::asset($cssFile)); - } - else if($this->cssFile!==false) - $cs->registerCssFile($this->cssFile); - $highlighter=empty($this->language)?false:Text_Highlighter::factory($this->language); - if($highlighter===false) $o='
'.CHtml::encode($content).'
'; else @@ -111,4 +102,21 @@ class CTextHighlighter extends COutputProcessor return CHtml::tag('div',$this->containerOptions,$o); } + + /** + * Registers the needed CSS and JavaScript. + * @since 1.0.1 + */ + public function registerClientScript() + { + $cs=Yii::app()->getClientScript(); + + if($this->cssFile===null) + { + $cssFile=Yii::getPathOfAlias('system.vendors.TextHighlighter.highlight').'.css'; + $cs->registerCssFile(CHtml::asset($cssFile)); + } + else if($this->cssFile!==false) + $cs->registerCssFile($this->cssFile); + } } diff --git a/framework/web/widgets/pagers/CLinkPager.php b/framework/web/widgets/pagers/CLinkPager.php index 8ae46b39d..a8ea64ecb 100644 --- a/framework/web/widgets/pagers/CLinkPager.php +++ b/framework/web/widgets/pagers/CLinkPager.php @@ -168,7 +168,7 @@ class CLinkPager extends CBasePager /** * Registers the needed client scripts (mainly CSS file). */ - protected function registerClientScript() + public function registerClientScript() { $cs=Yii::app()->getClientScript(); if($this->cssFile===null)