<?php

namespace Oxygen\Data\Cache;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Events;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Logging\Log;
use Illuminate\Log\Writer;
use Oxygen\Data\Behaviour\CacheInvalidatorInterface;

class CacheInvalidationSubscriber implements EventSubscriber {

    /**
     * The config.
     *
     * @var \Illuminate\Contracts\Events\Dispatcher
     */
    protected $events;

    protected $cacheSettings;

    protected $log;

    /**
     * Constructs the CacheInvalidationSubscriber.
     *
     * @param \Illuminate\Contracts\Events\Dispatcher             $events
     * @param \Oxygen\Data\Cache\CacheSettingsRepositoryInterface $cacheSettings
     * @param \Illuminate\Log\Writer                              $log
     */
    public function __construct(Dispatcher $events, CacheSettingsRepositoryInterface $cacheSettings, Writer $log) {
        $this->events = $events;
        $this->cacheSettings = $cacheSettings;
        $this->log = $log;
    }

    /**
     * Returns an array of events this subscriber wants to listen to.
     *
     * @return array
     */
    public function getSubscribedEvents() {
        return [
            Events::postPersist,
            Events::preUpdate,
            Events::preRemove
        ];
    }

    /**
     * Invalidates the cache.
     *
     * @param LifecycleEventArgs $args
     * @return void
     */
    public function preUpdate(LifecycleEventArgs $args) {
        $this->invalidate($args->getEntityManager(), $args->getEntity());
    }

    /**
     * Invalidates the cache.
     *
     * @param LifecycleEventArgs $args
     * @return void
     */
    public function preRemove(LifecycleEventArgs $args) {
        $this->invalidate($args->getEntityManager(), $args->getEntity());
    }

    /**
     * Invalidates the cache.
     *
     * @param LifecycleEventArgs $args
     * @return void
     */
    public function postPersist(LifecycleEventArgs $args) {
        $this->invalidate($args->getEntityManager(), $args->getEntity());
    }

    /**
     * Invalidates the cache.
     *
     * @param \Doctrine\ORM\EntityManager $em
     * @param object                      $entity
     */
    public function invalidate(EntityManager $em, $entity) {
        $this->log->info('Invalidating entity of class ' . get_class($entity) . ' with ID ' . $entity->getId());
        $this->events->fire('oxygen.entity.cache.invalidated', [$entity]);

        // if the cache depends on any entities of a given type
        foreach($this->cacheSettings->get(get_class($entity)) as $entity) {
            $this->invalidate($em, $this->find($em, $entity));
        }

        // if the cache depends on a specific entity
        if($entity instanceof CacheInvalidatorInterface) {
            foreach($entity->getEntitiesToBeInvalidated() as $entity) {
                $this->invalidate($em, $this->find($em, $entity));
            }
        }
    }

    private function find(EntityManager $em, $entity) {
        $repo = $em->getRepository($entity['class']);
        return $repo->find($entity['id']);
    }

}


<?php
/**
 * PEAR_DependencyDB, advanced installed packages dependency database
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    CVS: $Id: DependencyDB.php 313023 2011-07-06 19:17:11Z dufuz $
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Needed for error handling
 */
require_once 'PEAR.php';
require_once 'PEAR/Config.php';

