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 #112

Merged
merged 21 commits into from
May 11, 2024
Merged

Cake5 #112

Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: ['7.4', '8.0', '8.3']
php-version: ['8.1', '8.2', '8.3']
db-type: ['mysql', 'pgsql']
prefer-lowest: ['']
include:
- php-version: '7.4'
- php-version: '8.1'
db-type: 'sqlite'
prefer-lowest: 'prefer-lowest'

Expand Down Expand Up @@ -61,14 +61,14 @@ jobs:
if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:[email protected]/cakephp'; fi
if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:[email protected]/postgres'; fi

if [[ ${{ matrix.php-version }} == '7.4' && ${{ matrix.db-type }} == 'mysql' ]]; then
vendor/bin/phpunit --coverage-clover=coverage.xml
if [[ ${{ matrix.php-version }} == '8.1' && ${{ matrix.db-type }} == 'mysql' ]]; then
vendor/bin/phpunit tests/TestCase --coverage-clover=coverage.xml
else
vendor/bin/phpunit
vendor/bin/phpunit tests/TestCase
fi

- name: Code Coverage Report
if: success() && matrix.php-version == '7.4' && matrix.db-type == 'mysql'
if: success() && matrix.php-version == '8.1' && matrix.db-type == 'mysql'
uses: codecov/codecov-action@v1

cs-stan:
Expand All @@ -81,10 +81,10 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
php-version: '8.1'
extensions: mbstring, intl
coverage: none
tools: psalm:4, phpstan:1
tools: psalm:5.23.1, phpstan:1.10.65

