Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Compiler
  • CompilerExtension
  • Container
  • ContainerBuilder
  • ContainerLoader
  • DependencyChecker
  • PhpGenerator
  • ServiceDefinition
  • Statement

Exceptions

  • MissingServiceException
  • ServiceCreationException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  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: 
  8: namespace Nette\DI;
  9: 
 10: use Nette;
 11: use ReflectionClass;
 12: use ReflectionMethod;
 13: use Nette\Utils\Reflection;
 14: 
 15: 
 16: /**
 17:  * Cache dependencies checker.
 18:  */
 19: class DependencyChecker
 20: {
 21:     const VERSION = 1;
 22: 
 23:     use Nette\SmartObject;
 24: 
 25:     /** @var array of ReflectionClass|\ReflectionFunctionAbstract|string */
 26:     private $dependencies = [];
 27: 
 28: 
 29:     /**
 30:      * Adds dependencies to the list.
 31:      * @return static
 32:      */
 33:     public function add(array $deps)
 34:     {
 35:         $this->dependencies = array_merge($this->dependencies, $deps);
 36:         return $this;
 37:     }
 38: 
 39: 
 40:     /**
 41:      * Exports dependencies.
 42:      * @return array
 43:      */
 44:     public function export()
 45:     {
 46:         $files = $phpFiles = $classes = $functions = [];
 47:         foreach ($this->dependencies as $dep) {
 48:             if (is_string($dep)) {
 49:                 $files[] = $dep;
 50: 
 51:             } elseif ($dep instanceof ReflectionClass) {
 52:                 if (empty($classes[$name = $dep->getName()])) {
 53:                     $all = [$name] + class_parents($name) + class_implements($name);
 54:                     foreach ($all as & $item) {
 55:                         $all += class_uses($item);
 56:                         $phpFiles[] = (new ReflectionClass($item))->getFileName();
 57:                         $classes[$item] = TRUE;
 58:                     }
 59:                 }
 60: 
 61:             } elseif ($dep instanceof \ReflectionFunctionAbstract) {
 62:                 $phpFiles[] = $dep->getFileName();
 63:                 $functions[] = Reflection::toString($dep);
 64: 
 65:             } else {
 66:                 throw new Nette\InvalidStateException('Unexpected dependency ' . gettype($dep));
 67:             }
 68:         }
 69: 
 70:         $classes = array_keys($classes);
 71:         $functions = array_unique($functions, SORT_REGULAR);
 72:         $hash = self::calculateHash($classes, $functions);
 73:         $files = @array_map('filemtime', array_combine($files, $files)); // @ - file may not exist
 74:         $phpFiles = @array_map('filemtime', array_combine($phpFiles, $phpFiles)); // @ - file may not exist
 75:         return [self::VERSION, $files, $phpFiles, $classes, $functions, $hash];
 76:     }
 77: 
 78: 
 79:     /**
 80:      * Are dependencies expired?
 81:      * @return bool
 82:      */
 83:     public static function isExpired($version, $files, $phpFiles, $classes, $functions, $hash)
 84:     {
 85:         $current = @array_map('filemtime', array_combine($tmp = array_keys($files), $tmp)); // @ - files may not exist
 86:         $currentClass = @array_map('filemtime', array_combine($tmp = array_keys($phpFiles), $tmp)); // @ - files may not exist
 87:         return $version !== self::VERSION
 88:             || $files !== $current
 89:             || ($phpFiles !== $currentClass && $hash !== self::calculateHash($classes, $functions));
 90:     }
 91: 
 92: 
 93:     private static function calculateHash($classes, $functions)
 94:     {
 95:         $hash = [];
 96:         foreach ($classes as $name) {
 97:             try {
 98:                 $class = new ReflectionClass($name);
 99:             } catch (\ReflectionException $e) {
100:                 return;
101:             }
102:             $hash[] = [$name, Reflection::getUseStatements($class), $class->isAbstract()];
103:             foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
104:                 if ($prop->getDeclaringClass() == $class) { // intentionally ==
105:                     $hash[] = [$name, $prop->getName(), $prop->getDocComment()];
106:                 }
107:             }
108:             foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
109:                 if ($method->getDeclaringClass() == $class) { // intentionally ==
110:                     $hash[] = [
111:                         $name,
112:                         $method->getName(),
113:                         $method->getDocComment(),
114:                         self::hashParameters($method),
115:                         PHP_VERSION_ID >= 70000 && $method->hasReturnType()
116:                             ? [(string) $method->getReturnType(), $method->getReturnType()->allowsNull()]
117:                             : NULL
118:                     ];
119:                 }
120:             }
121:         }
122: 
123:         $flip = array_flip($classes);
124:         foreach ($functions as $name) {
125:             try {
126:                 $method = strpos($name, '::') ? new ReflectionMethod($name) : new \ReflectionFunction($name);
127:             } catch (\ReflectionException $e) {
128:                 return;
129:             }
130:             $class = $method instanceof ReflectionMethod ? $method->getDeclaringClass() : NULL;
131:             if ($class && isset($flip[$class->getName()])) {
132:                 continue;
133:             }
134:             $hash[] = [
135:                 $name,
136:                 $class ? Reflection::getUseStatements($method->getDeclaringClass()) : NULL,
137:                 $method->getDocComment(),
138:                 self::hashParameters($method),
139:                 PHP_VERSION_ID >= 70000 && $method->hasReturnType()
140:                     ? [(string) $method->getReturnType(), $method->getReturnType()->allowsNull()]
141:                     : NULL
142:             ];
143:         }
144: 
145:         return md5(serialize($hash));
146:     }
147: 
148: 
149:     private static function hashParameters(\ReflectionFunctionAbstract $method)
150:     {
151:         $res = [];
152:         if (PHP_VERSION_ID < 70000 && $method->getNumberOfParameters() && $method->getFileName()) {
153:             $res[] = file($method->getFileName())[$method->getStartLine() - 1];
154:         }
155:         foreach ($method->getParameters() as $param) {
156:             $res[] = [
157:                 $param->getName(),
158:                 PHP_VERSION_ID >= 70000 ? [Reflection::getParameterType($param), $param->allowsNull()] : NULL,
159:                 $param->isVariadic(),
160:                 $param->isDefaultValueAvailable()
161:                     ? [Reflection::getParameterDefaultValue($param)]
162:                     : NULL
163:             ];
164:         }
165:         return $res;
166:     }
167: 
168: }
169: 
Nette 2.4-20170119 API API documentation generated by ApiGen 2.8.0