$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
/**
 * Track dependency relationships between installed packages
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Tomas V.V.Cox <cox@idec.net.com>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.9.4
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_DependencyDB
{
    // {{{ properties

    /**
     * This is initialized by {@link setConfig()}
     * @var PEAR_Config
     * @access private
     */
    var $_config;
    /**
     * This is initialized by {@link setConfig()}
     * @var PEAR_Registry
     * @access private
     */
    var $_registry;
    /**
     * Filename of the dependency DB (usually .depdb)
     * @var string
     * @access private
     */
    var $_depdb = false;
    /**
     * File name of the lockfile (usually .depdblock)
     * @var string
     * @access private
     */
    var $_lockfile = false;
    /**
     * Open file resource for locking the lockfile
     * @var resource|false
     * @access private
     */
    var $_lockFp = false;
    /**
     * API version of this class, used to validate a file on-disk
     * @var string
     * @access private
     */
    var $_version = '1.0';
    /**
     * Cached dependency database file
     * @var array|null
     * @access private
     */
    var $_cache;

    // }}}
    // {{{ & singleton()

    /**
     * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
     * @param PEAR_Config
     * @param string|false full path to the dependency database, or false to use default
     * @return PEAR_DependencyDB|PEAR_Error
     * @static
     */
    function &singleton(&$config, $depdb = false)
    {
        $phpdir = $config->get('php_dir', null, 'pear.php.net');
        if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
            $a = new PEAR_DependencyDB;
            $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
            $a->setConfig($config, $depdb);
            $e = $a->assertDepsDB();
            if (PEAR::isError($e)) {
                return $e;
            }
        }

        return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
    }

    /**
     * Set up the registry/location of dependency DB
     * @param PEAR_Config|false
     * @param string|false full path to the dependency database, or false to use default
     */
    function setConfig(&$config, $depdb = false)
    {
        if (!$config) {
            $this->_config = &PEAR_Config::singleton();
        } else {
            $this->_config = &$config;
        }

        $this->_registry = &$this->_config->getRegistry();
        if (!$depdb) {
            $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
                DIRECTORY_SEPARATOR . '.depdb';
        } else {
            $this->_depdb = $depdb;
        }

        $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
    }
    // }}}

    function hasWriteAccess()
    {
        if (!file_exists($this->_depdb)) {
            $dir = $this->_depdb;
            while ($dir && $dir != '.') {
                $dir = dirname($dir); // cd ..
                if ($dir != '.' && file_exists($dir)) {
                    if (is_writeable($dir)) {
                        return true;
                    }

                    return false;
                }
            }

            return false;
        }

        return is_writeable($this->_depdb);
    }

    // {{{ assertDepsDB()

    /**
     * Create the dependency database, if it doesn't exist.  Error if the database is
     * newer than the code reading it.
     * @return void|PEAR_Error
     */
    function assertDepsDB()
    {
        if (!is_file($this->_depdb)) {
            $this->rebuildDB();
            return;
        }

        $depdb = $this->_getDepDB();
        // Datatype format has been changed, rebuild the Deps DB
        if ($depdb['_version'] < $this->_version) {
            $this->rebuildDB();
        }

        if ($depdb['_version']{0} > $this->_version{0}) {
            return PEAR::raiseError('Dependency database is version ' .
                $depdb['_version'] . ', and we are version ' .
                $this->_version . ', cannot continue');
        }
    }

    /**
     * Get a list of installed packages that depend on this package
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
     * @return array|false
     */
    function getDependentPackages(&$pkg)
    {
        $data = $this->_getDepDB();
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        if (isset($data['packages'][$channel][$package])) {
            return $data['packages'][$channel][$package];
        }

        return false;
    }

    /**
     * Get a list of the actual dependencies of installed packages that depend on
     * a package.
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
     * @return array|false
     */
    function getDependentPackageDependencies(&$pkg)
    {
        $data = $this->_getDepDB();
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        $depend = $this->getDependentPackages($pkg);
        if (!$depend) {
            return false;
        }

        $dependencies = array();
        foreach ($depend as $info) {
            $temp = $this->getDependencies($info);
            foreach ($temp as $dep) {
                if (
                    isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
                    strtolower($dep['dep']['channel']) == $channel &&
                    strtolower($dep['dep']['name']) == $package
                ) {
                    if (!isset($dependencies[$info['channel']])) {
                        $dependencies[$info['channel']] = array();
                    }

                    if (!isset($dependencies[$info['channel']][$info['package']])) {
                        $dependencies[$info['channel']][$info['package']] = array();
                    }
                    $dependencies[$info['channel']][$info['package']][] = $dep;
                }
            }
        }

        return $dependencies;
    }

    /**
     * Get a list of dependencies of this installed package
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
     * @return array|false
     */
    function getDependencies(&$pkg)
    {
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        $data = $this->_getDepDB();
        if (isset($data['dependencies'][$channel][$package])) {
            return $data['dependencies'][$channel][$package];
        }

        return false;
    }

    /**
     * Determine whether $parent depends on $child, near or deep
     * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
     * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
     */
    function dependsOn($parent, $child)
    {
        $c = array();
        $this->_getDepDB();
        return $this->_dependsOn($parent, $child, $c);
    }

    function _dependsOn($parent, $child, &$checked)
    {
        if (is_object($parent)) {
            $channel = strtolower($parent->getChannel());
            $package = strtolower($parent->getPackage());
        } else {
            $channel = strtolower($parent['channel']);
            $package = strtolower($parent['package']);
        }

        if (is_object($child)) {
            $depchannel = strtolower($child->getChannel());
            $deppackage = strtolower($child->getPackage());
        } else {
            $depchannel = strtolower($child['channel']);
            $deppackage = strtolower($child['package']);
        }

        if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
            return false; // avoid endless recursion
        }

        $checked[$channel][$package][$depchannel][$deppackage] = true;
        if (!isset($this->_cache['dependencies'][$channel][$package])) {
            return false;
        }

        foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
            if (isset($info['dep']['uri'])) {
                if (is_object($child)) {
                    if ($info['dep']['uri'] == $child->getURI()) {
                        return true;
                    }
                } elseif (isset($child['uri'])) {
                    if ($info['dep']['uri'] == $child['uri']) {
                        return true;
                    }
                }
                return false;
            }

            if (strtolower($info['dep']['channel']) == $depchannel &&
                  strtolower($info['dep']['name']) == $deppackage) {
                return true;
            }
        }

        foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
            if (isset($info['dep']['uri'])) {
                if ($this->_dependsOn(array(
                        'uri' => $info['dep']['uri'],
                        'package' => $info['dep']['name']), $child, $checked)) {
                    return true;
                }
            } else {
                if ($this->_dependsOn(array(
                        'channel' => $info['dep']['channel'],
                        'package' => $info['dep']['name']), $child, $checked)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Register dependencies of a package that is being installed or upgraded
     * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
     */
    function installPackage(&$package)
    {
        $data = $this->_getDepDB();
        unset($this->_cache);
        $this->_setPackageDeps($data, $package);
        $this->_writeDepDB($data);
    }

    /**
     * Remove dependencies of a package that is being uninstalled, or upgraded.
     *
     * Upgraded packages first uninstall, then install
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
     *        indices 'channel' and 'package'
     */
    function uninstallPackage(&$pkg)
    {
        $data = $this->_getDepDB();
        unset($this->_cache);
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        if (!isset($data['dependencies'][$channel][$package])) {
            return true;
        }

        foreach ($data['dependencies'][$channel][$package] as $dep) {
            $found      = false;
            $depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
            $depname    = strtolower($dep['dep']['name']);
            if (isset($data['packages'][$depchannel][$depname])) {
                foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
                    if ($info['channel'] == $channel && $info['package'] == $package) {
                        $found = true;
                        break;
                    }
                }
            }

            if ($found) {
                unset($data['packages'][$depchannel][$depname][$i]);
                if (!count($data['packages'][$depchannel][$depname])) {
                    unset($data['packages'][$depchannel][$depname]);
                    if (!count($data['packages'][$depchannel])) {
                        unset($data['packages'][$depchannel]);
                    }
                } else {
                    $data['packages'][$depchannel][$depname] =
                        array_values($data['packages'][$depchannel][$depname]);
                }
            }
        }

        unset($data['dependencies'][$channel][$package]);
        if (!count($data['dependencies'][$channel])) {
            unset($data['dependencies'][$channel]);
        }

        if (!count($data['dependencies'])) {
            unset($data['dependencies']);
        }

        if (!count($data['packages'])) {
            unset($data['packages']);
        }

        $this->_writeDepDB($data);
    }

    /**
     * Rebuild the dependency DB by reading registry entries.
     * @return true|PEAR_Error
     */
    function rebuildDB()
    {
        $depdb = array('_version' => $this->_version);
        if (!$this->hasWriteAccess()) {
            // allow startup for read-only with older Registry
            return $depdb;
        }

        $packages = $this->_registry->listAllPackages();
        if (PEAR::isError($packages)) {
            return $packages;
        }

        foreach ($packages as $channel => $ps) {
            foreach ($ps as $package) {
                $package = $this->_registry->getPackage($package, $channel);
                if (PEAR::isError($package)) {
                    return $package;
                }
                $this->_setPackageDeps($depdb, $package);
            }
        }

        $error = $this->_writeDepDB($depdb);
        if (PEAR::isError($error)) {
            return $error;
        }

        $this->_cache = $depdb;
        return true;
    }

    /**
     * Register usage of the dependency DB to prevent race conditions
     * @param int one of the LOCK_* constants
     * @return true|PEAR_Error
     * @access private
     */
    function _lock($mode = LOCK_EX)
    {
        if (stristr(php_uname(), 'Windows 9')) {
            return true;
        }

        if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
            // XXX does not check type of lock (LOCK_SH/LOCK_EX)
            return true;
        }

        $open_mode = 'w';
        // XXX People reported problems with LOCK_SH and 'w'
        if ($mode === LOCK_SH) {
            if (!file_exists($this->_lockfile)) {
                touch($this->_lockfile);
            } elseif (!is_file($this->_lockfile)) {
                return PEAR::raiseError('could not create Dependency lock file, ' .
                    'it exists and is not a regular file');
            }
            $open_mode = 'r';
        }

        if (!is_resource($this->_lockFp)) {
            $this->_lockFp = @fopen($this->_lockfile, $open_mode);
        }

        if (!is_resource($this->_lockFp)) {
            return PEAR::raiseError("could not create Dependency lock file" .
                                     (isset($php_errormsg) ? ": " . $php_errormsg : ""));
        }

        if (!(int)flock($this->_lockFp, $mode)) {
            switch ($mode) {
                case LOCK_SH: $str = 'shared';    break;
                case LOCK_EX: $str = 'exclusive'; break;
                case LOCK_UN: $str = 'unlock';    break;
                default:      $str = 'unknown';   break;
            }

            return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
        }

        return true;
    }

    /**
     * Release usage of dependency DB
     * @return true|PEAR_Error
     * @access private
     */
    function _unlock()
    {
        $ret = $this->_lock(LOCK_UN);
        if (is_resource($this->_lockFp)) {
            fclose($this->_lockFp);
        }
        $this->_lockFp = null;
        return $ret;
    }

    /**
     * Load the dependency database from disk, or return the cache
     * @return array|PEAR_Error
     */
    function _getDepDB()
    {
        if (!$this->hasWriteAccess()) {
            return array('_version' => $this->_version);
        }

        if (isset($this->_cache)) {
            return $this->_cache;
        }

        if (!$fp = fopen($this->_depdb, 'r')) {
            $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
            return $err;
        }

        $rt = get_magic_quotes_runtime();
        set_magic_quotes_runtime(0);
        clearstatcache();
        fclose($fp);
        $data = unserialize(file_get_contents($this->_depdb));
        set_magic_quotes_runtime($rt);
        $this->_cache = $data;
        return $data;
    }

    /**
     * Write out the dependency database to disk
     * @param array the database
     * @return true|PEAR_Error
     * @access private
     */
    function _writeDepDB(&$deps)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        if (!$fp = fopen($this->_depdb, 'wb')) {
            $this->_unlock();
            return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
        }

        $rt = get_magic_quotes_runtime();
        set_magic_quotes_runtime(0);
        fwrite($fp, serialize($deps));
        set_magic_quotes_runtime($rt);
        fclose($fp);
        $this->_unlock();
        $this->_cache = $deps;
        return true;
    }

    /**
     * Register all dependencies from a package in the dependencies database, in essence
     * "installing" the package's dependency information
     * @param array the database
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @access private
     */
    function _setPackageDeps(&$data, &$pkg)
    {
        $pkg->setConfig($this->_config);
        if ($pkg->getPackagexmlVersion() == '1.0') {
            $gen = &$pkg->getDefaultGenerator();
            $deps = $gen->dependenciesToV2();
        } else {
            $deps = $pkg->getDeps(true);
        }

        if (!$deps) {
            return;
        }

        if (!is_array($data)) {
            $data = array();
        }

        if (!isset($data['dependencies'])) {
            $data['dependencies'] = array();
        }

        $channel = strtolower($pkg->getChannel());
        $package = strtolower($pkg->getPackage());

        if (!isset($data['dependencies'][$channel])) {
            $data['dependencies'][$channel] = array();
        }

        $data['dependencies'][$channel][$package] = array();
        if (isset($deps['required']['package'])) {
            if (!isset($deps['required']['package'][0])) {
                $deps['required']['package'] = array($deps['required']['package']);
            }

            foreach ($deps['required']['package'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'required');
            }
        }

        if (isset($deps['optional']['package'])) {
            if (!isset($deps['optional']['package'][0])) {
                $deps['optional']['package'] = array($deps['optional']['package']);
            }

            foreach ($deps['optional']['package'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'optional');
            }
        }

        if (isset($deps['required']['subpackage'])) {
            if (!isset($deps['required']['subpackage'][0])) {
                $deps['required']['subpackage'] = array($deps['required']['subpackage']);
            }

            foreach ($deps['required']['subpackage'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'required');
            }
        }

        if (isset($deps['optional']['subpackage'])) {
            if (!isset($deps['optional']['subpackage'][0])) {
                $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
            }

            foreach ($deps['optional']['subpackage'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'optional');
            }
        }

        if (isset($deps['group'])) {
            if (!isset($deps['group'][0])) {
                $deps['group'] = array($deps['group']);
            }

            foreach ($deps['group'] as $group) {
                if (isset($group['package'])) {
                    if (!isset($group['package'][0])) {
                        $group['package'] = array($group['package']);
                    }

                    foreach ($group['package'] as $dep) {
                        $this->_registerDep($data, $pkg, $dep, 'optional',
                            $group['attribs']['name']);
                    }
                }

                if (isset($group['subpackage'])) {
                    if (!isset($group['subpackage'][0])) {
                        $group['subpackage'] = array($group['subpackage']);
                    }

                    foreach ($group['subpackage'] as $dep) {
                        $this->_registerDep($data, $pkg, $dep, 'optional',
                            $group['attribs']['name']);
                    }
                }
            }
        }

        if ($data['dependencies'][$channel][$package] == array()) {
            unset($data['dependencies'][$channel][$package]);
            if (!count($data['dependencies'][$channel])) {
                unset($data['dependencies'][$channel]);
            }
        }
    }

    /**
     * @param array the database
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param array the specific dependency
     * @param required|optional whether this is a required or an optional dep
     * @param string|false dependency group this dependency is from, or false for ordinary dep
     */
    function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
    {
        $info = array(
            'dep'   => $dep,
            'type'  => $type,
            'group' => $group
        );

        $dep  = array_map('strtolower', $dep);
        $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
        if (!isset($data['dependencies'])) {
            $data['dependencies'] = array();
        }

        $channel = strtolower($pkg->getChannel());
        $package = strtolower($pkg->getPackage());

        if (!isset($data['dependencies'][$channel])) {
            $data['dependencies'][$channel] = array();
        }

        if (!isset($data['dependencies'][$channel][$package])) {
            $data['dependencies'][$channel][$package] = array();
        }

        $data['dependencies'][$channel][$package][] = $info;
        if (isset($data['packages'][$depchannel][$dep['name']])) {
            $found = false;
            foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
                if ($p['channel'] == $channel && $p['package'] == $package) {
                    $found = true;
                    break;
                }
            }
        } else {
            if (!isset($data['packages'])) {
                $data['packages'] = array();
            }

            if (!isset($data['packages'][$depchannel])) {
                $data['packages'][$depchannel] = array();
            }

            if (!isset($data['packages'][$depchannel][$dep['name']])) {
                $data['packages'][$depchannel][$dep['name']] = array();
            }

            $found = false;
        }

        if (!$found) {
            $data['packages'][$depchannel][$dep['name']][] = array(
                'channel' => $channel,
                'package' => $package
            );
        }
    }
}