- name: Composer Install
run: composer require cakephp/cakephp-codesniffer:^4.2
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
/plugins
/vendor
.phpunit.result.cache
/.idea
*.diff
*.cache
15 changes: 11 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,19 @@
"irc": "irc://irc.freenode.org/muffin"
},
"require": {
"cakephp/orm": "^4.5"
"cakephp/orm": "^5.0"
},
"require-dev": {
"cakephp/cakephp": "^4.5",
"cakephp/cakephp-codesniffer": "^4.2",
"phpunit/phpunit": "^9.3"
"cakephp/cakephp": "^5.0",
"cakephp/cakephp-codesniffer": "^5.0",
"phpunit/phpunit": "^10.5.5",
"ext-mbstring": "*",
"vimeo/psalm": "5.23.1",
"phpstan/phpstan": "1.10.65"
},
"scripts": {
"cs-check": "phpcs --colors --parallel=16 -p src/ tests/",
"cs-fix": "phpcbf --colors --parallel=16 -p src/ tests/"
},
"autoload": {
"psr-4": {
Expand Down
18 changes: 2 additions & 16 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
parameters:
level: 6
level: 8
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
treatPhpDocTypesAsCertain: false
paths:
- src/
ignoreErrors:
-
message: "#^Call to an undefined method Cake\\\\Datasource\\\\RepositoryInterface\\:\\:callFinder\\(\\)\\.$#"
count: 1
path: src/Datasource/Query.php

-
message: "#^Call to an undefined method Cake\\\\Datasource\\\\RepositoryInterface\\:\\:getName\\(\\)\\.$#"
count: 1
path: src/Datasource/Query.php

-
message: "#^Method Muffin\\\\Webservice\\\\Datasource\\\\Query\\:\\:execute\\(\\) should return bool\\|int\\|Muffin\\\\Webservice\\\\Datasource\\\\ResultSet\\|Muffin\\\\Webservice\\\\Model\\\\Resource but returns Cake\\\\Datasource\\\\ResultSetInterface\\.$#"
count: 1
path: src/Datasource/Query.php
23 changes: 10 additions & 13 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
<?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" bootstrap="./tests/bootstrap.php" colors="true" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.2/phpunit.xsd" cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="Webservice Test Cases">
<directory>./tests/</directory>
</testsuite>
</testsuites>

<extensions>
<extension class="Cake\TestSuite\Fixture\PHPUnitExtension"/>
<bootstrap class="Cake\TestSuite\Fixture\Extension\PHPUnitExtension"/>
</extensions>

<filter>
<whitelist>
<php>
<ini name="memory_limit" value="-1"/>
<env name="FIXTURE_SCHEMA_METADATA" value="./tests/schema.php"/>
</php>
<source>
<include>
<directory suffix=".php">./src/</directory>
</whitelist>
</filter>
</include>
</source>
</phpunit>
18 changes: 7 additions & 11 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<?xml version="1.0"?>
<psalm
errorLevel="2"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
findUnusedCode="false"
findUnusedBaselineEntry="true"
>
<projectFiles>
<directory name="src" />
Expand All @@ -13,16 +16,9 @@
</projectFiles>

<issueHandlers>

<PropertyNotSetInConstructor errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingClosureParamType errorLevel="info" />

<DocblockTypeContradiction errorLevel="info" />
<RedundantConditionGivenDocblockType errorLevel="info" />

<UnsafeInstantiation errorLevel="info" />

<UnresolvableInclude errorLevel="info" />
<RedundantConditionGivenDocblockType errorLevel="suppress"/>
<MissingClosureParamType errorLevel="suppress"/>
<MissingClosureReturnType errorLevel="suppress"/>
<PropertyNotSetInConstructor errorLevel="suppress"/>
</issueHandlers>
</psalm>
83 changes: 72 additions & 11 deletions src/Datasource/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,33 @@
namespace Muffin\Webservice\Datasource;

use Cake\Core\App;
use Cake\Datasource\ConnectionInterface;
use Muffin\Webservice\Datasource\Exception\MissingConnectionException;
use Muffin\Webservice\Webservice\Driver\AbstractDriver;
use Muffin\Webservice\Webservice\Exception\MissingDriverException;
use Muffin\Webservice\Webservice\Exception\UnexpectedDriverException;
use Psr\SimpleCache\CacheInterface;

/**
* Class Connection
*
* @method \Muffin\Webservice\Webservice\Driver\AbstractDriver setWebservice(string $name, \Muffin\Webservice\Webservice\WebserviceInterface $webservice) Proxy method through to the Driver
* @method \Muffin\Webservice\Webservice\WebserviceInterface getWebservice(string $name) Proxy method through to the Driver
* @method string configName() Proxy method through to the Driver
*/
class Connection
class Connection implements ConnectionInterface
{
/**
* Driver
*
* @var \Muffin\Webservice\Webservice\Driver\AbstractDriver
*/
protected $_driver;
protected AbstractDriver $_driver;

protected CacheInterface $cacher;

/**
* The connection name in the connection manager.
*/
protected string $configName = '';

/**
* Constructor
Expand All @@ -33,17 +40,70 @@ class Connection
*/
public function __construct(array $config)
{
if (isset($config['name'])) {
$this->configName = $config['name'];
}
$config = $this->_normalizeConfig($config);
/** @psalm-var class-string<\Muffin\Webservice\Webservice\Driver\AbstractDriver> */
$driver = $config['driver'];
unset($config['driver'], $config['service']);

$this->_driver = new $driver($config);
$tempDriver = new $driver($config);

/** @psalm-suppress TypeDoesNotContainType */
if (!($this->_driver instanceof AbstractDriver)) {
throw new UnexpectedDriverException(['driver' => $driver]);
}
assert(
$tempDriver instanceof AbstractDriver,
'`$config[\'driver\']` must be an instance of `' . AbstractDriver::class . '`.'
);
$this->_driver = $tempDriver;
}

/**
* @param \Psr\SimpleCache\CacheInterface $cacher The cacher instance to use for query caching.
* @return self
* @psalm-suppress LessSpecificImplementedReturnType
*/
public function setCacher(CacheInterface $cacher): ConnectionInterface
{
$this->cacher = $cacher;

return $this;
}

/** @return \Psr\SimpleCache\CacheInterface */
public function getCacher(): CacheInterface
{
return $this->cacher;
}

/**
* {@inheritDoc}
*
* @param string $role Parameter is not used
* @see \Cake\Datasource\ConnectionInterface::getDriver()
* @return \Muffin\Webservice\Webservice\Driver\AbstractDriver
*/
public function getDriver(string $role = self::ROLE_WRITE): AbstractDriver
{
return $this->_driver;
}

/**
* Get the configuration name for this connection.
*
* @return string
*/
public function configName(): string
{
return $this->configName;
}

/**
* Get the config data for this connection.
*
* @return array<string, mixed>
*/
public function config(): array
{
return $this->_driver->getConfig();
}

/**
Expand Down Expand Up @@ -77,8 +137,9 @@ protected function _normalizeConfig(array $config): array
* @param array $args Arguments to pass-through
* @return mixed
*/
public function __call($method, $args)
public function __call(string $method, array $args): mixed
{
/* @phpstan-ignore-next-line This is supported behavior for now: https://www.php.net/manual/en/function.call-user-func-array.php (example 1) */
return call_user_func_array([$this->_driver, $method], $args);
}
}
2 changes: 1 addition & 1 deletion src/Datasource/Exception/MissingConnectionException.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ class MissingConnectionException extends CakeException
*
* @var string
*/
protected $_messageTemplate = 'No `%s` connection configured.';
protected string $_messageTemplate = 'No `%s` connection configured.';
}
11 changes: 5 additions & 6 deletions src/Datasource/Marshaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Marshaller
*
* @var \Muffin\Webservice\Model\Endpoint
*/
protected $_endpoint;
protected Endpoint $_endpoint;

/**
* Constructor.
Expand Down Expand Up @@ -53,7 +53,6 @@ public function one(array $data, array $options = []): EntityInterface
[$data, $options] = $this->_prepareDataAndOptions($data, $options);

$primaryKey = (array)$this->_endpoint->getPrimaryKey();
/** @psalm-var class-string<\Muffin\Webservice\Model\Resource> */
$resourceClass = $this->_endpoint->getResourceClass();
$entity = new $resourceClass();
$entity->setSource($this->_endpoint->getRegistryAlias());
Expand Down Expand Up @@ -121,7 +120,7 @@ protected function _validate(array $data, array $options, bool $isNew): array
$validator = $options['validator'];
}

if (!is_callable([$validator, 'errors'])) {
if (!is_callable([$validator, 'validate'])) {
throw new RuntimeException(sprintf(
'"validate" must be a boolean, a string or an object with method "errors()". Got %s instead.',
gettype($options['validate'])
Expand Down Expand Up @@ -165,7 +164,7 @@ protected function _prepareDataAndOptions(array $data, array $options): array
*
* @param array $data The data to hydrate.
* @param array $options List of options
* @return \Cake\Datasource\EntityInterface[] An array of hydrated records.
* @return array<\Cake\Datasource\EntityInterface> An array of hydrated records.
* @see \Muffin\Webservice\Model\Endpoint::newEntities()
*/
public function many(array $data, array $options = []): array
Expand Down Expand Up @@ -264,9 +263,9 @@ public function merge(EntityInterface $entity, array $data, array $options = [])
* data merged in
* @param array $data list of arrays to be merged into the entities
* @param array $options List of options.
* @return \Cake\Datasource\EntityInterface[]
* @return array<\Cake\Datasource\EntityInterface>
*/
public function mergeMany($entities, array $data, array $options = []): array
public function mergeMany(iterable $entities, array $data, array $options = []): array
{
$primary = (array)$this->_endpoint->getPrimaryKey();

Expand Down
Loading
Loading