Browse Source

Merge pull request #3393 from markstory/3.0-cell-bake

3.0 cell bake
José Lorenzo Rodríguez 12 years ago
parent
commit
e67b4e7e71

+ 80 - 0
src/Console/Command/Task/CellTask.php

@@ -0,0 +1,80 @@
+<?php
+/**
+ * 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
+ */
+namespace Cake\Console\Command\Task;
+
+use Cake\Console\Command\Task\SimpleBakeTask;
+
+/**
+ * Task for creating cells.
+ */
+class CellTask extends SimpleBakeTask {
+
+/**
+ * Task name used in path generation.
+ *
+ * @var string
+ */
+	public $pathFragment = 'View/Cell/';
+
+/**
+ * {@inheritDoc}
+ */
+	public function name() {
+		return 'cell';
+	}
+
+/**
+ * {@inheritDoc}
+ */
+	public function fileName($name) {
+		return $name . 'Cell.php';
+	}
+
+/**
+ * {@inheritDoc}
+ */
+	public function template() {
+		return 'cell';
+	}
+
+/**
+ * Bake the Cell class and template file.
+ *
+ * @param string $name The name of the cell to make.
+ * @return void
+ */
+	public function bake($name) {
+		$this->bakeTemplate($name);
+		return parent::bake($name);
+	}
+
+/**
+ * Bake an empty file for a cell.
+ *
+ * @param string $name The name of the cell a template is needed for.
+ * @return void
+ */
+	public function bakeTemplate($name) {
+		$templatePath = implode(DS, ['Template', 'Cell', $name, 'display.ctp']);
+		$restore = $this->pathFragment;
+		$this->pathFragment = $templatePath;
+
+		$path = $this->getPath();
+		$this->pathFragment = $restore;
+
+		$this->createFile($path, '');
+	}
+
+}

+ 1 - 1
src/Console/Command/Task/SimpleBakeTask.php

@@ -77,7 +77,7 @@ abstract class SimpleBakeTask extends BakeTask {
 		if (empty($name)) {
 			return $this->error('You must provide a name to bake a ' . $this->name());
 		}
-		$name = Inflector::classify($name);
+		$name = Inflector::camelize($name);
 		$this->bake($name);
 		$this->bakeTest($name);
 	}

+ 7 - 17
src/Console/Command/Task/TestTask.php

@@ -52,6 +52,7 @@ class TestTask extends BakeTask {
 		'Behavior' => 'Model\Behavior',
 		'Helper' => 'View\Helper',
 		'Shell' => 'Console\Command',
+		'Cell' => 'View\Cell',
 	];
 
 /**
@@ -67,6 +68,7 @@ class TestTask extends BakeTask {
 		'behavior' => 'Behavior',
 		'helper' => 'Helper',
 		'shell' => 'Shell',
+		'cell' => 'Cell',
 	];
 
 /**
@@ -376,23 +378,6 @@ class TestTask extends BakeTask {
 	}
 
 /**
- * Interact with the user to get additional fixtures they want to use.
- *
- * @return array Array of fixtures the user wants to add.
- */
-	public function getUserFixtures() {
-		$proceed = $this->in(__d('cake_console', 'Bake could not detect fixtures, would you like to add some?'), ['y', 'n'], 'n');
-		$fixtures = [];
-		if (strtolower($proceed) === 'y') {
-			$fixtureList = $this->in(__d('cake_console', "Please provide a comma separated list of the fixtures names you'd like to use.\nExample: 'app.comment, app.post, plugin.forums.post'"));
-			$fixtureListTrimmed = str_replace(' ', '', $fixtureList);
-			$fixtures = explode(',', $fixtureListTrimmed);
-		}
-		$this->_fixtures = array_merge($this->_fixtures, $fixtures);
-		return $fixtures;
-	}
-
-/**
  * Is a mock class required for this type of test?
  * Controllers require a mock class.
  *
@@ -435,6 +420,11 @@ class TestTask extends BakeTask {
 			$pre = "\$this->io = \$this->getMock('Cake\Console\ConsoleIo');\n";
 			$construct = "new {$className}(\$this->io);\n";
 		}
+		if ($type === 'cell') {
+			$pre = "\$this->request = \$this->getMock('Cake\Network\Request');\n";
+			$pre .= "\t\t\$this->response = \$this->getMock('Cake\Network\Response');\n";
+			$construct = "new {$className}(\$this->request, \$this->response);\n";
+		}
 		return [$pre, $construct, $post];
 	}
 

+ 41 - 0
src/Console/Templates/default/classes/cell.ctp

@@ -0,0 +1,41 @@
+<?php
+/**
+ * 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 "<?php\n"; ?>
+namespace <?= $namespace ?>\View\Cell;
+
+use Cake\View\Cell;
+
+/**
+ * <?= $name ?> cell
+ */
+class <?= $name ?>Cell extends Cell {
+
+/**
+ * List of valid options that can be passed into this
+ * cell's constructor.
+ *
+ * @var array
+ */
+	protected $_validCellOptions = [];
+
+/**
+ * Default display method.
+ *
+ * @return void
+ */
+	public function display() {
+	}
+
+}

