<?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_Config
 * @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: Yaml.php 25169 2012-12-22 12:23:11Z rob $
 */

/**
 * @see Zend_Config
 */

/**
 * YAML Adapter for Zend_Config
 *
 * @category  Zend
 * @package   Zend_Config
 * @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_Config_Yaml extends Zend_Config
{
    /**
     * Attribute name that indicates what section a config extends from
     */
    const EXTENDS_NAME = "_extends";

    /**
     * Whether to skip extends or not
     *
     * @var boolean
     */
    protected $_skipExtends = false;

    /**
     * What to call when we need to decode some YAML?
     *
     * @var callable
     */
    protected $_yamlDecoder = array(__CLASS__, 'decode');

    /**
     * Whether or not to ignore constants in parsed YAML
     * @var bool
     */
    protected static $_ignoreConstants = false;

    /**
     * Indicate whether parser should ignore constants or not
     *
     * @param  bool $flag
     * @return void
     */
    public static function setIgnoreConstants($flag)
    {
        self::$_ignoreConstants = (bool) $flag;
    }

    /**
     * Whether parser should ignore constants or not
     *
     * @return bool
     */
    public static function ignoreConstants()
    {
        return self::$_ignoreConstants;
    }

    /**
     * Get callback for decoding YAML
     *
     * @return callable
     */
    public function getYamlDecoder()
    {
        return $this->_yamlDecoder;
    }

    /**
     * Set callback for decoding YAML
     *
     * @param  callable $yamlDecoder the decoder to set
     * @return Zend_Config_Yaml
     */
    public function setYamlDecoder($yamlDecoder)
    {
        if (!is_callable($yamlDecoder)) {

            throw new Zend_Config_Exception('Invalid parameter to setYamlDecoder() - must be callable');
        }

        $this->_yamlDecoder = $yamlDecoder;
        return $this;
    }

    /**
     * Loads the section $section from the config file encoded as YAML
     *
     * Sections are defined as properties of the main object
     *
     * In order to extend another section, a section defines the "_extends"
     * property having a value of the section name from which the extending
     * section inherits values.
     *
     * Note that the keys in $section will override any keys of the same
     * name in the sections that have been included via "_extends".
     *
     * Options may include:
     * - allow_modifications: whether or not the config object is mutable
     * - skip_extends: whether or not to skip processing of parent configuration
     * - yaml_decoder: a callback to use to decode the Yaml source
     *
     * @param  string        $yaml     YAML file to process
     * @param  mixed         $section  Section to process
     * @param  array|boolean $options
     */
    public function __construct($yaml, $section = null, $options = false)
    {
        if (empty($yaml)) {

            throw new Zend_Config_Exception('Filename is not set');
        }

        $ignoreConstants    = $staticIgnoreConstants = self::ignoreConstants();
        $allowModifications = false;
        if (is_bool($options)) {
            $allowModifications = $options;
        } elseif (is_array($options)) {
            foreach ($options as $key => $value) {
                switch (strtolower($key)) {
                    case 'allow_modifications':
                    case 'allowmodifications':
                        $allowModifications = (bool) $value;
                        break;
                    case 'skip_extends':
                    case 'skipextends':
                        $this->_skipExtends = (bool) $value;
                        break;
                    case 'ignore_constants':
                    case 'ignoreconstants':
                        $ignoreConstants = (bool) $value;
                        break;
                    case 'yaml_decoder':
                    case 'yamldecoder':
                        $this->setYamlDecoder($value);
                        break;
                    default:
                        break;
                }
            }
        }

        // Suppress warnings and errors while loading file
        set_error_handler(array($this, '_loadFileErrorHandler'));
        $yaml = file_get_contents($yaml);
        restore_error_handler();

        // Check if there was a error while loading file
        if ($this->_loadFileErrorStr !== null) {

            throw new Zend_Config_Exception($this->_loadFileErrorStr);
        }

        // Override static value for ignore_constants if provided in $options
        self::setIgnoreConstants($ignoreConstants);

        // Parse YAML
        $config = call_user_func($this->getYamlDecoder(), $yaml);

        // Reset original static state of ignore_constants
        self::setIgnoreConstants($staticIgnoreConstants);

        if (null === $config) {
            // decode failed

            throw new Zend_Config_Exception("Error parsing YAML data");
        }

        if (null === $section) {
            $dataArray = array();
            foreach ($config as $sectionName => $sectionData) {
                $dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
            }
            parent::__construct($dataArray, $allowModifications);
        } elseif (is_array($section)) {
            $dataArray = array();
            foreach ($section as $sectionName) {
                if (!isset($config[$sectionName])) {

                    throw new Zend_Config_Exception(sprintf(
                        'Section "%s" cannot be found',
                        implode(' ', (array)$section)
                    ));
                }

                $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
            }
            parent::__construct($dataArray, $allowModifications);
        } else {
            if (!isset($config[$section])) {

                throw new Zend_Config_Exception(sprintf(
                    'Section "%s" cannot be found',
                    implode(' ', (array)$section)
                ));
            }

            $dataArray = $this->_processExtends($config, $section);
            if (!is_array($dataArray)) {
                // Section in the yaml data contains just one top level string
                $dataArray = array($section => $dataArray);
            }
            parent::__construct($dataArray, $allowModifications);
        }

        $this->_loadedSection = $section;
    }

    /**
     * Helper function to process each element in the section and handle
     * the "_extends" inheritance attribute.
     *
     * @param  array            $data Data array to process
     * @param  string           $section Section to process
     * @param  array            $config  Configuration which was parsed yet
     * @return array
     * @throws Zend_Config_Exception When $section cannot be found
     */
    protected function _processExtends(array $data, $section, array $config = array())
    {
        if (!isset($data[$section])) {

            throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
        }

        $thisSection  = $data[$section];

        if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) {
            $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]);

            if (!$this->_skipExtends) {
                $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config);
            }
            unset($thisSection[self::EXTENDS_NAME]);
        }

        $config = $this->_arrayMergeRecursive($config, $thisSection);

        return $config;
    }

    /**
     * Very dumb YAML parser
     *
     * Until we have Zend_Yaml...
     *
     * @param  string $yaml YAML source
     * @return array Decoded data
     */
    public static function decode($yaml)
    {
        $lines = explode("\n", $yaml);
        reset($lines);
        return self::_decodeYaml(0, $lines);
    }

    /**
     * Service function to decode YAML
     *
     * @param  int $currentIndent Current indent level
     * @param  array $lines  YAML lines
     * @return array|string
     */
    protected static function _decodeYaml($currentIndent, &$lines)
    {
        $config   = array();
        $inIndent = false;
        while (list($n, $line) = each($lines)) {
            $lineno = $n + 1;

            $line = rtrim(preg_replace("/#.*$/", "", $line));
            if (strlen($line) == 0) {
                continue;
            }

            $indent = strspn($line, " ");

            // line without the spaces
            $line = trim($line);
            if (strlen($line) == 0) {
                continue;
            }

            if ($indent < $currentIndent) {
                // this level is done
                prev($lines);
                return $config;
            }

            if (!$inIndent) {
                $currentIndent = $indent;
                $inIndent      = true;
            }

            if (preg_match("/(?!-)([\w\-]+):\s*(.*)/", $line, $m)) {
                // key: value
                if (strlen($m[2])) {
                    // simple key: value
                    $value = preg_replace("/#.*$/", "", $m[2]);
                    $value = self::_parseValue($value);
                } else {
                    // key: and then values on new lines
                    $value = self::_decodeYaml($currentIndent + 1, $lines);
                    if (is_array($value) && !count($value)) {
                        $value = "";
                    }
                }
                $config[$m[1]] = $value;
            } elseif ($line[0] == "-") {
                // item in the list:
                // - FOO
                if (strlen($line) > 2) {
                    $value = substr($line, 2);

                    $config[] = self::_parseValue($value);
                } else {
                    $config[] = self::_decodeYaml($currentIndent + 1, $lines);
                }
            } else {

                throw new Zend_Config_Exception(sprintf(
                    'Error parsing YAML at line %d - unsupported syntax: "%s"',
                    $lineno, $line
                ));
            }
        }
        return $config;
    }

    /**
     * Parse values
     *
     * @param string $value
     * @return string
     */
    protected static function _parseValue($value)
    {
        $value = trim($value);

        // remove quotes from string.
        if ('"' == $value['0']) {
            if ('"' == $value[count($value) -1]) {
                $value = substr($value, 1, -1);
            }
        } elseif ('\'' == $value['0'] && '\'' == $value[count($value) -1]) {
            $value = strtr($value, array("''" => "'", "'" => ''));
        }

        // Check for booleans and constants
        if (preg_match('/^(t(rue)?|on|y(es)?)$/i', $value)) {
            $value = true;
        } elseif (preg_match('/^(f(alse)?|off|n(o)?)$/i', $value)) {
            $value = false;
        } elseif (strcasecmp($value, 'null') === 0) {
            $value = null;
        } elseif (!self::$_ignoreConstants) {
            // test for constants
            $value = self::_replaceConstants($value);
        }

        return $value;
    }

    /**
     * Replace any constants referenced in a string with their values
     *
     * @param  string $value
     * @return string
     */
    protected static function _replaceConstants($value)
    {
        foreach (self::_getConstants() as $constant) {
            if (strstr($value, $constant)) {
                $value = str_replace($constant, constant($constant), $value);
            }
        }
        return $value;
    }

    /**
     * Get (reverse) sorted list of defined constant names
     *
     * @return array
     */
    protected static function _getConstants()
    {
        $constants = array_keys(get_defined_constants());
        rsort($constants, SORT_STRING);
        return $constants;
    }
}


<?php

