Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cake5 #47

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI

on:
push:
branches:
- master
- cake5
pull_request:
branches:
- '*'

permissions:
contents: read

jobs:
testsuite:
uses: cakephp/.github/.github/workflows/[email protected]
secrets: inherit

cs-stan:
uses: cakephp/.github/.github/workflows/[email protected]
secrets: inherit
5 changes: 5 additions & 0 deletions .phive/phars.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpstan" version="1.10.32" installed="1.10.32" location="./tools/phpstan" copy="false"/>
<phar name="psalm" version="5.15.0" installed="5.15.0" location="./tools/psalm" copy="false"/>
</phive>
58 changes: 0 additions & 58 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ bin/cake plugin load Muffin/Tags
or by manually adding the following line to `src/Application.php`:

```php
$this->addPlugin('Muffin/Obfuscate');
$this->addPlugin('Muffin/Tags');
```

## Usage
31 changes: 25 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
@@ -30,13 +30,15 @@
"source": "https://github.com/usemuffin/tags"
},
"require": {
"cakephp/orm": "^4.0",
"cakephp/utility": "^4.0"
"cakephp/orm": "^5.0.0",
"cakephp/utility": "^5.0.0"
},
"require-dev": {
"cakephp/cakephp": "^4.0",
"cakephp/cakephp-codesniffer": "^4.0",
"phpunit/phpunit": "~8.5.0"
"cakephp/cakephp": "^5.0.0",
"cakephp/cakephp-codesniffer": "^5.0",
"cakephp/migrations": "^4.0.0",
"phpunit/phpunit": "^10.1.0",
"vimeo/psalm": "^5.15"
},
"suggest": {
"muffin/slug": "For adding slugs to tags"
@@ -53,6 +55,23 @@
}
},
"config": {
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"scripts": {
"cs-check": "phpcs --colors --parallel=16 -p src/ tests/",
"cs-fix": "phpcbf --colors --parallel=16 -p src/ tests/",
"phpstan": "tools/phpstan analyse",
"psalm": "tools/psalm --show-info=false",
"stan": [
"@phpstan",
"@psalm"
],
"stan-baseline": "tools/phpstan --generate-baseline",
"psalm-baseline": "tools/psalm --set-baseline=psalm-baseline.xml",
"stan-setup": "phive install",
"test": "phpunit"
}
}
2 changes: 1 addition & 1 deletion config/Migrations/20150412195500_create_tags_tags.php
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@

