From fd43e81fd76203dadd573ede3cc35902dd713411 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Mon, 19 Feb 2018 12:59:29 +0200 Subject: [PATCH] [FrameworkBundle] Add command to delete an item from a cache pool --- .../Command/CachePoolDeleteCommand.php | 81 ++++++++++++ .../Resources/config/console.xml | 5 + .../Command/CachePoolDeleteCommandTest.php | 122 ++++++++++++++++++ .../CacheClearer/Psr6CacheClearer.php | 9 ++ 4 files changed, 217 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php new file mode 100644 index 0000000000..1849a5d098 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; + +/** + * Delete an item from a cache pool. + * + * @author Pierre du Plessis + */ +final class CachePoolDeleteCommand extends Command +{ + protected static $defaultName = 'cache:pool:delete'; + + private $poolClearer; + + public function __construct(Psr6CacheClearer $poolClearer) + { + parent::__construct(); + + $this->poolClearer = $poolClearer; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition(array( + new InputArgument('pool', InputArgument::REQUIRED, 'The cache pool from which to delete an item'), + new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'), + )) + ->setDescription('Deletes an item from a cache pool') + ->setHelp(<<<'EOF' +The %command.name% deletes an item from a given cache pool. + + %command.full_name% +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $pool = $input->getArgument('pool'); + $key = $input->getArgument('key'); + $cachePool = $this->poolClearer->getPool($pool); + + if (!$cachePool->hasItem($key)) { + $io->note(sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool)); + + return; + } + + if (!$cachePool->deleteItem($key)) { + throw new \Exception(sprintf('Cache item "%s" could not be deleted.', $key)); + } + + $io->success(sprintf('Cache item "%s" was successfully deleted.', $key)); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 34f47a0599..5611fa3ccd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -38,6 +38,11 @@ + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php new file mode 100644 index 0000000000..7ccfa84804 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand; +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Bundle\FrameworkBundle\Tests\TestCase; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; +use Symfony\Component\HttpKernel\KernelInterface; + +class CachePoolDeleteCommandTest extends TestCase +{ + private $cachePool; + + protected function setUp() + { + $this->cachePool = $this->getMockBuilder(CacheItemPoolInterface::class) + ->getMock(); + } + + public function testCommandWithValidKey() + { + $this->cachePool->expects($this->once()) + ->method('hasItem') + ->with('bar') + ->willReturn(true); + + $this->cachePool->expects($this->once()) + ->method('deleteItem') + ->with('bar') + ->willReturn(true); + + $tester = $this->getCommandTester($this->getKernel()); + $tester->execute(array('pool' => 'foo', 'key' => 'bar')); + + $this->assertContains('[OK] Cache item "bar" was successfully deleted.', $tester->getDisplay()); + } + + public function testCommandWithInValidKey() + { + $this->cachePool->expects($this->once()) + ->method('hasItem') + ->with('bar') + ->willReturn(false); + + $this->cachePool->expects($this->never()) + ->method('deleteItem') + ->with('bar'); + + $tester = $this->getCommandTester($this->getKernel()); + $tester->execute(array('pool' => 'foo', 'key' => 'bar')); + + $this->assertContains('[NOTE] Cache item "bar" does not exist in cache pool "foo".', $tester->getDisplay()); + } + + public function testCommandDeleteFailed() + { + $this->cachePool->expects($this->once()) + ->method('hasItem') + ->with('bar') + ->willReturn(true); + + $this->cachePool->expects($this->once()) + ->method('deleteItem') + ->with('bar') + ->willReturn(false); + + if (method_exists($this, 'expectExceptionMessage')) { + $this->expectExceptionMessage('Cache item "bar" could not be deleted.'); + } else { + $this->setExpectedException('Exception', 'Cache item "bar" could not be deleted.'); + } + + $tester = $this->getCommandTester($this->getKernel()); + $tester->execute(array('pool' => 'foo', 'key' => 'bar')); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|KernelInterface + */ + private function getKernel() + { + $container = $this + ->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface') + ->getMock(); + + $kernel = $this + ->getMockBuilder(KernelInterface::class) + ->getMock(); + + $kernel + ->expects($this->any()) + ->method('getContainer') + ->willReturn($container); + + $kernel + ->expects($this->once()) + ->method('getBundles') + ->willReturn(array()); + + return $kernel; + } + + private function getCommandTester(KernelInterface $kernel): CommandTester + { + $application = new Application($kernel); + $application->add(new CachePoolDeleteCommand(new Psr6CacheClearer(array('foo' => $this->cachePool)))); + + return new CommandTester($application->find('cache:pool:delete')); + } +} diff --git a/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php b/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php index f54ca96e99..d7db027072 100644 --- a/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php +++ b/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php @@ -28,6 +28,15 @@ class Psr6CacheClearer implements CacheClearerInterface return isset($this->pools[$name]); } + public function getPool($name) + { + if (!$this->hasPool($name)) { + throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); + } + + return $this->pools[$name]; + } + public function clearPool($name) { if (!isset($this->pools[$name])) {