PluginProbe
Packeta / trunk
Packeta vtrunk
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / deps / nette / di / src / DI / DependencyChecker.php

DependencyChecker.php in Packeta trunk, at deps/nette/di/src/DI/DependencyChecker.php

130 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * This file is part of the Nette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7 declare (strict_types=1);
8 namespace Packetery\Nette\DI;
9
10 use Packetery\Nette;
11 use Packetery\Nette\Utils\Reflection;
12 use Packetery\Nette\Utils\Type;
13 use ReflectionClass;
14 use ReflectionMethod;
15 /**
16 * Cache dependencies checker.
17 */
18 class DependencyChecker
19 {
20 use \Packetery\Nette\SmartObject;
21 public const Version = 1;
22 /** @deprecated use DependencyChecker::Version */
23 public const VERSION = self::Version;
24 /** @var array of ReflectionClass|\ReflectionFunctionAbstract|string */
25 private $dependencies = [];
26 /**
27 * Adds dependencies to the list.
28 * @return static
29 */
30 public function add(array $deps)
31 {
32 $this->dependencies = \array_merge($this->dependencies, $deps);
33 return $this;
34 }
35 /**
36 * Exports dependencies.
37 */
38 public function export() : array
39 {
40 $files = $phpFiles = $classes = $functions = [];
41 foreach ($this->dependencies as $dep) {
42 if (\is_string($dep)) {
43 $files[] = $dep;
44 } elseif ($dep instanceof ReflectionClass) {
45 if (empty($classes[$name = $dep->name])) {
46 $all = [$name] + \class_parents($name) + \class_implements($name);
47 foreach ($all as &$item) {
48 $all += \class_uses($item);
49 $phpFiles[] = (new ReflectionClass($item))->getFileName();
50 $classes[$item] = \true;
51 }
52 }
53 } elseif ($dep instanceof \ReflectionFunctionAbstract) {
54 $phpFiles[] = $dep->getFileName();
55 $functions[] = \rtrim(Reflection::toString($dep), '()');
56 } else {
57 throw new \Packetery\Nette\InvalidStateException(\sprintf('Unexpected dependency %s', \gettype($dep)));
58 }
59 }
60 $classes = \array_keys($classes);
61 $functions = \array_unique($functions, \SORT_REGULAR);
62 $hash = self::calculateHash($classes, $functions);
63 $files = @\array_map('filemtime', \array_combine($files, $files));
64 // @ - file may not exist
65 $phpFiles = @\array_map('filemtime', \array_combine($phpFiles, $phpFiles));
66 // @ - file may not exist
67 return [self::Version, $files, $phpFiles, $classes, $functions, $hash];
68 }
69 /**
70 * Are dependencies expired?
71 */
72 public static function isExpired(int $version, array $files, array &$phpFiles, array $classes, array $functions, string $hash) : bool
73 {
74 try {
75 $currentFiles = @\array_map('filemtime', \array_combine($tmp = \array_keys($files), $tmp));
76 // @ - files may not exist
77 $origPhpFiles = $phpFiles;
78 $phpFiles = @\array_map('filemtime', \array_combine($tmp = \array_keys($phpFiles), $tmp));
79 // @ - files may not exist
80 return $version !== self::Version || $files !== $currentFiles || $phpFiles !== $origPhpFiles && $hash !== self::calculateHash($classes, $functions);
81 } catch (\ReflectionException $e) {
82 return \true;
83 }
84 }
85 private static function calculateHash(array $classes, array $functions) : string
86 {
87 $hash = [];
88 foreach ($classes as $name) {
89 $class = new ReflectionClass($name);
90 $hash[] = [$name, Reflection::getUseStatements($class), $class->isAbstract(), \get_parent_class($name), \class_implements($name), \class_uses($name)];
91 foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
92 if ($prop->getDeclaringClass() == $class) {
93 // intentionally ==
94 $hash[] = [$name, $prop->name, $prop->getDocComment(), (string) Type::fromReflection($prop), \PHP_VERSION_ID >= 80000 ? \count($prop->getAttributes(Attributes\Inject::class)) : null];
95 }
96 }
97 foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
98 if ($method->getDeclaringClass() == $class) {
99 // intentionally ==
100 $hash[] = [$name, $method->name, $method->getDocComment(), self::hashParameters($method), (string) Type::fromReflection($method)];
101 }
102 }
103 }
104 $flip = \array_flip($classes);
105 foreach ($functions as $name) {
106 if (\strpos($name, '::')) {
107 $method = \PHP_VERSION_ID < 80300 ? new ReflectionMethod($name) : ReflectionMethod::createFromMethodName($name);
108 $class = $method->getDeclaringClass();
109 if (isset($flip[$class->name])) {
110 continue;
111 }
112 $uses = Reflection::getUseStatements($class);
113 } else {
114 $method = new \ReflectionFunction($name);
115 $uses = null;
116 }
117 $hash[] = [$name, $uses, $method->getDocComment(), self::hashParameters($method), (string) Type::fromReflection($method)];
118 }
119 return \md5(\serialize($hash));
120 }
121 private static function hashParameters(\ReflectionFunctionAbstract $method) : array
122 {
123 $res = [];
124 foreach ($method->getParameters() as $param) {
125 $res[] = [$param->name, (string) Type::fromReflection($param), $param->isVariadic(), $param->isDefaultValueAvailable() ? \is_object($tmp = Reflection::getParameterDefaultValue($param)) ? ['object' => \get_class($tmp)] : ['value' => $tmp] : null];
126 }
127 return $res;
128 }
129 }
130