<?php

namespace Reaction\Console\Routes;

use FastRoute\Dispatcher;
use Reaction;
use Reaction\RequestApplicationInterface;
use Reaction\Routes\RouterAbstract;
use Reaction\Routes\RouterInterface;

/**
 * Class Router
 * @package Reaction\Console\Routes
 * You can use controllerMap for this router
 *      'controllerMap' => [
 *         'migrate' => [
 *             'class' => 'Reaction\Console\Controllers\MigrateController',
 *             'migrationNamespaces' => [
 *                 'App\Migrations',
 *                 'Some\Namespace\Migrations',
 *             ],
 *         ],
 *     ],
 */
class Router extends RouterAbstract implements RouterInterface
{

    public $controllerNamespaces = [
        'Reaction\Console\Controllers',
    ];
    /**
     * @var array Controllers map
     */
    public $controllerMap = [];

    /**
     * @var string Default controller if none matches
     */
    public $defaultController = 'Reaction\Console\Controllers\HelpController';

    /**
     * Search for a given route
     * @param RequestApplicationInterface $app
     * @param string                      $routePath
     * @param string                      $method
     * @param bool                        $withInternal
     * @return array
     */
    public function searchRoute(RequestApplicationInterface $app, $routePath, $method = 'GET', $withInternal = false)
    {
        //If no command then show default ('help')
        if ($routePath === "" || $routePath === "/") {
            $routePath = 'help';
        }
        /** @var Controller $controller */
        list($controller, $actionName) = $this->createController($routePath, ['app' => $app], false);
        if ($controller === null || (!$withInternal && $controller instanceof Reaction\Routes\ControllerInternalInterface)) {
            return [static::ERROR_NOT_FOUND, null, null, []];
        }
        //Params are ignored by console controllers (parameters extracted from command line on action run)
        return [static::ERROR_OK, $controller, $actionName, []];
    }

