Location: PHPKode > projects > Maintainable PHP Framework > vendor/Mad/Script/Generator.php
<?php
/**
 * Class to generate directories and code stubs for common class skeletons
 *
 * @category   Mad
 * @package    Mad_Script
 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 * @license    http://opensource.org/licenses/bsd-license.php BSD
 */

/**
 * Class to generate directories and code stubs for common class skeletons
 *
 * @category   Mad
 * @package    Mad_Script
 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 * @license    http://opensource.org/licenses/bsd-license.php BSD
 */
class Mad_Script_Generator extends Mad_Script_Base
{
    /**
     * Template
     * @var Mad_View_Base
     */
    protected $_tpl;

    /**
     * Argument list passed in from the command line
     * @var array
     */
    protected $_args;

    /**
     * The author of the packages (who is running this script)
     * @var string
     */
    protected $_author;

    /**
     * Option to overwrite All files when getting input from user
     * @var boolean
     */
    protected $_overwriteAll = false;


    /*##########################################################################
    # Construct
    ##########################################################################*/

    /**
     * Take the array of arguments given
     * @param   array   $args
     */
    public function __construct($args)
    {
        $this->_tpl = new Mad_View_Base();
        $this->_tpl->addPath('vendor/Mad/Script/templates');

        $filename = array_shift($args);
        $action   = !empty($args) ? array_shift($args) : null;
        $this->_args = $args;

        // generate model stubs
        if (strtolower($action) == 'model') {
            $this->_generateModelStubs();

        // generate migration stubs
        } elseif (strtolower($action) == 'migration') {
            $name = !empty($this->_args) ? array_shift($this->_args) : null;
            $migration = Mad_Support_Inflector::underscore($name);

            $this->_generateMigrationStub($migration);

        // generate controller stubs
        } elseif (strtolower($action) == 'controller') {
            $this->_generateControllerStubs();

        // generate helper stubs
        } elseif (strtolower($action) == 'helper') {
            $this->_generateHelperStubs();

        } elseif (strtolower($action) == 'mailer') {
            $this->_generateMailerStubs();

        // invalid option - show help page
        } else {
            $this->_displayHelp();
        }
    }


    /*##########################################################################
    # Generators
    ##########################################################################*/

    /**
     * Generate model class stubs
     */
    private function _generateModelStubs()
    {
        $name = !empty($this->_args) ? array_shift($this->_args) : null;
        if (!$name) {
            $this->_exit("You did not specify the name of the Model to generate");
        }

        // CREATE FILES
        $modelFile = Mad_Support_Inflector::camelize($name);
        $modelName = Mad_Support_Inflector::classify($name);
        $tableName = Mad_Support_Inflector::tableize($name);

        // make namespace dir
        if (strstr($modelFile, '/')) {
            $this->_createDir(MAD_ROOT.'/app/models/'.dirname($modelFile).'/');
        }

        // template files & common vars
        $this->_tpl->author = $this->_author;
        $this->_tpl->className = $modelName;
        $this->_tpl->tableName = $tableName;

        // create Model file snippit
        $content = $this->_tpl->render('model.php');
        $this->_createFile(MAD_ROOT."/app/models/{$modelFile}.php", $content);

        // create Unit Test stub
        // make namespace dir
        if (strstr($modelFile, '/')) {
            $this->_createDir(MAD_ROOT.'/test/unit/'.dirname($modelFile).'/');
        }
        $this->_tpl->classFile = "models/{$modelName}.php";
        $this->_tpl->package = 'Models';
        $content = $this->_tpl->render('unit_test.php');
        $this->_createFile(MAD_ROOT."/test/unit/{$modelFile}Test.php", $content);

        // create Migration stub
        $this->_generateMigrationStub("create_$tableName");

        // create fixture stub
        $this->_createFile(MAD_ROOT."/test/fixtures/{$tableName}.yml", null);
    }

    /**
     * Generate migration class stubs
     */
    private function _generateMigrationStub($migrationName)
    {
        // create Migration stub
        $this->_tpl->migrationName = Mad_Support_Inflector::camelize($migrationName);
        $content = $this->_tpl->render('migration.php');

        // Find next migration version
        $versions = array();
        foreach (glob(MAD_ROOT."/db/migrate/[0-9]*_*.php") as $file) {
            preg_match_all('/([0-9]+)_([_a-z0-9]*).php/', $file, $matches);
            $versions[] = (int)$matches[1][0];
        }
        natsort($versions);
        $versions = array_reverse($versions);
        $lastVersion = !empty($versions) ? $versions[0] : 0;
        $lastVersion = str_pad($lastVersion, 3, "0", STR_PAD_LEFT);

        // we already made this migration 
        $migrationFile = MAD_ROOT."/db/migrate/{$lastVersion}_{$migrationName}.php";
        if (!file_exists($migrationFile)) {
            $nextVersion = !empty($versions) ? $versions[0] + 1 : 1;
            $nextVersion = str_pad($nextVersion, 3, "0", STR_PAD_LEFT);
            $migrationFile = MAD_ROOT."/db/migrate/{$nextVersion}_{$migrationName}.php";
        }

        $this->_createFile($migrationFile, $content);
    }

