* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; use Doctrine\Common\Annotations\AnnotationException; use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\PhpArrayAdapter; use Symfony\Component\Cache\Adapter\ProxyAdapter; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; /** * Warms up XML and YAML serializer metadata. * * @author Titouan Galopin */ class SerializerCacheWarmer implements CacheWarmerInterface { private $loaders; private $phpArrayFile; private $fallbackPool; /** * @param LoaderInterface[] $loaders the serializer metadata loaders * @param string $phpArrayFile the PHP file where metadata are cached * @param CacheItemPoolInterface $fallbackPool the pool where runtime-discovered metadata are cached */ public function __construct(array $loaders, $phpArrayFile, CacheItemPoolInterface $fallbackPool) { $this->loaders = $loaders; $this->phpArrayFile = $phpArrayFile; if (!$fallbackPool instanceof AdapterInterface) { $fallbackPool = new ProxyAdapter($fallbackPool); } $this->fallbackPool = $fallbackPool; } /** * {@inheritdoc} */ public function warmUp($cacheDir) { if (!class_exists(CacheClassMetadataFactory::class) || !method_exists(XmlFileLoader::class, 'getMappedClasses') || !method_exists(YamlFileLoader::class, 'getMappedClasses')) { return; } $adapter = new PhpArrayAdapter($this->phpArrayFile, $this->fallbackPool); $arrayPool = new ArrayAdapter(0, false); $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayPool); spl_autoload_register(array($adapter, 'throwOnRequiredClass')); try { foreach ($this->extractSupportedLoaders($this->loaders) as $loader) { foreach ($loader->getMappedClasses() as $mappedClass) { try { $metadataFactory->getMetadataFor($mappedClass); } catch (\ReflectionException $e) { // ignore failing reflection } catch (AnnotationException $e) { // ignore failing annotations } } } } finally { spl_autoload_unregister(array($adapter, 'throwOnRequiredClass')); } $values = $arrayPool->getValues(); $adapter->warmUp($values); foreach ($values as $k => $v) { $item = $this->fallbackPool->getItem($k); $this->fallbackPool->saveDeferred($item->set($v)); } $this->fallbackPool->commit(); } /** * {@inheritdoc} */ public function isOptional() { return true; } /** * @param LoaderInterface[] $loaders * * @return XmlFileLoader[]|YamlFileLoader[] */ private function extractSupportedLoaders(array $loaders) { $supportedLoaders = array(); foreach ($loaders as $loader) { if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { $supportedLoaders[] = $loader; } elseif ($loader instanceof LoaderChain) { $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getDelegatedLoaders())); } } return $supportedLoaders; } }