/** * Flushes the cache either by entry or flushes * the entire cache if no entry is provided. * * @param string|null $name * @return bool|void */ public function flush($name = null) { if ($name !== null) { return $this->flowCache->remove($name); } else { return $this->flowCache->flush(); } }
/** * Shutdown the Evaluator */ public function shutdownObject() { if (count($this->newExpressions) > 0) { $changesToPersist = false; $codeToBeCached = $this->expressionCache->get('cachedExpressionClosures'); /** * At this point a race condition could happen, that we try to prevent with an additional check. * So we compare the evaluated expressions during this request with the methods the cache has at * this point and only add methods that are not present. Only if we added anything we write the cache. */ foreach ($this->newExpressions as $functionName => $newExpression) { if (strpos($codeToBeCached, $functionName) === false) { $codeToBeCached .= 'if (!function_exists(\'' . $functionName . '\')) { ' . $newExpression . ' }' . chr(10); $changesToPersist = true; } } if ($changesToPersist) { $this->expressionCache->set('cachedExpressionClosures', $codeToBeCached); } } }
/** * Reads the specified class file, appends ORIGINAL_CLASSNAME_SUFFIX to its * class name and stores the result in the proxy classes cache. * * @param string $className Short class name of the class to copy * @param string $pathAndFilename Full path and filename of the original class file * @param string $proxyClassCode The code that makes up the proxy class * @return void * * @throws Exception If the original class filename doesn't match the actual class name inside the file. */ protected function cacheOriginalClassFileAndProxyCode($className, $pathAndFilename, $proxyClassCode) { $classCode = file_get_contents($pathAndFilename); $classCode = $this->stripOpeningPhpTag($classCode); $classNameSuffix = self::ORIGINAL_CLASSNAME_SUFFIX; $classCode = preg_replace_callback('/^([a-z\\s]*?)(final\\s+)?(interface|class)\\s+([a-zA-Z0-9_]+)/m', function ($matches) use($pathAndFilename, $classNameSuffix, $proxyClassCode) { $classNameAccordingToFileName = basename($pathAndFilename, '.php'); if ($matches[4] !== $classNameAccordingToFileName) { throw new Exception('The name of the class "' . $matches[4] . '" is not the same as the filename which is "' . basename($pathAndFilename) . '". Path: ' . $pathAndFilename, 1398356897); } return $matches[1] . $matches[3] . ' ' . $matches[4] . $classNameSuffix; }, $classCode); $classCode = preg_replace('/\\?>[\\n\\s\\r]*$/', '', $classCode); $proxyClassCode .= "\n" . '# PathAndFilename: ' . $pathAndFilename; $this->classesCache->set(str_replace('\\', '_', $className), $classCode . $proxyClassCode); }
/** * Loads php files containing classes or interfaces found in the classes directory of * a package and specifically registered classes. * * @param string $className Name of the class/interface to load * @return boolean */ public function loadClass($className) { if ($className[0] === '\\') { $className = ltrim($className, '\\'); } $namespaceParts = explode('\\', $className); // Workaround for Doctrine's annotation parser which does a class_exists() for annotations like "@param" and so on: if (isset($this->ignoredClassNames[$className]) || isset($this->ignoredClassNames[end($namespaceParts)]) || isset($this->nonExistentClasses[$className])) { return false; } // Loads any known proxied class: if ($this->classesCache !== null && ($this->availableProxyClasses === null || isset($this->availableProxyClasses[implode('_', $namespaceParts)])) && $this->classesCache->requireOnce(implode('_', $namespaceParts)) !== false) { return true; } $classNamePart = array_pop($namespaceParts); $classNameParts = explode('_', $classNamePart); $namespaceParts = array_merge($namespaceParts, $classNameParts); $namespacePartCount = count($namespaceParts); $currentPackageArray = $this->packageNamespaces; $packagenamespacePartCount = 0; // This will contain all possible class mappings for the given class name. We start with the fallback paths and prepend mappings with growing specificy. $collectedPossibleNamespaceMappings = [['p' => $this->fallbackClassPaths, 'c' => 0]]; if ($namespacePartCount > 1) { while ($packagenamespacePartCount + 1 < $namespacePartCount) { $possiblePackageNamespacePart = $namespaceParts[$packagenamespacePartCount]; if (!isset($currentPackageArray[$possiblePackageNamespacePart])) { break; } $packagenamespacePartCount++; $currentPackageArray = $currentPackageArray[$possiblePackageNamespacePart]; if (isset($currentPackageArray['_pathData'])) { array_unshift($collectedPossibleNamespaceMappings, ['p' => $currentPackageArray['_pathData'], 'c' => $packagenamespacePartCount]); } } } foreach ($collectedPossibleNamespaceMappings as $nameSpaceMapping) { if ($this->loadClassFromPossiblePaths($nameSpaceMapping['p'], $namespaceParts, $nameSpaceMapping['c'])) { return true; } } $this->nonExistentClasses[$className] = true; return false; }
/** * Flush all runtime expressions * * @return void */ public function flush() { $this->runtimeExpressionsCache->flush(); }