<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Authentication\Storage;
use Zend\Stdlib\PriorityQueue;
class Chain implements StorageInterface
{
/**
* Contains all storage that this authentication method uses. A storage
* placed in the priority queue with a higher priority is always used
* before using a storage with a lower priority.
*
* @var PriorityQueue
*/
protected $storageChain;
/**
* Initializes the priority queue.
*/
public function __construct()
{
$this->storageChain = new PriorityQueue();
}
/**
* @param StorageInterface $storage
* @param int $priority
*/
public function add(StorageInterface $storage, $priority = 1)
{
$this->storageChain->insert($storage, $priority);
}
/**
* Loop over the queue of storage until a storage is found that is non-empty. If such
* storage is not found, then this chain storage itself is empty.
*
* In case a non-empty storage is found then this chain storage is also non-empty. Report
* that, but also make sure that all storage with higher priorty that are empty
* are filled.
*
* @see StorageInterface::isEmpty()
*/
public function isEmpty()
{
$storageWithHigherPriority = array();
// Loop invariant: $storageWithHigherPriority contains all storage with higher priorty
// than the current one.
foreach ($this->storageChain as $storage) {
if ($storage->isEmpty()) {
$storageWithHigherPriority[] = $storage;
continue;
}
$storageValue = $storage->read();
foreach ($storageWithHigherPriority as $higherPriorityStorage) {
$higherPriorityStorage->write($storageValue);
}
return false;
}
return true;
}
/**
* If the chain is non-empty then the storage with the top priority is guaranteed to be
* filled. Return its value.
*
* @see StorageInterface::read()
*/
public function read()
{
return $this->storageChain->top()->read();
}
/**
* Write the new $contents to all storage in the chain.
*
* @see StorageInterface::write()
*/
public function write($contents)
{
foreach ($this->storageChain as $storage) {
$storage->write($contents);
}
}
/**
* Clear all storage in the chain.
*
* @see StorageInterface::clear()
*/
public function clear()
{
foreach ($this->storageChain as $storage) {
$storage->clear();
}
}
}