Yiinitializr: The Library

Introduction

For those who have created a project boilerplate with Yiinitializr site, you will find that is not just a project boilerplate what you just downloaded. Within the boilerplate comes a library named: Yiinitializr (not very original I know). The classes within this tiny library are simple, yet powerful, and will help you build your own project setup, the one that really fits your needs for your Yii application.

The Classes Explained

The Yiinitializr classes will help boost your application installation with ease and also to run Yii applications from its bootstrap files on a much cleaner way that the framework currently proposes. Let’s have a look at the following example:

// if installed via composer (pretty neat right?)
require('./../../common/lib/vendor/autoload.php');

Yiinitializr\Helpers\Initializer::create('./../', 'frontend', array(
    // will override frontend configuration file
    __DIR__ .'/../../common/config/main.php', // merged with
    __DIR__ .'/../../common/config/env.php', // merged with
    __DIR__ .'/../../common/config/local.php' // merged with
))->run();

Yiinitializr\Cli namespace

This namespace brings utilities to interact with the terminal or ‘cli’. A free beer goes to mr nramenta for them.

Yiinitializr\Cli\Console

The Console class helps you to display information to the console. You probably, think that it as easy as to ‘echo’ from any of your Command components that are runed by the Yiic command and is true, but this class comes with some magic:

Color

Console::output('this is %rcolored%n and %Bstyled%n');

Prompt

$db_host = Console::prompt('database host', ['default' => 'localhost']);

Selection

$opt = Console::select('Do you love Yii?',
    ['y' => 'yes', 'n' => 'no', 'a' => 'all']
);

Confirm

$sure = Console::confirm('are you sure?');

Work

<?php
Console::stdout('Working ... ');
Console::work(function($socket) { // $socket is optional, defaults to a spinner
    $n = 100;
    for ($i = 1; $i <= $n; $i++) {
        // do whatever it is you need to do
        socket_write($socket, "[$i/$n]\n");
        sleep(1); // sleep is good for you
    }
});
Console::stdout("%g[DONE]%n\n");

Yiinitializr\Cli\Daemon

The Daemon class provides helpers for starting and killing daemonized processes.

<?php
use Yiinitializr\Cli\Daemon;

if (Daemon::isRunning('/path/to/process.pid')) {
    echo "daemon is running.\n";
} else {
    echo "daemon is not running.\n";
}

Yiinitializr\Composer namespace

I should just call this namespace Tobias Schmunk as he was the master guru behind this class, the only thing I did was to read the e-book of Composer and studied every single piece of his fabulous Phundament application boilerplate. To modify the class to become of more general usage out of Phundament has no much credit.

Here, we find the Callback class, a super useful class that will allow you to execute commands prior, post Composer extensions installations or updates. It makes use of the scripts configuration feature and even though for the current templates found at Yiinitializr Site the only thing it does is to call Yiic migrate commands but I am sure that you are already thinking of its possibilities.

Yiinitializr\Helpers namespace

Yiinitializer\Helpers\ArrayX

This class includes cool functions to work with arrays. It contains one cloned from CMap, the mergeArray function, as we require this method in order to combine the different configuration files before the Yii application is even included. A clear example of it you find it on Yiinitializr/config/console, which is the file that where you set the configuration of your console application to run Composer callbacks. It has also

Yiinitializr\Helpers\Config

It reads the configuration file and provides an interface to access the settings. It also, when working with different environments, writes the “env.lock” file. By creating this file, it tells the Initializr helper class to not recreate the env.php configuration file of the environment selected. If anybody wishes to recreate them, in order to make use of other environment configuration file (ie. stage vs local), the coder just needs to delete the “env.lock” file from the Yiinitializr/config folder.

The configuration file

As with Yii, you need to go through a bit of configuration settings if you wish to handle your project structure initializing setup with Yiinitializr. But don’t worry, is not going to be too hard, the following is an example configuration file:

\\ where am i?
$dirname = dirname(__FILE__);
\\ where is the application folder?
$app = $dirname . '/../../..';
\\ where is the root?
$root = $app . '/..';

