PHP 7.2 버전용으로 올림!

This commit is contained in:
2018-06-21 02:17:31 +09:00
parent c1a6dd385a
commit b402846d43
70 changed files with 377 additions and 2115 deletions
+6 -26
View File
@@ -22,12 +22,9 @@ final class Key
private $expiringTime;
private $state = array();
/**
* @param string $resource
*/
public function __construct($resource)
public function __construct(string $resource)
{
$this->resource = (string) $resource;
$this->resource = $resource;
}
public function __toString()
@@ -35,39 +32,22 @@ final class Key
return $this->resource;
}
/**
* @param string $stateKey
*
* @return bool
*/
public function hasState($stateKey)
public function hasState(string $stateKey): bool
{
return isset($this->state[$stateKey]);
}
/**
* @param string $stateKey
* @param mixed $state
*/
public function setState($stateKey, $state)
public function setState(string $stateKey, $state): void
{
$this->state[$stateKey] = $state;
}
/**
* @param string $stateKey
*/
public function removeState($stateKey)
public function removeState(string $stateKey): void
{
unset($this->state[$stateKey]);
}
/**
* @param $stateKey
*
* @return mixed
*/
public function getState($stateKey)
public function getState(string $stateKey)
{
return $this->state[$stateKey];
}
+11 -10
View File
@@ -41,12 +41,12 @@ final class Lock implements LockInterface, LoggerAwareInterface
* @param float|null $ttl Maximum expected lock duration in seconds
* @param bool $autoRelease Whether to automatically release the lock or not when the lock instance is destroyed
*/
public function __construct(Key $key, StoreInterface $store, $ttl = null, $autoRelease = true)
public function __construct(Key $key, StoreInterface $store, float $ttl = null, bool $autoRelease = true)
{
$this->store = $store;
$this->key = $key;
$this->ttl = $ttl;
$this->autoRelease = (bool) $autoRelease;
$this->autoRelease = $autoRelease;
$this->logger = new NullLogger();
}
@@ -105,22 +105,25 @@ final class Lock implements LockInterface, LoggerAwareInterface
/**
* {@inheritdoc}
*/
public function refresh()
public function refresh($ttl = null)
{
if (!$this->ttl) {
if (null === $ttl) {
$ttl = $this->ttl;
}
if (!$ttl) {
throw new InvalidArgumentException('You have to define an expiration duration.');
}
try {
$this->key->resetLifetime();
$this->store->putOffExpiration($this->key, $this->ttl);
$this->store->putOffExpiration($this->key, $ttl);
$this->dirty = true;
if ($this->key->isExpired()) {
throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $this->key));
}
$this->logger->info('Expiration defined for "{resource}" lock for "{ttl}" seconds.', array('resource' => $this->key, 'ttl' => $this->ttl));
$this->logger->info('Expiration defined for "{resource}" lock for "{ttl}" seconds.', array('resource' => $this->key, 'ttl' => $ttl));
} catch (LockConflictedException $e) {
$this->dirty = false;
$this->logger->notice('Failed to define an expiration for the "{resource}" lock, someone else acquired the lock.', array('resource' => $this->key));
@@ -154,7 +157,7 @@ final class Lock implements LockInterface, LoggerAwareInterface
}
/**
* @return bool
* {@inheritdoc}
*/
public function isExpired()
{
@@ -162,9 +165,7 @@ final class Lock implements LockInterface, LoggerAwareInterface
}
/**
* Returns the remaining lifetime.
*
* @return float|null Remaining lifetime in seconds. Null when the lock won't expire.
* {@inheritdoc}
*/
public function getRemainingLifetime()
{
+16 -2
View File
@@ -24,7 +24,7 @@ interface LockInterface
{
/**
* Acquires the lock. If the lock is acquired by someone else, the parameter `blocking` determines whether or not
* the the call should block until the release of the lock.
* the call should block until the release of the lock.
*
* @param bool $blocking Whether or not the Lock should wait for the release of someone else
*
@@ -38,10 +38,12 @@ interface LockInterface
/**
* Increase the duration of an acquired lock.
*
* @param float|null $ttl Maximum expected lock duration in seconds
*
* @throws LockConflictedException If the lock is acquired by someone else
* @throws LockAcquiringException If the lock can not be refreshed
*/
public function refresh();
public function refresh(/* $ttl = null */);
/**
* Returns whether or not the lock is acquired.
@@ -56,4 +58,16 @@ interface LockInterface
* @throws LockReleasingException If the lock can not be released
*/
public function release();
/**
* @return bool
*/
public function isExpired();
/**
* Returns the remaining lifetime.
*
* @return float|null Remaining lifetime in seconds. Null when the lock won't expire.
*/
public function getRemainingLifetime();
}
+3 -5
View File
@@ -36,7 +36,7 @@ class FlockStore implements StoreInterface
*
* @throws LockStorageException If the lock directory doesnt exist or is not writable
*/
public function __construct($lockPath = null)
public function __construct(string $lockPath = null)
{
if (null === $lockPath) {
$lockPath = sys_get_temp_dir();
@@ -78,8 +78,7 @@ class FlockStore implements StoreInterface
);
// Silence error reporting
set_error_handler(function () {
});
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
if (!$handle = fopen($fileName, 'r')) {
if ($handle = fopen($fileName, 'x')) {
chmod($fileName, 0444);
@@ -91,8 +90,7 @@ class FlockStore implements StoreInterface
restore_error_handler();
if (!$handle) {
$error = error_get_last();
throw new LockStorageException($error['message'], 0, null);
throw new LockStorageException($error, 0, null);
}
// On Windows, even if PHP doc says the contrary, LOCK_NB works, see
+2 -6
View File
@@ -38,7 +38,7 @@ class MemcachedStore implements StoreInterface
* @param \Memcached $memcached
* @param int $initialTtl the expiration delay of locks in seconds
*/
public function __construct(\Memcached $memcached, $initialTtl = 300)
public function __construct(\Memcached $memcached, int $initialTtl = 300)
{
if (!static::isSupported()) {
throw new InvalidArgumentException('Memcached extension is required');
@@ -149,12 +149,8 @@ class MemcachedStore implements StoreInterface
/**
* Retrieve an unique token for the given key.
*
* @param Key $key
*
* @return string
*/
private function getToken(Key $key)
private function getToken(Key $key): string
{
if (!$key->hasState(__CLASS__)) {
$token = base64_encode(random_bytes(32));
+3 -11
View File
@@ -32,7 +32,7 @@ class RedisStore implements StoreInterface
* @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient
* @param float $initialTtl the expiration delay of locks in seconds
*/
public function __construct($redisClient, $initialTtl = 300.0)
public function __construct($redisClient, float $initialTtl = 300.0)
{
if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client && !$redisClient instanceof RedisProxy) {
throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, is_object($redisClient) ? get_class($redisClient) : gettype($redisClient)));
@@ -124,13 +124,9 @@ class RedisStore implements StoreInterface
/**
* Evaluates a script in the corresponding redis client.
*
* @param string $script
* @param string $resource
* @param array $args
*
* @return mixed
*/
private function evaluate($script, $resource, array $args)
private function evaluate(string $script, string $resource, array $args)
{
if ($this->redis instanceof \Redis || $this->redis instanceof \RedisCluster || $this->redis instanceof RedisProxy) {
return $this->redis->eval($script, array_merge(array($resource), $args), 1);
@@ -149,12 +145,8 @@ class RedisStore implements StoreInterface
/**
* Retrieves an unique token for the given key.
*
* @param Key $key
*
* @return string
*/
private function getToken(Key $key)
private function getToken(Key $key): string
{
if (!$key->hasState(__CLASS__)) {
$token = base64_encode(random_bytes(32));
+1 -1
View File
@@ -37,7 +37,7 @@ class RetryTillSaveStore implements StoreInterface, LoggerAwareInterface
* @param int $retrySleep Duration in ms between 2 retry
* @param int $retryCount Maximum amount of retry
*/
public function __construct(StoreInterface $decorated, $retrySleep = 100, $retryCount = PHP_INT_MAX)
public function __construct(StoreInterface $decorated, int $retrySleep = 100, int $retryCount = PHP_INT_MAX)
{
$this->decorated = $decorated;
$this->retrySleep = $retrySleep;
+3 -23
View File
@@ -13,7 +13,6 @@ namespace Symfony\Component\Lock\Store;
use Symfony\Component\Lock\Exception\InvalidArgumentException;
use Symfony\Component\Lock\Exception\LockConflictedException;
use Symfony\Component\Lock\Exception\NotSupportedException;
use Symfony\Component\Lock\Key;
use Symfony\Component\Lock\StoreInterface;
@@ -27,23 +26,13 @@ class SemaphoreStore implements StoreInterface
/**
* Returns whether or not the store is supported.
*
* @param bool|null $blocking when not null, checked again the blocking mode
*
* @return bool
*
* @internal
*/
public static function isSupported($blocking = null)
public static function isSupported()
{
if (!extension_loaded('sysvsem')) {
return false;
}
if (false === $blocking && \PHP_VERSION_ID < 50601) {
return false;
}
return true;
return extension_loaded('sysvsem');
}
public function __construct()
@@ -76,16 +65,7 @@ class SemaphoreStore implements StoreInterface
}
$resource = sem_get(crc32($key));
if (\PHP_VERSION_ID < 50601) {
if (!$blocking) {
throw new NotSupportedException(sprintf('The store "%s" does not supports non blocking locks.', get_class($this)));
}
$acquired = sem_acquire($resource);
} else {
$acquired = sem_acquire($resource, !$blocking);
}
$acquired = sem_acquire($resource, !$blocking);
if (!$acquired) {
throw new LockConflictedException();
+14
View File
@@ -97,6 +97,20 @@ class LockTest extends TestCase
$lock->refresh();
}
public function testRefreshCustom()
{
$key = new Key(uniqid(__METHOD__, true));
$store = $this->getMockBuilder(StoreInterface::class)->getMock();
$lock = new Lock($key, $store, 10);
$store
->expects($this->once())
->method('putOffExpiration')
->with($key, 20);
$lock->refresh(20);
}
public function testIsAquired()
{
$key = new Key(uniqid(__METHOD__, true));
+1 -6
View File
@@ -31,6 +31,7 @@ trait BlockingStoreTestTrait
* This test is time sensible: the $clockDelay could be adjust.
*
* @requires extension pcntl
* @requires extension posix
* @requires function pcntl_sigwaitinfo
*/
public function testBlockingLocks()
@@ -38,12 +39,6 @@ trait BlockingStoreTestTrait
// Amount a microsecond used to order async actions
$clockDelay = 50000;
if (\PHP_VERSION_ID < 50600 || defined('HHVM_VERSION_ID')) {
$this->markTestSkipped('The PHP engine does not keep resource in child forks');
return;
}
/** @var StoreInterface $store */
$store = $this->getStore();
$key = new Key(uniqid(__METHOD__, true));
@@ -27,10 +27,6 @@ class SemaphoreStoreTest extends AbstractStoreTest
*/
protected function getStore()
{
if (\PHP_VERSION_ID < 50601) {
$this->markTestSkipped('Non blocking semaphore are supported by PHP version greater or equals than 5.6.1');
}
return new SemaphoreStore();
}
}
+2 -3
View File
@@ -16,8 +16,7 @@
}
],
"require": {
"php": "^5.5.9|>=7.0.8",
"symfony/polyfill-php70": "~1.0",
"php": "^7.1.3",
"psr/log": "~1.0"
},
"require-dev": {
@@ -32,7 +31,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "3.4-dev"
"dev-master": "4.1-dev"
}
}
}
-19
View File
@@ -1,19 +0,0 @@
Copyright (c) 2015-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-74
View File
@@ -1,74 +0,0 @@
<?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\Polyfill\Php70;
/**
* @author Nicolas Grekas <p@tchwork.com>
*
* @internal
*/
final class Php70
{
public static function intdiv($dividend, $divisor)
{
$dividend = self::intArg($dividend, __FUNCTION__, 1);
$divisor = self::intArg($divisor, __FUNCTION__, 2);
if (0 === $divisor) {
throw new \DivisionByZeroError('Division by zero');
}
if (-1 === $divisor && ~PHP_INT_MAX === $dividend) {
throw new \ArithmeticError('Division of PHP_INT_MIN by -1 is not an integer');
}
return ($dividend - ($dividend % $divisor)) / $divisor;
}
public static function preg_replace_callback_array(array $patterns, $subject, $limit = -1, &$count = 0)
{
$count = 0;
$result = (string) $subject;
if (0 === $limit = self::intArg($limit, __FUNCTION__, 3)) {
return $result;
}
foreach ($patterns as $pattern => $callback) {
$result = preg_replace_callback($pattern, $callback, $result, $limit, $c);
$count += $c;
}
return $result;
}
public static function error_clear_last()
{
static $handler;
if (!$handler) {
$handler = function() { return false; };
}
set_error_handler($handler);
@trigger_error('');
restore_error_handler();
}
private static function intArg($value, $caller, $pos)
{
if (\is_int($value)) {
return $value;
}
if (!\is_numeric($value) || PHP_INT_MAX <= ($value += 0) || ~PHP_INT_MAX >= $value) {
throw new \TypeError(sprintf('%s() expects parameter %d to be integer, %s given', $caller, $pos, gettype($value)));
}
return (int) $value;
}
}
-28
View File
@@ -1,28 +0,0 @@
Symfony Polyfill / Php70
========================
This component provides features unavailable in releases prior to PHP 7.0:
- [`intdiv`](http://php.net/intdiv)
- [`preg_replace_callback_array`](http://php.net/preg_replace_callback_array)
- [`error_clear_last`](http://php.net/error_clear_last)
- `random_bytes` and `random_int` (from [paragonie/random_compat](https://github.com/paragonie/random_compat))
- [`*Error` throwable classes](http://php.net/Error)
- [`PHP_INT_MIN`](http://php.net/manual/en/reserved.constants.php#constant.php-int-min)
- `SessionUpdateTimestampHandlerInterface`
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
Compatibility notes
===================
To write portable code between PHP5 and PHP7, some care must be taken:
- `\*Error` exceptions must be caught before `\Exception`;
- after calling `error_clear_last()`, the result of `$e = error_get_last()` must be
verified using `isset($e['message'][0])` instead of `null !== $e`.
License
=======
This library is released under the [MIT license](LICENSE).
@@ -1,5 +0,0 @@
<?php
class ArithmeticError extends Error
{
}
@@ -1,5 +0,0 @@
<?php
class AssertionError extends Error
{
}
@@ -1,5 +0,0 @@
<?php
class DivisionByZeroError extends Error
{
}
@@ -1,5 +0,0 @@
<?php
class Error extends Exception
{
}
@@ -1,5 +0,0 @@
<?php
class ParseError extends Error
{
}
@@ -1,23 +0,0 @@
<?php
interface SessionUpdateTimestampHandlerInterface
{
/**
* Checks if a session identifier already exists or not.
*
* @param string $key
*
* @return bool
*/
public function validateId($key);
/**
* Updates the timestamp of a session when its data didn't change.
*
* @param string $key
* @param string $val
*
* @return bool
*/
public function updateTimestamp($key, $val);
}
@@ -1,5 +0,0 @@
<?php
class TypeError extends Error
{
}
-27
View File
@@ -1,27 +0,0 @@
<?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.
*/
use Symfony\Polyfill\Php70 as p;
if (PHP_VERSION_ID < 70000) {
if (!defined('PHP_INT_MIN')) {
define('PHP_INT_MIN', ~PHP_INT_MAX);
}
if (!function_exists('intdiv')) {
function intdiv($dividend, $divisor) { return p\Php70::intdiv($dividend, $divisor); }
}
if (!function_exists('preg_replace_callback_array')) {
function preg_replace_callback_array(array $patterns, $subject, $limit = -1, &$count = 0) { return p\Php70::preg_replace_callback_array($patterns, $subject, $limit, $count); }
}
if (!function_exists('error_clear_last')) {
function error_clear_last() { return p\Php70::error_clear_last(); }
}
}
-33
View File
@@ -1,33 +0,0 @@
{
"name": "symfony/polyfill-php70",
"type": "library",
"description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions",
"keywords": ["polyfill", "shim", "compatibility", "portable"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3",
"paragonie/random_compat": "~1.0|~2.0"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Php70\\": "" },
"files": [ "bootstrap.php" ],
"classmap": [ "Resources/stubs" ]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.8-dev"
}
}
}