Skip to content

Commit df2c62d

Browse files
cnizzardiniMasaKniChris Nizzardini
authored
MixerAPI v2.0.0 - CakePHP 5 support (#141)
* cleaing up deprecations, wip * cakephp5 compatibility * Ci updates with plugin tests (#137) - Now runs each plugin individually to catch any issues in the plugins composer.json - Moves coverage report into its own jobs * Require php81 cakephp44 (#138) * Require PHP 8.1 and CakePHP 4.4 * Require php 8.1 and cakephp 4.4 (#139) * Upgrade to CakePHP 5 * Update github actions * Get mixerapi/jwt-auth passing * composer changes for jwt-auth * Various fixes to JsonLdView and Core plugins for cake 5 * cake 5 * tests * update depedencies * fix bake test * fix collection-view * fix crud * remove grump * update plugin composers to cake 5 stable packages * ignore phpunit cache * remove debug code * fix bad merge on collection-view * remove phpunit cache * update plugin composers to cake 5 stable packages * downgrade phpmd to php 8.1 compatibility * fix failing jsonld test * fix failing jsonld test * appease the static analyzers * bounds test for php versions * remove grump package for plugin composer deps * debugging pipeline * fix coverage reporting * only run php 8.1 action once but do so with coverage reporting * split out mixerapi/core to avoid circular dependency problem * remove lock * split out mixerapi/core to avoid circular dependency problem * split out mixerapi/core to avoid circular dependency problem * min stability dev to pull in mixerapi/core * fix depedencies * fix composer * replace dev core package with stable one * update to latest swagger bake with cakephp 5 support * Handle non-named arg deprecations in Crud plugin * phpcs * mark test incomplete due to issue in MixerApi/Core NamespaceUtility --------- Co-authored-by: Masa Koni <masa.koni@riesenia.com> Co-authored-by: Chris Nizzardini <chris.nizzardini@thecmigroupa.ca>
1 parent 084a770 commit df2c62d

19 files changed

+237
-405
lines changed

assets/jsonld_config.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
*
1919
* @var string $entrypointUrl: Describes API default entry point
2020
* default: `/`
21+
*
22+
* @var string $connectionName: The name of your cakephp database connection (typically in config/app.php)
23+
* default: `default`
2124
*/
2225
return [
2326
'JsonLdView' => [
@@ -26,6 +29,7 @@
2629
'vocabUrl' => '/vocab',
2730
'title' => 'API Documentation',
2831
'description' => '',
29-
'entrypointUrl' => '/'
32+
'entrypointUrl' => '/',
33+
'connectionName' => 'default'
3034
]
31-
];
35+
];

composer.json

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,28 @@
55
"license": "MIT",
66
"keywords": ["cakephp", "json-ld", "jsonld", "cakephp json-ld", "cakephp jsonld"],
77
"require": {
8-
"php": "^8.0",
9-
"cakephp/cakephp": "^4.2",
10-
"mixerapi/core": "^1.0"
8+
"php": "^8.1",
9+
"cakephp/cakephp": "^5.0",
10+
"mixerapi/core": "^2.0"
11+
},
12+
"require-dev": {
13+
"josegonzalez/dotenv": "^3.2",
14+
"phpunit/phpunit": "^10.0"
1115
},
1216
"autoload": {
1317
"psr-4": {
1418
"MixerApi\\JsonLdView\\": "src/"
1519
}
1620
},
21+
"autoload-dev": {
22+
"psr-4": {
23+
"MixerApi\\JsonLdView\\": "plugins/json-ld-view/src/",
24+
"MixerApi\\JsonLdView\\Test\\": "plugins/json-ld-view/tests/",
25+
"MixerApi\\JsonLdView\\Test\\App\\": "plugins/json-ld-view/tests/test_app/src/"
26+
}
27+
},
1728
"support": {
29+
"issues": "https://github.com/mixerapi/mixerapi-dev/issues",
1830
"source": "https://github.com/mixerapi/json-ld-view"
1931
},
2032
"authors": [
@@ -23,6 +35,10 @@
2335
"role": "Organization"
2436
}
2537
],
26-
"prefer-stable": true,
27-
"minimum-stability": "dev"
38+
"config": {
39+
"allow-plugins": {
40+
"dealerdirect/phpcodesniffer-composer-installer": true,
41+
"cakephp/plugin-installer": true
42+
}
43+
}
2844
}