    /**
     * @inheritdoc
     */
    public function createController($path, $config = [], $defaultOnFault = true)
    {
        $parts = explode('/', trim($path, '/'));
        $actionId = count($parts) >= 2 ? mb_strtolower(array_pop($parts)) : null;
        $controllerPart = mb_strtolower(array_pop($parts));
        if (is_string($controllerPart) && isset($this->controllerMap[$controllerPart])) {
            $configMap = $this->controllerMap[$controllerPart];
            $configMap = is_string($configMap) ? ['class' => $configMap] : $configMap;
            $config = Reaction\Helpers\ArrayHelper::merge($configMap, $config);
            $controller = Reaction::create($config);
            list($controller, $actionId) = $this->createControllerInstance($controller, $actionId, $config);
            return $controller !== null
                ? [$controller, $actionId]
                : ($defaultOnFault ? $this->getDefaultControllerAndAction($config) : [null, null]);
        }
        return parent::createController($path, $config, $defaultOnFault);
    }
}


<?php

namespace NetLimeTheme\Core;

use NetLimeTheme\Core\Lib\ThemeModuleBase;
use NetLimeTheme\Core\Lib\ThemeSectionBase;

class Theme extends ThemeModuleBase
{
    protected $modules = [];

    protected $production = false;
    protected $registeredSections = [];
    protected $registeredWrappers = [];

