Вход Регистрация
Файл: concrete5.7.5.6/concrete/vendor/zendframework/zend-cache/src/Storage/Adapter/Dba.php
Строк: 589
<?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 ZendCacheStorageAdapter;

use 
stdClass;
use 
Traversable;
use 
ZendCacheException;
use 
ZendCacheStorageAvailableSpaceCapableInterface;
use 
ZendCacheStorageCapabilities;
use 
ZendCacheStorageClearByNamespaceInterface;
use 
ZendCacheStorageClearByPrefixInterface;
use 
ZendCacheStorageFlushableInterface;
use 
ZendCacheStorageIterableInterface;
use 
ZendCacheStorageOptimizableInterface;
use 
ZendCacheStorageTotalSpaceCapableInterface;
use 
ZendStdlibErrorHandler;

class 
Dba extends AbstractAdapter implements
    
AvailableSpaceCapableInterface,
    
ClearByNamespaceInterface,
    
ClearByPrefixInterface,
    
FlushableInterface,
    
IterableInterface,
    
OptimizableInterface,
    
TotalSpaceCapableInterface
{
    
/**
     * The DBA resource handle
     *
     * @var null|resource
     */
    
protected $handle;

    
/**
     * Buffered total space in bytes
     *
     * @var null|int|float
     */
    
protected $totalSpace;

    
/**
     * Constructor
     *
     * @param  null|array|Traversable|DbaOptions $options
     * @throws ExceptionExceptionInterface
     */
    
public function __construct($options null)
    {
        if (!
extension_loaded('dba')) {
            throw new 
ExceptionExtensionNotLoadedException('Missing ext/dba');
        }

        
parent::__construct($options);
    }

    
/**
     * Destructor
     *
     * Closes an open dba resource
     *
     * @see AbstractAdapter::__destruct()
     * @return void
     */
    
public function __destruct()
    {
        
$this->_close();

        
parent::__destruct();
    }

    
/* options */

    /**
     * Set options.
     *
     * @param  array|Traversable|DbaOptions $options
     * @return Apc
     * @see    getOptions()
     */
    
public function setOptions($options)
    {
        if (!
$options instanceof DbaOptions) {
            
$options = new DbaOptions($options);
        }

        return 
parent::setOptions($options);
    }

    
/**
     * Get options.
     *
     * @return DbaOptions
     * @see    setOptions()
     */
    
public function getOptions()
    {
        if (!
$this->options) {
            
$this->setOptions(new DbaOptions());
        }
        return 
$this->options;
    }

    
/* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    
public function getTotalSpace()
    {
        if (
$this->totalSpace === null) {
            
$pathname $this->getOptions()->getPathname();

            if (
$pathname === '') {
                throw new 
ExceptionLogicException('No pathname to database file');
            }

            
ErrorHandler::start();
            
$total disk_total_space(dirname($pathname));
            
$error ErrorHandler::stop();
            if (
$total === false) {
                throw new 
ExceptionRuntimeException("Can't detect total space of '{$pathname}'"0$error);
            }
            
$this->totalSpace $total;

            
// clean total space buffer on change pathname
            
$events     $this->getEventManager();
            
$handle     null;
            
$totalSpace = & $this->totalSpace;
            
$callback   = function ($event) use (& $events, & $handle, & $totalSpace) {
                
$params $event->getParams();
                if (isset(
$params['pathname'])) {
                    
$totalSpace null;
                    
$events->detach($handle);
                }
            };
            
$events->attach('option'$callback);
        }

        return 
$this->totalSpace;
    }

    
/* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    
public function getAvailableSpace()
    {
        
$pathname $this->getOptions()->getPathname();

        if (
$pathname === '') {
            throw new 
ExceptionLogicException('No pathname to database file');
        }

        
ErrorHandler::start();
        
$avail disk_free_space(dirname($pathname));
        
$error ErrorHandler::stop();
        if (
$avail === false) {
            throw new 
ExceptionRuntimeException("Can't detect free space of '{$pathname}'"0$error);
        }

        return 
$avail;
    }

    
/* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    
public function flush()
    {
        
$pathname $this->getOptions()->getPathname();

        if (
$pathname === '') {
            throw new 
ExceptionLogicException('No pathname to database file');
        }

        if (
file_exists($pathname)) {

            
// close the dba file before delete
            // and reopen (create) on next use
            
$this->_close();

            
ErrorHandler::start();
            
$result unlink($pathname);
            
$error  ErrorHandler::stop();
            if (!
$result) {
                throw new 
ExceptionRuntimeException("unlink('{$pathname}') failed"0$error);
            }
        }

        return 
true;
    }

    
/* ClearByNamespaceInterface */

    /**
     * Remove items by given namespace
     *
     * @param string $namespace
     * @return bool
     */
    
public function clearByNamespace($namespace)
    {
        
$namespace = (string) $namespace;
        if (
$namespace === '') {
            throw new 
ExceptionInvalidArgumentException('No namespace given');
        }

        
$prefix  $namespace $this->getOptions()->getNamespaceSeparator();
        
$prefixl strlen($prefix);
        
$result  true;

        
$this->_open();

        do { 
// Workaround for PHP-Bug #62491 & #62492
            
$recheck     false;
            
$internalKey dba_firstkey($this->handle);
            while (
$internalKey !== false && $internalKey !== null) {
                if (
substr($internalKey0$prefixl) === $prefix) {
                    
$result dba_delete($internalKey$this->handle) && $result;
                }

                
$internalKey dba_nextkey($this->handle);
            }
        } while (
$recheck);

        return 
$result;
    }

    
/* ClearByPrefixInterface */

    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @return bool
     */
    
public function clearByPrefix($prefix)
    {
        
$prefix = (string) $prefix;
        if (
$prefix === '') {
            throw new 
ExceptionInvalidArgumentException('No prefix given');
        }

        
$options   $this->getOptions();
        
$namespace $options->getNamespace();
        
$prefix    = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator() . $prefix;
        
$prefixL   strlen($prefix);
        
$result    true;

        
$this->_open();

        do { 
// Workaround for PHP-Bug #62491 & #62492
            
$recheck     false;
            
$internalKey dba_firstkey($this->handle);
            while (
$internalKey !== false && $internalKey !== null) {
                if (
substr($internalKey0$prefixL) === $prefix) {
                    
$result dba_delete($internalKey$this->handle) && $result;
                    
$recheck true;
                }

                
$internalKey dba_nextkey($this->handle);
            }
        } while (
$recheck);

        return 
$result;
    }

    
/* IterableInterface */

    /**
     * Get the storage iterator
     *
     * @return ApcIterator
     */
    
public function getIterator()
    {
        
$options   $this->getOptions();
        
$namespace $options->getNamespace();
        
$prefix    = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();

        return new 
DbaIterator($this$this->handle$prefix);
    }

    
/* OptimizableInterface */

    /**
     * Optimize the storage
     *
     * @return bool
     * @return ExceptionRuntimeException
     */
    
public function optimize()
    {
        
$this->_open();
        if (!
dba_optimize($this->handle)) {
            throw new 
ExceptionRuntimeException('dba_optimize failed');
        }
        return 
true;
    }

    
/* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws ExceptionExceptionInterface
     */
    
protected function internalGetItem(& $normalizedKey, & $success null, & $casToken null)
    {
        
$options   $this->getOptions();
        
$namespace $options->getNamespace();
        
$prefix    = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();

        
$this->_open();
        
$value dba_fetch($prefix $normalizedKey$this->handle);

        if (
$value === false) {
            
$success false;
            return 
null;
        }

        
$success true;
        
$casToken $value;
        return 
$value;
    }

    
/**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws ExceptionExceptionInterface
     */
    
protected function internalHasItem(& $normalizedKey)
    {
        
$options   $this->getOptions();
        
$namespace $options->getNamespace();
        
$prefix    = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();

        
$this->_open();
        return 
dba_exists($prefix $normalizedKey$this->handle);
    }

    
/* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws ExceptionExceptionInterface
     */
    
protected function internalSetItem(& $normalizedKey, & $value)
    {
        
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;

        
$this->_open();
        if (!
dba_replace($internalKey$value$this->handle)) {
            throw new 
ExceptionRuntimeException("dba_replace('{$internalKey}', ...) failed");
        }

        return 
true;
    }

    
/**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws ExceptionExceptionInterface
     */
    
protected function internalAddItem(& $normalizedKey, & $value)
    {
        
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;

        
$this->_open();

        
// Workaround for PHP-Bug #54242 & #62489
        
if (dba_exists($internalKey$this->handle)) {
            return 
false;
        }

        
// Workaround for PHP-Bug #54242 & #62489
        // dba_insert returns true if key already exists
        
ErrorHandler::start();
        
$result dba_insert($internalKey$value$this->handle);
        
$error  ErrorHandler::stop();
        if (!
$result || $error) {
            return 
false;
        }

        return 
true;
    }

    
/**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws ExceptionExceptionInterface
     */
    
protected function internalRemoveItem(& $normalizedKey)
    {
        
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;

        
$this->_open();

        
// Workaround for PHP-Bug #62490
        
if (!dba_exists($internalKey$this->handle)) {
            return 
false;
        }

        return 
dba_delete($internalKey$this->handle);
    }

    
/* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    
protected function internalGetCapabilities()
    {
        if (
$this->capabilities === null) {
            
$marker       = new stdClass();
            
$capabilities = new Capabilities(
                
$this,
                
$marker,
                array(
                    
'supportedDatatypes' => array(
                        
'NULL'     => 'string',
                        
'boolean'  => 'string',
                        
'integer'  => 'string',
                        
'double'   => 'string',
                        
'string'   => true,
                        
'array'    => false,
                        
'object'   => false,
                        
'resource' => false,
                    ),
                    
'minTtl'             => 0,
                    
'supportedMetadata'  => array(),
                    
'maxKeyLength'       => 0// TODO: maxKeyLength ????
                    
'namespaceIsPrefix'  => true,
                    
'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
                )
            );

            
// update namespace separator on change option
            
$this->getEventManager()->attach('option', function ($event) use ($capabilities$marker) {
                
$params $event->getParams();

                if (isset(
$params['namespace_separator'])) {
                    
$capabilities->setNamespaceSeparator($marker$params['namespace_separator']);
                }
            });

            
$this->capabilities     $capabilities;
            
$this->capabilityMarker $marker;
        }

        return 
$this->capabilities;
    }

    
/**
     * Open the database if not already done.
     *
     * @return void
     * @throws ExceptionLogicException
     * @throws ExceptionRuntimeException
     */
    
protected function _open()
    {
        if (!
$this->handle) {
            
$options $this->getOptions();
            
$pathname $options->getPathname();
            
$mode     $options->getMode();
            
$handler  $options->getHandler();

            if (
$pathname === '') {
                throw new 
ExceptionLogicException('No pathname to database file');
            }

            
ErrorHandler::start();
            
$dba =  dba_open($pathname$mode$handler);
            
$err ErrorHandler::stop();
            if (!
$dba) {
                throw new 
ExceptionRuntimeException(
                    
"dba_open('{$pathname}', '{$mode}', '{$handler}') failed"0$err
                
);
            }
            
$this->handle $dba;
        }
    }

    
/**
     * Close database file if opened
     *
     * @return void
     */
    
protected function _close()
    {
        if (
$this->handle) {
            
ErrorHandler::start(E_NOTICE);
            
dba_close($this->handle);
            
ErrorHandler::stop();
            
$this->handle null;
        }
    }
}
Онлайн: 0
Реклама