<commit_before>Creating and Updating Posts
===========================

With the `Post` model ready, we need to fine-tune the actions and views for the controller `PostController`. In this section, we first customize the access control of CRUD operations; we then modify the code implementing the `create` and `update` operations.


Customizing Access Control
--------------------------

The first thing we want to do is to customize the [access control](http://www.yiiframework.com/doc/guide/topics.auth#access-control-filter) because the code generated by `yiic` does not fit our needs.

We modify the `accessRules()` method in the file `/wwwroot/blog/protected/controllers/PostController.php` as follows,

~~~
[php]
public function accessRules()
{
	return array(
		array('allow',  // allow all users to perform 'list' and 'show' actions
			'actions'=>array('index', 'view'),
			'users'=>array('*'),
		),
		array('allow', // allow authenticated users to perform any action
			'users'=>array('@'),
		),
		array('deny',  // deny all users
			'users'=>array('*'),
		),
	);
}
~~~

The above rules state that all users can access the `index` and `view` actions, and authenticated users can access any actions, including the `admin` action. The user should be denied access in any other scenario. Note that these rules are evaluated in the order they are listed here. The first rule matching the current context makes the access decision. For example, if the current user is the system owner who tries to visit the post creation page, the second rule will match and it will give the access to the user.


Customizing `create` and `update` Operations
--------------------------------------------

The `create` and `update` operations are very similar. They both need to display an HTML form to collect user inputs, validate them, and save them into database. The main difference is that the `update` operation will pre-populate the form with the existing post data found in the database. For this reason, the `yiic` tool generates a partial view `/wwwroot/blog/protected/views/post/_form.php` that is embedded in both the `create` and `update` views to render the needed HTML form.

We first change the `_form.php` file so that the HTML form only collects the inputs we want: `title`, `content`, `tags` and `status`. We use plain text fields to collect inputs for the first three attributes, and a dropdown list to collect input for `status`. The dropdown list options are the text displays of the possible post statuses:

~~~
[php]
<?php echo $form->dropDownList($post,'status',Lookup::items('PostStatus')); ?>
~~~

In the above, we call `Lookup::items('PostStatus')` to bring back the list of post statuses.

We then modify the `Post` class so that it can automatically set some attributes (e.g. `create_time`, `author_id`) before a post is saved to the database. We override the `beforeSave()` method as follows,

~~~
[php]
protected function beforeSave()
{
	if(parent::beforeSave())
	{
		if($this->isNewRecord)
		{
			$this->create_time=$this->update_time=time();
			$this->author_id=Yii::app()->user->id;
		}
		else
			$this->update_time=time();
		return true;
	}
	else
		return false;
}
~~~

When we save a post, we want to update the `tbl_tag` table to reflect the change of tag frequencies. We can do this work in the `afterSave()` method, which is automatically invoked by Yii after a post is successfully saved into the database.

~~~
[php]
protected function afterSave()
{
	parent::afterSave();
	Tag::model()->updateFrequency($this->_oldTags, $this->tags);
}

private $_oldTags;

protected function afterFind()
{
	parent::afterFind();
	$this->_oldTags=$this->tags;
}
~~~

In the implementation, because we want to detect if the user changes the tags in case he is updating an existing post, we need to know what the old tags are. For this reason, we also write the `afterFind()` method to keep the old tags in the variable `_oldTags`. The method `afterFind()` is invoked automatically by Yii when an AR record is populated with the data from database.

We are not going to give details of the `Tag::updateFrequency()` method here. Interested readers may refer to the file `/wwwroot/yii/demos/blog/protected/models/Tag.php`.


<div class="revision">$Id$</div><commit_msg>(Fixes issue 1097)<commit_after>Creating and Updating Posts
===========================

With the `Post` model ready, we need to fine-tune the actions and views for the controller `PostController`. In this section, we first customize the access control of CRUD operations; we then modify the code implementing the `create` and `update` operations.


Customizing Access Control
--------------------------

The first thing we want to do is to customize the [access control](http://www.yiiframework.com/doc/guide/topics.auth#access-control-filter) because the code generated by `yiic` does not fit our needs.

We modify the `accessRules()` method in the file `/wwwroot/blog/protected/controllers/PostController.php` as follows,

~~~
[php]
public function accessRules()
{
	return array(
		array('allow',  // allow all users to perform 'list' and 'show' actions
			'actions'=>array('index', 'view'),
			'users'=>array('*'),
		),
		array('allow', // allow authenticated users to perform any action
			'users'=>array('@'),
		),
		array('deny',  // deny all users
			'users'=>array('*'),
		),
	);
}
~~~

The above rules state that all users can access the `index` and `view` actions, and authenticated users can access any actions, including the `admin` action. The user should be denied access in any other scenario. Note that these rules are evaluated in the order they are listed here. The first rule matching the current context makes the access decision. For example, if the current user is the system owner who tries to visit the post creation page, the second rule will match and it will give the access to the user.


Customizing `create` and `update` Operations
--------------------------------------------

The `create` and `update` operations are very similar. They both need to display an HTML form to collect user inputs, validate them, and save them into database. The main difference is that the `update` operation will pre-populate the form with the existing post data found in the database. For this reason, the `yiic` tool generates a partial view `/wwwroot/blog/protected/views/post/_form.php` that is embedded in both the `create` and `update` views to render the needed HTML form.

We first change the `_form.php` file so that the HTML form only collects the inputs we want: `title`, `content`, `tags` and `status`. We use plain text fields to collect inputs for the first three attributes, and a dropdown list to collect input for `status`. The dropdown list options are the text displays of the possible post statuses:

~~~
[php]
<?php echo $form->dropDownList($model,'status',Lookup::items('PostStatus')); ?>
~~~

In the above, we call `Lookup::items('PostStatus')` to bring back the list of post statuses.

We then modify the `Post` class so that it can automatically set some attributes (e.g. `create_time`, `author_id`) before a post is saved to the database. We override the `beforeSave()` method as follows,

~~~
[php]
protected function beforeSave()
{
	if(parent::beforeSave())
	{
		if($this->isNewRecord)
		{
			$this->create_time=$this->update_time=time();
			$this->author_id=Yii::app()->user->id;
		}
		else
			$this->update_time=time();
		return true;
	}
	else
		return false;
}
~~~

When we save a post, we want to update the `tbl_tag` table to reflect the change of tag frequencies. We can do this work in the `afterSave()` method, which is automatically invoked by Yii after a post is successfully saved into the database.

~~~
[php]
protected function afterSave()
{
	parent::afterSave();
	Tag::model()->updateFrequency($this->_oldTags, $this->tags);
}

private $_oldTags;

protected function afterFind()
{
	parent::afterFind();
	$this->_oldTags=$this->tags;
}
~~~

In the implementation, because we want to detect if the user changes the tags in case he is updating an existing post, we need to know what the old tags are. For this reason, we also write the `afterFind()` method to keep the old tags in the variable `_oldTags`. The method `afterFind()` is invoked automatically by Yii when an AR record is populated with the data from database.

We are not going to give details of the `Tag::updateFrequency()` method here. Interested readers may refer to the file `/wwwroot/yii/demos/blog/protected/models/Tag.php`.


<div class="revision">$Id$</div>
{'fraction_non_alphanumeric': 0.12199111942042533, 'fraction_numerical': 0.00046739892498247256, 'mean_word_length': 4.24770079705702, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7188324', 'n_tokens_mistral': 2382, 'n_tokens_neox': 2253, 'n_words': 1111}