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

Blueprint building #6

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9bad536
Draft of object builder based on callable blueprint
gardziejewskik Jul 18, 2018
1c0f4b2
Building complex object without default values
gardziejewskik Jul 23, 2018
985eb59
Building complex object with default values
gardziejewskik Jul 23, 2018
8e4bbb6
Building object with default values fix
gardziejewskik Jul 24, 2018
d1957bc
Building advanced object hierarchy with nested objects
gardziejewskik Jul 24, 2018
8326c72
Handle all ReflectionBuilder cases with BlueprintBuilder
gardziejewskik Jul 24, 2018
e6941b0
Removed unused dependency
gardziejewskik Jul 24, 2018
aa5c23e
Add code standard analyse
gardziejewskik Jul 24, 2018
580d2fa
Fix coding standards
gardziejewskik Jul 25, 2018
ab165fe
Refactoring and code cleaning
gardziejewskik Jul 25, 2018
f423631
Fix travis
gardziejewskik Jul 25, 2018
20b5e32
Fix travis
gardziejewskik Jul 25, 2018
b9b3db2
Fix travis
gardziejewskik Jul 25, 2018
ff97ad3
Refactor with remove unnecessary dependency
gardziejewskik Jul 26, 2018
ca15bfe
Fix
gardziejewskik Jul 26, 2018
83d4fbe
Small refactor CodeGenerator stack
gardziejewskik Jul 28, 2018
7e414c4
Refactor to use serializer for Node
gardziejewskik Jul 28, 2018
a8a5991
CS fix
gardziejewskik Jul 28, 2018
45d5461
FilesystemStore implementation
gardziejewskik Jul 30, 2018
9babfeb
Improve uTests
gardziejewskik Aug 2, 2018
d22d289
Merge from origin/master
gardziejewskik Aug 2, 2018
c11de98
Resolve conflicts
gardziejewskik Aug 2, 2018
5c22a4a
Improve quality of tests
gardziejewskik Aug 4, 2018
4049d30
Change PhpStan DocParser interface and unit improvement
gardziejewskik Aug 5, 2018
94a9f37
Better segregation of object for testing
gardziejewskik Aug 5, 2018
9b48cf4
Move some tests to component
gardziejewskik Aug 5, 2018
4e152a3
Fix CS
gardziejewskik Aug 5, 2018
bfb49a7
PhpDocParser tests
gardziejewskik Aug 5, 2018
30589be
Improve CodeCoverage
gardziejewskik Aug 5, 2018
029d3cc
Add StoreDecorator for PatternGenerator
gardziejewskik Aug 5, 2018
73aa8d2
Different parameter name strategy for Blueprint
gardziejewskik Aug 15, 2018
48f08e6
Fixes after CR
gardziejewskik Aug 18, 2018
ce5f444
Refactor - rename
gardziejewskik Nov 17, 2019
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
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
composer.lock
vendor
vendor
.idea
.php_cs.cache
.phpcs.cache
data
test/result
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ install:
- stty cols 120 && composer show

script:
- if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi
- if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi
- if [[ $CS_CHECK == 'true' ]]; then composer 'cs-check' ; fi
- if [[ $TEST_COVERAGE == 'true' ]]; then composer 'test-unit-coverage' ; else composer 'test-unit' ; fi
- if [[ $TEST_COVERAGE == 'true' ]]; then composer 'test-component-coverage' ; else composer 'test-component' ; fi
- if [[ $TEST_COVERAGE == 'true' ]]; then composer 'test-integration-coverage' ; else composer 'test-integration' ; fi

