[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