namespace Bcol\Component\Type;

/**
 * Class Pattern
 *
 * @author Brice Colucci <brice.colucci@gmail.com>
 */
class Pattern extends NonEmptyString
{
    const CLASS_NAME = __CLASS__;

    /**
     * @param string|String $subject
     * @param array         $matched = null
     * @param int           $flags   = 0
     * @param int           $offset  = 0
     *
     * @return int
     */
    public function match($subject, array &$matched = null, $flags = 0, $offset = 0)
    {
        $subject = new String($subject);

        return preg_match($this->getValue(), $subject->getValue(), $matched, $flags, $offset);
    }

    /**
     * @param string|String $subject
     * @param array         $matches = null
     * @param int           $flags   = PREG_PATTERN_ORDER
     * @param int           $offset  = 0
     *
     * @return int
     */
    public function matchAll($subject, array &$matches = null, $flags = PREG_PATTERN_ORDER, $offset = 0)
    {
        $subject = new String($subject);

        return preg_match_all($this->getValue(), $subject->getValue(), $matches, $flags, $offset);
    }
}


<?php
/**
 * <tasks:replace>
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @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: Replace.php 313023 2011-07-06 19:17:11Z dufuz $
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Common.php';
/**
 * Implements the replace file task.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @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_Task_Replace extends PEAR_Task_Common
{
    var $type = 'simple';
    var $phase = PEAR_TASK_PACKAGEANDINSTALL;
    var $_replacements;

    /**
     * Validate the raw xml at parsing-time.
     * @param PEAR_PackageFile_v2
     * @param array raw, parsed xml
     * @param PEAR_Config
     * @static
     */
    function validateXml($pkg, $xml, $config, $fileXml)
    {
        if (!isset($xml['attribs'])) {
            return array(PEAR_TASK_ERROR_NOATTRIBS);
        }
        if (!isset($xml['attribs']['type'])) {
            return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type');
        }
        if (!isset($xml['attribs']['to'])) {
            return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to');
        }
        if (!isset($xml['attribs']['from'])) {
            return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from');
        }
        if ($xml['attribs']['type'] == 'pear-config') {
            if (!in_array($xml['attribs']['to'], $config->getKeys())) {
                return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                    $config->getKeys());
            }
        } elseif ($xml['attribs']['type'] == 'php-const') {
            if (defined($xml['attribs']['to'])) {
                return true;
            } else {
                return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                    array('valid PHP constant'));
            }
        } elseif ($xml['attribs']['type'] == 'package-info') {
            if (in_array($xml['attribs']['to'],
                array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                    'release_notes', 'license', 'release-license', 'license-uri',
                    'version', 'api-version', 'state', 'api-state', 'release_date',
                    'date', 'time'))) {
                return true;
            } else {
                return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                    array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                    'release_notes', 'license', 'release-license', 'license-uri',
                    'version', 'api-version', 'state', 'api-state', 'release_date',
                    'date', 'time'));
            }
        } else {
            return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'],
                array('pear-config', 'package-info', 'php-const'));
        }
        return true;
    }

    /**
     * Initialize a task instance with the parameters
     * @param array raw, parsed xml
     * @param unused
     */
    function init($xml, $attribs)
    {
        $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml;
    }

    /**
     * Do a package.xml 1.0 replacement, with additional package-info fields available
     *
     * See validateXml() source for the complete list of allowed fields
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param string file contents
     * @param string the eventual final file location (informational only)
     * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
     *         (use $this->throwError), otherwise return the new contents
     */
    function startSession($pkg, $contents, $dest)
    {
        $subst_from = $subst_to = array();
        foreach ($this->_replacements as $a) {
            $a = $a['attribs'];
            $to = '';
            if ($a['type'] == 'pear-config') {
                if ($this->installphase == PEAR_TASK_PACKAGE) {
                    return false;
                }
                if ($a['to'] == 'master_server') {
                    $chan = $this->registry->getChannel($pkg->getChannel());
                    if (!PEAR::isError($chan)) {
                        $to = $chan->getServer();
                    } else {
                        $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                        return false;
                    }
                } else {
                    if ($this->config->isDefinedLayer('ftp')) {
                        // try the remote config file first
                        $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel());
                        if (is_null($to)) {
                            // then default to local
                            $to = $this->config->get($a['to'], null, $pkg->getChannel());
                        }
                    } else {
                        $to = $this->config->get($a['to'], null, $pkg->getChannel());
                    }
                }
                if (is_null($to)) {
                    $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                    return false;
                }
            } elseif ($a['type'] == 'php-const') {
                if ($this->installphase == PEAR_TASK_PACKAGE) {
                    return false;
                }
                if (defined($a['to'])) {
                    $to = constant($a['to']);
                } else {
                    $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]");
                    return false;
                }
            } else {
                if ($t = $pkg->packageInfo($a['to'])) {
                    $to = $t;
                } else {
                    $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]");
                    return false;
                }
            }
            if (!is_null($to)) {
                $subst_from[] = $a['from'];
                $subst_to[] = $to;
            }
        }
        $this->logger->log(3, "doing " . sizeof($subst_from) .
            " substitution(s) for $dest");
        if (sizeof($subst_from)) {
            $contents = str_replace($subst_from, $subst_to, $contents);
        }
        return $contents;
    }
}
?>


<?php

namespace BootPress\Database;

class Component extends Driver
{
    protected $prepared = array();

    /**
     * Prepare and execute a query.
     *
     * @param string|array $query  An SQL statement.
     * @param string|array $values The query parameters.
     *
     * @return mixed Either ``false`` if there was a problem, or whatever the ``$db->execute()``d.
     *
     * ```php
     * $db->exec(array(
     *     'CREATE TABLE employees (',
     *     '  id INTEGER PRIMARY KEY,',
     *     '  name TEXT NOT NULL DEFAULT "",',
     *     '  title TEXT NOT NULL DEFAULT ""',
     *     ')',
     * ));
     * ```
     */
    public function exec($query, $values = array())
    {
        if ($stmt = $this->prepare($query)) {
            $result = $this->execute($stmt, $values);
            $this->close($stmt);
        }

        return (isset($result)) ? $result : false;
    }

    /**
     * Insert new records into a database table.
     *
     * @param string|int $table Either the database table name, or the prepared statement id you got from calling this the first time.  You can also include *'INTO'* here which is handy for prepending a qualifier eg. *'OR IGNORE INTO table'*.
     * @param array      $data  Either the table column names (when preparing a statement), or a row of values (to insert).  If you are only inserting one record and want to save yourself some typing, then make this an ``array(name => value, ...)`` of columns.
     * @param string     $and   Anything you would like to add at the end of the query eg. *'ON DUPLICATE KEY UPDATE ...'*.
     *
     * @return bool|int Either ``false`` if there was an error, a prepared ``$stmt`` to keep passing off as the **$table**, or the ``$id`` of the row you just inserted.  Don't forget to ``$db->close($stmt)``.
     *
     * ```php
     * if ($stmt = $db->insert('employees', array('id', 'name', 'title'))) {
     *     $db->insert($stmt, array(101, 'John Smith', 'CEO'));
     *     $db->insert($stmt, array(102, 'Raj Reddy', 'Sysadmin'));
     *     $db->insert($stmt, array(103, 'Jason Bourne', 'Developer'));
     *     $db->insert($stmt, array(104, 'Jane Smith', 'Sales Manager'));
     *     $db->insert($stmt, array(105, 'Rita Patel', 'DBA'));
     *     $db->close($stmt);
     * }
     *
     * if ($db->insert('OR IGNORE INTO employees', array(
     *     'id' => 106,
     *     'name' => "Little Bobby'); DROP TABLE employees;--",
     *     'title' => 'Intern',
     * ))) {
     *     echo $db->log('count'); // 1 - It worked!
     * }
     * ```
     */
    public function insert($table, array $data, $and = '')
    {
        if (isset($this->prepared[$table])) {
            return $this->execute($table, $data);
        }
        $single = (count(array_filter(array_keys($data), 'is_string')) > 0) ? $data : false;
        if ($single) {
            $data = array_keys($data);
        }
        if (stripos($table, ' INTO ') !== false) { // eg. 'OR IGNORE INTO table'
            $query = "INSERT {$table} ";
        } else {
            $query = "INSERT INTO {$table} ";
        }
        $query .= '('.implode(', ', $data).') VALUES ('.implode(', ', array_fill(0, count($data), '?')).') '.$and;
        $stmt = $this->prepare($query);
        if ($single && $stmt) {
            $id = $this->insert($stmt, array_values($single));
            $this->close($stmt);

            return $id;
        }

        return $stmt;
    }

