diff --git a/.travis.yml b/.travis.yml index 8d1c3b24..3a7b4cf0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,42 @@ language: php +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + +env: + global: + - DEFAULT=1 + matrix: fast_finish: true include: - php: 7.0 - env: PHPCS=1 + env: PHPCS=1 DEFAULT=0 - php: 7.0 - env: PHPSTAN=1 + env: PHPSTAN=1 DEFAULT=0 before_script: + - if [[ $TRAVIS_PHP_VERSION != 7.0 ]]; then phpenv config-rm xdebug.ini; fi + + - composer install --prefer-dist --no-interaction + - if [[ $PHPCS = 1 ]]; then composer require cakephp/cakephp-codesniffer:dev-master; fi - if [[ $PHPSTAN = 1 ]]; then composer require phpstan/phpstan:^0.8; fi script: + - if [[ $DEFAULT = 1 && $TRAVIS_PHP_VERSION != 7.0 ]]; then vendor/bin/phpunit; fi + - if [[ $DEFAULT = 1 && $TRAVIS_PHP_VERSION = 7.0 ]]; then vendor/bin/phpunit --coverage-clover=clover.xml; fi + - if [[ $PHPCS = 1 ]]; then vendor/bin/phpcs -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ config/; fi - if [[ $PHPSTAN = 1 ]]; then vendor/bin/phpstan analyse -l 5 src; fi +after_success: + - if [[ $DEFAULT = 1 && $TRAVIS_PHP_VERSION = 7.0 ]]; then bash <(curl -s https://codecov.io/bash); fi + notifications: email: false diff --git a/composer.json b/composer.json index fbbb87f5..250ac3e5 100644 --- a/composer.json +++ b/composer.json @@ -35,13 +35,19 @@ }, "require-dev": { "friendsofcake/cakephp-test-utilities": "dev-master", - "markstory/asset_compress": "^3.2" + "markstory/asset_compress": "^3.2", + "phpunit/phpunit": "^5.7|^6.0" }, "autoload": { "psr-4": { "CrudView\\": "src" } }, + "autoload-dev": { + "psr-4": { + "CrudView\\Test\\": "tests" + } + }, "support": { "source": "https://github.com/FriendsOfCake/crud-view", "issues": "https://github.com/FriendsOfCake/crud-view/issues", diff --git a/docs/.editorconfig b/docs/.editorconfig index b10861a8..6511313f 100644 --- a/docs/.editorconfig +++ b/docs/.editorconfig @@ -5,7 +5,7 @@ root = false [*] indent_style = space -indent_size = 2 +indent_size = 4 charset = "utf-8" end_of_line = lf insert_final_newline = true diff --git a/docs/_partials/fields/formatter-callable.rst b/docs/_partials/fields/formatter-callable.rst index b8e941f6..84da1b68 100644 --- a/docs/_partials/fields/formatter-callable.rst +++ b/docs/_partials/fields/formatter-callable.rst @@ -58,3 +58,24 @@ In some cases, it may be useful to access a helper within the callable. For inst } ], ]); + +You can also keep your code DRY by configuring the ``CrudViewHelper`` to use +a callable formatter based on column type. For .e.g. + +.. code-block:: php + + // In controller action or preferably in beforeRender() + $this->viewBuilder()->setHelpers([ + 'CrudView' => [ + 'className' => 'CrudView.CrudView', + 'fieldFormatters' => [ + // Key can be any valid column type of table schema. + 'datetime' => function ($name, $value, $entity, $options, $View) { + return $View->Time->nice($value); + }, + 'boolean' => function ($name, $value, $entity, $options, $View) { + return $value ? 'Yes' : 'No'; + }, + ], + ], + ]); diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 00000000..445791ae --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,37 @@ + + + + + + + + + + ./tests/TestCase + + + + + + + + + + + + + + + + ./src/ + + + diff --git a/src/View/CrudView.php b/src/View/CrudView.php index cb19d3dc..a340c455 100644 --- a/src/View/CrudView.php +++ b/src/View/CrudView.php @@ -3,6 +3,8 @@ use Cake\Core\Configure; use Cake\Core\Plugin; +use Cake\Event\Event; +use Cake\Event\EventListenerInterface; use Cake\View\Exception\MissingTemplateException; use Cake\View\View; use CrudView\Traits\CrudViewConfigTrait; @@ -10,7 +12,7 @@ /** * @property \AssetCompress\View\Helper\AssetCompressHelper $AssetCompress */ -class CrudView extends View +class CrudView extends View implements EventListenerInterface { use CrudViewConfigTrait; @@ -37,9 +39,33 @@ public function initialize() { parent::initialize(); + $this->getEventManager()->on($this, ['priority' => 9]); $this->ensureConfig(); $this->_setupPaths(); $this->_setupHelpers(); + } + + /** + * Events this class is interested in. + * + * @return array + */ + public function implementedEvents() + { + return [ + 'View.beforeLayout' => 'beforeLayout', + ]; + } + + /** + * Handler for View.beforeLayout event. + * + * @param \Cake\Event\Event $event The View.beforeLayout event + * @param string $layoutFileName Layout filename. + * @return void + */ + public function beforeLayout(Event $event, $layoutFileName) + { $this->_loadAssets(); } @@ -83,25 +109,28 @@ protected function _loadAssets() */ protected function _setupHelpers() { - $this->loadHelper('Html', ['className' => 'BootstrapUI.Html']); - $this->loadHelper('Form', [ - 'className' => 'BootstrapUI.Form', - 'widgets' => [ - 'datetime' => ['CrudView\View\Widget\DateTimeWidget', 'select'] - ] - ]); - $this->loadHelper('Flash', ['className' => 'BootstrapUI.Flash']); - $this->loadHelper('Paginator', ['className' => 'BootstrapUI.Paginator']); + $helpers = [ + 'Html' => ['className' => 'BootstrapUI.Html'], + 'Form' => [ + 'className' => 'BootstrapUI.Form', + 'widgets' => [ + 'datetime' => ['CrudView\View\Widget\DateTimeWidget', 'select'] + ], + ], + 'Flash' => ['className' => 'BootstrapUI.Flash'], + 'Paginator' => ['className' => 'BootstrapUI.Paginator'], + 'CrudView' => ['className' => 'CrudView.CrudView'], + ]; + if (class_exists('\Cake\View\Helper\BreadcrumbsHelper')) { - $this->loadHelper('Breadcrumbs', ['className' => 'BootstrapUI.Breadcrumbs']); + $helpers['Breadcrumbs'] = ['className' => 'BootstrapUI.Breadcrumbs']; } - $this->loadHelper('CrudView.CrudView'); - $this->loadHelper('BootstrapUI.Flash'); - if (Configure::read('CrudView.useAssetCompress')) { - $this->loadHelper('AssetCompress.AssetCompress'); + $helpers['AssetCompress'] = ['className' => 'AssetCompress.AssetCompress']; } + + $this->helpers = array_merge($helpers, $this->helpers); } /** diff --git a/src/View/Helper/CrudViewHelper.php b/src/View/Helper/CrudViewHelper.php index e9f71c5a..7d5b7ed8 100644 --- a/src/View/Helper/CrudViewHelper.php +++ b/src/View/Helper/CrudViewHelper.php @@ -32,6 +32,15 @@ class CrudViewHelper extends Helper */ protected $_context; + /** + * Default config. + * + * @var array + */ + protected $_defaultConfig = [ + 'fieldFormatters' => null + ]; + /** * Set context * @@ -123,6 +132,15 @@ public function introspect($field, $value, array $options = []) $type = $this->columnType($field); + $fieldFormatters = $this->getConfig('fieldFormatters'); + if (isset($fieldFormatters[$type])) { + if (is_callable($fieldFormatters[$type])) { + return $fieldFormatters[$type]($field, $value, $this->getContext(), $options, $this->getView()); + } + + return $this->{$fieldFormatters[$type]}($field, $value, $options); + } + if ($type === 'boolean') { return $this->formatBoolean($field, $value, $options); } diff --git a/tests/TestCase/View/CrudViewTest.php b/tests/TestCase/View/CrudViewTest.php new file mode 100644 index 00000000..d059d288 --- /dev/null +++ b/tests/TestCase/View/CrudViewTest.php @@ -0,0 +1,35 @@ + [ + 'CrudView' => [ + 'className' => 'CrudView.CrudView', + 'fieldFormatters' => ['datetime' => 'formatTime'] + ] + ] + ] + ); + + $expected = [ + 'className' => 'CrudView.CrudView', + 'fieldFormatters' => ['datetime' => 'formatTime'], + ]; + $result = $CrudView->CrudView->getConfig(); + $this->assertEquals($expected, $result); + } +} diff --git a/tests/TestCase/View/Helper/CrudViewHelperTest.php b/tests/TestCase/View/Helper/CrudViewHelperTest.php new file mode 100644 index 00000000..e22a9b93 --- /dev/null +++ b/tests/TestCase/View/Helper/CrudViewHelperTest.php @@ -0,0 +1,75 @@ +View = $this->getMockBuilder(View::class) + ->setMethods() + ->getMock(); + + static::setAppNamespace(); + } + + public function testIntrospect() + { + $this->CrudView = $this->getMockBuilder(CrudViewHelper::class) + ->setConstructorArgs([$this->View]) + ->setMethods(['columnType']) + ->getMock(); + + $this->CrudView + ->expects($this->any()) + ->method('columnType') + ->with('created') + ->will($this->returnValue('datetime')); + + $value = new FrozenTime(); + $result = $this->CrudView->introspect('created', $value); + $this->assertEquals('just now', $result); + + $this->CrudView->setConfig('fieldFormatters', [ + 'datetime' => 'formatTime', + ]); + $result = $this->CrudView->introspect('created', $value); + $this->assertEquals($this->CrudView->Time->nice($value), $result); + + $this->CrudView->setConfig('fieldFormatters', [ + 'datetime' => function () { + return 'formatted time'; + }, + ]); + $result = $this->CrudView->introspect('created', $value); + $this->assertEquals('formatted time', $result); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 00000000..4f4d373d --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,26 @@ + dirname(dirname(__FILE__)) . DS]);