<?php
namespace Core\DateTime;

/**
 * Timer.php
 *
 * @author Michael "Tekkla" Zorn <tekkla@tekkla.de>
 * @copyright 2016
 * @license MIT
 */
class Timer
{

    /**
     *
     * @var int
     */
    private $start;

    /**
     *
     * @var int
     */
    private $end;

    /**
     *
     * @var bool
     */
    private $running = false;

    /**
     *
     * @var array
     */
    private $checkpoints = [];

    /**
     * Starts timer and creates first checkpoint
     *
     * @throws \RuntimeException
     *
     * @return Timer
     */
    public function start()
    {
        if ($this->running) {
            Throw new \RuntimeException('Timer is already running.');
        }

        $this->start = microtime(true);
        $this->checkpoints['start'] = $this->start;
        $this->running = true;

        return $this;
    }

    /**
     * Stopps timer and returns difference from start
     *
     * @throws \Exception
     */
    public function stop()
    {
        if (! $this->running) {
            Throw new \Exception('Timer is not running.');
        }

        $this->end = microtime(true);
        $this->checkpoints['end'] = $this->end;
        $this->running = false;

        return $this->getDiff();
    }

    /**
     * Adds a new named checkpoint which measures the time between now and the last checkpooint.
     *
     * @param string $name
     */
    public function checkpoint(string $name)
    {
        $this->checkpoints[$name] = microtime(true) - end($this->checkpoints);
    }

    /**
     * Returns the start time.
     *
     * @return integer
     */
    private function getStart(): int
    {
        return $this->start;
    }

    /**
     * Stopps timer and returns it's ending time.
     * Sets also endcheckpoint
     *
     * @return mixed
     */
    private function getEnd()
    {
        if ($this->running) {
            $this->stop();
        }

        return $this->end;
    }

    /**
     * Calculates and returns the time between start and end.
     *
     * @return number
     */
    public function getDiff()
    {
        return $this->getEnd() - $this->getStart();
    }

    /**
     * Resets timer to current time.
     */
    public function reset()
    {
        $this->start = 0;
    }
}


<?php
/*
 * This file is a part of Solve framework.
 *
 * @author Alexandr Viniychuk <alexandr.viniychuk@icloud.com>
 * @copyright 2009-2014, Alexandr Viniychuk
 * created: 10.05.14 18:10
 */

namespace Solve\Database\Models;
require_once __DIR__ . '/../Models/ModelCollection.php';
use Solve\Database\DatabaseService;
use Solve\Database\QC;
use Solve\DataTools\DataProcessor;
use Solve\Utils\Inflector;
use Solve\Database\Models\ModelCollection;

/**
 * Class Model
 * @package Solve\Database\Models
 *
 * @version 1.0
 * @author Alexandr Viniychuk <alexandr.viniychuk@icloud.com>
 */
class Model implements \ArrayAccess, \IteratorAggregate, \Countable {
    /**
     * @var ModelStructure
     */
    private $_structure;

    private $_tableName;
    private $_primaryKey;
    private $_collectionObjectReference;
    private $_internalObjectHash;

    private static $_dataProcessors = array();
    /**
     * @var DataProcessor
     */
    private        $_dataProcessor;
    private        $_data           = array();
    private        $_originalData   = array();
    private        $_changedData    = array();
    private        $_isNew          = true;
    private        $_invokedGetters = array();

    /**
     * @var null|string instance model name
     */
    private $_name = null;

    public function __construct($data = array()) {
        $this->_name               = get_called_class();
        $this->_internalObjectHash = md5(time() . microtime(true));
        $this->_structure          = ModelStructure::getInstanceForModel($this->_name);
        $this->_tableName          = $this->_structure->getTableName();
        $this->_primaryKey         = $this->_structure->getPrimaryKey();
        $this->mergeWithData($data);
        $this->initializeDataProcessor();
        $this->initializeAbilities();
        $this->configure();
    }

    public static function getModel($modelName) {
        if (class_exists($modelName)) {
            return new $modelName();
        } else {
            return new Model();
        }
    }

    /**
     * @param mixed|QC $criteria
     * @return Model
     */
    public static function loadOne($criteria) {
        /**
         * @var Model $object
         */
        $object = self::getModel(get_called_class());
        return $object->_loadOne($criteria);
    }

    /**
     * @param QC|mixed $criteria
     * @return ModelCollection
     */
    public static function loadList($criteria = null) {
        /**
         * @var Model $object
         */
        $object                    = self::getModel(get_called_class());
        $customCollectionClassName = Inflector::pluralize($object->_name) . 'Collection';
        $collectionClass           = class_exists($customCollectionClassName) ? $customCollectionClassName : '\\Solve\\Database\\Models\\ModelCollection';
        return call_user_func(array($collectionClass, 'loadList',), $criteria, $object);

    }

    /**
     * @param mixed|QC $criteria
     * @return Model
     */
    protected function _loadOne($criteria) {
        /**
         * @var QC $criteria
         */
        if (is_object($criteria) && $criteria->getModifier('rawSelect')) {
            $qc = $criteria;
        } else {
            $criteria = $this->_processCriteria($criteria);

            $qc = QC::create($this->_tableName);
            if (!empty($criteria)) {
                if (is_object($criteria)) {
                    $qc->importQC($criteria);
                }
                $qc->and($criteria);
            }
        }
        $this->_preLoad($qc);
        $this->setOriginalData($qc->executeOne());
        $this->unpackOriginalData();
        $this->_postLoad();
        if (empty($this->_data['id'])) {
            return DatabaseService::getConfig('loadOneFails') == 'model' ? $this : null;
        } else {
            return $this;
        }
    }

    public function _processCriteria($criteria) {
        if (is_scalar($criteria)) {
            $criteria = array($this->_primaryKey => $criteria,);
        }
        if (is_array($criteria)) {
            $newCriteria = array();
            if (array_key_exists(0, $criteria)) {
                $newCriteria[$this->_tableName . '.' . $this->_primaryKey] = $criteria;
            } else {
                foreach ($criteria as $key => $value) {
                    $newCriteria[$this->_tableName . '.' . $key] = $value;
                }
            }
            $criteria = $newCriteria;
            unset($newCriteria);
        }
        return $criteria;
    }

    public function setOriginalData($data) {
        if (empty($data)) $data = array();

        $this->_originalData = $data;
        $this->_data         = $data;
        $this->_isNew        = false;
        return $this;
    }

    protected function unpackOriginalData() {
        foreach($this->_structure->getColumns() as $columnName => $columnInfo) {
            if ($columnInfo['type'] == 'array') {
                $value = empty($this->_data[$columnName]) ? array() : unserialize($this->_originalData[$columnName]);
                $this->_setRawFieldValue($columnName, $value);
            }
        }
        return $this;
    }

    protected function getPackedData($data) {
        foreach($this->_structure->getColumns() as $columnName => $columnInfo) {
            if ($columnInfo['type'] == 'array') {
                $value = empty($data[$columnName]) ? "" : serialize($data[$columnName]);
                $data[$columnName] = $value;
            }
        }
        return $data;
    }

    public function _setRawFieldValue($field, $value) {
        $this->_data[$field] = $this->_originalData[$field] = $value;
        return $this;
    }

    public function _setRawFieldData($data) {
        foreach ($data as $field => $value) {
            $this->_data[$field] = $this->_originalData[$field] = $value;
        }
        return $this;
    }

    /**
     * Merge current data with provided
     * @param $data
     */
    public function mergeWithData($data) {
        foreach ($data as $key => $value) {
            if ($key != $this->_primaryKey && (
                    (!array_key_exists($key, $this->_data) && $this->_structure->hasColumn($key))
                    || (array_key_exists($key, $this->_data) && $value != $this->_data[$key])
                )
            ) {
                $this->offsetSet($key, $value);
            }
        }
    }

    public function validate() {
        return $this->_dataProcessor->process($this->_data)->isValid();
    }

    public function getErrors($columnName = null) {
        return $columnName ? $this->_dataProcessor->getErrors($columnName) : $this->_dataProcessor->getErrors();
    }

    public function addProcessRule($columnName, $ruleName, $params = array()) {
        $this->_dataProcessor->addProcessRule($columnName, $ruleName, $params);
        return $this;
    }

    public function addValidationRule($columnName, $ruleName, $params = array()) {
        $this->_dataProcessor->addValidationRule($columnName, $ruleName, $params);
        return $this;
    }

    public function getValidationRules($columnNameFor = null) {
        $rules = array();
        foreach ($this->_structure->getColumns() as $columnName => $columnInfo) {
            if ($columnNameFor && ($columnNameFor != $columnName)) continue;

            $rules[$columnName] = array();
            if (!empty($columnInfo['validation'])) {
                $rules[$columnName][0] = $columnInfo['validation'];
            }
            if (!empty($columnInfo['process'])) {
                $rules[$columnName][1] = $columnInfo['process'];
            }
            if (empty($rules[$columnName])) unset($rules[$columnName]);
        }
        return $rules;
    }

    public function save($forceSave = false) {
        if (!$this->isChanged() && !$forceSave) return true;
        $this->_preSave();

        if (!$this->validate()) return false;
        foreach($this->_dataProcessor->getData() as $columnName => $value) {
            if ($value != $this->_data[$columnName]) {
                $this->_changedData[$columnName] = $value;
            }
        }

        $dataToSave = array();
        foreach ($this->_structure->getColumns() as $column => $info) {
            if (array_key_exists($column, $this->_changedData)) {
                $dataToSave[$column] = $this->_changedData[$column];
            } elseif (array_key_exists('default', $info) && !array_key_exists($column, $this->_data)) {
                $dataToSave[$column] = $info['default'];
            } elseif ($forceSave) {
                if ($column == 'id') continue;
                $dataToSave[$column] = array_key_exists($column, $this->_data) ? $this->_data[$column] : null;
            }
        }
        $qc = QC::create($this->_tableName);
        $dataToSave = $this->getPackedData($dataToSave);
        if ($this->_isNew) {
            if (empty($dataToSave)) {
                $dataToSave = array($this->_primaryKey => null,);
            }
            $this->{$this->_primaryKey} = $qc->insert($dataToSave)->execute();
        } elseif (count($dataToSave)) {
            $qc->update($dataToSave)->where(array($this->_primaryKey => $this->{$this->_primaryKey},))->execute();
        }

        /**
         * Reloading data from DB for the newly created object
         */
        if ($this->_isNew) {
            $data = QC::create($this->_tableName)->where(array($this->_tableName . '.' . $this->_primaryKey => $this->{$this->_primaryKey},))->executeOne();
            $this->setOriginalData($data);
            $this->unpackOriginalData();
        }
        $this->_postSave();
        $this->_isNew       = false;
        $this->_changedData = array();
        return true;
    }

