Skip to content

Instantly share code, notes, and snippets.

@tai-sho
Created December 8, 2019 17:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tai-sho/596dbea45f3c8727b839667c1c3d6c19 to your computer and use it in GitHub Desktop.
Save tai-sho/596dbea45f3c8727b839667c1c3d6c19 to your computer and use it in GitHub Desktop.
bake with generation gap pattern
{#
/**
* 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 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#}
{% set propertyHintMap = DocBlock.buildEntityPropertyHintTypeMap(propertySchema ?: []) %}
{% set associationHintMap = DocBlock.buildEntityAssociationHintTypeMap(propertySchema ?: []) %}
{% set annotations = DocBlock.propertyHints(propertyHintMap) %}
{%- if associationHintMap %}
{%- set annotations = annotations|merge(['']) %}
{%- set annotations = annotations|merge(DocBlock.propertyHints(associationHintMap)) %}
{% endif %}
{%- set accessible = Bake.getFieldAccessibility(fields, primaryKey) %}
<?php
namespace {{ namespace }}\Model\Entity\Baked;
use Cake\ORM\Entity;
{{ DocBlock.classDescription(name, 'Entity', annotations)|raw }}
class {{ name }} extends Entity
{
{% if accessible %}
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array
*/
protected $_accessible = [{{ Bake.stringifyList(accessible, {'quotes': false})|raw }}];
{% endif %}
{%- if hidden %}
/**
* Fields that are excluded from JSON versions of the entity.
*
* @var array
*/
protected $_hidden = [{{ Bake.stringifyList(hidden)|raw }}];
{% endif %}
{%- if not accessible and not hidden %}
{% endif %}
}
<?php
namespace {{ namespace }}\Model\Entity;
use {{ namespace }}\Model\Entity\Baked\{{ name }} as BakedEntity;
/**
* {@inheritDoc}
*/
class {{ name }} extends BakedEntity
{
}
<?php
namespace {{ namespace }}\Model\Table;
use {{ namespace }}\Model\Table\Baked\{{ name }}Table as BakedTable;
{% set uses = ['use Cake\\ORM\\Query;', 'use Cake\\ORM\\RulesChecker;', 'use Cake\\ORM\\Table;', 'use Cake\\Validation\\Validator;'] %}
{{ uses|join('\n')|raw }}
/**
* {@inheritDoc}
*/
class {{ name }}Table extends BakedTable
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
}
{{- "\n" }}
{%- if validation %}
/**
* Default validation rules.
*
* @param Validator $validator Validator instance.
* @return Validator
*/
public function validationDefault(Validator $validator)
{
parent::validationDefault($validator);
return $validator;
}
{% endif %}
{%- if rulesChecker %}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param RulesChecker $rules The rules object to be modified.
* @return RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
parent::buildRules($rules);
return $rules;
}
{% endif %}
}
<?php
namespace App\Shell\Task;
use Bake\Shell\Task\ModelTask;
use Cake\Console\Shell;
use Cake\Core\Configure;
use Cake\ORM\TableRegistry;
/**
* Class GenerationGapModelTask
* @package App\Shell\Task
* @property \Bake\Shell\Task\FixtureTask $Fixture
* @property \Bake\Shell\Task\BakeTemplateTask $BakeTemplate
* @property \Bake\Shell\Task\TestTask $Test
*/
class GenerationGapModelTask extends ModelTask
{
/**
* {@inheritDoc}
*/
public function bake($name)
{
parent::bake($name);
$table = $this->getTable($name);
$tableObject = $this->getTableObject($name, $table);
$data = $this->getTableContext($tableObject, $table, $name);
$this->bakeExtendedEntity($tableObject, $data);
$this->bakeExtendedTable($tableObject, $data);
}
/**
* {@inheritDoc}
*/
public function createFile($path, $contents)
{
// BakeしたものはBakedのディレクトリに移動する
$paths = [
'Table' . DS => 'Table' . DS . 'Baked' . DS,
'Entity' . DS => 'Entity' . DS . 'Baked' . DS
];
$path = str_replace(array_keys($paths), array_values($paths), $path);
return parent::createFile($path, $contents);
}
/**
* Bake a extended table class.
*
* @param \Cake\ORM\Table $model Model name or object
* @param array $data An array to use to generate the Table
* @return string|null
*/
public function bakeExtendedTable($model, array $data = [])
{
if (!empty($this->params['no-table'])) {
return null;
}
$namespace = Configure::read('App.namespace');
$pluginPath = '';
if ($this->plugin) {
$namespace = $this->_pluginNamespace($this->plugin);
}
$name = $model->getAlias();
$entity = $this->_entityName($model->getAlias());
$data += [
'plugin' => $this->plugin,
'pluginPath' => $pluginPath,
'namespace' => $namespace,
'name' => $name,
'entity' => $entity,
'associations' => [],
'primaryKey' => 'id',
'displayField' => null,
'table' => null,
'validation' => [],
'rulesChecker' => [],
'behaviors' => [],
'connection' => $this->connection,
];
$this->BakeTemplate->set($data);
$out = $this->BakeTemplate->generate('Model/extended_table');
$path = $this->getPath();
$filename = $path . 'Table' . DS . $name . 'Table.php';
$this->out("\n" . sprintf('Baking table class for %s...', $name), 1, Shell::QUIET);
if ($this->_isFile($filename)) {
return null;
}
parent::createFile($filename, $out);
// Work around composer caching that classes/files do not exist.
// Check for the file as it might not exist in tests.
if (file_exists($filename)) {
require_once $filename;
}
TableRegistry::getTableLocator()->clear();
return $out;
}
/**
* Bake an entity class.
*
* @param \Cake\ORM\Table $model Model name or object
* @param array $data An array to use to generate the Table
* @return string|null
*/
public function bakeExtendedEntity($model, array $data = [])
{
if (!empty($this->params['no-entity'])) {
return null;
}
$name = $this->_entityName($model->getAlias());
$namespace = Configure::read('App.namespace');
$pluginPath = '';
if ($this->plugin) {
$namespace = $this->_pluginNamespace($this->plugin);
$pluginPath = $this->plugin . '.';
}
$data += [
'name' => $name,
'namespace' => $namespace,
'plugin' => $this->plugin,
'pluginPath' => $pluginPath,
'primaryKey' => []
];
$this->BakeTemplate->set($data);
$out = $this->BakeTemplate->generate('Model/extended_entity');
$path = $this->getPath();
$filename = $path . 'Entity' . DS . $name . '.php';
$this->out("\n" . sprintf('Baking entity class for %s...', $name), 1, Shell::QUIET);
if ($this->_isFile($filename)) {
return null;
}
parent::createFile($filename, $out);
return $out;
}
/**
* Check file exists
* @param string $path filepath
* @return bool
*/
protected function _isFile($path)
{
$path = str_replace(DS . DS, DS, $path);
$fileExists = is_file($path);
if ($fileExists) {
$this->_io->out('<warning>File exists, skipping</warning>.');
return true;
}
return false;
}
}
{#
/**
* 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 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#}
{% set annotations = DocBlock.buildTableAnnotations(associations, associationInfo, behaviors, entity, namespace) %}
<?php
namespace {{ namespace }}\Model\Table\Baked;
{% set uses = ['use Cake\\ORM\\Query;', 'use Cake\\ORM\\RulesChecker;', 'use Cake\\ORM\\Table;', 'use Cake\\Validation\\Validator;'] %}
{{ uses|join('\n')|raw }}
{{ DocBlock.classDescription(name, 'Model', annotations)|raw }}
class {{ name }}Table extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
{% if table %}
$this->setTable('{{ table }}');
{% endif %}
{%- if displayField %}
$this->setDisplayField('{{ displayField }}');
{% endif %}
{%- if primaryKey %}
{%- if primaryKey is iterable and primaryKey|length > 1 %}
$this->setPrimaryKey([{{ Bake.stringifyList(primaryKey, {'indent': false})|raw }}]);
{{- "\n" }}
{%- else %}
$this->setPrimaryKey('{{ primaryKey|as_array|first }}');
{{- "\n" }}
{%- endif %}
{% endif %}
{%- if behaviors %}
{% endif %}
{%- for behavior, behaviorData in behaviors %}
$this->addBehavior('{{ behavior }}'{{ (behaviorData ? (", [" ~ Bake.stringifyList(behaviorData, {'indent': 3, 'quotes': false})|raw ~ ']') : '')|raw }});
{% endfor %}
{%- if associations.belongsTo or associations.hasMany or associations.belongsToMany %}
{% endif %}
{%- for type, assocs in associations %}
{%- for assoc in assocs %}
{%- set assocData = [] %}
{%- for key, val in assoc if key is not same as('alias') %}
{%- set assocData = assocData|merge({(key): val}) %}
{%- endfor %}
$this->{{ type }}('{{ assoc.alias }}', [{{ Bake.stringifyList(assocData, {'indent': 3})|raw }}]);
{{- "\n" }}
{%- endfor %}
{% endfor %}
}
{{- "\n" }}
{%- if validation %}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
{% for field, rules in validation %}
{% set validationMethods = Bake.getValidationMethods(field, rules) %}
{% if validationMethods %}
$validator
{% for validationMethod in validationMethods %}
{% if loop.last %}
{% set validationMethod = validationMethod ~ ';' %}
{% endif %}
{{ validationMethod|raw }}
{% endfor %}
{% endif %}
{% endfor %}
return $validator;
}
{% endif %}
{%- if rulesChecker %}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
{% for field, rule in rulesChecker %}
$rules->add($rules->{{ rule.name }}(['{{ field }}']{{ (rule.extra is defined and rule.extra ? (", '#{rule.extra}'") : '')|raw }}));
{% endfor %}
return $rules;
}
{% endif %}
{%- if connection is not same as('default') %}
/**
* Returns the database connection name to use by default.
*
* @return string
*/
public static function defaultConnectionName()
{
return '{{ connection }}';
}
{% endif %}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment