Skip to content

Commit

Permalink
Merge remote branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mdomba committed Feb 17, 2012
2 parents e94df34 + bc40cef commit 2100f0d
Show file tree
Hide file tree
Showing 75 changed files with 1,396 additions and 60 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

Version 1.1.11 work in progress
-------------------------------

- Enh #171: Added support for PUT and DELETE request tunneled through POST via parameter named _method in POST body (musterknabe)
- Enh #266: Add support for HTML5 url, email, number, range and date fields to CHtml (gregmolnar)
- Enh: Added getIsFlashRequest(), proper handling of Flash/Flex request when using CWebLogRoute with FireBug. (resurtm)

Version 1.1.10 February 12, 2012
--------------------------------
Expand Down
1 change: 1 addition & 0 deletions demos/blog/assets/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
1 change: 1 addition & 0 deletions demos/blog/protected/runtime/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
34 changes: 34 additions & 0 deletions docs/blog/es/final.logging.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Registro de Errores
===================

Una aplicación Web en producción por lo general necesita un mecanismo de registro de errores sofisticado para varios eventos. En nuestra aplicación, quisiéramos registrar los errores que suceden cuando está siendo usada. Estos errores pueden ser errores de programación o mal uso del sistema por parte de los usuarios. Registrar estos errores va a ayudar a mejorar la Aplicación de Blog.
Podemos habilitar el registro de errores modificando la [configuración de la aplicación](http://www.yiiframework.com/doc/guide/es/basics.application#application-configuration) como sigue,

~~~
[php]
return array(
'preload'=>array('log'),

......

'components'=>array(
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'error, warning',
),
),
),
......
),
);
~~~

Con esta configuración, si sucede un error o notificación, información detallada va a ser registrada y salvada en un archivo ubicado en el directorio `/wwwroot/blog/protected/runtime`.