    protected function initializeDataProcessor() {
        if (empty(self::$_dataProcessors[$this->_name])) {
            self::$_dataProcessors[$this->_name] = new DataProcessor($this->getValidationRules());
        }
        $this->_dataProcessor = self::$_dataProcessors[$this->_name];
    }

    protected function initializeAbilities() {
        $abilities = $this->_structure->getAbilities();
        if (empty($abilities)) return true;

        foreach ($abilities as $abilityName => $abilityInfo) {
            $abilityInstance = ModelOperator::getAbilityInstanceForModel($this->_name, $abilityName);
            $abilityInstance->initialize();
        }
    }

    /**
     * @param string $relations
     */
    public function loadRelated($relations) {
        $relations = explode(',', $relations);
        $mr        = ModelRelation::getInstanceForModel($this);
        foreach ($relations as $name) {
            $mr->_loadRelated($this, $name);
        }
    }

    public function delete() {
        if ($this->isNew()) return false;
        $this->_preDelete();

        unset($this);
        return QC::create($this->_tableName)->delete(array($this->_primaryKey => $this->getID(),))->execute();
    }

    protected function preLoad($qc) {
    }

    protected function postLoad() {
    }

    protected function preSave() {
    }

    protected function postSave() {
    }

    protected function preDelete() {
    }

    private function _preLoad(QC $qc) {
        $abilities = $this->_structure->getAbilities();
        if (empty($abilities)) $abilities = array();
        foreach ($abilities as $abilityName => $abilityInfo) {
            ModelOperator::getAbilityInstanceForModel($this->_name, $abilityName)->preLoad($this, $qc);
        }
        $this->preLoad($qc);
    }

    private function _postLoad() {
        $abilities = $this->_structure->getAbilities();
        if (empty($abilities)) $abilities = array();

        foreach ($abilities as $abilityName => $abilityInfo) {
            ModelOperator::getAbilityInstanceForModel($this->_name, $abilityName)->postLoad($this);
        }

        $relations = $this->_structure->getRelations();
        if (empty($relations)) $relations = array();
        foreach($relations as $relationName => $relationInfo) {
            if (!empty($relationInfo['autoload'])) {
                $this->loadRelated($relationName);
            }
        }

        $this->postLoad();
    }

    private function _preSave() {
        $abilities = $this->_structure->getAbilities();
        if (empty($abilities)) $abilities = array();

        foreach ($abilities as $abilityName => $abilityInfo) {
            ModelOperator::getAbilityInstanceForModel($this->_name, $abilityName)->preSave($this);
        }
        $this->preSave();
    }

    private function _postSave() {
        $abilities = $this->_structure->getAbilities();
        if (empty($abilities)) $abilities = array();
        foreach ($abilities as $abilityName => $abilityInfo) {
            ModelOperator::getAbilityInstanceForModel($this->_name, $abilityName)->postSave($this);
        }
        $this->postSave();
    }

    private function _preDelete() {
        $abilities = $this->_structure->getAbilities();
        if (empty($abilities)) $abilities = array();
        foreach ($abilities as $abilityName => $abilityInfo) {
            ModelOperator::getAbilityInstanceForModel($this->_name, $abilityName)->preDelete($this);
        }
        $this->preDelete();
    }

    /**
     * Could be used for configuring model after constructor is done
     */
    protected function configure() {
    }

    public function isNew() {
        return $this->_isNew;
    }

    public function isEmpty() {
        return empty($this->_data);
    }

    public function isExists(){
        return !empty($this->_data) && !empty($this->_data[$this->_primaryKey]);
    }

    public function isChanged() {
        return count($this->_changedData) > 0;
    }

    public function getArray() {
        $res = array();
        foreach ($this->_data as $key => $value) {
            $res[$key] = is_object($value) && ($value instanceof Model || $value instanceof ModelCollection) ? $value->getArray() : $value;
        }
        return $res;
    }

    private function getCastedValue($value, $column) {
        $info = $this->_structure->getColumnInfo($column);
        if (strpos($info['type'], 'int') !== false) {
            return intval($value);
        }
        return $value;
    }

    public function getArrayCasted() {
        $res = array();
        foreach ($this->_data as $key => $value) {
            $res[$key] = is_object($value) && ($value instanceof Model || $value instanceof ModelCollection) ? $value->getArray() : $this->getCastedValue($value, $key);
        }
        return $res;
    }

    public function getChangedData($field = null) {
        if (!empty($field)) {
            return array_key_exists($field, $this->_changedData) ? $this->_changedData[$field] : null;
        } else {
            return $this->_changedData;
        }
    }

    public function clearChangedData($field = null) {
        if (!empty($field)) {
            unset($this->_changedData[$field]);
        } else {
            $this->_changedData = array();
        }
        return $this;
    }

    /**
     * @param null $what
     * @return mixed|ModelStructure
     */
    public function _getStructure($what = null) {
        if (!is_null($what)) {
            return $this->_structure->get($what);
        } else {
            return $this->_structure;
        }
    }

    public function _setCollectionReference($collectionObject) {
        $this->_collectionObjectReference = $collectionObject;
    }

    public function _hasCollectionReference() {
        return (!is_null($this->_collectionObjectReference));
    }

    public function _getCollectionReference() {
        return $this->_collectionObjectReference;
    }

    /**
     * Internal use: Get model name
     * @return null|string
     */
    public function _getName() {
        return $this->_name;
    }

    /**
     * Internal use: Set model name
     * @param $name
     */
    public function _setName($name) {
        $this->_name = $name;
    }

    public function __set($key, $value) {
        $this->offsetSet($key, $value);
    }

    public function &__get($key) {
        // if key is exists - return it
        if (array_key_exists($key, $this->_data)) return $this->_data[$key];

        $getterName = Inflector::camelize($key);
        $method     = 'get' . $getterName;
        $default    = null;

        // check for getter
        if (method_exists($this, $method) && !array_key_exists($getterName, $this->_invokedGetters)) {
            $this->_data[$key] = $this->_invokedGetters[$getterName] = $this->$method();
            return $this->_data[$key];
            // check for relation
        } elseif ($this->_structure->hasRelation($key) && !$this->_isNew) {
            $mr = ModelRelation::getInstanceForModel($this);
            $mr->_loadRelated($this, $key);
        } elseif ($methodInfo = ModelOperator::getInstanceAbilityMethod($this->_name, $method)) {
            if (empty($params)) $params = array();
            array_unshift($params, $this);
            call_user_func_array(array($methodInfo['ability'], $method,), $params);
        }
        if (array_key_exists($key, $this->_data)) {
            return $this->_data[$key];
        } else {
            return $default;
        }
    }

    public function __call($method, $params) {
        if (substr($method, -10) == 'RelatedIDs') {
            ModelRelation::getInstanceForModel($this)->$method($this, $params[0], $params[1]);
            return $this;
        } elseif (substr($method, 0, 10) == 'setRelated') {
            ModelRelation::getInstanceForModel($this)->setRelatedIDs($this, substr($method, 10), $params[0]);
            return $this;
        } elseif (substr($method, 0, 12) == 'clearRelated') {
            ModelRelation::getInstanceForModel($this)->clearRelatedIDs($this, substr($method, 12), empty($params[0]) ? array() : $params[0]);
            return $this;
        } elseif ($methodInfo = ModelOperator::getInstanceAbilityMethod($this->_name, $method)) {
            array_unshift($params, $this);
            call_user_func_array(array($methodInfo['ability'], $method,), $params);
            return $this;
        } elseif (substr($method, 0, 3) == 'set') {
            $this->offsetSet(Inflector::underscore(substr($method, 3)), $params[0]);
            return $this;
        } elseif (substr($method, 0, 3) == 'get') {
            return $this->offsetGet(Inflector::underscore(substr($method, 3)));
        }

        throw new \Exception('Undefined method for model: ' . $method);
    }

    public static function __callStatic($method, $params) {
        if ($methodInfo = ModelOperator::getStaticAbilityMethod(get_called_class(), $method)) {
            return $methodInfo['ability']->$method($params);
        }
        throw new \Exception('Undefined static method for model: ' . $method);
    }

    public function getID() {
        return array_key_exists($this->_primaryKey, $this->_data) ? $this->_data[$this->_primaryKey] : null;
    }

    public function getInternalObjectHash() {
        return $this->_internalObjectHash;
    }

    public function getIterator() {
        return new \ArrayIterator($this->_data);
    }

    public function count() {
        return count($this->_data);
    }

    public function offsetExists($offset) {
        return array_key_exists($offset, $this->_data);
    }

    public function &offsetGet($offset) {
        return $this->_data[$offset];
    }

    public function offsetSet($offset, $value) {
        if (method_exists($this, 'set' . Inflector::camelize($offset))) {
            $this->{'set' . Inflector::camelize($offset)}($value);
        }
        $this->_data[$offset]        = $value;
        $this->_changedData[$offset] = $value;
        if (array_key_exists($offset, $this->_invokedGetters)) {
            $this->_invokedGetters[$offset] = $value;
        }
    }

    public function offsetUnset($offset) {
        unset($this->_data[$offset]);
    }

}


<?php namespace Ordercloud\Entities\Connections;

use JsonSerializable;
use Ordercloud\Entities\Organisations\Organisation;

class Connection implements JsonSerializable
{
    const STATUS_CONNECTED = 'CONNECTED';
    const STATUS_DECLINED = 'DECLINED';
    const STATUS_PENDING = 'PENDING';

    /** @var integer */
    private $id;
    /** @var Organisation */
    private $fromOrganisation;
    /** @var Organisation */
    private $toOrganisation;
    /** @var ConnectionType */
    private $type;
    /** @var string */
    private $ended;
    /** @var boolean */
    private $enabled;
    /** @var string */
    private $status;
    /** @var string */
    private $settlementInterval;

    public function __construct($id, Organisation $fromOrganisation, Organisation $toOrganisation, ConnectionType $type, $ended, $enabled, $status, $settlementInterval)
    {
        $this->id = $id;
        $this->fromOrganisation = $fromOrganisation;
        $this->toOrganisation = $toOrganisation;
        $this->type = $type;
        $this->ended = $ended;
        $this->enabled = $enabled;
        $this->status = $status;
        $this->settlementInterval = $settlementInterval;
    }

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return Organisation
     */
    public function getFromOrganisation()
    {
        return $this->fromOrganisation;
    }

    /**
     * @return Organisation
     */
    public function getToOrganisation()
    {
        return $this->toOrganisation;
    }