src/Controller/Component/JsonLdContextComponent.php

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,42 @@
44
namespace MixerApi\JsonLdView\Controller\Component;
55

66
use Cake\Controller\Component;
7-
use Cake\Controller\ComponentRegistry;
87
use Cake\Core\Configure;
9-
use Cake\Database\Connection;
10-
use Cake\Datasource\ConnectionManager;
11-
use Cake\Utility\Inflector;
8+
use Cake\ORM\Locator\LocatorAwareTrait;
129
use MixerApi\Core\Model\ModelFactory;
13-
use MixerApi\Core\Utility\NamespaceUtility;
1410
use MixerApi\JsonLdView\JsonLdEntityContext;
15-
use RuntimeException;
1611

1712
/**
1813
* Builds JSON-LD context for the given entity.
1914
*
2015
* @link https://json-ld.org/learn.html
21-
* @uses \Cake\Datasource\ConnectionManager
22-
* @uses \MixerApi\Core\Model\ModelFactory
23-
* @uses \MixerApi\Core\Utility\NamespaceUtility
24-
* @uses \MixerApi\JsonLdView\JsonLdEntityContext
2516
*/
2617
class JsonLdContextComponent extends Component
2718
{
28-
private array $data = [];
19+
use LocatorAwareTrait;
2920

3021
/**
31-
* @param \Cake\Controller\ComponentRegistry $registry ComponentRegistry
32-
* @param array $config configurations
22+
* Returns the entity in JSON-LD form as an array
23+
*
24+
* @param string $tableAlias The Table alias
25+
* @return array
3326
*/
34-
public function __construct(ComponentRegistry $registry, array $config = [])
27+
public function build(string $tableAlias): array
3528
{
36-
parent::__construct($registry, $config);
37-
3829
$config = Configure::read('JsonLdView');
3930
if (!empty($config['vocabUrl'])) {
40-
$this->data['@vocab'] = $config['vocabUrl'];
31+
$data['@vocab'] = $config['vocabUrl'];
4132
}
4233
if ($config['isHydra']) {
43-
$this->data['hydra'] = 'http://www.w3.org/ns/hydra/core#';
44-
}
45-
}
46-
47-
/**
48-
* Returns the entity in JSON-LD form as an array
49-
*
50-
* @param string $entityName entity name (singular)
51-
* @return array
52-
*/
53-
public function build(string $entityName): array
54-
{
55-
$table = NamespaceUtility::findClass(
56-
Configure::read('App.namespace') . '\Model\Table\\',
57-
Inflector::camelize(Inflector::pluralize($entityName)) . 'Table'
58-
);
59-
60-
$connection = ConnectionManager::get('default');
61-
62-
if (!$connection instanceof Connection) {
63-
throw new RuntimeException('Unable to get Database Connection instance');
34+
$data['hydra'] = 'http://www.w3.org/ns/hydra/core#';
6435
}
6536

66-
$model = (new ModelFactory($connection, new $table()))->create();
37+
$table = $this->getTableLocator()->get($tableAlias);
38+
$model = (new ModelFactory($table->getConnection(), $table))->create();
6739

6840
return [
6941
'@context' => array_merge(
70-
$this->data,
42+
$data ?? [],
7143
(new JsonLdEntityContext($model))->build()
7244
),
7345
];

src/Controller/Component/JsonLdVocabComponent.php

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
use Cake\Controller\Component;
88
use Cake\Controller\ComponentRegistry;
99
use Cake\Core\Configure;
10-
use Cake\Database\Connection;
1110
use Cake\Datasource\ConnectionManager;
11+
use Cake\ORM\Locator\LocatorAwareTrait;
12+
use Cake\ORM\Table;
1213
use MixerApi\Core\Model\Model;
1314
use MixerApi\Core\Model\ModelFactory;
1415
use MixerApi\Core\Model\ModelProperty;
@@ -17,20 +18,16 @@
1718
use MixerApi\JsonLdView\JsonLdEntityContext;
1819
use MixerApi\JsonLdView\JsonLdSchema;
1920
use ReflectionClass;
20-
use RuntimeException;
2121

2222
/**
2323
* Builds JSON-LD vocab for entities in your API.
2424
*
2525
* @link https://json-ld.org/learn.html
26-
* @uses \Cake\Collection\Collection
27-
* @uses \MixerApi\Core\Model\ModelFactory
28-
* @uses \MixerApi\Core\Utility\NamespaceUtility
29-
* @uses \MixerApi\JsonLdView\JsonLdEntityContext
30-
* @uses ReflectionClass
3126
*/
3227
class JsonLdVocabComponent extends Component
3328
{
29+
use LocatorAwareTrait;
30+
3431
private ?array $data;
3532

3633
private string $hydraPrefix = '';
@@ -77,16 +74,25 @@ public function __construct(ComponentRegistry $registry, array $config = [])
7774
*/
7875
public function build(): array
7976
{
80-
$connection = ConnectionManager::get('default');
81-
82-
if (!$connection instanceof Connection) {
83-
throw new RuntimeException('Unable to get Database Connection instance');
84-
}
85-
86-
$tables = NamespaceUtility::findClasses(Configure::read('App.namespace') . '\Model\Table');
77+
/** @var \Cake\Database\Connection $connection */
78+
$connection = ConnectionManager::get(Configure::read('JsonLdView.connectionName', 'default'));
79+
$fqn = Configure::read('App.namespace') . '\Model\Table';
80+
$tables = NamespaceUtility::findClasses($fqn);
8781

8882
foreach ($tables as $table) {
89-
$model = (new ModelFactory($connection, new $table()))->create();
83+
if (!class_exists($table)) {
84+
continue;
85+
}
86+
$reflection = new \ReflectionClass($table);
87+
if (!$reflection->isInstantiable() || !$reflection->isSubclassOf(Table::class)) {
88+
continue;
89+
}
90+
$class = $reflection->getShortName();
91+
if (str_ends_with($class, 'Table')) {
92+
$class = substr($class, 0, strlen($class) - 5);
93+
}
94+
$tableInstance = $this->getTableLocator()->get($class);
95+
$model = (new ModelFactory($connection, $tableInstance))->create();
9096
if ($model === null) {
9197
continue;
9298
}
@@ -177,7 +183,7 @@ function (JsonLdSchema $schema) use ($property) {
177183
* @param \MixerApi\Core\Model\ModelProperty $property ModelProperty
178184
* @return bool
179185
*/
180-
private function isPropertyRequired(ModelProperty $property)
186+
private function isPropertyRequired(ModelProperty $property): bool
181187
{
182188
$validationSet = $property->getValidationSet();
183189
if (is_bool($validationSet->isPresenceRequired())) {
@@ -194,7 +200,7 @@ private function isPropertyRequired(ModelProperty $property)
194200
* @param \MixerApi\Core\Model\ModelProperty $property ModelProperty
195201
* @return bool
196202
*/
197-
private function isPropertyWriteable(ModelProperty $property)
203+
private function isPropertyWriteable(ModelProperty $property): bool
198204
{
199205
if ($property->isPrimaryKey()) {
200206
return false;

src/Controller/JsonLdController.php

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33

44
namespace MixerApi\JsonLdView\Controller;
55

6+
use MixerApi\JsonLdView\View\JsonLdView;
7+
8+
/**
9+
* @property \MixerApi\JsonLdView\Controller\Component\JsonLdContextComponent $JsonLdContext
10+
* @property \MixerApi\JsonLdView\Controller\Component\JsonLdVocabComponent $JsonLdVocab
11+
*/
612
class JsonLdController extends AppController
713
{
8-
/**
9-
* @var \MixerApi\JsonLdView\Controller\Component\JsonLdContextComponent
10-
*/
11-
protected $JsonLdContext;
12-
13-
/**
14-
* @var \MixerApi\JsonLdView\Controller\Component\JsonLdVocabComponent
15-
*/
16-
protected $JsonLdVocab;
17-
1814
/**
1915
* @return void
2016
* @throws \Exception
@@ -26,19 +22,26 @@ public function initialize(): void
2622
$this->loadComponent('MixerApi/JsonLdView.JsonLdVocab');
2723
}
2824

25+
/**
26+
* @inheritDoc
27+
*/
28+
public function viewClasses(): array
29+
{
30+
return [JsonLdView::class];
31+
}
32+
2933
/**
3034
* Displays JSON-LD context for the given entity.
3135
*
3236
* @link https://json-ld.org/learn.html
3337
* @param string|null $entity Entity name
3438
* @return \Cake\Http\Response
3539
*/
36-
public function contexts($entity = null)
40+
public function contexts(?string $entity = null): \Cake\Http\Response
3741
{
3842
$context = $this->JsonLdContext->build($entity);
3943

40-
return $this
41-
->response
44+
return $this->getResponse()
4245
->withType('application/ld+json')
4346
->withStringBody(json_encode($context, JSON_PRETTY_PRINT));
4447
}
@@ -50,13 +53,12 @@ public function contexts($entity = null)
5053
* @return \Cake\Http\Response
5154
* @throws \ReflectionException
5255
*/
53-
public function vocab()
56+
public function vocab(): \Cake\Http\Response
5457
{
55-
$context = $this->JsonLdVocab->build();
58+
$vocab = $this->JsonLdVocab->build();
5659

57-
return $this
58-
->response
60+
return $this->getResponse()
5961
->withType('application/ld+json')
60-
->withStringBody(json_encode($context, JSON_PRETTY_PRINT));
62+
->withStringBody(json_encode($vocab, JSON_PRETTY_PRINT));
6163
}
6264
}

src/JsonLdDataInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ interface JsonLdDataInterface
1919
public function getJsonLdIdentifier(EntityInterface $entity): string;
2020

2121
/**
22-
* Returns a context for the entity such as /contexts/Actor which would return as
23-
* `"@context": "/contexts/Actor"`
22+
* Returns a context for the entity such as /contexts/Actors which would return as
23+
* `"@context": "/contexts/Actors"`. The context should be in plural form i.e. Actors instead of Actor.
2424
*
2525
* @return string
2626
*/

src/Plugin.php

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use Cake\Core\BasePlugin;
77
use Cake\Core\Configure;
88
use Cake\Core\PluginApplicationInterface;
9-
use MixerApi\Core\Response\ResponseModifier;
109

1110
class Plugin extends BasePlugin
1211
{
@@ -15,45 +14,35 @@ class Plugin extends BasePlugin
1514
*
1615
* @var string
1716
*/
18-
protected $name = 'MixerApi/JsonLdView';
17+
protected ?string $name = 'MixerApi/JsonLdView';
1918

2019
/**
2120
* Console middleware
2221
*
2322
* @var bool
2423
*/
25-
protected $consoleEnabled = false;
24+
protected bool $consoleEnabled = false;
2625

2726
/**
2827
* Enable middleware
2928
*
3029
* @var bool
3130
*/
32-
protected $middlewareEnabled = false;
31+
protected bool $middlewareEnabled = false;
3332

3433
/**
3534
* Register container services
3635
*
3736
* @var bool
3837
*/
39-
protected $servicesEnabled = false;
38+
protected bool $servicesEnabled = false;
4039

4140
/**
4241
* Load routes or not
4342
*
4443
* @var bool
4544
*/
46-
protected $routesEnabled = false;
47-
48-
/**
49-
* @var string
50-
*/
51-
private const EXT = 'jsonld';
52-
53-
/**
54-
* @var string
55-
*/
56-
private const VIEW_CLASS = 'MixerApi/JsonLdView.JsonLd';
45+
protected bool $routesEnabled = false;
5746

5847
/**
5948
* @param \Cake\Core\PluginApplicationInterface $app PluginApplicationInterface
@@ -78,7 +67,5 @@ public function bootstrap(PluginApplicationInterface $app): void
7867
'entrypointUrl' => '/',
7968
]);
8069
}
81-
82-
(new ResponseModifier(self::EXT, self::VIEW_CLASS))->listen();
8370
}
8471
}

0 commit comments

Comments
 (0)