[Solar-svn] Revision 3024

pmjones at solarphp.com pmjones at solarphp.com
Thu Mar 20 07:49:59 CDT 2008


Solar_Cli_MakeApp: [NEW] Command-line script to create a new skeleton application.  By specifying --model, it will also create browse/read/edit/add/delete logic and views for you.  Long overdue, and per the request of Nate Abele.


Added: trunk/Solar/Cli/MakeApp/Data/app-model.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/app-model.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/app-model.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,175 @@
+class :class extends :extends {
+    
+    protected $_action_default = 'browse';
+    
+    public $list;
+    
+    public $item;
+    
+    public $form;
+    
+    public function actionBrowse()
+    {
+        // get the model
+        $model = Solar::factory(':model');
+        
+        // get the collection
+        $this->list = $model->fetchAll();
+    }
+    
+    public function actionRead($id = null)
+    {
+        // need an id
+        if (! $id) {
+            return $this->_error('ERR_NO_ID_SPECIFIED');
+        }
+                
+        // get the model
+        $model = Solar::factory(':model');
+        
+        // get the record
+        $item = $model->fetch($id);
+        
+        // does the record exist?
+        if (! $item) {
+            return $this->_error('ERR_NO_SUCH_ITEM');
+        }
+        
+        // done
+        $this->item = $item;
+    }
+    
+    public function actionEdit($id = null)
+    {
+        // process: cancel
+        if ($this->_isProcess('cancel')) {
+            // forward back to reading
+            return $this->_redirect("/{$this->_controller}/read/$id");
+        }
+        
+        // process: delete
+        if ($this->_isProcess('delete')) {
+            // forward to the delete method for confirmation
+            return $this->_redirect("/{$this->_controller}/delete/$id");
+        }
+        
+        // need an id
+        if (! $id) {
+            return $this->_error('ERR_NO_ID_SPECIFIED');
+        }
+        
+        // get the model
+        $model = Solar::factory(':model');
+        
+        // get the record
+        $item = $model->fetch($id);
+        
+        // does the record exist?
+        if (! $item) {
+            return $this->_error('ERR_NO_SUCH_ITEM');
+        }
+        
+        // process: save
+        if ($this->_isProcess('save')) {
+            
+            // what array name should we look for?
+            $model_name = $model->model_name;
+            
+            // get the POST data using the array name
+            $data = $this->_request->post($model_name, array());
+            
+            // load the data to the record
+            $item->load($data);
+            
+            // attempt the save.  this will update the record and
+            // set invalidation messages if it didn't work.
+            $item->save();
+        }
+        
+        // get the form-building hints
+        $form = $item->form();
+        
+        // catch flash indicating a successful add
+        if ($this->_session->getFlash('success_added')) {
+            $form->setStatus(true);
+            $form->feedback = $this->locale('SUCCESS_ADDED');
+        }
+        
+        // done
+        $this->item = $item;
+        $this->form = $form;
+    }
+    
+    public function actionAdd()
+    {
+        // process: cancel
+        if ($this->_isProcess('cancel')) {
+            // forward back to browse
+            return $this->_redirect("/{$this->_controller}/browse");
+        }
+        
+        // get the model
+        $model = Solar::factory(':model');
+        
+        // get a new record
+        $item = $model->fetchNew();
+        
+        // process: save
+        if ($this->_isProcess('save')) {
+            
+            // what array name should we look for?
+            $model_name = $model->model_name;
+            
+            // get the POST data using the array name
+            $data = $this->_request->post($model_name, array());
+            
+            // load the data to the record
+            $item->load($data);
+            
+            // attempt the save.  this will update the record and
+            // set invalidation messages if it didn't work.
+            if ($item->save()) {
+                // save a flash value for the next page
+                $this->_session->setFlash('success_added', true);
+                // redirect to editing.
+                return $this->_redirectNoCache("/{$this->_controller}/edit/{$item->id}");
+            }
+        }
+        
+        // set the item
+        $this->item = $item;
+        
+        // get the form-building hints
+        $this->form = $item->form();
+    }
+    
+    public function actionDelete($id)
+    {
+        // need an id
+        if (! $id) {
+            return $this->_error('ERR_NO_ID_SPECIFIED');
+        }
+        
+        // get the model
+        $model = Solar::factory(':model');
+        
+        // get the record
+        $item = $model->fetch($id);
+        
+        // does the record exist?
+        if (! $item) {
+            return $this->_error('ERR_NO_SUCH_ITEM');
+        }
+        
+        // process: delete confirm
+        if ($this->_isProcess('delete_confirm')) {
+            // delete it
+            $item->delete();
+            // redirect to browse
+            $this->_redirectNoCache("/{$this->_controller}");
+        }
+        
+        // show the item for deletion
+        $this->item = $item;
+    }
+}
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Data/app.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/app.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/app.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,9 @@
+class :class extends :extends {
+    
+    protected $_action_default = 'index';
+    
+    public function actionIndex()
+    {
+        
+    }
+}
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Data/locale.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/locale.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/locale.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,9 @@
+return array(
+    'ERR_NO_SUCH_ITEM'    => 'That item does not exist.',
+    'ERR_NO_ID_SPECIFIED' => 'No ID was specified',
+    'HEADING_BROWSE'      => 'Browse Records',
+    'HEADING_READ'        => 'View Record',
+    'HEADING_EDIT'        => 'Edit Record',
+    'HEADING_ADD'         => 'Add New Record',
+    'HEADING_DELETE'      => 'Delete Record?',
+);
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Data/view-add.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/view-add.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/view-add.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,10 @@
+<h2><?php echo $this->getText('HEADING_ADD'); ?></h2>
+
+<?php echo $this->form()
+                ->auto($this->form)
+                ->addProcessGroup(array(
+                    'save',
+                    'cancel',
+                ))
+                ->fetch();
+?>
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Data/view-browse.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/view-browse.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/view-browse.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,23 @@
+<h2><?php echo $this->getText('HEADING_BROWSE'); ?></h2>
+
+<ol>
+<?php foreach ($this->list as $item): ?>
+    <li><ul>
+    <?php
+        foreach ($item as $key => $val) {
+            echo "<li>" . $this->escape($key) . ": "
+               . $this->escape($val)
+               . "</li>\n";
+        }
+    
+        $id = $item->getPrimaryVal();
+        
+        echo "<li>"
+           . $this->action("{$this->controller}/read/$id", 'ACTION_READ')
+           . "</li>\n";
+    ?>
+    </ul></li>
+<?php endforeach; ?>
+</ol>
+
+<p><?php echo $this->action("{$this->controller}/add", 'ACTION_ADD'); ?>
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Data/view-delete.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/view-delete.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/view-delete.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,14 @@
+<h2><?php echo $this->getText('HEADING_DELETE'); ?></h2>
+
+<ul>
+    <?php foreach ($this->item as $key => $val) {
+        echo "<li>" . $this->escape($key) . ": "
+           . $this->escape($val)
+           . "</li>\n";
+    } ?>
+</ul>
+
+<?php echo $this->form()
+                ->addProcess('delete_confirm')
+                ->fetch()
+?>