    /**
     * Modify records in a database table.
     *
     * @param string|int $table Either the database table name, or the prepared statement id you got from calling this the first time.  You can also include *'SET'* here which is handy for getting some updates in that we can't otherwise do eg. *'table SET date = NOW(),'*.
     * @param array      $id    Either the name of the column with the unique identifier you will be referencing (when preparing a statement), or the unique identifier of the column you are updating.
     * @param array      $data  Either the table column names (when preparing a statement), or a row of values (to update).  If you are only updating one record and want to save yourself some typing, then make this an ``array(name => value, ...)`` of columns.
     * @param string     $and   Anything you would like to add at the end of the query after the WHERE eg. *'AND approved = "Y"'*.
     *
     * @return bool|int Either ``false`` if there was an error, a prepared ``$stmt`` to keep passing off as the **$table**, or the ``$num`` of rows affected.  Don't forget to ``$db->close($stmt)``.
     *
     * ```php
     * if (!$db->update('employees SET id = 101', 'id', array(
     *     106 => array(
     *         'name' => 'Roberto Cratchit',
     *         'title' => 'CEO',
     *     )
     * ))) {
     *     echo $db->log('error'); // A unique id constraint
     * }
     *
     * if ($stmt = $db->update('employees', 'id', array('title'))) {
     *     $db->update($stmt, 103, array('Janitor'));
     *     $db->update($stmt, 99, array('Quality Control'));
     *     $db->close($stmt);
     * }
     * ```
     */
    public function update($table, $id, array $data, $and = '')
    {
        if (isset($this->prepared[$table])) {
            $data[] = $id;

            return $this->execute($table, $data);
        }
        $first = each($data);
        $single = (is_array($first['value'])) ? $first['value'] : false;
        if ($single) {
            $data = array_keys($single);
        }
        if (stripos($table, ' SET ') !== false) { // eg. 'table SET date = NOW(),'
            $query = "UPDATE {$table} ";
        } else {
            $query = "UPDATE {$table} SET ";
        }
        $query .= implode(' = ?, ', $data).' = ? WHERE '.$id.' = ? '.$and;
        $stmt = $this->prepare($query);
        if ($single && $stmt) {
            $affected = $this->update($stmt, $first['key'], array_values($single));
            $this->close($stmt);

            return $affected;
        }

        return $stmt;
    }

    /**
     * Either update or insert records depending on whether they already exist or not.
     *
     * @param string|int $table Either the database table name, or the prepared statement id you got from calling this the first time.  You cannot include *'SET'* or *'INTO'* here.
     * @param array      $id    Either the name of the column with the unique identifier you will be referencing (when preparing a statement), or the unique identifier of the column you are upserting.
     * @param array      $data  Either the table column names (when preparing a statement), or a row of values (to upsert).  If you are only upserting one record and want to save yourself some typing, then make this an ``array(name => value, ...)`` of columns.
     *
     * @return bool|int Either ``false`` if there was an error, a prepared ``$stmt`` to keep passing off as the **$table**, or the ``$id`` of the row that was upserted.  Don't forget to ``$db->close($stmt)``.
     *
     * ```php
     * if ($stmt = $db->upsert('employees', 'id', array('name', 'title'))) {
     *     $db->upsert($stmt, 101, array('Roberto Cratchit', 'CEO'));
     *     $db->upsert($stmt, 106, array('John Smith', 'Developer'));
     *     $db->close($stmt);
     * }
     *
     * $db->upsert('employees', 'id', array(
     *     107 => array(
     *         'name' => 'Ella Minnow Pea',
     *         'title' => 'Executive Assistant',
     *     ),
     * ));
     * ```
     */
    public function upsert($table, $id, array $data)
    {
        if (isset($this->prepared[$table]['ref']) && $this->execute($table, $id)) {
            $data[] = $id;
            if ($row = $this->fetch($table)) {
                return ($this->execute($this->prepared[$table]['ref']['update'], $data)) ? array_shift($row) : false;
            } else {
                return $this->execute($this->prepared[$table]['ref']['insert'], $data);
            }
        }
        $first = each($data);
        $single = (is_array($first['value'])) ? $first['value'] : false;
        if ($single) {
            $data = array_keys($single);
        }
        if ($stmt = $this->prepare("SELECT {$id} FROM {$table} WHERE {$id} = ?", 'row')) {
            $this->prepared[$stmt]['ref']['update'] = $this->update($table, $id, $data);
            $this->prepared[$stmt]['ref']['insert'] = $this->insert($table, array_merge($data, array($id)));
        }
        if ($single && $stmt) {
            $id = $this->upsert($stmt, $first['key'], array_values($single));
            $this->close($stmt);

            return $id;
        }

        return $stmt;
    }

    /**
     * Select data from the database.
     *
     * @param string|array $select A SELECT statement.
     * @param string|array $values The query parameters.
     * @param string       $fetch  How you would like your row.
     *
     * @return bool|int Either ``false`` if there was a problem, or a statement that you can ``$db->fetch($result)`` rows from.  Don't forget to ``$db->close($result)``.
     *
     * ```php
     * if ($result = $db->query('SELECT name, title FROM employees', '', 'assoc')) {
     *     while ($row = $db->fetch($result)) {
     *         print_r($row);
     *         // array('name'=>'Roberto Cratchit', 'title'=>'CEO')
     *         // array('name'=>'Raj Reddy', 'title'=>'Sysadmin')
     *         // array('name'=>'Jason Bourne', 'title'=>'Janitor')
     *         // array('name'=>'Jane Smith', 'title'=>'Sales Manager')
     *         // array('name'=>'Rita Patel', 'title'=>'DBA')
     *         // array('name'=>'John Smith', 'title'=>'Developer')
     *         // array('name'=>'Ella Minnow Pea', 'title'=>'Executive Assistant')
     *     }
     *     $db->close($result);
     * }
     * ```
     */
    public function query($select, $values = array(), $fetch = 'row')
    {
        if ($stmt = $this->prepare($select, $fetch)) {
            if ($this->prepared[$stmt]['type'] == 'SELECT' && $this->execute($stmt, $values)) {
                return $stmt;
            }
            $this->close($stmt);
        }

        return false;
    }

    /**
     * Get all of the selected rows from your query at once.
     *
     * @param string|array $select A SELECT statement.
     * @param string|array $values The query parameters.
     * @param string       $fetch  How you would like your row.
     *
     * @return array No false heads up here.  You either have rows, or you don't.
     *
     * ```php
     * foreach ($db->all('SELECT id, name, title FROM employees') as $row) {
     *     list($id, $name, $title) = $row;
     * }
     * ```
     */
    public function all($select, $values = array(), $fetch = 'row')
    {
        $rows = array();
        if ($stmt = $this->query($select, $values, $fetch)) {
            while ($row = $this->fetch($stmt)) {
                $rows[] = $row;
            }
            $this->close($stmt);
        }

        return $rows;
    }

    /**
     * Get all of the id's from your query, or whatever the first column you requested is.
     *
     * @param string|array $select A SELECT statement.
     * @param string|array $values The query parameters.
     *
     * @return bool|array Either ``false`` if there were no rows, or an ``array()`` of every rows first value.
     *
     * ```php
     * if ($ids = $db->ids('SELECT id FROM employees WHERE title = ?', 'Intern')) {
     *     // Then Little Bobby Tables isn't as good as we thought.
     * }
     * ```
     */
    public function ids($select, $values = array())
    {
        $ids = array();
        if ($stmt = $this->query($select, $values, 'row')) {
            while ($row = $this->fetch($stmt)) {
                $ids[] = (int) array_shift($row);
            }
            $this->close($stmt);
        }

        return (!empty($ids)) ? $ids : false;
    }

    /**
     * Get only the first row from your query.
     *
     * @param string|array $select A SELECT statement.
     * @param string|array $values The query parameters.
     * @param string       $fetch  How you would like your row.
     *
     * @return bool|array Either ``false`` if there was no row, or an ``array()`` of the first one fetched.
     *
     * ```php
     * if ($janitor = $db->row('SELECT id, name FROM employees WHERE title = ?', 'Janitor', 'assoc')) {
     *     // array('id'=>103, 'name'=>'Jason Bourne')
     * }
     * ```
     */
    public function row($select, $values = array(), $fetch = 'row')
    {
        if ($stmt = $this->query($select, $values, $fetch)) {
            $row = $this->fetch($stmt);
            $this->close($stmt);
        }

        return (isset($row) && !empty($row)) ? $row : false;
    }

    /**
     * Get only the first value of the first row from your query.
     *
     * @param string|array $select A SELECT statement.
     * @param mixed        $values The query parameters.
     *
     * @return bool|string Either ``false`` if there was no row, or the ``$value`` you are looking for.
     *
     * ```php
     * echo $db->value('SELECT COUNT(*) FROM employees'); // 7
     * ```
     */
    public function value($select, $values = array())
    {
        return ($row = $this->row($select, $values, 'row')) ? array_shift($row) : false;
    }

    /**
     * Prepare a query to be executed.
     *
     * @param string|array $query An SQL statement.
     * @param string       $fetch How you would like the SELECT rows returned.  Either '**obj**', '**assoc**', '**named**', '**both**', or '**num**' (the default).
     *
     * @return bool|int Either ``false`` if there was an error, or a ``$stmt`` id that can be``$db->execute()``d or ``$db->fetch()``ed.  Don't forget to ``$db->close($stmt)``.
     */
    public function prepare($query, $fetch = null)
    {
        $query = (is_array($query)) ? trim(implode("\n", $query)) : trim($query);
        $stmt = count(static::$logs[$this->id]) + 1;
        $start = microtime(true);
        $this->prepared[$stmt]['obj'] = $this->dbPrepare($query);
        static::$logs[$this->id][$stmt] = array(
            'sql' => $query,
            'count' => 0,
            'prepared' => microtime(true) - $start,
            'executed' => 0,
        );
        $this->prepared[$stmt]['params'] = substr_count($query, '?');
        $this->prepared[$stmt]['type'] = strtoupper(strtok($query, " \r\n\t"));
        if ($this->prepared[$stmt]['type'] == 'SELECT') {
            $this->prepared[$stmt]['style'] = $this->dbStyle(strtolower((string) $fetch));
        }
        if ($this->prepared[$stmt]['obj'] === false) {
            unset($this->prepared[$stmt]);
            if ($error = $this->dbPrepareError()) {
                static::$logs[$this->id][$stmt]['errors'][] = $error;
            }

            return false;
        }

        return $stmt;
    }