+ 14 - 12
src/View/Cell.php

@@ -87,7 +87,7 @@ abstract class Cell {
 	protected $_eventManager = null;
 
 /**
- * These properties are settable directly on Cell and passed to the View as options.
+ * These properties can be set directly on Cell and passed to the View as options.
  *
  * @var array
  * @see \Cake\View\View
@@ -98,6 +98,8 @@ abstract class Cell {
 
 /**
  * List of valid options (constructor's fourth arguments)
+ * Override this property in subclasses to whitelist
+ * which options you want set as properties in your Cell.
  *
  * @var array
  */
@@ -112,7 +114,7 @@ abstract class Cell {
  * @param array $cellOptions
  */
 	public function __construct(Request $request = null, Response $response = null,
-		EventManager $eventManager = null, array $cellOptions = []) {
+			EventManager $eventManager = null, array $cellOptions = []) {
 		$this->_eventManager = $eventManager;
 		$this->request = $request;
 		$this->response = $response;
@@ -126,7 +128,7 @@ abstract class Cell {
 	}
 
 /**
- * Rendering method.
+ * Render the cell.
  *
  * @param string $action Custom template name to render. If not provided (null), the last
  * value will be used. This value is automatically set by `CellTrait::cell()`.
@@ -137,7 +139,14 @@ abstract class Cell {
 			$this->action = $action;
 		}
 
-		return $this->__toString();
+		$this->View = $this->createView();
+
+		$this->View->layout = false;
+		$className = explode('\\', get_class($this));
+		$className = array_pop($className);
+		$this->View->subDir = 'Cell' . DS . substr($className, 0, strpos($className, 'Cell'));
+
+		return $this->View->render(Inflector::underscore($this->action));
 	}
 
 /**
@@ -148,14 +157,7 @@ abstract class Cell {
  * @return string Rendered cell
  */
 	public function __toString() {
-		$this->View = $this->createView();
-
-		$this->View->layout = false;
-		$className = explode('\\', get_class($this));
-		$className = array_pop($className);
-		$this->View->subDir = 'Cell' . DS . substr($className, 0, strpos($className, 'Cell'));
-
-		return $this->View->render(Inflector::underscore($this->action));
+		return $this->render();
 	}
 
 /**

+ 10 - 6
src/View/CellTrait.php

@@ -28,16 +28,20 @@ trait CellTrait {
  *
  * Example:
  *
- *     // Taxonomy\View\Cell\TagCloudCell::smallList()
- *     $cell = $this->cell('Taxonomy.TagCloud::smallList', ['limit' => 10]);
+ * {{{
+ * // Taxonomy\View\Cell\TagCloudCell::smallList()
+ * $cell = $this->cell('Taxonomy.TagCloud::smallList', ['limit' => 10]);
  *
- *     // App\View\Cell\TagCloudCell::smallList()
- *     $cell = $this->cell('TagCloud::smallList', ['limit' => 10]);
+ * // App\View\Cell\TagCloudCell::smallList()
+ * $cell = $this->cell('TagCloud::smallList', ['limit' => 10]);
+ * }}}
  *
  * The `display` action will be used by default when no action is provided:
  *
- *     // Taxonomy\View\Cell\TagCloudCell::display()
- *     $cell = $this->cell('Taxonomy.TagCloud');
+ * {{{
+ * // Taxonomy\View\Cell\TagCloudCell::display()
+ * $cell = $this->cell('Taxonomy.TagCloud');
+ * }}}
  *
  * Cells are not rendered until they are echoed.
  *

+ 2 - 1
tests/TestCase/Console/Command/BakeShellTest.php

@@ -104,7 +104,7 @@ class BakeShellTest extends TestCase {
 			->method('out')
 			->with($this->stringContains('The following commands'));
 
-		$this->Shell->expects($this->exactly(18))
+		$this->Shell->expects($this->exactly(19))
 			->method('out');
 
 		$this->Shell->loadTasks();
@@ -135,6 +135,7 @@ class BakeShellTest extends TestCase {
 		$this->Shell->loadTasks();
 		$expected = [
 			'Behavior',
+			'Cell',
 			'Component',
 			'Controller',
 			'Fixture',

+ 2 - 2
tests/TestCase/Console/Command/CompletionShellTest.php

@@ -164,7 +164,7 @@ class CompletionShellTest extends TestCase {
 		$this->Shell->runCommand(['subcommands', 'CORE.bake']);
 		$output = $this->out->output;
 
-		$expected = "behavior component controller fixture helper model plugin project shell test view widget zerg\n";
+		$expected = "behavior cell component controller fixture helper model plugin project shell test view widget zerg\n";
 		$this->assertEquals($expected, $output);
 	}
 
@@ -229,7 +229,7 @@ class CompletionShellTest extends TestCase {
 		$this->Shell->runCommand(['subcommands', 'bake']);
 		$output = $this->out->output;
 
-		$expected = "behavior component controller fixture helper model plugin project shell test view widget zerg\n";
+		$expected = "behavior cell component controller fixture helper model plugin project shell test view widget zerg\n";
 		$this->assertEquals($expected, $output);
 	}
 

+ 106 - 0
tests/TestCase/Console/Command/Task/CellTaskTest.php

@@ -0,0 +1,106 @@
+<?php
+/**
+ * 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
+ */
+namespace Cake\Test\TestCase\Console\Command\Task;
+
+use Cake\Console\Command\Task\TemplateTask;
+use Cake\Core\Configure;
+use Cake\Core\Plugin;
+use Cake\TestSuite\TestCase;
+
+/**
+ * CellTaskTest class
+ */
+class CellTaskTest extends TestCase {
+
+/**
+ * setup method
+ *
+ * @return void
+ */
+	public function setUp() {
+		parent::setUp();
+		$io = $this->getMock('Cake\Console\ConsoleIo', [], [], '', false);
+
+		$this->Task = $this->getMock(
+			'Cake\Console\Command\Task\CellTask',
+			['in', 'err', 'createFile', '_stop'],
+			[$io]
+		);
+		$this->Task->Test = $this->getMock('Cake\Console\Command\Task\TestTask',
+			[],
+			[$io]
+		);
+		$this->Task->Template = new TemplateTask($io);
+		$this->Task->Template->initialize();
+		$this->Task->Template->interactive = false;
+	}
+
+/**
+ * Test the excute method.
+ *
+ * @return void
+ */
+	public function testMain() {
+		$this->Task->Test->expects($this->once())
+			->method('bake')
+			->with('cell', 'Example');
+
+		$this->Task->expects($this->at(0))
+			->method('createFile')
+			->with(
+				$this->_normalizePath(APP . 'Template/Cell/Example/display.ctp'),
+				''
+			);
+		$this->Task->expects($this->at(1))
+			->method('createFile')
+			->with(
+				$this->_normalizePath(APP . 'View/Cell/ExampleCell.php'),
+				$this->stringContains('class ExampleCell extends Cell')
+			);
+
+		$this->Task->main('Example');
+	}
+
+/**
+ * Test baking within a plugin.
+ *
+ * @return void
+ */
+	public function testMainPlugin() {
+		Plugin::load('TestPlugin');
+
+		$path = Plugin::path('TestPlugin');
+
+		$this->Task->plugin = 'TestPlugin';
+		$this->Task->expects($this->at(0))
+			->method('createFile')
+			->with(
+				$this->_normalizePath($path . 'Template/Cell/Example/display.ctp'),
+				''
+			);
+		$this->Task->expects($this->at(1))
+			->method('createFile')
+			->with(
+				$this->_normalizePath($path . 'View/Cell/ExampleCell.php'),
+				$this->stringContains('class ExampleCell extends Cell')
+			);
+
+		$result = $this->Task->bake('Example');
+		$this->assertContains('namespace TestPlugin\View\Cell;', $result);
+		$this->assertContains('use Cake\View\Cell;', $result);
+		$this->assertContains('class ExampleCell extends Cell {', $result);
+	}
+
+}

+ 23 - 15
tests/TestCase/Console/Command/Task/TestTaskTest.php

@@ -240,21 +240,6 @@ class TestTaskTest extends TestCase {
 	}
 
 /**
- * Test the user interaction for defining additional fixtures.
- *
- * @return void
- */
-	public function testGetUserFixtures() {
-		$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
-		$this->Task->expects($this->at(1))->method('in')
-			->will($this->returnValue('app.pizza, app.topping, app.side_dish'));
-
-		$result = $this->Task->getUserFixtures();
-		$expected = array('app.pizza', 'app.topping', 'app.side_dish');
-		$this->assertEquals($expected, $result);
-	}
-
-/**
  * Dataprovider for class name generation.
  *
  * @return array
@@ -275,6 +260,8 @@ class TestTaskTest extends TestCase {
 			['component', 'AuthComponent', 'App\Controller\Component\AuthComponent'],
 			['Shell', 'Example', 'App\Console\Command\ExampleShell'],
 			['shell', 'Example', 'App\Console\Command\ExampleShell'],
+			['Cell', 'Example', 'App\View\Cell\ExampleCell'],
+			['cell', 'Example', 'App\View\Cell\ExampleCell'],
 		];
 	}
 
@@ -323,6 +310,27 @@ class TestTaskTest extends TestCase {
 	}
 
 /**
+ * Test baking a test for a cell.
+ *
+ * @return void
+ */
+	public function testBakeCellTest() {
+		$this->Task->expects($this->once())
+			->method('createFile')
+			->will($this->returnValue(true));
+
+		$result = $this->Task->bake('Cell', 'Articles');
+
+		$this->assertContains("use App\View\Cell\ArticlesCell", $result);
+		$this->assertContains('class ArticlesCellTest extends TestCase', $result);
+
+		$this->assertContains('function setUp()', $result);
+		$this->assertContains("\$this->request = \$this->getMock('Cake\Network\Request')", $result);
+		$this->assertContains("\$this->response = \$this->getMock('Cake\Network\Response')", $result);
+		$this->assertContains("\$this->Articles = new ArticlesCell(\$this->request, \$this->response", $result);
+	}
+
+/**
  * Test baking a test for a concrete model.
  *
  * @return void