    /**
     * Generate controller class stubs
     */
    private function _generateControllerStubs()
    {
        $name = !empty($this->_args) ? array_shift($this->_args) : null;
        if (!$name) {
            $this->_exit("You did not specify the name of the Controller to generate");
        }
        // strip off controller if it's there and camelize
        $name = str_replace('Controller', '', $name);
        $class = Mad_Support_Inflector::camelize($name);

        // CREATE DIRECTORIES
        $this->_createDir(MAD_ROOT.'/app/views/'.$class.'/');

        // CREATE DIRECTORIES
        $this->_createDir(MAD_ROOT.'/test/functional/');

        // CREATE FILES
        $contrName  = $class.'Controller';
        $helperName = $class.'Helper';

        // template files & common vars
        $this->_tpl->author     = $this->_author;
        $this->_tpl->className  = $contrName;
        $this->_tpl->helperName = $helperName;

        // create Controller stub
        $this->_tpl->views = $this->_args;
        $content = $this->_tpl->render('controller.php');
        $this->_createFile(MAD_ROOT."/app/controllers/{$contrName}.php", $content);

        // create Helper stub
        $content = $this->_tpl->render('helper.php');
        $this->_createFile(MAD_ROOT."/app/helpers/{$helperName}.php", $content);

        // create Functional Test stub
        $this->_tpl->classFile = "controllers/{$contrName}.php";
        $this->_tpl->package   = 'Controllers';
        $content = $this->_tpl->render('functional_test.php');
        $this->_createFile(MAD_ROOT."/test/functional/{$contrName}Test.php", $content);
        
        // create view stubs
        foreach ($this->_args as $view) {
          $this->_tpl->class = $class;
          $this->_tpl->view  = $view;
          $content = $this->_tpl->render('view.php');
          $this->_createFile(MAD_ROOT."/app/views/{$class}/{$view}.html", $content);
        }
    }

    /**
     * Generate helper class stubs
     */
    private function _generateHelperStubs()
    {
        $name = !empty($this->_args) ? array_shift($this->_args) : null;
        if (!$name) {
            $this->_exit("You did not specify the name of the Helper to generate");
        }
        // strip off controller if it's there
        $name = str_replace('Helper', '', $name);

        // CREATE FILES
        $class = Mad_Support_Inflector::classify($name);
        $helperName = $class.'Helper';

        // template files & common vars
        $this->_tpl->author = $this->_author;
        $this->_tpl->className = $class;
        $this->_tpl->helperName = $helperName;

        // create Helper stub
        $content = $this->_tpl->render('helper.php');
        $this->_createFile(MAD_ROOT."/app/helpers/{$helperName}.php", $content);
    }

    /**
     * Generate mailer class stubs
     */
    private function _generateMailerStubs()
    {
        $name = !empty($this->_args) ? array_shift($this->_args) : null;
        if (!$name) {
            $this->_exit("You did not specify the name of the Mailer to generate");
        }
        $name = str_replace('Mailer', '', $name);
        $mailerName = Mad_Support_Inflector::camelize($name).'Mailer';

        $this->_tpl->mailerName = $mailerName;
        $content = $this->_tpl->render('mailer.php');
        $this->_createFile(MAD_ROOT."/app/models/{$mailerName}.php", $content);
        
        // CREATE DIRECTORIES
        $this->_createDir(MAD_ROOT.'/app/views/'.$mailerName);
    }

    /*##########################################################################
    # File/Directory creation methods
    ##########################################################################*/

    /**
     * Create directories on the filesystem
     * @param   string  $dir
     */
    private function _createDir($dir)
    {
        if (file_exists($dir)) {
            $this->_print("      exists  $dir");
        } else {
            mkdir($dir, 0777, true);
            $this->_print("      create  $dir");
        }
    }

    /**
     * Create a new file, or overwrite an existing file
     * @param   string  $filepath
     * @param   string  $content
     * @todo mkdir() temporary hack
     */
    private function _createFile($filepath, $content)
    {
        // File exists. Check for diff && prompt user for action
        if (file_exists($filepath)) {
            if (file_get_contents($filepath) == $content) {
                $this->_print("   identical  $filepath");
                return;
            }
            $write = $this->_overwriteAll ? 'Y' : $this->_prompt("overwrite $filepath? [Ynqa] ");

            // overwrite all files
            if ($write == 'a') {
                $this->_overwriteAll = true;
                $write = 'Y';
            }
            // quit script
            if ($write == 'q') {
                $this->_exit();
            // don't overwrite
            } elseif ($write == 'n') {
                $this->_print("        skip    $filepath");
            // overwrite
            } elseif ($write == 'Y') {
                file_put_contents($filepath, $content);
                $this->_print("       force  $filepath");
            }

        // File is new
        } else {
            file_put_contents($filepath, $content);
            $this->_print("      create  $filepath");
        }
    }


    /*##########################################################################
    # Utility methods
    ##########################################################################*/

    /**
     * Display help guidelines
     */
    private function _displayHelp()
    {
        $msg =
          "\tUsage:                                                                     \n".
          "\t 1. Generate controller class                                              \n".
          "\t    generate controller #ControllerName #Views                             \n".
          "\t      eg:                                                                  \n".
          "\t       ./script/generate controller Posts index show edit delete           \n".
          "\t                                                                           \n".
          "\t 2. Generate model class                                                   \n".
          "\t     generate model #ModelName                                             \n".
          "\t       eg:                                                                 \n".
          "\t       ./script/generate model Post                                        \n".
          "\t                                                                           \n".
          "\t 3. This help.                                                             \n".
          "\t     ./script/generate                                                     \n".
          "\n";
        $this->_exit($msg);
    }
}
Return current item: Maintainable PHP Framework