    /**
     * Execute a prepared statement.
     *
     * @param int          $stmt   A ``$db->prepare(...)``d statement's return value.
     * @param string|array $values The query parameters.  If there is only one or none, then this can be a string.
     *
     * @return mixed Either ``false`` if there was an error, ``true`` for a SELECT query, the inserted ``$id`` for an INSERT query, or the ``$num`` of affected rows for everything else.
     */
    public function execute($stmt, $values = null)
    {
        if (isset($this->prepared[$stmt])) {
            if (!is_array($values)) {
                $values = ($this->prepared[$stmt]['params'] == 1) ? array($values) : array();
            }
            $start = microtime(true);
            if ($this->dbExecute($this->prepared[$stmt]['obj'], array_values($values), $stmt)) {
                static::$logs[$this->id][$stmt]['executed'] += microtime(true) - $start;
                static::$logs[$this->id][$stmt]['count']++;
                switch ($this->prepared[$stmt]['type']) {
                    case 'SELECT':
                        return true;
                    break;
                    case 'INSERT':
                        return $this->dbInserted();
                    default:
                        return $this->dbAffected($this->prepared[$stmt]['obj']);
                }
            } elseif ($error = $this->dbExecuteError($this->prepared[$stmt]['obj'])) {
                static::$logs[$this->id][$stmt]['errors'][] = $error;
            }
        }

        return false;
    }

    /**
     * Get the next row from an executed SELECT statement.
     *
     * @param int $stmt A ``$db->prepare(...)``d statement's return value.
     *
     * @return mixed
     */
    public function fetch($stmt)
    {
        if (isset($this->prepared[$stmt]) && $this->prepared[$stmt]['type'] == 'SELECT') {
            return $this->dbFetch($this->prepared[$stmt]['obj'], $this->prepared[$stmt]['style'], $stmt);
        }

        return false;
    }

    /**
     * Closes a ``$db->prepared()``d statement to free up the database connection.
     *
     * @param int $stmt A ``$db->prepare(...)``d statement's return value.
     */
    public function close($stmt)
    {
        if (isset($this->prepared[$stmt])) {
            if (isset($this->prepared[$stmt]['ref'])) {
                foreach ($this->prepared[$stmt]['ref'] as $value) {
                    $this->close($value);
                }
            }
            $this->dbClose($this->prepared[$stmt]['obj'], $stmt);
            unset($this->prepared[$stmt]);
        }
    }

    /**
     * Returns a **$query** with it's **$values** in place so that you can stare at it, and try to figure out what is going on.
     *
     * @param string|array $query  An SQL statement.
     * @param mixed        $values The query parameters.
     *
     * @return string
     */
    public function debug($query, $values = array())
    {
        $query = (is_array($query)) ? trim(implode("\n", $query)) : trim($query);
        if (!is_array($values)) {
            $values = (!empty($values)) ? array($values) : array();
        }
        foreach ($values as $string) {
            if (false !== $replace = strpos($query, '?')) {
                $query = substr_replace($query, $this->dbEscape($string), $replace, 1);
            }
        }

        return $query;
    }

    /**
     * Returns information about the previously executed query.
     *
     * @param string $value If you don't want the whole array, then you can specify the specific value you do want.  Either '**sql**', '**count**', '**prepared**', '**executed**', '**errors**', '**average**', '**total**', or '**time**'.
     *
     * @return mixed
     */
    public function log($value = null)
    {
        $log = (is_numeric($value)) ? static::$logs[$this->id][$value] : end(static::$logs[$this->id]);
        if (isset($log['errors'])) {
            $log['errors'] = array_count_values($log['errors']);
        }
        $log['average'] = ($log['count'] > 0) ? $log['executed'] / $log['count'] : 0;
        $log['total'] = $log['prepared'] + $log['executed'];
        $log['time'] = round($log['total'] * 1000).' ms';
        if ($log['count'] > 1) {
            $log['time'] .= ' (~'.round($log['average'] * 1000).' ea)';
        }
        if (is_null($value) || is_numeric($value)) {
            return $log;
        }

        return (isset($log[$value])) ? $log[$value] : null;
    }
}


<?php
/**
 * This file is part of graze/array-filter
 *
 * Copyright (c) 2016 Nature Delivered Ltd. <https://www.graze.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @license https://github.com/graze/array-filter/blob/master/LICENSE.md
 * @link    https://github.com/graze/array-filter
 */

namespace Graze\ArrayFilter\Factory;

use Closure;
use DateTime;

class ValueFactory implements ValueFactoryInterface
{
    /**
     * @var array List of mapping templates to apply '<regex>' => 'value/closure'
     */
    private $mappings = [];

    public function __construct()
    {
        $this->mappings = [
            '/(?<!:\{)\{date:([^\}:]+):?([^\}]+)?\}(?!:\})/i' => function ($matches) {
                $dt = new DateTime($matches[1]);
                $format = isset($matches[2]) ? $matches[2] : 'c';
                return $dt->format($format);
            },
        ];
    }

    /**
     * @param string         $regex
     * @param string|Closure $replace
     *
     * @return $this
     */
    public function addMapping($regex, $replace)
    {
        $this->mappings[$regex] = $replace;

        return $this;
    }

    /**
     * Parse the supplied value and return the interpreted value
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public function parseValue($value)
    {
        foreach ($this->mappings as $mapping => $replace) {
            if (is_callable($replace)) {
                $value = preg_replace_callback($mapping, $replace, $value);
            } else {
                $value = preg_replace($mapping, $replace, $value);
            }
        }

        return $value;
    }
}


<?php namespace Neonbug\Translation\Providers;

use App;
use Route;
use View;
use Config;
use \Illuminate\Routing\Router as Router;

class ServiceProvider extends \Neonbug\Common\Providers\BaseServiceProvider {

	const PACKAGE_NAME     = 'translation';
	const PREFIX           = 'translation';
	const ROLE             = 'translation';
	const ADMIN_CONTROLLER = '\Neonbug\Translation\Controllers\AdminController';

	/**
	 * Define your route model bindings, pattern filters, etc.
	 *
	 * @param    \Illuminate\Routing\Router  $router
	 * @return  void
	 */
	public function boot(Router $router)
	{
		//============
		//== ASSETS ==
		//============
		$this->loadViewsFrom(__DIR__.'/../resources/views', static::PACKAGE_NAME);
		$this->publishes([
			__DIR__.'/../resources/views' => base_path('resources/views/vendor/' . static::PACKAGE_NAME),
		]);

		$this->loadViewsFrom(__DIR__.'/../resources/admin_views', static::PACKAGE_NAME . '_admin');
		$this->publishesAdmin([
			__DIR__.'/../resources/admin_views' => base_path('resources/views/vendor/' . static::PACKAGE_NAME . '_admin'),
		]);

		$this->loadTranslationsFrom('/', static::PACKAGE_NAME);

		$this->publishes([
			__DIR__.'/../assets/' => public_path('vendor/translation'),
		], 'public');

		$this->publishes([
			__DIR__.'/../database/migrations/' => database_path('/migrations')
		], 'migrations');

		$this->publishes([
			__DIR__.'/../config/' . static::PACKAGE_NAME . '.php' => config_path('neonbug/' . static::PACKAGE_NAME . '.php'),
		]);

		//============
		//== ROUTES ==
		//============
		$language = App::make('Language');
		$locale = ($language == null ? Config::get('app.default_locale') : $language->locale);

		$admin_language = App::make('AdminLanguage');
		$admin_locale = ($admin_language == null ? Config::get('app.admin_default_locale') : $admin_language->locale);

		$resource_repo = App::make('ResourceRepository');

		//admin
		$router->group([ 'prefix' => $admin_locale . '/admin/' . static::PREFIX,
			'middleware' => [ 'auth.admin', 'admin.menu' ], 'role' => static::ROLE,
			'menu.icon' => 'world', 'weight' => 6 ], function($router)
		{
			$router->get('list', [
				'as'   => static::PREFIX . '::admin::list',
				'uses' => static::ADMIN_CONTROLLER . '@adminList'
			]);

			$router->get('edit/{id}', [
				'as'   => static::PREFIX . '::admin::edit',
				'uses' => static::ADMIN_CONTROLLER . '@adminEdit'
			]);
			$router->post('edit/{id}', [
				'as'   => static::PREFIX . '::admin::edit-save',
				'uses' => static::ADMIN_CONTROLLER . '@adminEditPost'
			]);
		});

		$router->group([ 'prefix' => $admin_locale . '/admin/' . static::PREFIX, 'middleware' => [ 'auth.admin' ],
			'role' => static::ROLE ], function($router)
		{
			$router->post('delete', [
				'as'   => static::PREFIX . '::admin::delete',
				'uses' => static::ADMIN_CONTROLLER . '@adminDeletePost'
			]);
		});

		parent::boot($router);
	}

	/**
	 * Register any application services.
	 *
	 * This service provider is a great spot to register your various container
	 * bindings with the application. As you can see, we are registering our
	 * "Registrar" implementation here. You can add your own bindings too!
	 *
	 * @return  void
	 */
	public function register()
	{
		//===========
		//== BINDS ==
		//===========
		if (!App::bound('\Neonbug\Translation\Repositories\TranslationRepository'))
		{
			App::singleton('\Neonbug\Translation\Repositories\TranslationRepository', '\Neonbug\Translation\Repositories\TranslationRepository');
		}
	}

}


<?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_Filter
 * @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: PregReplace.php 24593 2012-01-05 20:35:02Z matthew $
 */

/**
 * @see Zend_Filter_Interface
 */

