diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..fa512e7 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,27 @@ +name: ci + +on: [push] + +jobs: + testsuite: + strategy: + matrix: + php-versions: ['8.1', '8.2', '8.3'] + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, intl-72.1 + ini-values: zend.assertions = 1 + + - name: Install composer dependencies. + run: composer install --no-interaction --prefer-dist --optimize-autoloader + + - name: Run PHPUnit. + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index d1502b0..76c22bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.phpunit.cache/ vendor/ composer.lock diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a8856ad..0000000 --- a/.travis.yml +++ /dev/null @@ -1,62 +0,0 @@ -language: php - -php: - - 7.2 - - 7.4 - -services: - - mysql - - postgresql - -env: - matrix: - - DB=mysql db_dsn='mysql://root@127.0.0.1/cakephp_test' - - DB=pgsql db_dsn='postgres://postgres@127.0.0.1/cakephp_test' - - DB=sqlite db_dsn='sqlite:///:memory:' - - global: - - DEFAULT=1 - -matrix: - fast_finish: true - - include: - - php: 7.2 - env: PHPCS=1 DEFAULT=0 - - - php: 7.2 - env: STATIC_ANALYSIS=1 DEFAULT=0 - - - php: 7.2 - env: PREFER_LOWEST=1 - -before_script: - - if [[ $TRAVIS_PHP_VERSION != 7.4 ]]; then phpenv config-rm xdebug.ini; fi - - - if [[ $PREFER_LOWEST != 1 ]]; then composer update --no-interaction; fi - - if [[ $PREFER_LOWEST == 1 ]]; then composer update --no-interaction --prefer-lowest --prefer-stable; fi - - - if [[ $DB = 'mysql' ]]; then mysql -e 'CREATE DATABASE cakephp_test;'; fi - - if [[ $DB = 'pgsql' ]]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi - - - if [[ $STATIC_ANALYSIS = 1 ]]; then composer require --dev phpstan/phpstan:^0.12; fi - -script: - - | - if [[ $DEFAULT = 1 && $TRAVIS_PHP_VERSION = 7.4 ]]; then - mkdir -p build/logs - vendor/bin/phpunit --coverage-clover=build/logs/clover.xml - fi - - if [[ $DEFAULT = 1 && $TRAVIS_PHP_VERSION != 7.4 ]]; then vendor/bin/phpunit; fi - - - if [[ $PHPCS = 1 ]]; then vendor/bin/phpcs -n -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi - -after_success: - - | - if [[ $DEFAULT = 1 && $TRAVIS_PHP_VERSION = 7.2 ]]; then - wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.1.0/php-coveralls.phar - chmod +x php-coveralls.phar - ./php-coveralls.phar - fi -notifications: - email: false diff --git a/composer.json b/composer.json index dd8a3e5..671eee4 100644 --- a/composer.json +++ b/composer.json @@ -12,24 +12,30 @@ } ], "require": { - "cakephp/orm": "~4.0", - "php": ">=7.2", - "php-coveralls/php-coveralls": "^2.0" + "php": "^8.1", + "cakephp/orm": "^5.0" }, "require-dev": { - "cakephp/cakephp": "~4.0", - "phpunit/phpunit": "^8", - "cakephp/cakephp-codesniffer": "dev-master" + "cakephp/cakephp": "^5.0", + "cakephp/cakephp-codesniffer": "^5.1", + "php-coveralls/php-coveralls": "^0.4.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5" }, "autoload": { "psr-4": { - "Josegonzalez\\Version\\": "src", - "Josegonzalez\\Version\\Test\\Fixture\\": "tests\\Fixture" + "Josegonzalez\\Version\\": "src/" } }, "autoload-dev": { "psr-4": { - "Josegonzalez\\Version\\Test\\": "tests" + "Josegonzalez\\Version\\Test\\": "tests/" } - } + }, + "config": { + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } } diff --git a/config/bootstrap.php b/config/bootstrap.php deleted file mode 100644 index d809914..0000000 --- a/config/bootstrap.php +++ /dev/null @@ -1,6 +0,0 @@ -on('Bake.beforeRender', function (Event $event) { - (new VersionListener($event))->execute(); -}); diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..30a43e4 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,4 @@ + + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7a13ae4..216957f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,37 +1,30 @@ - + + + - - - ./tests/TestCase + + tests/TestCase/ - - - ./src - ./tests - - - - - - - - - - - + + + + + + src/ + + diff --git a/src/Event/EventListener.php b/src/Event/EventListener.php index eeee22d..14084ff 100644 --- a/src/Event/EventListener.php +++ b/src/Event/EventListener.php @@ -13,8 +13,8 @@ namespace Josegonzalez\Version\Event; -use Cake\Event\Event as CakeEvent; use Cake\Event\EventDispatcherTrait; +use Cake\Event\EventInterface; use Cake\Event\EventListenerInterface; /** @@ -31,18 +31,18 @@ abstract class EventListener implements EventListenerInterface use EventDispatcherTrait; /** - * The CakeEvent attached to this class + * The EventInterface attached to this class * - * @var \Cake\Event\Event $event Event instance. + * @var \Cake\Event\EventInterface $event Event instance. */ - protected $event; + protected EventInterface $event; /** * Constructor. * - * @param \Cake\Event\Event $event Event instance. + * @param \Cake\Event\EventInterface $event Event instance. */ - public function __construct(CakeEvent $event) + public function __construct(EventInterface $event) { $this->event = $event; $this->getEventManager()->on($this); @@ -53,21 +53,21 @@ public function __construct(CakeEvent $event) * * @return void */ - public function execute() + public function execute(): void { $methods = array_values($this->implementedEvents()); foreach ($methods as $method) { - $this->dispatchEvent(sprintf('Bake.%s', $method), null, $this->event->subject); + $this->dispatchEvent(sprintf('Bake.%s', $method), [], $this->event->getSubject()); } } /** * Check whether or not a bake call is a certain type. * - * @param string|array $type The type of file you want to check. + * @param string $type The type of file you want to check. * @return bool Whether or not the bake template is the type you are checking. */ - public function isType($type) + public function isType(string $type): bool { $template = sprintf('Bake/%s.ctp', $type); diff --git a/src/Event/VersionListener.php b/src/Event/VersionListener.php index 97fb89e..5a68215 100644 --- a/src/Event/VersionListener.php +++ b/src/Event/VersionListener.php @@ -13,8 +13,9 @@ namespace Josegonzalez\Version\Event; +use Cake\Database\Connection; use Cake\Datasource\ConnectionManager; -use Cake\Event\Event; +use Cake\Event\EventInterface; use Cake\Utility\Hash; /** @@ -31,10 +32,10 @@ class VersionListener extends EventListener /** * Called before the entity template is rendered * - * @param \Cake\Event\Event $event An Event instance + * @param \Cake\Event\EventInterface $event An Event instance * @return void */ - public function beforeRenderEntity(Event $event) + public function beforeRenderEntity(EventInterface $event): void { $this->checkAssociation($event, 'versions'); } @@ -42,16 +43,16 @@ public function beforeRenderEntity(Event $event) /** * Called before the test case template is rendered * - * @param \Cake\Event\Event $event An Event instance + * @param \Cake\Event\EventInterface $event An Event instance * @return void */ - public function beforeRenderTestCase(Event $event) + public function beforeRenderTestCase(EventInterface $event): void { - $name = $event->subject->viewVars['subject']; + $name = $event->getSubject()->viewVars['subject']; $pattern = '/^' . preg_quote($name) . '_(\w+)_version$/'; - foreach (array_keys($event->subject->viewVars['fixtures']) as $key) { + foreach (array_keys($event->getSubject()->viewVars['fixtures']) as $key) { if (preg_match($pattern, $key)) { - unset($event->subject->viewVars['fixtures'][$key]); + unset($event->getSubject()->viewVars['fixtures'][$key]); } } } @@ -59,10 +60,10 @@ public function beforeRenderTestCase(Event $event) /** * Called before the table template is rendered * - * @param \Cake\Event\Event $event An Event instance + * @param \Cake\Event\EventInterface $event An Event instance * @return void */ - public function beforeRenderTable(Event $event) + public function beforeRenderTable(EventInterface $event): void { $this->checkAssociation($event, 'versions'); $this->fixVersionTables($event); @@ -71,19 +72,19 @@ public function beforeRenderTable(Event $event) /** * Removes unnecessary associations * - * @param \Cake\Event\Event $event An Event instance + * @param \Cake\Event\EventInterface $event An Event instance * @return void */ - protected function fixVersionTables(Event $event) + protected function fixVersionTables(EventInterface $event): void { - if (!preg_match('/Versions$/', $event->subject->viewVars['name'])) { + if (!preg_match('/Versions$/', $event->getSubject()->viewVars['name'])) { return; } - unset($event->subject->viewVars['rulesChecker']['version_id']); - foreach ($event->subject->viewVars['associations']['belongsTo'] as $i => $association) { + unset($event->getSubject()->viewVars['rulesChecker']['version_id']); + foreach ($event->getSubject()->viewVars['associations']['belongsTo'] as $i => $association) { if ($association['alias'] === 'Versions' && $association['foreignKey'] === 'version_id') { - unset($event->subject->viewVars['associations']['belongsTo'][$i]); + unset($event->getSubject()->viewVars['associations']['belongsTo'][$i]); } } } @@ -91,27 +92,28 @@ protected function fixVersionTables(Event $event) /** * Attaches the behavior and modifies associations as necessary * - * @param \Cake\Event\Event $event An Event instance + * @param \Cake\Event\EventInterface $event An Event instance * @param string $tableSuffix a suffix for the primary table * @return bool true if modified, false otherwise */ - protected function checkAssociation(Event $event, $tableSuffix) + protected function checkAssociation(EventInterface $event, string $tableSuffix): bool { - $subject = $event->subject; + $subject = $event->getSubject(); $connection = ConnectionManager::get($subject->viewVars['connection']); + assert($connection instanceof Connection); $schema = $connection->getSchemaCollection(); - $versionTable = sprintf('%s_%s', Hash::get($event->subject->viewVars, 'table'), $tableSuffix); + $versionTable = sprintf('%s_%s', Hash::get($event->getSubject()->viewVars, 'table'), $tableSuffix); if (!in_array($versionTable, $schema->listTables())) { return false; } - $event->subject->viewVars['behaviors']['Josegonzalez/Version.Version'] = [ + $event->getSubject()->viewVars['behaviors']['Josegonzalez/Version.Version'] = [ sprintf("'versionTable' => '%s'", $versionTable), ]; - $event->subject->viewVars['associations']['belongsTo'] = $this->modifyBelongsTo($event); - $event->subject->viewVars['rulesChecker'] = $this->modifyRulesChecker($event); + $event->getSubject()->viewVars['associations']['belongsTo'] = $this->modifyBelongsTo($event); + $event->getSubject()->viewVars['rulesChecker'] = $this->modifyRulesChecker($event); return true; } @@ -119,12 +121,12 @@ protected function checkAssociation(Event $event, $tableSuffix) /** * Removes unnecessary belongsTo associations * - * @param \Cake\Event\Event $event An Event instance + * @param \Cake\Event\EventInterface $event An Event instance * @return array */ - protected function modifyBelongsTo(Event $event) + protected function modifyBelongsTo(EventInterface $event): array { - $belongsTo = $event->subject->viewVars['associations']['belongsTo']; + $belongsTo = $event->getSubject()->viewVars['associations']['belongsTo']; foreach ($belongsTo as $i => $association) { if ($association['alias'] !== 'Versions' || $association['foreignKey'] !== 'version_id') { @@ -140,12 +142,12 @@ protected function modifyBelongsTo(Event $event) /** * Removes unnecessary rulesChecker entries * - * @param \Cake\Event\Event $event An Event instance + * @param \Cake\Event\EventInterface $event An Event instance * @return array */ - protected function modifyRulesChecker(Event $event) + protected function modifyRulesChecker(EventInterface $event): array { - $rulesChecker = $event->subject->viewVars['rulesChecker']; + $rulesChecker = $event->getSubject()->viewVars['rulesChecker']; foreach ($rulesChecker as $key => $config) { if (Hash::get($config, 'extra') !== 'Versions' || $key !== 'version_id') { diff --git a/src/Model/Behavior/Version/VersionTrait.php b/src/Model/Behavior/Version/VersionTrait.php index dd380d5..eb746ba 100644 --- a/src/Model/Behavior/Version/VersionTrait.php +++ b/src/Model/Behavior/Version/VersionTrait.php @@ -13,7 +13,8 @@ namespace Josegonzalez\Version\Model\Behavior\Version; -use Cake\ORM\TableRegistry; +use Cake\Datasource\FactoryLocator; +use Cake\ORM\Entity; /** * Trait VersionTrait @@ -33,25 +34,22 @@ trait VersionTrait * @param bool $reset If true, will re-retrieve the related version collection * @return \Cake\ORM\Entity|null */ - public function version($versionId, $reset = false) + public function version(int $versionId, bool $reset = false): ?Entity { $versions = $this->versions($reset); - if (empty($versions[$versionId])) { - return null; - } - return $versions[$versionId]; + return $versions[$versionId] ?? null; } /** * Retrieves the related versions for the current entity * * @param bool $reset If true, will re-retrieve the related version collection - * @return \Cake\Collection\CollectionInterface + * @return array<\Cake\ORM\Entity> */ - public function versions($reset = false) + public function versions(bool $reset = false): array { - if ($reset === false && $this->has('_versions')) { + if ($reset === false && $this->hasValue('_versions')) { return $this->get('_versions'); } @@ -59,7 +57,7 @@ public function versions($reset = false) * @var \Josegonzalez\Version\Model\Behavior\VersionBehavior $table * @var \Cake\Datasource\EntityInterface $this */ - $table = TableRegistry::get($this->getSource()); + $table = FactoryLocator::get('Table')->get($this->getSource()); $versions = $table->getVersions($this); $this->set('_versions', $versions); diff --git a/src/Model/Behavior/VersionBehavior.php b/src/Model/Behavior/VersionBehavior.php index 1925fa4..62a19dd 100644 --- a/src/Model/Behavior/VersionBehavior.php +++ b/src/Model/Behavior/VersionBehavior.php @@ -15,17 +15,20 @@ use ArrayObject; use Cake\Collection\Collection; -use Cake\Database\Type; +use Cake\Collection\CollectionInterface; +use Cake\Database\TypeFactory; use Cake\Datasource\EntityInterface; +use Cake\Datasource\ResultSetInterface; use Cake\Event\Event; -use Cake\Event\EventManager; +use Cake\ORM\Association; use Cake\ORM\Behavior; +use Cake\ORM\Locator\LocatorAwareTrait; use Cake\ORM\Query; -use Cake\ORM\TableRegistry; use Cake\Utility\Hash; use Cake\Utility\Inflector; use DateTime; use InvalidArgumentException; +use function Cake\Core\namespaceSplit; /** * This behavior provides a way to version dynamic data by keeping versions @@ -44,24 +47,16 @@ */ class VersionBehavior extends Behavior { - /** - * Table instance - * - * @var \Cake\ORM\Table - */ - // phpcs:disable - protected $_table; - // phpcs:enable + use LocatorAwareTrait; /** * Default config * * These are merged with user-provided configuration when the behavior is used. * - * @var array + * @var array */ - // phpcs:disable - protected $_defaultConfig = [ + protected array $_defaultConfig = [ 'implementedFinders' => ['versions' => 'findVersions'], 'versionTable' => 'version', 'versionField' => 'version_id', @@ -69,9 +64,8 @@ class VersionBehavior extends Behavior 'fields' => null, 'foreignKey' => 'foreign_key', 'referenceName' => null, - 'onlyDirty' => false + 'onlyDirty' => false, ]; - // phpcs:enable /** * Constructor hook method. @@ -100,7 +94,7 @@ public function initialize(array $config): void * @param string $table the table name to use for storing each field version * @return void */ - public function setupFieldAssociations($table) + public function setupFieldAssociations(string $table): void { $options = [ 'table' => $table, @@ -120,7 +114,7 @@ public function setupFieldAssociations($table) * @param array $options Association options. * @return \Cake\ORM\Association */ - public function versionAssociation($field = null, $options = []) + public function versionAssociation(?string $field = null, array $options = []): Association { $name = $this->associationName($field); @@ -166,7 +160,7 @@ public function versionAssociation($field = null, $options = []) * @param \ArrayObject $options the options passed to the save method * @return void */ - public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options) + public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options): void { $association = $this->versionAssociation(); $name = $association->getName(); @@ -186,7 +180,7 @@ public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $o } $created = new DateTime(); $new = []; - $entityClass = TableRegistry::getTableLocator()->get($this->_config['versionTable'])->getEntityClass(); + $entityClass = $this->getTableLocator()->get($this->_config['versionTable'])->getEntityClass(); foreach ($values as $field => $content) { if (in_array($field, $primaryKey) || $field == $versionField) { continue; @@ -202,9 +196,8 @@ public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $o 'created' => $created, ] + $this->extractForeignKey($entity); - $event = new Event('Model.Version.beforeSave', $this, $options); - $userData = EventManager::instance()->dispatch($event); - if (isset($userData) && $userData->getResult() !== null && is_array($userData->getResult())) { + $userData = $this->_table->dispatchEvent('Model.Version.beforeSave', (array)$options); + if ($userData !== null && $userData->getResult() !== null && is_array($userData->getResult())) { $data = array_merge($data, $userData->getResult()); } @@ -230,7 +223,7 @@ public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $o * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved * @return void */ - public function afterSave(Event $event, EntityInterface $entity) + public function afterSave(Event $event, EntityInterface $entity): void { $property = $this->versionAssociation()->getProperty(); $entity->unset($property); @@ -242,9 +235,9 @@ public function afterSave(Event $event, EntityInterface $entity) * @param \Cake\Datasource\EntityInterface $entity Entity. * @return int */ - public function getVersionId(EntityInterface $entity) + public function getVersionId(EntityInterface $entity): int { - $table = TableRegistry::getTableLocator()->get($this->_config['versionTable']); + $table = $this->getTableLocator()->get($this->_config['versionTable']); $extractedKey = $this->extractForeignKey($entity); //If any extracted key is null (in case of new entity), don't trigger db-query. @@ -263,7 +256,7 @@ public function getVersionId(EntityInterface $entity) 'model' => $this->_config['referenceName'], ] + $extractedKey ) - ->order(['id desc']) + ->orderBy(['id desc']) ->limit(1) ->enableHydration(false) ->toArray(); @@ -288,14 +281,14 @@ public function getVersionId(EntityInterface $entity) * @param array $options Options * @return \Cake\ORM\Query */ - public function findVersions(Query $query, array $options) + public function findVersions(Query $query, array $options): Query { $association = $this->versionAssociation(); $name = $association->getName(); return $query ->contain( - [$name => function (Query $q) use ($name, $options, $query) { + [$name => function (Query $q) use ($name, $options) { if (!empty($options['primaryKey'])) { $foreignKey = (array)$this->_config['foreignKey']; $aliasedFK = []; @@ -313,7 +306,7 @@ public function findVersions(Query $query, array $options) return $q; }] ) - ->formatResults([$this, 'groupVersions'], $query::PREPEND); + ->formatResults($this->groupVersions(...), $query::PREPEND); } /** @@ -323,12 +316,16 @@ public function findVersions(Query $query, array $options) * @param \Cake\Datasource\ResultSetInterface $results Results to modify. * @return \Cake\Collection\CollectionInterface */ - public function groupVersions($results) + public function groupVersions(ResultSetInterface $results): CollectionInterface { $property = $this->versionAssociation()->getProperty(); return $results->map( function (EntityInterface $row) use ($property) { + if ($row->has('_versions')) { + return $row; + } + $versionField = $this->_config['versionField']; $versions = (array)$row->get($property); $grouped = new Collection($versions); @@ -377,9 +374,9 @@ function (EntityInterface $row) use ($property) { * Returns the versions of a specific entity. * * @param \Cake\Datasource\EntityInterface $entity Entity. - * @return \Cake\Collection\CollectionInterface + * @return array<\Cake\Datasource\EntityInterface> */ - public function getVersions(EntityInterface $entity) + public function getVersions(EntityInterface $entity): array { $primaryKey = (array)$this->_table->getPrimaryKey(); @@ -392,8 +389,8 @@ public function getVersions(EntityInterface $entity) } $entities = $query->where($conditions)->all(); - if (empty($entities)) { - return new Collection([]); + if ($entities->isEmpty()) { + return []; } $entity = $entities->first(); @@ -406,7 +403,7 @@ public function getVersions(EntityInterface $entity) * * @return array */ - protected function fields() + protected function fields(): array { $schema = $this->_table->getSchema(); $fields = $schema->columns(); @@ -423,7 +420,7 @@ protected function fields() * @param \Cake\Datasource\EntityInterface $entity Entity. * @return array */ - protected function extractForeignKey($entity) + protected function extractForeignKey(EntityInterface $entity): array { $foreignKey = (array)$this->_config['foreignKey']; $primaryKey = (array)$this->_table->getPrimaryKey(); @@ -438,7 +435,7 @@ protected function extractForeignKey($entity) * @param string $field Field name. * @return string */ - protected function associationName($field = null) + protected function associationName(?string $field = null): string { $alias = Inflector::singularize($this->_table->getAlias()); if ($field) { @@ -453,7 +450,7 @@ protected function associationName($field = null) * * @return string */ - protected function referenceName() + protected function referenceName(): string { $table = $this->_table; $name = namespaceSplit(get_class($table)); @@ -474,16 +471,17 @@ protected function referenceName() * @param string $direction Direction (toPHP or toDatabase) * @return array */ - protected function convertFieldsToType(array $fields, $direction) + protected function convertFieldsToType(array $fields, string $direction): array { if (!in_array($direction, ['toPHP', 'toDatabase'])) { - throw new InvalidArgumentException(sprintf('Cannot convert type, Cake\Database\Type::%s does not exist', $direction)); + $message = sprintf('Cannot convert type, Cake\Database\Type::%s does not exist', $direction); + throw new InvalidArgumentException($message); } $driver = $this->_table->getConnection()->getDriver(); foreach ($fields as $field => $content) { $column = $this->_table->getSchema()->getColumn($field); - $type = Type::build($column['type']); + $type = TypeFactory::build($column['type']); $fields[$field] = $type->{$direction}($content, $driver); } diff --git a/src/VersionPlugin.php b/src/VersionPlugin.php new file mode 100644 index 0000000..eae4361 --- /dev/null +++ b/src/VersionPlugin.php @@ -0,0 +1,35 @@ +bootstrapCli($app); + } + } + + /** + * CLI bootstrap + * + * @param \Cake\Core\PluginApplicationInterface $app Applicaction instance + * @return void + */ + public function bootstrapCli(PluginApplicationInterface $app): void + { + $app->getEventManager()->on('Bake.beforeRender', function (Event $event): void { + (new VersionListener($event))->execute(); + }); + } +} diff --git a/tests/Fixture/ArticlesFixture.php b/tests/Fixture/ArticlesFixture.php index cc7139c..6ecaa50 100644 --- a/tests/Fixture/ArticlesFixture.php +++ b/tests/Fixture/ArticlesFixture.php @@ -25,30 +25,14 @@ */ class ArticlesFixture extends TestFixture { - public $table = 'articles'; - - /** - * Fields property - * - * @var array - */ - public $fields = [ - 'id' => ['type' => 'integer'], - 'author_id' => ['type' => 'integer', 'null' => true], - 'version_id' => ['type' => 'integer', 'null' => true], - 'title' => ['type' => 'string', 'null' => true], - 'body' => 'text', - 'published' => ['type' => 'string', 'length' => 1, 'default' => 'N'], - 'settings' => ['type' => 'json', 'null' => true], - '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]], - ]; + public string $table = 'articles'; /** * Records property * * @var array */ - public $records = [ + public array $records = [ ['author_id' => 1, 'version_id' => 2, 'title' => 'First Article Version 2', 'body' => 'First Article Body Version 2', 'published' => 'N'], ['author_id' => 2, 'version_id' => 3, 'title' => 'Second Article Version 3', 'body' => 'Second Article Body Version 3', 'published' => 'N'], ]; diff --git a/tests/Fixture/ArticlesTagsFixture.php b/tests/Fixture/ArticlesTagsFixture.php index 08443d8..678af1a 100644 --- a/tests/Fixture/ArticlesTagsFixture.php +++ b/tests/Fixture/ArticlesTagsFixture.php @@ -26,27 +26,14 @@ */ class ArticlesTagsFixture extends TestFixture { - public $table = 'articles_tags'; - - /** - * Fields property - * - * @var array - */ - public $fields = [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'], - 'version_id' => ['type' => 'integer', 'null' => true], - 'sort_order' => ['type' => 'integer', 'default' => 1], - '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['article_id', 'tag_id']]], - ]; + public string $table = 'articles_tags'; /** * Records property * * @var array */ - public $records = [ + public array $records = [ ['article_id' => 1, 'tag_id' => 1, 'version_id' => 2, 'sort_order' => 1], ]; } diff --git a/tests/Fixture/ArticlesTagsVersionsFixture.php b/tests/Fixture/ArticlesTagsVersionsFixture.php index bd57f70..ccd4eb6 100644 --- a/tests/Fixture/ArticlesTagsVersionsFixture.php +++ b/tests/Fixture/ArticlesTagsVersionsFixture.php @@ -31,33 +31,14 @@ class ArticlesTagsVersionsFixture extends TestFixture * * @var string */ - public $table = 'articles_tags_versions'; - - /** - * Fields property - * - * @var array - */ - public $fields = [ - 'id' => ['type' => 'integer'], - 'version_id' => ['type' => 'integer'], - 'model' => ['type' => 'string', 'null' => false], - 'article_id' => ['type' => 'integer', 'null' => false], - 'tag_id' => ['type' => 'integer', 'null' => false], - 'field' => ['type' => 'string', 'null' => false], - 'content' => ['type' => 'text'], - 'custom_field' => ['type' => 'text'], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id']], - ], - ]; + public string $table = 'articles_tags_versions'; /** * Records property * * @var array */ - public $records = [ + public array $records = [ ['version_id' => 1, 'model' => 'ArticlesTags', 'article_id' => 1, 'tag_id' => 1, 'field' => 'sort_order', 'content' => 1], ['version_id' => 2, 'model' => 'ArticlesTags', 'article_id' => 1, 'tag_id' => 1, 'field' => 'sort_order', 'content' => 2], ]; diff --git a/tests/Fixture/VersionsFixture.php b/tests/Fixture/VersionsFixture.php index 71defbf..cd5fd62 100644 --- a/tests/Fixture/VersionsFixture.php +++ b/tests/Fixture/VersionsFixture.php @@ -30,32 +30,14 @@ class VersionsFixture extends TestFixture * * @var string */ - public $table = 'version'; - - /** - * Fields property - * - * @var array - */ - public $fields = [ - 'id' => ['type' => 'integer'], - 'version_id' => ['type' => 'integer'], - 'model' => ['type' => 'string', 'null' => false], - 'foreign_key' => ['type' => 'integer', 'null' => false], - 'field' => ['type' => 'string', 'null' => false], - 'content' => ['type' => 'text'], - 'custom_field' => ['type' => 'text'], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id']], - ], - ]; + public string $table = 'version'; /** * Records property * * @var array */ - public $records = [ + public array $records = [ ['version_id' => 1, 'model' => 'Articles', 'foreign_key' => 1, 'field' => 'author_id', 'content' => 1], ['version_id' => 1, 'model' => 'Articles', 'foreign_key' => 1, 'field' => 'title', 'content' => 'First Article'], ['version_id' => 1, 'model' => 'Articles', 'foreign_key' => 1, 'field' => 'body', 'content' => 'First Article Body'], diff --git a/tests/Fixture/VersionsWithUserFixture.php b/tests/Fixture/VersionsWithUserFixture.php index 662d82c..b3414ca 100644 --- a/tests/Fixture/VersionsWithUserFixture.php +++ b/tests/Fixture/VersionsWithUserFixture.php @@ -30,32 +30,14 @@ class VersionsWithUserFixture extends TestFixture * * @var string */ - public $table = 'versions_with_user'; - - /** - * Fields property - * - * @var array - */ - public $fields = [ - 'id' => ['type' => 'integer'], - 'version_id' => ['type' => 'integer'], - 'user_id' => ['type' => 'integer'], - 'model' => ['type' => 'string', 'null' => false], - 'foreign_key' => ['type' => 'integer', 'null' => false], - 'field' => ['type' => 'string', 'null' => false], - 'content' => ['type' => 'text'], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id']], - ], - ]; + public string $table = 'versions_with_user'; /** * Records property * * @var array */ - public $records = [ + public array $records = [ ['version_id' => 1, 'model' => 'Articles', 'foreign_key' => 1, 'field' => 'author_id', 'content' => 1, 'user_id' => 2], ['version_id' => 1, 'model' => 'Articles', 'foreign_key' => 1, 'field' => 'title', 'content' => 'First Article', 'user_id' => 2], ['version_id' => 1, 'model' => 'Articles', 'foreign_key' => 1, 'field' => 'body', 'content' => 'First Article Body', 'user_id' => 2], diff --git a/tests/TestCase/Model/Entity/Test.php b/tests/TestApp/Model/Entity/Test.php similarity index 93% rename from tests/TestCase/Model/Entity/Test.php rename to tests/TestApp/Model/Entity/Test.php index 9861a23..71124ce 100644 --- a/tests/TestCase/Model/Entity/Test.php +++ b/tests/TestApp/Model/Entity/Test.php @@ -11,7 +11,7 @@ * @link https://github.com/josegonzalez/cakephp-version */ -namespace Josegonzalez\Version\Test\TestCase\Model\Entity; +namespace Josegonzalez\Version\Test\TestApp\Model\Entity; use Cake\ORM\Entity; use Josegonzalez\Version\Model\Behavior\Version\VersionTrait; diff --git a/tests/TestCase/Model/Behavior/VersionBehaviorTest.php b/tests/TestCase/Model/Behavior/VersionBehaviorTest.php index de780e7..c71f576 100644 --- a/tests/TestCase/Model/Behavior/VersionBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/VersionBehaviorTest.php @@ -14,11 +14,10 @@ namespace Josegonzalez\Version\Test\TestCase\Model\Behavior; use Cake\Event\EventManager; -use Cake\Http\BaseApplication; -use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use InvalidArgumentException; use Josegonzalez\Version\Model\Behavior\VersionBehavior; +use Josegonzalez\Version\Test\TestApp\Model\Entity\Test; use ReflectionObject; /** @@ -38,7 +37,7 @@ class VersionBehaviorTest extends TestCase * * @var array */ - public $fixtures = [ + public array $fixtures = [ 'plugin.Josegonzalez/Version.Versions', 'plugin.Josegonzalez/Version.VersionsWithUser', 'plugin.Josegonzalez/Version.Articles', @@ -46,32 +45,6 @@ class VersionBehaviorTest extends TestCase 'plugin.Josegonzalez/Version.ArticlesTags', ]; - /** - * Overwritten method to load plugins needed for the tests. - * - * @param array $plugins The plugins to load. - * @return \Cake\Http\BaseApplication - */ - public function loadPlugins(array $plugins = []): BaseApplication - { - $plugins = [ - 'Josegonzalez/Version', - ]; - - return parent::loadPlugins($plugins); // TODO: Change the autogenerated stub - } - - /** - * Tidy up, after test session has been finished. - * - * @return void - */ - public function tearDown(): void - { - parent::tearDown(); - TableRegistry::getTableLocator()->clear(); - } - /** * Save a new version * @@ -79,17 +52,17 @@ public function tearDown(): void */ public function testSaveNew() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', - ] + 'entityClass' => Test::class, + ], ); $table->addBehavior('Josegonzalez/Version.Version'); $article = $table->find('all')->first(); $this->assertEquals(2, $article->version_id); - $versionTable = TableRegistry::getTableLocator()->get('Version'); + $versionTable = $this->getTableLocator()->get('Version'); $results = $versionTable->find('all') ->where(['foreign_key' => $article->id]) ->enableHydration(false) @@ -99,7 +72,7 @@ public function testSaveNew() $article->title = 'Titulo'; $table->save($article); - $versionTable = TableRegistry::getTableLocator()->get('Version'); + $versionTable = $this->getTableLocator()->get('Version'); $results = $versionTable->find('all') ->where(['foreign_key' => $article->id]) ->enableHydration(false) @@ -114,12 +87,12 @@ public function testSaveNew() * * @return void */ - public function testFindVersion() + public function testFindVersionSpecific() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version'); @@ -134,12 +107,12 @@ public function testFindVersion() * * @return void */ - public function testFindVersionX() + public function testFindVersionAdditional() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $config = [ @@ -164,10 +137,10 @@ public function testFindVersionX() */ public function testFindVersions() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version'); @@ -209,10 +182,10 @@ public function testFindVersions() */ public function testSaveLimitFields() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version', ['fields' => 'title']); @@ -222,7 +195,7 @@ public function testSaveLimitFields() $article->body = 'Hello world!'; $table->save($article); - $versionTable = TableRegistry::getTableLocator()->get('Version'); + $versionTable = $this->getTableLocator()->get('Version'); $results = $versionTable->find('all') ->where(['foreign_key' => $article->id, 'version_id' => 3]) ->enableHydration(false) @@ -239,10 +212,10 @@ public function testSaveLimitFields() */ public function testSaveDirtyFields() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version', ['onlyDirty' => true]); @@ -252,7 +225,7 @@ public function testSaveDirtyFields() $article->body = 'Hello world!'; $table->save($article); - $versionTable = TableRegistry::getTableLocator()->get('Version'); + $versionTable = $this->getTableLocator()->get('Version'); $results = $versionTable->find('all') ->where(['foreign_key' => $article->id, 'version_id' => 3]) ->enableHydration(false) @@ -270,10 +243,10 @@ public function testSaveDirtyFields() */ public function testFindVersionLimitFields() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version', ['fields' => 'title']); @@ -291,10 +264,10 @@ public function testFindVersionLimitFields() */ public function testSaveWithValidMetaData() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version'); @@ -307,7 +280,7 @@ function ($event) { ]; } ); - $versionTable = TableRegistry::getTableLocator()->get('Version'); + $versionTable = $this->getTableLocator()->get('Version'); $results = $versionTable->find('all') ->where(['foreign_key' => $article->id]) @@ -332,10 +305,10 @@ function ($event) { */ public function testSaveWithInvalidMetaData() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version'); @@ -348,7 +321,7 @@ function ($event) { ]; } ); - $versionTable = TableRegistry::getTableLocator()->get('Version'); + $versionTable = $this->getTableLocator()->get('Version'); $results = $versionTable->find('all') ->where(['foreign_key' => $article->id]) @@ -373,10 +346,10 @@ function ($event) { */ public function testFindWithCompositeKeys() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'ArticlesTags', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior( @@ -400,10 +373,10 @@ public function testFindWithCompositeKeys() */ public function testSaveWithCompositeKeys() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'ArticlesTags', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior( @@ -430,10 +403,10 @@ public function testSaveWithCompositeKeys() */ public function testGetAdditionalMetaData() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior( @@ -443,9 +416,9 @@ public function testGetAdditionalMetaData() 'additionalVersionFields' => ['created', 'user_id'], ] ); - $article = $table->find('all')->first(); + $table->find('all')->first(); - $versionTable = TableRegistry::getTableLocator()->get('Version', ['table' => 'versions_with_user']); + $this->getTableLocator()->get('Version', ['table' => 'versions_with_user']); $results = $table->find('versions')->toArray(); @@ -460,10 +433,10 @@ public function testGetAdditionalMetaData() */ public function testAssociations() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version'); @@ -487,10 +460,10 @@ public function testAssociations() public function testGetVersionId() { // init test data - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version'); @@ -512,10 +485,10 @@ public function testGetVersionId() */ public function testSaveNonScalarType() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $schema = $table->getSchema(); @@ -539,10 +512,10 @@ public function testSaveNonScalarType() */ public function testVersionConvertsType() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $table->addBehavior('Josegonzalez/Version.Version'); @@ -559,10 +532,10 @@ public function testVersionConvertsType() */ public function testConvertFieldsToType() { - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $schema = $table->getSchema(); @@ -608,10 +581,10 @@ public function testConvertFieldsToTypeInvalidDirection() { $this->expectException(InvalidArgumentException::class); - $table = TableRegistry::getTableLocator()->get( + $table = $this->getTableLocator()->get( 'Articles', [ - 'entityClass' => 'Josegonzalez\Version\Test\TestCase\Model\Entity\Test', + 'entityClass' => Test::class, ] ); $behavior = new VersionBehavior($table); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index c4847ca..b7cd879 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,7 +1,11 @@ 'App']); -Cake\Core\Configure::write('debug', true); +Configure::write('App', ['namespace' => 'App']); +Configure::write('debug', true); -$TMP = new \Cake\Filesystem\Folder(TMP); -$TMP->create(TMP . 'cache/models', 0777); -$TMP->create(TMP . 'cache/persistent', 0777); -$TMP->create(TMP . 'cache/views', 0777); +$filesystem = new Filesystem(); +$filesystem->mkdir(TMP . 'cache/models', 0777); +$filesystem->mkdir(TMP . 'cache/persistent', 0777); +$filesystem->mkdir(TMP . 'cache/views', 0777); $cache = [ 'default' => [ - 'engine' => 'File' + 'engine' => 'File', ], '_cake_core_' => [ 'className' => 'File', 'prefix' => 'version_myapp_cake_core_', 'path' => CACHE . 'persistent/', 'serialize' => true, - 'duration' => '+10 seconds' + 'duration' => '+10 seconds', ], '_cake_model_' => [ 'className' => 'File', 'prefix' => 'version_my_app_cake_model_', 'path' => CACHE . 'models/', 'serialize' => 'File', - 'duration' => '+10 seconds' - ] + 'duration' => '+10 seconds', + ], ]; -Cake\Cache\Cache::setConfig($cache); -Cake\Core\Configure::write('Session', [ - 'defaults' => 'php' +Cache::setConfig($cache); +Configure::write('Session', [ + 'defaults' => 'php', ]); - // Ensure default test connection is defined if (!getenv('db_dsn')) { putenv('db_dsn=sqlite:///:memory:'); } -Cake\Datasource\ConnectionManager::setConfig('test', [ +ConnectionManager::setConfig('test', [ 'url' => getenv('db_dsn'), - 'timezone' => 'UTC' + 'timezone' => 'UTC', ]); + +$loader = new SchemaLoader(); +$loader->loadInternalFile(__DIR__ . '/schema.php'); diff --git a/tests/schema.php b/tests/schema.php new file mode 100644 index 0000000..efd052b --- /dev/null +++ b/tests/schema.php @@ -0,0 +1,69 @@ + [ + 'columns' => [ + 'id' => ['type' => 'integer'], + 'author_id' => ['type' => 'integer', 'null' => true], + 'version_id' => ['type' => 'integer', 'null' => true], + 'title' => ['type' => 'string', 'null' => true], + 'body' => 'text', + 'published' => ['type' => 'string', 'length' => 1, 'default' => 'N'], + 'settings' => ['type' => 'json', 'null' => true], + ], + 'constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]], + ], + 'articles_tags' => [ + 'columns' => [ + 'article_id' => ['type' => 'integer'], + 'tag_id' => ['type' => 'integer'], + 'version_id' => ['type' => 'integer', 'null' => true], + 'sort_order' => ['type' => 'integer', 'default' => 1], + ], + 'constraints' => ['primary' => ['type' => 'primary', 'columns' => ['article_id', 'tag_id']]], + ], + 'articles_tags_versions' => [ + 'columns' => [ + 'id' => ['type' => 'integer'], + 'version_id' => ['type' => 'integer'], + 'model' => ['type' => 'string', 'null' => false], + 'article_id' => ['type' => 'integer', 'null' => false], + 'tag_id' => ['type' => 'integer', 'null' => false], + 'field' => ['type' => 'string', 'null' => false], + 'content' => ['type' => 'text'], + 'custom_field' => ['type' => 'text'], + ], + 'constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id']], + ], + ], + 'version' => [ + 'columns' => [ + 'id' => ['type' => 'integer'], + 'version_id' => ['type' => 'integer'], + 'model' => ['type' => 'string', 'null' => false], + 'foreign_key' => ['type' => 'integer', 'null' => false], + 'field' => ['type' => 'string', 'null' => false], + 'content' => ['type' => 'text'], + 'custom_field' => ['type' => 'text'], + ], + 'constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id']], + ], + ], + 'versions_with_user' => [ + 'columns' => [ + 'id' => ['type' => 'integer'], + 'version_id' => ['type' => 'integer'], + 'user_id' => ['type' => 'integer'], + 'model' => ['type' => 'string', 'null' => false], + 'foreign_key' => ['type' => 'integer', 'null' => false], + 'field' => ['type' => 'string', 'null' => false], + 'content' => ['type' => 'text'], + ], + 'constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id']], + ], + ], +];