Administrowanie wiadomościami
==============
Administrowanie wiadomościami przede wszystkim odnosi się do wyświetlenia w liście wiadomości w widoku administratora co pozwala nam widzieć wiadomości o wszystkich statusach, aktualizować je oraz usuwać. Są one wykonywane odpowiednio przez operację `admin` oraz operację usuwania `delete`. Kod wygenerowany przez narzędzie `yiic` nie wymaga zbytniej modyfikacji. Poniżej wyjaśniamy przede wszystkim jak te dwie operacje zostały zaimplementowane.
Wyświetlenie listy wiadomości w widoku tabelarycznym
-----------------------------
Operacja `admin` wyświetla wszystkie wiadomości o wszystkich statusach w widoku tabelarycznym. Widok wspiera sortowanie oraz stronicowanie. Poniżej znajduje się metoda `actionAdmin()` kontrolera `PostController`:
~~~
[php]
public function actionAdmin()
{
$model=new Post('search');
if(isset($_GET['Post']))
$model->attributes=$_GET['Post'];
$this->render('admin',array(
'model'=>$model,
));
}
~~~
Powyższy kod został wygenerowany przez narzędzie `yiic` i nie został zmodyfikowany. Najpierw tworzy on model wiadomości `Post` dla [scenariusza](/doc/guide/form.model) wyszukiwania `search`. Będziemy używać tego modelu do gromadzenia warunków wyszukiwania, które specyfikuje użytkownik. Jeżeli istnieją dane dostarczone przez użytkownika, przypisujemy je do modelu. Na koniec generujemy widok `admin` wraz z modelem.
Poniżej znajduje się kod widoku `admin`:
~~~
[php]
breadcrumbs=array(
'Manage Posts',
);
?>
Manage Posts
widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'title',
'type'=>'raw',
'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
),
array(
'name'=>'status',
'value'=>'Lookup::item("PostStatus",$data->status)',
'filter'=>Lookup::items('PostStatus'),
),
array(
'name'=>'create_time',
'type'=>'datetime',
'filter'=>false,
),
array(
'class'=>'CButtonColumn',
),
),
)); ?>
~~~
Do wyświetlania wiadomości używamy klasy [CGridView]. Umożliwia ona nam sortowanie kolumn oraz wiadomości jeśli jest ich zbyt wiele by wyświetlić je na pojedynczej stronie. Nasza zmiana dotyczy sposobu wyświetlania każdej kolumny. Na przykład dla kolumny tytułu `title`, określamy iż powinna ona być wyświetlona jako hiperlink, który wskazuje na widok szczegółów wiadomości. Wyrażenie `$data->url` zwraca wartość właściwości `url`, którą zefiniowaliśmy w klasie wiadomości `Post`.
> Tip|Wskazówka: Podczas wyświetlania tekstu wołamy metodę [CHtml::encode()] do zakodowania znajdujących się w nim wpisów HTML. Chroni to przed [atakami XSS](http://www.yiiframework.com/doc/guide/topics.security).
Usuwanie wiadomości
--------------
W każdym wierszu siatki danych administratora `admin` znajduje się przycisk usuwania. Kliknięcie w ten przycisk powinno usunąć odpowiednią wiadomość. W aplikacji wywołuje to wywołanie akcji `delete` zaimplementowanej w następujący sposób:
~~~
[php]
public function actionDelete()
{
if(Yii::app()->request->isPostRequest)
{
// we only allow deletion via POST request
$this->loadModel()->delete();
if(!isset($_GET['ajax']))
$this->redirect(array('index'));
}
else
throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
}
~~~
Powyższy kod został wygenerowany przez narzędzie `yiic` i nie został zmieniony. Będziemy chcieli wyjaśnić nieco więcej na temat sprawdzania `$_POST['ajax']`. Widżet [CGridView] posiada bardzo fajną funkcję, która domyślnie wykonuje operacje sortowania, stronicowania, usuwania przy użyciu trybu AJAX. Oznacza to, że cała strona nie jest przeładowywana jeśli jakakolwiek z ww. operacji jest wykonywana. Jednakże, istnieje również możliwość uruchamiania widżetu bez trybu AJAX (poprzez ustawienie właściwości `ajaxUpdate` na false albo poprzez wyłączenie obsługi JavaScript po stronie klienta). Dla akcji `delete` zachodzi konieczność rozróżnienia tych dwóch scenariuszy: jeśli żądanie usuwania pochodzi z AJAX-a nie powinniśmy przekierowywać przeglądarki użytkownika, w przeciwnym przypadku powinniśmy.
Usuwanie wiadomości powinno również spowodować usuwanie jej wszystkich komentarzy. Dodatkowo powinniśmy również zaktualizować tabelę `tbl_tag` uwzględniając tagi z usuniętej wiadomości. Oba powyższe zadania powinny zostać osiągnięte poprzez napisanie metody `afterDelete` w klasie modelu wiadomości `Post` w następujący sposób:
~~~
[php]
protected function afterDelete()
{
parent::afterDelete();
Comment::model()->deleteAll('post_id='.$this->id);
Tag::model()->updateFrequency($this->tags, '');
}
~~~
Powyższy kod jest bardzo prosty. Najpierw usuwane są wszystkie komentarze, których `post_id` jest takie same jak ID usuniętej wiadomości. Następnie aktualizowana jest tabela `tbl_tag` dla wartości tagów `tags` z usuniętej wiadomości.
> Tip|Wskazówka: Musimy jawnie usunąć wszystkie komentarze dla usuniętej wiadomości, ponieważ SQLite nie wspiera ograniczeń klucza obcego. W silnikach bazy danych, które wpierają ograniczanie (takich jak MySQL, PostgreSQL), ograniczenie klucza obcego może zostać tak zdefiniowane, że silnik bazy danych automatycznie usunie powiązane komentarze w momencie usuwania wiadomości. W takim przypadku nie będziemy potrzebowali w naszym kodzie jawnego usuwania.
$Id: post.admin.txt 3557 2012-02-09 15:26:05Z alexander.makarow $