    protected $sections = [];
    protected $wrapper = false;

    public $is_ajax = false;
    public $is_post_req = false;
    public $theme_dir;

    /**
     * Init theme
     *
     * @param bool $production True false to enable caching if cache module is enabled
     */
    public function init($production = false)
    {
        setTheme($this);

        do_action("before_theme_setup");

        # Set mode
        $this->production = $production;

        # Set some other params
        $this->is_ajax = defined('DOING_AJAX') && DOING_AJAX;
        $this->is_post_req = $_SERVER['REQUEST_METHOD'] == 'POST';
        $this->theme_dir = get_template_directory();

        # Load extensions
        do_action("before_theme_autoload_modules");
        if (THEME_AUTOLOAD_MODULES):
            $this->autoLoadModules();
        endif;
        do_action("after_theme_autoload_modules");

        # Register wrappers
        do_action("before_theme_register_wrappers");
        do_action("on_theme_register_wrappers");
        do_action("after_theme_register_wrappers");

        # Register sections
        do_action("before_theme_register_sections");
        do_action("on_theme_register_sections");
        do_action("after_theme_register_sections");

        do_action("after_theme_setup");
    }

    /**
     * Auto load extensions
     */
    protected function autoLoadModules()
    {
        $extDirectory = __DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR;
        $extDirectories = glob($extDirectory . "*", GLOB_ONLYDIR);

        foreach ($extDirectories as $directory):
            if (basename($directory) === "core"):
                continue;
            endif;

            # Get className and classPath
            $className = substr(basename(glob($directory . "*/Theme*.php")[0]), 0, -4);
            $classPath = '\\NetLimeTheme\\Extensions\\' . $className;
            $this->registerModule($className, new $classPath());
        endforeach;
    }

    /**
     * Register theme module
     *
     * @param $key string Register module under this key
     * @param $instance
     */
    public function registerModule($key, $instance)
    {
        do_action("before_theme_module_register");
        apply_filters("before_theme_module_init", $key, $instance);

        $this->modules[$key] = $instance;
        $this->module($key)->init();

        apply_filters("after_theme_module_init", $key, $instance);
        do_action("after_theme_module_register");
    }

    /**
     * Get theme module using it´s key
     *
     * @param $key
     * @return mixed
     */
    public function module($key)
    {
        do_action("before_theme_get_module", $key);

        return $this->modules[$key];
    }

    /**
     * Register section to theme. Can be used to override already registered.
     *
     * @param string $sectionKey Class name of section to keep some convention
     * @param string $instance Instance of section
     */
    public function registerSection($sectionKey, $instance)
    {
        //$this->registeredSections[$sectionKey] = (object)["template" => $template_path, "cache" => $cache, "is_class" => $is_class];

        $this->registeredSections[$sectionKey] = $instance;
    }

    /**
     * Get section by it´s key
     *
     * @param string $sectionKey
     * @return \NetLimeTheme\Core\Lib\ThemeSectionBase
     * @throws \Exception
     */
    public function getRegisteredSection($sectionKey)
    {
        if (!isset($this->registeredSections[$sectionKey])):
            throw new \Exception("Section \"$sectionKey\" is not registered. Registered sections: " . implode(", ", array_keys($this->registeredSections)));
        endif;

        return $this->registeredSections[$sectionKey];
    }

    /**
     * Register wrapper to theme. Can be used to override already registered.
     *
     * @param string $wrapperKey Key that you will referring in templates
     * @param string $template_path Relative path to php file in theme directory ex.: "wrappers/1column.php"
     */
    public function registerWrapper($wrapperKey, $template_path)
    {
        $this->registeredWrappers[$wrapperKey] = (object)["template" => $template_path];
    }

