Skip to content

Commit

Permalink
Move definitions from factory (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Aug 27, 2021
1 parent 5c3b3d8 commit ebf3091
Show file tree
Hide file tree
Showing 54 changed files with 2,687 additions and 23 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
@@ -1,4 +1,4 @@
# _____ Change Log
# Yii Definitions Change Log

## 1.0.0 under development

Expand Down
22 changes: 11 additions & 11 deletions README.md
Expand Up @@ -2,18 +2,18 @@
<a href="https://github.com/yiisoft" target="_blank">
<img src="https://yiisoft.github.io/docs/images/yii_logo.svg" height="100px">
</a>
<h1 align="center">Yii _____</h1>
<h1 align="center">Yii Definitions</h1>
<br>
</p>

[![Latest Stable Version](https://poser.pugx.org/yiisoft/_____/v/stable.png)](https://packagist.org/packages/yiisoft/_____)
[![Total Downloads](https://poser.pugx.org/yiisoft/_____/downloads.png)](https://packagist.org/packages/yiisoft/_____)
[![Build status](https://github.com/yiisoft/_____/workflows/build/badge.svg)](https://github.com/yiisoft/_____/actions?query=workflow%3Abuild)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yiisoft/_____/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/_____/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/_____/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/_____/?branch=master)
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2F_____%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/_____/master)
[![static analysis](https://github.com/yiisoft/_____/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/_____/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/_____/coverage.svg)](https://shepherd.dev/github/yiisoft/_____)
[![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)
[![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)

The package ...

Expand All @@ -26,7 +26,7 @@ The package ...
The package could be installed with composer:

```shell
composer require yiisoft/_____ --prefer-dist
composer require yiisoft/definitions --prefer-dist
```

## General usage
Expand Down Expand Up @@ -60,7 +60,7 @@ The code is statically analyzed with [Psalm](https://psalm.dev/). To run static

## License

The Yii _____ is free software. It is released under the terms of the BSD License.
The Yii Definitions is free software. It is released under the terms of the BSD License.
Please see [`LICENSE`](./LICENSE.md) for more information.

Maintained by [Yii Software](https://www.yiiframework.com/).
Expand Down
19 changes: 11 additions & 8 deletions composer.json
@@ -1,19 +1,19 @@
{
"name": "yiisoft/replace-with-package-name",
"name": "yiisoft/definitions",
"type": "library",
"description": "_____",
"keywords": [
"_____"
"definitions"
],
"homepage": "https://www.yiiframework.com/",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/_____/issues?state=open",
"issues": "https://github.com/yiisoft/definitions/issues?state=open",
"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/_____"
"source": "https://github.com/yiisoft/definitions"
},
"funding": [
{
Expand All @@ -28,22 +28,25 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": "^7.4|^8.0"
"php": "^7.4|^8.0",
"psr/container": "^1.0|^2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"roave/infection-static-analysis-plugin": "^1.9",
"spatie/phpunit-watcher": "^1.23",
"vimeo/psalm": "^4.9"
"vimeo/psalm": "^4.9",
"yiisoft/injector": "^1.0",
"yiisoft/test-support": "^1.3"
},
"autoload": {
"psr-4": {
"Yiisoft\\_____\\": "src"
"Yiisoft\\Definitions\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Yiisoft\\_____\\Tests\\": "tests"
"Yiisoft\\Definitions\\Tests\\": "tests"
}
},
"extra": {
Expand Down
5 changes: 3 additions & 2 deletions phpunit.xml.dist
Expand Up @@ -16,8 +16,9 @@
</php>

<testsuites>
<testsuite name="Yii _____ tests">
<directory>./tests</directory>
<testsuite name="Yii Definitions tests">
<directory>./tests/Unit</directory>
<directory phpVersion="8" phpVersionOperator=">=">./tests/Php8</directory>
</testsuite>
</testsuites>

Expand Down
2 changes: 1 addition & 1 deletion psalm.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<psalm
errorLevel="2"
errorLevel="1"
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"
Expand Down
Empty file removed src/.gitkeep
Empty file.
162 changes: 162 additions & 0 deletions src/ArrayDefinition.php
@@ -0,0 +1,162 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Definitions;

use Yiisoft\Definitions\Contract\DefinitionInterface;
use Yiisoft\Definitions\Contract\DependencyResolverInterface;
use Yiisoft\Definitions\Exception\InvalidConfigException;
use Yiisoft\Definitions\Exception\NotFoundException;
use Yiisoft\Definitions\Exception\NotInstantiableException;
use Yiisoft\Definitions\Infrastructure\ArrayDefinitionBuilder;

use function count;

/**
* Builds object by array config
*
* @psalm-type MethodOrPropertyItem = array{0:string,1:string,2:mixed}
* @psalm-type ArrayDefinitionConfig = array{class:class-string,'__construct()'?:array}&array<string, mixed>
*/
final class ArrayDefinition implements DefinitionInterface
{
public const CLASS_NAME = 'class';
public const CONSTRUCTOR = '__construct()';

public const TYPE_PROPERTY = 'property';
public const TYPE_METHOD = 'method';

/**
* @psalm-var class-string
*/
private string $class;
private array $constructorArguments;

/**
* @psalm-var array<string, MethodOrPropertyItem>
*/
private array $methodsAndProperties;

/**
* @psalm-param class-string $class
* @psalm-param array<string, MethodOrPropertyItem> $methodsAndProperties
*/
private function __construct(string $class, array $constructorArguments, array $methodsAndProperties)
{
$this->class = $class;
$this->constructorArguments = $constructorArguments;
$this->methodsAndProperties = $methodsAndProperties;
}

/**
* @psalm-param ArrayDefinitionConfig $config
*/
public static function fromConfig(array $config): self
{
return new self(
$config[self::CLASS_NAME],
$config[self::CONSTRUCTOR] ?? [],
self::getMethodsAndPropertiesFromConfig($config)
);
}

/**
* @psalm-param class-string $class
* @psalm-param array<string, MethodOrPropertyItem> $methodsAndProperties
*/
public static function fromPreparedData(string $class, array $constructorArguments = [], array $methodsAndProperties = []): self
{
return new self($class, $constructorArguments, $methodsAndProperties);
}

/**
* @psalm-param array<string, mixed> $config
*
* @psalm-return array<string, MethodOrPropertyItem>
*/
private static function getMethodsAndPropertiesFromConfig(array $config): array
{
$methodsAndProperties = [];

/** @var mixed $value */
foreach ($config as $key => $value) {
if ($key === self::CONSTRUCTOR) {
continue;
}

if (count($methodArray = explode('()', $key)) === 2) {
$methodsAndProperties[$key] = [self::TYPE_METHOD, $methodArray[0], $value];
} elseif (count($propertyArray = explode('$', $key)) === 2) {
$methodsAndProperties[$key] = [self::TYPE_PROPERTY, $propertyArray[1], $value];
}
}

return $methodsAndProperties;
}

/**
* @psalm-return class-string
*/
public function getClass(): string
{
return $this->class;
}

public function getConstructorArguments(): array
{
return $this->constructorArguments;
}

/**
* @psalm-return array<string, MethodOrPropertyItem>
*/
public function getMethodsAndProperties(): array
{
return $this->methodsAndProperties;
}

/**
* @throws NotFoundException
* @throws NotInstantiableException
* @throws InvalidConfigException
*/
public function resolve(DependencyResolverInterface $container): object
{
return ArrayDefinitionBuilder::getInstance()->build($container, $this);
}

public function merge(self $other): self
{
$new = clone $this;
$new->class = $other->class;
$new->constructorArguments = $this->mergeArguments($this->constructorArguments, $other->constructorArguments);

$methodsAndProperties = $this->methodsAndProperties;
foreach ($other->methodsAndProperties as $key => $item) {
if ($item[0] === self::TYPE_PROPERTY) {
$methodsAndProperties[$key] = $item;
} elseif ($item[0] === self::TYPE_METHOD) {
/** @psalm-suppress MixedArgument, MixedAssignment */
$arguments = isset($methodsAndProperties[$key])
? $this->mergeArguments($methodsAndProperties[$key][2], $item[2])
: $item[2];
$methodsAndProperties[$key] = [$item[0], $item[1], $arguments];
}
}
$new->methodsAndProperties = $methodsAndProperties;

return $new;
}

private function mergeArguments(array $selfArguments, array $otherArguments): array
{
/** @var mixed $argument */
foreach ($otherArguments as $name => $argument) {
/** @var mixed */
$selfArguments[$name] = $argument;
}

return $selfArguments;
}
}
57 changes: 57 additions & 0 deletions src/CallableDefinition.php
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Definitions;

use ReflectionMethod;
use Yiisoft\Definitions\Contract\DefinitionInterface;
use Yiisoft\Definitions\Contract\DependencyResolverInterface;

use function is_array;
use function is_object;

final class CallableDefinition implements DefinitionInterface
{
/**
* @var array|callable
* @psalm-var callable|array{0:class-string,1:string}
*/
private $method;

/**
* @param array|callable $method
*
* @psalm-param callable|array{0:class-string,1:string} $method
*/
public function __construct($method)
{
$this->method = $method;
}

public function resolve(DependencyResolverInterface $container)
{
$callable = $this->prepareCallable($this->method, $container);

/** @psalm-suppress MixedMethodCall */
return $container->invoke($callable);
}

/**
* @param array|callable $callable
*
* @psalm-param callable|array{0:class-string,1:string} $callable
*/
private function prepareCallable($callable, DependencyResolverInterface $container): callable
{
if (is_array($callable) && !is_object($callable[0])) {
$reflection = new ReflectionMethod($callable[0], $callable[1]);
if (!$reflection->isStatic()) {
/** @var mixed */
$callable[0] = $container->get($callable[0]);
}
}

return $callable;
}
}

0 comments on commit ebf3091

Please sign in to comment.