return array(
    // yii configurations
    'yii' => array(
        // where is the path of the yii framework?
        // On this example we have installed yii with composer
        // and as it is used after composer installation, we
        // can safely point to the vendor folder.
        'path' => $app . '/lib/vendor/yiisoft/yii/framework'
    ),
    // yiinitializr specific settings
    'yiinitializr' => array(
        // config folders
        'config' => array(
            // we just need the console settings
            // On this example, and due that I used environments
            // i created a custom console.php app for
            // Yiinitializr\Composer\Callbak class
            'console' => $dirname . '/console.php'
        ),
        // application structure settings
        'app' => array(
            // where is the root?
            'root' => $root,
            // directories setup
            'directories' => array(
                // where are the different configuration files settings?
                'config' => array(
                    // 'key' is the configuration name (see above init example)
                    'main' => $app . '/config',
                    'console' => $app . '/config',
                    'test' => $app . '/config'
                ),
                // where are my runtime folders?
                'runtime' => array(
                    // heads up! only the folder location as "/config" will be
                    // appended
                    $app
                ),
                'assets' => array(
                    // where to write the "assets folders"?
                    $root . '/www'
                )
            ),
            'files' => array(
                // files to merge the main configuration file with
                // initializr will merge it automatically
                'config' => array(
                    'main' => array('env', 'local'),
                    'console' => array('env', 'local'),
                )
            )
        ),
    )
);

Yiinitializr\Helpers\Initializer

This class requires a little bit more attention and I hope you take a bit of time reading its code to truly understand what it does. Improving this class, can make our lives easier with Yii and I explain why:

  1. It tries to solve the problem with YII_DEBUG dynamically (no need to hardcode true|false on your index.php bootstrap file) – check the setOptions function.
  2. It creates all necessary read+write folders like runtime and assets (Yiinitializr works in conjunction with Composer but I am pretty sure some of you are already thinking on why is not Yii creating those folders when they are not found? Initializer class may provide the solution: if it doesn’t exist, build it don’t fail on error!)
  3. Automatically merges different configuration files that you may have for the different type of applications – check the config function.

Final Notes

We truly hope at 2amigOS! that you find this library as useful as it is for us. We do not expect that this procedure should be implemented at Yii‘s core but some of the features included in this small library are certainly something to consider on its future releases. Happy Yii coding!

References


[ad]

YiiBooster: How to implement files and images upload on TbRedactor Widget

Introduction

I have been requested to provide a tutorial on how to use the file upload feature of the TbRedactor widget, and even though I am no longer supporting the library due that the work belongs to Clevertech, I feel that I owe that to the Yii developers. So, here is the  tutorial.

How to do it

As you know, if you try to use TbRedactor “out of the box” and if you click on the “insert image”, you will see a “popup window” as the following image:

Captura de pantalla 2013-03-24 a la(s) 15.34.57

Not bad… but too plain. What about the really cool Fileupload shown on redactorJS site? How do we set it up? The answer is easier that you can imagine. In fact, the only thing that we need to tell the plugin is the URL address that will handle file and image upload processes.

// with a TbActiveForm
echo $form->redactorRow(
    $model,
    'attribute_name',
    array(
       'class'=>'span4',
       'rows'=>5,
       'options'=>array(
          'fileUpload' => $this->createUrl('site/testFileUpload'),
          'imageUpload' => $this->createUrl('site/testImageUpload'),
       )
    )
);

// as a widget
$this->widget('bootstrap.widgets.TbRedactorJs',
    array(
      'model'=>$model,
      'attribute'=>'attribute_name',
      'editorOptions'=>array(
          'fileUpload' => $this->createUrl('site/testFileUpload'),
          'imageUpload' => $this->createUrl('site/testImageUpload'),
          'width'=>'100%',
          'height'=>'400px'
       )
    ));

As soon as we have that setup, the popup window will display differently:

Files Upload
File Upload
Images Upload
Images Upload
Important How to handle file uploads is out of the scope of this tutorial. If you wish to know how to handle file uploads on the server from redactorJS, I highly recommend you to read the documentation at imperavi.

But wait a minute, what about if we wish to insert an image that has been previously uploaded? If we look at the redactor’s site we find really cool thumbnail images to choose from. Well, is a bit tricky but not too hard. The only thing that you have to do is to provide a URL where to download the “json” file that will get the uploaded files and their location.

// with a TbActiveForm
echo $form->redactorRow(
    $model,
    'attribute_name',
    array(
       'class'=>'span4',
       'rows'=>5,
       'options'=>array(
          'fileUpload' => $this->createUrl('site/testFileUpload'),
          'imageUpload' => $this->createUrl('site/testImageUpload'),
          'imageGetJson'=> $this->createUrl('site/testImageThumbs')
       )
    )
);

