Skip to content

Commit

Permalink
Merge pull request #32 from CakeDC/3.next
Browse files Browse the repository at this point in the history
3.next
  • Loading branch information
itosho authored Mar 7, 2024
2 parents 1555b25 + e3f30ea commit a6ee26e
Show file tree
Hide file tree
Showing 17 changed files with 210 additions and 153 deletions.
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
- 3.next
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>
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ CakePHP behavior plugin for easily generating some complicated queries like (bul
[![License](https://poser.pugx.org/itosho/easy-query/license)](https://packagist.org/packages/itosho/easy-query)

## Requirements
- PHP 7.2+
- CakePHP 4.0+
- MySQL 5.6+

:warning: For CakePHP3.x, use 1.x branch.
- PHP 8.1+
- CakePHP 5.0+
- MySQL 8.0+ / MariaDB 10.4+

## Installation
```bash
Expand Down
15 changes: 11 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@
"source": "https://github.com/itosho/easy-query"
},
"require": {
"php": ">=7.2.0",
"cakephp/orm": "^4.0"
"php": ">=8.1",
"cakephp/orm": "^5.0.0"
},
"require-dev": {
"cakephp/cakephp": "^4.0",
"phpunit/phpunit": "^8.5"
"cakephp/cakephp": "^5.0.0",
"phpunit/phpunit": "^10.1.0",
"cakephp/cakephp-codesniffer": "^5.0",
"vimeo/psalm": "^5.15"
},
"autoload": {
"psr-4": {
Expand All @@ -42,5 +44,10 @@
"psr-4": {
"Itosho\\EasyQuery\\Test\\": "tests"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}
5 changes: 5 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<ruleset name="itosho/easy-query">
<config name="installed_paths" value="../../cakephp/cakephp-codesniffer" />
<rule ref="CakePHP" />
</ruleset>
2 changes: 2 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameters:
ignoreErrors: []
10 changes: 8 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
includes:
- phpstan-baseline.neon

parameters:
checkMissingIterableValueType: false
ignoreErrors: []
level: 6
checkGenericClassInNonGenericObjectType: false
checkMissingIterableValueType: false
paths:
- src/
38 changes: 12 additions & 26 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,37 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
colors="true"
processIsolation="false"
stopOnFailure="false"
bootstrap="./tests/bootstrap.php"
>
<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>

<!-- Add any additional test suites you want to run here -->
<testsuites>
<testsuite name="EasyQuery Test Suite">
<directory>./tests/TestCase</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>
15 changes: 15 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
</psalm>
52 changes: 27 additions & 25 deletions src/Model/Behavior/InsertBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,35 @@

use Cake\Database\Expression\QueryExpression;
use Cake\Database\StatementInterface;
use Cake\I18n\FrozenTime;
use Cake\Datasource\EntityInterface;
use Cake\I18n\DateTime;
use Cake\ORM\Behavior;
use Cake\ORM\Entity;
use Cake\ORM\Query;
use Cake\ORM\TableRegistry;
use Cake\ORM\Locator\LocatorAwareTrait;
use Cake\ORM\Query\SelectQuery;
use LogicException;

/**
* Insert Behavior
*/
class InsertBehavior extends Behavior
{
use LocatorAwareTrait;

/**
* Default config
*
* @var array
* @var array<string, mixed>
*/
protected $_defaultConfig = [
protected array $_defaultConfig = [
'event' => ['beforeSave' => true],
];

/**
* execute bulk insert query
*
* @param Entity[] $entities insert entities
* @throws LogicException no save data
* @return StatementInterface query result
* @param array<\Cake\Datasource\EntityInterface> $entities insert entities
* @throws \LogicException no save data
* @return \Cake\Database\StatementInterface query result
*/
public function bulkInsert(array $entities): StatementInterface
{
Expand All @@ -50,7 +52,7 @@ public function bulkInsert(array $entities): StatementInterface
$fields = array_keys($saveData[0]);

$query = $this->_table
->query()
->insertQuery()
->insert($fields);
$query->clause('values')->setValues($saveData);

Expand All @@ -60,31 +62,31 @@ public function bulkInsert(array $entities): StatementInterface
/**
* execute insert select query for saving a record just once
*
* @param Entity $entity insert entity
* @param \Cake\Datasource\EntityInterface $entity insert entity
* @param array|null $conditions search conditions
* @return StatementInterface query result
* @return \Cake\Database\StatementInterface query result
*/
public function insertOnce(Entity $entity, array $conditions = null): StatementInterface
public function insertOnce(EntityInterface $entity, ?array $conditions = null): StatementInterface
{
if ($this->_config['event']['beforeSave']) {
$this->_table->dispatchEvent('Model.beforeSave', compact('entity'));
}

$entity->setVirtual([]);
$insertData = $entity->toArray();
if (isset($insertData['created']) && !is_null($insertData['created'])) {
$insertData['created'] = FrozenTime::now()->toDateTimeString();
if (isset($insertData['created'])) {
$insertData['created'] = DateTime::now()->toDateTimeString();
}
if (isset($insertData['modified']) && !is_null($insertData['modified'])) {
$insertData['modified'] = FrozenTime::now()->toDateTimeString();
if (isset($insertData['modified'])) {
$insertData['modified'] = DateTime::now()->toDateTimeString();
}

$fields = array_keys($insertData);
$existsConditions = $conditions;
if (is_null($existsConditions)) {
$existsConditions = $this->getExistsConditions($insertData);
}
$query = $this->_table->query()->insert($fields);
$query = $this->_table->insertQuery()->insert($fields);
$subQuery = $this
->buildTmpTableSelectQuery($insertData)
->where(function (QueryExpression $exp) use ($existsConditions) {
Expand All @@ -95,7 +97,7 @@ public function insertOnce(Entity $entity, array $conditions = null): StatementI
return $exp->notExists($query);
})
->limit(1);
/* @phpstan-ignore-next-line */

$query = $query->epilog($subQuery);

return $query->execute();
Expand All @@ -105,10 +107,10 @@ public function insertOnce(Entity $entity, array $conditions = null): StatementI
* build tmp table's select query for insert select query
*
* @param array $insertData insert data
* @throws LogicException select query is invalid
* @return Query tmp table's select query
* @return \Cake\ORM\Query\SelectQuery tmp table's select query
* @throws \LogicException select query is invalid
*/
private function buildTmpTableSelectQuery($insertData): Query
private function buildTmpTableSelectQuery(array $insertData): SelectQuery
{
$driver = $this->_table
->getConnection()
Expand All @@ -118,15 +120,15 @@ private function buildTmpTableSelectQuery($insertData): Query
foreach ($insertData as $key => $value) {
$col = $driver->quoteIdentifier($key);
if (is_null($value)) {
$schema[] = "NULL AS {$col}";
$schema[] = "NULL AS $col";
} else {
$bindKey = ':' . strtolower($key);
$binds[$bindKey] = $value;
$schema[] = "{$bindKey} AS {$col}";
$schema[] = "$bindKey AS $col";
}
}

$tmpTable = TableRegistry::getTableLocator()->get('tmp', [
$tmpTable = $this->fetchTable('tmp', [
'schema' => $this->_table->getSchema(),
]);
$query = $tmpTable
Expand Down
29 changes: 13 additions & 16 deletions src/Model/Behavior/UpsertBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Cake\Database\StatementInterface;
use Cake\Datasource\EntityInterface;
use Cake\ORM\Behavior;
use Cake\ORM\Entity;
use LogicException;

/**
Expand All @@ -17,9 +16,9 @@ class UpsertBehavior extends Behavior
/**
* Default config
*
* @var array
* @var array<string, mixed>
*/
protected $_defaultConfig = [
protected array $_defaultConfig = [
'updateColumns' => null,
'uniqueColumns' => null,
'event' => ['beforeSave' => true],
Expand All @@ -28,11 +27,11 @@ class UpsertBehavior extends Behavior
/**
* execute upsert query
*
* @param Entity $entity upsert entity
* @return EntityInterface|array|null result entity
* @throws LogicException invalid config
* @param \Cake\Datasource\EntityInterface $entity upsert entity
* @return \Cake\Datasource\EntityInterface|array|null result entity
* @throws \LogicException invalid config
*/
public function upsert(Entity $entity)
public function upsert(EntityInterface $entity): array|EntityInterface|null
{
if (!$this->isValidArrayConfig('updateColumns')) {
throw new LogicException('config updateColumns is invalid.');
Expand All @@ -52,13 +51,13 @@ public function upsert(Entity $entity)

$updateValues = [];
foreach ($updateColumns as $column) {
$updateValues[] = "`{$column}`=VALUES(`{$column}`)";
$updateValues[] = "`$column`=VALUES(`$column`)";
}
$updateStatement = implode(', ', $updateValues);
$expression = 'ON DUPLICATE KEY UPDATE ' . $updateStatement;

$this->_table
->query()
->insertQuery()
->insert($fields)
->values($upsertData)
->epilog($expression)
Expand All @@ -80,9 +79,9 @@ public function upsert(Entity $entity)
/**
* execute bulk upsert query
*
* @param Entity[] $entities upsert entities
* @return StatementInterface query result
* @throws LogicException invalid config or no save data
* @param array<\Cake\Datasource\EntityInterface> $entities upsert entities
* @return \Cake\Database\StatementInterface query result
* @throws \LogicException invalid config or no save data
*/
public function bulkUpsert(array $entities): StatementInterface
{
Expand All @@ -107,13 +106,12 @@ public function bulkUpsert(array $entities): StatementInterface
$updateColumns = $this->_config['updateColumns'];
$updateValues = [];
foreach ($updateColumns as $column) {
$updateValues[] = "`{$column}`=VALUES(`{$column}`)";
$updateValues[] = "`$column`=VALUES(`$column`)";
}
$updateStatement = implode(', ', $updateValues);
$expression = 'ON DUPLICATE KEY UPDATE ' . $updateStatement;

$query = $this->_table
->query()
->insertQuery()
->insert($fields)
->epilog($expression);
$query->clause('values')->setValues($saveData);
Expand All @@ -125,7 +123,6 @@ public function bulkUpsert(array $entities): StatementInterface
* validate config value
*
* @param string $configName config key
*
* @return bool valid or invalid
*/
private function isValidArrayConfig(string $configName): bool
Expand Down
Loading

0 comments on commit a6ee26e

Please sign in to comment.