diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml
new file mode 100644
index 0000000..52f86df
--- /dev/null
+++ b/.github/workflows/coding-standards.yml
@@ -0,0 +1,12 @@
+name: Coding Standards
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ cs:
+ uses: ray-di/.github/.github/workflows/coding-standards.yml@v1
+ with:
+ php_version: 8.3
\ No newline at end of file
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
new file mode 100644
index 0000000..9eb813a
--- /dev/null
+++ b/.github/workflows/continuous-integration.yml
@@ -0,0 +1,13 @@
+name: Continuous Integration
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ ci:
+ uses: ray-di/.github/.github/workflows/continuous-integration.yml@v1
+ with:
+ old_stable: '["8.2", "8.3", "8.4"]'
+ current_stable: 8.5
\ No newline at end of file
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
new file mode 100644
index 0000000..79ea4f6
--- /dev/null
+++ b/.github/workflows/static-analysis.yml
@@ -0,0 +1,43 @@
+name: Static Analysis
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ phpstan:
+ name: PHPStan
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.3'
+ coverage: none
+ tools: cs2pr
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install dependencies
+ run: composer install --no-interaction --no-progress --prefer-dist
+
+ - name: Run PHPStan
+ run: ./vendor/bin/phpstan analyse -c phpstan.neon --no-progress --no-interaction --error-format=checkstyle | cs2pr
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 88e2d70..ea59c2e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,5 +5,6 @@
/composer.lock
/phpunit.xml
/.php_cs.cache
+/.phpcs-cache
.phpunit.result.cache
/.phpunit.cache/
diff --git a/.php_cs.dist b/.php_cs.dist
deleted file mode 100644
index e7a5cac..0000000
--- a/.php_cs.dist
+++ /dev/null
@@ -1,185 +0,0 @@
-exclude(['tests/Fake', 'tests/tmp', 'template'])
- ->in(__DIR__);
-
-return \PhpCsFixer\Config::create()
- ->setRiskyAllowed(true)
- ->setRules([
- '@PSR2' => true,
- '@PHP70Migration:risky' => true,
- '@PHP71Migration:risky' => true,
- 'align_multiline_comment' => true,
- 'array_indentation' => true,
- 'array_syntax' => ['syntax' => 'short'],
- 'backtick_to_shell_exec' => true,
- 'binary_operator_spaces' => true, // @Symfony
- 'blank_line_after_opening_tag' => true, // @Symfony
- 'blank_line_before_return' => true,
- 'blank_line_before_statement' => ['statements' => ['break', 'continue', 'declare', 'return', 'throw']], // @Symfony
- 'cast_spaces' => true, // @Symfony
- 'class_attributes_separation' => ['elements' => ['const', 'method']], // @Symfony
-// 'class_keyword_remove' => true,
- 'combine_consecutive_issets' => true,
- 'combine_consecutive_unsets' => true,
-// 'comment_to_phpdoc' => true,
- 'compact_nullable_typehint' => true,
- 'concat_space' => ['spacing' => 'one'], // @Symfony
-// 'date_time_immutable' => true,
- 'declare_equal_normalize' => true, // @Symfony
- 'dir_constant' => true, // @Symfony:risky
- 'ereg_to_preg' => true, // @Symfony:risky
- 'error_suppression' => true, // @Symfony:risky
- 'escape_implicit_backslashes' => true,
- 'explicit_indirect_variable' => true,
- 'explicit_string_variable' => true,
-// 'final_internal_class' => true,
- 'fully_qualified_strict_types' => true,
- 'function_to_constant' => true, // @Symfony:risky
- 'function_typehint_space' => true, // @Symfony
- 'general_phpdoc_annotation_remove' => ['author', 'category', 'package', 'copyright', 'version'],
- 'header_comment' => ['header' => $header, 'comment_type' => 'comment'],
- 'heredoc_to_nowdoc' => true,
- 'include' => true, // @Symfony
-// 'increment_style' => 'pre', // @Symfony
- 'indentation_type' => true,
- 'is_null' => ['use_yoda_style' => false], // @Symfony:risky
- 'linebreak_after_opening_tag' => true,
-// 'list_syntax' => true,
-// 'logical_operators' => true,
- 'lowercase_cast' => true, // @Symfony
- 'lowercase_static_reference' => true, // @Symfony
- 'magic_constant_casing' => true,
-// 'mb_str_functions' => true,
- 'method_chaining_indentation' => true,
- 'method_separation' => true,
- 'modernize_types_casting' => true, // @Symfony:risky
- 'multiline_comment_opening_closing' => true,
- 'multiline_whitespace_before_semicolons' => true,
-// 'native_constant_invocation' => true,
- 'native_function_casing' => true, // @Symfony
-// 'native_function_invocation' => true,
-// 'new_with_braces' => true, // @Symfony
- 'no_alias_functions' => true, // @Symfony:risky
- 'no_alternative_syntax' => true,
- 'no_binary_string' => true,
- 'no_blank_lines_after_class_opening' => true, // @Symfony
- 'no_blank_lines_after_phpdoc' => true, // @Symfony
-// 'no_blank_lines_before_namespace' => true,
- 'no_empty_comment' => true, // @Symfony
- 'no_empty_phpdoc' => true, // @Symfony
- 'no_empty_statement' => true, // @Symfony
- 'no_extra_blank_lines' => true,
- 'no_homoglyph_names' => true, // @Symfony:risky
- 'no_leading_import_slash' => true, // @Symfony
- 'no_leading_namespace_whitespace' => true, // @Symfony
- 'no_mixed_echo_print' => true, // @Symfony
- 'no_multiline_whitespace_around_double_arrow' => true, // @Symfony
- 'no_null_property_initialization' => true,
- 'no_php4_constructor' => true,
- 'no_short_bool_cast' => true, // @Symfony
- 'no_short_echo_tag' => false,
- 'no_singleline_whitespace_before_semicolons' => true, // @Symfony
- 'no_spaces_around_offset' => true, // @Symfony
- 'no_superfluous_elseif' => true,
- 'no_superfluous_phpdoc_tags' => true,
- 'no_trailing_comma_in_list_call' => true, // @Symfony
- 'no_trailing_comma_in_singleline_array' => true, // @Symfony
- 'no_trailing_whitespace' => true,
- 'no_trailing_whitespace_in_comment' => true,
- 'no_unneeded_control_parentheses' => true, // @Symfony
- 'no_unneeded_curly_braces' => true, // @Symfony
- 'no_unneeded_final_method' => true, // @Symfony
- 'no_unreachable_default_argument_value' => true,
- 'no_unset_on_property' => true,
- 'no_unused_imports' => true,
- 'no_useless_else' => true,
- 'no_useless_return' => true,
- 'no_whitespace_before_comma_in_array' => true, // @Symfony
- 'no_whitespace_in_blank_line' => true, // @Symfony
- 'non_printable_character' => true, // @Symfony
- 'normalize_index_brace' => true, // @Symfony
- 'not_operator_with_space' => false,
- 'not_operator_with_successor_space' => true,
- 'object_operator_without_whitespace' => true, // @Symfony
- 'ordered_class_elements' => true,
- 'ordered_imports' => true,
- 'php_unit_construct' => true, // @Symfony:risky
- 'php_unit_dedicate_assert' => true,
- 'php_unit_expectation' => true,
- 'php_unit_fqcn_annotation' => true, // @Symfony
-// 'php_unit_internal_class' => true, // @Symfony]
-// 'php_unit_mock' => true,
- 'php_unit_namespaced' => true,
- 'php_unit_no_expectation_annotation' => true,
- 'php_unit_ordered_covers' => true,
- 'php_unit_set_up_tear_down_visibility' => true,
- 'php_unit_strict' => true,
-// 'php_unit_test_annotation' => true,
-// 'php_unit_test_case_static_method_calls' => true,
-// 'php_unit_test_class_requires_covers' => true,
-// 'phpdoc_add_missing_param_annotation' => true,
- 'phpdoc_align' => true, // @Symfony]
- 'phpdoc_annotation_without_dot' => true, // @Symfony]
- 'phpdoc_indent' => true, // @Symfony]
- 'phpdoc_inline_tag' => true, // @Symfony]
- 'phpdoc_no_access' => true, // @Symfony]
- 'phpdoc_no_alias_tag' => true, // @Symfony
- 'phpdoc_no_empty_return' => true, // @Symfony
- 'phpdoc_no_package' => true, // @Symfony
-// 'phpdoc_no_useless_inheritdoc' => true, // @Symfony
- 'phpdoc_order' => true,
- 'phpdoc_return_self_reference' => true, // @Symfony
- 'phpdoc_scalar' => true, // @Symfony
- 'phpdoc_separation' => true, // @Symfony
- 'phpdoc_single_line_var_spacing' => true, // @Symfony
-// 'phpdoc_summary' => true, // @Symfony
- 'phpdoc_to_comment' => true, // @Symfony
- 'phpdoc_trim' => true, // @Symfony
- 'phpdoc_trim_consecutive_blank_line_separation' => true,
- 'phpdoc_types' => true, // @Symfony
- 'phpdoc_types_order' => true, // @Symfony
- 'phpdoc_var_without_name' => true, // @Symfony
- 'protected_to_private' => true,
- 'psr0' => true,
- 'psr4' => true, // @Symfony:risky
- 'return_assignment' => true,
- 'return_type_declaration' => ['space_before' => 'one'],
- 'self_accessor' => true, // @Symfony:risky
- 'semicolon_after_instruction' => true, // @Symfony
- 'set_type_to_cast' => true, // @Symfony:risky
- 'short_scalar_cast' => true, // @Symfony:risky
- 'simplified_null_return' => true,
- 'single_blank_line_before_namespace' => true, // @Symfony
-// 'single_line_comment_style' => true, // @Symfony
- 'single_line_after_imports' => true,
- 'single_quote' => true, // @Symfony
- 'space_after_semicolon' => true, // @Symfony
- 'standardize_increment' => true, // @Symfony
- 'standardize_not_equals' => true, // @Symfony
-// 'static_lambda' => true,
-// 'strict_comparison' => true,
- 'strict_param' => true,
-// 'string_line_ending' => true,
- 'switch_case_semicolon_to_colon' => true,
- 'switch_case_space' => true,
- 'ternary_operator_spaces' => true,
-// 'trailing_comma_in_multiline_array' => true, // @Symfony
- 'trim_array_spaces' => true, // @Symfony
- 'unary_operator_spaces' => true, // @Symfony
- 'visibility_required' => true,
-// 'void_return' => true, // @PHP71Migration:risky
- 'whitespace_after_comma_in_array' => true, // @Symfony
-// 'yoda_style' => true // @Symfony
- ])
- ->setFinder($finder);
diff --git a/composer.json b/composer.json
index 22394c0..e253c7d 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"name": "ray/object-visual-grapher",
- "description": "",
+ "description": "A visual graph generator for Ray.Di object dependency graphs",
"license": "MIT",
"authors": [
{
@@ -12,14 +12,21 @@
"php": "^8.2"
},
"require-dev": {
- "phpunit/phpunit": "^10.5",
- "squizlabs/php_codesniffer": "^3.2",
- "friendsofphp/php-cs-fixer": "^2.11",
+ "bear/package": "^1.9.6",
+ "bear/query-repository": "^1.13",
+ "doctrine/coding-standard": "^14.0",
"phpmd/phpmd": "^2.6",
+ "phpstan/phpstan": "^2.0",
+ "phpunit/phpunit": "^10.5",
"ray/di": "^2.10|2.x-dev",
- "bear/package": "^1.9.6",
- "doctrine/annotations": "^1.8",
- "phpstan/phpstan": "^0.12.5"
+ "slevomat/coding-standard": "^8.15",
+ "squizlabs/php_codesniffer": "^4.0"
+ },
+ "config": {
+ "sort-packages": true,
+ "allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": false
+ }
},
"autoload": {
"psr-4": {
@@ -39,23 +46,28 @@
"php ./tests/bin/package.php && dot -T png ./tests/bin/package.dot -o ./tests/bin/package.png && open ./tests/bin/package.png"
],
"test": [
- "vendor/bin/phpunit"
+ "phpunit"
],
"tests": [
"@cs",
"@test",
- "vendor/bin/phpstan analyse -l max src -c phpstan.neon --no-progress"
+ "phpstan analyse -c phpstan.neon --no-progress"
],
"coverage": [
- "php -dzend_extension=xdebug.so ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage"
+ "php -dzend_extension=xdebug.so -dxdebug.mode=coverage ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage"
],
"cs": [
- "vendor/bin/php-cs-fixer fix -v --dry-run",
- "vendor/bin/phpcs --standard=phpcs.xml src;"
+ "phpcs --standard=./phpcs.xml src tests"
],
"cs-fix": [
- "vendor/bin/php-cs-fixer fix -v",
- "vendor/bin/phpcbf src tests"
+ "phpcbf src tests"
]
+ },
+ "scripts-descriptions": {
+ "test": "Run unit tests",
+ "tests": "Run coding standards, tests, and static analysis",
+ "coverage": "Generate test coverage report with Xdebug",
+ "cs": "Check coding standards",
+ "cs-fix": "Fix coding standards violations"
}
}
diff --git a/phpcs.xml b/phpcs.xml
index 460d322..19042e4 100755
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -1,18 +1,73 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ src
+ tests
+ */tests/Fake/*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/phpstan.neon b/phpstan.neon
index e69de29..2de7ef5 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -0,0 +1,5 @@
+parameters:
+ level: 8
+ phpVersion: 80200
+ paths:
+ - src
\ No newline at end of file
diff --git a/src/Arrow.php b/src/Arrow.php
index 19042ca..353f745 100644
--- a/src/Arrow.php
+++ b/src/Arrow.php
@@ -7,31 +7,23 @@
use Ray\Aop\ReflectionClass;
use Ray\Di\ProviderInterface;
+use function class_exists;
+
final class Arrow implements ArrowInterface
{
- /**
- * @var array
- */
+ /** @var array */
public static $history;
- /**
- * @var string
- */
+ /** @var string */
public $class;
- /**
- * @var string
- */
+ /** @var string */
private $interface;
- /**
- * @var string
- */
+ /** @var string */
private $arrowHead;
- /**
- * @var bool
- */
+ /** @var bool */
private $isInvalid;
public function __construct(string $fromId, string $toId, string $toClass)
@@ -41,15 +33,14 @@ public function __construct(string $fromId, string $toId, string $toClass)
$isProvider = class_exists($toClass) && (new ReflectionClass($toClass))->implementsInterface(ProviderInterface::class);
$this->arrowHead = $isProvider ? 'arrowhead=onormalonormal' : 'arrowhead=onormal';
$index = $fromId . $toId . $toClass;
- if (isset(self::$history[$index])) {
- // log duplicated (mostly @depracated) bindings (
- // error_log(sprintf('from:%s to:%s class:%s index:%s ', $fromId, $toClass, $toClass, $index));
- }
+ // log duplicated (mostly @depracated) bindings (
+ // error_log(sprintf('from:%s to:%s class:%s index:%s ', $fromId, $toClass, $toClass, $index));
+
$this->isInvalid = isset(self::$history[$index]);
self::$history[$index] = true;
}
- public function __toString()
+ public function __toString(): string
{
return $this->isInvalid ? '' : <<interface} -> {$this->class} [style=solid, arrowtail=none, {$this->arrowHead}]
diff --git a/src/ArrowInterface.php b/src/ArrowInterface.php
index beb93ab..cdcc9b4 100644
--- a/src/ArrowInterface.php
+++ b/src/ArrowInterface.php
@@ -6,5 +6,5 @@
interface ArrowInterface
{
- public function __toString();
+ public function __toString(): string;
}
diff --git a/src/ClassId.php b/src/ClassId.php
index 72fed29..292be16 100644
--- a/src/ClassId.php
+++ b/src/ClassId.php
@@ -6,8 +6,8 @@
final class ClassId
{
- public function __invoke(string $class) : string
+ public function __invoke(string $class): string
{
- return 'class_' . (new SnakeName)($class);
+ return 'class_' . (new SnakeName())($class);
}
}
diff --git a/src/ClassNode.php b/src/ClassNode.php
index 261089a..9db8cb9 100644
--- a/src/ClassNode.php
+++ b/src/ClassNode.php
@@ -4,36 +4,34 @@
namespace Ray\ObjectGrapher;
+use ReflectionClass;
+use ReflectionException;
+
+use function assert;
+use function class_exists;
+use function in_array;
+use function str_replace;
+
+use const PHP_EOL;
+
final class ClassNode implements NodeInterface
{
- /**
- * @var array
- */
+ /** @var array */
public static $ids = [];
- /**
- * @var string
- */
+ /** @var string */
private $id;
- /**
- * @var string
- */
+ /** @var string */
private $namespace;
- /**
- * @var string
- */
+ /** @var string */
private $class;
- /**
- * @var string
- */
+ /** @var string */
private $settersTable = '';
- /**
- * @var bool
- */
+ /** @var bool */
private $invalid = false;
/**
@@ -41,7 +39,7 @@ final class ClassNode implements NodeInterface
* @param string $class class
* @param array $setters
*
- * @throws \ReflectionException
+ * @throws ReflectionException
*/
public function __construct(string $id, string $class, array $setters)
{
@@ -50,10 +48,11 @@ public function __construct(string $id, string $class, array $setters)
return;
}
+
self::$ids[] = $id;
$this->id = $id;
assert(class_exists($class));
- $ref = new \ReflectionClass($class);
+ $ref = new ReflectionClass($class);
$this->namespace = str_replace('\\', '\\\\', $ref->getNamespaceName());
$this->class = $ref->getShortName();
foreach ($setters as $setterMethod => $port) {
@@ -61,7 +60,7 @@ public function __construct(string $id, string $class, array $setters)
}
}
- public function __toString()
+ public function __toString(): string
{
$html = $this->invalid ? '' : /* @lang html */ <<< EOT
{$this->id} [style=solid, margin=0.02, label=
diff --git a/src/DependencyId.php b/src/DependencyId.php
index 5877054..e1fb5a1 100644
--- a/src/DependencyId.php
+++ b/src/DependencyId.php
@@ -4,14 +4,18 @@
namespace Ray\ObjectGrapher;
+use function class_exists;
+use function sprintf;
+
final class DependencyId
{
- public function __invoke(string $interace, string $name) : string
+ public function __invoke(string $interace, string $name): string
{
if (class_exists($interace)) {
- return (new ClassId)($interace);
+ return (new ClassId())($interace);
}
- $snakeName = new SnakeName;
+
+ $snakeName = new SnakeName();
return sprintf('dependency_%s_%s', ($snakeName)($interace), ($snakeName)($name));
}
diff --git a/src/Graph.php b/src/Graph.php
index 3de5dc4..d30579c 100644
--- a/src/Graph.php
+++ b/src/Graph.php
@@ -4,6 +4,8 @@
namespace Ray\ObjectGrapher;
+use const PHP_EOL;
+
final class Graph
{
/**
@@ -20,12 +22,13 @@ final class Graph
*/
private $arrows;
- public function __toString()
+ public function __toString(): string
{
$string = '';
foreach ($this->nodes as $node) {
$string .= (string) $node . PHP_EOL;
}
+
$string .= PHP_EOL;
foreach ($this->arrows as $arrow) {
$string .= (string) $arrow . PHP_EOL;
@@ -34,12 +37,12 @@ public function __toString()
return $string;
}
- public function addNode(NodeInterface $node) : void
+ public function addNode(NodeInterface $node): void
{
$this->nodes[] = $node;
}
- public function addArrow(ArrowInterface $arrow) : void
+ public function addArrow(ArrowInterface $arrow): void
{
$this->arrows[] = $arrow;
}
diff --git a/src/InstanceNode.php b/src/InstanceNode.php
index f50202e..00baf98 100644
--- a/src/InstanceNode.php
+++ b/src/InstanceNode.php
@@ -6,26 +6,24 @@
use Ray\Di\Instance;
+use function addslashes;
+use function gettype;
+use function str_replace;
+
+use const PHP_EOL;
+
final class InstanceNode implements NodeInterface
{
- /**
- * @var string
- */
+ /** @var string */
private $id;
- /**
- * @var string
- */
+ /** @var string */
private $interface;
- /**
- * @var string
- */
+ /** @var string */
private $type;
- /**
- * @var string
- */
+ /** @var string */
private $named;
public function __construct(string $id, string $interface, string $named, Instance $instance)
@@ -36,7 +34,7 @@ public function __construct(string $id, string $interface, string $named, Instan
$this->type = gettype($instance->value);
}
- public function __toString()
+ public function __toString(): string
{
$html = /* @lang html */ <<< EOT
{$this->id} [style=dashed, margin=0.02, label=
diff --git a/src/InterfaceNode.php b/src/InterfaceNode.php
index c9747c9..f35a52b 100644
--- a/src/InterfaceNode.php
+++ b/src/InterfaceNode.php
@@ -4,31 +4,30 @@
namespace Ray\ObjectGrapher;
+use ReflectionClass;
+
+use function assert;
+use function class_exists;
+use function interface_exists;
+use function str_replace;
+
+use const PHP_EOL;
+
final class InterfaceNode implements NodeInterface
{
- /**
- * @var string
- */
+ /** @var string */
private $id;
- /**
- * @var string
- */
+ /** @var string */
private $namespace;
- /**
- * @var string
- */
+ /** @var string */
private $interface;
- /**
- * @var string
- */
+ /** @var string */
private $named;
- /**
- * @var string
- */
+ /** @var string */
private $bgColor;
public function __construct(string $id, string $interface, string $named)
@@ -39,7 +38,7 @@ public function __construct(string $id, string $interface, string $named)
$this->bgColor = $interface ? 'ffffff' : 'aaaaaa';
}
- public function __toString()
+ public function __toString(): string
{
$html = /* @lang html */ <<< EOT
{$this->id} [style=dashed, margin=0.02, label=
@@ -56,15 +55,15 @@ public function __toString()
return str_replace(PHP_EOL, '', $html);
}
- public function setInstance() : void
+ public function setInstance(): void
{
$this->interface = 'instance';
}
- private function setNamespace(string $interface) : void
+ private function setNamespace(string $interface): void
{
assert(interface_exists($interface) || class_exists($interface));
- $ref = new \ReflectionClass($interface);
+ $ref = new ReflectionClass($interface);
$this->namespace = str_replace('\\', '\\\\', $ref->getNamespaceName());
$this->interface = $ref->getShortName();
}
diff --git a/src/MyDependency.php b/src/MyDependency.php
index 4a33430..18d9734 100644
--- a/src/MyDependency.php
+++ b/src/MyDependency.php
@@ -10,32 +10,24 @@
final class MyDependency
{
- /**
- * @var string
- */
+ /** @var string */
public $class;
- /**
- * @var string
- */
+ /** @var string */
public $classId;
- /**
- * @var null|Arguments
- */
+ /** @var Arguments|null */
public $arguments;
- /**
- * @var SetterMethod
- */
+ /** @var SetterMethod */
public $setterMethods;
public function __construct(Dependency $dependency)
{
- $prop = new Prop;
+ $prop = new Prop();
$newInstance = $prop($dependency, 'newInstance');
$this->class = $prop($newInstance, 'class');
- $this->classId = (new ClassId)($this->class);
+ $this->classId = (new ClassId())($this->class);
$this->arguments = $prop($newInstance, 'arguments');
$this->setterMethods = $prop($newInstance, 'setterMethods');
}
diff --git a/src/NodeInterface.php b/src/NodeInterface.php
index d4272ab..7c4e0ea 100644
--- a/src/NodeInterface.php
+++ b/src/NodeInterface.php
@@ -6,5 +6,5 @@
interface NodeInterface
{
- public function __toString();
+ public function __toString(): string;
}
diff --git a/src/ObjectGrapher.php b/src/ObjectGrapher.php
index 64c90e3..de66b76 100644
--- a/src/ObjectGrapher.php
+++ b/src/ObjectGrapher.php
@@ -12,58 +12,51 @@
use Ray\Di\DependencyInterface;
use Ray\Di\DependencyProvider;
use Ray\Di\Instance;
+use ReflectionClass;
+use ReflectionException;
+
+use function assert;
+use function class_exists;
+use function explode;
+use function interface_exists;
+use function sprintf;
final class ObjectGrapher
{
- /**
- * @var Prop
- */
+ /** @var Prop */
private $prop;
- /**
- * @var Container
- */
+ /** @var Container */
private $container;
- /**
- * @var Container
- */
+ /** @var Container */
private $analysisContainer;
- /**
- * @var array
- */
+ /** @var array */
private $dependencies = [];
- /**
- * @var Graph
- */
+
+ /** @var Graph */
private $graph;
- /**
- * @var DependencyId
- */
+ /** @var DependencyId */
private $dependencyId;
- /**
- * @var ClassId
- */
+ /** @var ClassId */
private $classId;
- /**
- * @var SnakeName
- */
+ /** @var SnakeName */
private $snakeName;
public function __construct()
{
- $this->prop = new Prop;
- $this->graph = new Graph;
- $this->dependencyId = new DependencyId;
- $this->classId = new ClassId;
- $this->snakeName = new SnakeName;
+ $this->prop = new Prop();
+ $this->graph = new Graph();
+ $this->dependencyId = new DependencyId();
+ $this->classId = new ClassId();
+ $this->snakeName = new SnakeName();
}
- public function __invoke(AbstractModule $module) : string
+ public function __invoke(AbstractModule $module): string
{
$this->init();
$this->container = $module->getContainer();
@@ -75,42 +68,48 @@ public function __invoke(AbstractModule $module) : string
return $this->toString();
}
- private function init() : void
+ private function init(): void
{
Arrow::$history = ToClass::$index = ClassNode::$ids = [];
- $this->graph = new Graph;
- $this->analysisContainer = new Container;
+ $this->graph = new Graph();
+ $this->analysisContainer = new Container();
$this->dependencies = [];
}
- private function setGraph(string $type, string $name, DependencyInterface $dependency) : void
+ private function setGraph(string $type, string $name, DependencyInterface $dependency): void
{
$isTargetBinding = ! interface_exists($type);
$dependencyId = ($this->dependencyId)($type, $name);
if (! $isTargetBinding) {
$this->graph->addNode(new InterfaceNode($dependencyId, $type, $name));
}
+
if ($dependency instanceof Instance) {
$this->graph->addNode(new InstanceNode($dependencyId, $type, $name, $dependency));
}
+
if ($dependency instanceof Dependency) {
$this->dependencyNode($dependencyId, new MyDependency($dependency), $isTargetBinding);
}
- if ($dependency instanceof DependencyProvider) {
- $this->providerNode($dependencyId, $dependency);
+
+ if (! ($dependency instanceof DependencyProvider)) {
+ return;
}
+
+ $this->providerNode($dependencyId, $dependency);
}
- private function dependencyNode(string $interfaceId, MyDependency $dependency, bool $isTargetBinding) : void
+ private function dependencyNode(string $interfaceId, MyDependency $dependency, bool $isTargetBinding): void
{
if (! $isTargetBinding) {
$this->graph->addArrow(new ToClass($interfaceId, $dependency->classId));
}
+
$setters = $this->lineDependency($dependency);
$this->graph->addNode(new ClassNode($dependency->classId, $dependency->class, $setters));
}
- private function providerNode(string $interfaceId, DependencyProvider $dependency) : void
+ private function providerNode(string $interfaceId, DependencyProvider $dependency): void
{
$dependency = new MyDependency(($this->prop)($dependency, 'dependency'));
$setters = $this->lineDependency($dependency);
@@ -118,17 +117,17 @@ private function providerNode(string $interfaceId, DependencyProvider $dependenc
if ($interfaceId) {
$this->graph->addArrow(new ToProvider($interfaceId, $dependency->classId));
}
+
$this->graph->addNode(new ClassNode($dependency->classId, $dependency->class, $setters));
}
- /**
- * @return array setter symbol
- */
- private function lineDependency(MyDependency $dependency) : array
+ /** @return array setter symbol */
+ private function lineDependency(MyDependency $dependency): array
{
if (! $dependency->arguments) {
return [];
}
+
// constructor injection
$arguments = ($this->prop)($dependency->arguments, 'arguments');
$port = sprintf('p_%s_construct', ($this->snakeName)($dependency->class));
@@ -148,9 +147,9 @@ private function lineDependency(MyDependency $dependency) : array
return $setters;
}
- private function setterArrow(string $classPort, string $dependencyIndex) : void
+ private function setterArrow(string $classPort, string $dependencyIndex): void
{
- [$type, $name] = \explode('-', $dependencyIndex);
+ [$type, $name] = explode('-', $dependencyIndex);
$dependencyId = ($this->dependencyId)($type, $name);
$this->graph->addArrow(new Arrow($classPort, $dependencyId, $type));
if (class_exists($type)) {
@@ -158,19 +157,21 @@ private function setterArrow(string $classPort, string $dependencyIndex) : void
return;
}
+
$this->graph->addNode(new InterfaceNode($dependencyId, $type, $name));
}
- private function addClassNode(string $dependencyIndex) : void
+ private function addClassNode(string $dependencyIndex): void
{
- [$type, $name] = \explode('-', $dependencyIndex);
+ [$type, $name] = explode('-', $dependencyIndex);
assert(class_exists($type));
- $isAbstract = (new \ReflectionClass($type))->isAbstract();
+ $isAbstract = (new ReflectionClass($type))->isAbstract();
if ($isAbstract) {
$this->graph->addNode(new InterfaceNode(($this->classId)($type), $type, $name));
return;
}
+
$container = $this->container->getContainer();
if (isset($container[$dependencyIndex]) || isset($this->dependencies[$dependencyIndex])) {
return;
@@ -184,26 +185,24 @@ private function addClassNode(string $dependencyIndex) : void
* @param string $classId class ID
* @param string $port port ID
*/
- private function drawInjectionGraph(array $arguments, string $classId, string $port) : void
+ private function drawInjectionGraph(array $arguments, string $classId, string $port): void
{
foreach ($arguments as $argument) {
- assert($argument instanceof Argument);
$dependencyIndex = ($this->prop)($argument, 'index');
$classPort = sprintf('%s:%s:e', $classId, $port);
$this->setterArrow($classPort, $dependencyIndex);
}
}
- /**
- * @throws \ReflectionException
- */
- private function bindOnTheFly(string $dependencyIndex, string $type, string $name) : void
+ /** @throws ReflectionException */
+ private function bindOnTheFly(string $dependencyIndex, string $type, string $name): void
{
/** @var class-string $type */
$bind = new Bind($this->analysisContainer, $type);
if ($name !== '') {
$bind->annotatedWith($name);
}
+
$bind->to($type);
$dependency = $this->analysisContainer->getContainer()[$dependencyIndex];
assert($dependency instanceof Dependency);
@@ -212,7 +211,7 @@ private function bindOnTheFly(string $dependencyIndex, string $type, string $nam
$this->graph->addNode(new ClassNode(($this->classId)($type), $type, $setters));
}
- private function toString() : string
+ private function toString(): string
{
return <<getProperty($prop);
- } catch (\ReflectionException $e) {
+ $property = (new ReflectionClass($object::class))->getProperty($prop);
+ } catch (ReflectionException) {
return '';
}
diff --git a/src/ProviderNode.php b/src/ProviderNode.php
index 863f18a..d021ef6 100644
--- a/src/ProviderNode.php
+++ b/src/ProviderNode.php
@@ -4,21 +4,19 @@
namespace Ray\ObjectGrapher;
+use function str_replace;
+
+use const PHP_EOL;
+
final class ProviderNode implements NodeInterface
{
- /**
- * @var string
- */
+ /** @var string */
private $id;
- /**
- * @var string
- */
+ /** @var string */
private $provider;
- /**
- * @var string
- */
+ /** @var string */
private $settersTable = '';
/**
@@ -35,7 +33,7 @@ public function __construct(string $id, string $provider, array $setters)
}
}
- public function __toString()
+ public function __toString(): string
{
$html = /* @lang html */ <<< EOT
{$this->id} [style=solid, margin=0.02, label=<{$this->provider}
|
diff --git a/src/SnakeName.php b/src/SnakeName.php
index 2d7aaa2..0900f62 100644
--- a/src/SnakeName.php
+++ b/src/SnakeName.php
@@ -4,9 +4,11 @@
namespace Ray\ObjectGrapher;
+use function str_replace;
+
final class SnakeName
{
- public function __invoke(string $class) : string
+ public function __invoke(string $class): string
{
return str_replace('\\', '_', $class);
}
diff --git a/src/ToClass.php b/src/ToClass.php
index d20b680..1f0b316 100644
--- a/src/ToClass.php
+++ b/src/ToClass.php
@@ -6,24 +6,16 @@
final class ToClass implements ArrowInterface
{
- /**
- * @var array
- */
+ /** @var array */
public static $index;
- /**
- * @var string
- */
+ /** @var string */
public $class;
- /**
- * @var string
- */
+ /** @var string */
private $interface;
- /**
- * @var bool
- */
+ /** @var bool */
private $noArrow;
public function __construct(string $interfaceId, string $classId)
@@ -35,7 +27,7 @@ public function __construct(string $interfaceId, string $classId)
self::$index[$indexId] = true;
}
- public function __toString()
+ public function __toString(): string
{
return $this->noArrow ? '' : <<interface} -> {$this->class} [style=dashed, arrowtail=none, arrowhead=onormal]
diff --git a/src/ToProvider.php b/src/ToProvider.php
index d1f21a3..ad5b1d9 100644
--- a/src/ToProvider.php
+++ b/src/ToProvider.php
@@ -6,14 +6,10 @@
final class ToProvider implements ArrowInterface
{
- /**
- * @var string
- */
+ /** @var string */
public $class;
- /**
- * @var string
- */
+ /** @var string */
private $interface;
public function __construct(string $interface, string $class)
@@ -22,7 +18,7 @@ public function __construct(string $interface, string $class)
$this->interface = $interface;
}
- public function __toString()
+ public function __toString(): string
{
return <<interface} -> {$this->class} [style=dashed, arrowtail=none, arrowhead=onormalonormal]
diff --git a/tests/ObjectVisualGrapherTest.php b/tests/ObjectVisualGrapherTest.php
index fb670a9..1ca1cb1 100644
--- a/tests/ObjectVisualGrapherTest.php
+++ b/tests/ObjectVisualGrapherTest.php
@@ -4,32 +4,31 @@
namespace Ray\ObjectGrapher;
-use function array_keys;
use BEAR\Package\PackageModule;
use BEAR\Resource\Module\ResourceModule;
use PHPUnit\Framework\TestCase;
use Ray\Aop\Matcher;
use Ray\Aop\Pointcut;
+use function array_keys;
+
class ObjectVisualGrapherTest extends TestCase
{
- /**
- * @var ObjectGrapher
- */
+ /** @var ObjectGrapher */
protected $objectGrapher;
- protected function setUp() : void
+ protected function setUp(): void
{
- $this->objectGrapher = new ObjectGrapher;
+ $this->objectGrapher = new ObjectGrapher();
}
- public function testIsInstanceOfObjectGrapher() : void
+ public function testIsInstanceOfObjectGrapher(): void
{
$actual = $this->objectGrapher;
$this->assertInstanceOf(ObjectGrapher::class, $actual);
}
- public function test__invoke() : void
+ public function testInvoke(): void
{
$dot = ($this->objectGrapher)(new FakeModule());
$this->assertStringContainsString('dependency_Ray_ObjectGrapher_LoggerInterface_ -> class_Ray_ObjectGrapher_DatabaseLogger', $dot);
@@ -38,7 +37,7 @@ public function test__invoke() : void
$this->assertStringContainsString('dependency_Ray_ObjectGrapher_PdoInterface_ -> class_Ray_ObjectGrapher_PdoProvider [style=dashed, arrowtail=none, arrowhead=onormalonormal]', $dot);
}
- public function test__invokeBearResource() : void
+ public function testInvokeBearResource(): void
{
$dot = ($this->objectGrapher)(new ResourceModule('a'));
$this->assertStringContainsString('dependency__BEAR_Resource_Annotation_AppName [style', $dot);
@@ -46,17 +45,17 @@ public function test__invokeBearResource() : void
$this->assertStringContainsString('dependency_BEAR_Resource_SchemeCollectionInterface_ -> class_BEAR_Resource_Module_SchemeCollectionProvider [style=dashed, arrowtail=none, arrowhead=onormalonormal]', $dot);
}
- public function test__invokeBearPackage() : void
+ public function testInvokeBearPackage(): void
{
- $dot = ($this->objectGrapher)(new PackageModule);
+ $dot = ($this->objectGrapher)(new PackageModule());
$this->assertStringContainsString('_BEAR_Sunday_Provide_Transfer_ConditionalResponseInterface_ -> class_BEAR_Sunday_Provide_Transfer_ConditionalResponse [style=dashed, arrowtail=none, arrowhead=onormal]', $dot);
}
- public function testConcreteDependencyAnalysisDoesNotMutateModule() : void
+ public function testConcreteDependencyAnalysisDoesNotMutateModule(): void
{
- $module = new ConcreteModule;
+ $module = new ConcreteModule();
$container = $module->getContainer();
- $container->addPointcut(new Pointcut((new Matcher)->any(), (new Matcher)->any(), [DatabaseLogger::class]));
+ $container->addPointcut(new Pointcut((new Matcher())->any(), (new Matcher())->any(), [DatabaseLogger::class]));
$keys = array_keys($container->getContainer());
$pointcuts = $container->getPointcuts();
diff --git a/tests/bin/package.php b/tests/bin/package.php
index da340ed..89c0ac6 100644
--- a/tests/bin/package.php
+++ b/tests/bin/package.php
@@ -9,6 +9,6 @@
use BEAR\Package\PackageModule;
use Ray\ObjectGrapher\ObjectGrapher;
-$dot = (new ObjectGrapher)(new AppMetaModule(new Meta('Ray\ObjectGrapher'), new PackageModule));
+$dot = (new ObjectGrapher())(new AppMetaModule(new Meta('Ray\ObjectGrapher'), new PackageModule()));
$file = __DIR__ . '/package.dot';
file_put_contents($file, $dot);