    /**
     * @return ConnectionType
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * @return string
     */
    public function getEnded()
    {
        return $this->ended;
    }

    /**
     * @return boolean
     */
    public function isEnabled()
    {
        return $this->enabled;
    }

    /**
     * @return string
     */
    public function getStatus()
    {
        return $this->status;
    }

    /**
     * @return string
     */
    public function getSettlementInterval()
    {
        return $this->settlementInterval;
    }

    /**
     * Specify data which should be serialized to JSON
     */
    public function jsonSerialize()
    {
        return [
            'id' => $this->getId(),
            'fromOrganisation' => $this->getFromOrganisation(),
            'toOrganisation' => $this->getToOrganisation(),
            'type' => $this->getType(),
            'ended' => $this->getEnded(),
            'enabled' => $this->isEnabled(),
            'status' => $this->getStatus(),
            'settlementInterval' => $this->getSettlementInterval(),
        ];
    }
}


<?php

/*
 * This file is part of the frenzy-framework package.
 *
 * (c) Gustavo Falco <comfortablynumb84@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace IronEdge\Component\Config\Reader;

/*
 * @author Gustavo Falco <comfortablynumb84@gmail.com>
 */
use IronEdge\Component\Config\Exception\FileDoesNotExistException;
use IronEdge\Component\Config\Exception\FileIsNotReadableException;
use IronEdge\Component\Config\Exception\InvalidOptionTypeException;
use IronEdge\Component\Config\Exception\MissingOptionException;
use IronEdge\Component\FileUtils\File\Factory;

class FileReader implements ReaderInterface
{
    /**
     * Field _factory.
     *
     * @var
     */
    private $_factory;

    /**
     * Constructor.
     *
     * @param Factory|null $factory - Factory.
     */
    public function __construct(Factory $factory = null)
    {
        $this->_factory = $factory ?
            $factory :
            new Factory();
    }

    /**
     * This method reads the configuration from a file.
     *
     * @param array $options - Options.
     *
     * @throws MissingOptionException
     * @throws InvalidOptionTypeException
     * @throws FileDoesNotExistException
     * @throws FileIsNotReadableException
     *
     * @return array
     */
    public function read(array $options)
    {
        if (!isset($options['file'])) {
            throw MissingOptionException::create('file');
        }

        if (!is_string($options['file'])) {
            throw InvalidOptionTypeException::create('file', 'string');
        }

        if (!is_file($options['file'])) {
            throw FileDoesNotExistException::create($options['file']);
        }

        if (!is_readable($options['file'])) {
            throw FileIsNotReadableException::create($options['file']);
        }

        $file = $this->_factory->createInstance($options['file'], null, $options);

        return $file->getContents();
    }

}


<?php
/**
 * LoadTimezones
 */
namespace Delatbabel\Keylists\Console\Commands;

use Delatbabel\Keylists\Models\Keytype;
use Delatbabel\Keylists\Models\Keyvalue;
use Illuminate\Console\Command;

/**
 * Class LoadTimezones
 *
 * This is an example of a script to load data into the keytypes/keyvalues
 * tables from a PHP function. In this ase the function used is
 * timezone_identifiers_list() which contains the list of timezones
 * supported by PHP.
 */
class LoadTimezones extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'keylists:loadtimezones';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Load Timezone Names';

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        /** @var Keytype $keytype */
        $keytype = Keytype::create([
            'name'          => 'timezones',
            'description'   => 'Time Zones',
            'created_by'    => 'loader',
            'updated_by'    => 'loader',
        ]);

        // Get this in advance
        $count = 417;
        $bar   = $this->output->createProgressBar($count);

        $timezone_list = timezone_identifiers_list();

        foreach ($timezone_list as $timezone) {
            // Create the entry
            Keyvalue::create([
                'keytype_id'    => $keytype->id,
                'keyvalue'      => $timezone,
                'keyname'       => $timezone,
                'created_by'    => 'loader',
                'updated_by'    => 'loader',
            ]);

            // progress advance
            $bar->advance();
        }

        // Finished
        $bar->finish();
        $this->output->writeln('Finished');
    }
}


<?php

/**
* Jin Framework
* Diatem
*/

namespace Jin2\Utils;

/**
 * Boite à outils pour les opérations temporelles
 */
class TimeTools
{

  /**
   * Retourne le timestamp courant en milisecondes
   *
   * @return integer  Timestamp courant en MS
   */
  public static function getTimestampInMs()
  {
    return round(microtime(true) * 1000);
  }

  /**
   * Passe une date d'un format X à un format Y
   *
   * @param  string $date        Date quelconque
   * @param  string $fromFormat  Format d'entrée
   * @param  string $toFormat    Format de sortie
   * @return string              Date formatée
   */
  public static function fromFormatToFormat($date, $fromFormat, $toFormat)
  {
    $dt = \DateTime::createFromFormat($fromFormat, $date);
    return $dt->format($toFormat);
  }

  /**
   * Passe une date au format européen jj/mm/aaaa hh:mm:ss
   *
   * @param  string|DateTime $date      Date quelconque
   * @param  boolean         $withHour  Retourner les heures ou non
   * @return string                     Date au format européen
   */
  public static function toEuropeanFormat($date = null, $withHour = false)
  {
    if (is_string($date)) {
      $time = strtotime($date);
    } elseif (is_a($date, 'DateTime')) {
      $time = $date->getTimestamp();
    } else {
      return null;
    }
    return date('d/m/Y' . ($withHour ? ' H:i:s' : ''), $time);
  }

  /**
   * Passe une date au format américain aaaa-mm-jj hh:mm:ss
   *
   * @param  string|DateTime $date      Date quelconque
   * @param  boolean         $withHour  Retourner les heures ou non
   * @return string                     Date au format américain
   */
  public static function toAmericanFormat($date = null, $withHour = false)
  {
    if (is_string($date)) {
      $time = strtotime($date);
    } elseif (is_a($date, 'DateTime')) {
      $time = $date->getTimestamp();
    } else {
      return null;
    }
    return date('Y-m-d' . ($withHour ? ' H:i:s' : ''), $time);
  }

  /**
   * Passe une date au format HTML5 (= américain)
   *
   * @param  string|DateTime $date      Date quelconque
   * @param  boolean         $withHour  Retourner les heures ou non
   * @return string                     Date au format HTML5
   */
  public static function toHTML5Format($date = null, $withHour = false)
  {
    return static::toAmericanFormat($date, $withHour);
  }

  /**
   * Retourne TRUE si date1 est plus récente que date2
   *
   * @param  string|DateTime $date1     Date1
   * @param  string|DateTime $date2     Date2
   * @param  string          $operator  Opérateur de comparaison : =, <, <=, >=, >
   * @return boolean|null               Si TRUE : date1 > date2
   */
  public static function compare($date1, $date2, $operator = '=')
  {
    if (is_string($date1)) {
      $time1 = strtotime($date1);
    } elseif (is_a($date1, 'DateTime')) {
      $time1 = $date1->getTimestamp();
    } else {
      throw new \Exception('Format date1 invalide');
    }
    if (is_string($date2)) {
      $time2 = strtotime($date2);
    } elseif (is_a($date2, 'DateTime')) {
      $time2 = $date2->getTimestamp();
    } else {
      throw new \Exception('Format date2 invalide');
    }
    if ($operator == '=') {
      if ($time1 == $time2) {
        return true;
      }
    } else if ($operator == '>') {
      if ($time1 > $time2) {
        return true;
      }
    } else if ($operator == '<') {
      if ($time1 < $time2) {
        return true;
      }
    } else if ($operator == '>=') {
      if ($time1 >= $time2) {
        return true;
      }
    } else if ($operator == '<=') {
      if ($time1 <= $time2) {
        return true;
      }
    } else {
      throw new \Exception('Opérateur '. $operator .' non supporté');
    }
    return false;
  }

  /**
   * Retourne TRUE si $date est entre $from et $to
   *
   * @param  string|DateTime $date    Date à vérifier
   * @param  string|DateTime $from    Date de début de la plage
   * @param  string|DateTime $to      Date de fin de la plage
   * @param  boolean         $strict  (optional) TRUE pour exclure les limites
   * @return boolean                  Si TRUE : $from <(=) $date <(=) $to
   */
  public static function isBetween($date, $from, $to, $strict = false)
  {
    $operator = $strict ? '<' : '<=';
    return static::compare($from, $date, $operator) && static::compare($date, $to, $operator);
  }

  /**
   * Retourne la version littérale d'un mois
   *
   * @param  integer $month  Mois
   * @return string          Mois littéral
   */
  public static function literalMonth($month)
  {
    $month = intval($month);
    if ($month < 1 || $month > 12) {
        return '';
    }
    $months = array('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre');
    return $months[$month - 1];
  }

  /**
   * Vérifie si une date est valide
   *
   * @param  string  $date    Date
   * @param  string  $format  Format
   * @return boolean          TRUE si la date est valide
   */
  public static function validateDate($date, $format = 'Y-m-d H:i:s')
  {
    $d = \DateTime::createFromFormat($format, $date);
    return $d && $d->format($format) == $date;
  }

  /**
    * Modifie un objet DateTime en y ajoutant N jours ouvrés
    * @param DateTime  $date    Date
    * @param int       $nb      Nombre de jours ouvrés à ajouter
    * @return DateTime
    */
    public static function dateAddWorkDays(\DateTime $date, $nb)
	{
      $t = $date->getTimestamp();

      // loop for X days
      for($i=0; $i<$nb; $i++){
        // add 1 day to timestamp
        $addDay = 86400;

        // get what day it is next day
        $nextDay = date('w', ($t+$addDay));

        // if it's Saturday or Sunday get $i-1
        if($nextDay == 0 || $nextDay == 6){
          $i--;
        }

        // modify timestamp, add 1 day
        $t = $t+$addDay;
      }

      $date->setTimestamp($t);

      return $date;
    }
}


<?php namespace Mvalim\PackageUtils;

use Illuminate\Contracts\Foundation\Application;
use Mvalim\PackageUtils\Console\Publish;
use Mvalim\PackageUtils\Exceptions\PackageNotDefinedException;

class Container implements ContainerInterface {

	protected $packages = [];

	/**
	 * @var Application
	 */
	protected $app;

	/**
	 * @var Publish
	 */
	protected $command;

	public function __construct(Application $app)
	{
		$this->app = $app;

		$this->app->bindShared('package.publish', function ()
		{
			return new Publish();
		});

		$commands = [
			'package.publish'
		];

		$events = $this->app['events'];
		$events->listen('artisan.start', function ($artisan) use ($commands)
		{
			$artisan->resolveCommands($commands);
		});
	}