/**
 * @category   Zend
 * @package    Zend_Filter
 * @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_Filter_PregReplace implements Zend_Filter_Interface
{
    /**
     * Pattern to match
     * @var mixed
     */
    protected $_matchPattern = null;

    /**
     * Replacement pattern
     * @var mixed
     */
    protected $_replacement = '';

    /**
     * Is unicode enabled?
     *
     * @var bool
     */
    static protected $_unicodeSupportEnabled = null;

    /**
     * Is Unicode Support Enabled Utility function
     *
     * @return bool
     */
    static public function isUnicodeSupportEnabled()
    {
        if (self::$_unicodeSupportEnabled === null) {
            self::_determineUnicodeSupport();
        }

        return self::$_unicodeSupportEnabled;
    }

    /**
     * Method to cache the regex needed to determine if unicode support is available
     *
     * @return bool
     */
    static protected function _determineUnicodeSupport()
    {
        self::$_unicodeSupportEnabled = (@preg_match('/\pL/u', 'a')) ? true : false;
    }

    /**
     * Constructor
     * Supported options are
     *     'match'   => matching pattern
     *     'replace' => replace with this
     *
     * @param  string|array $options
     * @return void
     */
    public function __construct($options = null)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        } else if (!is_array($options)) {
            $options = func_get_args();
            $temp    = array();
            if (!empty($options)) {
                $temp['match'] = array_shift($options);
            }

            if (!empty($options)) {
                $temp['replace'] = array_shift($options);
            }

            $options = $temp;
        }

        if (array_key_exists('match', $options)) {
            $this->setMatchPattern($options['match']);
        }

        if (array_key_exists('replace', $options)) {
            $this->setReplacement($options['replace']);
        }
    }

    /**
     * Set the match pattern for the regex being called within filter()
     *
     * @param mixed $match - same as the first argument of preg_replace
     * @return Zend_Filter_PregReplace
     */
    public function setMatchPattern($match)
    {
        $this->_matchPattern = $match;
        return $this;
    }

    /**
     * Get currently set match pattern
     *
     * @return string
     */
    public function getMatchPattern()
    {
        return $this->_matchPattern;
    }

    /**
     * Set the Replacement pattern/string for the preg_replace called in filter
     *
     * @param mixed $replacement - same as the second argument of preg_replace
     * @return Zend_Filter_PregReplace
     */
    public function setReplacement($replacement)
    {
        $this->_replacement = $replacement;
        return $this;
    }

    /**
     * Get currently set replacement value
     *
     * @return string
     */
    public function getReplacement()
    {
        return $this->_replacement;
    }

    /**
     * Perform regexp replacement as filter
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        if ($this->_matchPattern == null) {

            throw new Zend_Filter_Exception(get_class($this) . ' does not have a valid MatchPattern set.');
        }

        return preg_replace($this->_matchPattern, $this->_replacement, $value);
    }

}


<?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\Http;

use Throwable;
use Valkyrja\Application;
use Valkyrja\Debug\ExceptionHandler;
use Valkyrja\Http\Events\HttpKernelHandled;
use Valkyrja\Http\Events\HttpKernelTerminate;
use Valkyrja\Http\Exceptions\HttpException;
use Valkyrja\Http\Middleware\MiddlewareAwareTrait;
use Valkyrja\Routing\Route;
use Valkyrja\Routing\Router;
use Valkyrja\Support\Providers\Provides;

/**
 * Class NativeKernel.
 *
 * @author Melech Mizrachi
 */
class NativeKernel implements Kernel
{
    use MiddlewareAwareTrait;
    use Provides;

    /**
     * The application.
     *
     * @var \Valkyrja\Application
     */
    protected $app;

    /**
     * The router.
     *
     * @var \Valkyrja\Routing\Router
     */
    protected $router;

    /**
     * Kernel constructor.
     *
     * @param Application $application The application
     * @param Router      $router      The router
     */
    public function __construct(Application $application, Router $router)
    {
        $this->app    = $application;
        $this->router = $router;

        $config = $application->config()['routing'];

        self::$middleware       = $config['middleware'];
        self::$middlewareGroups = $config['middlewareGroups'];
    }

    /**
     * Handle a request.
     *
     * @param Request $request The request
     *
     * @throws \Valkyrja\Http\Exceptions\HttpException
     *
     * @return \Valkyrja\Http\Response
     */
    public function handle(Request $request): Response
    {
        try {
            $response = $this->dispatchRouter($request);
        } catch (Throwable $exception) {
            $response = $this->getExceptionResponse($exception);
        }

        // Dispatch the after request handled middleware and return the response
        $this->responseMiddleware($request, $response);

        // Trigger an event for kernel handled
        $this->app->events()->trigger(
            HttpKernelHandled::class,
            [
                new HttpKernelHandled($request, $response),
            ]
        );

        return $response;
    }

    /**
     * Dispatch the request via the router.
     *
     * @param Request $request The request
     *
     * @return \Valkyrja\Http\Response
     */
    protected function dispatchRouter(Request $request): Response
    {
        // Set the request object in the container
        $this->app->container()->singleton(Request::class, $request);

        // Dispatch the before request handled middleware
        $middlewareReturn = $this->requestMiddleware($request);

        // If the middleware returned a response
        if ($middlewareReturn instanceof Response) {
            // Return the response
            return $middlewareReturn;
        }

        return $this->router->dispatch($request);
    }

    /**
     * Get a response from an exception.
     *
     * @param \Throwable $exception The exception
     *
     * @return \Valkyrja\Http\Response
     */
    protected function getExceptionResponse(Throwable $exception): Response
    {
        if ($exception instanceof HttpException && $exception->getResponse() !== null) {
            return $exception->getResponse();
        }

        $handler = new ExceptionHandler($this->app->debug());

        return $handler->getResponse($exception);
    }

    /**
     * Terminate the request.
     *
     * @param Request  $request  The request
     * @param Response $response The response
     *
     * @return void
     */
    public function terminate(Request $request, Response $response): void
    {
        // Dispatch the terminable middleware
        $this->terminableMiddleware($request, $response);

        // Terminate route middleware
        $this->terminateRouteMiddleware($request, $response);

        // Trigger an event for kernel terminate
        $this->app->events()->trigger(
            HttpKernelTerminate::class,
            [
                new HttpKernelTerminate($request, $response),
            ]
        );
    }

    /**
     * Run the kernel.
     *
     * @param Request $request The request
     *
     * @throws \Valkyrja\Http\Exceptions\HttpException
     *
     * @return void
     */
    public function run(Request $request = null): void
    {
        // If no request was passed get the bootstrapped definition
        if (null === $request) {
            $request = $this->app->container()->getSingleton(Request::class);
        }

        // Handle the request, dispatch the after request middleware, and send the response
        $response = $this->handle($request)->send();

        // Terminate the application
        $this->terminate($request, $response);
    }

    /**
     * Get the application.
     *
     * @return \Valkyrja\Application
     */
    protected function getApplication(): Application
    {
        return $this->app;
    }

    /**
     * Terminate the found route's middleware.
     *
     * @param Request  $request  The request
     * @param Response $response The response
     *
     * @return void
     */
    protected function terminateRouteMiddleware(Request $request, Response $response): void
    {
        // Ensure a route exists
        if (! $this->app->container()->isSingleton(Route::class)) {
            return;
        }

        /* @var Route $route */
        $route = $this->app->container()->getSingleton(Route::class);

        // If the dispatched route has middleware
        if (null !== $route->getMiddleware()) {
            // Terminate each middleware
            $this->terminableMiddleware(
                $request,
                $response,
                $route->getMiddleware()
            );
        }
    }

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

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


<?php namespace Ordercloud\Support\CommandBus;

use ReflectionClass;

class ReflectionCommandHandlerTranslator implements CommandHandlerTranslator
{
    /**
     * @param Command $command
     *
     * @return string
     */
    public function translate(Command $command)
    {
        $commandClass = new ReflectionClass($command);

        return sprintf('%s\\Handlers\\%sHandler', $commandClass->getNamespaceName(), $commandClass->getShortName());
    }
}


<?php
/**
 * PEAR_XMLParser
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Stephan Schmidt (original XML_Unserializer code)
 * @copyright  1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version    CVS: $Id: XMLParser.php 313023 2011-07-06 19:17:11Z dufuz $
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Parser for any xml file
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @author    Stephan Schmidt (original XML_Unserializer code)
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license 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_XMLParser
{
    /**
     * unserilialized data
     * @var string $_serializedData
     */
    var $_unserializedData = null;

    /**
     * name of the root tag
     * @var string $_root
     */
    var $_root = null;

    /**
     * stack for all data that is found
     * @var array    $_dataStack
     */
    var $_dataStack = array();

    /**
     * stack for all values that are generated
     * @var array    $_valStack
     */
    var $_valStack = array();

    /**
     * current tag depth
     * @var int    $_depth
     */
    var $_depth = 0;

    /**
     * The XML encoding to use
     * @var string $encoding
     */
    var $encoding = 'ISO-8859-1';

    /**
     * @return array
     */
    function getData()
    {
        return $this->_unserializedData;
    }

    /**
     * @param string xml content
     * @return true|PEAR_Error
     */
    function parse($data)
    {
        if (!extension_loaded('xml')) {
            include_once 'PEAR.php';
            return PEAR::raiseError("XML Extension not found", 1);
        }
        $this->_dataStack =  $this->_valStack = array();
        $this->_depth = 0;

        if (
            strpos($data, 'encoding="UTF-8"')
            || strpos($data, 'encoding="utf-8"')
            || strpos($data, "encoding='UTF-8'")
            || strpos($data, "encoding='utf-8'")
        ) {
            $this->encoding = 'UTF-8';
        }

        if (version_compare(phpversion(), '5.0.0', 'lt') && $this->encoding == 'UTF-8') {
            $data = utf8_decode($data);
            $this->encoding = 'ISO-8859-1';
        }

        $xp = xml_parser_create($this->encoding);
        xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
        xml_set_object($xp, $this);
        xml_set_element_handler($xp, 'startHandler', 'endHandler');
        xml_set_character_data_handler($xp, 'cdataHandler');
        if (!xml_parse($xp, $data)) {
            $msg = xml_error_string(xml_get_error_code($xp));
            $line = xml_get_current_line_number($xp);
            xml_parser_free($xp);
            include_once 'PEAR.php';
            return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
        }
        xml_parser_free($xp);
        return true;
    }

