diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index f7536b1ee2..8340bdf034 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -44,11 +44,17 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa function ($key, $innerItem) use ($defaultLifetime, $poolHash) { $item = new CacheItem(); $item->key = $key; + + if (null === $innerItem) { + return $item; + } + $item->value = $v = $innerItem->get(); $item->isHit = $innerItem->isHit(); - $item->defaultLifetime = $defaultLifetime; $item->innerItem = $innerItem; + $item->defaultLifetime = $defaultLifetime; $item->poolHash = $poolHash; + // Detect wrapped values that encode for their expiry and creation duration // For compactness, these values are packed in the key of an array using // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F @@ -202,7 +208,18 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa if (null === $item["\0*\0expiry"] && 0 < $item["\0*\0defaultLifetime"]) { $item["\0*\0expiry"] = microtime(true) + $item["\0*\0defaultLifetime"]; } - $innerItem = $item["\0*\0poolHash"] === $this->poolHash ? $item["\0*\0innerItem"] : $this->pool->getItem($this->namespace.$item["\0*\0key"]); + + if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) { + $innerItem = $item["\0*\0innerItem"]; + } elseif ($this->pool instanceof AdapterInterface) { + // this is an optimization specific for AdapterInterface implementations + // so we can save a round-trip to the backend by just creating a new item + $f = $this->createCacheItem; + $innerItem = $f($this->namespace.$item["\0*\0key"], null); + } else { + $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]); + } + ($this->setInnerItem)($innerItem, $item); return $this->pool->$method($innerItem); diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index e54044b60a..5b08418fcc 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -51,7 +51,6 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac $item->value = $value; $item->defaultLifetime = $protoItem->defaultLifetime; $item->expiry = $protoItem->expiry; - $item->innerItem = $protoItem->innerItem; $item->poolHash = $protoItem->poolHash; return $item; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php new file mode 100644 index 0000000000..b11c1f2870 --- /dev/null +++ b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php @@ -0,0 +1,38 @@ +getItem('foo'); + $item->tag(['tag1', 'tag2']); + $item->set('bar'); + $cache->save($item); + + $this->assertSame('bar', $cache->getItem('foo')->get()); + } + + public function dataProvider() + { + return [ + [new ArrayAdapter()], + // also testing with a non-AdapterInterface implementation + // because the ProxyAdapter behaves slightly different for those + [new ExternalAdapter()], + ]; + } +} diff --git a/src/Symfony/Component/Form/Extension/Core/CoreExtension.php b/src/Symfony/Component/Form/Extension/Core/CoreExtension.php index e578058e5c..b658b9979f 100644 --- a/src/Symfony/Component/Form/Extension/Core/CoreExtension.php +++ b/src/Symfony/Component/Form/Extension/Core/CoreExtension.php @@ -76,7 +76,7 @@ class CoreExtension extends AbstractExtension new Type\TimeType(), new Type\TimezoneType(), new Type\UrlType(), - new Type\FileType(), + new Type\FileType($this->translator), new Type\ButtonType(), new Type\SubmitType(), new Type\ResetType(), diff --git a/src/Symfony/Component/Form/FormFactoryBuilder.php b/src/Symfony/Component/Form/FormFactoryBuilder.php index fc8b12ffad..d73b438b4b 100644 --- a/src/Symfony/Component/Form/FormFactoryBuilder.php +++ b/src/Symfony/Component/Form/FormFactoryBuilder.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Extension\Core\CoreExtension; + /** * The default implementation of FormFactoryBuilderInterface. * @@ -18,6 +20,8 @@ namespace Symfony\Component\Form; */ class FormFactoryBuilder implements FormFactoryBuilderInterface { + private $forceCoreExtension; + /** * @var ResolvedFormTypeFactoryInterface */ @@ -43,6 +47,14 @@ class FormFactoryBuilder implements FormFactoryBuilderInterface */ private $typeGuessers = []; + /** + * @param bool $forceCoreExtension + */ + public function __construct($forceCoreExtension = false) + { + $this->forceCoreExtension = $forceCoreExtension; + } + /** * {@inheritdoc} */ @@ -150,6 +162,21 @@ class FormFactoryBuilder implements FormFactoryBuilderInterface { $extensions = $this->extensions; + if ($this->forceCoreExtension) { + $hasCoreExtension = false; + + foreach ($extensions as $extension) { + if ($extension instanceof CoreExtension) { + $hasCoreExtension = true; + break; + } + } + + if (!$hasCoreExtension) { + array_unshift($extensions, new CoreExtension()); + } + } + if (\count($this->types) > 0 || \count($this->typeExtensions) > 0 || \count($this->typeGuessers) > 0) { if (\count($this->typeGuessers) > 1) { $typeGuesser = new FormTypeGuesserChain($this->typeGuessers); diff --git a/src/Symfony/Component/Form/Forms.php b/src/Symfony/Component/Form/Forms.php index 7ea5ca8235..d7bb48cfb7 100644 --- a/src/Symfony/Component/Form/Forms.php +++ b/src/Symfony/Component/Form/Forms.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Extension\Core\CoreExtension; - /** * Entry point of the Form component. * @@ -81,10 +79,7 @@ final class Forms */ public static function createFormFactoryBuilder(): FormFactoryBuilderInterface { - $builder = new FormFactoryBuilder(); - $builder->addExtension(new CoreExtension()); - - return $builder; + return new FormFactoryBuilder(true); } /** diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php index da018b4a19..3c0a38d1b0 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php @@ -11,16 +11,26 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Extension\Core\CoreExtension; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\NativeRequestHandler; use Symfony\Component\Form\RequestHandlerInterface; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\Translation\TranslatorInterface; class FileTypeTest extends BaseTypeTest { const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\FileType'; + protected function getExtensions() + { + $translator = $this->createMock(TranslatorInterface::class); + $translator->expects($this->any())->method('trans')->willReturnArgument(0); + + return array_merge(parent::getExtensions(), [new CoreExtension(null, null, $translator)]); + } + // https://github.com/symfony/symfony/pull/5028 public function testSetData() {