MANUAL

All the doumentation of this web site is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License

How to build a complete plugin for W3StudioCMS

The goal of this tutorial is to build a complete plugin for W3StudioCMS which has to display a masked photo gallery. This plugin will use the amazing mb-masked-gallery jquery's plugin and will extend its capabilities to let a user easy implement and manage it in W3StudioCMS. You have to download the mb-gallery

In this tutorial you will learn:

  • How to implement an helper to use an existing jquery tool.
  • How to implement a new content and editor
  • How to create a new uploader
  • How to Use the toolbar.yml file

Build the helper

mb-masked-gallery structure

The masked galley tool has some elements that has to be reproduced:

  • An inclusion of several jquery static scripts
  • A jquery script which initializes the gallery
  • An html list of images

A typical setup for this tool could be:

<!-- Jquery static scripts inclusion -->
<script type="text/javascript" src="inc/jquery-1.3.2.js"></script>
<script type="text/javascript" src="inc/mbMaskedGallery.js"></script>
<script type="text/javascript" src="inc/jquery.metadata.js"></script>

<!-- jquery script initialization -->
<script type="text/javascript">
  $(function(){
    $("#g1").mbMaskGallery({
      type:"normal",
      galleryMask:"mask/monitor.png",
      galleryUrl:"",
      galleryColor:"black",
      galleryLoader:"loader/loader_black.gif",
      loaderOpacity:.3,
      loader:true,
      fadeTime: 500,
      slideTimer: 6000,
      changeOnClick:true,
      navId:"" //nav1
    });
  });
</script>

<!-- Html list of images -->
<div id="g1" class="galleryCont" style="display:inline-block;">
  <img src="images/3.jpg" alt="">
  <img src="images/2.jpg" alt="" >
  [...]
</div>

To implement this tool the best way to choose, is creating an helper which will include the required static scripts, build the initialization script and write the html images list.

Create the structure for the plugin

A plugin made for W3StudioCMS has the same folder structure of one made for symfony. The only mandatory rule you have to follow is the name to give to the plugin. The rule is "Every plugin made for W3StudioCms has to be suffixed by the string w3sExtension" as follows:

w3sExtension[NAME]Plugin

To start building the plugin, create a new directory under the plugins folder in your symfony's project and call it w3sExtensionMbMaskedGalleryPlugin. Under this folder create a new directory called lib and another one inside that called helper. This is the standard folder where symfony requires the helpers to be stored.

Create a new file called w3sMbMaskedGalleryHelper.php inside the helper folder. Open it and put the following code inside:

use_helper('Javascript', 'I18N');

function initMbMaskedGallery($options = array())
{
}

The function that will draw the masked gallery has been declared and accepts an optional array of options as parameter. The options specified in that array will override the default options we declare inside the helper function when exist or will be discarded when they don't exist.

In the mb-masked-gallery documentaion we find the options accepted by this tool, so we could define our default options. Add the following code to the function:

$defaultOptions = array(
  "type" => 'normal',
  "galleryMask" => 'oblo.png',
  "galleryUrl" => '',
  "galleryColor" => 'white',
  "galleryLoader" => 'loader_white.gif',
  "loaderOpacity" => 1,
  "loader" => true,
  "fadeTime" => 400,
  "slideTimer" => 5000,
  "changeOnClick" => true,
  "nextPath" => 'next.png',
  "prevPath" => 'prev.png',
  "navId" => '',);

This array defines the default options used by the helper to render the gallery when any option is specified by the user. Please note that the array keys are exactly named as the accepted options by the mb-gallery-mask. We have defined the options for the gallery initializing script and now we have to define the ones for the html code. Giving a look to the html code used by the mb-gallery, for sure is required an id for the div that contains the images and the same id is required by the script that inizializes the gallery.

To build the list of images we should define a folder where the images will be stored then we will read the files which are contained in that folder to build the list of images. Add the following code to the helper's function:

$defaultParams = array('id'         => 'image_gallery_1',
                       'imagesPath' => 'screenshots/',);

A new array of options has been defined to store the parameters required to build the html code. The options param passed to the function can contain all the options for both the default options arrays.

Now it's time to match the params passed as reference with the ones defined as default options. When an option passed in the reference array matches one of the default options it has to override the default one and when an option doesn't exists in the default options has to be discarged. Add the following code after the one inserted before:

$params = array_diff_key(array_merge($defaultParams, $options), array_diff_key($options, $defaultParams));

The array_merge($defaultParams, $options) combines the default params with the options passed as reference, overriding the options that match the ones contained in the $defaultParams.

The array_diff_key($options, $defaultParams) retrieves the options that are not contained in $defaultParams which are removed from the result array.