// as a widget
$this->widget('bootstrap.widgets.TbRedactorJs',
    array(
      'model'=>$model,
      'attribute'=>'attribute_name',
      'editorOptions'=>array(
          'fileUpload' => $this->createUrl('site/testFileUpload'),
          'imageUpload' => $this->createUrl('site/testImageUpload'),
          'imageGetJson'=> $this->createUrl('site/testImageThumbs')
          'width'=>'100%',
          'height'=>'400px'
       )
    ));

The following is an example action to return the thumbs and image information:

public function actionTestUpload()
{
   echo json_encode(array(
        array(
           'thumb' => '/images/image1_thumb.png',
           'image' => '/images/image1_big.png',
           'title' => 'Title1', // optional
           'folder' => 'myFolder' // optional
        ),
        array(
           'thumb' => '/images/image2_thumb.png',
           'image' => '/images/image2_big.png',
           'title' => 'Title2', // optional
           'folder' => 'myFolder' // optional
        )
   ));
}

Obviously, the above example has to contain the right resources to work but the result would endup with something similar to the following:

Images Choose
Images Choose Option

Further Reading


[ad]

YiiBooster: How to use TbFileUpload Widget

Introduction

The following wiki is to explain how to make use of the TbFileUpload widget from YiiBooster. I have received a couple of requests and I thought was worth writing a wiki for it.

Usage

Preparation

First, we need to make sure we have a folder with write permissions, that will be the place where we are going to save our uploaded files.

I normally create a files folder and I allocate it within my www one, that is where I keep my css, js, images files. So, even though you can place it where ever you wish and for the sake of the example, I will use thefiles folder name.

I also assume that you have configured a path alias that references the files folder. On this example, the path alias is frontend.www.files.

Note

  • This demo only works if the MyModel class already includes the function getImageUrl($img_type=null). If not, comment the 2 lines inside the data array, where ‘url’ and ‘thumbnail_url’ are defined, to make the demo work
  • If the MyModel has a different name, it needs to be replaced 1-2 times inside the upload action
  • The url where we are going to upload our files => upload action

Thanks Don Felipe

Setup your model

The way you handle validation on the server is up to you, the configuration I am going to provide now is just an example.

We are going to add one extra attribute to the model picture, which is going to hold any $_FILE type resource uploaded and validated when model is on upload scenario.

class MyModel extends CActiveRecord {
// ... more code here
/**
* This is the attribute holding the uploaded picture
* @var CUploadedFile
*/
public $picture;
// ... more code

/**
* @return array validation rules for model attributes.
*/
public function rules()
{
  return array(
    // ... more rules here
    array('picture', 'length', 'max' => 255, 'tooLong' => '{attribute} is too long (max {max} chars).', 'on' => 'upload'),
    array('picture', 'file', 'types' => 'jpg,jpeg,gif,png', 'maxSize' => 1024 * 1024 * 2, 'tooLarge' => 'Size should be less then 2MB !!!', 'on' => 'upload'),
    // ... more rules here
  );
}

Configuring the Widget

To render the widget on your view is quite straightforward, the are a couple of things very important to configure:

