diff --git a/CHANGELOG b/CHANGELOG index 0cc617c4c..51408ea4d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,12 +10,17 @@ Version 1.0.3 to be released ---------------------------- - Bug #127: CUploadedFile is using an undefined variable (Qiang) - Bug #132: CMysqlSchema has a typo (Qiang) +- Bug #133: CSort should properly quote the columns to be sorted (Qiang) +- Bug #135: CSort::link() does not work well with labels with special chars (Qiang) +- Bug #145: When layout property of CController is false, main layout is still applied (Qiang) - Bug: CHttpRequest.hostInfo may give wrong port number (Qiang) - Bug: CHtml::activeListBox does not work when multiple selection is needed (Qiang) - Bug: Inconsistency in timezone of log messages for different log routes (Qiang) - Bug: Script file registered for POS_BEGIN is rendered twice (Qiang) - New #117: Added count() support to relational AR (Qiang) - New #136: Added support to CWebUser to allow directly accessing persistent properties (Qiang) +- New #137: yiic model command should only set a column as required when it does not have default value (Qiang) +- New #138: Added support to specify additional attributes for OPTION tags (Qiang) - New: Upgraded jquery to 1.3.1 (Qiang) - New: Upgraded jquery star rating to 2.61 (Qiang) - New: Added skeleton application and refactored 'yiic webapp' command (Qiang) diff --git a/README b/README index 6400a90e3..939166304 100644 --- a/README +++ b/README @@ -1,19 +1,18 @@ - - Yii Web Programming Framework - ============================= +Yii Web Programming Framework +============================= Thank you for choosing Yii - a high-performance component-based PHP framework. INSTALLATION ------------ + Please make sure the release file is unpacked under a Web-accessible directory. You shall see the following files and directories: demos/ demos framework/ framework source files requirements/ requirement checker - testdrive/ a skeleton Yii application CHANGELOG describing changes in every Yii release LICENSE license of Yii README this file @@ -22,6 +21,7 @@ directory. You shall see the following files and directories: REQUIREMENTS ------------ + The minimum requirement by Yii is that your Web server supports PHP 5.1.0 or above. Yii has been tested with Apache HTTP server on Windows and Linux operating systems. @@ -34,8 +34,19 @@ the requirements by Yii, assuming "YiiPath" is where Yii is installed: QUICK START ----------- -Yii comes with a skeleton application located under the directory -"testdrive". It is a good starting point for your application. + +Yii comes with a command line tool called "yiic" that can create +a skeleton Yii application for you to start with. + +On command line, type in the following commands: + + $ cd YiiPath/framework (Linux) + cd YiiPath\framework (Windows) + + $ ./yiic webapp ../testdrive (Linux) + yiic webapp ..\testdrive (Windows) + +The new Yii application will be created at "YiiPath/testdrive". You can access it with the following URL: http://hostname/YiiPath/testdrive/index.php @@ -43,6 +54,7 @@ You can access it with the following URL: WHAT's NEXT ----------- + Please visit the project website for tutorials, class reference and join discussions with other Yii users. diff --git a/docs/blog/comment.create.txt b/docs/blog/comment.create.txt index 4da86bc5e..865ede61d 100644 --- a/docs/blog/comment.create.txt +++ b/docs/blog/comment.create.txt @@ -59,7 +59,8 @@ protected function newComment($post) $comment->validate('insert'); else if(isset($_POST['submitComment']) && $comment->save()) { - Yii::app()->user->setFlash('commentSubmitted','Thank you...'); $this->refresh(); + Yii::app()->user->setFlash('commentSubmitted','Thank you...'); + $this->refresh(); } } return $comment; diff --git a/docs/blog/final.url.txt b/docs/blog/final.url.txt index bd9b08cd8..e81da44e3 100644 --- a/docs/blog/final.url.txt +++ b/docs/blog/final.url.txt @@ -7,7 +7,7 @@ The URLs linking various pages of our blog application currently look ugly. For /index.php?r=post/show&id=1 ~~~ -In this section, we describe how to beautifying these URLs and make them SEO-friendly. We goal is to be able to use the following URLs in the application: +In this section, we describe how to beautifying these URLs and make them SEO-friendly. Our goal is to be able to use the following URLs in the application: * `/index.php/tag/yii`: leads to the page showing a list of posts with tag `yii`; * `/index.php/posts`: leads to the page showing the latest posts; diff --git a/docs/blog/post.model.txt b/docs/blog/post.model.txt index 2f16aad74..21f9472e9 100644 --- a/docs/blog/post.model.txt +++ b/docs/blog/post.model.txt @@ -31,7 +31,7 @@ public function rules() } ~~~ -In the above, we specify that the `title`, `length` and `max` attributes are required; the length of `title` should not exceed 128; the `status` attribute value should be 0 (draft), 1 (published) or 2 (archived); and the `tags` attribute should only contain word characters and commas. All other attributes (e.g. `id`, `createTime`) will not be validated because their values do not come from user input. +In the above, we specify that the `title`, `content` and `status` attributes are required; the length of `title` should not exceed 128; the `status` attribute value should be 0 (draft), 1 (published) or 2 (archived); and the `tags` attribute should only contain word characters and commas. All other attributes (e.g. `id`, `createTime`) will not be validated because their values do not come from user input. After making these changes, we can visit the post creation page again to verify that the new validation rules are taking effect. diff --git a/docs/blog/prototype.auth.txt b/docs/blog/prototype.auth.txt index 30d45fc32..0829dde38 100644 --- a/docs/blog/prototype.auth.txt +++ b/docs/blog/prototype.auth.txt @@ -79,6 +79,6 @@ switch($identity->errorCode) > Info: People often get confused about identity and the `user` application component. The former represents a way of performing authentication, while the latter is used to represent the information related with the current user. An application can only have one `user` component, but it can have one or several identity classes, depending on what kind of authentication it supports. Once authenticated, an identity instance may pass its state information to the `user` component so that they are globally accessible via `user`. -To test the modified `UserIdentity` class, we can browse the URL `http://www.example.com/blog/index.php` and try logging in with the username and password that we store in the `User` table. If we use the database provided by the [blog demo](http://www.yiiframework.com/demos/blog/], we should be able to login with username `demo` and password `demo`. Note that this blog system does not provide the user management feature. As a result, a user cannot change his account or create a new one through the Web interface. The user management feature may be considered as a future enhancement to the blog application. +To test the modified `UserIdentity` class, we can browse the URL `http://www.example.com/blog/index.php` and try logging in with the username and password that we store in the `User` table. If we use the database provided by the [blog demo](http://www.yiiframework.com/demos/blog/), we should be able to login with username `demo` and password `demo`. Note that this blog system does not provide the user management feature. As a result, a user cannot change his account or create a new one through the Web interface. The user management feature may be considered as a future enhancement to the blog application.
$Id$
\ No newline at end of file diff --git a/docs/blog/toc.txt b/docs/blog/toc.txt index 6b487d587..70c100bb1 100644 --- a/docs/blog/toc.txt +++ b/docs/blog/toc.txt @@ -21,7 +21,7 @@ - [Creating and Displaying Comments](comment.create) - [Managing Comments](comment.admin) -* Porlets +* Portlets - [Establishing Portlet Architecture](portlet.base) - [Creating User Menu Portlet](portlet.menu) - [Creating Login Portlet](portlet.login) diff --git a/docs/guide/quickstart.first-app.txt b/docs/guide/quickstart.first-app.txt index 22d61bf68..966a50f41 100644 --- a/docs/guide/quickstart.first-app.txt +++ b/docs/guide/quickstart.first-app.txt @@ -26,9 +26,6 @@ This will create a skeleton Yii application under the directory `WebRoot/testdrive`. The application has a directory structure that is is needed by most Yii applications. -> Tip: Starting from version 1.0.3, a testdrive application is included -> directly under the directory `YiiRoot/testdrive`. - Without writing a single line of code, we can test drive our first Yii application by accessing the following URL in a Web browser: diff --git a/framework/cli/commands/WebAppCommand.php b/framework/cli/commands/WebAppCommand.php index 68614dea1..b821202da 100644 --- a/framework/cli/commands/WebAppCommand.php +++ b/framework/cli/commands/WebAppCommand.php @@ -54,7 +54,7 @@ EOD; echo "Create a Web application under '$path'? [Yes|No] "; if(!strncasecmp(trim(fgets(STDIN)),'y',1)) { - $sourceDir=realpath(dirname(__FILE__).'/../../../testdrive'); + $sourceDir=realpath(dirname(__FILE__).'/../views/webapp'); if($sourceDir===false) die('Unable to locate the source directory.'); $list=$this->buildFileList($sourceDir,$path); diff --git a/framework/cli/commands/shell/ModelCommand.php b/framework/cli/commands/shell/ModelCommand.php index 29d7e84ac..5ae695edd 100644 --- a/framework/cli/commands/shell/ModelCommand.php +++ b/framework/cli/commands/shell/ModelCommand.php @@ -101,7 +101,7 @@ EOD; { if($column->isPrimaryKey && $table->sequenceName!==null || $column->isForeignKey) continue; - if(!$column->allowNull) + if(!$column->allowNull && $column->defaultValue!==null) $required[]=$column->name; if($column->type==='integer') $integers[]=$column->name; diff --git a/framework/cli/views/shell/crud/controller.php b/framework/cli/views/shell/crud/controller.php index 210d46b7c..cd26417e4 100644 --- a/framework/cli/views/shell/crud/controller.php +++ b/framework/cli/views/shell/crud/controller.php @@ -113,7 +113,7 @@ class {ClassName} extends CController { $criteria=new CDbCriteria; - $pages=new CPagination({ModelClass}::model()->count()); + $pages=new CPagination({ModelClass}::model()->count($criteria)); $pages->pageSize=self::PAGE_SIZE; $pages->applyLimit($criteria); @@ -134,7 +134,7 @@ class {ClassName} extends CController $criteria=new CDbCriteria; - $pages=new CPagination({ModelClass}::model()->count()); + $pages=new CPagination({ModelClass}::model()->count($criteria)); $pages->pageSize=self::PAGE_SIZE; $pages->applyLimit($criteria); diff --git a/testdrive/assets/.yii b/framework/cli/views/webapp/assets/.yii similarity index 100% rename from testdrive/assets/.yii rename to framework/cli/views/webapp/assets/.yii diff --git a/testdrive/css/bg.gif b/framework/cli/views/webapp/css/bg.gif similarity index 100% rename from testdrive/css/bg.gif rename to framework/cli/views/webapp/css/bg.gif diff --git a/testdrive/css/form.css b/framework/cli/views/webapp/css/form.css similarity index 100% rename from testdrive/css/form.css rename to framework/cli/views/webapp/css/form.css diff --git a/testdrive/css/main.css b/framework/cli/views/webapp/css/main.css similarity index 100% rename from testdrive/css/main.css rename to framework/cli/views/webapp/css/main.css diff --git a/testdrive/images/.yii b/framework/cli/views/webapp/images/.yii similarity index 100% rename from testdrive/images/.yii rename to framework/cli/views/webapp/images/.yii diff --git a/testdrive/index.php b/framework/cli/views/webapp/index.php similarity index 100% rename from testdrive/index.php rename to framework/cli/views/webapp/index.php diff --git a/testdrive/protected/.htaccess b/framework/cli/views/webapp/protected/.htaccess similarity index 100% rename from testdrive/protected/.htaccess rename to framework/cli/views/webapp/protected/.htaccess diff --git a/testdrive/protected/commands/shell/.yii b/framework/cli/views/webapp/protected/commands/shell/.yii similarity index 100% rename from testdrive/protected/commands/shell/.yii rename to framework/cli/views/webapp/protected/commands/shell/.yii diff --git a/testdrive/protected/components/MainMenu.php b/framework/cli/views/webapp/protected/components/MainMenu.php similarity index 100% rename from testdrive/protected/components/MainMenu.php rename to framework/cli/views/webapp/protected/components/MainMenu.php diff --git a/testdrive/protected/components/UserIdentity.php b/framework/cli/views/webapp/protected/components/UserIdentity.php similarity index 100% rename from testdrive/protected/components/UserIdentity.php rename to framework/cli/views/webapp/protected/components/UserIdentity.php diff --git a/testdrive/protected/components/views/mainMenu.php b/framework/cli/views/webapp/protected/components/views/mainMenu.php similarity index 100% rename from testdrive/protected/components/views/mainMenu.php rename to framework/cli/views/webapp/protected/components/views/mainMenu.php diff --git a/testdrive/protected/config/console.php b/framework/cli/views/webapp/protected/config/console.php similarity index 100% rename from testdrive/protected/config/console.php rename to framework/cli/views/webapp/protected/config/console.php diff --git a/testdrive/protected/config/main.php b/framework/cli/views/webapp/protected/config/main.php similarity index 100% rename from testdrive/protected/config/main.php rename to framework/cli/views/webapp/protected/config/main.php diff --git a/testdrive/protected/controllers/SiteController.php b/framework/cli/views/webapp/protected/controllers/SiteController.php similarity index 100% rename from testdrive/protected/controllers/SiteController.php rename to framework/cli/views/webapp/protected/controllers/SiteController.php diff --git a/testdrive/protected/extensions/.yii b/framework/cli/views/webapp/protected/extensions/.yii similarity index 100% rename from testdrive/protected/extensions/.yii rename to framework/cli/views/webapp/protected/extensions/.yii diff --git a/testdrive/protected/messages/.yii b/framework/cli/views/webapp/protected/messages/.yii similarity index 100% rename from testdrive/protected/messages/.yii rename to framework/cli/views/webapp/protected/messages/.yii diff --git a/testdrive/protected/models/ContactForm.php b/framework/cli/views/webapp/protected/models/ContactForm.php similarity index 100% rename from testdrive/protected/models/ContactForm.php rename to framework/cli/views/webapp/protected/models/ContactForm.php diff --git a/testdrive/protected/models/LoginForm.php b/framework/cli/views/webapp/protected/models/LoginForm.php similarity index 100% rename from testdrive/protected/models/LoginForm.php rename to framework/cli/views/webapp/protected/models/LoginForm.php diff --git a/testdrive/protected/runtime/.yii b/framework/cli/views/webapp/protected/runtime/.yii similarity index 100% rename from testdrive/protected/runtime/.yii rename to framework/cli/views/webapp/protected/runtime/.yii diff --git a/testdrive/protected/views/layouts/main.php b/framework/cli/views/webapp/protected/views/layouts/main.php similarity index 100% rename from testdrive/protected/views/layouts/main.php rename to framework/cli/views/webapp/protected/views/layouts/main.php diff --git a/testdrive/protected/views/site/contact.php b/framework/cli/views/webapp/protected/views/site/contact.php similarity index 100% rename from testdrive/protected/views/site/contact.php rename to framework/cli/views/webapp/protected/views/site/contact.php diff --git a/testdrive/protected/views/site/index.php b/framework/cli/views/webapp/protected/views/site/index.php similarity index 100% rename from testdrive/protected/views/site/index.php rename to framework/cli/views/webapp/protected/views/site/index.php diff --git a/testdrive/protected/views/site/login.php b/framework/cli/views/webapp/protected/views/site/login.php similarity index 100% rename from testdrive/protected/views/site/login.php rename to framework/cli/views/webapp/protected/views/site/login.php diff --git a/testdrive/protected/views/system/.yii b/framework/cli/views/webapp/protected/views/system/.yii similarity index 100% rename from testdrive/protected/views/system/.yii rename to framework/cli/views/webapp/protected/views/system/.yii diff --git a/testdrive/protected/yiic b/framework/cli/views/webapp/protected/yiic similarity index 100% rename from testdrive/protected/yiic rename to framework/cli/views/webapp/protected/yiic diff --git a/testdrive/protected/yiic.bat b/framework/cli/views/webapp/protected/yiic.bat similarity index 100% rename from testdrive/protected/yiic.bat rename to framework/cli/views/webapp/protected/yiic.bat diff --git a/testdrive/protected/yiic.php b/framework/cli/views/webapp/protected/yiic.php similarity index 100% rename from testdrive/protected/yiic.php rename to framework/cli/views/webapp/protected/yiic.php diff --git a/testdrive/themes/classic/views/.htaccess b/framework/cli/views/webapp/themes/classic/views/.htaccess similarity index 100% rename from testdrive/themes/classic/views/.htaccess rename to framework/cli/views/webapp/themes/classic/views/.htaccess diff --git a/testdrive/themes/classic/views/layouts/.yii b/framework/cli/views/webapp/themes/classic/views/layouts/.yii similarity index 100% rename from testdrive/themes/classic/views/layouts/.yii rename to framework/cli/views/webapp/themes/classic/views/layouts/.yii diff --git a/testdrive/themes/classic/views/site/.yii b/framework/cli/views/webapp/themes/classic/views/site/.yii similarity index 100% rename from testdrive/themes/classic/views/site/.yii rename to framework/cli/views/webapp/themes/classic/views/site/.yii diff --git a/testdrive/themes/classic/views/system/.yii b/framework/cli/views/webapp/themes/classic/views/system/.yii similarity index 100% rename from testdrive/themes/classic/views/system/.yii rename to framework/cli/views/webapp/themes/classic/views/system/.yii diff --git a/framework/web/CController.php b/framework/web/CController.php index ea739f756..6ca69c426 100644 --- a/framework/web/CController.php +++ b/framework/web/CController.php @@ -70,9 +70,9 @@ class CController extends CBaseController const STATE_INPUT_NAME='YII_PAGE_STATE'; /** - * @var mixed the name of the layout to be applied to this controller's views. + * @var string the name of the layout to be applied to this controller's views. * Defaults to null, meaning the {@link CWebApplication::layout application layout} - * is used. If false, no layout will be applied. + * is used. If it is an empty string, no layout will be applied. */ public $layout; /** @@ -509,7 +509,7 @@ class CController extends CBaseController { $output=$this->renderPartial($view,$data,true); - if(($layout=$this->layout)==null) + if(($layout=$this->layout)===null) $layout=Yii::app()->layout; if(!empty($layout) && ($layoutFile=$this->getLayoutFile($layout))!==false) @@ -533,7 +533,7 @@ class CController extends CBaseController */ public function renderText($text,$return=false) { - if(($layout=$this->layout)==null) + if(($layout=$this->layout)===null) $layout=Yii::app()->layout; if(!empty($layout) && ($layoutFile=$this->getLayoutFile($layout))!==false) diff --git a/framework/web/CSort.php b/framework/web/CSort.php index dede97245..827973c4c 100644 --- a/framework/web/CSort.php +++ b/framework/web/CSort.php @@ -122,9 +122,16 @@ class CSort extends CComponent $order=$this->defaultOrder; else { + $schema=CActiveRecord::model($this->modelClass)->getDbConnection()->getSchema(); $orders=array(); foreach($directions as $attribute=>$descending) + { + if(($pos=strpos($attribute,'.'))!==false) + $attribute=$schema->quoteTableName(substr($attribute,0,$pos)).'.'.$schema->quoteColumnName(substr($attribute,$pos+1)); + else + $attribute=$schema->quoteColumnName($attribute); $orders[]=$descending?$attribute.' DESC':$attribute; + } $order=implode(', ',$orders); } @@ -280,6 +287,6 @@ class CSort extends CComponent */ protected function createLink($attribute,$label,$url,$htmlOptions) { - return CHtml::link(CHtml::encode($label),$url,$htmlOptions); + return CHtml::link($label,$url,$htmlOptions); } } \ No newline at end of file diff --git a/framework/web/helpers/CHtml.php b/framework/web/helpers/CHtml.php index c8aa4840e..86a588be0 100644 --- a/framework/web/helpers/CHtml.php +++ b/framework/web/helpers/CHtml.php @@ -546,7 +546,9 @@ class CHtml * Generates a drop down list. * @param string the input name * @param string the selected value - * @param array data for generating the list options (value=>display) + * @param array data for generating the list options (value=>display). + * You may use {@link listData} to generate this data. + * Please refer to {@link listOptions} on how this data is used to generate the list options. * @param array additional HTML attributes. Besides normal HTML attributes, a few special * attributes are also recognized (see {@link clientChange} for more details.) * @return string the generated drop down list @@ -569,6 +571,8 @@ class CHtml * @param string the input name * @param string the selected value * @param array data for generating the list options (value=>display) + * You may use {@link listData} to generate this data. + * Please refer to {@link listOptions} on how this data is used to generate the list options. * @param array additional HTML attributes. Besides normal HTML attributes, a few special * attributes are also recognized (see {@link clientChange} for more details.) * @return string the generated list box @@ -1024,6 +1028,8 @@ class CHtml * @param CModel the data model * @param string the attribute * @param array data for generating the list options (value=>display) + * You may use {@link listData} to generate this data. + * Please refer to {@link listOptions} on how this data is used to generate the list options. * @param array additional HTML attributes. Besides normal HTML attributes, a few special * attributes are also recognized (see {@link clientChange} for more details.) * @return string the generated drop down list @@ -1054,6 +1060,8 @@ class CHtml * @param CModel the data model * @param string the attribute * @param array data for generating the list options (value=>display) + * You may use {@link listData} to generate this data. + * Please refer to {@link listOptions} on how this data is used to generate the list options. * @param array additional HTML attributes. Besides normal HTML attributes, a few special * attributes are also recognized (see {@link clientChange} for more details.) * @return string the generated list box @@ -1288,10 +1296,21 @@ class CHtml * * @return string the generated list options */ - protected static function listOptions($selection,$listData,&$htmlOptions) + public static function listOptions($selection,$listData,&$htmlOptions) { $content=''; if(isset($htmlOptions['prompt'])) @@ -1305,6 +1324,14 @@ class CHtml unset($htmlOptions['empty']); } + if(isset($htmlOptions['options'])) + { + $options=$htmlOptions['options']; + unset($htmlOptions['options']); + } + else + $options=array(); + foreach($listData as $key=>$value) { if(is_array($value)) @@ -1314,10 +1341,15 @@ class CHtml $content.=self::listOptions($selection,$value,$dummy); $content.=''."\n"; } - else if(!is_array($selection) && !strcmp($key,$selection) || is_array($selection) && in_array($key,$selection)) - $content.='\n"; else - $content.='\n"; + { + $attributes=array('value'=>(string)$key); + if(!is_array($selection) && !strcmp($key,$selection) || is_array($selection) && in_array($key,$selection)) + $attributes['selected']='selected'; + if(isset($options[$key])) + $attributes=array_merge($attributes,$options[$key]); + $content.=CHtml::tag('option',$attributes,self::encode((string)$value))."\n"; + } } return $content; } diff --git a/framework/yiic b/framework/yiic old mode 100644 new mode 100755