Added: trunk/Solar/Cli/MakeApp/Data/view-edit.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/view-edit.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/view-edit.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,16 @@
+<h2><?php echo $this->getText('HEADING_EDIT'); ?></h2>
+
+<p>[ <?php echo $this->action(
+    "/{$this->controller}/read/{$this->item->getPrimaryVal()}",
+    'ACTION_READ');
+?> ]</p>
+
+<?php echo $this->form()
+                ->auto($this->form)
+                ->addProcessGroup(array(
+                    'save',
+                    'cancel',
+                    'delete',
+                ))
+                ->fetch();
+?>
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Data/view-index.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/view-index.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/view-index.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1 @@
+Welcome to your new app.
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Data/view-read.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Data/view-read.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Data/view-read.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,16 @@
+<h2><?php echo $this->getText('HEADING_READ'); ?></h2>
+
+<p>[ <?php echo $this->action("/{$this->controller}", 'ACTION_BROWSE');?> ]</p>
+
+<ul>
+    <?php foreach ($this->item as $key => $val) {
+        echo "<li>" . $this->escape($key) . ": "
+           . $this->escape($val)
+           . "</li>\n";
+    } ?>
+</ul>
+
+<p><?php echo $this->action(
+    "/{$this->controller}/edit/{$this->item->getPrimaryVal()}",
+    'ACTION_EDIT');
+?></p>
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp/Info/options.php
===================================================================
--- trunk/Solar/Cli/MakeApp/Info/options.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp/Info/options.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,18 @@
+<?php
+return array(
+    'target' => array(
+        'long'    => 'table',
+        'descr'   => 'The target directory, typically the PEAR directory.',
+        'param'   => 'optional',
+    ),
+    'extends' => array(
+        'long'    => 'extends',
+        'descr'   => 'Extends from this class name.',
+        'param'   => 'required',
+    ),
+    'model' => array(
+        'long'    => 'model',
+        'descr'   => 'Add this model class automatically.',
+        'param'   => 'required',
+    ),
+);
\ No newline at end of file