    /**
     * Get wrapper by it´s key
     *
     * @param string $wrapperKey
     * @return \stdClass
     * @throws \Exception
     */
    public function getRegisteredWrapper($wrapperKey)
    {
        if (!isset($this->registeredWrappers[$wrapperKey])):
            throw new \Exception("Wrapper \"$wrapperKey\" is not registered.. Registered wrappers: " . implode(", ", array_keys($this->registeredWrappers)));
        endif;

        return $this->registeredWrappers[$wrapperKey];
    }

    /**
     * Set wrapper of the template
     *
     * @param $wrapperKey string Key of wrapper
     */
    public function setWrapper($wrapperKey)
    {
        do_action("before_theme_set_wrapper", $wrapperKey);

        $this->wrapper = $wrapperKey;

        do_action("after_theme_set_wrapper", $wrapperKey);
    }

    /**
     * Set sections that will be rendered.
     *
     * @param $sections array Syntax: array("sectionKey" => "location",...)
     */
    public function setSections(array $sections)
    {
        do_action("before_theme_set_sections", $sections);

        $this->sections = $sections;

        do_action("after_theme_set_sections", $sections);
    }

    /**
     * Render template
     *
     * @param bool|string $wrapperKey Same as theme()->setWrapper(...)
     * @param bool|array $sections Same as theme()->setSections(...)
     */
    public function render($wrapperKey = false, $sections = false)
    {
        do_action("before_theme_render");

        if ($wrapperKey):
            $this->setWrapper($wrapperKey);
        endif;

        if ($sections):
            $this->setSections($sections);
        endif;

        $wrapper = $this->getRegisteredWrapper($this->wrapper);

        include get_template_directory() . "/" . $wrapper->template;

        do_action("after_ntl_render");
    }

    /**
     * Render sections of given location inside wrapper
     *
     * @param $location string Render sections on this location
     */
    public function getContent($location)
    {
        do_action("before_theme_get_content");
        apply_filters("before_theme_get_content", $location);

        foreach ($this->sections as $section_data):

            # Skip if section is not in given location
            if ($section_data[1] !== $location):
                continue;
            endif;

            # Render it
            $this->renderSection($section_data[0]);

        endforeach;

        apply_filters("after_theme_get_content", $location);
        do_action("after_theme_get_content");
    }

    /**
     * Render section
     *
     * @param string $sectionKey The key of section used when registered
     * @param array $data Section data to render with
     */
    public function renderSection($sectionKey, $data = [])
    {
        # Get the section
        $section = $this->getRegisteredSection($sectionKey);

        # Set section data
        $section->data = &$data;

        do_action("before_theme_section_" . $sectionKey . "_render");
        apply_filters("before_theme_section_render", $sectionKey);

        # If needed do something before render without hook
        $section->beforeRender();

        # If cache is enabled and runtime is production and... then do cache
        if ($section->cache && $this->production && !is_user_logged_in() && !$this->is_post_req && !$this->is_ajax):
            $cache = $this->module("ThemeCache")->getCache($sectionKey, $section);
            echo $cache !== false ? $cache : $this->module("ThemeCache")->doCache($sectionKey, $section);
        else:
            $section->init();
            $section->render();
        endif;

        # If needed do something after render without hook
        $section->afterRender();

        apply_filters("after_theme_section_render", $sectionKey);
        do_action("after_theme_section_" . $sectionKey . "_render");
    }

    public function isProduction()
    {
        return $this->production;
    }
}


<?php

namespace Reaction\Routes\StdControllers;

use Reaction\Annotations\Ctrl;
use Reaction\Annotations\CtrlAction;
use Reaction\RequestApplicationInterface;
use Reaction\Routes\Controller;
use Reaction\Routes\ControllerInternalInterface;

/**
 * @Ctrl(group="/error")
 * Class ErrorController. This controller for internal usage only (to render errors)
 * @package Reaction\Routes
 */
class ErrorController extends Controller implements ControllerInternalInterface
{
    /**
     * @inheritdoc
     */
    public function init()
    {
        $this->baseViewPath = \Reaction::$app->getAlias('@reaction/Views');
        parent::init();
    }

    /**
     * Error action default
     * @CtrlAction(path="/error")
     * @param RequestApplicationInterface $app
     * @param \Throwable                  $exception
     * @return \Reaction\Web\ResponseBuilderInterface|string
     */
    public function actionError(RequestApplicationInterface $app, \Throwable $exception) {
        return $this->render($app, 'view', [
            'exception' => $exception,
            'exceptionName' => $this->getExceptionName($exception),
        ], true);
    }
}


<?php

namespace Ekyna\Bundle\CoreBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Class ColorValidator
 * @package Ekyna\Bundle\CoreBundle\Validator\Constraints
 * @author Étienne Dauvergne <contact@ekyna.com>
 */
