viernes, 23 de septiembre de 2011

Yupp CMS: creando modulos

En este artículo veremos como crear nuevos módulos para Yupp CMS.

Lo primero que tenemos es la estructura interna del CMS:
  • controllers
    • apps.cms2.controllers.CmsController.class.php
  • model
    • cms
      • cms2.model.cms.Layout.class.php
      • cms2.model.cms.Module.class.php
      • cms2.model.cms.Page.class.php
      • cms2.model.cms.PageZone.class.php
      • cms2.model.cms.Zone.class.php
  • views
    • cms
      • createModule.view.php
      • createPage.view.php
      • displayPage.view.php
      • displayPageRO.view.php
      • editModule.view.php
      • listModules.view.php
      • listPages.view.php
    • module
      • displayModule.template.php

El objetivo es crear un módulo para poder mostrar HTML y editarlo de forma visual en la web.

Lo primero que hacemos es crear la clase en el modelo, y ubicarla en model/nombreDelModulo:

YuppLoader::load('cms2.model.cms', 'Module');

class HtmlModule extends Module
{
   function __construct($args = array (), $isSimpleInstance = false)
   {
      $this->setWithTable("cms_html_module");
        
      $this->addAttribute("content", Datatypes :: TEXT);

      parent :: __construct($args, $isSimpleInstance);
   }

   public static function listAll(ArrayObject $params)
   {
      self :: $thisClass = __CLASS__;
      return PersistentObject :: listAll($params);
   }

   public static function count()
   {
      self :: $thisClass = __CLASS__;
      return PersistentObject :: count();
   }

   public static function get($id)
   {
      self :: $thisClass = __CLASS__;
      return PersistentObject :: get($id);
   }

   public static function findBy(Condition $condition, ArrayObject $params)
   {
      self :: $thisClass = __CLASS__;
      return PersistentObject :: findBy($condition, $params);
   }

   public static function countBy(Condition $condition)
   {
      self :: $thisClass = __CLASS__;
      return PersistentObject :: countBy($condition);
   }
}


El módulo se llama HtmlModule, y siempre debe extender a Module. La estructura de directorios en model quedará así:
  • model
    • cms
      • ...
    • htmlModule
      • cms2.model.htmlModule.HtmlModule.class.php

Ahora necesitamos crear un controlador que implemente las acciones particulares sobe ese módulo, como editar el contenido. El controlador debe tener el mismo nombre que el módulo. Aquí está el código del controlador:

YuppLoader::load('cms2.model.htmlModule', 'HtmlModule');

class HtmlModuleController extends YuppController {

   /**
    * Edita el contenido del modulo de HTML.
    * 
    * in: id
    * in: pageId
    */
   public function editAction()
   {
      $module = HtmlModule::get($this->params['id']);
      if (isset($this->params['doit']))
      {
         $module->setProperties($this->params);
         if (!$module->save()) print_r($module->getErrors());
         
         return $this->renderString('Modulo salvado correctamente');
      }
      
      return array('module'=>$module);
   }
}


Aquí está la estructura de directorios resultante de controladores:
  • controllers
    • apps.cms2.controllers.CmsController.class.php 
    •  apps.cms2.controllers.HtmlModuleController.class.php

 Por último, se implementan las vistas del módulo. Una vista será para la edición del contenido, y otra para la visualización del contenido del módulo. La estructura de directorios resultante es la siguiente:
  • views
    • cms
      • ....
    • module
      • displayModule.template.php
    • htmlModule
      • edit.view.php
      • displayModule.template.php

Como se puede ver, en realidad la vista de visualización del contenido del módulo es en realidad un template.

displayModule.template.php:

<?php echo $module->getContent(); ?>
<?php if ($mode=='edit') : ?>
  <div class="customModuleActions">
    <a href="'htmlModule', 'action'=>'edit', 'class'=>$module->getClass(), 'id'=>$module->getId())); ?>" alt="editar html" class="edit_html">
      <?php echo h('img', array('app'=>'cms2', 'src'=>'edit.gif')); ?>
    </a>  
  </div>
<?php endif; ?>



Este template muestra el contenido del módulo, y si estamos en modo "edit", muestra el botón para editar el contenido del módulo.


edit.view.php:

<?php

$m = Model::getInstance();

$module = $m->get('module');

YuppLoader::load('core.mvc', 'DisplayHelper');

?>
<html>
  <head>
    <style>
      body {
         padding: 5px;
      }
    </style>
    
    <?php echo h('js', array('app'=>'cms2', 'name'=>'jquery/jquery-1.5.1.min')); ?>
    <?php echo h('js', array('app'=>'cms2', 'name'=>'jquery/jquery.form-2.84')); ?>
    <script type="text/javascript">
      
      // Funcion que va a llamar el editor cuando termine de cargar (ver config del TinyMCE)
      var htmlinit = function() {
         
         parent.modalReady(document); // Notifica para que el parent actualice el tamanio del iframe
      }
      
      $(document).ready( function() {
        
        // Para que actualice el textarea con el contenido del TinyMCE, antes de mandarlo por ajax.
        // Ref: http://maestric.com/doc/javascript/tinymce_jquery_ajax_form
        $('#editForm').bind('form-pre-serialize', function(e) {
            
            tinyMCE.triggerSave();
        });
        
        // Submitea el form por ajax
        $('#editForm').ajaxForm({
          
          // Cuando el servidor responde ok, quiero actualizar
          // automaticamente el HTML del modulo sin hacer F5.
          success: function (res, status, response) {
             
            // Este es el modulo que cambia en el dom
            var module = $('#getClass().'__'.$module->getId(); ?>', parent.document);
             
            // Tengo que pedir al servidor el HTML actualizado para este modulo
            // Luego meto el actualizado en el dom, antes del que cambie
            // Luego elimino el modulo viejo del dom para que quede solo el actualizado
            
            $.ajax({
              url: ''cms', 'action'=>'moduleContent', 'params'=>array('class'=>$module->getClass(), 'id'=>$module->getId()))); ?>',
              success: function (newModuleContent, status) {
                
                // Actualiza solo el contenido!
                module.children('.moduleContent').html(newModuleContent);

                // Obtengo ventana modal
                var modal = $('#modal', parent.document); // Selecciona ventana
                
                // Cierra ventana modal
                modal.fadeOut('slow').css('display', 'none').children('iframe').attr('src', '');
              }
            });
          }
        });
      });
      
    </script>
  </head>
  <body>
    <form id="editForm" method="post" action="'edit')); ?>">
      <input type="hidden" name="id" value="getId(); ?>" />
      <input type="hidden" name="pageId" value="get('pageId'); ?>" />
      <?php DisplayHelper::html( 'content', $module->getContent() ); ?>
      <input type="submit" name="doit" value="Guardar" />
    </form>
  </body>
</html>


Eso es todo. Cualquiera puede desarrollar sus propios módulos, por ejemplo un cliente de twitter, un visualizador de videos de youtube, un blog, un albúm de fotos, etc, el límite es la imaginación!

.

No hay comentarios:

Publicar un comentario en la entrada