class CreateTagsTags extends AbstractMigration
{
public function change()
public function change(): void
{
$table = $this->table('tags_tags');

2 changes: 1 addition & 1 deletion config/Migrations/20150412195501_create_tags_tagged.php
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@

class CreateTagsTagged extends AbstractMigration
{
public function change()
public function change(): void
{
$table = $this->table('tags_tagged');

2 changes: 1 addition & 1 deletion config/Migrations/20151013144821_unique_tags.php
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ class UniqueTags extends AbstractMigration
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
public function change(): void
{
$table = $this->table('tags_tags');

6 changes: 6 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<ruleset name="Muffin/Obfuscate">
<config name="installed_paths" value="../../cakephp/cakephp-codesniffer" />
<rule ref="CakePHP" />
<arg value="s"/>
</ruleset>
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -2,3 +2,5 @@ parameters:
level: 6
checkGenericClassInNonGenericObjectType: false
checkMissingIterableValueType: false
paths:
- src/
40 changes: 16 additions & 24 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="./tests/bootstrap.php"
colors="true"
stopOnFailure="false"
>

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/bootstrap.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.2/phpunit.xsd" cacheDirectory=".phpunit.cache">
<coverage/>
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
<env name="FIXTURE_SCHEMA_METADATA" value="./tests/schema.php"/>
</php>
<testsuites>
<testsuite name="Muffin/Tags Test Cases">
<directory>./tests/</directory>
<directory>tests/TestCase/</directory>
</testsuite>
</testsuites>

<!-- Setup a listener for fixtures -->
<listeners>
<listener
class="\Cake\TestSuite\Fixture\FixtureInjector"
file="./vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureInjector.php">
<arguments>
<object class="\Cake\TestSuite\Fixture\FixtureManager" />
</arguments>
</listener>
</listeners>

<filter>
<whitelist>
<directory suffix=".php">./src/</directory>
</whitelist>
</filter>
<extensions>
<bootstrap class="Cake\TestSuite\Fixture\Extension\PHPUnitExtension"/>
</extensions>
<source>
<include>
<directory suffix=".php">src/</directory>
</include>
</source>
</phpunit>
17 changes: 9 additions & 8 deletions src/Model/Behavior/TagBehavior.php
Original file line number Diff line number Diff line change
@@ -19,9 +19,9 @@ class TagBehavior extends Behavior
* - delimiter: The delimiter used to explode() the tags. Default is comma.
* - separator: Namespace separator, by default semicolon.
*
* @var array
* @var array<string, mixed>
*/
protected $_defaultConfig = [
protected array $_defaultConfig = [
'delimiter' => ',',
'separator' => ':',
'namespace' => null,
@@ -65,7 +65,7 @@ public function initialize(array $config): void
/**
* Return lists of event's this behavior is interested in.
*
* @return array Events list.
* @return array<string, mixed> Events list.
*/
public function implementedEvents(): array
{
@@ -80,7 +80,7 @@ public function implementedEvents(): array
* @param \ArrayObject $options Options.
* @return void
*/
public function beforeMarshal(EventInterface $event, ArrayObject $data, ArrayObject $options)
public function beforeMarshal(EventInterface $event, ArrayObject $data, ArrayObject $options): void
{
$field = $this->getConfig('tagsAssoc.propertyName');
if (!empty($data[$field]) && (!is_array($data[$field]) || !array_key_exists('_ids', $data[$field]))) {
@@ -192,7 +192,6 @@ public function attachCounters(): void
}

if (!$counterCache->getConfig($taggedAlias)) {
$field = key($config['taggedCounter']);
$config['taggedCounter']['tag_count']['conditions'] = [
$taggedTable->aliasField($this->getConfig('fkTableField')) => $this->_table->getTable(),
];
@@ -206,7 +205,7 @@ public function attachCounters(): void
* @param array|string $tags List of tags as an array or a delimited string (comma by default).
* @return array Normalized tags valid to be marshaled.
*/
public function normalizeTags($tags): array
public function normalizeTags(array|string $tags): array
{
if (is_string($tags)) {
$tags = explode($this->getConfig('delimiter'), $tags);
@@ -237,6 +236,7 @@ public function normalizeTags($tags): array
}
[$id, $label] = $this->_normalizeTag($tag);
$result[] = $common + compact(empty($id) ? $df : $pk) + [
'label' => $label,
'tag_key' => $tagKey,
];
}
@@ -259,7 +259,7 @@ protected function _getTagKey(string $tag): string
* Checks if a tag already exists and returns the id if yes.
*
* @param string $tag Tag key.
* @return null|int
* @return int|null
*/
protected function _tagExists(string $tag): ?int
{
@@ -291,7 +291,8 @@ protected function _normalizeTag(string $tag): array
$namespace = '';
$label = $tag;
$separator = $this->getConfig('separator');
if (strpos($tag, $separator) !== false) {
if (str_contains($tag, $separator)) {
/** @psalm-suppress ArgumentTypeCoercion */
[$namespace, $label] = explode($separator, $tag);
}

2 changes: 1 addition & 1 deletion src/Model/Entity/Tag.php
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ class Tag extends Entity
*
* @var array
*/
public $accessible = [
public array $accessible = [
'*' => false,
'label' => true,
];
24 changes: 13 additions & 11 deletions src/Model/Entity/TagAwareTrait.php
Original file line number Diff line number Diff line change
@@ -3,30 +3,31 @@

namespace Muffin\Tags\Model\Entity;

use Cake\Datasource\EntityInterface;
use Cake\ORM\TableRegistry;

trait TagAwareTrait
{
/**
* Tag entity with given tags.
*
* @param string|array $tags List of tags as an array or a delimited string (comma by default).
* @param array|string $tags List of tags as an array or a delimited string (comma by default).
* @param bool $merge Whether to merge or replace tags. Default true.
* @return bool|\Cake\ORM\Entity False on failure, entity on success.
* @return \Cake\Datasource\EntityInterface|bool False on failure, entity on success.
*/
public function tag($tags, bool $merge = true)
public function tag(array|string $tags, bool $merge = true): EntityInterface|bool
{
return $this->_updateTags($tags, $merge ? 'append' : 'replace');
}

/**
* Untag entity from given tags.
*
* @param string|array|null $tags List of tags as an array or a delimited string (comma by default).
* @param array|string|null $tags List of tags as an array or a delimited string (comma by default).
* If no value is passed all tags will be removed.
* @return bool|\Cake\ORM\Entity False on failure, entity on success.
* @return \Cake\Datasource\EntityInterface|bool False on failure, entity on success.
*/
public function untag($tags = null)
public function untag(array|string|null $tags = null): EntityInterface|bool
{
if (empty($tags)) {
return $this->_updateTags([], 'replace');
@@ -41,8 +42,9 @@ public function untag($tags = null)

$tags = $this->get($property);
if (!$tags) {
$contain = [$behavior->getConfig('tagsAlias')];
$tags = $table->get($id, compact('contain'))->get($property);
$tags = $table
->get(primaryKey: $id, contain: [$behavior->getConfig('tagsAlias')])
->get($property);
}

$tagsTable = $table->{$behavior->getConfig('tagsAlias')};
@@ -81,12 +83,12 @@ function ($i) {
/**
* Tag entity with given tags.
*
* @param string|array $tags List of tags as an array or a delimited string (comma by default).
* @param array|string $tags List of tags as an array or a delimited string (comma by default).
* @param string $saveStrategy Whether to merge or replace tags.
* Valid values 'append', 'replace'.
* @return bool|\Cake\ORM\Entity False on failure, entity on success.
* @return \Cake\Datasource\EntityInterface|bool False on failure, entity on success.
*/
protected function _updateTags($tags, string $saveStrategy)
protected function _updateTags(array|string $tags, string $saveStrategy): EntityInterface|bool
{
$table = TableRegistry::getTableLocator()->get($this->source());
$behavior = $table->behaviors()->Tag;
2 changes: 1 addition & 1 deletion src/Model/Entity/Tagged.php
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ class Tagged extends Entity
*
* @var array
*/
public $accessible = [
public array $accessible = [
'*' => false,
];
}
12 changes: 6 additions & 6 deletions src/Plugin.php → src/TagsPlugin.php
Original file line number Diff line number Diff line change
@@ -8,33 +8,33 @@
/**
* Plugin class for tags
*/
class Plugin extends BasePlugin
class TagsPlugin extends BasePlugin
{
/**
* Plugin name.
*
* @var string
* @var string|null
*/
protected $name = 'Tags';
protected ?string $name = 'Tags';

/**
* Do bootstrapping or not
*
* @var bool
*/
protected $bootstrapEnabled = false;
protected bool $bootstrapEnabled = false;

/**
* Load routes or not
*
* @var bool
*/
protected $routesEnabled = false;
protected bool $routesEnabled = false;

/**
* Console middleware
*
* @var bool
*/
protected $consoleEnabled = false;
protected bool $consoleEnabled = false;
}
13 changes: 2 additions & 11 deletions tests/Fixture/BunsFixture.php
Original file line number Diff line number Diff line change
@@ -7,18 +7,9 @@

class BunsFixture extends TestFixture
{
public $table = 'tags_buns';
public string $table = 'tags_buns';

public $fields = [
'id' => ['type' => 'integer'],
'name' => ['type' => 'string', 'length' => 255],
'tag_count' => ['type' => 'integer', 'null' => true, 'default' => 0],
'_constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
];

public $records = [
public array $records = [
[
'name' => 'square',
'tag_count' => 1,
13 changes: 2 additions & 11 deletions tests/Fixture/MuffinsFixture.php
Original file line number Diff line number Diff line change
@@ -7,18 +7,9 @@

class MuffinsFixture extends TestFixture
{
public $table = 'tags_muffins';
public string $table = 'tags_muffins';

public $fields = [
'id' => ['type' => 'integer'],
'name' => ['type' => 'string', 'length' => 255],
'tag_count' => ['type' => 'integer', 'null' => true, 'default' => 0],
'_constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
];

public $records = [
public array $records = [
[
'name' => 'blue',
'tag_count' => 2,
16 changes: 2 additions & 14 deletions tests/Fixture/TaggedFixture.php
Original file line number Diff line number Diff line change
@@ -7,21 +7,9 @@

class TaggedFixture extends TestFixture
{
public $table = 'tags_tagged';
public string $table = 'tags_tagged';

public $fields = [
'id' => ['type' => 'integer'],
'tag_id' => ['type' => 'integer', 'null' => false],
'fk_id' => ['type' => 'integer', 'null' => false],
'fk_table' => ['type' => 'string', 'limit' => 255, 'null' => false],
'created' => ['type' => 'datetime', 'null' => true],
'modified' => ['type' => 'datetime', 'null' => true],
'_constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
];

public $records = [
public array $records = [
[
'tag_id' => 1,
'fk_id' => 1,
18 changes: 2 additions & 16 deletions tests/Fixture/TagsFixture.php
Original file line number Diff line number Diff line change
@@ -7,23 +7,9 @@

class TagsFixture extends TestFixture
{
public $table = 'tags_tags';
public string $table = 'tags_tags';

public $fields = [
'id' => ['type' => 'integer'],
'namespace' => ['type' => 'string', 'length' => 255, 'null' => true],
'tag_key' => ['type' => 'string', 'length' => 255],
'slug' => ['type' => 'string', 'length' => 255],
'label' => ['type' => 'string', 'length' => 255],
'counter' => ['type' => 'integer', 'unsigned' => true, 'default' => 0, 'null' => true],
'created' => ['type' => 'datetime', 'null' => true],
'modified' => ['type' => 'datetime', 'null' => true],
'_constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
];

public $records = [
public array $records = [
[
'namespace' => null,
'tag_key' => 'color',
15 changes: 8 additions & 7 deletions tests/TestCase/Model/Behavior/TagBehaviorTest.php
Original file line number Diff line number Diff line change
@@ -3,12 +3,12 @@

namespace Muffin\Tags\Test\TestCase\Model\Behavior;

use Cake\ORM\TableRegistry;
use Cake\TestSuite\TestCase;
use RuntimeException;

class TagBehaviorTest extends TestCase
{
public $fixtures = [
public array $fixtures = [
'plugin.Muffin/Tags.Buns',
'plugin.Muffin/Tags.Muffins',
'plugin.Muffin/Tags.Tagged',
@@ -19,7 +19,7 @@ public function setUp(): void
{
parent::setUp();

$table = TableRegistry::getTableLocator()->get('Muffin/Tags.Muffins', ['table' => 'tags_muffins']);
$table = $this->getTableLocator()->get('Muffin/Tags.Muffins', ['table' => 'tags_muffins']);
$table->addBehavior('Muffin/Tags.Tag');

$this->Table = $table;
@@ -29,7 +29,7 @@ public function setUp(): void
public function tearDown(): void
{
parent::tearDown();
TableRegistry::getTableLocator()->clear();
$this->getTableLocator()->clear();
unset($this->Behavior);
}

@@ -88,6 +88,7 @@ public function testNormalizeTags(): void
],
'id' => '3',
'tag_key' => '3-foobar',
'label' => 'foobar',
],
2 => [
'_joinData' => [
@@ -254,9 +255,9 @@ public function testCounterCacheDisabled(): void

public function testCounterCacheFieldException(): void
{
$this->expectException(\RuntimeException::class);
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Field "non_existent" does not exist in table "tags_buns"');
$table = TableRegistry::getTableLocator()->get('Muffin/Tags.Buns', ['table' => 'tags_buns']);
$table = $this->getTableLocator()->get('Muffin/Tags.Buns', ['table' => 'tags_buns']);
$table->addBehavior('Muffin/Tags.Tag', [
'taggedCounter' => [
'non_existent' => [],
@@ -266,6 +267,6 @@ public function testCounterCacheFieldException(): void

public function testAssociationConditionsAreWorkingAsExpected(): void
{
$this->assertEquals(2, count($this->Table->get(1, ['contain' => ['Tags']])->tags));
$this->assertEquals(2, count($this->Table->get(primaryKey: 1, contain: ['Tags'])->tags));
}
}
7 changes: 3 additions & 4 deletions tests/TestCase/Model/Entity/TagAwareTraitTest.php
Original file line number Diff line number Diff line change
@@ -3,13 +3,12 @@

namespace Muffin\Tags\Test\TestCase\Model\Entity;

use Cake\ORM\TableRegistry;
use Cake\TestSuite\TestCase;
use Muffin\Tags\Test\App\Model\Entity\TagsMuffin;

class TagAwareTraitTest extends TestCase
{
public $fixtures = [
public array $fixtures = [
'plugin.Muffin/Tags.Muffins',
'plugin.Muffin/Tags.Tagged',
'plugin.Muffin/Tags.Tags',
@@ -19,7 +18,7 @@ public function setUp(): void
{
parent::setUp();

$table = TableRegistry::getTableLocator()->get('Muffin/Tags.Muffins', ['table' => 'tags_muffins']);
$table = $this->getTableLocator()->get('Muffin/Tags.Muffins', ['table' => 'tags_muffins']);
$table->addBehavior('Muffin/Tags.Tag');

$this->Table = $table;
@@ -29,7 +28,7 @@ public function setUp(): void
public function tearDown(): void
{
parent::tearDown();
TableRegistry::getTableLocator()->clear();
$this->getTableLocator()->clear();
unset($this->Behavior);
}

20 changes: 16 additions & 4 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
<?php
declare(strict_types=1);

use Cake\Core\Plugin;
use Cake\TestSuite\Fixture\SchemaLoader;
use Muffin\Tags\TagsPlugin;
use function Cake\Core\env;

/**
* Test suite bootstrap.
*
* This function is used to find the location of CakePHP whether CakePHP
* has been installed as a dependency of the plugin, or the plugin is itself
* installed as a dependency of an application.
*
* @throws \Exception
*/
$findRoot = function ($root) {
do {
@@ -16,12 +23,17 @@
return $root;
}
} while ($root !== $lastRoot);

throw new Exception("Cannot find the root of the application, unable to run tests");
throw new Exception('Cannot find the root of the application, unable to run tests');
};
$root = $findRoot(__FILE__);
unset($findRoot);

chdir($root);

require $root . '/vendor/cakephp/cakephp/tests/bootstrap.php';

Plugin::getCollection()->add(new TagsPlugin());

// Create test database schema
if (env('FIXTURE_SCHEMA_METADATA')) {
$loader = new SchemaLoader();
$loader->loadInternalFile(env('FIXTURE_SCHEMA_METADATA'));
}
53 changes: 53 additions & 0 deletions tests/schema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);

return [
'tags_buns' => [
'columns' => [
'id' => ['type' => 'integer'],
'name' => ['type' => 'string', 'length' => 255],
'tag_count' => ['type' => 'integer', 'null' => true, 'default' => 0],
],
'constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
],
'tags_muffins' => [
'columns' => [
'id' => ['type' => 'integer'],
'name' => ['type' => 'string', 'length' => 255],
'tag_count' => ['type' => 'integer', 'null' => true, 'default' => 0],
],
'constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
],
'tags_tagged' => [
'columns' => [
'id' => ['type' => 'integer'],
'tag_id' => ['type' => 'integer', 'null' => false],
'fk_id' => ['type' => 'integer', 'null' => false],
'fk_table' => ['type' => 'string', 'limit' => 255, 'null' => false],
'created' => ['type' => 'datetime', 'null' => true],
'modified' => ['type' => 'datetime', 'null' => true],
],
'constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
],
'tags_tags' => [
'columns' => [
'id' => ['type' => 'integer'],
'namespace' => ['type' => 'string', 'length' => 255, 'null' => true],
'tag_key' => ['type' => 'string', 'length' => 255],
'slug' => ['type' => 'string', 'length' => 255],
'label' => ['type' => 'string', 'length' => 255],
'counter' => ['type' => 'integer', 'unsigned' => true, 'default' => 0, 'null' => true],
'created' => ['type' => 'datetime', 'null' => true],
'modified' => ['type' => 'datetime', 'null' => true],
],
'constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
],
],
];
5 changes: 5 additions & 0 deletions tests/test_app/src/Application.php
Original file line number Diff line number Diff line change
@@ -4,7 +4,12 @@
namespace Muffin\Tags\Test\App;

use Cake\Http\BaseApplication;
use Cake\Http\MiddlewareQueue;

class Application extends BaseApplication
{
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
return $middlewareQueue;
}
}
2 changes: 1 addition & 1 deletion tests/test_app/src/Model/Entity/TagsMuffin.php
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ class TagsMuffin extends Entity
{
use TagAwareTrait;

public function source($source = null)
public function source($source = null): string
{
return 'Muffin/Tags.Muffins';
}