    /**
     * Start element handler for XML parser
     *
     * @access private
     * @param  object $parser  XML parser object
     * @param  string $element XML element
     * @param  array  $attribs attributes of XML tag
     * @return void
     */
    function startHandler($parser, $element, $attribs)
    {
        $this->_depth++;
        $this->_dataStack[$this->_depth] = null;

        $val = array(
            'name'         => $element,
            'value'        => null,
            'type'         => 'string',
            'childrenKeys' => array(),
            'aggregKeys'   => array()
       );

        if (count($attribs) > 0) {
            $val['children'] = array();
            $val['type'] = 'array';
            $val['children']['attribs'] = $attribs;
        }

        array_push($this->_valStack, $val);
    }

    /**
     * post-process data
     *
     * @param string $data
     * @param string $element element name
     */
    function postProcess($data, $element)
    {
        return trim($data);
    }

    /**
     * End element handler for XML parser
     *
     * @access private
     * @param  object XML parser object
     * @param  string
     * @return void
     */
    function endHandler($parser, $element)
    {
        $value = array_pop($this->_valStack);
        $data  = $this->postProcess($this->_dataStack[$this->_depth], $element);

        // adjust type of the value
        switch (strtolower($value['type'])) {
            // unserialize an array
            case 'array':
                if ($data !== '') {
                    $value['children']['_content'] = $data;
                }

                $value['value'] = isset($value['children']) ? $value['children'] : array();
                break;

            /*
             * unserialize a null value
             */
            case 'null':
                $data = null;
                break;

            /*
             * unserialize any scalar value
             */
            default:
                settype($data, $value['type']);
                $value['value'] = $data;
                break;
        }

        $parent = array_pop($this->_valStack);
        if ($parent === null) {
            $this->_unserializedData = &$value['value'];
            $this->_root = &$value['name'];
            return true;
        }

        // parent has to be an array
        if (!isset($parent['children']) || !is_array($parent['children'])) {
            $parent['children'] = array();
            if ($parent['type'] != 'array') {
                $parent['type'] = 'array';
            }
        }

        if (!empty($value['name'])) {
            // there already has been a tag with this name
            if (in_array($value['name'], $parent['childrenKeys'])) {
                // no aggregate has been created for this tag
                if (!in_array($value['name'], $parent['aggregKeys'])) {
                    if (isset($parent['children'][$value['name']])) {
                        $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
                    } else {
                        $parent['children'][$value['name']] = array();
                    }
                    array_push($parent['aggregKeys'], $value['name']);
                }
                array_push($parent['children'][$value['name']], $value['value']);
            } else {
                $parent['children'][$value['name']] = &$value['value'];
                array_push($parent['childrenKeys'], $value['name']);
            }
        } else {
            array_push($parent['children'],$value['value']);
        }
        array_push($this->_valStack, $parent);

        $this->_depth--;
    }

    /**
     * Handler for character data
     *
     * @access private
     * @param  object XML parser object
     * @param  string CDATA
     * @return void
     */
    function cdataHandler($parser, $cdata)
    {
        $this->_dataStack[$this->_depth] .= $cdata;
    }
}


<?php

namespace Reaction\Web;

use Reaction;
use Reaction\Base\Component;
use Reaction\Exceptions\Exception;

/**
 * AssetConverter supports conversion of several popular script formats into JS or CSS scripts.
 *
 * It is used by [[AssetManager]] to convert files after they have been published.
 */
class AssetConverter extends Component implements AssetConverterInterface
{
    /**
     * @var array the commands that are used to perform the asset conversion.
     * The keys are the asset file extension names, and the values are the corresponding
     * target script types (either "css" or "js") and the commands used for the conversion.
     *
     * You may also use a [path alias](guide:concept-aliases) to specify the location of the command:
     *
     * ```php
     * [
     *     'styl' => ['css', '@app/node_modules/bin/stylus < {from} > {to}'],
     * ]
     * ```
     */
    public $commands = [
        'less' => ['css', 'lessc {from} {to} --no-color --source-map'],
        'scss' => ['css', 'sass {from} {to} --sourcemap'],
        'sass' => ['css', 'sass {from} {to} --sourcemap'],
        'styl' => ['css', 'stylus < {from} > {to}'],
        'coffee' => ['js', 'coffee -p {from} > {to}'],
        'ts' => ['js', 'tsc --out {to} {from}'],
    ];
    /**
     * @var bool whether the source asset file should be converted even if its result already exists.
     * You may want to set this to be `true` during the development stage to make sure the converted
     * assets are always up-to-date. Do not set this to true on production servers as it will
     * significantly degrade the performance.
     */
    public $forceConvert = false;

    /**
     * Converts a given asset file into a CSS or JS file.
     * @param string $asset the asset file path, relative to $basePath
     * @param string $basePath the directory the $asset is relative to.
     * @return string the converted asset file path, relative to $basePath.
     */
    public function convert($asset, $basePath)
    {
        $pos = strrpos($asset, '.');
        if ($pos !== false) {
            $ext = substr($asset, $pos + 1);
            if (isset($this->commands[$ext])) {
                list($ext, $command) = $this->commands[$ext];
                $result = substr($asset, 0, $pos + 1) . $ext;
                if ($this->forceConvert || @filemtime("$basePath/$result") < @filemtime("$basePath/$asset")) {
                    $this->runCommand($command, $basePath, $asset, $result);
                }

                return $result;
            }
        }

        return $asset;
    }

    /**
     * Runs a command to convert asset files.
     * @param string $command the command to run. If prefixed with an `@` it will be treated as a [path alias](guide:concept-aliases).
     * @param string $basePath asset base path and command working directory
     * @param string $asset the name of the asset file
     * @param string $result the name of the file to be generated by the converter command
     * @return bool true on success, false on failure. Failures will be logged.
     * @throws \Reaction\Exceptions\Exception when the command fails and YII_DEBUG is true.
     * In production mode the error will be logged.
     */
    protected function runCommand($command, $basePath, $asset, $result)
    {
        $command = Reaction::$app->getAlias($command);

        $command = strtr($command, [
            '{from}' => escapeshellarg("$basePath/$asset"),
            '{to}' => escapeshellarg("$basePath/$result"),
        ]);
        $descriptor = [
            1 => ['pipe', 'w'],
            2 => ['pipe', 'w'],
        ];
        $pipes = [];
        $proc = proc_open($command, $descriptor, $pipes, $basePath);
        $stdout = stream_get_contents($pipes[1]);
        $stderr = stream_get_contents($pipes[2]);
        foreach ($pipes as $pipe) {
            fclose($pipe);
        }
        $status = proc_close($proc);

        if ($status === 0) {
            Reaction::$app->logger->debug("Converted $asset into $result:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr");
        } elseif (Reaction::isDev()) {
            throw new Exception("AssetConverter command '$command' failed with exit code $status:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr");
        } else {
            Reaction::error("AssetConverter command '$command' failed with exit code $status:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr");
        }

        return $status === 0;
    }
}


<?php
/**
 * Created by PhpStorm.
 * User: gordon
 * Date: 20/3/2561
 * Time: 14:27 น.
 */
namespace Suilven\Notifier\Jobs;

use Maknz\Slack\Client;
use SilverStripe\Core\Injector\Injector;
use Symbiote\QueuedJobs\Services\AbstractQueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJob;

class NotifyViaSlackJob extends AbstractQueuedJob implements QueuedJob
{
    /**
     * @var string job type is queued
     */
    private $type = QueuedJob::IMMEDIATE;

    /**
     * Initialise job as immediate with no timing restrictions
     * @param string $webhookURL the URL to use to ping slack
     * @param string $message the message payload
     * @param null|string the channel to send to, blank for the webhook default
     * @param null $type the job type
     */
    public function __construct()
    {
        $this->type = QueuedJob::IMMEDIATE;
        $this->times = array();
    }

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

    /**
     * @return string
     */
    public function getTitle()
    {
        return "Slack Sender";
    }

    /**
     * Setup
     */
    public function setup()
    {
        $this->totalSteps = 1;
    }

    /**
     * Send the webhook to slack
     */
    public function process()
    {
        // $this->channel evaluates to blank in the following if, so store it as a variable
        $channel = $this->channel;

        $client = new Client($this->webhookURL);
        if (empty($channel)) {
            $client->send($this->message);
        } else {
            #Send to designated channel
            $client->to($this->channel)->send($this->message);
        }

        // required to terminate the job
        $this->isComplete = true;
        $this->currentStep = 1;
    }
}


<?php

declare(strict_types=1);

/**
 * States.
 *
 * LICENSE
 *
 * This source file is subject to the MIT license and the version 3 of the GPL3
 * license that are bundled with this package in the folder licences
 * 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 richarddeloge@gmail.com so we can send you a copy immediately.
 *
 *
 * @copyright   Copyright (c) 2009-2017 Richard Déloge (richarddeloge@gmail.com)
 *
 * @link        http://teknoo.software/states Project website
 *
 * @license     http://teknoo.software/license/mit         MIT License
 * @author      Richard Déloge <richarddeloge@gmail.com>
 */

namespace Teknoo\States\LifeCycle\Observing;

