Merge branch '3.1'
* 3.1: [TwigBundle] Removed redundant return statement. enable property info [Cache] Fix default lifetime being ignored [DependencyInjection] Fixed deprecated default message template with XML Reference the actual location of the documentation [TwigBridge] Removed extra arguments in 2 places. [Cache] Fix incorrect timestamps generated by FilesystemAdapter [Process] Fix write access check for pipes on Windows [HttpKernel] Use flock() for HttpCache's lock files Conflicts: src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php
This commit is contained in:
commit
b6bbe43b4b
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Bridge\Twig\Extension;
|
||||
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
|
||||
|
||||
/**
|
||||
@ -48,7 +47,7 @@ class LogoutUrlExtension extends \Twig_Extension
|
||||
*/
|
||||
public function getLogoutPath($key = null)
|
||||
{
|
||||
return $this->generator->getLogoutPath($key, UrlGeneratorInterface::ABSOLUTE_PATH);
|
||||
return $this->generator->getLogoutPath($key);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +59,7 @@ class LogoutUrlExtension extends \Twig_Extension
|
||||
*/
|
||||
public function getLogoutUrl($key = null)
|
||||
{
|
||||
return $this->generator->getLogoutUrl($key, UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
return $this->generator->getLogoutUrl($key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,7 @@
|
||||
<argument type="service" id="serializer.mapping.class_metadata_factory" />
|
||||
<argument>null</argument> <!-- name converter -->
|
||||
<argument type="service" id="serializer.property_accessor" />
|
||||
<argument type="service" id="property_info" on-invalid="ignore" />
|
||||
|
||||
<!-- Run after all custom serializers -->
|
||||
<tag name="serializer.normalizer" priority="-1000" />
|
||||
|
@ -68,6 +68,7 @@ $container->loadFromExtension('framework', array(
|
||||
'enable_annotations' => true,
|
||||
'name_converter' => 'serializer.name_converter.camel_case_to_snake_case',
|
||||
),
|
||||
'property_info' => true,
|
||||
'ide' => 'file%%link%%format',
|
||||
'request' => array(
|
||||
'formats' => array(
|
||||
|
@ -41,5 +41,6 @@
|
||||
<framework:validation enabled="true" cache="validator.mapping.cache.doctrine.apc" />
|
||||
<framework:annotations cache="file" debug="true" file-cache-dir="%kernel.cache_dir%/annotations" />
|
||||
<framework:serializer enabled="true" enable-annotations="true" name-converter="serializer.name_converter.camel_case_to_snake_case" />
|
||||
<framework:property-info />
|
||||
</framework:config>
|
||||
</container>
|
||||
|
@ -53,6 +53,7 @@ framework:
|
||||
enabled: true
|
||||
enable_annotations: true
|
||||
name_converter: serializer.name_converter.camel_case_to_snake_case
|
||||
property_info: ~
|
||||
ide: file%%link%%format
|
||||
request:
|
||||
formats:
|
||||
|
@ -469,6 +469,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertEquals('Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', $argument[0]->getClass());
|
||||
$this->assertNull($container->getDefinition('serializer.mapping.class_metadata_factory')->getArgument(1));
|
||||
$this->assertEquals(new Reference('serializer.name_converter.camel_case_to_snake_case'), $container->getDefinition('serializer.normalizer.object')->getArgument(1));
|
||||
$this->assertEquals(new Reference('property_info', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $container->getDefinition('serializer.normalizer.object')->getArgument(3));
|
||||
}
|
||||
|
||||
public function testRegisterSerializerExtractor()
|
||||
|
@ -48,7 +48,7 @@ class FilesystemLoaderTest extends TestCase
|
||||
;
|
||||
$loader = new FilesystemLoader($locator, $parser);
|
||||
|
||||
return $this->assertTrue($loader->exists($template));
|
||||
$this->assertTrue($loader->exists($template));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,7 +56,7 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface
|
||||
|
||||
foreach ($deferred as $key => $item) {
|
||||
if (null === $item->expiry) {
|
||||
$byLifetime[0][$namespace.$key] = $item->value;
|
||||
$byLifetime[0 < $item->defaultLifetime ? $item->defaultLifetime : 0][$namespace.$key] = $item->value;
|
||||
} elseif ($item->expiry > $now) {
|
||||
$byLifetime[$item->expiry - $now][$namespace.$key] = $item->value;
|
||||
} else {
|
||||
|
@ -151,6 +151,9 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) {
|
||||
$expiry = time() + $item["\0*\0defaultLifetime"];
|
||||
}
|
||||
|
||||
$this->values[$key] = $value;
|
||||
$this->expiries[$key] = null !== $expiry ? $expiry : PHP_INT_MAX;
|
||||
|
@ -71,7 +71,7 @@ class FilesystemAdapter extends AbstractAdapter
|
||||
protected function doSave(array $values, $lifetime)
|
||||
{
|
||||
$ok = true;
|
||||
$expiresAt = $lifetime ? time() + $lifetime : PHP_INT_MAX;
|
||||
$expiresAt = time() + ($lifetime ?: 31557600); // 31557600s = 1 year
|
||||
|
||||
foreach ($values as $id => $value) {
|
||||
$ok = $this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".serialize($value), $expiresAt) && $ok;
|
||||
|
@ -144,6 +144,9 @@ class ProxyAdapter implements AdapterInterface
|
||||
}
|
||||
$item = (array) $item;
|
||||
$expiry = $item["\0*\0expiry"];
|
||||
if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) {
|
||||
$expiry = time() + $item["\0*\0defaultLifetime"];
|
||||
}
|
||||
$innerItem = $item["\0*\0poolHash"] === $this->poolHash ? $item["\0*\0innerItem"] : $this->pool->getItem($this->namespace.$item["\0*\0key"]);
|
||||
$innerItem->set($item["\0*\0value"]);
|
||||
$innerItem->expiresAt(null !== $expiry ? \DateTime::createFromFormat('U', $expiry) : null);
|
||||
|
@ -11,20 +11,19 @@
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
use Symfony\Component\Cache\Adapter\RedisAdapter;
|
||||
|
||||
abstract class AbstractRedisAdapterTest extends CachePoolTest
|
||||
abstract class AbstractRedisAdapterTest extends AdapterTestCase
|
||||
{
|
||||
protected static $redis;
|
||||
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
||||
}
|
||||
|
||||
return new RedisAdapter(self::$redis, str_replace('\\', '.', __CLASS__));
|
||||
return new RedisAdapter(self::$redis, str_replace('\\', '.', __CLASS__), $defaultLifetime);
|
||||
}
|
||||
|
||||
public static function setupBeforeClass()
|
||||
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
|
||||
abstract class AdapterTestCase extends CachePoolTest
|
||||
{
|
||||
public function testDefaultLifeTime()
|
||||
{
|
||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cache = $this->createCachePool(2);
|
||||
|
||||
$item = $this->cache->getItem('key.dlt');
|
||||
$item->set('value');
|
||||
$this->cache->save($item);
|
||||
sleep(1);
|
||||
|
||||
$item = $this->cache->getItem('key.dlt');
|
||||
$this->assertTrue($item->isHit());
|
||||
|
||||
sleep(2);
|
||||
$item = $this->cache->getItem('key.dlt');
|
||||
$this->assertFalse($item->isHit());
|
||||
}
|
||||
}
|
@ -11,12 +11,11 @@
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
use Symfony\Component\Cache\Adapter\ApcuAdapter;
|
||||
|
||||
class ApcuAdapterTest extends CachePoolTest
|
||||
class ApcuAdapterTest extends AdapterTestCase
|
||||
{
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
||||
@ -28,7 +27,7 @@ class ApcuAdapterTest extends CachePoolTest
|
||||
$this->markTestSkipped('Fails transiently on Windows.');
|
||||
}
|
||||
|
||||
return new ApcuAdapter(str_replace('\\', '.', __CLASS__));
|
||||
return new ApcuAdapter(str_replace('\\', '.', __CLASS__), $defaultLifetime);
|
||||
}
|
||||
|
||||
public function testUnserializable()
|
||||
|
@ -11,21 +11,20 @@
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||
|
||||
/**
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class ArrayAdapterTest extends CachePoolTest
|
||||
class ArrayAdapterTest extends AdapterTestCase
|
||||
{
|
||||
protected $skippedTests = array(
|
||||
'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.',
|
||||
'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.',
|
||||
);
|
||||
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
return new ArrayAdapter();
|
||||
return new ArrayAdapter($defaultLifetime);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
|
||||
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||
use Symfony\Component\Cache\Adapter\ChainAdapter;
|
||||
@ -20,15 +19,15 @@ use Symfony\Component\Cache\Tests\Fixtures\ExternalAdapter;
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class ChainAdapterTest extends CachePoolTest
|
||||
class ChainAdapterTest extends AdapterTestCase
|
||||
{
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
||||
}
|
||||
|
||||
return new ChainAdapter(array(new ArrayAdapter(), new ExternalAdapter(), new FilesystemAdapter()));
|
||||
return new ChainAdapter(array(new ArrayAdapter($defaultLifetime), new ExternalAdapter(), new FilesystemAdapter('', $defaultLifetime)), $defaultLifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,22 +11,21 @@
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
use Symfony\Component\Cache\Adapter\DoctrineAdapter;
|
||||
|
||||
/**
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class DoctrineAdapterTest extends CachePoolTest
|
||||
class DoctrineAdapterTest extends AdapterTestCase
|
||||
{
|
||||
protected $skippedTests = array(
|
||||
'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayCache is not.',
|
||||
'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayCache is not.',
|
||||
);
|
||||
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
return new DoctrineAdapter(new ArrayCache());
|
||||
return new DoctrineAdapter(new ArrayCache(), '', $defaultLifetime);
|
||||
}
|
||||
}
|
||||
|
@ -11,21 +11,20 @@
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
|
||||
|
||||
/**
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class FilesystemAdapterTest extends CachePoolTest
|
||||
class FilesystemAdapterTest extends AdapterTestCase
|
||||
{
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
||||
}
|
||||
|
||||
return new FilesystemAdapter('sf-cache');
|
||||
return new FilesystemAdapter('', $defaultLifetime);
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass()
|
||||
|
@ -19,8 +19,8 @@ use Symfony\Component\Cache\Adapter\ProxyAdapter;
|
||||
*/
|
||||
class NamespacedProxyAdapterTest extends ProxyAdapterTest
|
||||
{
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
return new ProxyAdapter(new ArrayAdapter(), 'foo');
|
||||
return new ProxyAdapter(new ArrayAdapter(), 'foo', $defaultLifetime);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Cache\IntegrationTests\CachePoolTest;
|
||||
use Psr\Cache\CacheItemInterface;
|
||||
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||
use Symfony\Component\Cache\Adapter\ProxyAdapter;
|
||||
@ -20,16 +19,16 @@ use Symfony\Component\Cache\CacheItem;
|
||||
/**
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class ProxyAdapterTest extends CachePoolTest
|
||||
class ProxyAdapterTest extends AdapterTestCase
|
||||
{
|
||||
protected $skippedTests = array(
|
||||
'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.',
|
||||
'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.',
|
||||
);
|
||||
|
||||
public function createCachePool()
|
||||
public function createCachePool($defaultLifetime = 0)
|
||||
{
|
||||
return new ProxyAdapter(new ArrayAdapter());
|
||||
return new ProxyAdapter(new ArrayAdapter(), '', $defaultLifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,7 +166,7 @@ class XmlFileLoader extends FileLoader
|
||||
}
|
||||
|
||||
if ($deprecated = $this->getChildren($service, 'deprecated')) {
|
||||
$definition->setDeprecated(true, $deprecated[0]->nodeValue);
|
||||
$definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
|
||||
}
|
||||
|
||||
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument'));
|
||||
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
<services>
|
||||
<service id="foo" class="Foo">
|
||||
<deprecated />
|
||||
</service>
|
||||
<service id="bar" class="Bar">
|
||||
<deprecated>The "%service_id%" service is deprecated.</deprecated>
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
@ -302,6 +302,21 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader->load('tag_with_empty_name.xml');
|
||||
}
|
||||
|
||||
public function testDeprecated()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
|
||||
$loader->load('services_deprecated.xml');
|
||||
|
||||
$this->assertTrue($container->getDefinition('foo')->isDeprecated());
|
||||
$message = 'The "foo" service is deprecated. You should stop using it, as it will soon be removed.';
|
||||
$this->assertSame($message, $container->getDefinition('foo')->getDeprecationMessage('foo'));
|
||||
|
||||
$this->assertTrue($container->getDefinition('bar')->isDeprecated());
|
||||
$message = 'The "bar" service is deprecated.';
|
||||
$this->assertSame($message, $container->getDefinition('bar')->getDeprecationMessage('bar'));
|
||||
}
|
||||
|
||||
public function testConvertDomElementToArray()
|
||||
{
|
||||
$doc = new \DOMDocument('1.0');
|
||||
|
@ -38,7 +38,7 @@ class Store implements StoreInterface
|
||||
public function __construct($root)
|
||||
{
|
||||
$this->root = $root;
|
||||
if (!is_dir($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) {
|
||||
if (!file_exists($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) {
|
||||
throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root));
|
||||
}
|
||||
$this->keyCache = new \SplObjectStorage();
|
||||
@ -52,22 +52,15 @@ class Store implements StoreInterface
|
||||
{
|
||||
// unlock everything
|
||||
foreach ($this->locks as $lock) {
|
||||
if (file_exists($lock)) {
|
||||
@unlink($lock);
|
||||
}
|
||||
flock($lock, LOCK_UN);
|
||||
fclose($lock);
|
||||
}
|
||||
|
||||
$error = error_get_last();
|
||||
if (1 === $error['type'] && false === headers_sent()) {
|
||||
// send a 503
|
||||
header('HTTP/1.0 503 Service Unavailable');
|
||||
header('Retry-After: 10');
|
||||
echo '503 Service Unavailable';
|
||||
}
|
||||
$this->locks = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the cache for a given Request.
|
||||
* Tries to lock the cache for a given Request, without blocking.
|
||||
*
|
||||
* @param Request $request A Request instance
|
||||
*
|
||||
@ -75,21 +68,24 @@ class Store implements StoreInterface
|
||||
*/
|
||||
public function lock(Request $request)
|
||||
{
|
||||
$path = $this->getPath($this->getCacheKey($request).'.lck');
|
||||
if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) {
|
||||
return false;
|
||||
$key = $this->getCacheKey($request);
|
||||
|
||||
if (!isset($this->locks[$key])) {
|
||||
$path = $this->getPath($key);
|
||||
if (!file_exists(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) {
|
||||
return $path;
|
||||
}
|
||||
$h = fopen($path, 'cb');
|
||||
if (!flock($h, LOCK_EX | LOCK_NB)) {
|
||||
fclose($h);
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
$this->locks[$key] = $h;
|
||||
}
|
||||
|
||||
$lock = @fopen($path, 'x');
|
||||
if (false !== $lock) {
|
||||
fclose($lock);
|
||||
|
||||
$this->locks[] = $path;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return !file_exists($path) ?: $path;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,17 +97,37 @@ class Store implements StoreInterface
|
||||
*/
|
||||
public function unlock(Request $request)
|
||||
{
|
||||
$file = $this->getPath($this->getCacheKey($request).'.lck');
|
||||
$key = $this->getCacheKey($request);
|
||||
|
||||
return is_file($file) ? @unlink($file) : false;
|
||||
if (isset($this->locks[$key])) {
|
||||
flock($this->locks[$key], LOCK_UN);
|
||||
fclose($this->locks[$key]);
|
||||
unset($this->locks[$key]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isLocked(Request $request)
|
||||
{
|
||||
$path = $this->getPath($this->getCacheKey($request).'.lck');
|
||||
clearstatcache(true, $path);
|
||||
$key = $this->getCacheKey($request);
|
||||
|
||||
return is_file($path);
|
||||
if (isset($this->locks[$key])) {
|
||||
return true; // shortcut if lock held by this process
|
||||
}
|
||||
|
||||
if (!file_exists($path = $this->getPath($key))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$h = fopen($path, 'rb');
|
||||
flock($h, LOCK_EX | LOCK_NB, $wouldBlock);
|
||||
flock($h, LOCK_UN); // release the lock we just acquired
|
||||
fclose($h);
|
||||
|
||||
return (bool) $wouldBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,7 +160,7 @@ class Store implements StoreInterface
|
||||
}
|
||||
|
||||
list($req, $headers) = $match;
|
||||
if (is_file($body = $this->getPath($headers['x-content-digest'][0]))) {
|
||||
if (file_exists($body = $this->getPath($headers['x-content-digest'][0]))) {
|
||||
return $this->restoreResponse($headers, $body);
|
||||
}
|
||||
|
||||
@ -291,7 +307,7 @@ class Store implements StoreInterface
|
||||
*/
|
||||
private function getMetadata($key)
|
||||
{
|
||||
if (false === $entries = $this->load($key)) {
|
||||
if (!$entries = $this->load($key)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
@ -307,7 +323,15 @@ class Store implements StoreInterface
|
||||
*/
|
||||
public function purge($url)
|
||||
{
|
||||
if (is_file($path = $this->getPath($this->getCacheKey(Request::create($url))))) {
|
||||
$key = $this->getCacheKey(Request::create($url));
|
||||
|
||||
if (isset($this->locks[$key])) {
|
||||
flock($this->locks[$key], LOCK_UN);
|
||||
fclose($this->locks[$key]);
|
||||
unset($this->locks[$key]);
|
||||
}
|
||||
|
||||
if (file_exists($path = $this->getPath($key))) {
|
||||
unlink($path);
|
||||
|
||||
return true;
|
||||
@ -327,7 +351,7 @@ class Store implements StoreInterface
|
||||
{
|
||||
$path = $this->getPath($key);
|
||||
|
||||
return is_file($path) ? file_get_contents($path) : false;
|
||||
return file_exists($path) ? file_get_contents($path) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -341,23 +365,36 @@ class Store implements StoreInterface
|
||||
private function save($key, $data)
|
||||
{
|
||||
$path = $this->getPath($key);
|
||||
if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tmpFile = tempnam(dirname($path), basename($path));
|
||||
if (false === $fp = @fopen($tmpFile, 'wb')) {
|
||||
return false;
|
||||
}
|
||||
@fwrite($fp, $data);
|
||||
@fclose($fp);
|
||||
if (isset($this->locks[$key])) {
|
||||
$fp = $this->locks[$key];
|
||||
@ftruncate($fp, 0);
|
||||
@fseek($fp, 0);
|
||||
$len = @fwrite($fp, $data);
|
||||
if (strlen($data) !== $len) {
|
||||
@ftruncate($fp, 0);
|
||||
|
||||
if ($data != file_get_contents($tmpFile)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!file_exists(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (false === @rename($tmpFile, $path)) {
|
||||
return false;
|
||||
$tmpFile = tempnam(dirname($path), basename($path));
|
||||
if (false === $fp = @fopen($tmpFile, 'wb')) {
|
||||
return false;
|
||||
}
|
||||
@fwrite($fp, $data);
|
||||
@fclose($fp);
|
||||
|
||||
if ($data != file_get_contents($tmpFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (false === @rename($tmpFile, $path)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@chmod($path, 0666 & ~umask());
|
||||
|
@ -50,6 +50,9 @@ class HttpCacheTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
if ($this->cache) {
|
||||
$this->cache->getStore()->cleanup();
|
||||
}
|
||||
$this->kernel = null;
|
||||
$this->cache = null;
|
||||
$this->caches = null;
|
||||
|
@ -19,6 +19,10 @@ class StoreTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $request;
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* @var Store
|
||||
*/
|
||||
protected $store;
|
||||
|
||||
protected function setUp()
|
||||
|
@ -14,7 +14,7 @@ previous version of the component will break with this version.
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/ldap/index.html)
|
||||
* [Documentation](https://symfony.com/doc/current/components/ldap)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
|
@ -52,27 +52,30 @@ class WindowsPipes extends AbstractPipes
|
||||
Process::STDERR => Process::ERR,
|
||||
);
|
||||
$tmpDir = sys_get_temp_dir();
|
||||
if (!@fopen($file = $tmpDir.'\\sf_proc_00.check', 'wb')) {
|
||||
throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
|
||||
}
|
||||
@unlink($file);
|
||||
$error = 'unknown reason';
|
||||
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
|
||||
for ($i = 0;; ++$i) {
|
||||
foreach ($pipes as $pipe => $name) {
|
||||
$file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
|
||||
if (file_exists($file) && !@unlink($file)) {
|
||||
if (file_exists($file) && !unlink($file)) {
|
||||
continue 2;
|
||||
}
|
||||
$h = @fopen($file, 'xb');
|
||||
$h = fopen($file, 'xb');
|
||||
if (!$h && false === strpos($error, 'File exists')) {
|
||||
restore_error_handler();
|
||||
throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
|
||||
}
|
||||
if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
|
||||
continue 2;
|
||||
}
|
||||
if (isset($this->files[$pipe])) {
|
||||
@unlink($this->files[$pipe]);
|
||||
unlink($this->files[$pipe]);
|
||||
}
|
||||
$this->files[$pipe] = $file;
|
||||
}
|
||||
break;
|
||||
}
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
parent::__construct($input);
|
||||
|
Reference in New Issue
Block a user