| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 3 namespace WordPress\AiClientDependencies\Http\Discovery; 4 5 use WordPress\AiClientDependencies\Http\Discovery\Exception\ClassInstantiationFailedException; 6 use WordPress\AiClientDependencies\Http\Discovery\Exception\DiscoveryFailedException; 7 use WordPress\AiClientDependencies\Http\Discovery\Exception\NoCandidateFoundException; 8 use WordPress\AiClientDependencies\Http\Discovery\Exception\StrategyUnavailableException; 9 use WordPress\AiClientDependencies\Http\Discovery\Strategy\DiscoveryStrategy; 10 /** 11 * Registry that based find results on class existence. 12 * 13 * @author David de Boer <david@ddeboer.nl> 14 * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> 15 * @author Tobias Nyholm <tobias.nyholm@gmail.com> 16 */ 17 abstract class ClassDiscovery 18 { 19 /** 20 * A list of strategies to find classes. 21 * 22 * @var DiscoveryStrategy[] 23 */ 24 private static $strategies = [Strategy\GeneratedDiscoveryStrategy::class, Strategy\CommonClassesStrategy::class, Strategy\CommonPsr17ClassesStrategy::class, Strategy\PuliBetaStrategy::class]; 25 private static $deprecatedStrategies = [Strategy\PuliBetaStrategy::class => \true]; 26 /** 27 * Discovery cache to make the second time we use discovery faster. 28 * 29 * @var array 30 */ 31 private static $cache = []; 32 /** 33 * Finds a class. 34 * 35 * @param string $type 36 * 37 * @return string|\Closure 38 * 39 * @throws DiscoveryFailedException 40 */ 41 protected static function findOneByType($type) 42 { 43 // Look in the cache 44 if (null !== $class = self::getFromCache($type)) { 45 return $class; 46 } 47 static $skipStrategy; 48 $skipStrategy ?? $skipStrategy = self::safeClassExists(Strategy\GeneratedDiscoveryStrategy::class) ? \false : Strategy\GeneratedDiscoveryStrategy::class; 49 $exceptions = []; 50 foreach (self::$strategies as $strategy) { 51 if ($skipStrategy === $strategy) { 52 continue; 53 } 54 try { 55 $candidates = $strategy::getCandidates($type); 56 } catch (StrategyUnavailableException $e) { 57 if (!isset(self::$deprecatedStrategies[$strategy])) { 58 $exceptions[] = $e; 59 } 60 continue; 61 } 62 foreach ($candidates as $candidate) { 63 if (isset($candidate['condition'])) { 64 if (!self::evaluateCondition($candidate['condition'])) { 65 continue; 66 } 67 } 68 // save the result for later use 69 self::storeInCache($type, $candidate); 70 return $candidate['class']; 71 } 72 $exceptions[] = new NoCandidateFoundException($strategy, $candidates); 73 } 74 throw DiscoveryFailedException::create($exceptions); 75 } 76 /** 77 * Get a value from cache. 78 * 79 * @param string $type 80 * 81 * @return string|null 82 */ 83 private static function getFromCache($type) 84 { 85 if (!isset(self::$cache[$type])) { 86 return; 87 } 88 $candidate = self::$cache[$type]; 89 if (isset($candidate['condition'])) { 90 if (!self::evaluateCondition($candidate['condition'])) { 91 return; 92 } 93 } 94 return $candidate['class']; 95 } 96 /** 97 * Store a value in cache. 98 * 99 * @param string $type 100 * @param string $class 101 */ 102 private static function storeInCache($type, $class) 103 { 104 self::$cache[$type] = $class; 105 } 106 /** 107 * Set new strategies and clear the cache. 108 * 109 * @param string[] $strategies list of fully qualified class names that implement DiscoveryStrategy 110 */ 111 public static function setStrategies(array $strategies) 112 { 113 self::$strategies = $strategies; 114 self::clearCache(); 115 } 116 /** 117 * Returns the currently configured discovery strategies as fully qualified class names. 118 * 119 * @return string[] 120 */ 121 public static function getStrategies(): iterable 122 { 123 return self::$strategies; 124 } 125 /** 126 * Append a strategy at the end of the strategy queue. 127 * 128 * @param string $strategy Fully qualified class name of a DiscoveryStrategy 129 */ 130 public static function appendStrategy($strategy) 131 { 132 self::$strategies[] = $strategy; 133 self::clearCache(); 134 } 135 /** 136 * Prepend a strategy at the beginning of the strategy queue. 137 * 138 * @param string $strategy Fully qualified class name to a DiscoveryStrategy 139 */ 140 public static function prependStrategy($strategy) 141 { 142 array_unshift(self::$strategies, $strategy); 143 self::clearCache(); 144 } 145 public static function clearCache() 146 { 147 self::$cache = []; 148 } 149 /** 150 * Evaluates conditions to boolean. 151 * 152 * @return bool 153 */ 154 protected static function evaluateCondition($condition) 155 { 156 if (is_string($condition)) { 157 // Should be extended for functions, extensions??? 158 return self::safeClassExists($condition); 159 } 160 if (is_callable($condition)) { 161 return (bool) $condition(); 162 } 163 if (is_bool($condition)) { 164 return $condition; 165 } 166 if (is_array($condition)) { 167 foreach ($condition as $c) { 168 if (\false === static::evaluateCondition($c)) { 169 // Immediately stop execution if the condition is false 170 return \false; 171 } 172 } 173 return \true; 174 } 175 return \false; 176 } 177 /** 178 * Get an instance of the $class. 179 * 180 * @param string|\Closure $class a FQCN of a class or a closure that instantiate the class 181 * 182 * @return object 183 * 184 * @throws ClassInstantiationFailedException 185 */ 186 protected static function instantiateClass($class) 187 { 188 try { 189 if (is_string($class)) { 190 return new $class(); 191 } 192 if (is_callable($class)) { 193 return $class(); 194 } 195 } catch (\Exception $e) { 196 throw new ClassInstantiationFailedException('Unexpected exception when instantiating class.', 0, $e); 197 } 198 throw new ClassInstantiationFailedException('Could not instantiate class because parameter is neither a callable nor a string'); 199 } 200 /** 201 * We need a "safe" version of PHP's "class_exists" because Magento has a bug 202 * (or they call it a "feature"). Magento is throwing an exception if you do class_exists() 203 * on a class that ends with "Factory" and if that file does not exits. 204 * 205 * This function catches all potential exceptions and makes sure to always return a boolean. 206 * 207 * @param string $class 208 * 209 * @return bool 210 */ 211 public static function safeClassExists($class) 212 { 213 try { 214 return class_exists($class) || interface_exists($class); 215 } catch (\Exception $e) { 216 return \false; 217 } 218 } 219 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sat Jun 13 09:38:55 2026 | Cross-referenced by PHPXref |