  • the url where we are going to upload our files
  • the file types we are going to accept and their maximum size

Now, lets render it:

<!--?php $this--->widget('bootstrap.widgets.TbFileUpload', array(
    'url' => $this->createUrl("my/upload"),
    'model' => $model,
    'attribute' =>'picture', // see the attribute?
    'multiple' => true,
    'options' => array(
    'maxFileSize' => 2000000,
    'acceptFileTypes' => 'js:/(\.|\/)(gif|jpe?g|png)$/i',
))); ?>

Handling Upload

Everything is ready now but the controller. We have to configure the action that will handle the upload process. Here you go, the upload action of our controller -very, very basic – and not fully tested:

class myController extends CController {
   // ... more code here/**
   * Handles resource upload
   * @throws CHttpException
   */
   public function actionUpload()
   {
      header('Vary: Accept');
      if (isset($_SERVER['HTTP_ACCEPT']) &&
      (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false))
      {
         header('Content-type: application/json');
      } else {
         header('Content-type: text/plain');
      }
      $data = array();

      $model = new MyModel('upload');
      $model->picture = CUploadedFile::getInstance($model, 'picture');
      if ($model->picture !== null && $model->validate(array('picture')))
      {
         $model->picture->saveAs(
            Yii::getPathOfAlias('frontend.www.files').'/'.$model->picture->name);
         $model>file_name = $model->picture->name;
         // save picture name
         if( $model->save())
         {
            // return data to the fileuploader
            $data[] = array(
            'name' => $model->picture->name,
            'type' => $model->picture->type,
            'size' => $model->picture->size,
            // we need to return the place where our image has been saved
            'url' => $model->getImageUrl(), // Should we add a helper method?
            // we need to provide a thumbnail url to display on the list
            // after upload. Again, the helper method now getting thumbnail.
            'thumbnail_url' => $model->getImageUrl(MyModel::IMG_THUMBNAIL),
            // we need to include the action that is going to delete the picture
            // if we want to after loading
            'delete_url' => $this->createUrl('my/delete',
            array('id' => $model->id, 'method' => 'uploader')),
               'delete_type' => 'POST');
         } else {
               $data[] = array('error' => 'Unable to save model after saving picture');
         }
      } else {
         if ($model->hasErrors('picture'))
         {
            $data[] = array('error', $model->getErrors('picture'));
         } else {
            throw new CHttpException(500, "Could not upload file ". CHtml::errorSummary($model));
         }
      }
      // JQuery File Upload expects JSON data
      echo json_encode($data);
   }

   // .... more code here

} // end of controller

Resources

YiiBackboneBoilerplate – Project Setup for your Yii+BackboneJS applications

YiiBackboneBoilerplate

We at Clevertech use this folder structure setup for our own projects when developing BackboneJS applications.

Overview

YiiBackboneBoilerplate, aims to provide Yii Backbone developers with an application folder to ease the startup of their projects. It uses the flexibility of our YiiBoilerplate with a twist for BackboneJS applications.

What is BackboneJS?

Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.

You may be thinking that Yii is too powerful to be used just as a RESTful service. That for this purpose it could be done with NodeJS or any of the other libraries available, but it is the power of Yii and for the sake of application scalability that we decided to use it.

BackboneJS + Yii

We love to work at Clevertech with Yii, in fact, it is one of the biggest assets of our company nowadays. Nevertheless, we are very aware of the new trends, and we had the opportunity to work with BackboneJS. So we decided that it could be good to provide a project startup for our developers, and allow us to get the best out of both worlds.

Backbone Overall Folder Structure

This document will be focused mainly in the folder structure that we set for the Backbone application. Please, read YiiBoilerplate’s README for a deeper explanation of the main Yii folder structure setup.

Below the directory structure we are using:

/
backend/
    ...
common/
    ...
console/
    ...
frontend/
    ...
    www/
        app/
            css/
            img/
            js/
                boilerplate/
                collections/
                libs/
                models/
                views/
                app.js
                controller.js
                main.js
                router.js
                vent.js
            templates/
tests/
    ...

Backbone Application Directories

In the js directory, we have:

  • boilerplate: we have created a set of elements for you to create a model, collection, module and/or view. Please, note that the basic application skeleton that we have setup for you is based onBackbone.Marionette, and the views are different from normal Backbone views.
  • collections: this is were we place the Backbone collections for our application.
  • libs: holds the main libraries. We included the ones we thought would be the most useful.
  • models: this is were we place the Backbone models for our application.
  • views: and this is where we place the backbone views.

A special note regarding the templates directory. This folder is normally within the js folder, but we thought that it would be better to separate UI design from the business logic of the javascript files.

The runpostdeploy script

This section is actually extracted from YiiBoilerplate, but it is worth repeating the procedure.

The project has a very handy script that automatically creates the required and folders that are not shared for a Yii application, the runtime and assets folders, extracts the configuration settings specified for a specific environment then copies them to the ****-env.php*** files, and then runs migrations when not on private environments –we believe that migrations should be always run manually by developers on their machines.

To use this, from the application’s root folder, simply run:

./runpostdeploy environmentType migrations