	/**
	 * Add a package instance to the container
	 * @param string $name
	 * @param string $namespace
	 * @return Package
	 */
	public function addPackage($name, $namespace = null)
	{
		return $this->packages[ $name ] = new Package($name, $namespace);
	}

	/**
	 * Return a given package instance
	 *
	 * @param $name
	 * @return Package
	 * @throws PackageNotDefinedException
	 */
	public function package($name)
	{
		if( ! isset($this->packages[ $name ]))
		{
			throw new PackageNotDefinedException("$name is not defined");
		}
		return $this->packages[ $name ];
	}

	/**
	 * Return an array containing all packages instances
	 *
	 * @return array
	 */
	public function getPackages()
	{
		return $this->packages;
	}

	/**
	 * Add the command instance to the container
	 *
	 * @param $command
	 */
	public function setCommand($command)
	{
		$this->command = $command;
	}

	/**
	 * Get the command instance
	 *
	 * @return Publish
	 */
	public function command()
	{
		return $this->command;
	}

}


<?php
/**
 * Helper class to facilitate dynamic content inside staticpublisher produced php files.
 *
 * @author Mark Guinn <mark@adaircreative.com>
 * @date 8.5.10
 */
class LivePubHelper extends Object
{
    protected static $is_publishing = false;

    protected static $silverstripe_db_included = false;

    /**
     * @var $vars array - each key is a variable name and value is php code to initialize it
     */
    public static $vars = array();

    /**
     * @var $init_code array - each entry is a separate block of code, reset for each page
     */
    public static $init_code = array();