We should repeate the same instructions for the $defaultOptions param, so it could be a good idea to create a function instead repeating the code. Add the following function to the helper:

function matchParams($param1, $param2)
{
  return array_diff_key(array_merge($param2, $param1), array_diff_key($param1, $param2));
}

then replace the code inserted before with this one:

$params = matchParams($options, $defaultParams);
$curOptions = matchParams($options, $defaultOptions);

Let's define the images paths now. We should decide where the masked gallery images have to be placed. The best available option is that the gallery's images have to be placed under the uploads/assets folder as all the other images. But this will cause an evident problem: in this way all the site's images will be displayed in the gallery.

The solution is to create a new directory under the assets folder and let it to be changeable by the user, because if it was hardcoded all the galleries used in a site will display all the images loaded in that folder. Put this code under the one inserted before:

$extraImagesPath = (substr($params['imagesPath'], strlen($params['imagesPath']) - 1, 1) != '/') ? $params['imagesPath'] . '/' : $params['imagesPath'];
$fullPath = w3sToolkit::checkLastDirSeparator(sfConfig::get('sf_web_dir') . sfConfig::get('app_gallery_base_images_dir')) . $extraImagesPath;
$absolutePath = w3sToolkit::checkLastDirSeparator(sfConfig::get('app_gallery_base_images_dir')) . $extraImagesPath;

The param extraImagesPath represents the folder under the one defined by the app_gallery_base_images_dir param. It is defined in the $defaultParams as imagesPath and can be overrided when the helper is called. It is needed the full images path and the absolute images path, as defined.

To get the images we will use the sfFinder tool. Add the following code to the helper's function:

$images = '';
$files = sfFinder::type('file')->maxdepth(0)->relative()->sort_by_name()->in($fullPath);
if (count($files) > 0)
{

}
else
{
  $gallery = __('<p>Any image availble in this folder.</p>');
}

return $gallery;

The sfFinder will search into the folder stored in the $fullPath variable and will return only the files in that folder, without any recursion. If any is found, a warning message is displayed.

When some files are found, the helper must build the code to display the gallery. The first thing to do is to add a call to the static javascripts. We will use the use_javascript helper which will load the javascripts and will put them into the page's header. Add the following code inside the if block:

use_javascript('/w3sExtensionMbMaskedGalleryPlugin/js/jquery-1.3.2.min.js');
use_javascript('/w3sExtensionMbMaskedGalleryPlugin/js/jquery.metadata.js');
use_javascript('/w3sExtensionMbMaskedGalleryPlugin/js/mbMaskedGallery.min.js');

The used path by the function is quickly explained. We are building a plugin which assets will be published into the symfony's project web folder by the symfony's task publish-assets. In fact the assets contained into the plugin's web folder will be copied or symlinked to the project's web dir and the folder or the symlink will be called as the plugin is called.

You have to create a new web directory under the plugin's dir, and another directory inside it that has to be called js. Then you have to copy the javascripts reported in the code above into the js folder, you have just created.

Next step is to format the options. Add the following code next the other one you've just added.

$options = array();
foreach($curOptions as $option => $value)
{
  switch($option)
  {
    case 'galleryMask':
      $value = sfConfig::get('app_gallery_masks_images_dir') . '/' . $value;
      break;
    case 'galleryLoader':
      $value = sfConfig::get('app_gallery_loaders_images_dir') . '/' . $value;
      break;
    case 'nextPath':
    case 'prevPath':
      $value = sfConfig::get('app_gallery_controls_images_dir') . '/' . $value;
      break;
  }

  if(!(int)$value && ($value != 'true' && $value != 'false')){ $value = sprintf('"%s"', $value);}
  $options[] = sprintf('%s: %s', $option, $value);
}

The options related to mask, controls and loader requires the full path because in the options it is passed only the image name, so here is added the absolute images path. Then it is required to escape the string values.

The options have been setted so the javascript code that will initialize the gallery can be written:

$gallery = sprintf('if(jQuery){jQuery.noConflict();}
                    jQuery(document).ready(function() {
                      jQuery("#%s").mbMaskGallery({
                        %s
                      });
                    });', $params['id'], implode(",\n", $options));
$gallery = javascript_tag($gallery);

The initialization script is stored in the $gallery variable. Now it is only required the html code:

foreach($files as $file)
{
  $images .= sprintf('<img src="%s" alt="">', $absolutePath . $file);
}
$gallery .= sprintf('<div id="%s" class="galleryCont">%s</div>', $params['id'], $images);

The images that has been found by the finder are converted in html code and the div is added to the $gallery variable.

To use the helper you can write something like this:

<?php
use_helper('w3sMbMaskedGallery');
echo initMbMaskedGallery();

Go to the next tutorial