  • environmentType (required): can be “any” of the ones you configure on the environments folders (i.e../runpostdeploy private to use ****-private.php*** configurations)
  • migrations (optional): could be “migrate“” or “no-migrate“.
    • migrate: will run migrations
    • no-migrate: will not run migrations (on private we won’t run them anyway)

Final Notes

We would like to inform that this is just a startup boilerplate for your own projects. It is not intended by any means to be used ‘AS IS’, but rather as a base to scale to more complicated structures.

Neverteless, we have included a couple of goodies that we hope to improve with the help of the community.

Resources and Download

Get the most up to date version from the Github repository!

YiiSES – Implement Bulk Mail Marketing with Amazon Simple Email Service

Introduction

I had to develop a module for a client at Clevertech that was quite interesting and not any developed for Yii yet. The module was to take care of the bulk mail services of the client and it supposed to work with nearly new Amazon Simple Email Service, which make the task even more interesting. The end result was YiiSES and to tell you the truth I was very happy with it.

Nevertheless, an image is worth thousand words, check the following thumbnails:

Features List

  • Campaign Management
  • Campaign Stats
    • How many opened / failed / successful
  • Amazon SES Usage Stats
  • Subscriber Management
  • Google track vars
  • And much more

I think is much better if you check it out by yourself. The whole project is Open Source and is freely available under Creative Commons Attribution-ShareAlike 3.0 Unported License, you can get is source code at Clevertech’s github profile: https://github.com/clevertech/YiiSES, we would love to hear your feedback, specially me.

YiiSES Overview

YiiSES is a ‘nearly’ ready to use module that provides our Yii applications with a powerful mail marketing tool.

The system makes use of Amazon Simple Email Service (Amazon SES), chosen for its highly reduced price, scalability and features. A developer can easily register and use its service at no charge. The only issue is that the developer will only be able to send to verified email addresses only.

This module has been ported to Open Source from one of the projects at Clevertech and we are very happy with its results so far.

Install

Even though there was some good effort to make it easy to install, its configuration is a bit tricky. We hope this will change with a bit of help from the community.

Within the code you will find two types of configurations, one to be used with YiiBoilerplate project structure (default), and the other when we install the module on a Yii’s default application structure.

The following instructions are to install the module on a Yii’s default application structure.

Configuration

  • Create your web application ./yiic webapp <folder>
  • Create your modules folder under protected and unpack the module there
  • Place commands\CampaignCommand.php on your commands directory and ses\migrations.. on the migrations directory.
  • Configure your config\main.php and config\console.php configuration files (make sure your db is setup correctly –migrations will only work on mySQL db):
// console.php
    …
    // urlManager must be the same configuration as on main.php
    'urlManager' => array(
        // remember to have your .htaccess setup correctly
        'urlFormat' => 'path',
        'showScriptName' => false,
        'urlSuffix' => '/',
        'rules'=>array(
            '<controller:\w+>/<id:\d+>'=>'<controller>/view',
            '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
            '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
        ),  
    ),
    // request is required to create appropriate urls within the emails
    // when processed with the CampaignCommand.php
    'request' => array(
    )
    …

