summaryrefslogtreecommitdiff
path: root/demos/blog-tutorial/protected/pages/Day4
diff options
context:
space:
mode:
Diffstat (limited to 'demos/blog-tutorial/protected/pages/Day4')
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/CreateListPost.page4
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/CreateNewPost.page2
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/CreateEditPost.page136
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/CreateListPost.page182
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/CreateNewPost.page144
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/CreateReadPost.page135
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/Overview.page28
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/directories.gifbin11129 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/output.gifbin3406 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/output2.gifbin6326 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/output3.gifbin11874 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/fr/output4.gifbin11916 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/CreateEditPost.page133
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/CreateListPost.page185
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/CreateNewPost.page142
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/CreateReadPost.page135
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/Overview.page26
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/directories.gifbin11129 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/output.gifbin3406 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/output2.gifbin6326 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/output3.gifbin11874 -> 0 bytes
-rwxr-xr-xdemos/blog-tutorial/protected/pages/Day4/id/output4.gifbin11916 -> 0 bytes
22 files changed, 3 insertions, 1249 deletions
diff --git a/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page b/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page
index 1dada650..1c266c83 100755
--- a/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page
+++ b/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page
@@ -28,8 +28,8 @@ We now create the template and class files for the <tt>ListPost</tt> page: <tt>p
Based on the functionality requirement of the <tt>ListPost</tt> page, we will use two controls in the page template:
</p>
<ul>
-<li><a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Repeater">TRepeater</a>: this control is mainly used to display a list of data items. The presentation of the each data item can be specified via an inline template or an external template control (the approach we will use here).</li>
-<li><a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Pager">TPager</a>: this control is used to paginate a list of data items. It interacts with end-users to determine which page of data to be displayed in a <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.List">list control</a> (e.g. <tt>TListBox</tt>) or <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Data">data control</a> (e.g. <tt>TRepeater</tt>).</li>
+<li><a href="http://www.pradoframework.net/site/demos/quickstart/?page=Controls.Repeater">TRepeater</a>: this control is mainly used to display a list of data items. The presentation of the each data item can be specified via an inline template or an external template control (the approach we will use here).</li>
+<li><a href="http://www.pradoframework.net/site/demos/quickstart/?page=Controls.Pager">TPager</a>: this control is used to paginate a list of data items. It interacts with end-users to determine which page of data to be displayed in a <a href="http://www.pradoframework.net/site/demos/quickstart/?page=Controls.List">list control</a> (e.g. <tt>TListBox</tt>) or <a href="http://www.pradoframework.net/site/demos/quickstart/?page=Controls.Data">data control</a> (e.g. <tt>TRepeater</tt>).</li>
</ul>
<p>
diff --git a/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page b/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page
index 7797efaa..fe36b3ff 100755
--- a/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page
+++ b/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page
@@ -51,7 +51,7 @@ We now create two files <tt>protected/pages/posts/NewPost.page</tt> and <tt>prot
<h2>Creating Page Template</h2>
<p>
-The <tt>NewPost</tt> page template contains a <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.TextBox">TTextBox</a> to collect the post title and a <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.HtmlArea">THtmlArea</a> to collect the post content. The latter is a WYSIWYG HTML editor. To ensure the user input is valid, we associate validators with these input controls.
+The <tt>NewPost</tt> page template contains a <a href="http://www.pradoframework.net/site/demos/quickstart/?page=Controls.TextBox">TTextBox</a> to collect the post title and a <a href="http://www.pradoframework.net/site/demos/quickstart/?page=Controls.HtmlArea">THtmlArea</a> to collect the post content. The latter is a WYSIWYG HTML editor. To ensure the user input is valid, we associate validators with these input controls.
</p>
<com:TTextHighlighter CssClass="source" Language="prado">
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/CreateEditPost.page b/demos/blog-tutorial/protected/pages/Day4/fr/CreateEditPost.page
deleted file mode 100755
index 09220322..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/CreateEditPost.page
+++ /dev/null
@@ -1,136 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Création de la page modification d'un message <tt>EditPost</tt></h1>
-
-
-<p>
-La page <tt>EditPost</tt> est fournie aux auteurs et administrateurs pour modifier les messages. Comme la page <a href="?page=Day4.CreateNewPost">NewPost</a>, elle affiche un formulaire permettant de modifier les données d'un message.
-</p>
-
-
-<p>
-Nous créons deux fichiers <tt>protected/pages/posts/EditPost.page</tt> et <tt>protected/pages/posts/EditPost.php</tt> contenant respectivement le gabarit et la classe de notre page.
-</p>
-
-<h2>Création du gabarit</h2>
-<p>
-Le gabarit de la page <tt>EditPost</tt> est très proche de celui de la page <tt>NewPost</tt> template. Seul le titre et le texte du bouton sont différents.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;%@ Title="Mon Blog - Modification Message" %>
-
-&lt;com:TContent ID="Main">
-
-<h1>Modification message</h1>
-
-<span>Titre:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="TitleEdit"
- ErrorMessage="Veuillez indiquer un titre."
- Display="Dynamic" />
-<br/>
-&lt;com:TTextBox ID="TitleEdit" Columns="50" />
-
-<br/>
-<span>Message:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="ContentEdit"
- ErrorMessage="Veuillez indiquer le contenu du message."
- Display="Dynamic" />
-<br/>
-&lt;com:THtmlArea ID="ContentEdit" />
-
-<br/>
-&lt;com:TButton Text="Enregistrer" OnClick="saveButtonClicked" />
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-
-<h2>Création du fichier de classe</h2>
-
-
-<p>
-La classe de <tt>EditPage</tt> est un peu plus complexe que celle de la page <tt>NewPage</tt> parce qu'elle doit lire les informations auparavant. Elle doit aussi vérifier les autorisations. En particulier, elle doit s'assurer que le message ne puisse être modifié que par l'auteur ou par un administrateur. Ces vérifications d'autorisation ne sont pas fournies par PRADO.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class EditPost extends TPage
-{
- /**
- * initialise les contrôles de saisies avec les données du message.
- * cette méthode est appelée lors de l'initialisation de la page
- * @param mixed param : paramètres de l'évènement
- */
- public function onInit($param)
- {
- parent::onInit($param);
- // récupère les données de l'utilisateur. Equivalent à:
- // $postRecord=$this->getPost();
- $postRecord=$this->Post;
- // vérification des droits: seul l'auteur ou un administrateur peuvent modifier le message
- if($postRecord->author_id!==$this->User->Name && !$this->User->IsAdmin)
- throw new THttpException(500,'Vous n êtes pas autoriser à modifier ce message.');
-
- if(!$this->IsPostBack) // est-ce le premier appel à la page
- {
- // rempli les contrôles avec les données du message
- $this->TitleEdit->Text=$postRecord->title;
- $this->ContentEdit->Text=$postRecord->content;
- }
- }
-
- /**
- * Enregistre si toutes les validations sont Ok
- * cette méthode répond à l'évènement OnClick du bouton "Enregistrer".
- * @param mixed sender : celui qui a généré l'évènement
- * @param mixed param : paramètres de l'évènement
- */
- public function saveButtonClicked($sender,$param)
- {
- if($this->IsValid) // toutes les validations sont ok ?
- {
- // récupère les données de l'utilisateur. Equivalent à:
- // $postRecord=$this->getPost();
- $postRecord=$this->Post;
-
- // affecte les données saisies aux champs de la BDD
- $postRecord->title=$this->TitleEdit->SafeText;
- $postRecord->content=$this->ContentEdit->SafeText;
-
- // enregistre les données par la méthode save de l'Active Record
- $postRecord->save();
-
- // redirige le navigateur vers la page ReadPost
- $url=$this->Service->constructUrl('posts.ReadPost',array('id'=>$postRecord->post_id));
- $this->Response->redirect($url);
- }
- }
-
- /**
- * retourne les données du message devant être modifiées.
- * @return PostRecord les données devant être modifiés.
- * @throws THttpException si le message est inexistant.
- */
- protected function getPost()
- {
- // l'ID du message devant être modifié passé par un paramètre GET
- $postID=(int)$this->Request['id'];
- // utilise Active Record pour lire le message correspondant à cet ID
- $postRecord=PostRecord::finder()->findByPk($postID);
- if($postRecord===null)
- throw new THttpException(500,'Message inexistant.');
- return $postRecord;
- }
-}
-</com:TTextHighlighter>
-
-<h2>Test</h2>
-<p>
-Pour tester notre page <tt>EditPost</tt>, authentifiez-vous auparavant et allez à l'URL <tt>http://hostname/blog/index.php?page=EditPost&id=1</tt>. Cette URL peut aussi être atteinte par le bouton <tt>Modifier</tt> de notre page de détail.
-</p>
-
-<img src="<%~ output4.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/CreateListPost.page b/demos/blog-tutorial/protected/pages/Day4/fr/CreateListPost.page
deleted file mode 100755
index ab6ddfc4..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/CreateListPost.page
+++ /dev/null
@@ -1,182 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Création de la page d'affichage des messages <tt>ListPost</tt></h1>
-
-<p>
-La page <tt>ListPost</tt> affiche les derniers messages sous forme de liste. S'il y a trop de messages, ils seront affichés dans différentes pages.
-</p>
-
-<p>
-Avant que nous ne passions à l'implémentation, nous voudrions que notre page d'accueil pointe vers la page à venir <tt>ListPost</tt>, ceci dans le but d'afficher la liste des derniers messages dès qu'un utilisateur se connecte au site. Pour cela, nous allons modifier le fichier de configuration de l'application <tt>protected/application.xml</tt> de cette manière.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="xml">
-......
-<services>
- <service id="page" class="TPageService" DefaultPage="posts.ListPost">
- <pages MasterClass="Application.layouts.MainLayout" />
- </service>
-</services>
-</com:TTextHighlighter>
-
-<p>
-Nous alons maintenant créer le gabarit et le fichier de classe pour notre page <tt>ListPost</tt> : <tt>protected/pages/posts/ListPost.page</tt> et <tt>protected/pages/posts/ListPost.php</tt>.
-</p>
-
-<h2>Création du gabarit</h2>
-<p>
-Pour satisfaire les fonctionnalités de notre page <tt>ListPost</tt>, nous allons utiliser deux contrôles dans notre gabarit.
-</p>
-<ul>
-<li><a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Repeater">TRepeater</a>: ce contrôle permet d'afficher principalement une liste d'éléments. La présentation de chacun ce ces éléments peut être défini soit par un gabarit interne, soit par un gabarit externe (choix que nous avons fait).</li>
-<li><a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Pager">TPager</a>: ce contrôle permet de faire la pagination d'une liste d'éléments. Il interagit avec l'utilisateur pour définir quelle page doit être affiché dans un <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.List">contrôle de liste</a> (ie: <tt>TListBox</tt>) ou dans un <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Data">contrôle de données</a> (ie: <tt>TRepeater</tt>).</li>
-</ul>
-<p>
-Ci-dessous le contenu du gabarit :
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;%@ Title="Mon Blog" %>
-
-&lt;com:TContent ID="Main">
-
-&lt;com:TRepeater ID="Repeater"
- ItemRenderer="Application.pages.posts.PostRenderer"
- AllowPaging="true"
- AllowCustomPaging="true"
- PageSize="5"
- />
-
-&lt;com:TPager ControlToPaginate="Repeater" OnPageIndexChanged="pageChanged" />
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-<p>
-Dans la partie répétée <tt>TRepeater</tt>, nous indiquons que l'affichage du contenu est délégué à l'élément <tt>PostRenderer</tt> que nous allons créer après. Pour permettre à PRADO de trouver cette classe, nous fournissons l'espace de noms complet <tt>Application.pages.posts.PostRenderer</tt>, qui correspond au fichier <tt>protected/pages/posts/PostRenderer.php</tt>.
-</p>
-
-<p>
-Nous définissons aussi quelques propriétés complémentaires du <tt>TRepeater</tt> pour activer la pagination. Et nous définissons la propriété <tt>ControlToPaginate</tt> du <tt>TPager</tt> afin qu'il sache quelle est la zone répetée à paginer.
-</p>
-
-
-<h2>Création du fichier de classe</h2>
-<p>
-En fonction du gabarit précédent, nous pouvons voir que notre fichier de classe doit implémenter un gestionnaire d'évènement pour <tt>pageChanged()</tt> (déclenché par <tt>OnPageIndexChanged</tt> du <tt>TPager</tt>). Nous devons aussi remplir les données qui apparaitront dans le <tt>TRepeater</tt>. Ci-dessous le source complet du fichier de classe :
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class ListPost extends TPage
-{
- /**
- * Initialise le TRepeater.
- * Cette méthode est appelé par le framework lors de l'initialisation de la page
- * @param mixed param : paramètres de l'évènement
- */
- public function onInit($param)
- {
- parent::onInit($param);
- if(!$this->IsPostBack) // la page est chargée pour la première fois ?
- {
- // récupère le nombre total de messages
- $this->Repeater->VirtualItemCount=PostRecord::finder()->count();
- // rempli le TRepeater avec les données
- $this->populateData();
- }
- }
-
- /**
- * Gestionnaire d'évènement pour OnPageIndexChanged du TPager.
- * Cette méthode est appelée lors du changement de page
- */
- public function pageChanged($sender,$param)
- {
- // change l'index de la page courante par le nouvel index
- $this->Repeater->CurrentPageIndex=$param->NewPageIndex;
- // rempli de nouveau le TRepeater
- $this->populateData();
- }
-
- /**
- * détermine quelle page doit être affichée et remplie
- * TRepeater avec les données lues
- */
- protected function populateData()
- {
- $offset=$this->Repeater->CurrentPageIndex*$this->Repeater->PageSize;
- $limit=$this->Repeater->PageSize;
- if($offset+$limit>$this->Repeater->VirtualItemCount)
- $limit=$this->Repeater->VirtualItemCount-$offset;
- $this->Repeater->DataSource=$this->getPosts($offset,$limit);
- $this->Repeater->dataBind();
- }
-
- /**
- * lis les données à partir de la base de données en utilisant les fonctionnalités offset et limit.
- */
- protected function getPosts($offset, $limit)
- {
- // construit les critères de la requête
- $criteria=new TActiveRecordCriteria;
- $criteria->OrdersBy['create_time']='desc';
- $criteria->Limit=$limit;
- $criteria->Offset=$offset;
- // lit les messages en fonction des critères précédents
- return PostRecord::finder()->withAuthor()->findAll($criteria);
- }
-}
-</com:TTextHighlighter>
-
-<h2>Création du <tt>PostRenderer</tt></h2>
-
-<p>
-Nous devons toujours créer la classe <tt>PostRenderer</tt>. Elle définit la manière dont sera affichée chaque ligne de notre <tt>TRepeater</tt>. Nous la créons en tant que gabarit de contrôle, ce qui nous permet d'utiliser notre système de gabarit. Le fichier de gabarit ainsi que notre fichier de classe seront sauvegardés respectivement sous <tt>PostRenderer.tpl</tt> et <tt>PostRenderer.php</tt> dans le dossier <tt>protected/pages/posts</tt>.
-</p>
-<h3>Création du gabarit pour <tt>PostRenderer</tt></h3>
-<p>
-Le gabarit définit la présentation des différentes informations d'un message : titre, nom, heure, contenu. Nous lions le titre à la page <tt>ReadPost</tt> qui affiche le détail du message.
-</p>
-<p>
-L'expression <tt>$this->Data</tt> fait référence aux données provenant du <tt>TRepeater</tt>. Dans notre cas, c'est un objet de type <tt>PostRecord</tt>. Remarquez comment nous accédons au nom de l'auteur du message par <tt>$this->Data->author->username</tt>.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-<div class="post-box">
-<h3>
-&lt;com:THyperLink Text="&lt;%# $this->Data->title %>"
- NavigateUrl="&lt;%# $this->Service->constructUrl('posts.ReadPost',array('id'=>$this->Data->post_id)) %>" />
-</h3>
-
-<p>
-Auteur:
-&lt;com:TLiteral Text="&lt;%# $this->Data->author->username %>" /><br/>
-Heure:
-&lt;com:TLiteral Text="&lt;%# date('m/d/Y h:m:sa', $this->Data->create_time) %>" />
-</p>
-
-<p>
-&lt;com:TLiteral Text="&lt;%# $this->Data->content %>" />
-</p>
-</div>
-</com:TTextHighlighter>
-
-<h3>Création du fichier de classe pour <tt>PostRenderer</tt></h3>
-
-<p>
-Notre classe est très simple, elle hérite de <tt>TRepeaterItemRenderer</tt> et ne contient aucun autre code.
-</p>
-<com:TTextHighlighter CssClass="source" Language="php">
-class PostRenderer extends TRepeaterItemRenderer
-{
-}
-</com:TTextHighlighter>
-
-<h2>Test</h2>
-<p>
-Pour tester la page <tt>ListPost</tt>, naviguons à l'URL <tt>http://hostname/blog/index.php</tt> (rappellez-vous, nous avons défini <tt>ListPost</tt> comme étant notre page d'accueil). Nous devrions obtenir le résultat suivant. vu que nous n'avons qu'un seul message pour le moment, le contrôle de pagination n'apparait pas. Plus tard, quand nous aurons fini la page <tt>NewPost</tt>, nous pourrons ajouter des messages et revenir ici pour tester notre contrôle de pagination.
-</p>
-
-<img src="<%~ output.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/CreateNewPost.page b/demos/blog-tutorial/protected/pages/Day4/fr/CreateNewPost.page
deleted file mode 100755
index 9ddd97b9..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/CreateNewPost.page
+++ /dev/null
@@ -1,144 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Création de la page nouveau message <tt>NewPost</tt></h1>
-
-<p>
-La page <tt>NewPost</tt> permet aux utilisateurs authentifiés de créer des nouveaux messages. Elle doit afficher un formulaire permettant la saisie des informations du message.
-</p>
-
-
-<p>
-Parce que la page <tt>NewPost</tt> ne peut être vue que par les utilisateurs authentifiés, nous ajoutons un fichier de configuration de page <tt>config.xml</tt> dans le dossier <tt>protected/pages/posts</tt>. Ce fichier indique que seuls les utilisateurs authentifiés peuvent voir les pages <tt>NewPost</tt> et <tt>EditPost</tt> qui sera implémentée dans la section suivante. Tous les autres utilisateurs n'ont accès qu'aux pages <tt>ListPost</tt> et <tt>ReadPost</tt>.
-</p>
-
-
-<com:TTextHighlighter CssClass="source" Language="xml">
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <authorization>
- <allow pages="NewPost,EditPost" users="@" />
- <allow pages="ListPost,ReadPost" />
- <deny users="*" />
- </authorization>
-</configuration>
-</com:TTextHighlighter>
-
-<com:TipBox>
- Il est souvent utile de démarrer les règles d'autorisation par un <tt>&lt;deny users="*"&gt;</tt>, puis, de le compléter en donnant pas à pas les accès aux différentes pages à l'aides de règles <tt>allow</tt> supplémentaires
-</com:TipBox>
-<p>
-Vu le nombre grandissant de pages, nous allons modifier le pied de page de notre <tt>gabarit principal</tt> pour qu'il inclus des liens vers : la page d'accueil, la page nouvel utilisateur <a href="?page=Day3.CreateNewUser">NewUser</a> (visible seulement par les administrateurs), et la page à venir : nouveau message <tt>NewPost</tt> (visible seulement par les utilisateurs authentifiés).
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-<div id="footer">
-&lt;com:THyperLink Text="Accueil"
- NavigateUrl="&lt;%= $this->Service->DefaultPageUrl %>" />
-
-&lt;com:THyperLink Text="Nouveau message"
- NavigateUrl="&lt;%= $this->Service->constructUrl('posts.NewPost') %>"
- Visible="&lt;%= !$this->User->IsGuest %>" />
-
-&lt;com:THyperLink Text="Nouvel utilisateur"
- NavigateUrl="&lt;%= $this->Service->constructUrl('users.NewUser') %>"
- Visible="&lt;%= $this->User->IsAdmin %>" />
-...autres liens...
-</div>
-</com:TTextHighlighter>
-
-<p>
-Nous allons maintenant créer deux fichiers <tt>protected/pages/posts/NewPost.page</tt> et <tt>protected/pages/posts/NewPost.php</tt> contenant respectivement le gabarit et la classe de notre page.
-</p>
-
-
-<h2>Création du gabarit</h2>
-<p>
-Le gabarit de <tt>NewPost</tt> contient une référence à un <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.TextBox">TTextBox</a> pour saisir le titre de notre message et à un <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.HtmlArea">THtmlArea</a> pour saisir le contenu. Ce dernier est un éditeur WYSIWYG HTML. Pour contrôler les valeurs saisies, nous associons des validateurs aux contrôles précédents.
-</p>
-
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;%@ Title="Mon Blog - Nouveau Message" %>
-
-&lt;com:TContent ID="Main">
-
-<h1>Création nouveau message</h1>
-
-<span>Titre:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="TitleEdit"
- ErrorMessage="Veuillez indiquer un titre."
- Display="Dynamic" />
-<br/>
-&lt;com:TTextBox ID="TitleEdit" Columns="50" />
-
-<br/>
-<span>Message:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="ContentEdit"
- ErrorMessage="Veuillez indiquer le contenu du message."
- Display="Dynamic" />
-<br/>
-&lt;com:THtmlArea ID="ContentEdit" />
-
-<br/>
-&lt;com:TButton Text="Ajouter" OnClick="createButtonClicked" />
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-
-<h2>Création du fichier de classe</h2>
-<p>
-Dans le gabarit précédent, nous voyons que la fonction principale de notre page est l'appel de la méthode <tt>createButtonClicked()</tt> implémenté par un évènement <tt>OnClick</tt> attaché au bouton <tt>Ajouter</tt>.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class NewPost extends TPage
-{
- /**
- * création d'un nouveau message si toutes les données sont valides.
- * cette méthode est appelée par l'évènement OnClick du bouton "Ajouter".
- * @param mixed sender : celui qui a généré l'évènement
- * @param mixed param : paramètres de l'évènement
- */
- public function createButtonClicked($sender,$param)
- {
- if($this->IsValid) // tous les validateurs sont Ok ?
- {
- // créer un nouvel objet PostRecord avec les données du formulaire
- $postRecord=new PostRecord;
- // utiliser SafeText à la place de Text évite les attaques XSS
- $postRecord->title=$this->TitleEdit->SafeText;
- $postRecord->content=$this->ContentEdit->SafeText;
- $postRecord->author_id=$this->User->Name;
- $postRecord->create_time=time();
- $postRecord->status=0;
-
- // enregistre les données dans la BDD par la méthode save de l'Active Record
- $postRecord->save();
-
- // redirige le navigateur vers le message nouvellement créé
- $url=$this->Service->constructUrl('posts.ReadPost',array('id'=>$postRecord->post_id));
- $this->Response->redirect($url);
- }
- }
-}
-</com:TTextHighlighter>
-
-<h2>Test</h2>
-<p>
-Pour tester notre page <tt>NewPost</tt>, identifiez-vous auparavant et cliquez sur le lien <tt>Nouveau message</tt> dans le pied de page. Le navigateur affiche le résultat suivant avec comme URL <tt>http://hostname/blog/index.php?page=NewPost</tt>.
-</p>
-
-<com:InfoBox>
-Quand vous visitez la page <tt>NewPost</tt> pour la première fois, vous pourrez remarquer qu'elle mettra plusieurs secondes avant de s'afficher. Ceci est dû au fait que PRADO a besoin de décompresser et de publier le code javascript et les images pour l'éditeur WYSIWYG du contrôle <tt>THtmlArea</tt>. Ceci est fait une fois pour toutes.
-</com:InfoBox>
-
-<com:TipBox>
-Pour tester la fonctionnalité de pagination que nous avons mise en place dans la page <a href="?page=Day4.CreateListPost">ListPost</a>, nous pouvons créer cinq messages ou plus et regardez ce qu'il se passe sur la page d'accueil. Le contrôle <tt>TPager</tt> de la page <tt>ListPost</tt> affiche cinq éléments par page.
-</com:TipBox>
-
-<img src="<%~ output3.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/CreateReadPost.page b/demos/blog-tutorial/protected/pages/Day4/fr/CreateReadPost.page
deleted file mode 100755
index 385737d3..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/CreateReadPost.page
+++ /dev/null
@@ -1,135 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Création de la page détail d'un message <tt>ReadPost</tt></h1>
-
-<p>
-La page <tt>ReadPost</tt> affiche le détail d'un message. Pour les utilisateurs autorisés, un lien sera disponible permettant de modifier ou de supprimer le message.
-</p>
-
-<p>
-Nous créons deux fichiers <tt>protected/pages/posts/ReadPost.page</tt> et <tt>protected/pages/posts/ReadPost.php</tt> qui contiendront respectivement notre gabarit et notre classe.
-</p>
-
-<h2>Création du gabarit</h2>
-<p>
-Le gabarit de <tt>ReadPost</tt> est très proche du gabarit de <tt>PostRenderer</tt>, chacun d'eux affiche le détail d'un message. La différence est que la page <tt>ReadPost</tt> doit afficher deux boutons, permettant aux utilisateurs autorisés de modifier ou supprimer le message.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;com:TContent ID="Main">
-
-<h2>
-&lt;com:TLiteral Text="&lt;%= $this->Post->title %>" />
-</h2>
-
-&lt;com:TControl Visible="&lt;%= $this->canEdit() %>">
- <a href="&lt;%= $this->Service->constructUrl('posts.EditPost',array('id'=>$this->Post->post_id))%>">Modifier</a> |
- &lt;com:TLinkButton Text="Supprimer"
- OnClick="deletePost"
- Attributes.onclick="javascript:if(!confirm('Etes vous sûr ?')) return false;" />
-&lt;/com:TControl>
-
-<p>
-Auteur:
-&lt;com:TLiteral Text="&lt;%= $this->Post->author->username %>" /><br/>
-Heure:
-&lt;com:TLiteral Text="&lt;%= date('m/d/Y h:m:sa', $this->Post->create_time) %>" />
-</p>
-
-<p>
-&lt;com:TLiteral Text="&lt;%= $this->Post->content %>" />
-</p>
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-<p>
-Plusieurs expressions PHP sont utilisées dans le gabarit. L'expression <tt>$this->Post</tt> fait référence à la propriété définie dans la classe de <tt>ReadPost</tt>. Elle représente l'objet <tt>PostRecord</tt> correspondant au message actuel.
-</p>
-
-<com:InfoBox>
-Même si nous utilisons régulièrement des expressions dans nos gabarits, nous n'en abusons pas. Une des règles principales pour savoir si l'on doit utiliser une expression est <i>l'expression doit être une propriété ou une simple mise en forme d'une propriété</i>. En suivant cette ligne de conduite, nous nous assurons d'une bonne séparation entre le contenu et la présentation, sans perdre en flexibilité.
-</com:InfoBox>
-
-<p>
-Nous pouvons aussi remarquer dans le gabarit précédent, que, nos deux boutons sont entourés d'un <tt>TControl</tt> dont la propriété 'visible' est déterminée par l'expression <tt>$this->canEdit()</tt>. Pour le bouton <tt>Supprimer</tt>, nous utilisons une boite de dialogue javascript pour confirmer la suppression du message.
-Nous pouvons aussi remarquer dans le gabarit précédent, que, nos deux boutons sont entourés d'un <tt>TControl</tt> dont la propriété 'visible' est déterminée par l'expression <tt>$this->canEdit()</tt>. Pour le bouton <tt>Supprimer</tt>, nous utilisons une boite de dialogue javascript pour confirmer la suppression du message.
-</p>
-
-<com:InfoBox>
-Tous les contrôles PRADO, ont une propriété très utile <tt>Attributes</tt> qui accepte n'importe quelle paire de valeurs (nom-valeur). La plupart des contrôles PRADO répercutent directement ces informations dans la balise HTML. Par exemple, dans le bouton <tt>Supprimer</tt> nous définissons <tt>onclick</tt> qui est directement reporté dans la balise <tt>&lt;a&gt;</tt> sous forme d'un attribut <tt>onclick</tt>.
-</com:InfoBox>
-
-<h2>Création du fichier de classe</h2>
-
-<p>
-Dans le gabarit précédent, nous voyons que notre classe doit implémenter le gestionnaire d'évènement <tt>deletePost()</tt> (attaché à l'évènement <tt>Onclick</tt> de notre bouton <tt>Supprimer</tt>). Nous devons aussi lire les données du message dont l'ID est passé par un paramètre GET.</p>
-
-<com:InfoBox>
-Nous implémentons la fonctionnalité suppression dans le classe <tt>ReadPost</tt> parce qu'il est classique de faire ainsi. Quand l'utilisateur clique sur le bouton <tt>Supprimer</tt>, une boite de dialogue demande confirmation de la suppression. Si l'utilisateur confirme, l'évènement <tt>OnClick</tt> du bouton <tt>Supprimer</tt> est déclenché.
-</com:InfoBox>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class ReadPost extends TPage
-{
- private $_post;
- /**
- * lis les données du message.
- * cette méthode est appelée lors de l'initialisation de la page
- * @param mixed param : paramètres de l'évènement
- */
- public function onInit($param)
- {
- parent::onInit($param);
- // id du message passé par un paramètre GET
- $postID=(int)$this->Request['id'];
- // lis le message ainsi que les données correspondantes à l'auteur
- $this->_post=PostRecord::finder()->withAuthor()->findByPk($postID);
- if($this->_post===null) // si l'id du message est invalide
- throw new THttpException(500, 'Impossible de trouver le message demandé.');
- // défini le titre de la page comme étant celui du message
- $this->Title=$this->_post->title;
- }
-
- /**
- * @return PostRecord retourne l'objet PostRecord correspondant au message
- */
- public function getPost()
- {
- return $this->_post;
- }
-
- /**
- * supprime le message actuellement visualisé
- * cette méthode est appelée par l'évènement OnClick du bouton "Supprimer"
- */
- public function deletePost($sender,$param)
- {
- // seul l'auteur ou un administrateur peuvent supprimer le message
- if(!$this->canEdit())
- throw new THttpException('Nous n'êtes pas autorisé à effectuer cette action.');
- // le supprime de la base de données
- $this->_post->delete();
- // redirige le navigateur vers la page d'accueil
- $this->Response->redirect($this->Service->DefaultPageUrl);
- }
-
- /**
- * @return boolean infiquant si le message peut être modifier ou supprimer par l'utilisateur actuel
- */
- public function canEdit()
- {
- // seul l'auteur ou un administrateur peuvent modifier/supprimer le message
- return $this->User->Name===$this->Post->author_id || $this->User->IsAdmin;
- }
-}
-</com:TTextHighlighter>
-
-<h2>Test</h2>
-<p>
-Pour tester notre page <tt>ReadPost</tt>, allons à l'URL <tt>http://hostname/blog/index.php</tt> et cliquons sur le titre du seul message affiché. Notre navigateur devrait afficher le résultat suivant avec l'URL <tt>http://hostname/blog/index.php?page=ReadPost&id=1</tt>. Notez que si vous n'êtes pas connecté, les deux boutons ne sont pas visibles.
-</p>
-
-<img src="<%~ output2.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/Overview.page b/demos/blog-tutorial/protected/pages/Day4/fr/Overview.page
deleted file mode 100755
index baaf13af..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/Overview.page
+++ /dev/null
@@ -1,28 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Vue d'ensemble de la gestion des messages</h1>
-
-<p>
-Dans cette section, nous allons créer les pages correspondantes à la gestion des messages. En particulier, nous mettrons en place les quatre opérations de base (Création-Lecture-Modification-Suppression) (CRUD:Create-Retrieve-Update-Delete).
-</p>
-
-
-<p>
-Nous allons créer les nouvelles pages dans le dossier <tt>protected/pages/posts</tt> créé à cet effet.
-</p>
-
-
-<ul>
- <li><tt>ListPost</tt> affiche la liste des messages triés par ordre de date décroissante.</li>
- <li><tt>ReadPost</tt> affiche le détail d'un message.</li>
- <li><tt>NewPost</tt> permet aux utilisateurs enregistrés de créer un nouveau message.</li>
- <li><tt>EditPost</tt> permet à l'auteur et aux administrateurs de modifier un message.</li>
-</ul>
-
-<p>
-Après avoir fini cette section, nous devrions obtenir l'arborescence suivante :
-</p>
-
-<img src="<%~ directories.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/directories.gif b/demos/blog-tutorial/protected/pages/Day4/fr/directories.gif
deleted file mode 100755
index 5ba55184..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/directories.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/output.gif b/demos/blog-tutorial/protected/pages/Day4/fr/output.gif
deleted file mode 100755
index 8c1caea8..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/output.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/output2.gif b/demos/blog-tutorial/protected/pages/Day4/fr/output2.gif
deleted file mode 100755
index 7078e6c6..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/output2.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/output3.gif b/demos/blog-tutorial/protected/pages/Day4/fr/output3.gif
deleted file mode 100755
index ff1834a4..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/output3.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/fr/output4.gif b/demos/blog-tutorial/protected/pages/Day4/fr/output4.gif
deleted file mode 100755
index b1208a0d..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/fr/output4.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/CreateEditPost.page b/demos/blog-tutorial/protected/pages/Day4/id/CreateEditPost.page
deleted file mode 100755
index b7ded3b3..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/CreateEditPost.page
+++ /dev/null
@@ -1,133 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Membuat Halaman <tt>EditPost</tt></h1>
-
-<p>
-Halaman <tt>EditPost</tt> disediakan bagi para pembuat dan administrator untuk mengedit tulisan blog yang sudah ada. Seperti halaman <a href="?page=Day4.CreateNewPost">NewPost</a> , ia menampilkan sebuah formulir untuk mengumpulkan perubahan terhadap judul dan konten tulisan.
-</p>
-
-<p>
-Kita membuat dua file <tt>protected/pages/posts/EditPost.page</tt> dan <tt>protected/pages/posts/EditPost.php</tt> masing-masing untuk menyimpan template halaman dan kelas halaman.
-</p>
-
-<h2>Membuat Template Halaman</h2>
-<p>
-Template halaman <tt>EditPost</tt> sangat mirip dengan template <tt>NewPost</tt>. Hanya judul halaman dan tombol yang berbeda.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;%@ Title="My Blog - Edit Post" %>
-
-&lt;com:TContent ID="Main">
-
-<h1>Edit Post</h1>
-
-<span>Title:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="TitleEdit"
- ErrorMessage="Please provide a title."
- Display="Dynamic" />
-<br/>
-&lt;com:TTextBox ID="TitleEdit" Columns="50" />
-
-<br/>
-<span>Content:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="ContentEdit"
- ErrorMessage="Please provide content."
- Display="Dynamic" />
-<br/>
-&lt;com:THtmlArea ID="ContentEdit" />
-
-<br/>
-&lt;com:TButton Text="Save" OnClick="saveButtonClicked" />
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-
-<h2>Membuat Kelas Halaman</h2>
-
-<p>
-Kelas halaman <tt>EditPage</tt> lebih kompleks dibanding <tt>NewPage</tt> karena ia perlu mengambil data tulisan yang ditetapkan terlebih dulu. Ia juga perlu melakukan pemeriksaan otorisasi tambahan. Ada kalanya ia perlu memastikan bahwa tulisan hanya bisa diedit oleh pembuat atau administrator. Pemeriksaan otorisasi sudah disediakan oleh PRADO.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class EditPost extends TPage
-{
- /**
- * Menginisialisasi input dengan data tulisan yang sudah ada.
- * Metode ini dipanggil oleh kerangka kerja saat halaman diinisialisasi.
- * @param parameter event campuran
- */
- public function onInit($param)
- {
- parent::onInit($param);
- // Menambil data pengguna yang sudah ada. Ini sama dengan:
- // $postRecord=$this->getPost();
- $postRecord=$this->Post;
- // Pemeriksaan otorisasi: hanya pembuat atau administrator dapat mengedit tulisan
- if($postRecord->author_id!==$this->User->Name && !$this->User->IsAdmin)
- throw new THttpException(500,'You are not allowed to edit this post.');
-
- if(!$this->IsPostBack) // jika halaman pertama kali diminta
- {
- // Mempopulasikan kontrol input dengan data tulisan yang sudah ada
- $this->TitleEdit->Text=$postRecord->title;
- $this->ContentEdit->Text=$postRecord->content;
- }
- }
-
- /**
- * Menyimpan tulisan jika semua input sudah benar.
- * Metode ini merespon event OnClick pada tombol "Save".
- * @param pengirim event campuran
- * @param parameter event campuran
- */
- public function saveButtonClicked($sender,$param)
- {
- if($this->IsValid) // jika semua validasi sukses
- {
- // Mengambil data pengguna yang sudah ada. Ini sama dengan:
- // $postRecord=$this->getPost();
- $postRecord=$this->Post;
-
- // Mengambil data input
- $postRecord->title=$this->TitleEdit->SafeText;
- $postRecord->content=$this->ContentEdit->SafeText;
-
- // menyimpan ke database via mekanisme Rekaman Aktif
- $postRecord->save();
-
- // mengalihkan browser ke halaman ReadPost
- $url=$this->Service->constructUrl('posts.ReadPost',array('id'=>$postRecord->post_id));
- $this->Response->redirect($url);
- }
- }
-
- /**
- * Mengembalikan data tulisan yang akan diedit.
- * @return PostRecord data tulisan yang akan diedit.
- * @throws THttpException jika data tulisan tidak ada.
- */
- protected function getPost()
- {
- // ID tulisan yang diedit dikirimkan via parameter GET 'id'
- $postID=(int)$this->Request['id'];
- // gunakan Rekaman Aktif untuk mencari ID tulisan tertentu
- $postRecord=PostRecord::finder()->findByPk($postID);
- if($postRecord===null)
- throw new THttpException(500,'Post is not found.');
- return $postRecord;
- }
-}
-</com:TTextHighlighter>
-
-<h2>Pengujian</h2>
-<p>
-Untuk menguji halaman <tt>EditPost</tt>, masuk lebih dulu dan kemudian kunjungi URL berikut: <tt>http://hostname/blog/index.php?page=EditPost&id=1</tt>. URL ini juga bisa dijangkau dengan mengklik link <tt>Edit</tt> pada halaman rician tulisan.
-</p>
-
-<img src="<%~ output4.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/CreateListPost.page b/demos/blog-tutorial/protected/pages/Day4/id/CreateListPost.page
deleted file mode 100755
index d682535e..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/CreateListPost.page
+++ /dev/null
@@ -1,185 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Membuat Halaman <tt>ListPost</tt></h1>
-
-<p>
-Halaman <tt>ListPost</tt> menampilkan tulisan blog terakhir dalam sebuah daftar. Jika di sana terlalu banyak tulisan, maka akan ditampilkan dalam beberapa lembar halaman.
-</p>
-
-<p>
-Sebelum kita berlanjut dengan implementasi, kita ingin mengarahkan homepage kita ke halaman <tt>ListPage</tt> mendatang, karena kita ingin para pengguna melihat tulisan terakhir saat mereka menyentuh website. Untuk melakukannya, kita mengubah konfigurasi aplikasi <tt>protected/application.xml</tt> sebagai berikut,
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="xml">
-......
-<services>
- <service id="page" class="TPageService" DefaultPage="posts.ListPost">
- <pages MasterClass="Application.layouts.MainLayout" />
- </service>
-</services>
-</com:TTextHighlighter>
-
-<p>
-Sekarang kita membuat file template dan kelas untuk halaman <tt>ListPost</tt>: <tt>protected/pages/posts/ListPost.page</tt> dan <tt>protected/pages/posts/ListPost.php</tt>.
-</p>
-
-<h2>Membuat Template Halaman</h2>
-<p>
-Berdasarkan pada kebutuhan fungsionalitas halaman <tt>ListPost</tt>, kita akan menggunakan dua kontrol dalam template halaman:
-</p>
-<ul>
-<li><a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Repeater">TRepeater</a>: kontrol ini dipakai terutama untuk menampilkan daftar atas item data. Penyajian dari setiap item data bisa ditetapkan melalui template inline atau kontrol template eksternal (pendekatan yang akan kita gunakan di sini).</li>
-<li><a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Pager">TPager</a>: kontrol ini dipakai untuk memecah daftar item data. Ia berinteraksi dengan pengguna-akhir untuk menentukan halaman data mana yang ditampilkan dalam <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.List">kontrol daftar</a> (misalnya <tt>TListBox</tt>) pada <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Data">kontrol data</a> (misalnya <tt>TRepeater</tt>).</li>
-</ul>
-
-<p>
-Di bawah ini adalah konten dalam template halaman:
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;%@ Title="My Blog" %>
-
-&lt;com:TContent ID="Main">
-
-&lt;com:TRepeater ID="Repeater"
- ItemRenderer="Application.pages.posts.PostRenderer"
- AllowPaging="true"
- AllowCustomPaging="true"
- PageSize="5"
- />
-
-&lt;com:TPager ControlToPaginate="Repeater" OnPageIndexChanged="pageChanged" />
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-<p>
-Dalam pengulang, kita menetapkan bahwa konten yang diulang ditampilkan menggunakan penyaji item <tt>PostRenderer</tt> yang akan kita buat nantinya. Agar PRADO bisa menemukan kelas ini, kita memberikan namespace <tt>Application.pages.posts.PostRenderer</tt>, berarti file kelasnya adalah <tt>protected/pages/posts/PostRenderer.php</tt>.
-</p>
-
-<p>
-Kita juga menyetel beberapa properti lain pada pengulang untuk menghidupkan lembaran halaman. Dan kita menyetel properti <tt>ControlToPaginate</tt> pada lembaran agar ia mengetahui konten mana yang diulang harus dibuat lembaran.
-</p>
-
-
-<h2>Membuat Kelas Halaman</h2>
-
-<p>
-Dari template halaman di atas, kita melihat bahwa kita perlu menulis kelas halaman yang mengimplementasikan pengendali event: <tt>pageChanged()</tt> (ditempelkan ke event lembaran <tt>OnPageIndexChanged</tt>). Kita juga perlu mempopulasikan data tulisan ke dalam pengulang berdasarkan pada setelan lembaran saat ini. Berikut ini adalah kode sumber lengkap kelas halaman:
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class ListPost extends TPage
-{
- /**
- * Menginisialisasi pengulang.
- * Metode ini dipanggil oleh kerangka kerja saat menginisialisasi halaman
- * @param mixed event parameter
- */
- public function onInit($param)
- {
- parent::onInit($param);
- if(!$this->IsPostBack) // jika halaman diminta pertama kali
- {
- // ambil jumlah total tulisan yang tersedia
- $this->Repeater->VirtualItemCount=PostRecord::finder()->count();
- // populasikan data tulisan ke dalam pengulang
- $this->populateData();
- }
- }
-
- /**
- * Pengendali event untuk event OnPageIndexChanged pada lembaran.
- * Metode ini dipanggil saat pengguna mengklik tombol halaman
- * dan kemudian mengubah halaman tulisan yang ditampilkan.
- */
- public function pageChanged($sender,$param)
- {
- // ubah indeks halaman sekarang ke yang baru
- $this->Repeater->CurrentPageIndex=$param->NewPageIndex;
- // re-populasi data ke dalam pengulang
- $this->populateData();
- }
-
- /**
- * Menentukan halaman tulisan mana yang ditampilkan dan
- * mempopulasi pengulang dengan data yang sudah diambil.
- */
- protected function populateData()
- {
- $offset=$this->Repeater->CurrentPageIndex*$this->Repeater->PageSize;
- $limit=$this->Repeater->PageSize;
- if($offset+$limit>$this->Repeater->VirtualItemCount)
- $limit=$this->Repeater->VirtualItemCount-$offset;
- $this->Repeater->DataSource=$this->getPosts($offset,$limit);
- $this->Repeater->dataBind();
- }
-
- /**
- * Mengambil tulisan dari database dengan ofset dan limit.
- */
- protected function getPosts($offset, $limit)
- {
- // Bentuk kriteria query
- $criteria=new TActiveRecordCriteria;
- $criteria->OrdersBy['create_time']='desc';
- $criteria->Limit=$limit;
- $criteria->Offset=$offset;
- // query untuk tulisan dengan kriteria di atas dan informasi pembuat
- return PostRecord::finder()->withAuthor()->findAll($criteria);
- }
-}
-</com:TTextHighlighter>
-
-<h2>Membuat <tt>PostRenderer</tt></h2>
-
-<p>
-Kita masih perlu untuk membuat kelas penyaji item <tt>PostRenderer</tt>. Ia mendefinisikan bagaimana setiap tulisan harus ditampilkan dalam pengulang. Kita membuatnya sebagai kontrol template yang membolehkan kita untuk menetapkan penyajian tulisan menggunakan sintaks template fleksibel kita. Template dan file kelas masing-masing disimpan sebagai <tt>PostRenderer.tpl</tt> dan <tt>PostRenderer.php</tt> di bawah direktori <tt>protected/pages/posts</tt>.
-</p>
-
-<h3>Membuat Template Penyaji</h3>
-<p>
-Template penyaji menetapkan penyajian berbagai field dalam sebuah tulisan, termasuk judul, nama pembuat, waktu penulisan dan kontennya. Kita me-link judul tulisan ke <tt>ReadPost</tt> yang menampilkan lebih rinci atas tulisan yang dipilih.
-</p>
-<p>
-Ekspresi <tt>$this->Data</tt> merujuk ke item data yang dikirimkan ke pengulang. Dalam kasus kita, ia adalah obyek <tt>PostRecord</tt>. Perhatikan bagaimana kita mengambil nama pembuat pada tulisan dengan <tt>$this->Data->author->username</tt>.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-<div class="post-box">
-<h3>
-&lt;com:THyperLink Text="&lt;%# $this->Data->title %>"
- NavigateUrl="&lt;%# $this->Service->constructUrl('posts.ReadPost',array('id'=>$this->Data->post_id)) %>" />
-</h3>
-
-<p>
-Author:
-&lt;com:TLiteral Text="&lt;%# $this->Data->author->username %>" /><br/>
-Time:
-&lt;com:TLiteral Text="&lt;%# date('m/d/Y h:m:sa', $this->Data->create_time) %>" />
-</p>
-
-<p>
-&lt;com:TLiteral Text="&lt;%# $this->Data->content %>" />
-</p>
-</div>
-</com:TTextHighlighter>
-
-<h3>Membuat Kelas Penyaji</h3>
-<p>
-Kelas penyaji sangat sederhana. Ia diperluas dari <tt>TRepeaterItemRenderer</tt> dan tidak berisi kode apapun.
-</p>
-<com:TTextHighlighter CssClass="source" Language="php">
-class PostRenderer extends TRepeaterItemRenderer
-{
-}
-</com:TTextHighlighter>
-
-<h2>Pengujian</h2>
-<p>
-Untuk menguji halaman <tt>ListPost</tt>, kunjungi URL <tt>http://hostname/blog/index.php</tt> (ingat kita telah menyetel <tt>ListPost</tt> sebagai homepage baru kita). Kita akan melihat hasil seperti berikut. Karena kita hanya mempunyai satu tulisan saat ini, lembaran tidak akan muncul. Nantinya ketika menyelesaikan <tt>NewPost</tt>, kita dapat menambah tulisan lebih banyak dan datang kembali untuk menguji lembaran halaman lagi.
-</p>
-
-<img src="<%~ output.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/CreateNewPost.page b/demos/blog-tutorial/protected/pages/Day4/id/CreateNewPost.page
deleted file mode 100755
index 31aba2bb..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/CreateNewPost.page
+++ /dev/null
@@ -1,142 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Membuat Halaman <tt>NewPost</tt></h1>
-
-<p>
-Halaman <tt>NewPost</tt> disediakan untuk mengotentikasi pengguna untuk pembuatan tulisan blog baru. Ia perlu untuk menampilkan formulir yang mengumpulkan informasi mengenai tulisan baru, termasuk judul tulisan dan konten badan tulisan.
-</p>
-
-<p>
-Karena <tt>NewPost</tt> hanya bisa diakses oleh pengguna terotentikasi, kita menambahkan file konfigurasi <tt>config.xml</tt> di bawah direktori <tt>protected/pages/posts</tt>. Konfigurasi menetapkan bahwa para pengguna tidak bisa mengakses <tt>NewPost</tt> dan <tt>EditPost</tt> yang akan diperkenalkan dalam bagian berikutnya. Semua pengguna lainnya hanya memiliki akses ke <tt>ListPost</tt> dan <tt>ReadPost</tt>
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="xml">
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <authorization>
- <deny pages="NewPost,EditPost" users="?" />
- <allow pages="ListPost,ReadPost" />
- <deny users="*" />
- </authorization>
-</configuration>
-</com:TTextHighlighter>
-
-<com:TipBox>
-Selalu menjadi ide yang baik untuk memulai dengan <tt>deny="*"</tt> yang menampung semua aturan dari bawah dan secara bertahap memberikan akses ke halaman dengan aturan tambahan.
-</com:TipBox>
-
-<p>
-Karena jumlah halaman kita berkembang, kita ingin memodifikasi <tt>MainLayout</tt> agar dalam footer pada halaman blog kita ada link ke berbagai halaman, termasuk homepage, halaman <a href="?page=Day3.CreateNewUser">NewUser</a> (hanya terlihat oleh administrator), dan halaman <tt>NewPost</tt> mendatang (hanya terlihat oleh pengguna terotentikasi).
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-<div id="footer">
-&lt;com:THyperLink Text="Home"
- NavigateUrl="&lt;%= $this->Service->DefaultPageUrl %>" />
-
-&lt;com:THyperLink Text="New Post"
- NavigateUrl="&lt;%= $this->Service->constructUrl('posts.NewPost') %>"
- Visible="&lt;%= !$this->User->IsGuest %>" />
-
-&lt;com:THyperLink Text="New User"
- NavigateUrl="&lt;%= $this->Service->constructUrl('users.NewUser') %>"
- Visible="&lt;%= $this->User->IsAdmin %>" />
-...other links...
-</div>
-</com:TTextHighlighter>
-
-<p>
-Sekarang kita membuat dua file <tt>protected/pages/posts/NewPost.page</tt> dan <tt>protected/pages/posts/NewPost.php</tt> masing-masing untuk menyimpan template halaman dan kelas halaman.
-</p>
-
-<h2>Membuat Template Halaman</h2>
-<p>
-Template halaman <tt>NewPost</tt> berisi <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.TextBox">TTextBox</a> untuk mengumpulkan judul tulisan dan <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.HtmlArea">THtmlArea</a> untuk mengumpulkan konten tulisan. Yang terakhir adalah editor HTML WYSIWYG. Guna memastikan bahwa input pengguna sudah benar, kita mengaitkan validator dengan kontrol input ini.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;%@ Title="My Blog - New Post" %>
-
-&lt;com:TContent ID="Main">
-
-<h1>Membuat Tulisan Baru</h1>
-
-<span>Title:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="TitleEdit"
- ErrorMessage="Please provide a title."
- Display="Dynamic" />
-<br/>
-&lt;com:TTextBox ID="TitleEdit" Columns="50" />
-
-<br/>
-<span>Content:</span>
-&lt;com:TRequiredFieldValidator
- ControlToValidate="ContentEdit"
- ErrorMessage="Please provide content."
- Display="Dynamic" />
-<br/>
-&lt;com:THtmlArea ID="ContentEdit" />
-
-<br/>
-&lt;com:TButton Text="Create" OnClick="createButtonClicked" />
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-
-<h2>Membuat Kelas Halaman</h2>
-
-<p>
-Dari template halaman di atas, kita melihat bahwa sebagian besar kita perlu menulis sebuah kelas halaman yang mengimplementasikan pengendali event: <tt>createButtonClicked()</tt> (ditempelkan ke tombo <tt>Create</tt> dalam event <tt>OnClick</tt>).
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class NewPost extends TPage
-{
- /**
- * Membuat tulisan baru jika semua input benar.
- * Metode ini merespon event OnClick pada tombol "create".
- * @param mixed event sender
- * @param mixed event parameter
- */
- public function createButtonClicked($sender,$param)
- {
- if($this->IsValid) // bila semua validasi sukses
- {
- // populasikan obyek PostRecord dengan input pengguna
- $postRecord=new PostRecord;
- // menggunakan SafeText datipada Text guna menghindari serangan Penaskahan Situs Silang
- $postRecord->title=$this->TitleEdit->SafeText;
- $postRecord->content=$this->ContentEdit->SafeText;
- $postRecord->author_id=$this->User->Name;
- $postRecord->create_time=time();
- $postRecord->status=0;
-
- // simpan ke database lewat mekanisme Rekaman Aktif
- $postRecord->save();
-
- // alihkan browser ke halaman tulisan yang baru dibuat
- $url=$this->Service->constructUrl('posts.ReadPost',array('id'=>$postRecord->post_id));
- $this->Response->redirect($url);
- }
- }
-}
-</com:TTextHighlighter>
-
-<h2>Pengujian</h2>
-<p>
-Untuk menguji halaman <tt>NewPost</tt>, masuk lebih dulu dan klik pada link tombol <tt>New Post</tt> dalam footer pada homepage. Browser kita akan menampilkan hasil berikut dengan URL <tt>http://hostname/blog/index.php?page=NewPost</tt>.
-</p>
-
-<com:InfoBox>
-Ketika Anda mengunjungi halaman <tt>NewPost</tt> untuk pertama kali, Anda bisa melihat bahwa diperlukan beberapa detik sebelum halaman ditampilkan. Ini dikarenakan PRADO perlu mengurai dan mempublikasikan kode javascript dan gambar untuk kontrol <tt>THtmlArea</tt> yang dipakai dalam halaman. Ini dikerjakan sekali dan untuk semuanya.
-</com:InfoBox>
-
-<com:TipBox>
-Untuk menguji fitur lembaran yang kita kembangkan untuk halaman <a href="?page=Day4.CreateListPost">ListPost</a>, kita dapat membuat lima atau lebih tulisan dan melihat apa yang terjadi pada homepage. Lembar dalam <tt>ListPost</tt> menampilkan lima tulisan setiap halamannya.
-</com:TipBox>
-
-<img src="<%~ output3.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/CreateReadPost.page b/demos/blog-tutorial/protected/pages/Day4/id/CreateReadPost.page
deleted file mode 100755
index 9aeaed7b..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/CreateReadPost.page
+++ /dev/null
@@ -1,135 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Membuat Halaman <tt>ReadPost</tt></h1>
-
-<p>
-Halaman <tt>ReadPost</tt> menampilkan rincian konten tulisan blog. Untuk para pengguna yang diotorisasi, akan ditampilkan tombol link yang membolehkan mereka untuk mengedit atau menghapus tulisan.
-</p>
-
-<p>
-Kita membuat dua file <tt>protected/pages/posts/ReadPost.page</tt> dan <tt>protected/pages/posts/ReadPost.php</tt> masing-masing untuk menyimpan template halaman dan kelas halaman.
-</p>
-
-<h2>Membuat Template Halaman</h2>
-<p>
-Template halaman <tt>ReadPost</tt> sangat mirip dengan template <tt>PostRenderer</tt>, keduanya menyajikan konten tulisan. Perbedaannya adalah bahwa <tt>ReadPost</tt> perlu menampilkan dua tombol link ketika pengguna saat ini diotorisasi untuk mengedit atau menghapus tulisan.
-</p>
-
-<com:TTextHighlighter CssClass="source" Language="prado">
-&lt;com:TContent ID="Main">
-
-<h2>
-&lt;com:TLiteral Text="&lt;%= $this->Post->title %>" />
-</h2>
-
-&lt;com:TControl Visible="&lt;%= $this->canEdit() %>">
- <a href="&lt;%= $this->Service->constructUrl('posts.EditPost',array('id'=>$this->Post->post_id))%>">Edit</a> |
- &lt;com:TLinkButton Text="Delete"
- OnClick="deletePost"
- Attributes.onclick="javascript:if(!confirm('Are you sure?')) return false;" />
-&lt;/com:TControl>
-
-<p>
-Author:
-&lt;com:TLiteral Text="&lt;%= $this->Post->author->username %>" /><br/>
-Time:
-&lt;com:TLiteral Text="&lt;%= date('m/d/Y h:m:sa', $this->Post->create_time) %>" />
-</p>
-
-<p>
-&lt;com:TLiteral Text="&lt;%= $this->Post->content %>" />
-</p>
-
-&lt;/com:TContent>
-</com:TTextHighlighter>
-
-<p>
-Banyak ekspresi PHP dipakai dalam template di atas. Ekspresi <tt>$this->Post</tt> merujuk ke properti yang didefinisikan dalam kelas halaman <tt>ReadPost</tt>. Ia mewakili obyek <tt>PostRecord</tt> yang terkait dengan tulisan yang saat ini sedang dilihat.
-</p>
-
-<com:InfoBox>
-Meskipun sebagian besar kita menggunakan ekspresi dalam template, we do not overuse them. A major guideline in determining whether we should use an expression in a template is that <i>the expression should be a property or a simple presentational transformation of the property</i>. By following this guideline, we ensure content and presentation are well separated without losing sufficient flexibility.
-</com:InfoBox>
-
-<p>
-Kita juga mencatatan dalam template di atas bahwa dua link tombol dikurung di dalam <tt>TControl</tt> yang penampakannya ditentukan oleh ekspresi <tt>$this->canEdit()</tt>. Untuk link tombol <tt>Delete</tt>, kita menggunakan dialog konfirmasi javascript untuk memperoleh konfirmasi pengguna saat ia mengklik untuk menghapus tulisan.
-</p>
-
-<com:InfoBox>
-Seluruh kontrol PRADO mempunyai properti yang sangat berguna bernama <tt>Attributes</tt> yang dapat menerima pasangan nama-nilai bebas. Kebanyakan kontrol PRADO akan menyajikan pasangan nama-nilai dalam <tt>Attributes</tt> secara literal terkait tag HTML. Sebagai contoh, daam link tombol <tt>Delete</tt> di atas, kita mendefinisikan sebuah <tt>onclick</tt> yang disajikan sebagai atribut <tt>onclick</tt> yang menghasilkan tag <tt>&lt;a&gt;</tt>.
-</com:InfoBox>
-
-
-<h2>Membuat Kelas Halaman</h2>
-
-<p>
-Dari template halaman di atas, kita melihat bahwa kita perlu menulis kelas halaman yang mengimplementasikan pengendali event: <tt>deletePost()</tt> (ditempelkan ke tombol <tt>Delete</tt> dalam event <tt>OnClick</tt>). Kita juga perlu untuk mengambil data tulisan yang ditetapkan oleh ID tulisan melalui parameter GET <tt>id</tt>. </p>
-
-<com:InfoBox>
-Kita mengimplementasikan fitur penghapusan tulisan dalam halaman <tt>ReadPost</tt> karena ini sangat alami untuk melakukannya di sini. Ketika pengguna mengklik pada tombol <tt>Delete</tt>, dialog konfirmasi javascript akan muncul. Jika pengguna mengkonfirmasinya, penghapusan akan dibawa dalam respon terhadap event <tt>OnClick</tt> dari tombol <tt>Delete</tt>.
-</com:InfoBox>
-
-<com:TTextHighlighter CssClass="source" Language="php">
-class ReadPost extends TPage
-{
- private $_post;
- /**
- * Mengambil data tulisan.
- * Metode ini dipanggil oleh kerangka kerja saat inisialisasi halaman
- * @param mixed event parameter
- */
- public function onInit($param)
- {
- parent::onInit($param);
- // id tulisan dikirimkan via parameter GET 'id'
- $postID=(int)$this->Request['id'];
- // mengambil PostRecord dengan informasi pembuat terisi dalam
- $this->_post=PostRecord::finder()->withAuthor()->findByPk($postID);
- if($this->_post===null) // jika id tulisan tidak benar
- throw new THttpException(500,'Unable to find the specified post.');
- // setel judul halaman sebagai judul tulisan
- $this->Title=$this->_post->title;
- }
-
- /**
- * @return PostRecord yang saat ini sedang dilihat
- */
- public function getPost()
- {
- return $this->_post;
- }
-
- /**
- * Menghapus tulisan yang saat ini sedang dilihat
- * Metode ini dipanggil saat pengguna mengklik tombol "Delete"
- */
- public function deletePost($sender,$param)
- {
- // hanya pembuat atau administrator bisa menghapus tulisan
- if(!$this->canEdit())
- throw new THttpException('You are not allowed to perform this action.');
- // hapus dari DB
- $this->_post->delete();
- // alihkan browser ke homepage
- $this->Response->redirect($this->Service->DefaultPageUrl);
- }
-
- /**
- * @return boolean apakah pengguna saat ini bisa mengedit/menghapus tulisan yg sedang dilihat
- */
- public function canEdit()
- {
- // hanya pembuat atau administrator bisa mengedi/menghapus tulisan
- return $this->User->Name===$this->Post->author_id || $this->User->IsAdmin;
- }
-}
-</com:TTextHighlighter>
-
-<h2>Pengujian</h2>
-<p>
-Untuk menguji halaman <tt>ReadPost</tt>, kunjungi URL <tt>http://hostname/blog/index.php</tt> dan klik pada judul tulisan. Browser kita akan menampilkan hasil berikut dengan URL <tt>http://hostname/blog/index.php?page=ReadPost&id=1</tt>. Catatan, jika kita tidak masuk, dua tombol link tidak akan terlihat.
-</p>
-
-<img src="<%~ output2.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/Overview.page b/demos/blog-tutorial/protected/pages/Day4/id/Overview.page
deleted file mode 100755
index 3427e11f..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/Overview.page
+++ /dev/null
@@ -1,26 +0,0 @@
-<com:TContent ID="Main">
-
-<h1>Tinjauan Manajemen Tulisan</h1>
-
-<p>
-Pada bagian ini, kita membuat halaman yang terkait dengan manajemen tulisan. Dalam keadaan tertentu, kita mengimplementasikan operasi CRUD (Create-Retrieve-Update-Delete) dengan memperhatikan tulisan blog.
-</p>
-
-<p>
-Berdasarkan pada kebutuhan, kita perlu membuat halaman berikut yang diatur di bawah direktori baru <tt>protected/pages/posts</tt>.
-</p>
-
-<ul>
- <li><tt>ListPost</tt> menampilkan tulisan dengan waktu pembuatan dalam urutan mengecil.</li>
- <li><tt>ReadPost</tt> menampilkan rincian tulisan.</li>
- <li><tt>NewPost</tt> membolehkan pengguna teregistrasi untuk membuat tulisan baru.</li>
- <li><tt>EditPost</tt> membolehkan pembuat atau administrator untuk mengedit tulisan yang sudah ada.</li>
-</ul>
-
-<p>
-Setelah menyelesaikan bagian ini, kita akan mengharapkan untuk melihat direktori dan file berikut:
-</p>
-
-<img src="<%~ directories.gif %>" class="output" />
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/directories.gif b/demos/blog-tutorial/protected/pages/Day4/id/directories.gif
deleted file mode 100755
index 5ba55184..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/directories.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/output.gif b/demos/blog-tutorial/protected/pages/Day4/id/output.gif
deleted file mode 100755
index 8c1caea8..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/output.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/output2.gif b/demos/blog-tutorial/protected/pages/Day4/id/output2.gif
deleted file mode 100755
index 7078e6c6..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/output2.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/output3.gif b/demos/blog-tutorial/protected/pages/Day4/id/output3.gif
deleted file mode 100755
index ff1834a4..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/output3.gif
+++ /dev/null
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day4/id/output4.gif b/demos/blog-tutorial/protected/pages/Day4/id/output4.gif
deleted file mode 100755
index b1208a0d..00000000
--- a/demos/blog-tutorial/protected/pages/Day4/id/output4.gif
+++ /dev/null
Binary files differ