From d8ba6c2aece24278b8c4a53f751a6fd8ae2e4367 Mon Sep 17 00:00:00 2001 From: AD7six Date: Fri, 7 Nov 2014 11:17:28 +0000 Subject: [PATCH] Create Bake View This is a view is to be used mostly (or probably exclusively) via bake, allowing templates to use all view features (helpers, elements) with the goal of simplifying bake template modifications --- src/Shell/Task/BehaviorTask.php | 2 +- src/Shell/Task/CellTask.php | 2 +- src/Shell/Task/ComponentTask.php | 2 +- src/Shell/Task/ControllerTask.php | 4 +- src/Shell/Task/FixtureTask.php | 2 +- src/Shell/Task/HelperTask.php | 2 +- src/Shell/Task/ModelTask.php | 4 +- src/Shell/Task/PluginTask.php | 6 +- src/Shell/Task/ShellTask.php | 2 +- src/Shell/Task/SimpleBakeTask.php | 2 +- src/Shell/Task/TemplateTask.php | 124 ++----------- src/Shell/Task/TestTask.php | 2 +- src/Shell/Task/ViewTask.php | 40 +--- .../actions.ctp} | 74 ++++---- .../classes => Controller}/component.ctp | 11 +- src/Template/Bake/Controller/controller.ctp | 48 +++++ .../Bake/{default/views => Element}/form.ctp | 61 +++--- src/Template/Bake/Element/property.ctp | 18 ++ src/Template/Bake/Layout/default.ctp | 16 ++ .../{default/classes => Model}/behavior.ctp | 11 +- .../{default/classes => Model}/entity.ctp | 32 ++-- .../Bake/{default/classes => Model}/table.ctp | 91 +++++---- .../Bake/{default/classes => Shell}/shell.ctp | 13 +- src/Template/Bake/Template/add.ctp | 16 ++ src/Template/Bake/Template/edit.ctp | 16 ++ .../{default/views => Template}/index.ctp | 58 +++--- src/Template/Bake/Template/view.ctp | 173 ++++++++++++++++++ .../Bake/{default/classes => View}/cell.ctp | 11 +- .../Bake/{default/classes => View}/helper.ctp | 11 +- .../Bake/{default => }/config/routes.ctp | 8 +- .../Bake/default/classes/controller.ctp | 74 -------- src/Template/Bake/default/views/view.ctp | 173 ------------------ .../{default/test => tests}/bootstrap.ctp | 6 +- .../{default/classes => tests}/fixture.ctp | 36 ++-- .../{default/test => tests}/phpunit.xml.ctp | 2 +- .../classes/test.ctp => tests/test_case.ctp} | 62 +++---- src/View/BakeView.php | 153 ++++++++++++++++ src/View/Helper/ClassHelper.php | 44 +++++ tests/TestCase/View/BakeViewTest.php | 81 ++++++++ 39 files changed, 848 insertions(+), 645 deletions(-) rename src/Template/Bake/{default/actions/controller_actions.ctp => Controller/actions.ctp} (57%) rename src/Template/Bake/{default/classes => Controller}/component.ctp (84%) create mode 100644 src/Template/Bake/Controller/controller.ctp rename src/Template/Bake/{default/views => Element}/form.ctp (50%) create mode 100644 src/Template/Bake/Element/property.ctp create mode 100644 src/Template/Bake/Layout/default.ctp rename src/Template/Bake/{default/classes => Model}/behavior.ctp (84%) rename src/Template/Bake/{default/classes => Model}/entity.ctp (73%) rename src/Template/Bake/{default/classes => Model}/table.ctp (62%) rename src/Template/Bake/{default/classes => Shell}/shell.ctp (85%) create mode 100644 src/Template/Bake/Template/add.ctp create mode 100644 src/Template/Bake/Template/edit.ctp rename src/Template/Bake/{default/views => Template}/index.ctp (50%) create mode 100644 src/Template/Bake/Template/view.ctp rename src/Template/Bake/{default/classes => View}/cell.ctp (87%) rename src/Template/Bake/{default/classes => View}/helper.ctp (85%) rename src/Template/Bake/{default => }/config/routes.ctp (89%) delete mode 100644 src/Template/Bake/default/classes/controller.ctp delete mode 100644 src/Template/Bake/default/views/view.ctp rename src/Template/Bake/{default/test => tests}/bootstrap.ctp (57%) rename src/Template/Bake/{default/classes => tests}/fixture.ctp (67%) rename src/Template/Bake/{default/test => tests}/phpunit.xml.ctp (94%) rename src/Template/Bake/{default/classes/test.ctp => tests/test_case.ctp} (56%) create mode 100644 src/View/BakeView.php create mode 100644 src/View/Helper/ClassHelper.php create mode 100644 tests/TestCase/View/BakeViewTest.php diff --git a/src/Shell/Task/BehaviorTask.php b/src/Shell/Task/BehaviorTask.php index 7ad34cb5d3a..338b189005b 100644 --- a/src/Shell/Task/BehaviorTask.php +++ b/src/Shell/Task/BehaviorTask.php @@ -46,7 +46,7 @@ public function fileName($name) { * {@inheritDoc} */ public function template() { - return 'behavior'; + return 'Model/behavior'; } } diff --git a/src/Shell/Task/CellTask.php b/src/Shell/Task/CellTask.php index 673b016fed0..8efa04404cc 100644 --- a/src/Shell/Task/CellTask.php +++ b/src/Shell/Task/CellTask.php @@ -46,7 +46,7 @@ public function fileName($name) { * {@inheritDoc} */ public function template() { - return 'cell'; + return 'View/cell'; } /** diff --git a/src/Shell/Task/ComponentTask.php b/src/Shell/Task/ComponentTask.php index 5705d32f570..d2a15431783 100644 --- a/src/Shell/Task/ComponentTask.php +++ b/src/Shell/Task/ComponentTask.php @@ -46,7 +46,7 @@ public function fileName($name) { * {@inheritDoc} */ public function template() { - return 'component'; + return 'Controller/component'; } } diff --git a/src/Shell/Task/ControllerTask.php b/src/Shell/Task/ControllerTask.php index 5115e48bb62..c9c40f87311 100644 --- a/src/Shell/Task/ControllerTask.php +++ b/src/Shell/Task/ControllerTask.php @@ -99,7 +99,7 @@ public function bakeActions($controllerName) { 'plugin', 'admin', 'pluralName', 'singularName', 'singularHumanName', 'pluralHumanName', 'modelObj', 'currentModelName' )); - $actions = $this->Template->generate('actions', 'controller_actions'); + $actions = $this->Template->generate('Controller/actions'); return $actions; } @@ -161,7 +161,7 @@ public function bakeController($controllerName, array $data) { $this->Template->set($data); - $contents = $this->Template->generate('classes', 'controller'); + $contents = $this->Template->generate('Controller/controller'); $path = $this->getPath(); $filename = $path . $controllerName . 'Controller.php'; diff --git a/src/Shell/Task/FixtureTask.php b/src/Shell/Task/FixtureTask.php index f4a0481dff2..476c5277b2e 100644 --- a/src/Shell/Task/FixtureTask.php +++ b/src/Shell/Task/FixtureTask.php @@ -212,7 +212,7 @@ public function generateFixtureFile($model, array $otherVars) { $this->Template->set('model', $model); $this->Template->set($vars); - $content = $this->Template->generate('classes', 'fixture'); + $content = $this->Template->generate('tests/fixture'); $this->out("\n" . sprintf('Baking test fixture for %s...', $model), 1, Shell::QUIET); $this->createFile($path . $filename, $content); diff --git a/src/Shell/Task/HelperTask.php b/src/Shell/Task/HelperTask.php index 321d1416069..23a02677d95 100644 --- a/src/Shell/Task/HelperTask.php +++ b/src/Shell/Task/HelperTask.php @@ -46,7 +46,7 @@ public function fileName($name) { * {@inheritDoc} */ public function template() { - return 'helper'; + return 'View/helper'; } } diff --git a/src/Shell/Task/ModelTask.php b/src/Shell/Task/ModelTask.php index 4d4adf102db..bfc54020410 100644 --- a/src/Shell/Task/ModelTask.php +++ b/src/Shell/Task/ModelTask.php @@ -594,7 +594,7 @@ public function bakeEntity($model, array $data = []) { ]; $this->Template->set($data); - $out = $this->Template->generate('classes', 'entity'); + $out = $this->Template->generate('Model/entity'); $path = $this->getPath(); $filename = $path . 'Entity' . DS . $name . '.php'; @@ -639,7 +639,7 @@ public function bakeTable($model, array $data = []) { ]; $this->Template->set($data); - $out = $this->Template->generate('classes', 'table'); + $out = $this->Template->generate('Model/table'); $path = $this->getPath(); $filename = $path . 'Table' . DS . $name . 'Table.php'; diff --git a/src/Shell/Task/PluginTask.php b/src/Shell/Task/PluginTask.php index eb3abda3731..9e21c7caee4 100644 --- a/src/Shell/Task/PluginTask.php +++ b/src/Shell/Task/PluginTask.php @@ -189,7 +189,7 @@ protected function _generateRoutes($plugin, $path) { 'plugin' => $plugin, ]); $this->out('Generating routes.php file...'); - $out = $this->Template->generate('config', 'routes'); + $out = $this->Template->generate('config/routes'); $file = $path . $plugin . DS . 'config' . DS . 'routes.php'; $this->createFile($file, $out); } @@ -207,7 +207,7 @@ protected function _generatePhpunitXml($plugin, $path) { 'path' => $path ]); $this->out('Generating phpunit.xml file...'); - $out = $this->Template->generate('test', 'phpunit.xml'); + $out = $this->Template->generate('tests/phpunit.xml'); $file = $path . $plugin . DS . 'phpunit.xml'; $this->createFile($file, $out); } @@ -226,7 +226,7 @@ protected function _generateTestBootstrap($plugin, $path) { 'root' => ROOT ]); $this->out('Generating tests/bootstrap.php file...'); - $out = $this->Template->generate('test', 'bootstrap'); + $out = $this->Template->generate('tests/bootstrap'); $file = $path . $plugin . DS . 'tests' . DS . 'bootstrap.php'; $this->createFile($file, $out); } diff --git a/src/Shell/Task/ShellTask.php b/src/Shell/Task/ShellTask.php index bacd068677f..74c9ffd7afb 100644 --- a/src/Shell/Task/ShellTask.php +++ b/src/Shell/Task/ShellTask.php @@ -46,7 +46,7 @@ public function fileName($name) { * {@inheritDoc} */ public function template() { - return 'shell'; + return 'Shell/shell'; } } diff --git a/src/Shell/Task/SimpleBakeTask.php b/src/Shell/Task/SimpleBakeTask.php index 4784e47af1f..82f779377dc 100644 --- a/src/Shell/Task/SimpleBakeTask.php +++ b/src/Shell/Task/SimpleBakeTask.php @@ -91,7 +91,7 @@ public function main($name = null) { public function bake($name) { $this->Template->set('name', $name); $this->Template->set($this->templateData()); - $contents = $this->Template->generate('classes', $this->template()); + $contents = $this->Template->generate($this->template()); $filename = $this->getPath() . $this->fileName($name); $this->createFile($filename, $contents); diff --git a/src/Shell/Task/TemplateTask.php b/src/Shell/Task/TemplateTask.php index 6e4bf27f4b5..c0078bf9ea7 100644 --- a/src/Shell/Task/TemplateTask.php +++ b/src/Shell/Task/TemplateTask.php @@ -19,6 +19,9 @@ use Cake\Core\ConventionsTrait; use Cake\Core\Plugin; use Cake\Filesystem\Folder; +use Cake\Network\Request; +use Cake\Network\Response; +use Cake\View\BakeView; use Cake\View\ViewVarsTrait; /** @@ -39,135 +42,38 @@ class TemplateTask extends Shell { public $templatePaths = []; /** - * Initialize callback. Setup paths for the template task. + * BakeView instance * - * @return void + * @var Cake\View\BakeView */ - public function initialize() { - $this->templatePaths = $this->_findTemplates(); - } + public $View; /** - * Find the paths to all the installed shell templates in the app. - * - * Bake templates are directories under `Template/Bake` path. - * They are listed in this order: app -> plugin -> default + * Initialize callback. Setup paths for the template task. * - * @return array Array of bake templates that are installed. + * @return void */ - protected function _findTemplates() { - $paths = App::path('Template'); - - $plugins = Plugin::loaded(); - foreach ($plugins as $plugin) { - $paths[] = Plugin::classPath($plugin) . 'Template' . DS; - } - - $core = current(App::core('Template')); - $Folder = new Folder($core . 'Bake' . DS . 'default'); - - $contents = $Folder->read(); - $templateFolders = $contents[0]; - - $paths[] = $core; - - foreach ($paths as $i => $path) { - $paths[$i] = rtrim($path, DS) . DS; - } - - $this->_io->verbose('Found the following bake templates:'); - - $templates = []; - foreach ($paths as $path) { - $Folder = new Folder($path . 'Bake', false); - $contents = $Folder->read(); - $subDirs = $contents[0]; - foreach ($subDirs as $dir) { - $Folder = new Folder($path . 'Bake' . DS . $dir); - $contents = $Folder->read(); - $subDirs = $contents[0]; - if (array_intersect($contents[0], $templateFolders)) { - $templateDir = $path . 'Bake' . DS . $dir . DS; - $templates[$dir] = $templateDir; - - $this->_io->verbose(sprintf("- %s -> %s", $dir, $templateDir)); - } - } - } - return $templates; + public function initialize() { + $this->View = new BakeView(new Request(), new Response()); } /** * Runs the template * - * @param string $directory directory / type of thing you want - * @param string $filename template name + * @param string $template bake template to render * @param array $vars Additional vars to set to template scope. * @return string contents of generated code template */ - public function generate($directory, $filename, $vars = null) { + public function generate($template, $vars = null) { if ($vars !== null) { $this->set($vars); } - if (empty($this->templatePaths)) { + if (empty($this->View)) { $this->initialize(); } - $templatePath = $this->getTemplatePath(); - $templateFile = $this->_findTemplate($templatePath, $directory, $filename); - if ($templateFile) { - extract($this->viewVars); - ob_start(); - ob_implicit_flush(0); - include $templateFile; - $content = ob_get_clean(); - return $content; - } - return ''; - } - -/** - * Find the template name for the current operation. - * If there is only one template in $templatePaths it will be used. - * If there is a -template param in the cli args, it will be used. - * If there is more than one installed template user interaction will happen - * - * @return string returns the path to the selected template. - * @throws \RuntimeException When the chosen template cannot be found. - */ - public function getTemplatePath() { - if (empty($this->params['template'])) { - $this->params['template'] = 'default'; - } - if (!isset($this->templatePaths[$this->params['template']])) { - $msg = sprintf('Unable to locate "%s" bake template', $this->params['template']); - throw new \RuntimeException($msg); - } - $this->_io->verbose(sprintf('Using "%s" bake template', $this->params['template'])); - return $this->templatePaths[$this->params['template']]; - } -/** - * Find a template inside a directory inside a path. - * Will scan all other template dirs if the template is not found in the first directory. - * - * @param string $path The initial path to look for the file on. If it is not found fallbacks will be used. - * @param string $directory Subdirectory to look for ie. 'views', 'objects' - * @param string $filename lower_case_underscored filename you want. - * @return string filename will exit program if template is not found. - */ - protected function _findTemplate($path, $directory, $filename) { - $templateFile = $path . $directory . DS . $filename . '.ctp'; - if (file_exists($templateFile)) { - return $templateFile; - } - foreach ($this->templatePaths as $path) { - $templatePath = $path . $directory . DS . $filename . '.ctp'; - if (file_exists($templatePath)) { - return $templatePath; - } - } - $this->err('Could not find template for %s', $filename); - return false; + $this->View->set($this->viewVars); + return $this->View->render($template); } } diff --git a/src/Shell/Task/TestTask.php b/src/Shell/Task/TestTask.php index 227f517446f..58e6c39c7ee 100644 --- a/src/Shell/Task/TestTask.php +++ b/src/Shell/Task/TestTask.php @@ -202,7 +202,7 @@ public function bake($type, $className) { 'realType', 'preConstruct', 'postConstruct', 'construction', 'uses', 'baseNamespace', 'subNamespace', 'namespace' )); - $out = $this->Template->generate('classes', 'test'); + $out = $this->Template->generate('tests/test_case'); $filename = $this->testCaseFileName($type, $fullClassName); $emptyFile = $this->getPath() . $this->getSubspacePath($type) . DS . 'empty'; diff --git a/src/Shell/Task/ViewTask.php b/src/Shell/Task/ViewTask.php index 89c68977420..5ba793e7c57 100644 --- a/src/Shell/Task/ViewTask.php +++ b/src/Shell/Task/ViewTask.php @@ -365,45 +365,7 @@ public function getContent($action, $vars = null) { $this->Template->set('action', $action); $this->Template->set('plugin', $this->plugin); $this->Template->set($vars); - $template = $this->getTemplate($action); - if ($template) { - return $this->Template->generate('views', $template); - } - return false; - } - -/** - * Gets the template name based on the action name - * - * @param string $action name - * @return string template name - */ - public function getTemplate($action) { - if ($action != $this->template && in_array($action, $this->noTemplateActions)) { - return false; - } - if (!empty($this->template) && $action != $this->template) { - return $this->template; - } - $templatePath = $this->Template->getTemplatePath(); - - if (!empty($this->params['prefix'])) { - $prefixed = Inflector::underscore($this->params['prefix']) . '_' . $action; - if (file_exists($templatePath . 'views/' . $prefixed . '.ctp')) { - return $prefixed; - } - $generic = preg_replace('/(.*)(_add|_edit)$/', '\1_form', $prefixed); - if (file_exists($templatePath . 'views/' . $generic . '.ctp')) { - return $generic; - } - } - if (file_exists($templatePath . 'views/' . $action . '.ctp')) { - return $action; - } - if (in_array($action, ['add', 'edit'])) { - return 'form'; - } - return $action; + return $this->Template->generate("Template/$action"); } /** diff --git a/src/Template/Bake/default/actions/controller_actions.ctp b/src/Template/Bake/Controller/actions.ctp similarity index 57% rename from src/Template/Bake/default/actions/controller_actions.ctp rename to src/Template/Bake/Controller/actions.ctp index 669b720d414..dd4e4b68b09 100644 --- a/src/Template/Bake/default/actions/controller_actions.ctp +++ b/src/Template/Bake/Controller/actions.ctp @@ -1,4 +1,4 @@ -associations()->type('HasOne')), array_map($extractor, $modelObj->associations()->type('HasMany')) ); -?> +%> /** * Index method @@ -40,12 +40,12 @@ $allAssociations = array_merge( * @return void */ public function index() { - +<% if ($belongsTo): %> $this->paginate = [ - 'contain' => [] + 'contain' => [<%= $stringifyList($belongsTo) %>] ]; - - $this->set('', $this->paginate($this->)); +<% endif; %> + $this->set('<%= $pluralName %>', $this->paginate($this-><%= $currentModelName %>)); } /** @@ -56,41 +56,43 @@ $allAssociations = array_merge( * @throws \Cake\Network\Exception\NotFoundException */ public function view($id = null) { - $ = $this->->get($id, [ - 'contain' => [] + $<%= $singularName%> = $this-><%= $currentModelName %>->get($id, [ + 'contain' => [<%= $stringifyList($allAssociations) %>] ]); - $this->set('', $); + $this->set('<%= $singularName %>', $<%= $singularName %>); } - +<% $compact = ["'" . $singularName . "'"]; %> /** * Add method * * @return void */ public function add() { - $ = $this->->newEntity($this->request->data); + $<%= $singularName %> = $this-><%= $currentModelName %>->newEntity($this->request->data); if ($this->request->is('post')) { - if ($this->->save($)) { - $this->Flash->success('The has been saved.'); + if ($this-><%= $currentModelName; %>->save($<%= $singularName %>)) { + $this->Flash->success('The <%= strtolower($singularHumanName) %> has been saved.'); return $this->redirect(['action' => 'index']); } else { - $this->Flash->error('The could not be saved. Please, try again.'); + $this->Flash->error('The <%= strtolower($singularHumanName) %> could not be saved. Please, try again.'); } } -association($assoc); $otherName = $association->target()->alias(); $otherPlural = $this->_variableName($otherName); - echo "\t\t\${$otherPlural} = \$this->{$currentModelName}->{$otherName}->find('list');\n"; - $compact[] = "'{$otherPlural}'"; +%> + $<%= $otherPlural %> = $this-><%= $currentModelName %>-><%= $otherName %>->find('list'); +<% + $compact[] = "'<%= $otherPlural %>'"; endforeach; - echo "\t\t\$this->set(compact(" . join(', ', $compact) . "));\n"; -?> +%> + $this->set(compact(" <%= join(', ', $compact) %> ")); } - +<% $compact = ["'" . $singularName . "'"]; %> /** * Edit method * @@ -99,28 +101,30 @@ $allAssociations = array_merge( * @throws \Cake\Network\Exception\NotFoundException */ public function edit($id = null) { - $ = $this->->get($id, [ - 'contain' => [] + $<%= $singularName %> = $this-><%= $currentModelName %>->get($id, [ + 'contain' => [<%= $stringifyList($belongsToMany) %>] ]); if ($this->request->is(['patch', 'post', 'put'])) { - $ = $this->->patchEntity($, $this->request->data); - if ($this->->save($)) { - $this->Flash->success('The has been saved.'); + $<%= $singularName %> = $this-><%= $currentModelName %>->patchEntity($<%= $singularName %>, $this->request->data); + if ($this-><%= $currentModelName; %>->save($<%= $singularName %>)) { + $this->Flash->success('The <%= strtolower($singularHumanName) %> has been saved.'); return $this->redirect(['action' => 'index']); } else { - $this->Flash->error('The could not be saved. Please, try again.'); + $this->Flash->error('The <%= strtolower($singularHumanName) %> could not be saved. Please, try again.'); } } -association($assoc); $otherName = $association->target()->alias(); $otherPlural = $this->_variableName($otherName); - echo "\t\t\${$otherPlural} = \$this->{$currentModelName}->{$otherName}->find('list');\n"; - $compact[] = "'{$otherPlural}'"; +%> + $<%= $otherPlural %> = $this-><%= $currentModelName %>-><%= $otherName %>->find('list'); +<% + $compact[] = "'<%= $otherPlural %>'"; endforeach; - echo "\t\t\$this->set(compact(" . join(', ', $compact) . "));\n"; - ?> +%> + $this->set(compact(" <%= join(', ', $compact) %> ")); } /** @@ -131,12 +135,12 @@ $allAssociations = array_merge( * @throws \Cake\Network\Exception\NotFoundException */ public function delete($id = null) { - $ = $this->->get($id); + $<%= $singularName %> = $this-><%= $currentModelName %>->get($id); $this->request->allowMethod(['post', 'delete']); - if ($this->->delete($)) { - $this->Flash->success('The has been deleted.'); + if ($this-><%= $currentModelName; %>->delete($<%= $singularName %>)) { + $this->Flash->success('The <%= strtolower($singularHumanName) %> has been deleted.'); } else { - $this->Flash->error('The could not be deleted. Please, try again.'); + $this->Flash->error('The <%= strtolower($singularHumanName) %> could not be deleted. Please, try again.'); } return $this->redirect(['action' => 'index']); } diff --git a/src/Template/Bake/default/classes/component.ctp b/src/Template/Bake/Controller/component.ctp similarity index 84% rename from src/Template/Bake/default/classes/component.ctp rename to src/Template/Bake/Controller/component.ctp index b4c655aab12..be5dfe525fe 100644 --- a/src/Template/Bake/default/classes/component.ctp +++ b/src/Template/Bake/Controller/component.ctp @@ -1,4 +1,4 @@ - -namespace \Controller\Component; +%> +\Controller\Component; use Cake\Controller\Component; use Cake\Controller\ComponentRegistry; /** - * component + * <%= $name %> component */ -class Component extends Component { +class <%= $name %>Component extends Component { /** * Default configuration. diff --git a/src/Template/Bake/Controller/controller.ctp b/src/Template/Bake/Controller/controller.ctp new file mode 100644 index 00000000000..7490e66945f --- /dev/null +++ b/src/Template/Bake/Controller/controller.ctp @@ -0,0 +1,48 @@ +<% +/** + * Controller bake template file + * + * Allows templating of Controllers generated from bake. + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @since 1.3.0 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +use Cake\Utility\Inflector; + +$defaultModel = $name; +%> +\Controller<%= $prefix %>; + +use <%= $namespace %>\Controller\AppController; + +/** + * <%= $name %> Controller + * + * @property <%= $namespace %>\Model\Table\<%= $defaultModel %>Table $<%= $defaultModel %> + +<% foreach ($components as $component): %> + + * @property <%= $component %>Component $<%= $component %> + +<% endforeach; %> + */ +class <%= $name %>Controller extends AppController { +<%= $this->Class->property('helpers', $helpers); %> +<%= $this->Class->property('components', $components); %> +<% if (!empty($actions)): %> + +<% echo trim($actions); %> + +<% endif; %> + +} diff --git a/src/Template/Bake/default/views/form.ctp b/src/Template/Bake/Element/form.ctp similarity index 50% rename from src/Template/Bake/default/views/form.ctp rename to src/Template/Bake/Element/form.ctp index a5ed49475b8..bc0d0cdb8f4 100644 --- a/src/Template/Bake/default/views/form.ctp +++ b/src/Template/Bake/Element/form.ctp @@ -1,4 +1,4 @@ -filter(function($field) use ($schema) { return $schema->columnType($field) !== 'binary'; }); -?> +%>
-

" ?>

+

-
-Form->create(\${$singularVar}) ?>\n" ?> +
+Form->create($<%= $singularVar %>); ?>
- ", Inflector::humanize($action), $singularHumanName) ?> -, <%= $singularHumanName %>) ?> + Form->input('{$field}', ['options' => \${$keyFields[$field]}]);\n"; +%> + echo $this->Form->input('<%= $field %>', ['options' => $<%= $keyFields[$field] %>]); +<% continue; } if (!in_array($field, ['created', 'modified', 'updated'])) { - echo "\t\techo \$this->Form->input('{$field}');\n"; +%> + echo $this->Form->input('<%= $field %>'); +<% } } if (!empty($associations['BelongsToMany'])) { foreach ($associations['BelongsToMany'] as $assocName => $assocData) { - echo "\t\techo \$this->Form->input('{$assocData['property']}._ids', ['options' => \${$assocData['variable']}]);\n"; +%> + echo $this->Form->input('<%= $assocData['property'] %>._ids', ['options' => $<%= $assocData['variable'] %>]); +<% } } - echo "\t?>\n"; -?> +%> + ?>
-Form->button(__('Submit')) ?>\n"; - echo "Form->end() ?>\n"; -?> + Form->button(__('Submit')) ?> + Form->end() ?>
diff --git a/src/Template/Bake/Element/property.ctp b/src/Template/Bake/Element/property.ctp new file mode 100644 index 00000000000..a3906b340bf --- /dev/null +++ b/src/Template/Bake/Element/property.ctp @@ -0,0 +1,18 @@ +<% +use Cake\Utility\Inflector; + +$last = count($value) - 1; +%> + +/** + * <%= Inflector::humanize($name) %> + + * + * @var array + */ + public $<%= $name %> = [ +<% foreach($value as $i => $val): %> + '<%= $val %>'<%= $i < $last ? ',' : ''; %> + +<% endforeach; %> + ]; diff --git a/src/Template/Bake/Layout/default.ctp b/src/Template/Bake/Layout/default.ctp new file mode 100644 index 00000000000..c62311d4bc1 --- /dev/null +++ b/src/Template/Bake/Layout/default.ctp @@ -0,0 +1,16 @@ +<% +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @since 3.0.0 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +%> +<%= $this->fetch('content') %> diff --git a/src/Template/Bake/default/classes/behavior.ctp b/src/Template/Bake/Model/behavior.ctp similarity index 84% rename from src/Template/Bake/default/classes/behavior.ctp rename to src/Template/Bake/Model/behavior.ctp index 60056fc0b4b..024e3b5d297 100644 --- a/src/Template/Bake/default/classes/behavior.ctp +++ b/src/Template/Bake/Model/behavior.ctp @@ -1,4 +1,4 @@ - -namespace \Model\Behavior; +%> +\Model\Behavior; use Cake\ORM\Behavior; use Cake\ORM\Table; /** - * behavior + * <%= $name %> behavior */ -class Behavior extends Behavior { +class <%= $name %>Behavior extends Behavior { /** * Default configuration. diff --git a/src/Template/Bake/default/classes/entity.ctp b/src/Template/Bake/Model/entity.ctp similarity index 73% rename from src/Template/Bake/default/classes/entity.ctp rename to src/Template/Bake/Model/entity.ctp index 50beae1a06d..3a86b71ef8e 100644 --- a/src/Template/Bake/default/classes/entity.ctp +++ b/src/Template/Bake/Model/entity.ctp @@ -1,4 +1,4 @@ - -namespace \Model\Entity; +%> +\Model\Entity; use Cake\ORM\Entity; /** - * Entity. + * <%= $name %> Entity. */ -class extends Entity { +class <%= $name %> extends Entity { - +<% if (!empty($fields)): %> /** * Fields that can be mass assigned using newEntity() or patchEntity(). * * @var array */ protected $_accessible = [ - - '' => true, - +<% foreach ($fields as $field): %> + '<%= $field %>' => true, +<% endforeach; %> ]; - - - +<% if (!empty($hidden)): %> +<% $hidden = array_map(function($el) { return "'$el'"; }, $hidden); -?> +%> /** * Fields that are excluded from JSON an array versions of the entity. * * @var array */ protected $_hidden = [ - + <%= implode(",\n\t\t", $hidden) %> ]; - +<% endif %> } diff --git a/src/Template/Bake/default/classes/table.ctp b/src/Template/Bake/Model/table.ctp similarity index 62% rename from src/Template/Bake/default/classes/table.ctp rename to src/Template/Bake/Model/table.ctp index a805060c648..d4b77bf678b 100644 --- a/src/Template/Bake/default/classes/table.ctp +++ b/src/Template/Bake/Model/table.ctp @@ -1,4 +1,4 @@ - -namespace \Model\Table; +%> +\Model\Table; use Cake\ORM\Query; use Cake\ORM\Table; use Cake\Validation\Validator; /** - * Model + * <%= $name %> Model */ -class Table extends Table { +class <%= $name %>Table extends Table { /** * Initialize method @@ -34,44 +33,44 @@ class Table extends Table { * @return void */ public function initialize(array $config) { - - $this->table(''); - - - $this->displayField(''); - - - + $this->table('<%= $table %>'); +<% endif %> +<% if (!empty($displayField)): %> + $this->displayField('<%= $displayField %>'); +<% endif %> +<% if (!empty($primaryKey)): %> +<% $key = array_map(function($el) { return "'$el'"; }, (array)$primaryKey); -?> - 1): ?> - $this->primaryKey([]); - - $this->primaryKey(); - - - $behaviorData): ?> - $this->addBehavior(''); - - - $assocs): ?> - - - - - - $this->('', [ - $val): ?> - - '$val',\n" ?> - - +%> +<% if (count($primaryKey) > 1): %> + $this->primaryKey([<%= implode(', ', $key) %>]); +<% else: %> + $this->primaryKey(<%= current($key) %>); +<% endif %> +<% endif %> +<% foreach ($behaviors as $behavior => $behaviorData): %> + $this->addBehavior('<%= $behavior %>'<%= $behaviorData ? ", [" . implode(', ', $behaviorData) . ']' : '' %>); +<% endforeach %> +<% $firstAssoc = true; %> +<% foreach ($associations as $type => $assocs): %> +<% foreach ($assocs as $assoc): %> +<% if ($firstAssoc): %> +<%= "\n" %> +<% $firstAssoc = false; %> +<% endif %> + $this-><%= $type %>('<%= $assoc['alias'] %>', [ +<% foreach ($assoc as $key => $val): %> +<% if ($key !== 'alias'): %> + <%= "'$key' => '$val',\n" %> +<% endif %> +<% endforeach %> ]); - - +<% endforeach %> +<% endforeach %> } - +<% if (!empty($validation)): %> /** * Default validation rules. * @@ -80,8 +79,8 @@ $key = array_map(function($el) { return "'$el'"; }, (array)$primaryKey); */ public function validationDefault(Validator $validator) { $validator - - +<% foreach ($validation as $field => $rules): foreach ($rules as $ruleName => $rule): if ($rule['rule'] && !isset($rule['provider'])): @@ -126,12 +125,12 @@ foreach ($validation as $field => $rules): endif; endforeach; endforeach; -?> - +%> +<%= "\t\t\t" . implode("\n\t\t\t", $validationMethods) . ";" %> return $validator; } - +<% endif %> } diff --git a/src/Template/Bake/default/classes/shell.ctp b/src/Template/Bake/Shell/shell.ctp similarity index 85% rename from src/Template/Bake/default/classes/shell.ctp rename to src/Template/Bake/Shell/shell.ctp index 82652df9904..331baf3c811 100644 --- a/src/Template/Bake/default/classes/shell.ctp +++ b/src/Template/Bake/Shell/shell.ctp @@ -1,4 +1,4 @@ - -namespace \Shell; +%> +\Shell; use Cake\Console\Shell; /** - * shell command. + * <%= $name %> shell command. */ -class Shell extends Shell { +class <%= $name %>Shell extends Shell { /** * main() method. diff --git a/src/Template/Bake/Template/add.ctp b/src/Template/Bake/Template/add.ctp new file mode 100644 index 00000000000..428b7f26bda --- /dev/null +++ b/src/Template/Bake/Template/add.ctp @@ -0,0 +1,16 @@ +<% +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @since 3.0.0 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +echo $this->element('form'); diff --git a/src/Template/Bake/Template/edit.ctp b/src/Template/Bake/Template/edit.ctp new file mode 100644 index 00000000000..428b7f26bda --- /dev/null +++ b/src/Template/Bake/Template/edit.ctp @@ -0,0 +1,16 @@ +<% +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @since 3.0.0 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +echo $this->element('form'); diff --git a/src/Template/Bake/default/views/index.ctp b/src/Template/Bake/Template/index.ctp similarity index 50% rename from src/Template/Bake/default/views/index.ctp rename to src/Template/Bake/Template/index.ctp index 14a8812ba56..48f320b637e 100644 --- a/src/Template/Bake/default/views/index.ctp +++ b/src/Template/Bake/Template/index.ctp @@ -1,4 +1,4 @@ -columnType($field), ['binary', 'text']); }) ->take(7); -?> +%>
-

"; ?>

+

<%= "<%= __('Actions') %>"; %>

    -
  • Html->link(__('New " . $singularHumanName . "'), ['action' => 'add']) ?>"; ?>
  • -<%= "<%= \$this->Html->link(__('New " . $singularHumanName . "'), ['action' => 'add']) %>"; %> +<% $done = []; foreach ($associations as $type => $data) { foreach ($data as $alias => $details) { if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { - echo "\t\t
  • Html->link(__('List " . $this->_pluralHumanName($alias) . "'), ['controller' => '{$details['controller']}', 'action' => 'index']) ?>
  • \n"; - echo "\t\t
  • Html->link(__('New " . $this->_singularHumanName($alias) . "'), ['controller' => '{$details['controller']}', 'action' => 'add']) ?>
  • \n"; + echo "\t\t
  • <%= \$this->Html->link(__('List " . $this->_pluralHumanName($alias) . "'), ['controller' => '<%= $details['controller'] %>', 'action' => 'index']) %>
  • \n"; + echo "\t\t
  • <%= \$this->Html->link(__('New " . $this->_singularHumanName($alias) . "'), ['controller' => '<%= $details['controller'] %>', 'action' => 'add']) %>
  • \n"; $done[] = $details['controller']; } } } -?> +%>
-
+
- - - - + <% foreach ($fields as $field): %> + + <% endforeach; %> + - \n"; + <% + echo "<% foreach (\$<%= $pluralVar %> as \$<%= $singularVar %>): %>\n"; echo "\t\t\n"; foreach ($fields as $field) { $isKey = false; @@ -58,43 +58,43 @@ $fields = collection($fields) foreach ($associations['BelongsTo'] as $alias => $details) { if ($field === $details['foreignKey']) { $isKey = true; - echo "\t\t\t\n"; + echo "\t\t\t\n"; break; } } } if ($isKey !== true) { if (!in_array($schema->columnType($field), ['integer', 'biginteger', 'decimal', 'float'])) { - echo "\t\t\t\n"; + echo "\t\t\t\n"; } else { - echo "\t\t\t\n"; + echo "\t\t\t\n"; } } } - $pk = "\${$singularVar}->{$primaryKey[0]}"; + $pk = "\$<%= $singularVar %>-><%= $primaryKey[0] %>"; echo "\t\t\t\n"; echo "\t\t\n"; - echo "\t\n"; - ?> + echo "\t<% endforeach; %>\n"; + %>
Paginator->sort('{$field}') ?>"; ?>"; ?><%= "<%= \$this->Paginator->sort('<%= $field %>') %>"; %><%= "<%= __('Actions') %>"; %>
\n\t\t\t\thas('{$details['property']}') ? \$this->Html->link(\${$singularVar}->{$details['property']}->{$details['displayField']}, ['controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}->{$details['property']}->{$details['primaryKey'][0]}]) : '' ?>\n\t\t\t\n\t\t\t\t<%= \$<%= $singularVar %>->has('<%= $details['property'] %>') ? \$this->Html->link(\$<%= $singularVar %>-><%= $details['property'] %>-><%= $details['displayField'] %>, ['controller' => '<%= $details['controller'] %>', 'action' => 'view', \$<%= $singularVar %>-><%= $details['property'] %>-><%= $details['primaryKey'][0] %>]) : '' %>\n\t\t\t{$field}) ?><%= h(\$<%= $singularVar %>-><%= $field %>) %>Number->format(\${$singularVar}->{$field}) ?><%= \$this->Number->format(\$<%= $singularVar %>-><%= $field %>) %>\n"; - echo "\t\t\t\tHtml->link(__('View'), ['action' => 'view', {$pk}]) ?>\n"; - echo "\t\t\t\tHtml->link(__('Edit'), ['action' => 'edit', {$pk}]) ?>\n"; - echo "\t\t\t\tForm->postLink(__('Delete'), ['action' => 'delete', {$pk}], ['confirm' => __('Are you sure you want to delete # {0}?', {$pk})]) ?>\n"; + echo "\t\t\t\t<%= \$this->Html->link(__('View'), ['action' => 'view', <%= $pk %>]) %>\n"; + echo "\t\t\t\t<%= \$this->Html->link(__('Edit'), ['action' => 'edit', <%= $pk %>]) %>\n"; + echo "\t\t\t\t<%= \$this->Form->postLink(__('Delete'), ['action' => 'delete', <%= $pk %>], ['confirm' => __('Are you sure you want to delete # <%= 0 %>?', <%= $pk %>)]) %>\n"; echo "\t\t\t
    - Paginator->prev('< ' . __('previous'));\n"; echo "\t\t\techo \$this->Paginator->numbers();\n"; echo "\t\t\techo \$this->Paginator->next(__('next') . ' >');\n"; - echo "\t\t?>\n"; - ?> + echo "\t\t%>\n"; + %>
-

Paginator->counter() ?>"; ?>

+

<%= "<%= \$this->Paginator->counter() %>"; %>

diff --git a/src/Template/Bake/Template/view.ctp b/src/Template/Bake/Template/view.ctp new file mode 100644 index 00000000000..8608ab30f53 --- /dev/null +++ b/src/Template/Bake/Template/view.ctp @@ -0,0 +1,173 @@ +<% +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @since 1.2.0 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +use Cake\Utility\Inflector; + +$associations += ['BelongsTo' => [], 'HasOne' => [], 'HasMany' => [], 'BelongsToMany' => []]; +$immediateAssociations = $associations['BelongsTo'] + $associations['HasOne']; +$associationFields = collection($fields) + ->map(function($field) use ($immediateAssociations) { + foreach ($immediateAssociations as $alias => $details) { + if ($field === $details['foreignKey']) { + return [$field => $details]; + } + } + }) + ->filter() + ->reduce(function($fields, $value) { + return $fields + $value; + }, []); + +$groupedFields = collection($fields) + ->filter(function($field) use ($schema) { + return $schema->columnType($field) !== 'binary'; + }) + ->groupBy(function($field) use ($schema, $associationFields) { + $type = $schema->columnType($field); + if (isset($associationFields[$field])) { + return 'string'; + } + if (in_array($type, ['integer', 'float', 'decimal', 'biginteger'])) { + return 'number'; + } + if (in_array($type, ['date', 'time', 'datetime', 'timestamp'])) { + return 'date'; + } + return in_array($type, ['text', 'boolean']) ? $type : 'string'; + }) + ->toArray(); + +$groupedFields += ['number' => [], 'string' => [], 'boolean' => [], 'date' => [], 'text' => []]; +%> +
+

<%= "<%= __('Actions') %>" %>

+
    +<% + $pk = "\$<%= $singularVar %>-><%= $primaryKey[0] %>"; + + echo "\t\t
  • <%= \$this->Html->link(__('Edit " . $singularHumanName . "'), ['action' => 'edit', <%= $pk %>]) %>
  • \n"; + echo "\t\t
  • <%= \$this->Form->postLink(__('Delete " . $singularHumanName . "'), ['action' => 'delete', <%= $pk %>], ['confirm' => __('Are you sure you want to delete # <%= 0 %>?', <%= $pk %>)]) %>
  • \n"; + echo "\t\t
  • <%= \$this->Html->link(__('List " . $pluralHumanName . "'), ['action' => 'index']) %>
  • \n"; + echo "\t\t
  • <%= \$this->Html->link(__('New " . $singularHumanName . "'), ['action' => 'add']) %>
  • \n"; + + $done = []; + foreach ($associations as $type => $data) { + foreach ($data as $alias => $details) { + if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { + echo "\t\t
  • <%= \$this->Html->link(__('List " . $this->_pluralHumanName($alias) . "'), ['controller' => '<%= $details['controller'] %>', 'action' => 'index']) %>
  • \n"; + echo "\t\t
  • <%= \$this->Html->link(__('New " . Inflector::humanize(Inflector::singularize(Inflector::underscore($alias))) . "'), ['controller' => '<%= $details['controller'] %>', 'action' => 'add']) %>
  • \n"; + $done[] = $details['controller']; + } + } + } +%> +
+
+
+

<%= "<%= h(\$<%= $singularVar %>-><%= $displayField %>) %>"; %>

+
+<% if ($groupedFields['string']) : %> +
+<% foreach ($groupedFields['string'] as $field) : %> +<% if (isset($associationFields[$field])) : + $details = $associationFields[$field]; +%> +
<%= "<%= __('" . Inflector::humanize($details['property']) . "') %>" %>
+

<%= "<%= \$<%= $singularVar %>->has('<%= $details['property'] %>') ? \$this->Html->link(\$<%= $singularVar %>-><%= $details['property'] %>-><%= $details['displayField'] %>, ['controller' => '<%= $details['controller'] %>', 'action' => 'view', \$<%= $singularVar %>-><%= $details['property'] %>-><%= $details['primaryKey'][0] %>]) : '' %>" %>

+<% else : %> +
<%= "<%= __('" . Inflector::humanize($field) . "') %>" %>
+

<%= "<%= h(\$<%= $singularVar %>-><%= $field %>) %>" %>

+<% endif; %> +<% endforeach; %> +
+<% endif; %> +<% if ($groupedFields['number']) : %> +
+<% foreach ($groupedFields['number'] as $field) : %> +
<%= "<%= __('" . Inflector::humanize($field) . "') %>" %>
+

<%= "<%= \$this->Number->format(\$<%= $singularVar %>-><%= $field %>) %>" %>

+<% endforeach; %> +
+<% endif; %> +<% if ($groupedFields['date']) : %> +
+<% foreach ($groupedFields['date'] as $field) : %> +
<%= "<%= __('" . Inflector::humanize($field) . "') %>" %>
+

<%= "<%= h(\$<%= $singularVar %>-><%= $field %>) %>" %>

+<% endforeach; %> +
+<% endif; %> +<% if ($groupedFields['boolean']) : %> +
+<% foreach ($groupedFields['boolean'] as $field) : %> +
<%= "<%= __('" . Inflector::humanize($field) . "') %>" %>
+

<%= "<%= \$<%= $singularVar %>-><%= $field %> ? __('Yes') : __('No'); %>" %>

+<% endforeach; %> +
+<% endif; %> +
+<% if ($groupedFields['text']) : %> +<% foreach ($groupedFields['text'] as $field) : %> +
+
+
<%= "<%= __('" . Inflector::humanize($field) . "') %>" %>
+ <%= "<%= \$this->Text->autoParagraph(h(\$<%= $singularVar %>-><%= $field %>)); %>"; %> + +
+
+<% endforeach; %> +<% endif; %> +
+<% +$relations = $associations['HasMany'] + $associations['BelongsToMany']; +foreach ($relations as $alias => $details): + $otherSingularVar = Inflector::variable($alias); + $otherPluralHumanName = Inflector::humanize($details['controller']); + %> + +<% endforeach; %> diff --git a/src/Template/Bake/default/classes/cell.ctp b/src/Template/Bake/View/cell.ctp similarity index 87% rename from src/Template/Bake/default/classes/cell.ctp rename to src/Template/Bake/View/cell.ctp index 0bd11809e79..0e2e77b8c5d 100644 --- a/src/Template/Bake/default/classes/cell.ctp +++ b/src/Template/Bake/View/cell.ctp @@ -1,4 +1,4 @@ - -namespace \View\Cell; +%> +\View\Cell; use Cake\View\Cell; /** - * cell + * <%= $name %> cell */ -class Cell extends Cell { +class <%= $name %>Cell extends Cell { /** * List of valid options that can be passed into this diff --git a/src/Template/Bake/default/classes/helper.ctp b/src/Template/Bake/View/helper.ctp similarity index 85% rename from src/Template/Bake/default/classes/helper.ctp rename to src/Template/Bake/View/helper.ctp index 5f0e4abf4e7..d3fa5600aa0 100644 --- a/src/Template/Bake/default/classes/helper.ctp +++ b/src/Template/Bake/View/helper.ctp @@ -1,4 +1,4 @@ - -namespace \View\Helper; +%> +\View\Helper; use Cake\View\Helper; use Cake\View\View; /** - * helper + * <%= $name %> helper */ -class Helper extends Helper { +class <%= $name %>Helper extends Helper { /** * Default configuration. diff --git a/src/Template/Bake/default/config/routes.ctp b/src/Template/Bake/config/routes.ctp similarity index 89% rename from src/Template/Bake/default/config/routes.ctp rename to src/Template/Bake/config/routes.ctp index 62440c7d6f6..dd676301018 100644 --- a/src/Template/Bake/default/config/routes.ctp +++ b/src/Template/Bake/config/routes.ctp @@ -1,4 +1,4 @@ - +%> +', function($routes) { +Router::plugin('<%= $plugin %>', function($routes) { $routes->fallbacks(); }); diff --git a/src/Template/Bake/default/classes/controller.ctp b/src/Template/Bake/default/classes/controller.ctp deleted file mode 100644 index 79cd1fe13c9..00000000000 --- a/src/Template/Bake/default/classes/controller.ctp +++ /dev/null @@ -1,74 +0,0 @@ - -namespace \Controller; - -use \Controller\AppController; - -/** - * Controller - * - - */ -class Controller extends AppController { - - -} diff --git a/src/Template/Bake/default/views/view.ctp b/src/Template/Bake/default/views/view.ctp deleted file mode 100644 index 00b6845cd83..00000000000 --- a/src/Template/Bake/default/views/view.ctp +++ /dev/null @@ -1,173 +0,0 @@ - [], 'HasOne' => [], 'HasMany' => [], 'BelongsToMany' => []]; -$immediateAssociations = $associations['BelongsTo'] + $associations['HasOne']; -$associationFields = collection($fields) - ->map(function($field) use ($immediateAssociations) { - foreach ($immediateAssociations as $alias => $details) { - if ($field === $details['foreignKey']) { - return [$field => $details]; - } - } - }) - ->filter() - ->reduce(function($fields, $value) { - return $fields + $value; - }, []); - -$groupedFields = collection($fields) - ->filter(function($field) use ($schema) { - return $schema->columnType($field) !== 'binary'; - }) - ->groupBy(function($field) use ($schema, $associationFields) { - $type = $schema->columnType($field); - if (isset($associationFields[$field])) { - return 'string'; - } - if (in_array($type, ['integer', 'float', 'decimal', 'biginteger'])) { - return 'number'; - } - if (in_array($type, ['date', 'time', 'datetime', 'timestamp'])) { - return 'date'; - } - return in_array($type, ['text', 'boolean']) ? $type : 'string'; - }) - ->toArray(); - -$groupedFields += ['number' => [], 'string' => [], 'boolean' => [], 'date' => [], 'text' => []]; -?> -
-

" ?>

-
    -{$primaryKey[0]}"; - - echo "\t\t
  • Html->link(__('Edit " . $singularHumanName . "'), ['action' => 'edit', {$pk}]) ?>
  • \n"; - echo "\t\t
  • Form->postLink(__('Delete " . $singularHumanName . "'), ['action' => 'delete', {$pk}], ['confirm' => __('Are you sure you want to delete # {0}?', {$pk})]) ?>
  • \n"; - echo "\t\t
  • Html->link(__('List " . $pluralHumanName . "'), ['action' => 'index']) ?>
  • \n"; - echo "\t\t
  • Html->link(__('New " . $singularHumanName . "'), ['action' => 'add']) ?>
  • \n"; - - $done = []; - foreach ($associations as $type => $data) { - foreach ($data as $alias => $details) { - if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { - echo "\t\t
  • Html->link(__('List " . $this->_pluralHumanName($alias) . "'), ['controller' => '{$details['controller']}', 'action' => 'index']) ?>
  • \n"; - echo "\t\t
  • Html->link(__('New " . Inflector::humanize(Inflector::singularize(Inflector::underscore($alias))) . "'), ['controller' => '{$details['controller']}', 'action' => 'add']) ?>
  • \n"; - $done[] = $details['controller']; - } - } - } -?> -
-
-
-

{$displayField}) ?>"; ?>

-
- -
- - -
" ?>
-

has('{$details['property']}') ? \$this->Html->link(\${$singularVar}->{$details['property']}->{$details['displayField']}, ['controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}->{$details['property']}->{$details['primaryKey'][0]}]) : '' ?>" ?>

- -
" ?>
-

{$field}) ?>" ?>

- - -
- - -
- -
" ?>
-

Number->format(\${$singularVar}->{$field}) ?>" ?>

- -
- - -
- -
" ?>
-

{$field}) ?>" ?>

- -
- - -
- -
" ?>
-

{$field} ? __('Yes') : __('No'); ?>" ?>

- -
- -
- - -
-
-
" ?>
- Text->autoParagraph(h(\${$singularVar}->{$field})); ?>"; ?> - -
-
- - -
- $details): - $otherSingularVar = Inflector::variable($alias); - $otherPluralHumanName = Inflector::humanize($details['controller']); - ?> - - diff --git a/src/Template/Bake/default/test/bootstrap.ctp b/src/Template/Bake/tests/bootstrap.ctp similarity index 57% rename from src/Template/Bake/default/test/bootstrap.ctp rename to src/Template/Bake/tests/bootstrap.ctp index 388eb47d9d5..5a7b022e022 100644 --- a/src/Template/Bake/default/test/bootstrap.ctp +++ b/src/Template/Bake/tests/bootstrap.ctp @@ -1,7 +1,7 @@ - +. + * Test suite bootstrap for <%= $plugin %>. */ // Customize this to be a relative path for embedded plugins. // For standalone plugins, this should point at a CakePHP installation. -require '/config/bootstrap.php'; +require '<%= $root %>/config/bootstrap.php'; diff --git a/src/Template/Bake/default/classes/fixture.ctp b/src/Template/Bake/tests/fixture.ctp similarity index 67% rename from src/Template/Bake/default/classes/fixture.ctp rename to src/Template/Bake/tests/fixture.ctp index adb8eafe78c..606fff2d89d 100644 --- a/src/Template/Bake/default/classes/fixture.ctp +++ b/src/Template/Bake/tests/fixture.ctp @@ -1,4 +1,4 @@ - - -namespace \Test\Fixture; +%> +\Test\Fixture; use Cake\TestSuite\Fixture\TestFixture; /** - * Fixture + * <%= $name %>Fixture * */ -class Fixture extends TestFixture { +class <%= $name %>Fixture extends TestFixture { - +<% if ($table): %> /** * Table name * * @var string */ - public $table = ''; + public $table = '<%= $table %>'; - - +<% endif; %> +<% if ($import): %> /** * Import * * @var array */ - public $import = ; + public $import = <%= $import %>; - - +<% endif; %> +<% if ($schema): %> /** * Fields * * @var array */ - public $fields = ; + public $fields = <%= $schema %>; - - +<% endif; %> +<% if ($records): %> /** * Records * * @var array */ - public $records = ; + public $records = <%= $records %>; - +<% endif; %> } diff --git a/src/Template/Bake/default/test/phpunit.xml.ctp b/src/Template/Bake/tests/phpunit.xml.ctp similarity index 94% rename from src/Template/Bake/default/test/phpunit.xml.ctp rename to src/Template/Bake/tests/phpunit.xml.ctp index f029e94d81e..d14a35a728c 100644 --- a/src/Template/Bake/default/test/phpunit.xml.ctp +++ b/src/Template/Bake/tests/phpunit.xml.ctp @@ -13,7 +13,7 @@ - + ./tests/TestCase diff --git a/src/Template/Bake/default/classes/test.ctp b/src/Template/Bake/tests/test_case.ctp similarity index 56% rename from src/Template/Bake/default/classes/test.ctp rename to src/Template/Bake/tests/test_case.ctp index e624872ce0a..98320515ecf 100644 --- a/src/Template/Bake/default/classes/test.ctp +++ b/src/Template/Bake/tests/test_case.ctp @@ -1,4 +1,4 @@ - -namespace \Test\TestCase\; +%> +\Test\TestCase\<%= $subNamespace %>; - -use ; - - +<% foreach ($uses as $dependency): %> +use <%= $dependency; %>; +<% endforeach; %> +<% if ($isController): %> use Cake\TestSuite\IntegrationTestCase; - +<% else: %> use Cake\TestSuite\TestCase; - +<% endif; %> /** - * Test Case + * <%= $fullClassName %> Test Case */ - -class Test extends IntegrationTestCase { - -class Test extends TestCase { - +<% if ($isController): %> +class <%= $className %>Test extends IntegrationTestCase { +<% else: %> +class <%= $className %>Test extends TestCase { +<% endif; %> - +<% if (!empty($fixtures)): %> /** * Fixtures * * @var array */ public $fixtures = [ - '' + '<%= join("',\n\t\t'", $fixtures); %>' ]; - - +<% endif; %> +<% if (!empty($construction)): %> /** * setUp method * @@ -58,9 +58,9 @@ class Test extends TestCase { */ public function setUp() { parent::setUp(); - - $this-> - +<%= $preConstruct ? "\t\t" . $preConstruct : '' %> + $this-><%= $subject . ' = ' . $construction %> +<%= $postConstruct ? "\t\t" . $postConstruct : '' %> } /** @@ -69,24 +69,24 @@ class Test extends TestCase { * @return void */ public function tearDown() { - unset($this->); + unset($this-><%= $subject %>); parent::tearDown(); } - - +<% endif; %> +<% foreach ($methods as $method): %> /** - * Test method + * Test <%= $method %> method * * @return void */ - public function test() { + public function test<%= Inflector::camelize($method) %>() { $this->markTestIncomplete('Not implemented yet.'); } - - +<% endforeach; %> +<% if (empty($methods)): %> /** * Test initial setup * @@ -96,5 +96,5 @@ class Test extends TestCase { $this->markTestIncomplete('Not implemented yet.'); } - +<% endif; %> } diff --git a/src/View/BakeView.php b/src/View/BakeView.php new file mode 100644 index 00000000000..97dcbfce4ea --- /dev/null +++ b/src/View/BakeView.php @@ -0,0 +1,153 @@ +_getViewFileName($view); + + $this->_currentType = static::TYPE_VIEW; + $this->dispatchEvent('View.beforeRender', [$viewFileName]); + $this->Blocks->set('content', $this->_render($viewFileName)); + $this->dispatchEvent('View.afterRender', [$viewFileName]); + + if ($layout === null) { + $layout = $this->layout; + } + if ($layout && $this->autoLayout) { + $this->Blocks->set('content', $this->renderLayout('', $layout)); + } + + return $this->Blocks->get('content'); + } + +/** + * Sandbox method to evaluate a template / view script in. + * + * @param string $viewFile Filename of the view + * @param array $dataForView Data to include in rendered view. + * If empty the current View::$viewVars will be used. + * @return string Rendered output + */ + protected function _evaluate($viewFile, $dataForView) { + $viewString = $this->_getViewFileContents($viewFile); + + $randomString = sha1($viewString); + $unPhp = [ + ' "<$randomString=", + ' "<$randomString", + ' ?>' => " $randomString>" + ]; + $templatify = [ + '<%=' => ' '' => '?>' + ]; + + $viewString = str_replace(array_keys($unPhp), array_values($unPhp), $viewString); + $viewString = str_replace(array_keys($templatify), array_values($templatify), $viewString); + + $this->__viewFile = TMP . $randomString . '.php'; + file_put_contents($this->__viewFile, $viewString); + + unset($randomString, $templatify, $viewFile, $viewString); + extract($dataForView); + ob_start(); + + include $this->__viewFile; + + unset($this->__viewFile); + + return str_replace(array_values($unPhp), array_keys($unPhp), ob_get_clean()); + } + +/** + * Returns filename of given template file (.ctp) as a string. + * CamelCased template names will be under_scored! This means that you can have + * LongTemplateNames that refer to long_template_names.ctp views. + * + * Also allows rendering a template string directly + * + * @param string $name Controller action to find template filename for + * @return string Template filename or a Bake template string + * @throws \Cake\View\Exception\MissingTemplateException when a view file could not be found. + */ + protected function _getViewFileName($name = null) { + if (strpos($name, '<') !== false) { + return $name; + } + return parent::_getViewFileName($name); + } + +/** + * Get the contents of the template file + * + * @param string $name A template name or a Bake template string + * @return string Bake template to evaluate + */ + protected function _getViewFileContents($name) { + if (strpos($name, '<') !== false) { + return $name; + } + + $filename = $this->_getViewFileName($name); + return file_get_contents($filename); + } + +/** + * Return all possible paths to find view files in order + * + * @param string $plugin Optional plugin name to scan for view files. + * @param bool $cached Set to false to force a refresh of view paths. Default true. + * @return array paths + */ + protected function _paths($plugin = null, $cached = true) { + $paths = parent::_paths($plugin, false); + foreach($paths as &$path) { + $path .= 'Bake' . DS; + } + return $paths; + } +} diff --git a/src/View/Helper/ClassHelper.php b/src/View/Helper/ClassHelper.php new file mode 100644 index 00000000000..0ee625d2106 --- /dev/null +++ b/src/View/Helper/ClassHelper.php @@ -0,0 +1,44 @@ + $name, + 'value' => $value + ]; + return $this->_View->element('property', $params); + } + +} diff --git a/tests/TestCase/View/BakeViewTest.php b/tests/TestCase/View/BakeViewTest.php new file mode 100644 index 00000000000..141ddfd5ffb --- /dev/null +++ b/tests/TestCase/View/BakeViewTest.php @@ -0,0 +1,81 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @since 1.2.0 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Cake\Test\TestCase\View; + +use Cake\Network\Request; +use Cake\Network\Response; +use Cake\TestSuite\TestCase; +use Cake\View\BakeView; + +/** + * BakeViewTest class + * + */ +class BakeViewTest extends TestCase { + +/** + * setUp method + * + * @return void + */ + public function setUp() { + parent::setUp(); + + $request = new Request(); + $response = new Response(); + $this->View = new BakeView($request, $response); + } + +/** + * tearDown method + * + * @return void + */ + public function tearDown() { + parent::tearDown(); + unset($this->View); + } + + public function testRenderString() { + $template = 'The value of aVariable is: <%= $aVariable %>.'; + + $this->View->set(['aVariable' => 123]); + $result = $this->View->render($template); + $expected = 'The value of aVariable is: 123.'; + + $this->assertSame($expected, $result, 'variables in erb-style tags should be evaluated'); + } + + public function testRenderIgnorePhpTags() { + $template = 'The value of aVariable is: <%= $aVariable %>. Not .'; + + $this->View->set(['aVariable' => 123]); + $result = $this->View->render($template); + $expected = 'The value of aVariable is: 123. Not .'; + + $this->assertSame($expected, $result, 'variables in php tags should be treated as strings'); + } + + public function testRenderIgnorePhpShortTags() { + $template = 'The value of aVariable is: <%= $aVariable %>. Not .'; + + $this->View->set(['aVariable' => 123]); + $result = $this->View->render($template); + $expected = 'The value of aVariable is: 123. Not .'; + + $this->assertSame($expected, $result, 'variables in php tags should be treated as strings'); + } + +}