    // main.php
    …
    'modules' => array(
        'ses'=>array(
            'password'=>'clevertech',
        ),
    ),
    …   
    // urlManager must be the same configuration as on main.php
    'urlManager' => array(
        // remember to have your .htaccess setup correctly
        'urlFormat' => 'path',
        'showScriptName' => false,
        'urlSuffix' => '/',
        'rules'=>array(
            '<controller:\w+>/<id:\d+>'=>'<controller>/view',
            '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
            '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
        ),  
    ),  
    …
    'params'=> array(
        'ses.aws.key'=>'',
    …
  • Setup required parameters on your configuration files (must be shared among console.php and main.php):
    • ses.aws.key: Your Amazon SES API Key
    • ses.aws.secret: Your Amazon SES Secret
    • ses.aws.verifiedEmail: You are required to verify at least one email address on Amazon SES console in order to send emails
    • ses.aws.test.email: Email where to send test emails. If your account is not in production, then this email should be also verified on Amazon SES console.
    • ses.emailonacid.key: If you wish to preview and test your emails on EmailOnAcid service, you have to configure your API key here.
    • ses.emailonacid.pwd: Your password to access EmailOnAcid service for testing and previewing your emails.
    • ses.files.path: Set this parameter in order to make use of the image upload capabilities ofRedactorJS, our chosen WYSIWYG editor for the module.
    • ses.files.url: Required to display the thumbnail gallery of RedactorJS.
    • ses.panel.login.url: The Route to the control panel. This parameter is required at the unsubscribe form. If somebody tries to remove an email from a registered user, then it will be presented with the link created from this route, to inform that he should log into its panel in order to unsubscribe.
    • ses.from.name: Your application name. Will be included in the Emails From Name (ie.”My Application ” )
  • Make sure your paths are correctly set:
    • CampaignCommand.php::init() – line 74
    • CampaignCommand.php::sendEmail() – line 376
    • models\Email.php::formatHTMLMessage() – line 136
    • models\Template.php::getView – line 65
  • Run migrations ./yiic migrate from your command line prompt.

The User table and Model

One important part of the configuration is how you deal with the subscribers. The module works by default with the assumptions that your application has a User model with id, email, and username, subscribedattributes.

The module comes with a single field for campaign that configures whether to send to subscribers or not but you can easily change that behavior to match different fields or subscription option from your registered members -but this is something that I won’t explain here :).

Requirements

The following requirements are all included already within the module:
– EPHPThumb – SES Component
– YiiBootstrap
– HighCharts
– RedactorJS

Contribute

If you wish to contribute, please fork our repository!


[ad]

ENexmo Yii Extension Library

Introduction

ENexmo Library allows Yii programmers to use the Restful API offered by Mobile Messaging provider Nexmo.

ENexmo is a cloud-based SMS API that lets you send and receive high volume of messages at wholesale rates.

Requires

Quick Start

Once you have created your Nexmo account and include ENexmo library and EHttpClient on the extension folder is as easy as this:

/* import extensions before any call */
Yii::import('ext.httpclient.*');
Yii::import('ext.nexmo.*');

/* to send a message */
$nexmo_sms = new ENexmoSms('YOURAPIKEY','YOURAPISECRET');

$response = $nexmo_sms->sendTextMessage('RECIPIENTSNUMBER','SENDERID','Howdy testing! Please, search on http://www.google.com.');

/* responses are on JSON or XML. Defaults to JSON, but you can change that */
/* we use CHtml::encode for demo purposes only, to check for responses */
echo CHtml::encode($response);

/* to make requests for account */
$nexmo_account = new ENexmoAccount('key','secret');
$nexmo_account->format = ENexmoBase::FORMAT_JSON;

/* to search for a message */
echo CHtml::encode($nexmo_account->searchMessage('09AFDA98'));
//echo CHtml::encode($nexmo_account->searchMessagesByIds(array('09AFCC5B','09AFDA98')));
//echo CHtml::encode($nexmo_account->searchMessagesByDateAndRecipient('2012-03-20','34607040932'));
//echo CHtml::encode($nexmo_account->balance);
//echo CHtml::encode($nexmo_account->ownNumbers);
//echo CHtml::encode($nexmo_account->getSmsPricing('ES'));

Please check Nexmo API Documentation Nexmo API Documentation

Ei18n Translation Module

Introduction

Ei18 is a translation module to allow Yii’ers to easily manage missing translations on application pages. It is heavily inspired by yii.translatedeveloped by Gustavo Salomé Silva gusnips.

The reason I developed a new one is because Gustavo’s approach wasn’t suitable for my needs, I wanted the translation to be specific to the languages I was editing and not to edit them all at once. Also, the theme was not rendering right and I couldn’t make it work properly as my design was not developed with the one Yii comes by default.

I wanted to make it as a component only but then I realized that to be a module was the right way to go as I could automate language edition without making the user tweak far too many things.

The following is a snapshot of the editor:

 

Features

  • Automatically creates the message translation tables on your database.
  • The module allows the edition of translations specified by categories. Its utility widget WTranslate handles that very smoothly.
  • All is AJAX based at the frontend. I thought that would be better to leave to developers the creation of a backend in order to edit translation on a regular basis.
  • Its Ei18 component has a couple of helper functions to also manage language setting automation. Check also its Set CAction class to be included on the controller that will handle language setting.

Requirements

  • jQuery v1.7 or higher (tested with jQuery v1.7)
  • fancybox 2.0.5
  • jwysiwyg 0.97.2
  • jbar Jquery plugin –Modified version
  • Yii 1.9
  • Translations handled by CDbMessageSource

Tested With

  • Chrome 17.0.963.56 on Macosx Lion
  • Safari Version 5.1.3 (7534.53.10) on Macosx Lion
  • Firefox 8.0.1 Macosx Lion
  • Firefox 9.0.1 Macosx Lion

Quick Start

The configuration is a bit troublesome, but once you get it up and running editing your missing translations will be peanuts.

In order to make it run we need to:

  • Configure Ei18n on your main.php configuration file
  • Render the widget on your base layout file

Configuring Ei18n

On you main.php configuration file do the following:

/* import the module */
   'import'=>array(
   /* ... */
       'application.modules.translate.TranslateModule'
   /* ... */
/* setup your default language */
    'language'=> 'en',
/* setup message translation method */
    'components'=>array(
       'messages' => array(
           'class' => 'CDbMessageSource',
           'onMissingTranslation' => array('Ei18n', 'missingTranslation'),
           'sourceMessageTable' => 'tbl_source_message',
           'translatedMessageTable' => 'tbl_message'
           ),
/* setup global translate application component */
       'translate' => array(
           'class' => 'translate.components.Ei18n',
           'createTranslationTables' => true,
           'connectionID' => 'db',
           'languages' => array(
                    'en' => 'English',
                    'es' => 'Español',
                    'it' => 'Italiano'
                    )
            ),
        ),
/* setup the module */
       'modules' => array(
            'translate'
        ),
/* preload the global translate application component */
       'preload'=> array(
            'translate'
        )
        /* ... */

Displaying the editor

Once the module and the translation component have been set. You just use any of the following helper functions:

Yii::app()->translate->renderMissingTranslationsEditor();
    /* or only certain categories*/
/* Yii::app()->translate->renderTranslationsEditor(array('index','menu')); */

The first method and due to the view rendering nature of Yii, I highly recommend the display of those functions at the bottom of your main or base layout, as it will collect all missing ones throughout the rendering processes.

Remember the translations are automatically collected when Yii goes through all thoseYii::t(‘category’,’translation text’); statements throughout your code and fires the onMissingTranslation event.

Yes, is on Github

Anybody willing to help improving E1i8n is highly welcome. Check the github repository on the resources section.

Changelog

  • version 1.0.0 Initial version release

Resources


[ad]

EScriptBoost Extension for Yii

Introduction

Probably a lot of you would wonder why, having so many good extensions related to minifying/compressing/packing your javascript code and your css files at the Yii Extensions Repository, here comes this guy offering us another solution.

I did check out all the extension in our repository, just to name some of them:

All of them are great, but none were filling the requirements we had. I did not have any issue compressing all our files as our team, will use the YUI compressor jar file to create our compressed javascript versions and then use the wonderful mapping features of CClientScript. The issue was with the assets of external, or own developed, extensions and the javascript code that, even Yii own widgets, were writing to the POS_BEGIN, POS_END, POS_HEAD, POS_LOAD, POS_READY positions. Thats exactly what this library is doing: allowing Yii coders to minify those scripts.

I have created a GitHub repository for those willing to contribute on any of the extensions I created. Please, check the link at the bottom of this wiki.

Library

The library comes with three flavors:

  • EScriptBoost Component
  • EClientScriptBoost Extension
  • AssetManagerBoost Extension

EScriptBoost Component

This is a very easy to use component to compress your Javascript or CSS code at your will. The minifiers used are:

Usage

// this is a very simple example :)
// we use cache as we do not want to
// compress/minify all the time our
// script
$js = Yii::app()->cache->get('scriptID');

if(!$js)
{
     $cacheDuration = 30;
     $js = <<<EOD
     // my long and uncompressed code here
EOD;
     // $js = EScriptBoost::packJs($js);
     // $js = EScriptBoost::minifyJs($js, EScriptBoost::JS_MIN_PLUS);
     $js = EScriptBoost::minifyJs($js, EScriptBoost::JS_MIN);

     // see Cache guide for more options | dependencies
     Yii::app()->cache->set('scriptID', $cacheDuration);
}
Yii::app()->clientScript->registerScript('scriptID', $js);

That was troublesome right? No worries, if you don’t really care about using JS_MIN, or JS_MIN_PLUS, you can use its helper function registerScript, it will handle all of the above automatically:

$js = <<<EOD
    // my long and uncompressed code here
EOD;
EScriptBoost::registerScript('scriptID', $js);

EClientScriptBoost Extension

EScriptBoost was good for the javascript code written by me but what about the ones written by Yii widgets?EClientScriptBoost was developed to solve that:

Usage

On your main.php config file:

'import' => array(
// ... other configuration settings on main.php
// ... importing the folder where scriptboost is
    'application.extensions.scriptboost.*',
// ... more configuration settings
    ),
// ... other configuration settings on main.php
'components' => array(
     'clientScript' => array(
// ... assuming you have previously imported the folder
//     where EClientScriptBoost is
         'class'=>'EClientScriptBoost',
         'cacheDuration'=>30,
// ... more configuration settings

Done! now, every time you or other component on your application will be minified and cached as you specify on your cache settings. Easy right?

EAssetManagerBoost Extension

But there was one more challenge to solve. Some extensions, widgets, etc, do publish a whole bunch of files in our assets that are not minified. This is where EAssetManagerBoost comes handy.

This extension does only minify javascript/css files, and also makes sure that the, about to be compressed, file do not match any of its $minifiedExtensionFlags so minified/compressed files are not processed at all.

Usage

Make sure you have deleted your previous assets folder contents.

'import' => array(
// ... other configuration settings on main.php
// ... importing the folder where scriptboost is
    'application.extensions.scriptboost.*',
// ... more configuration settings
    ),
// ... other configuration settings on main.php
'components' => array(
    'assetManager' => array(
// ... assuming you have previously imported the folder
      'class' => 'EAssetManagerBoost',
      'minifiedExtensionFlags'=>array('min.js','minified.js','packed.js')
        ),
// ... more configuration settings

Important Note There is a small drawback to use EAssetManagerBoost and is that, the first time your application is requested, it will take a bit of time as it will go throughout all your asset files to be published and minify them.

Resources


[ad]

Using events with CAction classes

Introduction

There are some good guides out there explaining how to work with events and the ways to attach them to your components, but none (that I know) explain the following way to configure your events with CAction classes on your controllers.

As you know, events are used by:

  • Declaring an event in your component adding its method (ie. function onClick($event))
  • Attach it to event handlers (ie. $object->onClick=array($handlerObject,’staticmethod’);)
  • Raising it from your component to call all subscribed handlers (ie. $this->raiseEvent(‘onClick’,$event)). Remember, that for a handler, you can write an object with static methods, an object with a method, create a function (create_function) and even attach a function directly (since PHP 5.3)

Tip

If we look at the magic method __set of CComponent, we will see that event handlers are actually set like properties.
Having that into account, the following is my quick tip to set your event handlers when working with CAction classes, which I think is far much better to organize your code in your controllers.

The CAction class

Lets write a simple CAction class for the example and save it as EMyAction.php:

class EMyAction extends CAction{
	public function onTest($event){
		$this->raiseEvent('onTest', $event);
	}
	public function run() {
		$event = new CEvent($this);
		$this->onTest($event);
	}
}

The Controller

Now in our controller, for the sake of the example, lets write a method handler and configure the action (assumed to be on actions folder under, which is in controllers folder).


// our event handler method, that, for simplicity,
// we set it in our controller
public function eventHandlerMethod($event)
{
	echo 'TESTING Handler';
}

// declaring actions and its event handlers
public function actions()
{
	return array(
		// test is the action name <controller/action>
		'test'=>array(
			'class'=>'actions.EMyAction',
			'onTest'=>array($this,'eventHandlerMethod')
		)
    );
}

And that’s it, call the controller’s action as you would with any other in your preferred browser to test the results.

Yii 1.1 Application Development Cookbook -by Alexander Makarov

As most of you know, I am a heavy user of the Yii’s forum. Lots of times, people keep asking what is the best way to learn Yii, what should be the steps? Where are good resources to look for their answers… I once wrote an article: Yii Learning Guide, that should be now updated with a new great resource, the new book written by Alexander Makarov (samdark), Yii 1.1 Application Development Cookbook.

I had the pleasure to be one of the reviewers of the book, and I must admit that I felt more like a student than a reviewer :). The book is an excellent guide to solve, through practical examples, some of the challenges a Yii programmer would face during its Yii application development:

– How events work
– Using Exceptions
– Components, Widgets, Collections
– Deep on Router, Controllers and Views
– AJAX and JQuery with Yii
– Forms, ActiveRecord, Models and Database
– Zii Components
– Extensions
– Error Handling, debugging and Logging
– Security and performance tuning
– Using external libraries
– Deployment

In addition, the book is not only a good practical reference to the points above, but also directs to external references on the web for further reading. It is a perfect companion for our online Yii site, class reference, wiki, and forum… I have mine already, when are you going to get yours?

 

 


[ad]