use Teknoo\States\LifeCycle\Event\EventDispatcherBridgeInterface;
use Teknoo\States\LifeCycle\StatedClass\LifeCyclableInterface;
use Teknoo\States\LifeCycle\Tokenization\TokenizerInterface;

/**
 * Class Observer
 * Default implementation to manage several observations of stated class instances and distpatch change to the system
 * via one or several event dispatcher *.
 *
 * @copyright   Copyright (c) 2009-2017 Richard Déloge (richarddeloge@gmail.com)
 *
 * @link        http://teknoo.software/states Project website
 *
 * @license     http://teknoo.software/license/mit         MIT License
 * @author      Richard Déloge <richarddeloge@gmail.com>
 */
class Observer implements ObserverInterface
{
    /**
     * Tokenizer to generate events name to use to distpach changes.
     *
     * @var TokenizerInterface
     */
    private $tokenizer;

    /**
     * List of dispatchers to use to dispatch an event from an observed's change.
     *
     * @var EventDispatcherBridgeInterface[]
     */
    private $dispatchersList = [];

    /**
     * List of observed stated class instance to dispatch instance's change.
     *
     * @var ObservedInterface[]
     */
    private $observedList = [];

    /**
     * Factory to generate new ObservedFactoryInterface to manage an observation.
     *
     * @var ObservedFactoryInterface
     */
    private $observedFactory;