El componente `log` ofrece otras funciones avanzadas, como enviar mensajes de error a una lista de direcciones de correo electrónico, mostrando los mensajes registrados en una ventana de consola JavaScript, etc. Para más detalles, por favor consulta [La Guía](http://www.yiiframework.com/doc/guide/es/topics.logging).


<div class="revision">$Id$</div>
43 changes: 43 additions & 0 deletions docs/blog/es/final.url.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Optimización de URLs
====================

Las URLs apuntando a varias páginas de nuestra Aplicación de Blog actualmente se ven feas. Por ejemplo, la URL para mostrar la página de un post se ve como:

~~~
/index.php?r=post/show&id=1&title=A+Test+Post
~~~

En esta sección, describimos cómo optimizar estas URLs y hacerlas SEO amigables. Nuestro objetivo es ser capaces de usar las siguientes URLs en la aplicación:

1. `/index.php/posts/yii`: lleva a la pagina mostrando una lista de posts con la etiqueta `yii`;
2. `/index.php/post/2/A+Test+Post`: lleva a la página que muestra el detalle del post con ID 2 cuyo título es `A Test Post`;
3. `/index.php/post/update?id=1`: lleva a la página que permite actualizar el post con ID 1.

Nota que en el formato de la segunda URL, incluimos el título de post en la URL. Esto es principalmente para hacer las URL SEO amigables. Se dice que los motores de búsqueda respetan las palabras encontradas en la URL cuando son indexadas.

Para cumplir nuestro objetivo, modificamos la [configuración de la aplicación](http://www.yiiframework.com/doc/guide/es/basics.application#application-configuration) como sigue:

~~~
[php]
return array(
......
'components'=>array(
......
'urlManager'=>array(
'urlFormat'=>'path',
'rules'=>array(
'post/<id:\d+>/<title:.*?>'=>'post/view',
'posts/<tag:.*?>'=>'post/index',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),
),
),
);
~~~

En lo anterior, configuramos el componente de [urlManager](http://www.yiiframework.com/doc/guide/es/topics.url) configurando su propiedad `urlFormat` que sea `path` y agregando una serie de `rules` (reglas).

Las reglas son usadas por `urlManager` para clasificar y crear las URLs en el formato deseado. Por ejemplo, la segunda regla dice que si una URL `/index.php/posts/yii` es pedida, el componente `urlManager` debería ser responsable de despachar el pedido a la [ruta](http://www.yiiframework.com/doc/guide/es/basics.controller#route) `post/index` y generar un parámetro GET `tag` con el valor `yii`. Por otro lado, cuando creamos una URL con la ruta `post/index` y parámetro `tag`, el componente `urlManager` va a usar ésta regla para generar la URL deseada `/index.php/posts/yii`. Por esta razón, decimos que `urlManager` es un gestor de URL de doble-camino.
El componente `urlManager` puede optimizar todavía más nuestras URLs, como ocultar `index.php` en las URLs, agregando un sufijo `.html` a las URLs. Podemos obtener estas funciones fácilmente con la configuración de varias propiedades de `urlManager` en la configuración de la aplicación. Para más detalles, por favor consulta [La Guía][the Guide](http://www.yiiframework.com/doc/guide/es/topics.url).

<div class="revision">$Id$</div>
79 changes: 79 additions & 0 deletions docs/blog/es/portlet.comments.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
Creación de Portlet de Comentarios Recientes
============================================

En esta sección, creamos el último portlet que muestra una lista de los comentarios recientes publicados.

Creando la clase `RecentComments`
---------------------------------

Creamos la clase `RecentComments` en el archivo `/wwwroot/blog/protected/components/RecentComments.php`. El archivo tendrá el siguiente contenido:

~~~
[php]
Yii::import('zii.widgets.CPortlet');

class RecentComments extends CPortlet
{
public $title='Recent Comments';
public $maxComments=10;

public function getRecentComments()
{
return Comment::model()->findRecentComments($this->maxComments);
}

protected function renderContent()
{
$this->render('recentComments');
}
}
~~~

En el código anterior, invocamos el método `findRecentComments` que es el definido en la clase `Comment` como sigue,

~~~
[php]
class Comment extends CActiveRecord
{
......
public function findRecentComments($limit=10)
{
return $this->with('post')->findAll(array(
'condition'=>'t.status='.self::STATUS_APPROVED,
'order'=>'t.create_time DESC',
'limit'=>$limit,
));
}
}
~~~

Creando la vista `recentComments`
---------------------------------

La vista `recentComments` se guarda en el archivo `/wwwroot/blog/protected/components/views/recentComments.php`. Simplemente muestra cada comentario retornado por el método `RecentComments::getRecentComments()`.

Usando el Portlet `RecentComments`
----------------------------------

Modificamos el archivo de diseño `/wwwroot/blog/protected/views/layouts/column2.php` para embeber este último portlet,

~~~
[php]
......
<div id="sidebar">

<?php if(!Yii::app()->user->isGuest) $this->widget('UserMenu'); ?>

<?php $this->widget('TagCloud', array(
'maxTags'=>Yii::app()->params['tagCloudCount'],
)); ?>

<?php $this->widget('RecentComments', array(
'maxComments'=>Yii::app()->params['recentCommentCount'],
)); ?>

</div>
......
~~~

<div class="revision">$Id$</div>
90 changes: 90 additions & 0 deletions docs/blog/es/portlet.menu.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
Creación de Portlet Menú de Usuarios
====================================

Basados en el análisis de requerimientos, necesitamos tres portlets diferentes: el portlet de "menú de usuario", el portlet de "nube de etiquetas" y el portlet de "comentarios recientes". Vamos a desarrollar estos portlets extendiendo el widget [CPortlet] que provee Yii.

En esta sección, vamos a desarrollar nuestro primer portlet concreto - el portlet de menú de usuario que despliega una lista de items de menú que son accesibles solamente a usuarios autenticados. El menú contiene cuatro items:

* Comentarios aprobados: un hipervínculo que lleva a una lista de comentarios pendientes de aprobación;
* Crear Nuevo Post: un hipervínculo que lleva a la página de creación de un post;
* Gestionar Posts: un hipervínculo que lleva a la página de gestión de posts;
* Logout: un botón que hace el logout del usuario actual.

Creando la clase `UserMenu`
---------------------------

Creamos la clase `UserMenu` para representar la parte lógica del portlet de menú de usuario. La clase es guardada en el archivo `/wwwroot/blog/protected/components/UserMenu.php` con el siguiente contenido:

~~~
[php]
Yii::import('zii.widgets.CPortlet');

class UserMenu extends CPortlet
{
public function init()
{
$this->title=CHtml::encode(Yii::app()->user->name);
parent::init();
}

protected function renderContent()
{
$this->render('userMenu');
}
}
~~~

La clase `UserMenu` extiende de la clase `CPortlet` desde la librería `zii`. Sobrecarga los métodos `init()` y `renderContent()` de `CPortlet`. El primero configura el título del portlet para que sea el nombre del usuario actual; el segundo genera el cuerpo del portlet mostrando una vista llamada `userMenu`.

> Tip|Consejo: Notar que debemos incluir explícitamente la clase `CPortlet` llamando a `Yii::import()` antes de que hagamos referencia por primera vez. Esto se debe a que `CPortlet` es parte del project `zii` -- la librería oficial de extensiones para Yii. Por cuestiones de rendimiento, las clases en este proyecto no son listadas como clases del núcleo. Por ello, debemos importarla antes de usarla por primera vez.

Creando la vista `userMenu`
---------------------------

Luego, creamos la vista `userMenu` que es guardada en el archivo `/wwwroot/blog/protected/components/views/userMenu.php`:

~~~
[php]
<ul>
<li><?php echo CHtml::link('Create New Post',array('post/create')); ?></li>
<li><?php echo CHtml::link('Manage Posts',array('post/admin')); ?></li>
<li><?php echo CHtml::link('Approve Comments',array('comment/index'))
. ' (' . Comment::model()->pendingCommentCount . ')'; ?></li>
<li><?php echo CHtml::link('Logout',array('site/logout')); ?></li>
</ul>
~~~

> Info: Por defecto, los archivos de vista para un widget deben ser ubicados en el subdirectorio `views` conteniendo el archivo de clase del widget. El nombre del archivo debe ser el mismo que el nombre de la vista.

Usando el Portlet `UserMenu`
----------------------------

Es hora de hacer uso de nuestro recién creado portlet `UserMenu`. Modificamos el archivo de vista del diseño `/wwwroot/blog/protected/views/layouts/column2.php` como sigue:

~~~
[php]
......
<div id="sidebar">
<?php if(!Yii::app()->user->isGuest) $this->widget('UserMenu'); ?>
</div>
......
~~~

En lo anterior, llamamos al método `widget()` para generar y ejecutar una instancia de la clase 'UserMenu'. Como el portlet debe ser mostrado solamente a usuarios autenticados, llamamos a `widget()` solamente cuando la propiedad `isGuest` del usuario actual es falsa (significando que el usuario está autenticado).

Probando el Portlet `UserMenu`
------------------------------

Vamos a probar lo que hemos hecho hasta ahora.

1. Abre una ventana del navegador e ingresa la URL `http://www.example.com/blog/index.php`. Verifica que no se muestre nada en la sección de la barra lateral de la pagina.
2. Haz click en el hipervínculo `Login` e ingresa los datos en el formulario para ingresar. Si el ingreso es exitoso, verifica que el portlet `UserMenu` aparezca en la barra lateral y el portlet tenga el nombre de usuario como su título.
3. Haz click en el hipervínculo de `Logout` en el portlet `UserMenu`. Verifica que la acción de logout sea exitosa y que el portlet `UserMenu`desaparece.


Resumen
-------

Lo que creamos es un portlet que es altamente reusable. Podemos fácilmente reusarlo en un proyecto diferente con pocas o ninguna modificación. Más aún, el diseño de este portlet sigue de cerca la filosofía en que la lógica y la presentación deben estar separadas. Mientras no mencionamos esto anteriormente, esta práctica es usada casi en todos lados de una aplicación Yii típica.

<div class="revision">$Id$</div>
60 changes: 60 additions & 0 deletions docs/blog/es/portlet.tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Creación de Portlet de Nube de Etiquetas (Tag Cloud)
==========================

[Nube de etiquetas](https://es.wikipedia.org/wiki/Nube_de_palabras) muestra una lista de etiquetas de post con elementos visuales diferenciando la popularidad de cada etiqueta individualmente.

Creando la clase `TagCloud`
---------------------------

Creamos la clase `TagCloud` en el archivo `/wwwroot/blog/protected/components/TagCloud.php`. El archivo tendrá el siguiente contenido:

~~~
[php]
Yii::import('zii.widgets.CPortlet');

class TagCloud extends CPortlet
{
public $title='Tags';
public $maxTags=20;

protected function renderContent()
{
$tags=Tag::model()->findTagWeights($this->maxTags);

foreach($tags as $tag=>$weight)
{
$link=CHtml::link(CHtml::encode($tag), array('post/index','tag'=>$tag));
echo CHtml::tag('span', array(
'class'=>'tag',
'style'=>"font-size:{$weight}pt",
), $link)."\n";
}
}
}
~~~

Al contrario del portlet `UserMenu`, el portlet `TagCloud` no usa una vista. Su presentación se realiza en el método `renderContent()`. Esto se debe a que la presentación no contiene muchas etiquetas HTML.

Mostramos cada etiqueta como un hipervínculo a la página `index` del post con su correspondiente etiqueta de parámetro. El tamaño de la fuente para cada enlace de la etiqueta se ajusta de acuerdo al peso relativo con las otras etiquetas. Si una etiqueta tiene una frecuencia más alta que la otra, va a tener un tamaño de fuente mayor.

Usando el Portlet `TagCloud`
----------------------------

El uso del portlet `TagCloud` es muy simple. Modificamos el diseño del archivo `/wwwroot/blog/protected/views/layouts/column2.php` como sigue,

~~~
[php]
......
<div id="sidebar">

<?php if(!Yii::app()->user->isGuest) $this->widget('UserMenu'); ?>

<?php $this->widget('TagCloud', array(
'maxTags'=>Yii::app()->params['tagCloudCount'],
)); ?>

</div>
......
~~~

<div class="revision">$Id$</div>
Loading

0 comments on commit 2100f0d

Please sign in to comment.