Pressroom template verwijderd, website naar root van repo

This commit is contained in:
2020-03-22 15:30:52 +01:00
parent 2cb6a77425
commit f3d1c41e91
7620 changed files with 0 additions and 186900 deletions

View File

@@ -0,0 +1,132 @@
<?php
namespace Illuminate\Cache;
use Illuminate\Contracts\Cache\Store;
class ApcStore extends TaggableStore implements Store
{
use RetrievesMultipleKeys;
/**
* The APC wrapper instance.
*
* @var \Illuminate\Cache\ApcWrapper
*/
protected $apc;
/**
* A string that should be prepended to keys.
*
* @var string
*/
protected $prefix;
/**
* Create a new APC store.
*
* @param \Illuminate\Cache\ApcWrapper $apc
* @param string $prefix
* @return void
*/
public function __construct(ApcWrapper $apc, $prefix = '')
{
$this->apc = $apc;
$this->prefix = $prefix;
}
/**
* Retrieve an item from the cache by key.
*
* @param string|array $key
* @return mixed
*/
public function get($key)
{
$value = $this->apc->get($this->prefix.$key);
if ($value !== false) {
return $value;
}
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
$this->apc->put($this->prefix.$key, $value, (int) ($minutes * 60));
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function increment($key, $value = 1)
{
return $this->apc->increment($this->prefix.$key, $value);
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function decrement($key, $value = 1)
{
return $this->apc->decrement($this->prefix.$key, $value);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->put($key, $value, 0);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function forget($key)
{
return $this->apc->delete($this->prefix.$key);
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
return $this->apc->flush();
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return $this->prefix;
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace Illuminate\Cache;
class ApcWrapper
{
/**
* Indicates if APCu is supported.
*
* @var bool
*/
protected $apcu = false;
/**
* Create a new APC wrapper instance.
*
* @return void
*/
public function __construct()
{
$this->apcu = function_exists('apcu_fetch');
}
/**
* Get an item from the cache.
*
* @param string $key
* @return mixed
*/
public function get($key)
{
return $this->apcu ? apcu_fetch($key) : apc_fetch($key);
}
/**
* Store an item in the cache.
*
* @param string $key
* @param mixed $value
* @param int $seconds
* @return array|bool
*/
public function put($key, $value, $seconds)
{
return $this->apcu ? apcu_store($key, $value, $seconds) : apc_store($key, $value, $seconds);
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function increment($key, $value)
{
return $this->apcu ? apcu_inc($key, $value) : apc_inc($key, $value);
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function decrement($key, $value)
{
return $this->apcu ? apcu_dec($key, $value) : apc_dec($key, $value);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function delete($key)
{
return $this->apcu ? apcu_delete($key) : apc_delete($key);
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
return $this->apcu ? apcu_clear_cache() : apc_clear_cache('user');
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace Illuminate\Cache;
use Illuminate\Contracts\Cache\Store;
class ArrayStore extends TaggableStore implements Store
{
use RetrievesMultipleKeys;
/**
* The array of stored values.
*
* @var array
*/
protected $storage = [];
/**
* Retrieve an item from the cache by key.
*
* @param string|array $key
* @return mixed
*/
public function get($key)
{
if (array_key_exists($key, $this->storage)) {
return $this->storage[$key];
}
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
$this->storage[$key] = $value;
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function increment($key, $value = 1)
{
$this->storage[$key] = ! isset($this->storage[$key])
? $value : ((int) $this->storage[$key]) + $value;
return $this->storage[$key];
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function decrement($key, $value = 1)
{
return $this->increment($key, $value * -1);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->put($key, $value, 0);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function forget($key)
{
unset($this->storage[$key]);
return true;
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
$this->storage = [];
return true;
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return '';
}
}

View File

@@ -0,0 +1,304 @@
<?php
namespace Illuminate\Cache;
use Closure;
use Illuminate\Support\Arr;
use InvalidArgumentException;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Contracts\Cache\Factory as FactoryContract;
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
class CacheManager implements FactoryContract
{
/**
* The application instance.
*
* @var \Illuminate\Foundation\Application
*/
protected $app;
/**
* The array of resolved cache stores.
*
* @var array
*/
protected $stores = [];
/**
* The registered custom driver creators.
*
* @var array
*/
protected $customCreators = [];
/**
* Create a new Cache manager instance.
*
* @param \Illuminate\Foundation\Application $app
* @return void
*/
public function __construct($app)
{
$this->app = $app;
}
/**
* Get a cache store instance by name.
*
* @param string|null $name
* @return mixed
*/
public function store($name = null)
{
$name = $name ?: $this->getDefaultDriver();
return $this->stores[$name] = $this->get($name);
}
/**
* Get a cache driver instance.
*
* @param string $driver
* @return mixed
*/
public function driver($driver = null)
{
return $this->store($driver);
}
/**
* Attempt to get the store from the local cache.
*
* @param string $name
* @return \Illuminate\Contracts\Cache\Repository
*/
protected function get($name)
{
return isset($this->stores[$name]) ? $this->stores[$name] : $this->resolve($name);
}
/**
* Resolve the given store.
*
* @param string $name
* @return \Illuminate\Contracts\Cache\Repository
*
* @throws \InvalidArgumentException
*/
protected function resolve($name)
{
$config = $this->getConfig($name);
if (is_null($config)) {
throw new InvalidArgumentException("Cache store [{$name}] is not defined.");
}
if (isset($this->customCreators[$config['driver']])) {
return $this->callCustomCreator($config);
} else {
$driverMethod = 'create'.ucfirst($config['driver']).'Driver';
if (method_exists($this, $driverMethod)) {
return $this->{$driverMethod}($config);
} else {
throw new InvalidArgumentException("Driver [{$config['driver']}] is not supported.");
}
}
}
/**
* Call a custom driver creator.
*
* @param array $config
* @return mixed
*/
protected function callCustomCreator(array $config)
{
return $this->customCreators[$config['driver']]($this->app, $config);
}
/**
* Create an instance of the APC cache driver.
*
* @param array $config
* @return \Illuminate\Cache\ApcStore
*/
protected function createApcDriver(array $config)
{
$prefix = $this->getPrefix($config);
return $this->repository(new ApcStore(new ApcWrapper, $prefix));
}
/**
* Create an instance of the array cache driver.
*
* @return \Illuminate\Cache\ArrayStore
*/
protected function createArrayDriver()
{
return $this->repository(new ArrayStore);
}
/**
* Create an instance of the file cache driver.
*
* @param array $config
* @return \Illuminate\Cache\FileStore
*/
protected function createFileDriver(array $config)
{
return $this->repository(new FileStore($this->app['files'], $config['path']));
}
/**
* Create an instance of the Memcached cache driver.
*
* @param array $config
* @return \Illuminate\Cache\MemcachedStore
*/
protected function createMemcachedDriver(array $config)
{
$prefix = $this->getPrefix($config);
$memcached = $this->app['memcached.connector']->connect(
$config['servers'],
array_get($config, 'persistent_id'),
array_get($config, 'options', []),
array_filter(array_get($config, 'sasl', []))
);
return $this->repository(new MemcachedStore($memcached, $prefix));
}
/**
* Create an instance of the Null cache driver.
*
* @return \Illuminate\Cache\NullStore
*/
protected function createNullDriver()
{
return $this->repository(new NullStore);
}
/**
* Create an instance of the Redis cache driver.
*
* @param array $config
* @return \Illuminate\Cache\RedisStore
*/
protected function createRedisDriver(array $config)
{
$redis = $this->app['redis'];
$connection = Arr::get($config, 'connection', 'default');
return $this->repository(new RedisStore($redis, $this->getPrefix($config), $connection));
}
/**
* Create an instance of the database cache driver.
*
* @param array $config
* @return \Illuminate\Cache\DatabaseStore
*/
protected function createDatabaseDriver(array $config)
{
$connection = $this->app['db']->connection(Arr::get($config, 'connection'));
return $this->repository(
new DatabaseStore(
$connection, $this->app['encrypter'], $config['table'], $this->getPrefix($config)
)
);
}
/**
* Create a new cache repository with the given implementation.
*
* @param \Illuminate\Contracts\Cache\Store $store
* @return \Illuminate\Cache\Repository
*/
public function repository(Store $store)
{
$repository = new Repository($store);
if ($this->app->bound(DispatcherContract::class)) {
$repository->setEventDispatcher(
$this->app[DispatcherContract::class]
);
}
return $repository;
}
/**
* Get the cache prefix.
*
* @param array $config
* @return string
*/
protected function getPrefix(array $config)
{
return Arr::get($config, 'prefix') ?: $this->app['config']['cache.prefix'];
}
/**
* Get the cache connection configuration.
*
* @param string $name
* @return array
*/
protected function getConfig($name)
{
return $this->app['config']["cache.stores.{$name}"];
}
/**
* Get the default cache driver name.
*
* @return string
*/
public function getDefaultDriver()
{
return $this->app['config']['cache.default'];
}
/**
* Set the default cache driver name.
*
* @param string $name
* @return void
*/
public function setDefaultDriver($name)
{
$this->app['config']['cache.default'] = $name;
}
/**
* Register a custom driver creator Closure.
*
* @param string $driver
* @param \Closure $callback
* @return $this
*/
public function extend($driver, Closure $callback)
{
$this->customCreators[$driver] = $callback->bindTo($this, $this);
return $this;
}
/**
* Dynamically call the default driver instance.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->store()->$method(...$parameters);
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Illuminate\Cache;
use Illuminate\Support\ServiceProvider;
class CacheServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = true;
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->singleton('cache', function ($app) {
return new CacheManager($app);
});
$this->app->singleton('cache.store', function ($app) {
return $app['cache']->driver();
});
$this->app->singleton('memcached.connector', function () {
return new MemcachedConnector;
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [
'cache', 'cache.store', 'memcached.connector',
];
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace Illuminate\Cache\Console;
use Illuminate\Console\Command;
use Illuminate\Support\Composer;
use Illuminate\Filesystem\Filesystem;
class CacheTableCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'cache:table';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a migration for the cache database table';
/**
* The filesystem instance.
*
* @var \Illuminate\Filesystem\Filesystem
*/
protected $files;
/**
* @var \Illuminate\Support\Composer
*/
protected $composer;
/**
* Create a new cache table command instance.
*
* @param \Illuminate\Filesystem\Filesystem $files
* @param \Illuminate\Support\Composer $composer
* @return void
*/
public function __construct(Filesystem $files, Composer $composer)
{
parent::__construct();
$this->files = $files;
$this->composer = $composer;
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
$fullPath = $this->createBaseMigration();
$this->files->put($fullPath, $this->files->get(__DIR__.'/stubs/cache.stub'));
$this->info('Migration created successfully!');
$this->composer->dumpAutoloads();
}
/**
* Create a base migration file for the table.
*
* @return string
*/
protected function createBaseMigration()
{
$name = 'create_cache_table';
$path = $this->laravel->databasePath().'/migrations';
return $this->laravel['migration.creator']->create($name, $path);
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace Illuminate\Cache\Console;
use Illuminate\Console\Command;
use Illuminate\Cache\CacheManager;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class ClearCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'cache:clear';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Flush the application cache';
/**
* The cache manager instance.
*
* @var \Illuminate\Cache\CacheManager
*/
protected $cache;
/**
* Create a new cache clear command instance.
*
* @param \Illuminate\Cache\CacheManager $cache
* @return void
*/
public function __construct(CacheManager $cache)
{
parent::__construct();
$this->cache = $cache;
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
$this->laravel['events']->fire('cache:clearing', [$this->argument('store'), $this->tags()]);
$this->cache()->flush();
$this->laravel['events']->fire('cache:cleared', [$this->argument('store'), $this->tags()]);
$this->info('Cache cleared successfully.');
}
/**
* Get the cache instance for the command.
*
* @return \Illuminate\Cache\Repository
*/
protected function cache()
{
$cache = $this->cache->store($this->argument('store'));
return empty($this->tags()) ? $cache : $cache->tags($this->tags());
}
/**
* Get the tags passed to the command.
*
* @return array
*/
protected function tags()
{
return array_filter(explode(',', $this->option('tags')));
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['store', InputArgument::OPTIONAL, 'The name of the store you would like to clear.'],
];
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [
['tags', null, InputOption::VALUE_OPTIONAL, 'The cache tags you would like to clear.', null],
];
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Illuminate\Cache\Console;
use Illuminate\Console\Command;
use Illuminate\Cache\CacheManager;
class ForgetCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $signature = 'cache:forget {key : The key to remove} {store? : The store to remove the key from}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Remove an item from the cache';
/**
* The cache manager instance.
*
* @var \Illuminate\Cache\CacheManager
*/
protected $cache;
/**
* Create a new cache clear command instance.
*
* @param \Illuminate\Cache\CacheManager $cache
* @return void
*/
public function __construct(CacheManager $cache)
{
parent::__construct();
$this->cache = $cache;
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
$this->cache->store($this->argument('store'))->forget(
$this->argument('key')
);
$this->info('The ['.$this->argument('key').'] key has been removed from the cache.');
}
}

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCacheTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('cache');
}
}

View File

@@ -0,0 +1,280 @@
<?php
namespace Illuminate\Cache;
use Closure;
use Exception;
use Carbon\Carbon;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract;
class DatabaseStore implements Store
{
use RetrievesMultipleKeys;
/**
* The database connection instance.
*
* @var \Illuminate\Database\ConnectionInterface
*/
protected $connection;
/**
* The encrypter instance.
*
* @var \Illuminate\Contracts\Encryption\Encrypter
*/
protected $encrypter;
/**
* The name of the cache table.
*
* @var string
*/
protected $table;
/**
* A string that should be prepended to keys.
*
* @var string
*/
protected $prefix;
/**
* Create a new database store.
*
* @param \Illuminate\Database\ConnectionInterface $connection
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
* @param string $table
* @param string $prefix
* @return void
*/
public function __construct(ConnectionInterface $connection, EncrypterContract $encrypter,
$table, $prefix = '')
{
$this->table = $table;
$this->prefix = $prefix;
$this->encrypter = $encrypter;
$this->connection = $connection;
}
/**
* Retrieve an item from the cache by key.
*
* @param string|array $key
* @return mixed
*/
public function get($key)
{
$prefixed = $this->prefix.$key;
$cache = $this->table()->where('key', '=', $prefixed)->first();
// If we have a cache record we will check the expiration time against current
// time on the system and see if the record has expired. If it has, we will
// remove the records from the database table so it isn't returned again.
if (is_null($cache)) {
return;
}
$cache = is_array($cache) ? (object) $cache : $cache;
// If this cache expiration date is past the current time, we will remove this
// item from the cache. Then we will return a null value since the cache is
// expired. We will use "Carbon" to make this comparison with the column.
if (Carbon::now()->getTimestamp() >= $cache->expiration) {
$this->forget($key);
return;
}
return $this->encrypter->decrypt($cache->value);
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
$key = $this->prefix.$key;
// All of the cached values in the database are encrypted in case this is used
// as a session data store by the consumer. We'll also calculate the expire
// time and place that on the table so we will check it on our retrieval.
$value = $this->encrypter->encrypt($value);
$expiration = $this->getTime() + (int) ($minutes * 60);
try {
$this->table()->insert(compact('key', 'value', 'expiration'));
} catch (Exception $e) {
$this->table()->where('key', $key)->update(compact('value', 'expiration'));
}
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function increment($key, $value = 1)
{
return $this->incrementOrDecrement($key, $value, function ($current, $value) {
return $current + $value;
});
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function decrement($key, $value = 1)
{
return $this->incrementOrDecrement($key, $value, function ($current, $value) {
return $current - $value;
});
}
/**
* Increment or decrement an item in the cache.
*
* @param string $key
* @param mixed $value
* @param \Closure $callback
* @return int|bool
*/
protected function incrementOrDecrement($key, $value, Closure $callback)
{
return $this->connection->transaction(function () use ($key, $value, $callback) {
$prefixed = $this->prefix.$key;
$cache = $this->table()->where('key', $prefixed)
->lockForUpdate()->first();
// If there is no value in the cache, we will return false here. Otherwise the
// value will be decrypted and we will proceed with this function to either
// increment or decrement this value based on the given action callbacks.
if (is_null($cache)) {
return false;
}
$cache = is_array($cache) ? (object) $cache : $cache;
$current = $this->encrypter->decrypt($cache->value);
// Here we'll call this callback function that was given to the function which
// is used to either increment or decrement the function. We use a callback
// so we do not have to recreate all this logic in each of the functions.
$new = $callback((int) $current, $value);
if (! is_numeric($current)) {
return false;
}
// Here we will update the values in the table. We will also encrypt the value
// since database cache values are encrypted by default with secure storage
// that can't be easily read. We will return the new value after storing.
$this->table()->where('key', $prefixed)->update([
'value' => $this->encrypter->encrypt($new),
]);
return $new;
});
}
/**
* Get the current system time.
*
* @return int
*/
protected function getTime()
{
return Carbon::now()->getTimestamp();
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->put($key, $value, 5256000);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function forget($key)
{
$this->table()->where('key', '=', $this->prefix.$key)->delete();
return true;
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
return (bool) $this->table()->delete();
}
/**
* Get a query builder for the cache table.
*
* @return \Illuminate\Database\Query\Builder
*/
protected function table()
{
return $this->connection->table($this->table);
}
/**
* Get the underlying database connection.
*
* @return \Illuminate\Database\ConnectionInterface
*/
public function getConnection()
{
return $this->connection;
}
/**
* Get the encrypter instance.
*
* @return \Illuminate\Contracts\Encryption\Encrypter
*/
public function getEncrypter()
{
return $this->encrypter;
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return $this->prefix;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Illuminate\Cache\Events;
abstract class CacheEvent
{
/**
* The key of the event.
*
* @var string
*/
public $key;
/**
* The tags that were assigned to the key.
*
* @var array
*/
public $tags;
/**
* Create a new event instance.
*
* @param string $key
* @param array $tags
* @return void
*/
public function __construct($key, array $tags = [])
{
$this->key = $key;
$this->tags = $tags;
}
/**
* Set the tags for the cache event.
*
* @param array $tags
* @return $this
*/
public function setTags($tags)
{
$this->tags = $tags;
return $this;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Illuminate\Cache\Events;
class CacheHit extends CacheEvent
{
/**
* The value that was retrieved.
*
* @var mixed
*/
public $value;
/**
* Create a new event instance.
*
* @param string $key
* @param mixed $value
* @param array $tags
* @return void
*/
public function __construct($key, $value, array $tags = [])
{
parent::__construct($key, $tags);
$this->value = $value;
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Illuminate\Cache\Events;
class CacheMissed extends CacheEvent
{
//
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Illuminate\Cache\Events;
class KeyForgotten extends CacheEvent
{
//
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Illuminate\Cache\Events;
class KeyWritten extends CacheEvent
{
/**
* The value that was written.
*
* @var mixed
*/
public $value;
/**
* The number of minutes the key should be valid.
*
* @var int
*/
public $minutes;
/**
* Create a new event instance.
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @param array $tags
* @return void
*/
public function __construct($key, $value, $minutes, $tags = [])
{
parent::__construct($key, $tags);
$this->value = $value;
$this->minutes = $minutes;
}
}

View File

@@ -0,0 +1,263 @@
<?php
namespace Illuminate\Cache;
use Exception;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Filesystem\Filesystem;
class FileStore implements Store
{
use RetrievesMultipleKeys;
/**
* The Illuminate Filesystem instance.
*
* @var \Illuminate\Filesystem\Filesystem
*/
protected $files;
/**
* The file cache directory.
*
* @var string
*/
protected $directory;
/**
* Create a new file cache store instance.
*
* @param \Illuminate\Filesystem\Filesystem $files
* @param string $directory
* @return void
*/
public function __construct(Filesystem $files, $directory)
{
$this->files = $files;
$this->directory = $directory;
}
/**
* Retrieve an item from the cache by key.
*
* @param string|array $key
* @return mixed
*/
public function get($key)
{
return Arr::get($this->getPayload($key), 'data');
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
$this->ensureCacheDirectoryExists($path = $this->path($key));
$this->files->put(
$path, $this->expiration($minutes).serialize($value), true
);
}
/**
* Create the file cache directory if necessary.
*
* @param string $path
* @return void
*/
protected function ensureCacheDirectoryExists($path)
{
if (! $this->files->exists(dirname($path))) {
$this->files->makeDirectory(dirname($path), 0777, true, true);
}
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function increment($key, $value = 1)
{
$raw = $this->getPayload($key);
return tap(((int) $raw['data']) + $value, function ($newValue) use ($key, $raw) {
$this->put($key, $newValue, $raw['time']);
});
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function decrement($key, $value = 1)
{
return $this->increment($key, $value * -1);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->put($key, $value, 0);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function forget($key)
{
if ($this->files->exists($file = $this->path($key))) {
return $this->files->delete($file);
}
return false;
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
if (! $this->files->isDirectory($this->directory)) {
return false;
}
foreach ($this->files->directories($this->directory) as $directory) {
if (! $this->files->deleteDirectory($directory)) {
return false;
}
}
return true;
}
/**
* Retrieve an item and expiry time from the cache by key.
*
* @param string $key
* @return array
*/
protected function getPayload($key)
{
$path = $this->path($key);
// If the file doesn't exists, we obviously can't return the cache so we will
// just return null. Otherwise, we'll get the contents of the file and get
// the expiration UNIX timestamps from the start of the file's contents.
try {
$expire = substr(
$contents = $this->files->get($path, true), 0, 10
);
} catch (Exception $e) {
return $this->emptyPayload();
}
// If the current time is greater than expiration timestamps we will delete
// the file and return null. This helps clean up the old files and keeps
// this directory much cleaner for us as old files aren't hanging out.
if (Carbon::now()->getTimestamp() >= $expire) {
$this->forget($key);
return $this->emptyPayload();
}
$data = unserialize(substr($contents, 10));
// Next, we'll extract the number of minutes that are remaining for a cache
// so that we can properly retain the time for things like the increment
// operation that may be performed on this cache on a later operation.
$time = ($expire - Carbon::now()->getTimestamp()) / 60;
return compact('data', 'time');
}
/**
* Get a default empty payload for the cache.
*
* @return array
*/
protected function emptyPayload()
{
return ['data' => null, 'time' => null];
}
/**
* Get the full path for the given cache key.
*
* @param string $key
* @return string
*/
protected function path($key)
{
$parts = array_slice(str_split($hash = sha1($key), 2), 0, 2);
return $this->directory.'/'.implode('/', $parts).'/'.$hash;
}
/**
* Get the expiration time based on the given minutes.
*
* @param float|int $minutes
* @return int
*/
protected function expiration($minutes)
{
$time = Carbon::now()->getTimestamp() + (int) ($minutes * 60);
return $minutes === 0 || $time > 9999999999 ? 9999999999 : (int) $time;
}
/**
* Get the Filesystem instance.
*
* @return \Illuminate\Filesystem\Filesystem
*/
public function getFilesystem()
{
return $this->files;
}
/**
* Get the working directory of the cache.
*
* @return string
*/
public function getDirectory()
{
return $this->directory;
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return '';
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Illuminate\Cache;
use Memcached;
class MemcachedConnector
{
/**
* Create a new Memcached connection.
*
* @param array $servers
* @param string|null $connectionId
* @param array $options
* @param array $credentials
* @return \Memcached
*/
public function connect(array $servers, $connectionId = null, array $options = [], array $credentials = [])
{
$memcached = $this->getMemcached(
$connectionId, $credentials, $options
);
if (! $memcached->getServerList()) {
// For each server in the array, we'll just extract the configuration and add
// the server to the Memcached connection. Once we have added all of these
// servers we'll verify the connection is successful and return it back.
foreach ($servers as $server) {
$memcached->addServer(
$server['host'], $server['port'], $server['weight']
);
}
}
return $memcached;
}
/**
* Get a new Memcached instance.
*
* @param string|null $connectionId
* @param array $credentials
* @param array $options
* @return \Memcached
*/
protected function getMemcached($connectionId, array $credentials, array $options)
{
$memcached = $this->createMemcachedInstance($connectionId);
if (count($credentials) == 2) {
$this->setCredentials($memcached, $credentials);
}
if (count($options)) {
$memcached->setOptions($options);
}
return $memcached;
}
/**
* Create the Memcached instance.
*
* @param string|null $connectionId
* @return \Memcached
*/
protected function createMemcachedInstance($connectionId)
{
return empty($connectionId) ? new Memcached : new Memcached($connectionId);
}
/**
* Set the SASL credentials on the Memcached connection.
*
* @param \Memcached $memcached
* @param array $credentials
* @return void
*/
protected function setCredentials($memcached, $credentials)
{
list($username, $password) = $credentials;
$memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
$memcached->setSaslAuthData($username, $password);
}
}

View File

@@ -0,0 +1,235 @@
<?php
namespace Illuminate\Cache;
use Memcached;
use Carbon\Carbon;
use ReflectionMethod;
use Illuminate\Contracts\Cache\Store;
class MemcachedStore extends TaggableStore implements Store
{
/**
* The Memcached instance.
*
* @var \Memcached
*/
protected $memcached;
/**
* A string that should be prepended to keys.
*
* @var string
*/
protected $prefix;
/**
* Indicates whether we are using Memcached version >= 3.0.0.
*
* @var bool
*/
protected $onVersionThree;
/**
* Create a new Memcached store.
*
* @param \Memcached $memcached
* @param string $prefix
* @return void
*/
public function __construct($memcached, $prefix = '')
{
$this->setPrefix($prefix);
$this->memcached = $memcached;
$this->onVersionThree = (new ReflectionMethod('Memcached', 'getMulti'))
->getNumberOfParameters() == 2;
}
/**
* Retrieve an item from the cache by key.
*
* @param string $key
* @return mixed
*/
public function get($key)
{
$value = $this->memcached->get($this->prefix.$key);
if ($this->memcached->getResultCode() == 0) {
return $value;
}
}
/**
* Retrieve multiple items from the cache by key.
*
* Items not found in the cache will have a null value.
*
* @param array $keys
* @return array
*/
public function many(array $keys)
{
$prefixedKeys = array_map(function ($key) {
return $this->prefix.$key;
}, $keys);
if ($this->onVersionThree) {
$values = $this->memcached->getMulti($prefixedKeys, Memcached::GET_PRESERVE_ORDER);
} else {
$null = null;
$values = $this->memcached->getMulti($prefixedKeys, $null, Memcached::GET_PRESERVE_ORDER);
}
if ($this->memcached->getResultCode() != 0) {
return array_fill_keys($keys, null);
}
return array_combine($keys, $values);
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
$this->memcached->set($this->prefix.$key, $value, $this->toTimestamp($minutes));
}
/**
* Store multiple items in the cache for a given number of minutes.
*
* @param array $values
* @param float|int $minutes
* @return void
*/
public function putMany(array $values, $minutes)
{
$prefixedValues = [];
foreach ($values as $key => $value) {
$prefixedValues[$this->prefix.$key] = $value;
}
$this->memcached->setMulti($prefixedValues, $this->toTimestamp($minutes));
}
/**
* Store an item in the cache if the key doesn't exist.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return bool
*/
public function add($key, $value, $minutes)
{
return $this->memcached->add($this->prefix.$key, $value, $this->toTimestamp($minutes));
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function increment($key, $value = 1)
{
return $this->memcached->increment($this->prefix.$key, $value);
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function decrement($key, $value = 1)
{
return $this->memcached->decrement($this->prefix.$key, $value);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->put($key, $value, 0);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function forget($key)
{
return $this->memcached->delete($this->prefix.$key);
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
return $this->memcached->flush();
}
/**
* Get the UNIX timestamp for the given number of minutes.
*
* @param int $minutes
* @return int
*/
protected function toTimestamp($minutes)
{
return $minutes > 0 ? Carbon::now()->addSeconds($minutes * 60)->getTimestamp() : 0;
}
/**
* Get the underlying Memcached connection.
*
* @return \Memcached
*/
public function getMemcached()
{
return $this->memcached;
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return $this->prefix;
}
/**
* Set the cache key prefix.
*
* @param string $prefix
* @return void
*/
public function setPrefix($prefix)
{
$this->prefix = ! empty($prefix) ? $prefix.':' : '';
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace Illuminate\Cache;
use Illuminate\Contracts\Cache\Store;
class NullStore extends TaggableStore implements Store
{
use RetrievesMultipleKeys;
/**
* The array of stored values.
*
* @var array
*/
protected $storage = [];
/**
* Retrieve an item from the cache by key.
*
* @param string $key
* @return mixed
*/
public function get($key)
{
//
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
//
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function increment($key, $value = 1)
{
//
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function decrement($key, $value = 1)
{
//
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
//
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return void
*/
public function forget($key)
{
//
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
return true;
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return '';
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace Illuminate\Cache;
use Carbon\Carbon;
use Illuminate\Contracts\Cache\Repository as Cache;
class RateLimiter
{
/**
* The cache store implementation.
*
* @var \Illuminate\Contracts\Cache\Repository
*/
protected $cache;
/**
* Create a new rate limiter instance.
*
* @param \Illuminate\Contracts\Cache\Repository $cache
* @return void
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
/**
* Determine if the given key has been "accessed" too many times.
*
* @param string $key
* @param int $maxAttempts
* @param float|int $decayMinutes
* @return bool
*/
public function tooManyAttempts($key, $maxAttempts, $decayMinutes = 1)
{
if ($this->cache->has($key.':lockout')) {
return true;
}
if ($this->attempts($key) >= $maxAttempts) {
$this->lockout($key, $decayMinutes);
$this->resetAttempts($key);
return true;
}
return false;
}
/**
* Add the lockout key to the cache.
*
* @param string $key
* @param int $decayMinutes
* @return void
*/
protected function lockout($key, $decayMinutes)
{
$this->cache->add(
$key.':lockout', Carbon::now()->getTimestamp() + ($decayMinutes * 60), $decayMinutes
);
}
/**
* Increment the counter for a given key for a given decay time.
*
* @param string $key
* @param float|int $decayMinutes
* @return int
*/
public function hit($key, $decayMinutes = 1)
{
$this->cache->add($key, 0, $decayMinutes);
return (int) $this->cache->increment($key);
}
/**
* Get the number of attempts for the given key.
*
* @param string $key
* @return mixed
*/
public function attempts($key)
{
return $this->cache->get($key, 0);
}
/**
* Reset the number of attempts for the given key.
*
* @param string $key
* @return mixed
*/
public function resetAttempts($key)
{
return $this->cache->forget($key);
}
/**
* Get the number of retries left for the given key.
*
* @param string $key
* @param int $maxAttempts
* @return int
*/
public function retriesLeft($key, $maxAttempts)
{
$attempts = $this->attempts($key);
return $maxAttempts - $attempts;
}
/**
* Clear the hits and lockout for the given key.
*
* @param string $key
* @return void
*/
public function clear($key)
{
$this->resetAttempts($key);
$this->cache->forget($key.':lockout');
}
/**
* Get the number of seconds until the "key" is accessible again.
*
* @param string $key
* @return int
*/
public function availableIn($key)
{
return $this->cache->get($key.':lockout') - Carbon::now()->getTimestamp();
}
}

View File

@@ -0,0 +1,277 @@
<?php
namespace Illuminate\Cache;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Contracts\Redis\Factory as Redis;
class RedisStore extends TaggableStore implements Store
{
/**
* The Redis factory implementation.
*
* @var \Illuminate\Contracts\Redis\Factory
*/
protected $redis;
/**
* A string that should be prepended to keys.
*
* @var string
*/
protected $prefix;
/**
* The Redis connection that should be used.
*
* @var string
*/
protected $connection;
/**
* Create a new Redis store.
*
* @param \Illuminate\Contracts\Redis\Factory $redis
* @param string $prefix
* @param string $connection
* @return void
*/
public function __construct(Redis $redis, $prefix = '', $connection = 'default')
{
$this->redis = $redis;
$this->setPrefix($prefix);
$this->setConnection($connection);
}
/**
* Retrieve an item from the cache by key.
*
* @param string|array $key
* @return mixed
*/
public function get($key)
{
$value = $this->connection()->get($this->prefix.$key);
return ! is_null($value) ? $this->unserialize($value) : null;
}
/**
* Retrieve multiple items from the cache by key.
*
* Items not found in the cache will have a null value.
*
* @param array $keys
* @return array
*/
public function many(array $keys)
{
$results = [];
$values = $this->connection()->mget(array_map(function ($key) {
return $this->prefix.$key;
}, $keys));
foreach ($values as $index => $value) {
$results[$keys[$index]] = ! is_null($value) ? $this->unserialize($value) : null;
}
return $results;
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
$this->connection()->setex(
$this->prefix.$key, (int) max(1, $minutes * 60), $this->serialize($value)
);
}
/**
* Store multiple items in the cache for a given number of minutes.
*
* @param array $values
* @param float|int $minutes
* @return void
*/
public function putMany(array $values, $minutes)
{
$this->connection()->multi();
foreach ($values as $key => $value) {
$this->put($key, $value, $minutes);
}
$this->connection()->exec();
}
/**
* Store an item in the cache if the key doesn't exist.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
* @return bool
*/
public function add($key, $value, $minutes)
{
$lua = "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])";
return (bool) $this->connection()->eval(
$lua, 1, $this->prefix.$key, $this->serialize($value), (int) max(1, $minutes * 60)
);
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function increment($key, $value = 1)
{
return $this->connection()->incrby($this->prefix.$key, $value);
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int
*/
public function decrement($key, $value = 1)
{
return $this->connection()->decrby($this->prefix.$key, $value);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->connection()->set($this->prefix.$key, $this->serialize($value));
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function forget($key)
{
return (bool) $this->connection()->del($this->prefix.$key);
}
/**
* Remove all items from the cache.
*
* @return bool
*/
public function flush()
{
$this->connection()->flushdb();
return true;
}
/**
* Begin executing a new tags operation.
*
* @param array|mixed $names
* @return \Illuminate\Cache\RedisTaggedCache
*/
public function tags($names)
{
return new RedisTaggedCache(
$this, new TagSet($this, is_array($names) ? $names : func_get_args())
);
}
/**
* Get the Redis connection instance.
*
* @return \Predis\ClientInterface
*/
public function connection()
{
return $this->redis->connection($this->connection);
}
/**
* Set the connection name to be used.
*
* @param string $connection
* @return void
*/
public function setConnection($connection)
{
$this->connection = $connection;
}
/**
* Get the Redis database instance.
*
* @return \Illuminate\Contracts\Redis\Factory
*/
public function getRedis()
{
return $this->redis;
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return $this->prefix;
}
/**
* Set the cache key prefix.
*
* @param string $prefix
* @return void
*/
public function setPrefix($prefix)
{
$this->prefix = ! empty($prefix) ? $prefix.':' : '';
}
/**
* Serialize the value.
*
* @param mixed $value
* @return mixed
*/
protected function serialize($value)
{
return is_numeric($value) ? $value : serialize($value);
}
/**
* Unserialize the value.
*
* @param mixed $value
* @return mixed
*/
protected function unserialize($value)
{
return is_numeric($value) ? $value : unserialize($value);
}
}

View File

@@ -0,0 +1,166 @@
<?php
namespace Illuminate\Cache;
class RedisTaggedCache extends TaggedCache
{
/**
* Forever reference key.
*
* @var string
*/
const REFERENCE_KEY_FOREVER = 'forever_ref';
/**
* Standard reference key.
*
* @var string
*/
const REFERENCE_KEY_STANDARD = 'standard_ref';
/**
* Store an item in the cache.
*
* @param string $key
* @param mixed $value
* @param \DateTime|float|int $minutes
* @return void
*/
public function put($key, $value, $minutes = null)
{
$this->pushStandardKeys($this->tags->getNamespace(), $key);
parent::put($key, $value, $minutes);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->pushForeverKeys($this->tags->getNamespace(), $key);
parent::forever($key, $value);
}
/**
* Remove all items from the cache.
*
* @return void
*/
public function flush()
{
$this->deleteForeverKeys();
$this->deleteStandardKeys();
parent::flush();
}
/**
* Store standard key references into store.
*
* @param string $namespace
* @param string $key
* @return void
*/
protected function pushStandardKeys($namespace, $key)
{
$this->pushKeys($namespace, $key, self::REFERENCE_KEY_STANDARD);
}
/**
* Store forever key references into store.
*
* @param string $namespace
* @param string $key
* @return void
*/
protected function pushForeverKeys($namespace, $key)
{
$this->pushKeys($namespace, $key, self::REFERENCE_KEY_FOREVER);
}
/**
* Store a reference to the cache key against the reference key.
*
* @param string $namespace
* @param string $key
* @param string $reference
* @return void
*/
protected function pushKeys($namespace, $key, $reference)
{
$fullKey = $this->store->getPrefix().sha1($namespace).':'.$key;
foreach (explode('|', $namespace) as $segment) {
$this->store->connection()->sadd($this->referenceKey($segment, $reference), $fullKey);
}
}
/**
* Delete all of the items that were stored forever.
*
* @return void
*/
protected function deleteForeverKeys()
{
$this->deleteKeysByReference(self::REFERENCE_KEY_FOREVER);
}
/**
* Delete all standard items.
*
* @return void
*/
protected function deleteStandardKeys()
{
$this->deleteKeysByReference(self::REFERENCE_KEY_STANDARD);
}
/**
* Find and delete all of the items that were stored against a reference.
*
* @param string $reference
* @return void
*/
protected function deleteKeysByReference($reference)
{
foreach (explode('|', $this->tags->getNamespace()) as $segment) {
$this->deleteValues($segment = $this->referenceKey($segment, $reference));
$this->store->connection()->del($segment);
}
}
/**
* Delete item keys that have been stored against a reference.
*
* @param string $referenceKey
* @return void
*/
protected function deleteValues($referenceKey)
{
$values = array_unique($this->store->connection()->smembers($referenceKey));
if (count($values) > 0) {
foreach (array_chunk($values, 1000) as $valuesChunk) {
call_user_func_array([$this->store->connection(), 'del'], $valuesChunk);
}
}
}
/**
* Get the reference key for the segment.
*
* @param string $segment
* @param string $suffix
* @return string
*/
protected function referenceKey($segment, $suffix)
{
return $this->store->getPrefix().$segment.':'.$suffix;
}
}

View File

@@ -0,0 +1,517 @@
<?php
namespace Illuminate\Cache;
use Closure;
use DateTime;
use ArrayAccess;
use Carbon\Carbon;
use BadMethodCallException;
use Illuminate\Cache\Events\CacheHit;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Cache\Events\KeyWritten;
use Illuminate\Cache\Events\CacheMissed;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Cache\Events\KeyForgotten;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Cache\Repository as CacheContract;
class Repository implements CacheContract, ArrayAccess
{
use Macroable {
__call as macroCall;
}
/**
* The cache store implementation.
*
* @var \Illuminate\Contracts\Cache\Store
*/
protected $store;
/**
* The event dispatcher implementation.
*
* @var \Illuminate\Contracts\Events\Dispatcher
*/
protected $events;
/**
* The default number of minutes to store items.
*
* @var float|int
*/
protected $default = 60;
/**
* Create a new cache repository instance.
*
* @param \Illuminate\Contracts\Cache\Store $store
* @return void
*/
public function __construct(Store $store)
{
$this->store = $store;
}
/**
* Determine if an item exists in the cache.
*
* @param string $key
* @return bool
*/
public function has($key)
{
return ! is_null($this->get($key));
}
/**
* Retrieve an item from the cache by key.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
{
if (is_array($key)) {
return $this->many($key);
}
$value = $this->store->get($this->itemKey($key));
// If we could not find the cache value, we will fire the missed event and get
// the default value for this cache value. This default could be a callback
// so we will execute the value function which will resolve it if needed.
if (is_null($value)) {
$this->event(new CacheMissed($key));
$value = value($default);
} else {
$this->event(new CacheHit($key, $value));
}
return $value;
}
/**
* Retrieve multiple items from the cache by key.
*
* Items not found in the cache will have a null value.
*
* @param array $keys
* @return array
*/
public function many(array $keys)
{
$values = $this->store->many(collect($keys)->map(function ($value, $key) {
return is_string($key) ? $key : $value;
})->values()->all());
return collect($values)->map(function ($value, $key) use ($keys) {
return $this->handleManyResult($keys, $key, $value);
})->all();
}
/**
* Handle a result for the "many" method.
*
* @param array $keys
* @param string $key
* @param mixed $value
* @return mixed
*/
protected function handleManyResult($keys, $key, $value)
{
// If we could not find the cache value, we will fire the missed event and get
// the default value for this cache value. This default could be a callback
// so we will execute the value function which will resolve it if needed.
if (is_null($value)) {
$this->event(new CacheMissed($key));
return isset($keys[$key]) ? value($keys[$key]) : null;
}
// If we found a valid value we will fire the "hit" event and return the value
// back from this function. The "hit" event gives developers an opportunity
// to listen for every possible cache "hit" throughout this applications.
$this->event(new CacheHit($key, $value));
return $value;
}
/**
* Retrieve an item from the cache and delete it.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function pull($key, $default = null)
{
return tap($this->get($key, $default), function ($value) use ($key) {
$this->forget($key);
});
}
/**
* Store an item in the cache.
*
* @param string $key
* @param mixed $value
* @param \DateTime|float|int $minutes
* @return void
*/
public function put($key, $value, $minutes = null)
{
if (is_array($key)) {
return $this->putMany($key, $value);
}
if (! is_null($minutes = $this->getMinutes($minutes))) {
$this->store->put($this->itemKey($key), $value, $minutes);
$this->event(new KeyWritten($key, $value, $minutes));
}
}
/**
* Store multiple items in the cache for a given number of minutes.
*
* @param array $values
* @param float|int $minutes
* @return void
*/
public function putMany(array $values, $minutes)
{
if (! is_null($minutes = $this->getMinutes($minutes))) {
$this->store->putMany($values, $minutes);
foreach ($values as $key => $value) {
$this->event(new KeyWritten($key, $value, $minutes));
}
}
}
/**
* Store an item in the cache if the key does not exist.
*
* @param string $key
* @param mixed $value
* @param \DateTime|float|int $minutes
* @return bool
*/
public function add($key, $value, $minutes)
{
if (is_null($minutes = $this->getMinutes($minutes))) {
return false;
}
// If the store has an "add" method we will call the method on the store so it
// has a chance to override this logic. Some drivers better support the way
// this operation should work with a total "atomic" implementation of it.
if (method_exists($this->store, 'add')) {
return $this->store->add(
$this->itemKey($key), $value, $minutes
);
}
// If the value did not exist in the cache, we will put the value in the cache
// so it exists for subsequent requests. Then, we will return true so it is
// easy to know if the value gets added. Otherwise, we will return false.
if (is_null($this->get($key))) {
$this->put($key, $value, $minutes);
return true;
}
return false;
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function increment($key, $value = 1)
{
return $this->store->increment($key, $value);
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return int|bool
*/
public function decrement($key, $value = 1)
{
return $this->store->decrement($key, $value);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->store->forever($this->itemKey($key), $value);
$this->event(new KeyWritten($key, $value, 0));
}
/**
* Get an item from the cache, or store the default value.
*
* @param string $key
* @param \DateTime|float|int $minutes
* @param \Closure $callback
* @return mixed
*/
public function remember($key, $minutes, Closure $callback)
{
$value = $this->get($key);
// If the item exists in the cache we will just return this immediately and if
// not we will execute the given Closure and cache the result of that for a
// given number of minutes so it's available for all subsequent requests.
if (! is_null($value)) {
return $value;
}
$this->put($key, $value = $callback(), $minutes);
return $value;
}
/**
* Get an item from the cache, or store the default value forever.
*
* @param string $key
* @param \Closure $callback
* @return mixed
*/
public function sear($key, Closure $callback)
{
return $this->rememberForever($key, $callback);
}
/**
* Get an item from the cache, or store the default value forever.
*
* @param string $key
* @param \Closure $callback
* @return mixed
*/
public function rememberForever($key, Closure $callback)
{
$value = $this->get($key);
// If the item exists in the cache we will just return this immediately and if
// not we will execute the given Closure and cache the result of that for a
// given number of minutes so it's available for all subsequent requests.
if (! is_null($value)) {
return $value;
}
$this->forever($key, $value = $callback());
return $value;
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return bool
*/
public function forget($key)
{
return tap($this->store->forget($this->itemKey($key)), function () use ($key) {
$this->event(new KeyForgotten($key));
});
}
/**
* Begin executing a new tags operation if the store supports it.
*
* @param array|mixed $names
* @return \Illuminate\Cache\TaggedCache
*
* @throws \BadMethodCallException
*/
public function tags($names)
{
if (! method_exists($this->store, 'tags')) {
throw new BadMethodCallException('This cache store does not support tagging.');
}
$cache = $this->store->tags($names);
if (! is_null($this->events)) {
$cache->setEventDispatcher($this->events);
}
return $cache->setDefaultCacheTime($this->default);
}
/**
* Format the key for a cache item.
*
* @param string $key
* @return string
*/
protected function itemKey($key)
{
return $key;
}
/**
* Get the default cache time.
*
* @return float|int
*/
public function getDefaultCacheTime()
{
return $this->default;
}
/**
* Set the default cache time in minutes.
*
* @param float|int $minutes
* @return $this
*/
public function setDefaultCacheTime($minutes)
{
$this->default = $minutes;
return $this;
}
/**
* Get the cache store implementation.
*
* @return \Illuminate\Contracts\Cache\Store
*/
public function getStore()
{
return $this->store;
}
/**
* Fire an event for this cache instance.
*
* @param string $event
* @return void
*/
protected function event($event)
{
if (isset($this->events)) {
$this->events->dispatch($event);
}
}
/**
* Set the event dispatcher instance.
*
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function setEventDispatcher(Dispatcher $events)
{
$this->events = $events;
}
/**
* Determine if a cached value exists.
*
* @param string $key
* @return bool
*/
public function offsetExists($key)
{
return $this->has($key);
}
/**
* Retrieve an item from the cache by key.
*
* @param string $key
* @return mixed
*/
public function offsetGet($key)
{
return $this->get($key);
}
/**
* Store an item in the cache for the default time.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function offsetSet($key, $value)
{
$this->put($key, $value, $this->default);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return void
*/
public function offsetUnset($key)
{
$this->forget($key);
}
/**
* Calculate the number of minutes with the given duration.
*
* @param \DateTime|float|int $duration
* @return float|int|null
*/
protected function getMinutes($duration)
{
if ($duration instanceof DateTime) {
$duration = Carbon::now()->diffInSeconds(Carbon::instance($duration), false) / 60;
}
return (int) ($duration * 60) > 0 ? $duration : null;
}
/**
* Handle dynamic calls into macros or pass missing methods to the store.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}
return $this->store->$method(...$parameters);
}
/**
* Clone cache repository instance.
*
* @return void
*/
public function __clone()
{
$this->store = clone $this->store;
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Illuminate\Cache;
trait RetrievesMultipleKeys
{
/**
* Retrieve multiple items from the cache by key.
*
* Items not found in the cache will have a null value.
*
* @param array $keys
* @return array
*/
public function many(array $keys)
{
$return = [];
foreach ($keys as $key) {
$return[$key] = $this->get($key);
}
return $return;
}
/**
* Store multiple items in the cache for a given number of minutes.
*
* @param array $values
* @param float|int $minutes
* @return void
*/
public function putMany(array $values, $minutes)
{
foreach ($values as $key => $value) {
$this->put($key, $value, $minutes);
}
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace Illuminate\Cache;
use Illuminate\Contracts\Cache\Store;
class TagSet
{
/**
* The cache store implementation.
*
* @var \Illuminate\Contracts\Cache\Store
*/
protected $store;
/**
* The tag names.
*
* @var array
*/
protected $names = [];
/**
* Create a new TagSet instance.
*
* @param \Illuminate\Contracts\Cache\Store $store
* @param array $names
* @return void
*/
public function __construct(Store $store, array $names = [])
{
$this->store = $store;
$this->names = $names;
}
/**
* Reset all tags in the set.
*
* @return void
*/
public function reset()
{
array_walk($this->names, [$this, 'resetTag']);
}
/**
* Reset the tag and return the new tag identifier.
*
* @param string $name
* @return string
*/
public function resetTag($name)
{
$this->store->forever($this->tagKey($name), $id = str_replace('.', '', uniqid('', true)));
return $id;
}
/**
* Get a unique namespace that changes when any of the tags are flushed.
*
* @return string
*/
public function getNamespace()
{
return implode('|', $this->tagIds());
}
/**
* Get an array of tag identifiers for all of the tags in the set.
*
* @return array
*/
protected function tagIds()
{
return array_map([$this, 'tagId'], $this->names);
}
/**
* Get the unique tag identifier for a given tag.
*
* @param string $name
* @return string
*/
public function tagId($name)
{
return $this->store->get($this->tagKey($name)) ?: $this->resetTag($name);
}
/**
* Get the tag identifier key for a given tag.
*
* @param string $name
* @return string
*/
public function tagKey($name)
{
return 'tag:'.$name.':key';
}
/**
* Get all of the tag names in the set.
*
* @return array
*/
public function getNames()
{
return $this->names;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Illuminate\Cache;
abstract class TaggableStore
{
/**
* Begin executing a new tags operation.
*
* @param array|mixed $names
* @return \Illuminate\Cache\TaggedCache
*/
public function tags($names)
{
return new TaggedCache($this, new TagSet($this, is_array($names) ? $names : func_get_args()));
}
}

View File

@@ -0,0 +1,95 @@
<?php
namespace Illuminate\Cache;
use Illuminate\Contracts\Cache\Store;
class TaggedCache extends Repository
{
use RetrievesMultipleKeys;
/**
* The tag set instance.
*
* @var \Illuminate\Cache\TagSet
*/
protected $tags;
/**
* Create a new tagged cache instance.
*
* @param \Illuminate\Contracts\Cache\Store $store
* @param \Illuminate\Cache\TagSet $tags
* @return void
*/
public function __construct(Store $store, TagSet $tags)
{
parent::__construct($store);
$this->tags = $tags;
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function increment($key, $value = 1)
{
$this->store->increment($this->itemKey($key), $value);
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function decrement($key, $value = 1)
{
$this->store->decrement($this->itemKey($key), $value);
}
/**
* Remove all items from the cache.
*
* @return void
*/
public function flush()
{
$this->tags->reset();
}
/**
* {@inheritdoc}
*/
protected function itemKey($key)
{
return $this->taggedItemKey($key);
}
/**
* Get a fully qualified key for a tagged item.
*
* @param string $key
* @return string
*/
public function taggedItemKey($key)
{
return sha1($this->tags->getNamespace()).':'.$key;
}
/**
* Fire an event for this cache instance.
*
* @param string $event
* @return void
*/
protected function event($event)
{
parent::event($event->setTags($this->tags->getNames()));
}
}

View File

@@ -0,0 +1,41 @@
{
"name": "illuminate/cache",
"description": "The Illuminate Cache package.",
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"require": {
"php": ">=5.6.4",
"illuminate/contracts": "5.4.*",
"illuminate/support": "5.4.*",
"nesbot/carbon": "~1.20"
},
"autoload": {
"psr-4": {
"Illuminate\\Cache\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "5.4-dev"
}
},
"suggest": {
"illuminate/database": "Required to use the database cache driver (5.4.*).",
"illuminate/filesystem": "Required to use the file cache driver (5.4.*).",
"illuminate/redis": "Required to use the redis cache driver (5.4.*)."
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}