after_script:
- if [[ $TEST_COVERAGE == 'true' ]]; then vendor/bin/php-coveralls -v ; fi
Expand Down
43 changes: 36 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
"keywords": [],
"require": {
"php": "^7.2",
"phpstan/phpdoc-parser": "^0.3.0",
"roave/better-reflection": "^3.0"
"phpstan/phpdoc-parser": "^0.3.0"
},
"require-dev": {
"phpunit/phpunit": "^7.2"
"friendsofphp/php-cs-fixer": "^2.12",
"phpstan/phpstan": "^0.10.2",
"phpstan/phpstan-phpunit": "^0.10.0",
"phpstan/phpstan-strict-rules": "^0.10.1",
"phpunit/phpunit": "^7.2",
"slevomat/coding-standard": "^4.6"
},
"autoload": {
"psr-4": {
Expand All @@ -25,10 +29,35 @@
"sort-packages": true
},
"scripts": {
"check": [
"@test"
"test-unit": "phpunit -c phpunit.xml --testsuite unit --colors=always ",
"test-unit-coverage": "phpunit -c phpunit.xml --testsuite unit --coverage-php test/result/unit.cov --colors=never",
"test-component": "phpunit -c phpunit.xml --testsuite component --colors=always ",
"test-component-coverage": "phpunit -c phpunit.xml --testsuite component --coverage-php test/result/component.cov --colors=never",
"test-integration": "phpunit -c phpunit.xml --testsuite integration --colors=always ",
"test-integration-coverage": "phpunit -c phpunit.xml --testsuite integration --coverage-php test/result/integration.cov --colors=never",
"cs-phpstan": [
"phpstan analyse --level=max --ansi --no-progress -c phpstan.neon src"
],
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
"cs-phpcs": [
"phpcs --standard=ruleset.xml --extensions=php -v --ignore=.config.php src test --cache=.phpcs.cache"
],
"cs-phpcs-fix": [
"phpcbf --standard=ruleset.xml --extensions=php --ignore=.config.php src test --cache=.phpcs.cache"
],
"cs-php-cs-fixer": [
"php-cs-fixer fix src --allow-risky yes --diff --show-progress dots --verbose --dry-run"
],
"cs-php-cs-fixer-fix": [
"php-cs-fixer fix src --allow-risky yes --diff --show-progress dots --verbose"
],
"cs-check": [
"@cs-phpcs",
"@cs-php-cs-fixer",
"@cs-phpstan"
],
"cs-fix": [
"@cs-phpcs-fix",
"@cs-php-cs-fixer-fix"
]
}
}
6 changes: 6 additions & 0 deletions phpstan-test.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
parameters:
tmpDir: data/cache/phpstan-test
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
- vendor/phpstan/phpstan-strict-rules/rules.neon
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
parameters:
tmpDir: data/cache/phpstan
8 changes: 7 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@

<testsuites>
<testsuite name="unit">
<directory>test/unit/</directory>
<directory>test/Unit/</directory>
</testsuite>
<testsuite name="component">
<directory>test/Component/</directory>
</testsuite>
<testsuite name="integration">
<directory>test/Integration/</directory>
</testsuite>
</testsuites>

Expand Down
45 changes: 45 additions & 0 deletions ruleset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0"?>
<ruleset name="ObjectBuilder">
<rule ref="PSR2"/>
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xml">
<exclude name="SlevomatCodingStandard.Classes.UnusedPrivateElements"/>
<exclude name="SlevomatCodingStandard.Commenting.DisallowOneLinePropertyDocComment"/>
<exclude name="SlevomatCodingStandard.ControlStructures.DisallowYodaComparison"/>
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameInAnnotation"/>
<exclude name="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly"/>
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions"/>
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedExceptions"/>
<exclude name="SlevomatCodingStandard.Namespaces.UseOnlyWhitelistedNamespaces"/>
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingPropertyTypeHint"/>
<exclude name="SlevomatCodingStandard.Operators.DisallowIncrementAndDecrementOperators"/>
</rule>
<rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName">
<properties>
<property name="rootNamespaces" type="array" value="
src=>RstGroup\ObjectBuilder,
test=>RstGroup\ObjectBuilder\Test,
"/>
</properties>
</rule>
<rule ref="SlevomatCodingStandard.Types.EmptyLinesAroundTypeBraces">
<properties>
<property name="linesCountAfterOpeningBrace" type="int" value="0"/>
<property name="linesCountBeforeClosingBrace" type="int" value="0"/>
</properties>
</rule>
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations">
<properties>
<property name="forbiddenAnnotations" type="array" value="@author,@created,@version,@package,@copyright,@license" />
</properties>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration">
<properties>
<property name="allAnnotationsAreUseful" type="boolean" value="true" />
</properties>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
<properties>
<property name="searchAnnotations" type="boolean" value="true" />
</properties>
</rule>
</ruleset>
3 changes: 2 additions & 1 deletion src/Builder.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php declare(strict_types=1);
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder;

interface Builder
{
/** @param mixed[] $data */
public function build(string $class, array $data): object;
}
55 changes: 55 additions & 0 deletions src/Builder/Blueprint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder;

use RstGroup\ObjectBuilder\Builder;

final class Blueprint implements Builder
{
/** @var Builder\Blueprint\Factory */
private $blueprintFactory;
/** @var ParameterNameStrategy */
private $strategy;

/** @codeCoverageIgnore */
public function __construct(
Builder\Blueprint\Factory $factory,
ParameterNameStrategy $strategy
) {
$this->blueprintFactory = $factory;
$this->strategy = $strategy;
}

/** @param mixed[] $data */
public function build(string $class, array $data): object
{
$blueprint = $this->blueprintFactory->create($class);

$preparedData = $this->prepareData($data);

return $blueprint($preparedData);
}

/**
* @param mixed[] $data
* @return mixed[]
*/
private function prepareData(array $data): array
{
$preparedData = [];

foreach ($data as $key => $value) {
if (is_array($value)) {
$value = $this->prepareData($value);
}

if (!is_int($key)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key can any, not only int or string

Copy link
Collaborator Author

@gardziejewskik gardziejewskik Aug 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key can either be an integer or a string. The value can be of any type.
Other types are casted underlying to string or int.

$key = $this->strategy->getName($key);
}

$preparedData[$key] = $value;
}

return $preparedData;
}
}
8 changes: 8 additions & 0 deletions src/Builder/Blueprint/Factory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder\Blueprint;

interface Factory
{
public function create(string $class): callable;
}
25 changes: 25 additions & 0 deletions src/Builder/Blueprint/Factory/CodeGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder\Blueprint\Factory;

use RstGroup\ObjectBuilder\Builder\Blueprint\Factory;
use RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\PatternGenerator;

final class CodeGenerator implements Factory
{
/** @var PatternGenerator */
private $generator;

/** @codeCoverageIgnore */
public function __construct(PatternGenerator $generator)
{
$this->generator = $generator;
}

public function create(string $class): callable
{
$pattern = $this->generator->create($class);

return eval($pattern);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should check this value before return to avoid typeerror

}
}
50 changes: 50 additions & 0 deletions src/Builder/Blueprint/Factory/CodeGenerator/Node.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator;

abstract class Node
{
/** @var string */
protected $name;
/** @var mixed|null */
private $defaultValue;
/** @var string */
private $type;
/** @var bool */
private $nullable;

/** @param mixed $defaultValue */
public function __construct(string $type, string $name, bool $nullable = false, $defaultValue = null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it's better to expects all parameters

{
$this->name = $name;
$this->defaultValue = $defaultValue;
$this->type = $type;
$this->nullable = $nullable;
}

public function type(): string
{
return $this->type;
}

public function name(): string
{
return $this->name;
}

public function withDefaultValue(): bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like method which changes immutable object. hasDefaultValue?

{
return null !== $this->defaultValue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Null it's still value

}

public function nullable(): bool
{
return $this->nullable;
}

/** @return mixed */
public function defaultValue()
{
return $this->defaultValue;
}
}
22 changes: 22 additions & 0 deletions src/Builder/Blueprint/Factory/CodeGenerator/Node/Complex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

use RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

final class Complex extends Node
{
/** @var Node[] */
private $nodes = [];

public function add(Node $node): void
{
$this->nodes[] = $node;
}

/** @return Node[] */
public function innerNodes(): iterable
{
return $this->nodes;
}
}
22 changes: 22 additions & 0 deletions src/Builder/Blueprint/Factory/CodeGenerator/Node/ObjectList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

use RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

final class ObjectList extends Node
{
/** @var Node */
private $objectNode;

public function __construct(string $name, Node $objectNode)
{
parent::__construct($objectNode->type(), $name);
$this->objectNode = $objectNode;
}

public function objectNode(): Node
{
return $this->objectNode;
}
}
9 changes: 9 additions & 0 deletions src/Builder/Blueprint/Factory/CodeGenerator/Node/Scalar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

use RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

final class Scalar extends Node
{
}
10 changes: 10 additions & 0 deletions src/Builder/Blueprint/Factory/CodeGenerator/Node/Serializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php declare(strict_types = 1);

namespace RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

use RstGroup\ObjectBuilder\Builder\Blueprint\Factory\CodeGenerator\Node;

interface Serializer
{
public function serialize(Node $node): string;
}
Loading