    /**
     * @var $base_init_code string - constant code that is added for all pages
     */
    public static $base_init_code = '<?php
		$isAjax = (isset($_REQUEST["ajax"]) || (isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"));
	?>';

    /**
     * @var $context string - php|html - tells eval_php whether to wrap code in <?php ?> tag
     */
    public static $context = 'html';

    /**
     * @var $template_path array - where to look for php templates. initially contains /templates/php in project and theme
     */
    protected static $template_path = array();

    /**
     * this is only to be called when static publishing is starting
     */
    public static function init_pub()
    {
        global $project;

        self::$is_publishing = true;

        // if we've set up a global static configuration, add that in
        $file = BASE_PATH . '/' . $project . '/_config_static.php';
        if (file_exists($file) && strpos(self::$base_init_code, $file) === false) {
            self::$base_init_code .= "\n<?php include_once('$file') ?>\n";
        }
    }

    /**
     * called when publishing is done
     */
    public static function stop_pub()
    {
        self::$is_publishing = false;
    }

    /**
     * resets the init code to the base config file
     */
    public static function clear_init_code()
    {
        self::$init_code = array();
        self::$vars = array();
        self::$silverstripe_db_included = false;
        if (self::$base_init_code) {
            array_unshift(self::$init_code, self::$base_init_code);
        }
    }

    /**
     * Outputs the static config code if needed. This should be placed in a function in Page_Controller and called from template.
     */
    public static function get_init_code()
    {
        if (self::is_publishing()) {
            $code = "";

            // if objects have set up initialization code, add that in
            foreach (self::$init_code as $block) {
                $block = trim($block);
                if (strlen($block) == 0) {
                    continue;
                }
                if (substr($block, 0, 5) != '<?php') {
                    $code .= '<?php ';
                }
                $code .= $block;
                if (substr($block, -2) != '?>') {
                    $code .= ' ?>';
                }
                $code .= "\n";
            }

            // if there are variables to initialize, add that in
            if (count(self::$vars) > 0) {
                $code .= "\n<?php\n";
                foreach (self::$vars as $var => $valCode) {
                    if ($valCode === true) {
                        continue;
                    } // this means it was already set in the initialization
                    $code .= '$' . $var . ' = ' . $valCode . ";\n";
                }
                $code .= "\n?>\n";
            }

            return $code;
        }
    }

    /**
     * @param string $code
     * @param string $id [optional] - if present, this prevents the same code from being added twice
     */
    public static function add_init_code($code, $id = null)
    {
        if ($id) {
            self::$init_code[$id] = $code;
        } else {
            self::$init_code[] = $code;
        }
    }

    /**
     * @return string
     */
    public static function get_init_code_and_clear()
    {
        $code = self::get_init_code();
        self::clear_init_code();
        return $code;
    }

    /**
     * returns true if we are currently publishing
     * @return boolean
     */
    public static function is_publishing()
    {
        // this will break if you ever turned off $echo_progress on purpose
        //return class_exists('StaticPublisher') && StaticPublisher::$echo_progress;
        return self::$is_publishing;
    }

    /**
     * evaluates the given php code unless we're currently publishing, in which case it
     * returns php code that will echo the return value of the eval'd code.
     *
     * @param string $code
     * @return string
     */
    public static function eval_php($code)
    {
        if (self::is_publishing()) {
            return self::$context=='html'
                ? '<?php echo eval(\'' . addcslashes($code, "'") . '\'); ?>'
                : 'eval(\'' . addcslashes($code, "'") . '\')';
        } else {
            return eval($code);
        }
    }

    /**
     * evaluates the given php code unless we're currently publishing, in which case it
     * adds the php code to the initialization code.
     * NOTE: this will not return or output the result
     *
     * @param string $code
     * @param bool   $alwaysExec
     * @return none
     */
    public static function exec_php($code, $alwaysExec=false)
    {
        if (self::is_publishing()) {
            self::$init_code[] = $code;
            if ($alwaysExec) {
                eval($code);
            }
        } else {
            eval($code);
        }
    }

    /**
     * loads a php template from the templates/php folder (allowing for themes)
     * returns either the result of executing the code, or the code itself,
     * depending on whether we're staticpublishing or not
     *
     * @param string $filename
     * @throws Exception
     * @return string
     */
    public static function include_php($filename)
    {
        // set up default template paths if needed
        if (count(self::$template_path) == 0) {
            self::init_template_paths();
        }

        // check all the possible paths we've accumulated
        $tpl = false;
        foreach (self::$template_path as $path) {
            $checkPath = $path . '/' . $filename . '.php';

            if (file_exists($checkPath)) {
                $tpl = $checkPath;
                break;
            }
        }

        if (!$tpl) {
            throw new Exception("Unable to locate PHP template: $filename (paths=".implode(':', self::$template_path).")");
        }

        // load it up
        if (self::is_publishing()) {
            //return file_get_contents($tpl);
            return '<?php include "' . $tpl . '"; ?>';
        } else {
            ob_start();
            include $tpl;
            $html = ob_get_contents();
            ob_end_clean();
            //return '<!-- php template -->' . $html . '<!-- end php template -->';
            return $html;
        }
    }

    /**
     * Sets up the default template paths
     */
    protected static function init_template_paths()
    {
        global $project;
        self::$template_path = array();
        self::$template_path[] = BASE_PATH . '/' . SSViewer::get_theme_folder() . '/templates/php';
        self::$template_path[] = BASE_PATH . '/' . $project . '/templates/php';
    }

    /**
     * @param array $paths
     */
    public static function set_template_paths(array $paths)
    {
        self::$template_path = $paths;
    }

    /**
     * Path should be relative to BASE_PATH
     * @param string $path
     */
    public static function add_template_path($path)
    {
        if (!isset(self::$template_path) || empty(self::$template_path)) {
            self::init_template_paths();
        }
        if ($path[0] != '/') {
            $path = BASE_PATH . '/' . $path;
        }
        self::$template_path[] = rtrim($path, '/');
    }

    /**
     * factory method to create a new wrapper object. if we're
     * static publishing and an appropriate helper class is
     * available it will use that instead. A helper class shouldn't
     * be needed very often but would be used if you wanted a totally
     * different class for publishing vs normal mode
     *
     * @param object|array $object
     * @param string $class - what class to wrap it in
     * @param boolean $add_init_code [optional] - if true, the classes default static init code will be added automatically
     * @return ViewableWrapper
     */
    public static function wrap($object, $class = 'ViewableWrapper', $add_init_code=true)
    {
        if (self::is_publishing()) {
            $class2 = "{$class}_LivePub";
            if (class_exists($class2, true)) {
                $class = $class2;
            }

            $obj = new $class($object);
            if ($add_init_code && ($init = $obj->getStaticInit())) {
                self::$init_code[] = $init;
            }
        } else {
            $obj = new $class($object);
        }

        return $obj;
    }

    /**
     * Takes an array of objects or arrays and creates a dataobjectset,
     * calling {@link LivePubHelper::wrap} on each item in the array.
     *
     * @static
     * @param array $list
     * @param string $class [optional] - default is 'ViewableWrapper'
     * @param string $exclude [optional] - filter set by excluding these values
     * @param string $exclude_field [optional] - field to filter by
     * @return DataObjectSet
     */
    public static function wrap_set(array $list, $class = 'ViewableWrapper', $exclude=null, $exclude_field=null)
    {
        $set = new DataObjectSet();

        foreach ($list as $r) {
            $obj = self::wrap($r, $class);
            if ($exclude && in_array($obj->getField($exclude_field), $exclude)) {
                continue;
            }
            $set->push($obj);
        }

        return $set;
    }

    /**
     * if this is called, the published version of the page
     * will include and initialize the DB::query stub
     * and connect to the main silverstripe database.
     * This allows limited use of DB::query() in both a live
     * and published context.
     */
    public static function require_silverstripe_db()
    {
        global $databaseConfig;
        if (self::is_publishing() && !self::$silverstripe_db_included) {
            self::$silverstripe_db_included = true;
            self::$init_code[] = '
				$databaseConfig = '.var_export($databaseConfig, true).';
				require_once "'.dirname(dirname(__FILE__)).'/dummy_classes/LivePubDB.php";
				DB::init();
			';
        }
    }

    /**
     * Ensures that the session will be available on the published page.
     */
    public static function require_session()
    {
        self::add_init_code('if (!session_id()) session_start();', 'require_session');
    }
}


<?php

namespace Think;

/**
 * 引导类
 */
final class Think
{

    /**
     * @var string 版本号
     */
    const VERSION = '3.2.3-CheungPang';

    /**
     * 应用程序初始化

     * @return void
     */
    public static function init()
    {
        /*
         * 设定错误和异常处理
         */
//        register_shutdown_function([__CLASS__, 'fatalError']);
//        set_error_handler([__CLASS__, 'appError']);

        /*
         * 初始化文件存储方式
         */
        Storage::connect();

        /**
         * 检查核心必须文件
         */
        if (!Storage::has(__DIR__.'/../Conf/core.php') ||
            !Storage::has(__DIR__.'/../Conf/config.php') ||
            !Storage::has(__DIR__.'/../Conf/tags.php')
        ) {
            static::halt('系统核心文件缺失');
        }
        /*
         * 加载核心文件
         */
        $mode = include __DIR__.'/../Conf/core.php';
        foreach ($mode as $file) {
            if (is_file($file)) {
                /** @noinspection PhpIncludeInspection */
                include $file;
            }
        }

        /*
         * 加载应用模式配置文件
         */
        $config = include __DIR__.'/../Conf/config.php';
        foreach ($config as $key => $file) {
            is_numeric($key) ? C(load_config($file)) : C($key, load_config($file));
        }

        /*
         * 加载模式行为定义
         */
        $tags = include __DIR__.'/../Conf/tags.php';
        if (isset($tags)) {
            is_array($tags) && Hook::import($tags);
        }

        /*
         * 加载应用行为
         */
        if (is_file(CONF_PATH.'tags.php')) {
            $appBehaviors = include CONF_PATH.'tags.php';
            is_array($appBehaviors) && Hook::import($appBehaviors);
        }

        /*
         * 加载框架底层语言包
         */
        L(include __DIR__.'/../Lang/'.C('DEFAULT_LANG').'.php');

        if (APP_DEBUG) {
            // 调试模式加载系统默认的配置文件
            C(include __DIR__.'/../Conf/debug.php');
            // 读取应用调试配置文件
            if (is_file(CONF_PATH.'debug.php')) {
                C(include CONF_PATH.'debug.php');
            }
        }

        /*
         * 设置系统时区
         * @todo move to other place
         */
        date_default_timezone_set(C('DEFAULT_TIMEZONE'));

        /*
         * 记录加载文件时间
         */
        G('loadTime');

    }

    /**
     * 自定义错误处理
     * @deprecated
     *
     * @param int $errNo 错误类型
     * @param string $errStr 错误信息
     * @param string $errFile 错误文件
     * @param int $errLine 错误行数
     *
     * @return void
     */
//    public static function appError($errNo, $errStr, $errFile, $errLine)
//    {
//        switch ($errNo) {
//            case E_ERROR:
//            case E_PARSE:
//            case E_CORE_ERROR:
//            case E_COMPILE_ERROR:
//            case E_USER_ERROR:
//                ob_end_clean();
//                $errorStr = "$errStr ".$errFile." 第 $errLine 行.";
//                static::halt($errorStr);
//                break;
//            default:
//                $errorStr = "[$errNo] $errStr ".$errFile." 第 $errLine 行.";
//                static::trace($errorStr, '', 'NOTIC');
//                break;
//        }
//    }

    /**
     * 致命错误捕获
     * @deprecated
     */
//    public static function fatalError()
//    {
//        if ($e = error_get_last()) {
//            switch ($e['type']) {
//                case E_ERROR:
//                case E_PARSE:
//                case E_CORE_ERROR:
//                case E_COMPILE_ERROR:
//                case E_USER_ERROR:
//                    ob_end_clean();
//                    static::halt($e);
//                    break;
//                default:
//                    break;
//            }
//        }
//    }

    /**
     * 错误输出
     *
     * @param mixed $error 错误
     *
     * @return void
     */
    public static function halt($error)
    {
        $e = [];
        if (APP_DEBUG || IS_CLI) {
            //调试模式下输出错误信息
            if (!is_array($error)) {
                $trace = debug_backtrace();
                $e['message'] = $error;
                $e['file'] = $trace[0]['file'];
                $e['line'] = $trace[0]['line'];
                ob_start();
                debug_print_backtrace();
                $e['trace'] = ob_get_clean();
            } else {
                $e = $error;
            }
            if (IS_CLI) {
                echo iconv(
                        'UTF-8',
                        'gbk',
                        $e['message']
                    ).PHP_EOL.'FILE: '.$e['file'].'('.$e['line'].')'.PHP_EOL.$e['trace'];

                return;
            }
        } else {
            //否则定向到错误页面
            $error_page = C('ERROR_PAGE');
            if (!empty($error_page)) {
                redirect($error_page);
            } else {
                $message = is_array($error) ? $error['message'] : $error;
                $e['message'] = C('SHOW_ERROR_MSG') ? $message : C('ERROR_MESSAGE');
            }
        }
        // 包含异常页面模板
        $exceptionFile = C('TMPL_EXCEPTION_FILE', null, C('TMPL_EXCEPTION_FILE'));
        /** @noinspection PhpIncludeInspection */
        include $exceptionFile;
        return;
    }

    /**
     * 添加和获取页面Trace记录
     *
     * @param string $value 变量
     * @param string $label 标签
     * @param string $level 日志级别(或者页面Trace的选项卡)
     * @param bool $record 是否记录日志
     *
     * @return array
     */
    public static function trace($value = '[think]', $label = '', $level = 'DEBUG', $record = false)
    {
        static $_trace = [];
        // 获取trace信息
        if ('[think]' === $value) {
            return $_trace;
        } else {
            $info = ($label ? $label.':' : '').print_r($value, true);
            $level = strtoupper($level);

            if ((defined('IS_AJAX') && IS_AJAX) || !C('SHOW_PAGE_TRACE') || $record) {
                Log::record($info, $level, $record);
            } else {
                if (!isset($_trace[$level]) || count($_trace[$level]) > C('TRACE_MAX_RECORD')) {
                    $_trace[$level] = [];
                }
                $_trace[$level][] = $info;
            }
        }
    }

    /**
     * 禁止clone对象
     */
    public function __clone()
    {
        trigger_error('Cloning '.__CLASS__.' is not allowed.', E_USER_ERROR);
    }

    /**
     * 禁止反序列化对象
     */
    public function __wakeup()
    {
        trigger_error('Unserializing '.__CLASS__.' is not allowed.', E_USER_ERROR);
    }
}


<?php

namespace Reaction\Db;

use React\Promise\PromiseInterface;
use Reaction\Base\BaseObject;
use Reaction\Db\Constraints\CheckConstraint;
use Reaction\Db\Constraints\Constraint;
use Reaction\Db\Constraints\DefaultValueConstraint;
use Reaction\Db\Constraints\ForeignKeyConstraint;
use Reaction\Db\Constraints\IndexConstraint;
use Reaction\Exceptions\NotSupportedException;
use Reaction\Promise\ExtendedPromiseInterface;
use function Reaction\Promise\all;
use function Reaction\Promise\reject;
use function Reaction\Promise\resolve;

/**
 * Class Schema
 * @package Reaction\Db
 * @method  getViewNames(string $schema = "", bool $refresh = false)
 */
class Schema extends BaseObject implements SchemaInterface
{
    /**
     * Schema cache version, to detect incompatibilities in cached values when the
     * data format of the cache changes.
     */
    const SCHEMA_CACHE_VERSION = 1;

    /**
     * @var DatabaseInterface
     */
    public $db;
    /**
     * @var string the default schema name used for the current session.
     */
    public $defaultSchema;
    /**
     * @var array Table metadata type those are implemented by driver
     */
    public $tableMetaImplemented = [
        self::META_SCHEMA,
        self::META_PK,
        self::META_FK,
        self::META_INDEXES,
        self::META_UNIQUES,
        self::META_CHECKS,
        self::META_DEFAULTS,
    ];

    /**
     * @var array list of ALL schema names in the database, except system schemas
     */
    protected $_schemaNames;
    /**
     * @var array list of ALL table names in the database
     */
    protected $_tableNames = [];
    /**
     * @var array list of all table metadata in the database for sync usage
     */
    protected $_tableMetadata = [];
    /**
     * @var string|string[] character used to quote schema, table, etc. names.
     * An array of 2 characters can be used in case starting and ending characters are different.
     */
    protected $tableQuoteCharacter = "'";
    /**
     * @var string|string[] character used to quote column names.
     * An array of 2 characters can be used in case starting and ending characters are different.
     */
    protected $columnQuoteCharacter = '"';
    /**
     * @var string server version as a string.
     */
    protected $_serverVersion;
    /**
     * @var QueryBuilderInterface DB query builder
     */
    protected $_builder;

    /**
     * Refreshes the schema.
     * This method cleans up all cached table schemas so that they can be re-created later
     * to reflect the database schema change.
     * @return ExtendedPromiseInterface when finished
     */
    public function refresh()
    {
        return $this->refreshTablesMetadata();
    }

    /**
     * @return QueryBuilderInterface the query builder for this connection.
     */
    public function getQueryBuilder()
    {
        if ($this->_builder === null) {
            $this->_builder = $this->createQueryBuilder();
        }

        return $this->_builder;
    }

    /**
     * Creates a query builder for the database.
     * This method may be overridden by child classes to create a DBMS-specific query builder.
     * @return QueryBuilderInterface query builder instance
     */
    public function createQueryBuilder()
    {
        return new QueryBuilder(['db' => $this->db]);
    }

    /**
     * Create a column schema builder instance giving the type and value precision.
     *
     * This method may be overridden by child classes to create a DBMS-specific column schema builder.
     *
     * @param string $type type of the column. See [[ColumnSchemaBuilder::$type]].
     * @param int|string|array $length length or precision of the column. See [[ColumnSchemaBuilder::$length]].
     * @return ColumnSchemaBuilder column schema builder instance
     */
    public function createColumnSchemaBuilder($type, $length = null)
    {
        return new ColumnSchemaBuilder($type, $length);
    }

    /**
     * Returns a server version as a string comparable by [[\version_compare()]].
     * @return string server version as a string.
     */
    public function getServerVersion()
    {
        throw new NotSupportedException(get_class($this) . ' does not support version obtaining.');
    }

    /**
     * @return bool whether this DBMS supports [savepoint](http://en.wikipedia.org/wiki/Savepoint).
     */
    public function supportsSavepoint()
    {
        return $this->db->enableSavepoint;
    }

    /**
     * Obtains the metadata for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool $refresh whether to reload the table schema even if it is found in the cache.
     * @return TableSchema|null table metadata. `null` if the named table does not exist.
     */
    public function getTableSchema($name, $refresh = false)
    {
        return $this->getTableMetadata($name, 'schema', $refresh);
    }

    /**
     * Obtains the metadata for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool $refresh whether to reload the table schema even if it is found in the cache.
     * @return ExtendedPromiseInterface with TableSchema table metadata. `null` if the named table does not exist.
     */
    public function getTableSchemaAsync($name, $refresh = false) {
        return $this->getTableMetadataRaw($name, 'schema', $refresh);
    }

    /**
     * Returns the metadata for all tables in the database.
     * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema name.
     * @param bool $refresh whether to fetch the latest available table schemas. If this is `false`,
     * cached data may be returned if available.
     * @return ExtendedPromiseInterface with TableSchema[] the metadata for all tables in the database.
     * Each array element is an instance of [[TableSchema]] or its child class.
     */
    public function getTableSchemas($schema = '', $refresh = false)
    {
        return $this->getSchemaMetadata($schema, 'schema', $refresh);
    }

    /**
     * Returns all schema names in the database, except system schemas.
     * @param bool $refresh whether to fetch the latest available schema names. If this is false,
     * schema names fetched previously (if available) will be returned.
     * @return ExtendedPromiseInterface with string[] all schema names in the database, except system schemas.
     */
    public function getSchemaNames($refresh = false)
    {
        if ($this->_schemaNames === null || $refresh) {
            return $this->findSchemaNames()->then(
                function($names) use($refresh) {
                    $this->_schemaNames = $names;
                    return $names;
                }
            );
        }

        return resolve($this->_schemaNames);
    }

    /**
     * Returns all table names in the database.
     * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema name.
     * If not empty, the returned table names will be prefixed with the schema name.
     * @param bool   $refresh whether to fetch the latest available table names. If this is false,
     * table names fetched previously (if available) will be returned.
     * @return ExtendedPromiseInterface with string[] all table names in the database.
     */
    public function getTableNames($schema = '', $refresh = false)
    {
        if (!isset($this->_tableNames[$schema]) || $refresh) {
            return $this->findTableNames($schema)->then(
                function($names) use ($schema) {
                    $this->_tableNames[$schema] = $names;
                    return $names;
                }
            );
        }

        return resolve($this->_tableNames[$schema]);
    }

    /**
     * Resolves the table name and schema name (if any).
     * @param string $name the table name
     * @return TableSchema [[TableSchema]] with resolved table, schema, etc. names.
     */
    protected function resolveTableName($name)
    {
        throw new NotSupportedException(get_class($this) . ' does not support resolving table names.');
    }

    /**
     * Returns all schema names in the database, including the default one but not system schemas.
     * This method should be overridden by child classes in order to support this feature
     * because the default implementation simply throws an exception.
     * @return ExtendedPromiseInterface with array all schema names in the database, except system schemas.
     */
    protected function findSchemaNames()
    {
        throw new NotSupportedException(get_class($this) . ' does not support fetching all schema names.');
    }

    /**
     * Returns all table names in the database.
     * This method should be overridden by child classes in order to support this feature
     * because the default implementation simply throws an exception.
     * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
     * @return ExtendedPromiseInterface with array all table names in the database. The names have NO schema name prefix.
     */
    protected function findTableNames($schema = '')
    {
        throw new NotSupportedException(get_class($this) . ' does not support fetching all table names.');
    }

    /**
     * Quotes a string value for use in a query.
     * Note that if the parameter is not a string, it will be returned without change.
     * @param string $str string to be quoted
     * @return string the properly quoted string
     * @see http://www.php.net/manual/en/function.PDO-quote.php
     */
    public function quoteValue($str)
    {
        return "'" . addcslashes(str_replace("'", "''", $str), "\000\n\r\\\032") . "'";
    }

    /**
     * Quotes a table name for use in a query.
     * If the table name contains schema prefix, the prefix will also be properly quoted.
     * If the table name is already quoted or contains '(' or '{{',
     * then this method will do nothing.
     * @param string $name table name
     * @return string the properly quoted table name
     * @see quoteSimpleTableName()
     */
    public function quoteTableName($name)
    {
        if (strpos($name, '(') !== false || strpos($name, '{{') !== false) {
            return $name;
        }
        if (strpos($name, '.') === false) {
            return $this->quoteSimpleTableName($name);
        }
        $parts = explode('.', $name);
        foreach ($parts as $i => $part) {
            $parts[$i] = $this->quoteSimpleTableName($part);
        }

        return implode('.', $parts);
    }

    /**
     * Quotes a column name for use in a query.
     * If the column name contains prefix, the prefix will also be properly quoted.
     * If the column name is already quoted or contains '(', '[[' or '{{',
     * then this method will do nothing.
     * @param string $name column name
     * @return string the properly quoted column name
     * @see quoteSimpleColumnName()
     */
    public function quoteColumnName($name)
    {
        if (strpos($name, '(') !== false || strpos($name, '[[') !== false) {
            return $name;
        }
        if (($pos = strrpos($name, '.')) !== false) {
            $prefix = $this->quoteTableName(substr($name, 0, $pos)) . '.';
            $name = substr($name, $pos + 1);
        } else {
            $prefix = '';
        }
        if (strpos($name, '{{') !== false) {
            return $name;
        }

        return $prefix . $this->quoteSimpleColumnName($name);
    }

    /**
     * Quotes a simple table name for use in a query.
     * A simple table name should contain the table name only without any schema prefix.
     * If the table name is already quoted, this method will do nothing.
     * @param string $name table name
     * @return string the properly quoted table name
     */
    public function quoteSimpleTableName($name)
    {
        if (is_string($this->tableQuoteCharacter)) {
            $startingCharacter = $endingCharacter = $this->tableQuoteCharacter;
        } else {
            list($startingCharacter, $endingCharacter) = $this->tableQuoteCharacter;
        }
        return strpos($name, $startingCharacter) !== false ? $name : $startingCharacter . $name . $endingCharacter;
    }

    /**
     * Quotes a simple column name for use in a query.
     * A simple column name should contain the column name only without any prefix.
     * If the column name is already quoted or is the asterisk character '*', this method will do nothing.
     * @param string $name column name
     * @return string the properly quoted column name
     */
    public function quoteSimpleColumnName($name)
    {
        if (is_string($this->tableQuoteCharacter)) {
            $startingCharacter = $endingCharacter = $this->columnQuoteCharacter;
        } else {
            list($startingCharacter, $endingCharacter) = $this->columnQuoteCharacter;
        }
        return $name === '*' || strpos($name, $startingCharacter) !== false ? $name : $startingCharacter . $name . $endingCharacter;
    }

    /**
     * Unquotes a simple table name.
     * A simple table name should contain the table name only without any schema prefix.
     * If the table name is not quoted, this method will do nothing.
     * @param string $name table name.
     * @return string unquoted table name.
     */
    public function unquoteSimpleTableName($name)
    {
        if (is_string($this->tableQuoteCharacter)) {
            $startingCharacter = $this->tableQuoteCharacter;
        } else {
            $startingCharacter = $this->tableQuoteCharacter[0];
        }
        return strpos($name, $startingCharacter) === false ? $name : substr($name, 1, -1);
    }

    /**
     * Unquotes a simple column name.
     * A simple column name should contain the column name only without any prefix.
     * If the column name is not quoted or is the asterisk character '*', this method will do nothing.
     * @param string $name column name.
     * @return string unquoted column name.
     */
    public function unquoteSimpleColumnName($name)
    {
        if (is_string($this->columnQuoteCharacter)) {
            $startingCharacter = $this->columnQuoteCharacter;
        } else {
            $startingCharacter = $this->columnQuoteCharacter[0];
        }
        return strpos($name, $startingCharacter) === false ? $name : substr($name, 1, -1);
    }

    /**
     * Returns the actual name of a given table name.
     * This method will strip off curly brackets from the given table name
     * and replace the percentage character '%' with [[Connection::tablePrefix]].
     * @param string $name the table name to be converted
     * @return string the real name of the given table name
     */
    public function getRawTableName($name)
    {
        if (strpos($name, '{{') !== false) {
            $name = preg_replace('/\\{\\{(.*?)\\}\\}/', '\1', $name);

            return str_replace('%', $this->db->tablePrefix, $name);
        }

        return $name;
    }

    /**
     * Refresh table schema
     * @param string $tableName
     * @param bool   $nameIsRaw
     * @return ExtendedPromiseInterface
     */
    public function refreshTableSchema($tableName, $nameIsRaw = false) {
        return $this->refreshTableMetadata($tableName, $nameIsRaw);
    }

    /**
     * Refresh table schema, indexes, primary key and other metadata
     * @param string $tableName
     * @param bool   $nameIsRaw
     * @return ExtendedPromiseInterface
     */
    public function refreshTableMetadata($tableName, $nameIsRaw = false) {
        $rawName = $nameIsRaw ? $tableName : $this->getRawTableName($tableName);
        $metaTypes = $this->tableMetaImplemented;
        if (isset($this->_tableMetadata[$rawName])) {
            unset($this->_tableMetadata[$rawName]);
        }
        foreach ($metaTypes as $metaType) {
            $promises[] = $this->getTableMetadataRaw($rawName, $metaType, true)->otherwise(function() { return true; });
        }
        return !empty($promises) ? all($promises) : resolve(true);
    }

    /**
     * Executes the INSERT command, returning primary key values.
     * @param string                   $table the table that new rows will be inserted into.
     * @param array                    $columns the column data (name => value) to be inserted into the table.
     * @param ConnectionInterface|null $connection
     * @return ExtendedPromiseInterface with array|false primary key values or false if the command fails
     */
    public function insert($table, $columns, $connection = null)
    {
        $command = $this->db->createCommand()->insert($table, $columns);
        if (isset($connection)) {
            $command->setConnection($connection);
        }
        return $command->execute()->then(
            function() use ($table, $columns) {
                $tableSchema = $this->getTableSchema($table);
                $result = [];
                foreach ($tableSchema->primaryKey as $name) {
                    if ($tableSchema->columns[$name]->autoIncrement) {
                        $result[$name] = $this->getLastInsertID($tableSchema->sequenceName);
                        break;
                    }

                    $result[$name] = isset($columns[$name]) ? $columns[$name] : $tableSchema->columns[$name]->defaultValue;
                }

                return $result;
            }
        );
    }

    /**
     * Get last inserted ID
     * NOT SUPPORTED!
     * @param string $sequenceName
     * @return null
     */
    public function getLastInsertID($sequenceName = '') {
        return null;
    }

    /**
     * Get table metadata
     * @param string $name
     * @param string $type
     * @param bool   $refresh
     * @return TableSchema|Constraint|Constraint[]|IndexConstraint[]|ForeignKeyConstraint[]|DefaultValueConstraint[]|CheckConstraint[]|null
     */
    protected function getTableMetadata($name, $type = self::META_SCHEMA, $refresh = false)
    {
        $rawName = $this->getRawTableName($name);
        if ($refresh) {
            $this->getTableMetadataRaw($rawName, $type, true);
        }
        if (isset($this->_tableMetadata[$rawName][$type])) {
            return $this->_tableMetadata[$rawName][$type];
        }
        return null;
    }

    /**
     * @param string $name
     * @param string $type
     * @param bool   $refresh
     * @return ExtendedPromiseInterface
     * @deprecated Old async function
     */
    protected function getTableMetadataAsync($name, $type, $refresh = false)
    {
        $rawName = $this->getRawTableName($name);
        $metadata = $this->getTableMetadata($name, $type);
        if ($metadata === null || $refresh) {
            return $this->getTableMetadataRaw($rawName, $type, true);
        }
        return resolve($metadata);
    }

    /**
     * Get table metadata from DB
     * @param string $name
     * @param string $type
     * @param bool   $refresh
     * @return ExtendedPromiseInterface
     */
    protected function getTableMetadataRaw($name, $type, $refresh = false)
    {
        /** @var ExtendedPromiseInterface $promise */
        $promise = $this->{'loadTable' . ucfirst($type)}($name);
        if ($refresh) {
            $promise->then(function($data) use ($name, $type) {
                $this->_tableMetadata[$name] = isset($this->_tableMetadata[$name]) ? $this->_tableMetadata[$name] : [];
                $this->_tableMetadata[$name][$type] = $data;
                return $data;
            });
        }
        return $promise;
    }

    /**
     * Returns the metadata of the given type for all tables in the given schema.
     * This method will call a `'getTable' . ucfirst($type)` named method with the table name
     * and the refresh flag to obtain the metadata.
     * @param string $schema the schema of the metadata. Defaults to empty string, meaning the current or default schema name.
     * @param string $type metadata type.
     * @param bool $refresh whether to fetch the latest available table metadata. If this is `false`,
     * cached data may be returned if available.
     * @return ExtendedPromiseInterface with array array of metadata.
     */
    protected function getSchemaMetadata($schema, $type, $refresh)
    {
        return $this->getTableNames($schema, $refresh)->then(
            function($names) use($schema, $type, $refresh) {
                $metadata = [];
                $metaPromises = [];
                $methodName = 'getTable' . ucfirst($type);
                if (method_exists($this, $methodName . 'Async')) {
                    $methodName .= 'Async';
                }
                foreach ($names as $name) {
                    if ($schema !== '') {
                        $name = $schema . '.' . $name;
                    }
                    /** @var ExtendedPromiseInterface $metaPromise */
                    $metaPromise = $this->$methodName($name, $refresh);
                    $metaPromise->then(
                        function($tableMetadata) use(&$metadata) {
                            if ($tableMetadata !== null) {
                                $metadata[] = $tableMetadata;
                            }
                        },
                        function() { return null; }
                    );
                    $metaPromises[] = $metaPromise;
                }
                return all($metaPromises)
                    ->then(function() use (&$metadata) {
                        return $metadata;
                    });
            }
        );
    }

    /**
     * Sets the metadata of the given type for the given table.
     * @param string $name table name.
     * @param string $type metadata type.
     * @param mixed $data metadata.
     */
    protected function setTableMetadata($name, $type, $data)
    {
        $rawName = $this->getRawTableName($name);
        $this->_tableMetadata[$rawName] = isset($this->_tableMetadata[$rawName]) ? $this->_tableMetadata[$rawName] : [];
        $this->_tableMetadata[$rawName][$type] = $data;
    }

    /**
     * Loads the metadata for the specified table.
     * @param string $name table name
     * @return TableSchema|null DBMS-dependent table metadata, `null` if the table does not exist.
     * @throws NotSupportedException
     */
    protected function loadTableSchema($name)
    {
        throw new NotSupportedException("Loading table schema is not supported by this DB");
    }

    /**
     * Resolves the table name and schema name (if any).
     * @param TableSchema $table the table metadata object
     * @param string      $name the table name
     * @throws NotSupportedException
     */
    protected function resolveTableNames($table, $name)
    {
        throw new NotSupportedException(get_class($this) . ' does not support resolving all table names.');
    }

    /**
     * Loads the column information into a [[ColumnSchema]] object.
     * @param array $info column information
     * @return ColumnSchema the column schema object
     * @throws NotSupportedException
     */
    protected function loadColumnSchema($info)
    {
        throw new NotSupportedException(get_class($this) . ' does not support loading column schema');
    }

    /**
     * Creates a column schema for the database.
     * This method may be overridden by child classes to create a DBMS-specific column schema.
     * @return ColumnSchemaInterface column schema instance.
     */
    protected function createColumnSchema()
    {
        return $this->db->createColumnSchema();
    }

    /**
     * Extracts the PHP type from abstract DB type.
     * @param ColumnSchema $column the column schema information
     * @return string PHP type name
     */
    protected function getColumnPhpType($column)
    {
        static $typeMap = [
            // abstract type => php type
            self::TYPE_TINYINT => 'integer',
            self::TYPE_SMALLINT => 'integer',
            self::TYPE_INTEGER => 'integer',
            self::TYPE_BIGINT => 'integer',
            self::TYPE_BOOLEAN => 'boolean',
            self::TYPE_FLOAT => 'double',
            self::TYPE_DOUBLE => 'double',
            self::TYPE_BINARY => 'resource',
            self::TYPE_JSON => 'array',
        ];
        if (isset($typeMap[$column->type])) {
            if ($column->type === 'bigint') {
                return PHP_INT_SIZE === 8 && !$column->unsigned ? 'integer' : 'string';
            } elseif ($column->type === 'integer') {
                return PHP_INT_SIZE === 4 && $column->unsigned ? 'string' : 'integer';
            }

            return $typeMap[$column->type];
        }

        return 'string';
    }

    /**
     * Returns the cache key for the specified table name.
     * @param string $name the table name.
     * @return mixed the cache key.
     */
    protected function getCacheKey($name)
    {
        return [
            __CLASS__,
            $this->db->getDsn(),
            $this->db->username,
            $this->getRawTableName($name),
        ];
    }

    /**
     * Returns the cache tag name.
     * This allows [[refresh()]] to invalidate all cached table schemas.
     * @return string the cache tag name
     */
    protected function getCacheTag()
    {
        return md5(serialize([
            __CLASS__,
            $this->db->getDsn(),
            $this->db->username,
        ]));
    }

    /**
     * Get server version promised
     * @return ExtendedPromiseInterface
     */
    protected function getServerVersionPromised() {
        return resolve(null);
    }

    /**
     * Refresh table schemas in cache and $_tableSchemas
     * @param string $schema
     * @return ExtendedPromiseInterface
     */
    protected function refreshTablesMetadata($schema = '') {
        $schema = $schema !== '' ? $schema : $this->defaultSchema;
        $metaTypes = $this->tableMetaImplemented;
        return $this->getTableNames($schema, true)->then(
            function($names) use ($metaTypes) {
                $promises = [];
                $this->_tableMetadata = [];
                foreach ($names as $name) {
                    $promises[] = $this->refreshTableMetadata($name, true);
                }
                return !empty($promises) ? all($promises) : resolve(true);
            }
        );
    }

    /**
     * Init component
     * @return ExtendedPromiseInterface
     */
    public function initComponent()
    {
        $promises = [];
        $promises[] = $this->getServerVersionPromised()->otherwise(function() { return false; });
        $promises[] = $this->refreshTablesMetadata();
        return all($promises);
    }

    /**
     * Obtains the primary key for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool   $refresh whether to reload the information even if it is found in the cache.
     * @return Constraint|null table primary key, `null` if the table has no primary key.
     */
    public function getTablePrimaryKey($name, $refresh = false)
    {
        throw new NotSupportedException(get_class($this) . ' does not support loading primary key');
    }

    /**
     * Obtains the foreign keys information for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool   $refresh whether to reload the information even if it is found in the cache.
     * @return ForeignKeyConstraint[] table foreign keys.
     */
    public function getTableForeignKeys($name, $refresh = false)
    {
        throw new NotSupportedException(get_class($this) . ' does not support loading foreign keys');
    }

    /**
     * Obtains the indexes information for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool   $refresh whether to reload the information even if it is found in the cache.
     * @return IndexConstraint[] table indexes.
     */
    public function getTableIndexes($name, $refresh = false)
    {
        throw new NotSupportedException(get_class($this) . ' does not support loading indexes');
    }

    /**
     * Obtains the unique constraints information for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool   $refresh whether to reload the information even if it is found in the cache.
     * @return Constraint[] table unique constraints.
     */
    public function getTableUniques($name, $refresh = false)
    {
        throw new NotSupportedException(get_class($this) . ' does not support loading uniques');
    }

    /**
     * Obtains the check constraints information for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool   $refresh whether to reload the information even if it is found in the cache.
     * @return CheckConstraint[] table check constraints.
     */
    public function getTableChecks($name, $refresh = false)
    {
        throw new NotSupportedException(get_class($this) . ' does not support loading checks');
    }

    /**
     * Obtains the default value constraints information for the named table.
     * @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
     * @param bool   $refresh whether to reload the information even if it is found in the cache.
     * @return DefaultValueConstraint[] table default value constraints.
     */
    public function getTableDefaultValues($name, $refresh = false)
    {
        throw new NotSupportedException(get_class($this) . ' does not support loading default values');
    }
}


<?php
/**
 * This file is part of the Hephaistos project management API.
 *
 * As each files provides by the CSCFA, this file is licensed
 * under the MIT license.
 *
 * PHP version 5.6
 *
 * @category Trait
 * @package  Hephaistos
 * @author   matthieu vallance <matthieu.vallance@cscfa.fr>
 * @license  MIT <https://opensource.org/licenses/MIT>
 * @link     http://cscfa.fr
 */
namespace CSDT\CollectionsBundle\TraitCollection;

use CSDT\CollectionsBundle\CollectionInterfaces\ContainerCollectionInterface;
use CSDT\CollectionsBundle\CollectionInterfaces\CollectionInterface;

/**
 * Subsetable collection trait
 *
 * This trait define the logic of a
 * subsetable collection:
 *
 * @category Trait
 * @package  Hephaistos
 * @author   matthieu vallance <matthieu.vallance@cscfa.fr>
 * @license  MIT <https://opensource.org/licenses/MIT>
 * @link     http://cscfa.fr
 */
trait SubsetableCollectionTrait
{

    /**
     * Get subset
     *
     * This method return a new ContainerCollectionInterface
     * containing the value of the given key, parsed
     * as ContainerCollectionInterface.
     *
     * @param mixed $key The key whence create the subset
     *
     * @throws \LogicException If the method is called with an instance that
     *                         don't match ContainerCollectionInterface
     * @return ContainerCollectionInterface
     */
    public function getSubset($key)
    {
        $target = $this->newInstance();

        if (!($target instanceof ContainerCollectionInterface)) {
            throw new \LogicException(
                "The SubsetableCollectionTrait must be used".
                " into ContainerCollectionInterface childs"
            );
        }

        if ($this->has($key)) {
            $source = $this->get($key);

            if (is_array($source)) {
                $this->fromArray($source, $target);
            } else if ($source instanceof CollectionInterface) {
                $this->fromArray($source->toArray(), $target);
            }
        }

        return $target;
    }

    /**
     * New instance
     *
     * This method is used to create dynamically
     * an instance of ContainerCollectionInterface.
     *
     * @return                     ContainerCollectionInterface
     * @codingStandardsIgnoreStart
     */
    private function newInstance()
    {
        // @codingStandardsIgnoreEnd

        $reflection = new \ReflectionClass($this);
        return $reflection->newInstanceWithoutConstructor();
    }

    /**
     * From array
     *
     * This method hydrate a ContainerCollectionInterface
     * from the values and key contained into an array
     *
     * @param array                        $source The source array
     * @param ContainerCollectionInterface $target The target collection
     *
     * @return void
     */
    protected function fromArray(
        array $source,
        ContainerCollectionInterface $target
    ) {
        foreach ($source as $key => $value) {
            $target->set($key, $value);
        }
    }
}


<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Cache
 * @subpackage Zend_Cache_Backend
 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Backend.php 24989 2012-06-21 07:24:13Z mabe $
 */

/**
 * @package    Zend_Cache
 * @subpackage Zend_Cache_Backend
 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Cache_Backend
{
    /**
     * Frontend or Core directives
     *
     * =====> (int) lifetime :
     * - Cache lifetime (in seconds)
     * - If null, the cache is valid forever
     *
     * =====> (int) logging :
     * - if set to true, a logging is activated throw Zend_Log
     *
     * @var array directives
     */
    protected $_directives = array(
        'lifetime' => 3600,
        'logging'  => false,
        'logger'   => null
    );

    /**
     * Available options
     *
     * @var array available options
     */
    protected $_options = array();

    /**
     * Constructor
     *
     * @param  array $options Associative array of options
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function __construct(array $options = array())
    {
        while (list($name, $value) = each($options)) {
            $this->setOption($name, $value);
        }
    }

    /**
     * Set the frontend directives
     *
     * @param  array $directives Assoc of directives
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function setDirectives($directives)
    {
        if (!is_array($directives)) Zend_Cache::throwException('Directives parameter must be an array');
        while (list($name, $value) = each($directives)) {
            if (!is_string($name)) {
                Zend_Cache::throwException("Incorrect option name : $name");
            }
            $name = strtolower($name);
            if (array_key_exists($name, $this->_directives)) {
                $this->_directives[$name] = $value;
            }

        }

        $this->_loggerSanity();
    }

    /**
     * Set an option
     *
     * @param  string $name
     * @param  mixed  $value
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function setOption($name, $value)
    {
        if (!is_string($name)) {
            Zend_Cache::throwException("Incorrect option name : $name");
        }
        $name = strtolower($name);
        if (array_key_exists($name, $this->_options)) {
            $this->_options[$name] = $value;
        }
    }

    /**
     * Returns an option
     *
     * @param string $name Optional, the options name to return
     * @throws Zend_Cache_Exceptions
     * @return mixed
     */
    public function getOption($name)
    {
        $name = strtolower($name);

        if (array_key_exists($name, $this->_options)) {
            return $this->_options[$name];
        }

        if (array_key_exists($name, $this->_directives)) {
            return $this->_directives[$name];
        }

        Zend_Cache::throwException("Incorrect option name : {$name}");
    }

    /**
     * Get the life time
     *
     * if $specificLifetime is not false, the given specific life time is used
     * else, the global lifetime is used
     *
     * @param  int $specificLifetime
     * @return int Cache life time
     */
    public function getLifetime($specificLifetime)
    {
        if ($specificLifetime === false) {
            return $this->_directives['lifetime'];
        }
        return $specificLifetime;
    }

    /**
     * Return true if the automatic cleaning is available for the backend
     *
     * DEPRECATED : use getCapabilities() instead
     *
     * @deprecated
     * @return boolean
     */
    public function isAutomaticCleaningAvailable()
    {
        return true;
    }

    /**
     * Determine system TMP directory and detect if we have read access
     *
     * inspired from Zend_File_Transfer_Adapter_Abstract
     *
     * @return string
     * @throws Zend_Cache_Exception if unable to determine directory
     */
    public function getTmpDir()
    {
        $tmpdir = array();
        foreach (array($_ENV, $_SERVER) as $tab) {
            foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
                if (isset($tab[$key]) && is_string($tab[$key])) {
                    if (($key == 'windir') or ($key == 'SystemRoot')) {
                        $dir = realpath($tab[$key] . '\\temp');
                    } else {
                        $dir = realpath($tab[$key]);
                    }
                    if ($this->_isGoodTmpDir($dir)) {
                        return $dir;
                    }
                }
            }
        }
        $upload = ini_get('upload_tmp_dir');
        if ($upload) {
            $dir = realpath($upload);
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        if (function_exists('sys_get_temp_dir')) {
            $dir = sys_get_temp_dir();
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        // Attemp to detect by creating a temporary file
        $tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
        if ($tempFile) {
            $dir = realpath(dirname($tempFile));
            unlink($tempFile);
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        if ($this->_isGoodTmpDir('/tmp')) {
            return '/tmp';
        }
        if ($this->_isGoodTmpDir('\\temp')) {
            return '\\temp';
        }
        Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');
    }

    /**
     * Verify if the given temporary directory is readable and writable
     *
     * @param string $dir temporary directory
     * @return boolean true if the directory is ok
     */
    protected function _isGoodTmpDir($dir)
    {
        if (is_readable($dir)) {
            if (is_writable($dir)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Make sure if we enable logging that the Zend_Log class
     * is available.
     * Create a default log object if none is set.
     *
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected function _loggerSanity()
    {
        if (!isset($this->_directives['logging']) || !$this->_directives['logging']) {
            return;
        }

        if (isset($this->_directives['logger'])) {
            if ($this->_directives['logger'] instanceof Zend_Log) {
                return;
            }
            Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
        }

        // Create a default logger to the standard output stream

        $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
        $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
        $this->_directives['logger'] = $logger;
    }

    /**
     * Log a message at the WARN (4) priority.
     *
     * @param  string $message
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected function _log($message, $priority = 4)
    {
        if (!$this->_directives['logging']) {
            return;
        }

        if (!isset($this->_directives['logger'])) {
            Zend_Cache::throwException('Logging is enabled but logger is not set.');
        }
        $logger = $this->_directives['logger'];
        if (!$logger instanceof Zend_Log) {
            Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
        }
        $logger->log($message, $priority);
    }
}


<?php

/**
 * BaseMigration
 *
 * @package app\console\migrations
 */

namespace jarrus90\User\migrations;

use Yii;
use yii\db\Migration;
use yii\rbac\DbManager;
use yii\base\InvalidConfigException;

/**
 * Migration is the base class for representing a database migration.
 * Migration is designed to be used together with the "yii migrate" command.
 * Basically added functions to create and assign roles from migrations
 */
class RbacMigration extends Migration {

    /**
     * @var \yii\rbac\DbManager Auth manager application component.
     */
    protected $authManager;

    /**
     * Initialize migrations.
     * Calls parent init method, then loads current authManager instance.
     *
     * @return DbManager
     * @throws yii\base\InvalidConfigException
     */
    public function init() {
        parent::init();
        $this->authManager = Yii::$app->getAuthManager();
        if (!$this->authManager instanceof DbManager) {
            throw new InvalidConfigException('You should configure "authManager" component to use database before executing this migration.');
        }
    }

    /**
     * Create role.
     * If role already exists doesn nothing.
     *
     * @param string $name Role name
     * @param string $description Role description
     * @return \yii\rbac\Permission the new Permission object
     */
    function createRole($name, $description) {
        if ($user = $this->authManager->getRole($name)) {
            echo "{$name} role already exists\n";
        } else {
            $user = $this->authManager->createRole($name);
            $user->description = $description;
            $this->authManager->add($user);
            echo "{$name} role created\n";
        }
        return $user;
    }

    /**
     * Assigns child role to parent
     *
     * @param string $parent Parent role name
     * @param string $child Child role name
     */
    function assignChildRole($parent, $child) {
        if (!$this->authManager->hasChild($parent, $child)) {
            $this->authManager->addChild($parent, $child);
            echo "New child '{$child->name}' added to '{$parent->name}'\n";
        } else {
            echo "Role '{$child->name}' was already added to '{$parent->name}'\n";
        }
    }

}


<?php

namespace Kcs\FunctionMock\Registry;

use Kcs\FunctionMock\FunctionProphecy;
use Kcs\FunctionMock\Generator\Generator;
use Kcs\FunctionMock\NamespaceProphecy;

class MockRegistry
{
    /**
     * @var NamespaceProphecy[]
     */
    protected $mocks = [];

    /**
     * @var MockRegistry
     */
    private static $instance = null;

    /**
     * Get singleton instance of the registry
     *
     * @return MockRegistry
     */
    public static function getInstance()
    {
        if (null === self::$instance) {
            self::$instance = new static();
        }

        return self::$instance;
    }

    /**
     * Has mock registered for this function?
     *
     * @param string $name
     *
     * @return bool
     */
    public function has($name)
    {
        return isset($this->mocks[$name]);
    }

    /**
     * Register a new function prophecy into the registry
     *
     * @param FunctionProphecy $prophecy
     *
     * @return $this
     *
     * @throws \Exception
     */
    public function register(FunctionProphecy $prophecy)
    {
        $name = $prophecy->getFQName();

        if ($this->has($name)) {
            throw new \Exception();
        }

        if (! function_exists($name)) {
            Generator::generate($prophecy);
        }

        $this->mocks[$name] = $prophecy->getNamespace();

        return $this;
    }

    /**
     * Call the registered function mock
     *
     * @param string $name The fully-qualified function name
     * @param string $uqfn The unqualified function name
     * @param array $args
     *
     * @return mixed
     * @throws \Exception
     *
     * @internal
     */
    public function call($name, $uqfn, array $args)
    {
        if (! $this->has($name)) {
            throw new \Exception();
        }

        return $this->mocks[$name]->call($uqfn, $args);
    }

    /**
     * Unregister all the mocks
     */
    public function unregisterAll()
    {
        $this->mocks = [];
    }
}