class ColorValidator extends ConstraintValidator
{
    /**
     * {@inheritdoc}
     */
    public function validate($code, Constraint $constraint)
    {
        if (! $constraint instanceof Color) {
            throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Color');
        }

        if (null === $code) {
            return;
        }

        /** @var Color $constraint */

        $types = [
            'RGBA' => ['rgba', '\([0-9]{1,3},\s?[0-9]{1,3},\s?[0-9]{1,3},\s?[0-9\.]{1,5}\)'],
            'RGB'  => ['rgb',  '\([0-9]{1,3},\s?[0-9]{1,3},\s?[0-9]{1,3}\)'],
            'HSLA' => ['hsla', '\([0-9]{1,3},\s?[0-9]{1,3},\s?[0-9]{1,3},\s?[0-9\.]{1,5}\)'],
            'HSL'  => ['hsl',  '\([0-9]{1,3},\s?[0-9]{1,3},\s?[0-9]{1,3}\)'],
            'HSV'  => ['hsv',  '\([0-9]{1,3},\s?[0-9]{1,3},\s?[0-9]{1,3}\)'],
            'HEX'  => ['#',    '([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})'],
        ];

        foreach($types as $type => $tests) {
            if ($tests[0] !== substr($code, 0, strlen($tests[0]))) {
                continue;
            }
            $regex = sprintf('@^(%s%s)$@', $tests[0], $tests[1]);
            if (!preg_match($regex, $code, $matches)) {
                $this->context->addViolation($constraint->invalidCode, ['%type%' => $type, '%code%' => $code]);
            }
            return;
        }

        $this->context->addViolation($constraint->unknownFormat, ['%color%' => $code]);
    }
}


<?php

/*
 * This file is part of the Valkyrja framework.
 *
 * (c) Melech Mizrachi
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Valkyrja\Console\Output;

use Valkyrja\Application;
use Valkyrja\Console\Enums\FormatBackground;
use Valkyrja\Console\Enums\FormatForeground;
use Valkyrja\Console\Enums\FormatOption;
use Valkyrja\Support\Providers\Provides;

/**
 * Class OutputFormatter.
 *
 * @author Melech Mizrachi
 */
class NativeOutputFormatter implements OutputFormatter
{
    use Provides;

    /**
     * The foreground color.
     *
     * @var int
     */
    protected $foreground;

    /**
     * The background color.
     *
     * @var int
     */
    protected $background;

    /**
     * The options.
     *
     * @var int[]
     */
    protected $options = [];

    /**
     * Set the foreground.
     *
     * @param FormatForeground $foreground The foreground color
     *
     * @return void
     */
    public function setForeground(FormatForeground $foreground = null): void
    {
        if (null === $foreground) {
            $this->foreground = null;

            return;
        }

        $this->foreground = $foreground->getValue();
    }

    /**
     * Set the background.
     *
     * @param FormatBackground $background The background
     *
     * @return void
     */
    public function setBackground(FormatBackground $background = null): void
    {
        if (null === $background) {
            $this->background = null;

            return;
        }

        $this->background = $background->getValue();
    }

    /**
     * Set foreground or background to black.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function black(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::BLACK : FormatForeground::BLACK,
            $background
        );
    }

    /**
     * Set foreground or background to red.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function red(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::RED : FormatForeground::RED,
            $background
        );
    }

    /**
     * Set foreground or background to green.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function green(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::GREEN : FormatForeground::GREEN,
            $background
        );
    }

    /**
     * Set foreground or background to yellow.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function yellow(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::YELLOW : FormatForeground::YELLOW,
            $background
        );
    }

    /**
     * Set foreground or background to blue.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function blue(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::BLUE : FormatForeground::BLUE,
            $background
        );
    }

    /**
     * Set foreground or background to magenta.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function magenta(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::MAGENTA : FormatForeground::MAGENTA,
            $background
        );
    }

    /**
     * Set foreground or background to cyan.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function cyan(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::CYAN : FormatForeground::CYAN,
            $background
        );
    }

    /**
     * Set foreground or background to white.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function white(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::WHITE : FormatForeground::WHITE,
            $background
        );
    }

    /**
     * Set foreground or background to default.
     *
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    public function resetColor(bool $background = null): void
    {
        $this->setColor(
            $background ? FormatBackground::DEFAULT : FormatForeground::DEFAULT,
            $background
        );
    }

    /**
     * Set a color.
     *
     * @param int  $color      The color
     * @param bool $background [optional] Whether this is to set the background
     *
     * @return void
     */
    protected function setColor(int $color, bool $background = null): void
    {
        if (null !== $background) {
            $this->background = $color;

            return;
        }

        $this->foreground = $color;
    }

    /**
     * Set an option.
     *
     * @param FormatOption $option The option
     *
     * @return void
     */
    public function setOption(FormatOption $option): void
    {
        $this->options[$option->getValue()] = $option->getValue();
    }

    /**
     * Determine whether an option has been set.
     *
     * @param FormatOption $option The option
     *
     * @return bool
     */
    public function hasOption(FormatOption $option): bool
    {
        return isset($this->options[$option->getValue()]);
    }

    /**
     * Remove an option.
     *
     * @param FormatOption $option The option
     *
     * @return void
     */
    public function removeOption(FormatOption $option): void
    {
        if ($this->hasOption($option)) {
            unset($this->options[$option->getValue()]);
        }
    }

    /**
     * Set options.
     *
     * @param FormatOption[] ...$options The options
     *
     * @return void
     */
    public function setOptions(FormatOption ...$options): void
    {
        foreach ($options as $option) {
            $this->setOption($option);
        }
    }

    /**
     * Set the bold option.
     *
     * @return void
     */
    public function bold(): void
    {
        $this->setOptionNum(FormatOption::BOLD);
    }

    /**
     * Set the underscore option.
     *
     * @return void
     */
    public function underscore(): void
    {
        $this->setOptionNum(FormatOption::UNDERSCORE);
    }

    /**
     * Set the blink option.
     *
     * @return void
     */
    public function blink(): void
    {
        $this->setOptionNum(FormatOption::BLINK);
    }

