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

Add override method attributes #1151

Merged
merged 8 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
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
8 changes: 4 additions & 4 deletions .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Install PHP dependencies
run: |
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpunit/phpunit atk4/ergebnis-phpunit-slow-test-detector --dev; fi
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer --dev && composer --no-interaction --no-update require jdorn/sql-formatter; fi
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer ergebnis/composer-normalize --dev && composer --no-interaction --no-update require jdorn/sql-formatter; fi
if [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpstan/\* --dev; fi
composer update --ansi --prefer-dist --no-interaction --no-progress --optimize-autoloader

Expand Down Expand Up @@ -89,7 +89,7 @@ jobs:
- php: 'latest'
type: 'Phpunit Burn'
env:
LOG_COVERAGE: "${{ fromJSON('{true: \"1\", false: \"\"}')[matrix.php == '8.2' && matrix.type == 'Phpunit' && (github.event_name == 'pull_request' || (github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master')))] }}"
LOG_COVERAGE: "${{ fromJSON('{true: \"1\", false: \"\"}')[matrix.php == '8.3' && matrix.type == 'Phpunit' && (github.event_name == 'pull_request' || (github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master')))] }}"
services:
mysql:
image: mysql:8
Expand Down Expand Up @@ -141,12 +141,12 @@ jobs:
- name: Install PHP dependencies
run: |
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "Phpunit Lowest" ] && [ "${{ matrix.type }}" != "Phpunit Burn" ]; then composer remove --no-interaction --no-update phpunit/phpunit atk4/ergebnis-phpunit-slow-test-detector --dev; fi
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer --dev && composer --no-update --ansi --prefer-dist --no-interaction --no-progress require jdorn/sql-formatter; fi
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer ergebnis/composer-normalize --dev && composer --no-update --ansi --prefer-dist --no-interaction --no-progress require jdorn/sql-formatter; fi
if [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpstan/\* --dev; fi
if [ -n "$LOG_COVERAGE" ]; then composer require --no-interaction --no-install phpunit/phpcov; fi
composer update --ansi --prefer-dist --no-interaction --no-progress --optimize-autoloader
if [ "${{ matrix.type }}" = "Phpunit Lowest" ]; then composer update --ansi --prefer-dist --prefer-lowest --prefer-stable --no-interaction --no-progress --optimize-autoloader; fi
if [ "${{ matrix.type }}" = "Phpunit Burn" ]; then sed -i 's~public function runBare(): void~public function runBare(): void { gc_collect_cycles(); gc_collect_cycles(); $memDiffs = array_fill(0, '"$(if [ \"$GITHUB_EVENT_NAME\" == \"schedule\" ]; then echo 64; else echo 4; fi)"', 0); for ($i = -1; $i < count($memDiffs); ++$i) { $this->_runBare(); gc_collect_cycles(); gc_collect_cycles(); $mem = memory_get_usage(); if ($i !== -1) { $memDiffs[$i] = $mem - $memPrev; } $memPrev = $mem; rsort($memDiffs); if (array_sum($memDiffs) >= 4096 * 1024 || $memDiffs[2] > 0) { $this->onNotSuccessfulTest(new AssertionFailedError("Memory leak detected! (" . implode(" + ", array_map(static fn ($v) => number_format($v / 1024, 3, ".", " "), array_filter($memDiffs))) . " KB, " . ($i + 2) . " iterations)")); } } } private function _runBare(): void~' vendor/phpunit/phpunit/src/Framework/TestCase.php && cat vendor/phpunit/phpunit/src/Framework/TestCase.php | grep '_runBare('; fi
if [ "${{ matrix.type }}" = "Phpunit Burn" ]; then sed -i 's~public function runBare(): void~public function runBare(): void { gc_collect_cycles(); $memDiffs = array_fill(0, '"$(if [ \"$GITHUB_EVENT_NAME\" == \"schedule\" ]; then echo 64; else echo 4; fi)"', 0); for ($i = -1; $i < count($memDiffs); ++$i) { $this->_runBare(); gc_collect_cycles(); $mem = memory_get_usage(); if ($i !== -1) { $memDiffs[$i] = $mem - $memPrev; } $memPrev = $mem; rsort($memDiffs); if (array_sum($memDiffs) >= 4096 * 1024 || $memDiffs[2] > 0) { $e = new AssertionFailedError("Memory leak detected! (" . implode(" + ", array_map(static fn ($v) => number_format($v / 1024, 3, ".", " "), array_filter($memDiffs))) . " KB, " . ($i + 2) . " iterations)"); $this->status = TestStatus::failure($e->getMessage()); Event\\Facade::emitter()->testFailed($this->valueObjectForEvents(), Event\\Code\\ThrowableBuilder::from($e), Event\\Code\\ComparisonFailureBuilder::from($e)); $this->onNotSuccessfulTest($e); } } } private function _runBare(): void~' vendor/phpunit/phpunit/src/Framework/TestCase.php && cat vendor/phpunit/phpunit/src/Framework/TestCase.php | grep '_runBare('; fi

- name: Init
run: |
Expand Down
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Agile Data is a framework for defining your "business layer" which is separate f

[![Build](https://github.com/atk4/data/actions/workflows/test-unit.yml/badge.svg?branch=develop)](https://github.com/atk4/data/actions?query=branch:develop)
[![CodeCov](https://codecov.io/gh/atk4/data/branch/develop/graph/badge.svg)](https://codecov.io/gh/atk4/data)
[![GitHub release](https://img.shields.io/github/release/atk4/data.svg)](CHANGELOG.md)
[![GitHub release](https://img.shields.io/github/release/atk4/data.svg)](https://github.com/atk4/data/releases)
[![Code Climate](https://codeclimate.com/github/atk4/data/badges/gpa.svg)](https://codeclimate.com/github/atk4/data)

Quick-Links: [Documentation](https://atk4-data.readthedocs.io) | [Discord channel](https://discord.gg/QVKSk2B) | [ATK UI](https://github.com/atk4/ui)
Expand Down Expand Up @@ -53,7 +53,7 @@ $api->rest('/clients', new Client($db));

## Extensibility and Add-ons

ATK Data is extensible and offers wide range of add-ons like [Audit](https://github.com/atk4/audit). Developer may also implement advanced DB concepts like "[disjoint subtypes](https://nearly.guru/blog/data/disjoint-subtypes-in-php)" - allowing to efficiently persist object-oriented data in your database.
ATK Data is extensible and offers wide range of add-ons like [Audit](https://github.com/atk4/audit).

Regardless of how your model is constructed and what database backend is used, it can easily be used in conjunction with any 3rd party add-on, like [Charts](https://github.com/atk4/chart).

Expand All @@ -65,7 +65,7 @@ Designed for medium to large PHP applications and frameworks, ATK Data is a clea
- Execute more on the server. Agile Data converts query logic into server-specific language (e.g. SQL) then delivers you the exact data rows / columns which you need from a single statement, no matter how complex.
- Data architecture transparency. As your database structure change, your application code does not need to be refactored. Replace fields with expressions, denormalize/normalize data, join and merge tables. Only update your application in a single place.
- Extensions. "[Audit](https://github.com/atk4/audit)" - transparently record all edits, updates and deletes with "Undo" support.
- [Out of the box UI](https://github.com/atk4/ui). Who wants to build Admin systems today? Tens of professional components: [Crud](https://ui.atk4.org/demos/crud.php), [Grid](https://ui.atk4.org/demos/grid.php), [Form](https://ui.atk4.org/demos/form3.php) as well as add-ons like [Charts](https://github.com/atk4/chart) can be added to your PHP app with 3-lines of code.
- [Out of the box UI](https://github.com/atk4/ui). Who wants to build Admin systems today? Tens of professional components: [Crud](https://ui.atk4.org/demos/collection/crud.php), [Grid](https://ui.atk4.org/demos/collection/grid.php), [Form](https://ui.atk4.org/demos/form/form.php) as well as add-ons like [Charts](https://github.com/atk4/chart) can be added to your PHP app with 3-lines of code.
- RestAPI server for Agile Data is currently under development.
- Agile Data and all extensions mentioned above are licensed under MIT and are free to use.

Expand Down Expand Up @@ -285,11 +285,11 @@ We put all our focus into making a good quality software and give it to you for

#### Q: Is there training material for Agile Data / Agile UI

We are working on it. For now - visit our [gitter.im](https://gitter.im/atk4/atk4).
We are working on it. For now - visit our [![Discord](https://img.shields.io/badge/discord-User_Forum-green.svg)](https://discord.gg/QVKSk2B).

#### Q: How can I help / Contribute?

Say hi. We enjoy meeting new people regardless of how good they are with PHP and the framework (https://gitter.im/atk4/atk4).
Say hi. We enjoy meeting new people regardless of how good they are with PHP and the framework [![Discord](https://img.shields.io/badge/discord-User_Forum-green.svg)](https://discord.gg/QVKSk2B).

If you want to help, we have a special tag [Help Wanted](https://github.com/atk4/data/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) in our issue system:

Expand Down Expand Up @@ -713,6 +713,5 @@ Please consider our other MIT-licensed project - [Agile UI](https://atk4.org/) t

## Community and Support

[![Gitter](https://img.shields.io/gitter/room/atk4/data.svg)](https://gitter.im/atk4/dataset?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Stack Overflow Community](https://img.shields.io/stackexchange/stackoverflow/t/atk4.svg)](https://stackoverflow.com/questions/ask?tags=atk4)
[![Discord User forum](https://img.shields.io/badge/discord-User_Forum-green.svg)](https://forum.agiletoolkit.org/c/44)
[![Discord Community](https://img.shields.io/badge/discord-User_Forum-green.svg)](https://discord.gg/QVKSk2B)
2 changes: 0 additions & 2 deletions docs/persistence/sql/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ DSQL can also execute queries with multiple sub-queries, joins, expressions
grouping, ordering, unions as well as queries on result-set.

- See {ref}`quickstart` if you would like to start learning DSQL.
- See https://github.com/atk4/dsql-primer for various working
examples of using DSQL with a real data-set.

## DSQL is Part of Agile Toolkit

Expand Down
12 changes: 12 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ parameters:
excludePaths:
- vendor

checkMissingOverrideMethodAttribute: true

ignoreErrors:
- '~^Unsafe usage of new static\(\)\.$~'

Expand All @@ -26,6 +28,16 @@ parameters:
path: '*'
count: 1

# https://github.com/phpstan/phpstan/issues/10208
-
message: '~^Return type \(Atk4\\Data\\Model\\Scope\) of method Atk4\\Data\\Model\\Scope::(clear|negate)\(\) should be covariant with return type \(\$this\(Atk4\\Data\\Model\\Scope\\AbstractScope\)\) of method Atk4\\Data\\Model\\Scope\\AbstractScope::(clear|negate)\(\)$~'
path: 'src/Model/Scope.php'
count: 2
-
message: '~^Return type \(Atk4\\Data\\Model\\Scope\\Condition\) of method Atk4\\Data\\Model\\Scope\\Condition::(clear|negate)\(\) should be covariant with return type \(\$this\(Atk4\\Data\\Model\\Scope\\AbstractScope\)\) of method Atk4\\Data\\Model\\Scope\\AbstractScope::(clear|negate)\(\)$~'
path: 'src/Model/Scope/Condition.php'
count: 2

# AbstractPlatform::getIdentitySequenceName() method is deprecated in DBAL 3.4+,
# in DBAL 4.0 OraclePlatform::getIdentitySequenceName() is protected and
# PostgreSQLPlatform::getIdentitySequenceName() is removed:
Expand Down
4 changes: 3 additions & 1 deletion src/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,10 @@ public function getCaption(): string

/**
* When field is used as expression, this method will be called.
* Universal way to convert ourselves to expression. Off-load implementation into persistence.
*
* Off-load implementation into persistence.
*/
#[\Override]
public function getDsqlExpression(Expression $expression): Expression
{
$this->getOwner()->assertHasPersistence();
Expand Down
1 change: 1 addition & 0 deletions src/Field/EmailField.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class EmailField extends Field
/** @var bool Allow display name as per RFC2822, eg. format like "Romans <[email protected]>" */
public $allowName = false;

#[\Override]
public function normalize($value)
{
$value = parent::normalize($value);
Expand Down
1 change: 1 addition & 0 deletions src/Field/PasswordField.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public function hashPasswordIsHashed(string $value): bool
return \password_get_info($value)['algo'] === \PASSWORD_BCRYPT;
}

#[\Override]
public function normalize($hash): ?string
{
$hash = parent::normalize($hash);
Expand Down
9 changes: 2 additions & 7 deletions src/Field/SqlExpressionField.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,13 @@ class SqlExpressionField extends Field
/** @var string Specifies which field to use. */
public $field;

/**
* Should this field use alias?
* Expression fields always need alias.
*/
#[\Override]
public function useAlias(): bool
{
return true;
}

/**
* When field is used as expression, this method will be called.
*/
#[\Override]
public function getDsqlExpression(Expression $expression): Expression
{
$expr = $this->expr;
Expand Down
1 change: 1 addition & 0 deletions src/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,7 @@ public function export(array $fields = null, string $keyField = null, bool $type
*
* @return \Traversable<static>
*/
#[\Override]
final public function getIterator(): \Traversable
{
return $this->createIteratorBy([]);
Expand Down
3 changes: 3 additions & 0 deletions src/Model/AggregateModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public function setGroupBy(array $fields, array $aggregateExpressions = [])
return $this;
}

#[\Override]
public function addField(string $name, $seed = []): Field
{
if ($seed instanceof SqlExpressionField) {
Expand All @@ -120,6 +121,7 @@ public function addField(string $name, $seed = []): Field
return parent::addField($name, $seed);
}

#[\Override]
public function action(string $mode, array $args = [])
{
switch ($mode) {
Expand Down Expand Up @@ -173,6 +175,7 @@ protected function initQueryGrouping(Query $query): void
}
}

#[\Override]
public function __debugInfo(): array
{
return array_merge(parent::__debugInfo(), [
Expand Down
18 changes: 9 additions & 9 deletions src/Model/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,21 @@ public function getNestedConditions()
return $this->elements;
}

#[\Override]
protected function onChangeModel(): void
{
foreach ($this->elements as $nestedCondition) {
$nestedCondition->onChangeModel();
}
}

#[\Override]
public function isEmpty(): bool
{
return count($this->elements) === 0;
}

#[\Override]
public function isCompound(): bool
{
return count($this->elements) > 1;
Expand Down Expand Up @@ -140,18 +143,15 @@ public function isAnd(): bool
return $this->junction === self::AND;
}

/**
* Clears the compound condition from nested conditions.
*
* @return static
*/
public function clear()
#[\Override]
public function clear(): self
{
$this->elements = [];

return $this;
}

#[\Override]
public function simplify(): AbstractScope
{
if (count($this->elements) !== 1) {
Expand All @@ -165,10 +165,9 @@ public function simplify(): AbstractScope

/**
* Use De Morgan's laws to negate.
*
* @return static
*/
public function negate()
#[\Override]
public function negate(): self
{
$this->junction = $this->junction === self::OR ? self::AND : self::OR;

Expand All @@ -179,6 +178,7 @@ public function negate()
return $this;
}

#[\Override]
public function toWords(Model $model = null): string
{
$parts = [];
Expand Down
11 changes: 5 additions & 6 deletions src/Model/Scope/AbstractScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ public function getModel(): ?Model
/**
* Empty the scope object.
*
* @return static
* @return $this
*/
abstract public function clear();
abstract public function clear(): self;

/**
* Negate the scope object
* e.g from '=' to '!='.
* Negate the scope object e.g. from '=' to '!='.
*
* @return static
* @return $this
*/
abstract public function negate();
abstract public function negate(): self;

/**
* Return if scope has any conditions.
Expand Down
9 changes: 7 additions & 2 deletions src/Model/Scope/Condition.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public function __construct($key, $operator = null, $value = null)
}
}

#[\Override]
protected function onChangeModel(): void
{
$model = $this->getModel();
Expand Down Expand Up @@ -257,12 +258,14 @@ public function toQueryArguments(): array
return [$field, $operator, $value];
}

#[\Override]
public function isEmpty(): bool
{
return array_filter([$this->key, $this->operator, $this->value]) ? false : true;
}

public function clear()
#[\Override]
public function clear(): self
{
$this->key = null; // @phpstan-ignore-line
$this->operator = null;
Expand All @@ -271,7 +274,8 @@ public function clear()
return $this;
}

public function negate()
#[\Override]
public function negate(): self
{
if (isset(self::$operators[$this->operator]['negate'])) {
$this->operator = self::$operators[$this->operator]['negate'];
Expand All @@ -283,6 +287,7 @@ public function negate()
return $this;
}

#[\Override]
public function toWords(Model $model = null): string
{
if ($model === null) {
Expand Down
4 changes: 3 additions & 1 deletion src/Model/Scope/RootScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ public function setModel(Model $model)
return $this;
}

#[\Override]
public function getModel(): Model
{
return $this->model;
}

public function negate()
#[\Override]
public function negate(): self
{
throw new Exception('Model scope cannot be negated');
}
Expand Down
8 changes: 5 additions & 3 deletions src/Persistence/Array_.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,7 @@ private function saveRow(Model $model, array $rowData, $id): void
}
}

/**
* @param array<string, mixed> $defaults
*/
#[\Override]
public function add(Model $model, array $defaults = []): void
{
$defaults = array_merge([
Expand Down Expand Up @@ -222,6 +220,7 @@ private function remapLoadRow(Model $model, array $row): array
return $rowRemapped;
}

#[\Override]
public function tryLoad(Model $model, $id): ?array
{
$model->assertIsModel();
Expand Down Expand Up @@ -272,6 +271,7 @@ public function tryLoad(Model $model, $id): ?array
return $this->typecastLoadRow($model, $rowData);
}

#[\Override]
protected function insertRaw(Model $model, array $dataRaw)
{
$this->seedData($model);
Expand All @@ -283,13 +283,15 @@ protected function insertRaw(Model $model, array $dataRaw)
return $idRaw;
}

#[\Override]
protected function updateRaw(Model $model, $idRaw, array $dataRaw): void
{
$table = $this->seedDataAndGetTable($model);

$this->saveRow($model, array_merge($this->filterRowDataOnlyModelFields($model, $table->getRowById($model, $idRaw)->getData()), $dataRaw), $idRaw);
}

#[\Override]
protected function deleteRaw(Model $model, $idRaw): void
{
$table = $this->seedDataAndGetTable($model);
Expand Down
4 changes: 1 addition & 3 deletions src/Persistence/Array_/Action/RenameColumnIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ public function __construct(\Traversable $iterator, string $origName, string $ne
$this->newName = $newName;
}

/**
* @return array<string, mixed>
*/
#[\Override]
public function current(): array
{
$row = parent::current();
Expand Down
Loading