    /**
     * @param ObservedFactoryInterface $observedFactory
     */
    public function __construct(ObservedFactoryInterface $observedFactory)
    {
        //Initialize collections
        $this->observedFactory = $observedFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function setTokenizer(TokenizerInterface $tokenizer): ObserverInterface
    {
        $this->tokenizer = $tokenizer;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getTokenizer(): TokenizerInterface
    {
        return $this->tokenizer;
    }

    /**
     * {@inheritdoc}
     */
    public function addEventDispatcher(EventDispatcherBridgeInterface $dispatcher): ObserverInterface
    {
        $this->dispatchersList[\spl_object_hash($dispatcher)] = $dispatcher;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function removeEventDispatcher(EventDispatcherBridgeInterface $dispatcher): ObserverInterface
    {
        $dispatcherHash = \spl_object_hash($dispatcher);
        if (isset($this->dispatchersList[$dispatcherHash])) {
            //Dispatcher not found, do nothing "silently"
            unset($this->dispatchersList[$dispatcherHash]);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function listEventDispatcher(): array
    {
        return $this->dispatchersList;
    }

    /**
     * {@inheritdoc}
     */
    public function attachObject(LifeCyclableInterface $object): ObservedInterface
    {
        $objectHash = \spl_object_hash($object);
        //Create the observed instance to manage the observation
        $observed = $this->observedFactory->create($this, $object);
        $object->registerObserver($observed);

        $this->observedList[$objectHash] = $observed;

        return $observed;
    }

    /**
     * {@inheritdoc}
     */
    public function detachObject(LifeCyclableInterface $object): ObserverInterface
    {
        $objectHash = \spl_object_hash($object);
        if (isset($this->observedList[$objectHash])) {
            $observed = $this->observedList[$objectHash];
            $object->unregisterObserver($observed);
            unset($this->observedList[$objectHash]);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function listObserved(): array
    {
        return $this->observedList;
    }

    /**
     * {@inheritdoc}
     */
    public function dispatchNotification(ObservedInterface $observed): ObserverInterface
    {
        //Extract from the observed the event and generate formated events name
        $event = $observed->getLastEvent();
        $eventsNamesList = $this->getTokenizer()->getToken($event);

        foreach ($eventsNamesList as $eventName) {
            foreach ($this->dispatchersList as $dispatcher) {
                $dispatcher->dispatch($eventName, $event);
            }
        }

        return $this;
    }
}


<?php

namespace Fenrizbes\CropBundle\Behavior;

use Fenrizbes\UploadableBehavior\Behavior\UploadableBehavior;

class CroppableBehavior extends \Behavior
{
    /**
     * {@inheritdoc}
     */
    protected $tableModificationOrder = 40;

    /**
     * {@inheritdoc}
     */
    protected $parameters = array(
        'columns' => 'image'
    );

    /**
     * Array of columns
     *
     * @var array
     */
    protected $columns;

    protected function getColumns()
    {
        if (is_null($this->columns)) {
            $this->columns = array();

            foreach (explode(',', $this->getParameter('columns')) as $column) {
                $this->columns[trim($column)] = trim($column) .'_coordinates';
            }
        }

        return $this->columns;
    }

    /**
     * {@inheritdoc}
     */
    public function modifyTable()
    {
        $table = $this->getTable();

        foreach ($this->getColumns() as $image_column => $coordinates_column) {
            if (!$table->hasColumn($image_column)) {
                $table->addColumn(array(
                    'name' => $image_column,
                    'type' => 'VARCHAR',
                    'size' => 255
                ));
            }

            if (!$table->hasColumn($coordinates_column)) {
                $table->addColumn(array(
                    'name' => $coordinates_column,
                    'type' => 'OBJECT'
                ));
            }
        }

        $this->modifyUploadableBehavior();
    }

    /**
     * Adds or modifies the uploadable behavior
     */
    protected function modifyUploadableBehavior()
    {
        $table = $this->getTable();

        if ($table->hasBehavior('uploadable')) {
            $uploadable = $table->getBehavior('uploadable');
            $parameters = $uploadable->getParameters();
            $up_columns = explode(',', $parameters['columns']);

            foreach (array_keys($this->getColumns()) as $column) {
                foreach ($up_columns as $up_column) {
                    if (trim($up_column) == $column) {
                        continue 2;
                    }
                }

                $up_columns[] = $column;
            }

            $parameters['columns'] = implode(',', $up_columns);
            $uploadable->setParameters($parameters);
        } else {
            $uploadable = new UploadableBehavior();
            $uploadable->setName('uploadable');
            $uploadable->setParameters(array(
                'columns' => implode(',', array_keys($this->getColumns()))
            ));

            $table->addBehavior($uploadable);
        }
    }

    /**
     * Constructs methods
     *
     * @return string
     */
    public function objectMethods()
    {
        $script = '';

        foreach ($this->getColumns() as $image_column => $coordinates_column) {
            $script .= $this->renderTemplate('setCroppableData', array(
                'image_column'       => $this->getTable()->getColumn($image_column)->getPhpName(),
                'coordinates_column' => $this->getTable()->getColumn($coordinates_column)->getPhpName()
            ));

            $script .= $this->renderTemplate('getCroppableData', array(
                'image_column'       => $this->getTable()->getColumn($image_column)->getPhpName(),
                'coordinates_column' => $this->getTable()->getColumn($coordinates_column)->getPhpName()
            ));
        }

        return $script;
    }
}


<?php
/*
 * This file is part of the Skeetr package.
 *
 * (c) Máximo Cuadros <mcuadros@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Skeetr\Client\RPC;

use UnexpectedValueException;

class Request
{
    private $id;
    private $method;
    private $params = [];

    /**
     * Configure the request based on a JSON
     *
     * @param  string  $json
     * @return boolean
     */
    public static function fromJSON($json)
    {
        $request = new static();
        print_r($json);
        $data = json_decode($json, true);
print_r($data);
        if (!$data) {
            throw new UnexpectedValueException(sprintf(
                'Unexpected message, invalid JSON from nginx: "%s"', $json
            ));
        }

        if (isset($data['id'])) {
            $request->setId($data['id']);
        }

        if (isset($data['method'])) {
            $request->setMethod($data['method']);
        }

        if (isset($data['params'])) {
            $request->setPrams($data['params']);
        }

        return $request;
    }

    /**
     * Sets the request id
     *
     * @param string $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * Sets method
     *
     * @param string $method
     */
    public function setMethod($method)
    {
        $this->method = $method;
    }

    /**
     * Sets params
     *
     * @param array $params request params
     */
    public function setPrams(Array $params)
    {
        $this->params = $params;
    }

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

    /**
     * Get method
     *
     * @return string
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * Get params
     *
     * @return array
     */
    public function getParams()
    {
        return $this->params;
    }

    /**
     * Returns a array with the values of this Request
     *
     * @return array
     */
    public function toArray()
    {
        return [
            'id' => $this->id,
            'method' => $this->method,
            'params' => $this->params
        ];
    }

    /**
     * Returns a JSON with the values of this Request
     *
     * @return string
     */
    public function toJSON()
    {
        return json_encode($this->toArray());
    }
}


<?php
namespace Soluble\Normalist\Synthetic\ResultSet;

use Soluble\Normalist\Synthetic\Table;
use Soluble\Normalist\Synthetic\Record;
use Soluble\Normalist\Synthetic\Exception;
use Soluble\Db\Sql\Select;
use Iterator;
use Countable;

class ResultSet implements Iterator, Countable
{
    /**
     *
     * @var \Zend\Db\ResultSet\ResultSet
     */
    protected $dataSource;

    /**
     * @var Table
     */
    protected $table;

    /**
     *
     * @var Select
     */
    protected $select;

    /**
     * @var null|int
     */
    protected $count = null;

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

    /**
     *
     * @var boolean
     */
    protected $has_complete_record_definition;

    /**
     *
     * @param Select $select Originating select object
     * @param Table $table Originating table
     * @param boolean $has_complete_record_definition
     */
    public function __construct(Select $select, Table $table, $has_complete_record_definition = false)
    {
        $this->select = $select;
        $this->table = $table;
        $this->has_complete_record_definition = $has_complete_record_definition;
        $this->dataSource = $select->execute();
    }

    /**
     * This method allows the results to be iterable multiple times
     * for database drivers that does not support rewind() method.
     * PDO_Mysql for example does not provide backward scrolling resultset,
     * They are forward only. MySQLi provides backward scrolling so this method
     * should not be used.
     *
     * @throws Zend\Db\ResultSet\Exception\RuntimeException Buffering must be enabled before iteration is started
     *
     * @return ResultSet
     */
    public function buffer()
    {
        $this->dataSource->buffer();
        return $this;
    }

    /**
     * Return an array version of the resultset
     * @return array
     */
    public function toArray()
    {
        return $this->dataSource->toArray();
    }

    /**
     * Return an json version of the resultset
     * @return string Json encoded version
     */
    public function toJson()
    {
        return json_encode($this->dataSource->toArray());
    }

    /**
     * Iterator: move pointer to next item
     *
     * @return void
     */
    public function next()
    {
        $this->dataSource->next();
        $this->position++;
    }

    /**
     * Iterator: retrieve current key
     *
     * @return mixed
     */
    public function key()
    {
        return $this->position;
    }

    /**
     * Iterator: get current item
     *
     * @throws Exception\LogicException whenever a record cannot be instanciated, due to missing column specs
     * @return Record
     */
    public function current()
    {
        $data = $this->dataSource->current();

        if (!$this->has_complete_record_definition) {
            $data_columns   = array_keys($this->table->getColumnsInformation());
            $record_columns = array_keys((array) $data);
            $matches = array_intersect($data_columns, $record_columns);
            if (count($matches) != count($data_columns)) {
                $missings = implode(',', array_diff($data_columns, $record_columns));
                $msg = __METHOD__ . ": Cannot create a Record due to incomplete or aliased column definition (missing: $missings).";
                $msg .= "Check whether columns have been modified in TableSearch::columns() method, or use an toArray(), toJson()... version of the ResultSet.";
                throw new Exception\LogicException($msg);
            }
            $this->has_complete_record_definition = true;
        }

        $record = $this->table->record($data, $ignore = true);
        $record->setState(Record::STATE_CLEAN);
        return $record;
    }

    /**
     * Iterator: is pointer valid?
     *
     * @return bool
     */
    public function valid()
    {
        return $this->dataSource->valid();
    }

    /**
     * Iterator: rewind
     *
     * @return void
     */
    public function rewind()
    {
        $this->position = 0;
    }

    /**
     * Countable: return count of rows
     *
     * @return int
     */
    public function count()
    {
        if ($this->count === null) {
            $this->count = $this->dataSource->count();
        }
        return $this->count;
    }
}


<?php
/**
 * This source file is part of Xloit project.
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the MIT License that is bundled with this package in the file LICENSE.
 * It is also available through the world-wide-web at this URL:
 * <http://www.opensource.org/licenses/mit-license.php>
 * 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@xloit.com> so we can send you a copy immediately.
 *
 * @license   MIT
 * @link      http://xloit.com
 * @copyright Copyright (c) 2016, Xloit. All rights reserved.
 */

namespace Xloit\Bridge\Zend\Session\SaveHandler\Database;

use Xloit\DateTime\DateTime;

/**
 * A {@link Database} class.
 *
 * @package Xloit\Bridge\Zend\Session\SaveHandler\Database
 */
class Database implements DatabaseInterface
{
    /**
     *
     *
     * @var Adapter\AdapterInterface
     */
    protected $adapter;

    /**
     * Holds the sessionName value.
     *
     * @var string
     */
    protected $sessionName;

    /**
     * Holds the sessionSavePath value.
     *
     * @var string
     */
    protected $sessionSavePath;

    /**
     * Holds the lifetime value.
     *
     * @var string
     */
    protected $lifetime;

    /**
     * MongoDB session save handler options.
     *
     * @var DatabaseOptions
     */
    protected $options;

    /**
     * Constructor to prevent {@link AbstractDatabase} from being loaded more than once.
     *
     * @param Adapter\AdapterInterface $adapter
     * @param DatabaseOptions          $options
     */
    public function __construct(Adapter\AdapterInterface $adapter, DatabaseOptions $options)
    {
        $adapter->setOptions($options);

        $this->adapter = $adapter;
        $this->options = $options;
        /** @noinspection PhpUsageOfSilenceOperatorInspection */
        $this->lifetime = @ini_get('session.gc_maxlifetime');
    }

    /**
     * Returns the SessionName value.
     *
     * @return string
     */
    public function getSessionName()
    {
        return $this->sessionName;
    }

    /**
     * Sets the SessionName value.
     *
     * @param string $sessionName
     *
     * @return $this
     */
    public function setSessionName($sessionName)
    {
        $this->sessionName = $sessionName;

        return $this;
    }

    /**
     * Returns the SessionSavePath value.
     *
     * @return string
     */
    public function getSessionSavePath()
    {
        return $this->sessionSavePath;
    }

    /**
     * Sets the SessionSavePath value.
     *
     * @param string $sessionSavePath
     *
     * @return $this
     */
    public function setSessionSavePath($sessionSavePath)
    {
        $this->sessionSavePath = $sessionSavePath;

        return $this;
    }

    /**
     * Returns the Lifetime value.
     *
     * @return string
     */
    public function getLifetime()
    {
        if (!$this->lifetime) {
            /** @noinspection PhpUsageOfSilenceOperatorInspection */
            $this->lifetime = @ini_get('session.gc_maxlifetime');
        }

        return $this->lifetime;
    }

    /**
     * Sets the Lifetime value.
     *
     * @param string $lifetime
     *
     * @return $this
     */
    public function setLifetime($lifetime)
    {
        $this->lifetime = $lifetime;

        return $this;
    }

    /**
     * Returns the Options value.
     *
     * @return DatabaseOptions
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Sets the Options value.
     *
     * @param DatabaseOptions $options
     *
     * @return $this
     */
    public function setOptions(DatabaseOptions $options)
    {
        $this->options = $options;

        return $this;
    }

    /**
     * Open Session - retrieve resources.
     *
     * @param string $savePath
     * @param string $name
     *
     * @return bool
     */
    public function open($savePath, $name)
    {
        $this->sessionSavePath = $savePath;
        $this->sessionName     = $name;

        return true;
    }

    /**
     * Close Session - free resources.
     *
     * @return bool
     */
    public function close()
    {
        return true;
    }

    /**
     * Read session data.
     *
     * @param string $id
     *
     * @return mixed
     * @throws \Zend\Json\Exception\RuntimeException
     */
    public function read($id)
    {
        $idColumn   = $this->options->getIdColumn();
        $nameColumn = $this->options->getNameColumn();
        $adapter    = $this->getAdapter();

        $sessionData = [
            $idColumn   => $id,
            $nameColumn => $this->sessionName
        ];

        $session = $adapter->select($sessionData);

        if ($session) {
            if ($adapter->isValid($session)) {
                return $this->sanitizeDataRead($id, $adapter->getDataValue($session));
            }

            $this->destroy($id);
        }

        return '';
    }

    /**
     * Returns the Adapter value.
     *
     * @return Adapter\AdapterInterface
     */
    public function getAdapter()
    {
        return $this->adapter;
    }

    /**
     * Sets the Adapter value.
     *
     * @param Adapter\AdapterInterface $adapter
     *
     * @return $this
     */
    public function setAdapter($adapter)
    {
        $this->adapter = $adapter;

        return $this;
    }

    /**
     * Destroy Session - remove data from resource for given session id.
     *
     * @param string $id
     *
     * @return bool
     */
    public function destroy($id)
    {
        $idColumn    = $this->options->getIdColumn();
        $nameColumn  = $this->options->getNameColumn();
        $adapter     = $this->getAdapter();
        $sessionData = [
            $idColumn   => $id,
            $nameColumn => $this->sessionName
        ];
        $session     = $adapter->select($sessionData);

        if ($session) {
            return (bool) $this->getAdapter()->delete($session);
        }

        return false;
    }

    /**
     * Write Session - commit data to resource.
     *
     * @param string $id
     * @param mixed  $data
     *
     * @return bool
     * @throws \InvalidArgumentException
     */
    public function write($id, $data)
    {
        $idColumn       = $this->options->getIdColumn();
        $nameColumn     = $this->options->getNameColumn();
        $dataColumn     = $this->options->getDataColumn();
        $modifiedColumn = $this->options->getModifiedColumn();
        $createdColumn  = $this->options->getCreatedColumn();
        $lifetimeColumn = $this->options->getLifetimeColumn();
        $adapter        = $this->getAdapter();

        $sessionData = [
            $idColumn   => $id,
            $nameColumn => $this->sessionName
        ];

        $session = $adapter->select($sessionData);

        $sessionData[$dataColumn]     = $this->sanitizeDataWrite($id, $data);
        $sessionData[$modifiedColumn] = new DateTime();

        if ($session) {
            return (bool) $adapter->update($session, $sessionData);
        }

        $sessionData[$lifetimeColumn] = $this->lifetime;
        $sessionData[$createdColumn]  = new DateTime();

        /** @noinspection PhpUndefinedMethodInspection */
        return (bool) $adapter->insert($sessionData);
    }

    /**
     * Garbage Collection - remove old session data older than the maximum lifetime (in seconds).
     *
     * @param int $maxLifetime
     *
     * @return bool
     */
    public function gc($maxLifetime)
    {
        return (bool) $this->getAdapter()->gc($maxLifetime);
    }

    /**
     *
     *
     * @param string $id
     * @param string $data
     *
     * @return string
     */
    protected function sanitizeDataRead(
        /** @noinspection PhpUnusedParameterInspection */
        $id, $data
    ) {
        return (string) $data;
    }

    /**
     *
     *
     * @param string $id
     * @param string $data
     *
     * @return string
     */
    protected function sanitizeDataWrite(
        /** @noinspection PhpUnusedParameterInspection */
        $id, $data
    ) {
        return (string) $data;
    }
}