    /**
     * Set the reverse option.
     *
     * @return void
     */
    public function reverse(): void
    {
        $this->setOptionNum(FormatOption::INVERSE);
    }

    /**
     * Set the conceal option.
     *
     * @return void
     */
    public function conceal(): void
    {
        $this->setOptionNum(FormatOption::CONCEAL);
    }

    /**
     * Reset the options.
     *
     * @return void
     */
    public function resetOptions(): void
    {
        $this->options = [];
    }

    /**
     * Set an option by its number value.
     *
     * @param int $option The option
     *
     * @return void
     */
    protected function setOptionNum(int $option): void
    {
        $this->options[$option] = $option;
    }

    /**
     * Format a message.
     *
     * @param string $message The message
     *
     * @return string
     */
    public function format(string $message): string
    {
        $set   = [];
        $unset = [];

        // Check if a foreground was specified
        if (null !== $this->foreground) {
            $set[]   = $this->foreground;
            $unset[] = FormatForeground::DEFAULT;
        }

        // Check if a background was specified
        if (null !== $this->background) {
            $set[]   = $this->background;
            $unset[] = FormatBackground::DEFAULT;
        }

        // Check if options were specified
        if (\count($this->options)) {
            // Iterate through all the options
            foreach ($this->options as $option) {
                $set[]   = $option;
                $unset[] = FormatOption::DEFAULT[$option];
            }
        }

        // No need to format if there's nothing to set
        if (0 === \count($set)) {
            return $message;
        }

        return sprintf(
            "\033[%sm%s\033[%sm",
            implode(';', $set),
            $message,
            implode(';', $unset)
        );
    }

    /**
     * The items provided by this provider.
     *
     * @return array
     */
    public static function provides(): array
    {
        return [
            OutputFormatter::class,
        ];
    }

    /**
     * Publish the provider.
     *
     * @param Application $app The application
     *
     * @return void
     */
    public static function publish(Application $app): void
    {
        $app->container()->singleton(
            OutputFormatter::class,
            new static()
        );
    }
}


<?php

namespace Pompdelux\PHPRedisBundle\Logger;

use Psr\Log\LoggerInterface;

/**
 * Logger
 */
class Logger
{
    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $logger;

    /**
     * @var int
     */
    protected $commandCount = 0;

    /**
     * @var array
     */
    protected $commands = array();

    /**
     * Constructor.
     *
     * @param LoggerInterface $logger A LoggerInterface instance
     */
    public function __construct(LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }

    /**
     * Logs a command
     *
     * @param string      $command    Redis command
     * @param float       $duration   Duration in milliseconds
     * @param string      $connection Connection alias
     * @param bool|string $error      Error message or false if command was successful
     */
    public function logCommand($command, $duration, $connection, $error = false)
    {
        ++$this->commandCount;

        if (null !== $this->logger) {
            $this->commands[] = [
                'cmd' => $command,
                'executionMS' => $duration,
                'conn' => $connection,
                'error' => $error
            ];

            if ($error) {
                $this->logger->error('Command "' . $command . '" failed (' . $error . ')');
            } else {
                $this->logger->debug('Executing command "' . $command . '"');
            }
        }
    }

    /**
     * Returns the number of logged commands.
     *
     * @return integer
     */
    public function getNbCommands()
    {
        return $this->commandCount;
    }

    /**
     * Returns an array of the logged commands.
     *
     * @return array
     */
    public function getCommands()
    {
        return $this->commands;
    }

    /**
     * Forward logger calls to the Logger class
     *
     * @param string $method
     * @param array  $parameters
     *
     * @return mixed
     */
    public function __call($method, array $parameters = [])
    {
        if (method_exists($this->logger, $method)) {
            return call_user_func_array([$this->logger, $method], $parameters);
        }
    }
}


<?php
namespace Core\Toolbox\Converter;

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

    /**
     * Transforms the php.ini notation for numbers (like '2M') to an integer (2*1024*1024 in case of 2M)
     *
     * @var $size string Size inas string (like '2M')
     *
     * @return int Size in bytes
     */
    public function sizeToBytes()
    {
        if (!is_string($this->value)) {
            return $this->value;
        }

        $suffix = substr($this->value, -1);
        $value = substr($this->value, 0, -1);

        switch (strtoupper($suffix)) {
            case 'P':
                $value *= 1024;
            case 'T':
                $value *= 1024;
            case 'G':
                $value *= 1024;
            case 'M':
                $value *= 1024;
            case 'K':
                $value *= 1024;
                break;
        }

        return $this->result = $value;
    }

    /**
     * Converts a filesize (bytes as integer) into a human readable string format.
     * For example: 1024 => 1K
     *
     * @param array $units
     *            Optional unit strings
     * @param string $format
     *            The outputformat
     *
     * @throws ConverterException
     *
     * @return string unknown
     */
    public function byteToSize(array $units = null, string $format = '%d%s')
    {
        if (!$this->value == '0' . $this->value) {
            Throw new ConverterException(sprintf('Wrong parameter type'));
        }

        if ($this->value > 0) {
            $unit = intval(log($this->value, 1024));

            if (!isset($units)) {
                $units = [
                    'K',
                    'M',
                    'G',
                    'T',
                    'P'
                ];
            }

            if (array_key_exists($unit, $units) === true) {
                return $this->result = sprintf($format, $this->value / pow(1024, $unit), $units[$unit]);
            }
        }

        return $this->result = $this->value;
    }
}