/** * Save AOP proxy to the separate file anr returns the php source code for inclusion * * @param ReflectionClass $class Original class reflection * @param string|ClassProxy $child * * @return string */ private function saveProxyToCache($class, $child) { static $cacheDirSuffix = '/_proxies/'; $cacheDir = $this->cachePathManager->getCacheDir(); // Without cache we should rewrite original file if (!$cacheDir) { return $child; } $cacheDir = $cacheDir . $cacheDirSuffix; $fileName = str_replace($this->options['appDir'] . DIRECTORY_SEPARATOR, '', $class->getFileName()); $proxyFileName = $cacheDir . $fileName; $dirname = dirname($proxyFileName); if (!file_exists($dirname)) { mkdir($dirname, $this->options['cacheFileMode'], true); } $body = '<?php' . PHP_EOL; $namespace = $class->getNamespaceName(); if ($namespace) { $body .= "namespace {$namespace};" . PHP_EOL . PHP_EOL; } $refNamespace = new ReflectionFileNamespace($class->getFileName(), $namespace); foreach ($refNamespace->getNamespaceAliases() as $fqdn => $alias) { $body .= "use {$fqdn} as {$alias};" . PHP_EOL; } $body .= $child; file_put_contents($proxyFileName, $body, LOCK_EX); // For cache files we don't want executable bits by default chmod($proxyFileName, $this->options['cacheFileMode'] & ~0111); return 'include_once AOP_CACHE_DIR . ' . var_export($cacheDirSuffix . $fileName, true) . ';' . PHP_EOL; }
/** * This method may transform the supplied source and return a new replacement for it * * @param StreamMetaData $metadata Metadata for source * @return void|bool Return false if transformation should be stopped */ public function transform(StreamMetaData $metadata) { // Do not create a cache if (!$this->cachePath) { return $this->processTransformers($metadata); } $originalUri = $metadata->uri; $wasProcessed = false; $cacheUri = $this->cacheManager->getCachePathForResource($originalUri); $lastModified = filemtime($originalUri); $cacheState = $this->cacheManager->queryCacheState($originalUri); $cacheModified = $cacheState ? $cacheState['filemtime'] : 0; if ($cacheModified < $lastModified || !$this->container->isFresh($cacheModified)) { $wasProcessed = $this->processTransformers($metadata); if ($wasProcessed) { $parentCacheDir = dirname($cacheUri); if (!is_dir($parentCacheDir)) { mkdir($parentCacheDir, 0770, true); } file_put_contents($cacheUri, $metadata->source); if (!$cacheState && $this->cacheFileMode) { chmod($cacheUri, $this->cacheFileMode); } } $this->cacheManager->setCacheState($originalUri, array('filemtime' => isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time(), 'cacheUri' => $wasProcessed ? $cacheUri : null)); return $wasProcessed; } if ($cacheState) { $wasProcessed = isset($cacheState['cacheUri']); } if ($wasProcessed) { $metadata->source = file_get_contents($cacheUri); } return $wasProcessed; }
/** * Save AOP proxy to the separate file anr returns the php source code for inclusion * * @param ParsedClass $class Original class reflection * @param string|ClassProxy $child * * @return string */ private function saveProxyToCache($class, $child) { static $cacheDirSuffix = '/_proxies/'; $cacheDir = $this->cachePathManager->getCacheDir(); // Without cache we should rewrite original file if (!$cacheDir) { return $child; } $cacheDir = $cacheDir . $cacheDirSuffix; $fileName = str_replace($this->options['appDir'] . DIRECTORY_SEPARATOR, '', $class->getFileName()); $proxyFileName = $cacheDir . $fileName; $dirname = dirname($proxyFileName); if (!file_exists($dirname)) { mkdir($dirname, 0770, true); } $body = '<?php' . PHP_EOL; $namespace = $class->getNamespaceName(); if ($namespace) { $body .= "namespace {$namespace};" . PHP_EOL . PHP_EOL; } foreach ($class->getNamespaceAliases() as $alias => $fqdn) { $body .= "use {$fqdn} as {$alias};" . PHP_EOL; } $body .= $child; file_put_contents($proxyFileName, $body); return 'include_once AOP_CACHE_DIR . ' . var_export($cacheDirSuffix . $fileName, true) . ';' . PHP_EOL; }
/** * This method may transform the supplied source and return a new replacement for it * * @param StreamMetaData $metadata Metadata for source * @return bool Return false if transformation should be stopped */ public function transform(StreamMetaData $metadata) { // Do not create a cache if (!$this->cacheManager->getCacheDir()) { return $this->processTransformers($metadata); } $originalUri = $metadata->uri; $wasProcessed = false; $cacheUri = $this->cacheManager->getCachePathForResource($originalUri); // Guard to disable overwriting of original files if ($cacheUri === $originalUri) { return false; } $lastModified = filemtime($originalUri); $cacheState = $this->cacheManager->queryCacheState($originalUri); $cacheModified = $cacheState ? $cacheState['filemtime'] : 0; if ($cacheModified < $lastModified || isset($cacheState['cacheUri']) && $cacheState['cacheUri'] !== $cacheUri || !$this->container->isFresh($cacheModified)) { $wasProcessed = $this->processTransformers($metadata); if ($wasProcessed) { $parentCacheDir = dirname($cacheUri); if (!is_dir($parentCacheDir)) { mkdir($parentCacheDir, $this->cacheFileMode, true); } file_put_contents($cacheUri, $metadata->source, LOCK_EX); // For cache files we don't want executable bits by default chmod($cacheUri, $this->cacheFileMode & ~0111); } $this->cacheManager->setCacheState($originalUri, array('filemtime' => isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time(), 'cacheUri' => $wasProcessed ? $cacheUri : null)); return $wasProcessed; } if ($cacheState) { $wasProcessed = isset($cacheState['cacheUri']); } if ($wasProcessed) { $metadata->source = file_get_contents($cacheUri); } return $wasProcessed; }
/** * Warms up the cache. * * @param string $cacheDir The cache directory */ public function warmUp($cacheDir) { $options = $this->aspectKernel->getOptions(); $oldCacheDir = $this->cachePathManager->getCacheDir(); $this->cachePathManager->setCacheDir($cacheDir . '/aspect'); $enumerator = new Enumerator($options['appDir'], $options['includePaths'], $options['excludePaths']); $iterator = $enumerator->enumerate(); set_error_handler(function ($errno, $errstr, $errfile, $errline) { throw new \ErrorException($errstr, $errno, 0, $errfile, $errline); }); $errors = array(); foreach ($iterator as $file) { $realPath = $file->getRealPath(); try { // This will trigger creation of cache file_get_contents(FilterInjectorTransformer::PHP_FILTER_READ . SourceTransformingLoader::FILTER_IDENTIFIER . "/resource=" . $realPath); } catch (\Exception $e) { $errors[$realPath] = $e; } } restore_error_handler(); $this->cachePathManager->flushCacheState(); $this->cachePathManager->setCacheDir($oldCacheDir); }
/** * Replace source path with correct one * * This operation can check for cache, can rewrite paths, add additional filters and much more * * @param string $originalResource Initial resource to include * @param string $originalDir Path to the directory from where include was called for resolving relative resources * * @return string Transformed path to the resource */ public static function rewrite($originalResource, $originalDir = '') { static $appDir, $cacheDir, $debug; if (!$appDir) { extract(self::$options, EXTR_IF_EXISTS); } $resource = (string) $originalResource; if ($resource['0'] !== '/') { $shouldCheckExistence = true; $resource = PathResolver::realpath($resource, $shouldCheckExistence) ?: PathResolver::realpath("{$originalDir}/{$resource}", $shouldCheckExistence) ?: $originalResource; } $cachedResource = self::$cachePathManager->getCachePathForResource($resource); // If the cache is disabled or no cache yet, then use on-fly method if (!$cacheDir || $debug || !file_exists($cachedResource)) { return self::PHP_FILTER_READ . self::$filterName . "/resource=" . $resource; } return $cachedResource; }