2018-04-17 02:11:51 +00:00
< ? 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\Simple ;
use Psr\SimpleCache\CacheInterface ;
use Symfony\Component\Cache\Exception\InvalidArgumentException ;
use Symfony\Component\Cache\PruneableInterface ;
use Symfony\Component\Cache\ResettableInterface ;
2024-01-12 05:08:24 +00:00
use Symfony\Component\Cache\Traits\PhpArrayTrait ;
2018-04-17 02:11:51 +00:00
/**
* Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0 .
* Warmed up items are read - only and run - time discovered items are cached using a fallback adapter .
*
* @ author Titouan Galopin < galopintitouan @ gmail . com >
* @ author Nicolas Grekas < p @ tchwork . com >
*/
class PhpArrayCache implements CacheInterface , PruneableInterface , ResettableInterface
{
use PhpArrayTrait ;
/**
* @ param string $file The PHP file were values are cached
* @ param CacheInterface $fallbackPool A pool to fallback on when an item is not hit
*/
public function __construct ( $file , CacheInterface $fallbackPool )
{
$this -> file = $file ;
$this -> pool = $fallbackPool ;
2024-01-12 05:08:24 +00:00
$this -> zendDetectUnicode = filter_var ( ini_get ( 'zend.detect_unicode' ), \FILTER_VALIDATE_BOOLEAN );
2018-04-17 02:11:51 +00:00
}
/**
* This adapter should only be used on PHP 7.0 + to take advantage of how PHP
* stores arrays in its latest versions . This factory method decorates the given
* fallback pool with this adapter only if the current PHP version is supported .
*
2024-01-12 05:08:24 +00:00
* @ param string $file The PHP file were values are cached
* @ param CacheInterface $fallbackPool A pool to fallback on when an item is not hit
2018-04-17 02:11:51 +00:00
*
* @ return CacheInterface
*/
public static function create ( $file , CacheInterface $fallbackPool )
{
2024-01-12 05:08:24 +00:00
if ( \PHP_VERSION_ID >= 70000 ) {
2018-04-17 02:11:51 +00:00
return new static ( $file , $fallbackPool );
}
return $fallbackPool ;
}
/**
* { @ inheritdoc }
*/
public function get ( $key , $default = null )
{
2024-01-12 05:08:24 +00:00
if ( ! \is_string ( $key )) {
throw new InvalidArgumentException ( sprintf ( 'Cache key must be string, "%s" given.' , \is_object ( $key ) ? \get_class ( $key ) : \gettype ( $key )));
2018-04-17 02:11:51 +00:00
}
if ( null === $this -> values ) {
$this -> initialize ();
}
if ( ! isset ( $this -> values [ $key ])) {
return $this -> pool -> get ( $key , $default );
}
$value = $this -> values [ $key ];
if ( 'N;' === $value ) {
$value = null ;
2024-01-12 05:08:24 +00:00
} elseif ( \is_string ( $value ) && isset ( $value [ 2 ]) && ':' === $value [ 1 ]) {
2018-04-17 02:11:51 +00:00
try {
$e = null ;
$value = unserialize ( $value );
} catch ( \Error $e ) {
} catch ( \Exception $e ) {
}
if ( null !== $e ) {
return $default ;
}
}
return $value ;
}
/**
* { @ inheritdoc }
*/
public function getMultiple ( $keys , $default = null )
{
if ( $keys instanceof \Traversable ) {
$keys = iterator_to_array ( $keys , false );
2024-01-12 05:08:24 +00:00
} elseif ( ! \is_array ( $keys )) {
throw new InvalidArgumentException ( sprintf ( 'Cache keys must be array or Traversable, "%s" given.' , \is_object ( $keys ) ? \get_class ( $keys ) : \gettype ( $keys )));
2018-04-17 02:11:51 +00:00
}
foreach ( $keys as $key ) {
2024-01-12 05:08:24 +00:00
if ( ! \is_string ( $key )) {
throw new InvalidArgumentException ( sprintf ( 'Cache key must be string, "%s" given.' , \is_object ( $key ) ? \get_class ( $key ) : \gettype ( $key )));
2018-04-17 02:11:51 +00:00
}
}
if ( null === $this -> values ) {
$this -> initialize ();
}
return $this -> generateItems ( $keys , $default );
}
/**
* { @ inheritdoc }
*/
public function has ( $key )
{
2024-01-12 05:08:24 +00:00
if ( ! \is_string ( $key )) {
throw new InvalidArgumentException ( sprintf ( 'Cache key must be string, "%s" given.' , \is_object ( $key ) ? \get_class ( $key ) : \gettype ( $key )));
2018-04-17 02:11:51 +00:00
}
if ( null === $this -> values ) {
$this -> initialize ();
}
return isset ( $this -> values [ $key ]) || $this -> pool -> has ( $key );
}
/**
* { @ inheritdoc }
*/
public function delete ( $key )
{
2024-01-12 05:08:24 +00:00
if ( ! \is_string ( $key )) {
throw new InvalidArgumentException ( sprintf ( 'Cache key must be string, "%s" given.' , \is_object ( $key ) ? \get_class ( $key ) : \gettype ( $key )));
2018-04-17 02:11:51 +00:00
}
if ( null === $this -> values ) {
$this -> initialize ();
}
return ! isset ( $this -> values [ $key ]) && $this -> pool -> delete ( $key );
}
/**
* { @ inheritdoc }
*/
public function deleteMultiple ( $keys )
{
2024-01-12 05:08:24 +00:00
if ( ! \is_array ( $keys ) && ! $keys instanceof \Traversable ) {
throw new InvalidArgumentException ( sprintf ( 'Cache keys must be array or Traversable, "%s" given.' , \is_object ( $keys ) ? \get_class ( $keys ) : \gettype ( $keys )));
2018-04-17 02:11:51 +00:00
}
$deleted = true ;
2024-01-12 05:08:24 +00:00
$fallbackKeys = [];
2018-04-17 02:11:51 +00:00
foreach ( $keys as $key ) {
2024-01-12 05:08:24 +00:00
if ( ! \is_string ( $key )) {
throw new InvalidArgumentException ( sprintf ( 'Cache key must be string, "%s" given.' , \is_object ( $key ) ? \get_class ( $key ) : \gettype ( $key )));
2018-04-17 02:11:51 +00:00
}
if ( isset ( $this -> values [ $key ])) {
$deleted = false ;
} else {
$fallbackKeys [] = $key ;
}
}
if ( null === $this -> values ) {
$this -> initialize ();
}
if ( $fallbackKeys ) {
$deleted = $this -> pool -> deleteMultiple ( $fallbackKeys ) && $deleted ;
}
return $deleted ;
}
/**
* { @ inheritdoc }
*/
public function set ( $key , $value , $ttl = null )
{
2024-01-12 05:08:24 +00:00
if ( ! \is_string ( $key )) {
throw new InvalidArgumentException ( sprintf ( 'Cache key must be string, "%s" given.' , \is_object ( $key ) ? \get_class ( $key ) : \gettype ( $key )));
2018-04-17 02:11:51 +00:00
}
if ( null === $this -> values ) {
$this -> initialize ();
}
return ! isset ( $this -> values [ $key ]) && $this -> pool -> set ( $key , $value , $ttl );
}
/**
* { @ inheritdoc }
*/
public function setMultiple ( $values , $ttl = null )
{
2024-01-12 05:08:24 +00:00
if ( ! \is_array ( $values ) && ! $values instanceof \Traversable ) {
throw new InvalidArgumentException ( sprintf ( 'Cache values must be array or Traversable, "%s" given.' , \is_object ( $values ) ? \get_class ( $values ) : \gettype ( $values )));
2018-04-17 02:11:51 +00:00
}
$saved = true ;
2024-01-12 05:08:24 +00:00
$fallbackValues = [];
2018-04-17 02:11:51 +00:00
foreach ( $values as $key => $value ) {
2024-01-12 05:08:24 +00:00
if ( ! \is_string ( $key ) && ! \is_int ( $key )) {
throw new InvalidArgumentException ( sprintf ( 'Cache key must be string, "%s" given.' , \is_object ( $key ) ? \get_class ( $key ) : \gettype ( $key )));
2018-04-17 02:11:51 +00:00
}
if ( isset ( $this -> values [ $key ])) {
$saved = false ;
} else {
$fallbackValues [ $key ] = $value ;
}
}
if ( $fallbackValues ) {
$saved = $this -> pool -> setMultiple ( $fallbackValues , $ttl ) && $saved ;
}
return $saved ;
}
private function generateItems ( array $keys , $default )
{
2024-01-12 05:08:24 +00:00
$fallbackKeys = [];
2018-04-17 02:11:51 +00:00
foreach ( $keys as $key ) {
if ( isset ( $this -> values [ $key ])) {
$value = $this -> values [ $key ];
if ( 'N;' === $value ) {
yield $key => null ;
2024-01-12 05:08:24 +00:00
} elseif ( \is_string ( $value ) && isset ( $value [ 2 ]) && ':' === $value [ 1 ]) {
2018-04-17 02:11:51 +00:00
try {
yield $key => unserialize ( $value );
} catch ( \Error $e ) {
yield $key => $default ;
} catch ( \Exception $e ) {
yield $key => $default ;
}
} else {
yield $key => $value ;
}
} else {
$fallbackKeys [] = $key ;
}
}
if ( $fallbackKeys ) {
foreach ( $this -> pool -> getMultiple ( $fallbackKeys , $default ) as $key => $item ) {
yield $key => $item ;
}
}
}
}