Added: trunk/Solar/Cli/MakeApp.php
===================================================================
--- trunk/Solar/Cli/MakeApp.php	                        (rev 0)
+++ trunk/Solar/Cli/MakeApp.php	2008-03-20 12:49:58 UTC (rev 3024)
@@ -0,0 +1,308 @@
+<?php
+/**
+ * 
+ * Solar command to make a page-controller app structure.
+ * 
+ * @category Solar
+ * 
+ * @package Solar_Cli
+ * 
+ * @author Paul M. Jones <pmjones at solarphp.com>
+ * 
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * 
+ * @version $Id: MakeModel.php 2995 2008-03-12 13:58:29Z pmjones $
+ * 
+ */
+class Solar_Cli_MakeApp extends Solar_Cli_Base {
+    
+    /**
+     * 
+     * The base directory where we will write the class file to, typically
+     * the local PEAR directory.
+     * 
+     * @var string
+     * 
+     */
+    protected $_target = null;
+    
+    /**
+     * 
+     * The name of the app class.
+     * 
+     * @var string
+     * 
+     */
+    protected $_class;
+    
+    
+    protected $_class_dir;
+    
+    protected $_class_file;
+    
+    /**
+     * 
+     * What base app to extend?
+     * 
+     * @var string
+     * 
+     */
+    protected $_extends = 'Solar_AppBase';
+    
+    /**
+     * 
+     * Is there one model that we're using?
+     * 
+     * @var string
+     * 
+     */
+    protected $_model = null;
+    
+    /**
+     * 
+     * Array of class templates (skeletons).
+     * 
+     * @var array
+     * 
+     */
+    protected $_tpl = array();
+    
+    /**
+     * 
+     * Write out a series of files and dirs for a page-controller.
+     * 
+     * @param string $class The target class name for the app.
+     * 
+     * @return void
+     * 
+     */
+    protected function _exec($class = null)
+    {
+        // we need a class name, at least
+        if (! $class) {
+            throw $this->_exception('ERR_NO_CLASS');
+        } else {
+            $this->_class = $class;
+        }
+        
+        $this->_outln('Making app.');
+        
+        // we need a target directory
+        $this->_setTarget();
+        
+        // extending a class?
+        $this->_setExtends();
+        
+        // using a model?
+        $this->_setModel();
+        
+        // load the templates
+        $this->_loadTemplates();
+        
+        // the class file locations
+        $this->_class_file = $this->_target
+            . str_replace('_', DIRECTORY_SEPARATOR, $this->_class)
+            . '.php';
+        
+        // the class dir location
+        $this->_class_dir = Solar_Dir::fix(
+            $this->_target . str_replace('_', '/', $this->_class)
+        );
+        
+        // write the app class itself
+        $this->_writeAppClass();
+        
+        // create the View, Locale, Helper, Layout dirs
+        $this->_createDirs();
+        
+        // write Locale/en_US.php
+        $this->_writeLocale();
+        
+        // write files in the View dir
+        $this->_writeViews();
+        
+        // done!
+        $this->_outln("Done.");
+    }
+    
+    protected function _writeAppClass()
+    {
+        // emit feedback
+        $this->_outln("Preparing to write '{$this->_class}' to '{$this->_target}'.");
+        
+        // using app, or app-model?
+        if ($this->_model) {
+            $tpl_key = 'app-model';
+        } else {
+            $tpl_key = 'app';
+        }
+        
+        // get the app class template
+        $text = str_replace(
+            array(':class', ':extends', ':model'),
+            array($this->_class, $this->_extends, $this->_model),
+            $this->_tpl[$tpl_key]
+        );
+        
+        // write the app class
+        if (file_exists($this->_class_file)) {
+            $this->_outln('App class already exists.');
+        } else {
+            $this->_outln('Writing app class.');
+            file_put_contents($this->_class_file, $text);
+        }
+    }
+    
+    protected function _createDirs()
+    {
+        $dir = $this->_class_dir;
+        
+        if (! file_exists($dir)) {
+            $this->_outln('Creating app directory.');
+            mkdir($dir, 0755, true);
+        } else {
+            $this->_outln('App directory exists.');
+        }
+        
+        $list = array('Layout', 'Locale', 'View', 'Helper');
+        
+        foreach ($list as $sub) {
+            if (! file_exists("$dir/$sub")) {
+                $this->_outln("Creating app $sub directory.");
+                mkdir("$dir/$sub", 0755, true);
+            } else {
+                $this->_outln("App $sub directory exists.");
+            }
+        }
+    }
+    
+    protected function _writeLocale()
+    {
+        $text = $this->_tpl['locale'];
+        
+        $file = $this->_class_dir . DIRECTORY_SEPARATOR . "/Locale/en_US.php";
+        if (file_exists($file)) {
+            $this->_outln('Locale file exists.');
+        } else {
+            $this->_outln('Writing locale file.');
+            file_put_contents($file, $text);
+        }
+    }
+    
+    protected function _writeViews()
+    {
+        if (! $this->_model) {
+            $list = array('index');
+        } else {
+            $list = array(
+                'browse',
+                'read',
+                'edit',
+                'add',
+                'delete',
+            );
+        }
+        
+        foreach ($list as $view) {
+            
+            $text = str_replace(
+                array(':class', ':extends', ':model'),
+                array($this->_class, $this->_extends, $this->_model),
+                $this->_tpl["view-$view"]
+            );
+            
+            $file = $this->_class_dir . "/View/$view.php";
+            if (file_exists($file)) {
+                $this->_outln("View '$view' exists.");
+            } else {
+                $this->_outln("Writing '$view' view.");
+                file_put_contents($file, $text);
+            }
+        }
+    }
+    
+    /**
+     * 
+     * Loads the template array from skeleton files.
+     * 
+     * @return void
+     * 
+     */
+    protected function _loadTemplates()
+    {
+        $this->_tpl = array();
+        $dir = Solar_Dir::fix(dirname(__FILE__) . '/MakeApp/Data');
+        $list = glob($dir . '*.php');
+        foreach ($list as $file) {
+            
+            // strip .php off the end of the file name to get the key
+            $key = substr(basename($file), 0, -4);
+            
+            // load the file template
+            $this->_tpl[$key] = file_get_contents($file);
+            
+            // we need to add the php-open tag ourselves, instead of
+            // having it in the template file, becuase the PEAR packager
+            // complains about parsing the skeleton code.
+            // 
+            // however, only do this on non-view files.
+            if (substr($key, 0, 4) != 'view') {
+                $this->_tpl[$key] = "<?php\n" . $this->_tpl[$key];
+            }
+        }
+    }
+    
+    /**
+     * 
+     * Sets the base directory target.
+     * 
+     * @return void
+     * 
+     */
+    protected function _setTarget()
+    {
+        $target = $this->_options['target'];
+        if (! $target) {
+            // use the same target as 2 levels up from this class,
+            // should be the PEAR dir (or main Solar dir)
+            $target = Solar_Dir::name(__FILE__, 2);
+        }
+        
+        $this->_target = Solar_Dir::fix($target);
+    }
+    
+    /**
+     * 
+     * Sets the class this app will extend from.
+     * 
+     * @return void
+     * 
+     */
+    protected function _setExtends()
+    {
+        $extends = $this->_options['extends'];
+        if ($extends) {
+            $this->_extends = $extends;
+        } else {
+            $this->_extends = 'Solar_App_Base';
+        }
+    }
+    
+    /**
+     * 
+     * Sets the model this class will use.
+     * 
+     * @return void
+     * 
+     */
+    protected function _setModel()
+    {
+        $model = $this->_options['model'];
+        if ($model) {
+            $this->_model = $model;
+        } else {
+            $this->_model = null;
+        }
+    }
+}
+




More information about the Solar-svn mailing list