Skip to content

Commit

Permalink
Merge branch 'master' into parameter-name-binding
Browse files Browse the repository at this point in the history
  • Loading branch information
xepozz authored Oct 23, 2024
2 parents 0e2312c + 674ef5b commit 986742f
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 91 deletions.
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
/.gitattributes export-ignore
/.gitignore export-ignore
/.phpunit-watcher.yml export-ignore
/.scrutinizer.yml export-ignore
/.styleci.yml export-ignore
/infection.json.dist export-ignore
/phpunit.xml.dist export-ignore
Expand Down
35 changes: 0 additions & 35 deletions .scrutinizer.yml

This file was deleted.

7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# Yii Definitions Change Log

## 3.2.1 under development
## 3.3.1 under development

- no changes in this release.

## 3.3.0 March 16, 2024

- New #90: Allow multiple method call in array definition (@vjik)
- Bug #86: Fix crash when intersection types are used (@vjik)
- Enh #87: Support parameter name bindings (@xepozz)

Expand Down
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright © 2008 by Yii Software (https://www.yiiframework.com/)
Copyright © 2008 by Yii Software (<https://www.yiiframework.com/>)
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
47 changes: 18 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<p align="center">
<a href="https://github.com/yiisoft" target="_blank">
<img src="https://yiisoft.github.io/docs/images/yii_logo.svg" height="100px">
<img src="https://yiisoft.github.io/docs/images/yii_logo.svg" height="100px" alt="Yii">
</a>
<h1 align="center">Yii Definitions</h1>
<br>
Expand All @@ -9,8 +9,7 @@
[![Latest Stable Version](https://poser.pugx.org/yiisoft/definitions/v/stable.png)](https://packagist.org/packages/yiisoft/definitions)
[![Total Downloads](https://poser.pugx.org/yiisoft/definitions/downloads.png)](https://packagist.org/packages/yiisoft/definitions)
[![Build status](https://github.com/yiisoft/definitions/workflows/build/badge.svg)](https://github.com/yiisoft/definitions/actions?query=workflow%3Abuild)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yiisoft/definitions/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/definitions/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/definitions/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/definitions/?branch=master)
[![Code Coverage](https://codecov.io/gh/yiisoft/definitions/graph/badge.svg?token=9srXPaWGlj)](https://codecov.io/gh/yiisoft/definitions)
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Fdefinitions%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/definitions/master)
[![static analysis](https://github.com/yiisoft/definitions/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/definitions/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/definitions/coverage.svg)](https://shepherd.dev/github/yiisoft/definitions)
Expand All @@ -21,7 +20,7 @@ but could be used in other [PSR-11](https://www.php-fig.org/psr/psr-11/) compati
The following are provided:

- Definitions describing services or objects to create. This includes syntax, its validation and resolving it to objects.
- References and dynamic references to point to other definitions. These include additional utility to refer to multiple
- References and dynamic references to point to other definitions. These include additional utility to refer to multiple
definitions at once.

## Requirements
Expand All @@ -30,7 +29,7 @@ The following are provided:

## Installation

The package could be installed with composer:
The package could be installed with [Composer](https://getcomposer.org):

```shell
composer require yiisoft/definitions
Expand Down Expand Up @@ -70,6 +69,16 @@ In the above:
and method calls, postfixed with `()`. They are set/called
in the order they appear in the array.

For multiple method call postfix key with unique string, for example:

```php
[
'class' => Collector::class,
'add()' => ['Alex'],
'add()2' => ['Mike'],
]
```

#### `CallableDefinition`

Callable definition builds an object by executing a callable injecting
Expand Down Expand Up @@ -263,32 +272,12 @@ var_dump($storage->has(EngineMarkOne::class));

`has()` will return `false` even if `EngineMarkOne` exists.

## Testing

### Unit testing

The package is tested with [PHPUnit](https://phpunit.de/). To run tests:
## Documentation

```shell
./vendor/bin/phpunit
```
- [Internals](docs/internals.md)

### Mutation testing

The package tests are checked with [Infection](https://infection.github.io/) mutation framework with
[Infection Static Analysis Plugin](https://github.com/Roave/infection-static-analysis-plugin). To run it:

```shell
./vendor/bin/roave-infection-static-analysis-plugin
```

### Static analysis

The code is statically analyzed with [Psalm](https://psalm.dev/). To run static analysis:

```shell
./vendor/bin/psalm
```
If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for
that. You may also check out other [Yii Community Resources](https://www.yiiframework.com/community).

## License

Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/definitions/issues?state=open",
"source": "https://github.com/yiisoft/definitions",
"forum": "https://www.yiiframework.com/forum/",
"wiki": "https://www.yiiframework.com/wiki/",
"irc": "irc://irc.freenode.net/yii",
"chat": "https://t.me/yii3en",
"source": "https://github.com/yiisoft/definitions"
"irc": "ircs://irc.libera.chat:6697/yii",
"chat": "https://t.me/yii3en"
},
"funding": [
{
Expand Down
44 changes: 44 additions & 0 deletions docs/internals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Internals

## Unit testing

The package is tested with [PHPUnit](https://phpunit.de/). To run tests:

```shell
./vendor/bin/phpunit
```

## Mutation testing

The package tests are checked with [Infection](https://infection.github.io/) mutation framework with
[Infection Static Analysis Plugin](https://github.com/Roave/infection-static-analysis-plugin). To run it:

```shell
./vendor/bin/roave-infection-static-analysis-plugin
```

## Static analysis

The code is statically analyzed with [Psalm](https://psalm.dev/). To run static analysis:

```shell
./vendor/bin/psalm
```

## Code style

Use [Rector](https://github.com/rectorphp/rector) to make codebase follow some specific rules or
use either newest or any specific version of PHP:

```shell
./vendor/bin/rector
```

## Dependencies

This package uses [composer-require-checker](https://github.com/maglnet/ComposerRequireChecker) to check if
all dependencies are correctly defined in `composer.json`. To run the checker, execute the following command:

```shell
./vendor/bin/composer-require-checker
```
17 changes: 8 additions & 9 deletions src/Helpers/DefinitionValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ public static function validateArrayDefinition(array $definition, ?string $id =
}

// Methods and properties
if (str_ends_with($key, '()')) {
self::validateMethod($key, $classReflection, $classPublicMethods, $className, $value);
if ((count($methodArray = explode('()', $key)) === 2) && !empty($methodArray[0])) {
self::validateMethod($methodArray[0], $classReflection, $classPublicMethods, $className, $value);
continue;
}
if (str_starts_with($key, '$')) {
Expand Down Expand Up @@ -183,14 +183,13 @@ private static function generatePossibleMessage(
* @throws InvalidConfigException
*/
private static function validateMethod(
string $key,
string $methodName,
ReflectionClass $classReflection,
array $classPublicMethods,
string $className,
mixed $value
): void {
$parsedKey = substr($key, 0, -2);
if (!$classReflection->hasMethod($parsedKey)) {
if (!$classReflection->hasMethod($methodName)) {
if ($classReflection->hasMethod('__call') || $classReflection->hasMethod('__callStatic')) {
/**
* Magic method may intercept the call, but reflection does not know about it.
Expand All @@ -207,20 +206,20 @@ private static function validateMethod(
sprintf(
'Invalid definition: class "%s" does not have the public method with name "%s". ' . $possiblePropertiesMessage,
$className,
$parsedKey,
$methodName,
)
);
}
if (!in_array($parsedKey, $classPublicMethods, true)) {
if (!in_array($methodName, $classPublicMethods, true)) {
throw new InvalidConfigException(
sprintf(
'Invalid definition: method "%s" must be public.',
$className . '::' . $key,
$className . '::' . $methodName . '()',
)
);
}
if (!is_array($value)) {
throw ExceptionHelper::incorrectArrayDefinitionMethodArguments($key, $value);
throw ExceptionHelper::incorrectArrayDefinitionMethodArguments($methodName . '()', $value);
}
}

Expand Down
25 changes: 23 additions & 2 deletions tests/Unit/ArrayDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -506,15 +506,15 @@ public function testReferenceContainer(): void

public function testMagicMethods(): void
{
$definiton = ArrayDefinition::fromConfig([
$definition = ArrayDefinition::fromConfig([
'class' => Recorder::class,
'first()' => [],
'$second' => null,
'third()' => ['hello', true],
'$fourth' => 'hello',
]);

$object = $definiton->resolve(new SimpleContainer());
$object = $definition->resolve(new SimpleContainer());

$this->assertSame(
[
Expand Down Expand Up @@ -633,4 +633,25 @@ public function testWrongParameterNameBindingsFormat(array $definitions, string
);
$storage->get($class);
}

public function testMultipleCall()
{
$definition = ArrayDefinition::fromConfig([
'class' => Recorder::class,
'test()' => [1],
'test()_2' => [2],
'test()_3' => [3],
]);

$object = $definition->resolve(new SimpleContainer());

$this->assertSame(
[
'Call test(int)',
'Call test(int)',
'Call test(int)',
],
$object->getEvents(),
);
}
}
45 changes: 35 additions & 10 deletions tests/Unit/Helpers/DefinitionValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,23 @@ public function dataErrorOnPropertyOrMethodTypo(): array
return [
['dev', true, 'Invalid definition: key "dev" is not allowed. Did you mean "$dev"?'],
['setId', [42], 'Invalid definition: key "setId" is not allowed. Did you mean "setId()"?'],
['set()Id', [42], 'Invalid definition: key "set()Id" is not allowed. Did you mean "setId()"?'],
[' set()Id', [42], 'Invalid definition: key " set()Id" is not allowed. Did you mean "setId()"?'],
['()setId', [42], 'Invalid definition: key "()setId" is not allowed. Did you mean "setId()"?'],
[
'set()Id',
[42],
sprintf(
'Invalid definition: class "%s" does not have the public method with name "set". Possible methods to call: "getName", "getVersion", "getColors", "addApp", "getApps", "getId", "setId", "setId777", "withAuthor", "getAuthor", "withCountry", "getCountry"',
Phone::class
),
],
[
' set()Id',
[42],
sprintf(
'Invalid definition: class "%s" does not have the public method with name " set". Possible methods to call: "getName", "getVersion", "getColors", "addApp", "getApps", "getId", "setId", "setId777", "withAuthor", "getAuthor", "withCountry", "getCountry"',
Phone::class
),
],
[
'getCountryPrivate',
[42],
Expand All @@ -216,6 +231,14 @@ public function dataErrorOnPropertyOrMethodTypo(): array
Phone::class . '::$country',
),
],
[
' country',
[42],
sprintf(
'Invalid definition: key " country" is not allowed. Property "%s" must be public to be able to be called.',
Phone::class . '::$country',
),
],
[
'()test',
[42],
Expand Down Expand Up @@ -271,6 +294,14 @@ public function dataValidate(): array
'magic method reference' => [['class' => Recorder::class, 'add()' => ['test magic method']]],
'magic only call reference' => [['class' => MagicCall::class, 'add()' => ['test magic method']]],
'magic property reference' => [['class' => Recorder::class, '$add' => ['test magic property']]],
'multiple call methods' => [
[
'class' => Recorder::class,
'test()' => [1],
'test()_2' => [2],
'test()_3' => [3],
],
],
];
}

Expand Down Expand Up @@ -332,20 +363,14 @@ public function dataIncorrectMethodName(): array
'class' => Phone::class,
'addApp()hm()' => ['name' => 'hello'],
],
sprintf(
'Invalid definition: class "%s" does not have the public method with name "addApp()hm".',
Phone::class,
),
'Invalid definition: key "addApp()hm()" is not allowed. The key may be a call of a method or a setting of a property.',
],
[
[
'class' => UTF8User::class,
'имя()aa()' => ['значение'],
],
sprintf(
'Invalid definition: class "%s" does not have the public method with name "имя()aa".',
UTF8User::class,
),
'Invalid definition: key "имя()aa()" is not allowed. The key may be a call of a method or a setting of a property.',
],
];
}
Expand Down

0 comments on commit 986742f

Please sign in to comment.