<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa\Query
 * @author    Hong Zhang <phossa@126.com>
 * @copyright 2015 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa\Query;

use Phossa\Query\Statement\Raw;
use Phossa\Query\Dialect\Common;
use Phossa\Query\Message\Message;
use Phossa\Query\Statement\Expression;
use Phossa\Query\Builder\SettingsTrait;
use Phossa\Query\Builder\ParameterTrait;
use Phossa\Query\Statement\RawInterface;
use Phossa\Query\Statement\PreviousTrait;
use Phossa\Query\Dialect\DialectInterface;
use Phossa\Query\Builder\BuilderInterface;
use Phossa\Query\Dialect\DialectAwareTrait;
use Phossa\Query\Builder\ExecutorAwareTrait;
use Phossa\Query\Statement\StatementInterface;
use Phossa\Query\Statement\ExpressionInterface;
use Phossa\Query\Dialect\Common\CreateInterface;
use Phossa\Query\Exception\BadMethodCallException;
use Phossa\Query\Dialect\Common\SelectStatementInterface;
use Phossa\Query\Dialect\Common\InsertStatementInterface;
use Phossa\Query\Dialect\Common\UpdateStatementInterface;
use Phossa\Query\Dialect\Common\DeleteStatementInterface;

/**
 * Query Builder
 *
 * ```php
 * // create a builder with table specified
 * $user = (new Builder())->table('User');
 *
 * // SELECT * FROM `User`
 * $select = $user->select();
 *
 * // INSERT INTO `User` ...
 * $insert = $user->insert()->...
 * ```
 *
 * @package Phossa\Query
 * @author  Hong Zhang <phossa@126.com>
 * @see     BuilderInterface
 * @version 1.0.0
 * @since   1.0.0 added
 */
class Builder implements BuilderInterface
{
    use SettingsTrait,
        PreviousTrait,
        ParameterTrait,
        DialectAwareTrait,
        ExecutorAwareTrait;

    /**
     * tables
     *
     * @var    array
     * @access protected
     */
    protected $tables;

    /**
     * Constructor
     *
     * ```php
     * // builder with default table `users`
     * $users = new Builder(new Mysql(), 'users')
     *
     * // builder with defult tables:  `users` and `accounts` AS `a`
     * $builder = new Builder(new Mysql(), ['users', 'accounts' => 'a'])
     *
     * // change default settings
     * $builder = new Builder(new Mysql(), false, ['autoQuote' => false]);
     * ```
     *
     * @param  DialectInterface $dialect default dialect is `Common`
     * @param  string|array $table table[s] to build upon
     * @param  array $settings builder settings
     * @access public
     */
    public function __construct(
        DialectInterface $dialect = null,
        $table = '',
        array $settings = []
    ) {
        // settings
        $this->combineSettings($settings);

        // default to Common
        $this->setDialect($dialect ?: new Common());

        // set default table if any
        $this->tables = $this->fixTable($table);
    }

    /**
     * {@inheritDoc}
     */
    public function expr()/*# : ExpressionInterface */
    {
        return new Expression($this);
    }

    /**
     * {@inheritDoc}
     */
    public function raw(/*# string */ $string)/*# : RawInterface */
    {
        // get values from argument list
        if (func_num_args() > 1) {
            $values = func_get_args();
            array_shift($values);

            // replacement
            $pat = $rep = [];
            foreach ($values as $val) {
                $pat[] = '/\?/';
                $rep[] = $this->generatePlaceholder($val);
            }

            return new Raw(preg_replace($pat, $rep, $string, 1), $this);
        } else {
            return new Raw($string, $this);
        }
    }

    /**
     * Clone the builder and set default table[s]
     *
     * ```php
     * // a user table query builder
     * $user = $builder->table('user', 'u');
     *
     * // working on user table
     * $user->select()->...
     * ```
     *
     * {@inheritDoc}
     */
    public function table($table, /*# string */ $tableAlias = '')
    {
        $tbl = $this->fixTable($table, $tableAlias);

        // clone the builder if table different
        if ($tbl != $this->tables) {
            $clone = clone $this;
            $clone->tables = $tbl;
            return $clone;
        } else {
            return $this;
        }
    }

    /**
     * Alias of self::table()
     *
     * @see    self::table()
     */
    public function from($table, /*# string */ $tableAlias = '')
    {
        return $this->table($table, $tableAlias);
    }

    /**
     * Set $col to FALSE if do NOT want table pass to $select
     *
     * {@inheritDoc}
     */
    public function select(
        $col = '',
        /*# string */ $colAlias = ''
    )/*# : SelectStatementInterface */ {
        /* @var $select SelectStatementInterface */
        $select = $this->getDialectStatement('select', false !== $col);

        // set columns/fields
        if (!empty($col)) {
            $select->col($col, $colAlias);
        }

        return $select;
    }

    /**
     * {@inheritDoc}
     */
    public function insert(array $values = [])/*# : InsertStatementInterface */
    {
        /* @var $insert InsertStatementInterface */
        $insert = $this->getDialectStatement('insert');

        // sets
        if (!empty($values)) {
            $insert->set($values);
        }

        return $insert;
    }

    /**
     * {@inheritDoc}
     */
    public function replace(array $values = [])/*# : ReplaceStatementInterface */
    {
        /* @var $replace ReplaceStatementInterface */
        $replace = $this->getDialectStatement('replace');

        // set cols
        if (!empty($values)) {
            $replace->set($values);
        }

        return $replace;
    }

    /**
     * {@inheritDoc}
     */
    public function update(array $values = [])/*# : UpdateStatementInterface */
    {
        /* @var $update UpdateStatementInterface */
        $update = $this->getDialectStatement('update');

        // sets
        if (!empty($values)) {
            $update->set($values);
        }

        return $update;
    }

    /**
     * {@inheritDoc}
     */
    public function delete($records = '')/*# : DeleteStatementInterface */
    {
        /* @var $delete DeleteStatementInterface */
        $delete = $this->getDialectStatement('delete');

        // table records
        if (!empty($records)) {
            $delete->record($records);
        }

        return $delete;
    }

    /**
     * {@inheritDoc}
     */
    public function create()/*# : CreateInterface */
    {
        return $this->getDialect()->create($this);
    }

    /**
     * Get the statement object
     *
     * @param  string $method
     * @param  bool $setTable set with builder tables
     * @return StatementInterface
     * @throws BadMethodCallException if no method found for this dialect
     * @access protected
     */
    protected function getDialectStatement(
        /*# string */ $method,
        /*# bool */ $setTable = true
    )/*# StatementInterface */ {
        // dialect
        $dialect = $this->getDialect();

        // check method
        if (!method_exists($dialect, $method)) {
            throw new BadMethodCallException(
                Message::get(Message::BUILDER_UNKNOWN_METHOD, $method),
                Message::BUILDER_UNKNOWN_METHOD
            );
        }

        /* @var $statement StatementInterface */
        $statement = call_user_func([$dialect, $method], $this);

        // prevous statement like in UNION
        if ($this->hasPrevious()) {
            $statement->setPrevious($this->getPrevious());
            $this->setPrevious(null);

        // set tables
        } elseif ($setTable && count($this->tables)) {
            if (method_exists($statement, 'from')) {

                // FROM all tables
                $statement->from($this->tables);
            } else {

                // INTO the first table
                $statement->into($this->tables[array_keys($this->tables)[0]]);
            }
        }

        return $statement;
    }

    /**
     * fix table notation
     *
     * @param  mixed $table
     * @param  string $tableAlias
     * @return array
     * @access protected
     */
    protected function fixTable(
        $table,
        /*# string */ $tableAlias = ''
    )/*# : array */ {
        if (empty($table)) {
            $table = [];
        } else {
            if (!is_array($table)) {
                $table = empty($tableAlias) ? [$table] :
                [$table => $tableAlias];
            }
        }
        return $table;
    }
}


<?php

namespace Qck;

/**
 * Session Management for a user
 *
 * @author muellerm
 */
class Session implements \Qck\Interfaces\Session
{

    function __construct( \Qck\Interfaces\IpAddress $IpAddress = null, \Qck\Interfaces\Browser $Browser = null, $SessionDir = null )
    {
        $this->IpAddress  = $IpAddress;
        $this->Browser    = $Browser;
        $this->SessionDir = $SessionDir;
    }

    public function getUsername()
    {
        $this->startOrRestart();
        return isset( $_SESSION[ "Username" ] ) ? $_SESSION[ "Username" ] : null;
    }

    public function startSession( $Username, $TimeOutSecs = 900 )
    {
        $this->startOrRestart();
        session_regenerate_id( true );
        $_SESSION[ "Username" ]    = $Username;
        $_SESSION[ "TimeOutSecs" ] = $TimeOutSecs;
    }

    function stopSession()
    {
        $this->startOrRestart();
        session_unset();
        session_destroy();
    }

    // will start a new session OR
    protected function startOrRestart()
    {
        // if we have an active session: stop here
        if ( session_status() == PHP_SESSION_ACTIVE )
            return;

        // set the session dir if needed
        if ( $this->SessionDir )
        {
            if ( !file_exists( $this->SessionDir ) )
            {
                mkdir( $this->SessionDir, 0777, true );
            }
            session_save_path( $this->SessionDir );
        }

        // start the session
        session_start();

        // check ip and browser info first
        $FingerPrint = "";
        if ( $this->IpAddress )
        {
            if ( !$this->IpAddress->isValid() )
            {
                session_unset();
                session_destroy();
                throw new \Exception(
                        "Cannot start session. Reason: Invalid IP " . $this->IpAddress->getValue() . " detected", 403 );
            }
            else
                $FingerPrint = $this->IpAddress->getValue();
        }

        if ( $this->Browser )
        {
            if ( !$this->Browser->isKnownBrowser() )
            {
                session_unset();
                session_destroy();
                throw new \Exception(
                        "Cannot start session. Reason: Invalid Browser " . $this->Browser->getSignature() . " detected.", 403 );
            }
            else
                $FingerPrint .= $this->Browser->getSignature();
        }

        // now check for changes if we had a session before or a timeout
        $currFp = md5( $FingerPrint );
        $prevFp = isset( $_SESSION[ "FingerPrint" ] ) ? $_SESSION[ "FingerPrint" ] : null;
        if ( $prevFp )
        {
            if ( $prevFp != $currFp )
            {
                session_unset();
                session_destroy();
                throw new \Exception( "Cannot start session. Reason: IP changed. Current is $currFp, previous was: $prevFp", Interfaces\HttpResponder::EXIT_CODE_UNAUTHORIZED );
            }
        }

        // check timeout
        $currTime    = time();
        $prevTime    = isset( $_SESSION[ "LastSessionStart" ] ) ? $_SESSION[ "LastSessionStart" ] : null;
        $timeOutSecs = isset( $_SESSION[ "TimeOutSecs" ] ) ? $_SESSION[ "TimeOutSecs" ] : null;
        if ( $prevTime && $timeOutSecs )
        {
            if ( $prevTime + $timeOutSecs < $currTime )
            {
                session_unset();
                session_destroy();
                throw new \Exception( "Session timeout", Interfaces\HttpResponder::EXIT_CODE_UNAUTHORIZED );
            }
        }

        $_SESSION[ "FingerPrint" ]      = $currFp;
        $_SESSION[ "LastSessionStart" ] = $currTime;
    }

    /**
     *
     * @var \Qck\Interfaces\IpAddress
     */
    protected $IpAddress;

    /**
     *
     * @var \Qck\Interfaces\Browser
     */
    protected $Browser;

    /**
     *
     * @var string
     */
    protected $SessionDir;

}


<?php
/*
 * Copyright (c) 2014 @trashtoy
 * https://github.com/trashtoy/
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
 * Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/**
 * PHP class file.
 * @auhtor trashtoy
 * @since  2.0.0
 */
namespace Peach\Markup;
use Peach\Util\Strings;

/**
 * 与えられたノードを HTML や XML などの文字列に変換するクラスです.
 */
class DefaultContext extends Context
{
    /**
     * マークアップ時の改行やインデント処理を担当します.
     * @var Indent
     */
    private $indent;

    /**
     * タグの出力方式 (空要素や boolean 属性などの扱い) を制御します.
     * @var Renderer
     */
    private $renderer;

    /**
     * 開始タグの直後に改行するかどうかの判定を行います.
     * @var BreakControl
     */
    private $breakControl;

    /**
     * TRUE の場合はノードの前後にインデントと改行を付加します.
     * @var bool
     */
    private $isIndentMode;

    /**
     * TRUE の場合はコメントの内部を処理している状態とみなします.
     * コメントの内部にあるコメントは無視するようになります.
     * @var bool
     */
    private $isCommentMode;

    /**
     * handle() メソッド実行時の処理結果が格納されます.
     * @var string
     */
    private $result;

    /**
     * 指定された Renderer, Indent, BreakControl オブジェクトを使って
     * マークアップを行う DefaultContext オブジェクトを構築します.
     *
     * @param Renderer     $renderer
     * @param Indent       $indent
     * @param BreakControl $breakControl
     */
    public function __construct(Renderer $renderer, Indent $indent = null, BreakControl $breakControl = null)
    {
        if (!isset($indent)) {
            $indent = new Indent();
        }
        if (!isset($breakControl)) {
            $breakControl = DefaultBreakControl::getInstance();
        }
        $this->renderer      = $renderer;
        $this->indent        = $indent;
        $this->breakControl  = $breakControl;
        $this->isIndentMode  = true;
        $this->isCommentMode = false;
        $this->result        = "";
    }

    /**
     * コメントノードを読み込みます.
     * @param Comment $comment
     */
    public function handleComment(Comment $comment)
    {
        if ($this->isCommentMode) {
            $this->formatChildNodes($comment);
            return;
        }

        $this->isCommentMode = true;
        $prefix = $this->escapeEndComment($comment->getPrefix());
        $suffix = $this->escapeEndComment($comment->getSuffix());
        $this->result .= $this->indent() . "<!--{$prefix}";
        if ($this->isIndentMode) {
            if ($this->checkBreakModeInComment($comment)) {
                $breakCode = $this->breakCode();
                $this->result .= $breakCode;
                $this->formatChildNodes($comment);
                $this->result .= $breakCode;
                $this->result .= $this->indent();
            } else {
                $this->isIndentMode = false;
                $this->formatChildNodes($comment);
                $this->isIndentMode = true;
            }
        } else {
            $this->formatChildNodes($comment);
        }
        $this->result .= "{$suffix}-->";
        $this->isCommentMode = false;
    }

    /**
     * コメントノードを 1 行 ("<--foobar-->") で記述するか改行するかの判定を行います.
     *
     * @param  Comment $comment
     * @return bool
     */
    private function checkBreakModeInComment(Comment $comment)
    {
        $nodes = $comment->getChildNodes();
        switch (count($nodes)) {
            case 0:
                return false;
            case 1:
                $node = $nodes[0];
                if ($node instanceof Comment) {
                    return $this->checkBreakModeInComment($node);
                }

                return ($node instanceof Element);
            default:
                return true;
        }
    }

    /**
     * Text ノードを読み込みます.
     * @param Text $text
     */
    public function handleText(Text $text) {
        $this->result .= $this->indent() . $this->escape($text->getText());
    }

    /**
     * Code を読み込みます.
     * @param Code $code
     */
    public function handleCode(Code $code)
    {
        $text   = $code->getText();
        if (!strlen($text)) {
            return;
        }

        $lines  = Strings::getLines($text);
        $indent = $this->indent();
        $this->result .= $indent;
        $this->result .= implode($this->breakCode() . $indent, $lines);
    }

    /**
     * EmptyElement を読み込みます.
     * @param EmptyElement $element
     * @see Context::handleEmptyElement()
     */
    public function handleEmptyElement(EmptyElement $element) {
        $this->result .= $this->indent() . $this->renderer->formatEmptyTag($element);
    }

    /**
     * ContainerElement を読み込みます.
     * @param ContainerElement $element
     * @see Context::handleContainerElement()
     */
    public function handleContainerElement(ContainerElement $element)
    {
        $this->result .= $this->indent() . $this->renderer->formatStartTag($element);
        if ($this->isIndentMode) {
            if ($this->breakControl->breaks($element)) {
                $this->result .= $this->indent->stepUp();
                $this->result .= $this->formatChildNodes($element);
                $this->result .= $this->breakCode();
                $this->result .= $this->indent->stepDown();
            } else {
                $this->isIndentMode = false;
                $this->formatChildNodes($element);
                $this->isIndentMode = true;
            }
        } else {
           $this->formatChildNodes($element);
        }
        $this->result .= $this->renderer->formatEndTag($element);
    }

    /**
     * NodeList を変換します.
     * @param NodeList $node
     */
    public function handleNodeList(NodeList $node)
    {
        $this->formatChildNodes($node);
    }

    /**
     * マークアップされたコードを返します.
     * @return string
     */
    public function getResult()
    {
        return $this->result;
    }

    /**
     * 指定されたコンテナの子ノードを書式化します.
     * 各子ノードの出力結果の末尾には, 改行コードで連結されます. (インデントモードが ON の場合)
     * 末尾の子ノードの出力結果の後ろに改行コードは付きません.
     *
     * @param Container $container
     */
    private function formatChildNodes(Container $container)
    {
        $nextBreak  = "";
        $breakCode  = $this->breakCode();
        $childNodes = $container->getChildNodes();
        foreach ($childNodes as $child) {
            $this->result .= $nextBreak;
            $this->handle($child);
            $nextBreak = $breakCode;
        }
    }

    /**
     * None を処理します. 何もせずに終了します.
     *
     * @param None $none
     */
    public function handleNone(None $none)
    {
    }

    /**
     * インデントモードが ON の場合は空白文字, OFF の場合は空文字列を返します.
     * @return string
     */
    private function indent()
    {
        return $this->isIndentMode ? $this->indent->indent() : "";
    }

    /**
     * インデントモードが ON の場合は改行コード, OFF の場合は空文字列を返します.
     * @return string
     */
    private function breakCode()
    {
        return $this->isIndentMode ? $this->indent->breakCode() : "";
    }

    /**
     * 予期しないインデントを回避するため, 改行コードを文字参照に置き換えます.
     * @param  string $text
     * @return string
     */
    private function escape($text)
    {
        return preg_replace("/\\r\\n|\\r|\\n/", "
", htmlspecialchars($text));
    }

    /**
     * 意図しないタイミングでコメントノードが終了するのを防ぐため, "-->" を文字参照に置き換えます.
     * @param  string $text
     * @return string
     */
    private function escapeEndComment($text)
    {
        return str_replace("-->", "-->", $text);
    }
}


<?php
namespace Yoanm\BehatUtilsExtension\ServiceContainer\Configuration;

use Monolog\Logger;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class LoggerConfiguration implements ConfigurationInterface
{
    /**
     * {@inheritdoc}
     */
    public function getConfigNode()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('logger');
        $rootNode
            ->addDefaultsIfNotSet()
            ->children()
                ->scalarNode('path')
                    ->info('Name of the log file')
                    ->defaultValue('behat.log')
                ->end()
                ->scalarNode('level')
                    ->info('Log level')
                    ->beforeNormalization()
                        ->always()
                        ->then(function ($value) {
                            return Logger::toMonologLevel($value);
                        })
                    ->end()
                    ->defaultValue(Logger::INFO)
                ->end()
            ->end();

        return $rootNode;
    }
}


<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa\Query
 * @author    Hong Zhang <phossa@126.com>
 * @copyright 2015 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa\Query\Clause;

use Phossa\Query\Statement\RawInterface;
use Phossa\Query\Statement\StatementInterface;

/**
 * ValueTrait
 *
 * Dealing with value of WHERE, SET etc.
 *
 * @package Phossa\Query
 * @author  Hong Zhang <phossa@126.com>
 * @version 1.0.0
 * @since   1.0.0 added
 */
trait ValueTrait
{
    /**
     * Process value
     *
     * @param  mixed $value
     * @return string placeholder or value
     * @access protected
     */
    protected function processValue($value)/*# : string */
    {
        // object
        if (is_object($value)) {
            if ($value instanceof RawInterface) {
                return $value->getStatement([], false);
            } elseif ($value instanceof StatementInterface) {
                return '(' . $value->getStatement([], false) . ')';
            }
        }

        // scalar
        if (is_null($value)) {
            return 'NULL';
        } else {
            return $this->getPlaceholder($value);
        }
    }

    /* from ParameterAwareTrait */
    abstract protected function getPlaceholder($value)/*# : string */;
}


<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa\Query
 * @author    Hong Zhang <phossa@126.com>
 * @copyright 2015 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa\Query\Dialect\Common;

use Phossa\Query\Clause\SetTrait;
use Phossa\Query\Clause\IntoTrait;
use Phossa\Query\Clause\ValueTrait;
use Phossa\Query\Statement\StatementAbstract;

/**
 * Insert
 *
 * @package Phossa\Query
 * @author  Hong Zhang <phossa@126.com>
 * @see     InsertStatementInterface
 * @version 1.0.0
 * @since   1.0.0 added
 */
class Insert extends StatementAbstract implements InsertStatementInterface
{
    use IntoTrait, SetTrait, ValueTrait;

    /**
     * Statement type
     *
     * @var    string
     * @access protected
     */
    protected $type = 'INSERT';

    /**
     * clauses ordering
     *
     * @var    int
     * @access protected
     */
    const ORDER_INTO   = 10;
    const ORDER_SET    = 20;
    const ORDER_VALUES = 25;

    /**
     * order, prefix, join char
     *
     * @var    array
     * @access protected
     */
    protected $config = [
        // into
        self::ORDER_INTO  => [
            'prefix'    => '',
            'func'      => 'buildInto',
            'join'      => '',
            'indent'    => false,
        ],

        // set cols
        self::ORDER_SET => [
            'prefix'    => '',
            'func'      => 'buildSet',
            'join'      => '',
            'indent'    => true,
        ],

        // build values
        self::ORDER_VALUES => [
            'prefix'    => 'VALUES',
            'func'      => 'buildValues',
            'join'      => '',
            'indent'    => true,
        ],
    ];

    /**
     * INSERT ... SELECT
     *
     * {@inheritDoc}
     */
    public function select(
        $col = '',
        /*# string */ $colAlias = ''
    )/*# : SelectStatementInterface */ {
        return $this->getBuilder()->setPrevious($this)->select($col, $colAlias);
    }
}


<?php
declare(strict_types=1);
/**
 * Caridea
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 * @copyright 2015-2018 LibreWorks contributors
 * @license   Apache-2.0
 */
namespace Caridea\Http;

use Psr\Http\Message\UriInterface;
use Psr\Http\Message\ResponseInterface;

/**
 * An implementation of RFC 7807, Problem Details for HTTP APIs.
 *
 * @copyright 2015-2018 LibreWorks contributors
 * @license   Apache-2.0
 * @see https://tools.ietf.org/html/rfc7807
 */
class ProblemDetails implements \JsonSerializable
{
    const MIME_TYPE_JSON = 'application/problem+json';
    const REGEX_NAMES = '/^[a-z][a-z0-9_]{2,}$/i';

    /**
     * @var \Psr\Http\Message\UriInterface An absolute URI that identifies the problem type
     */
    protected $type;
    /**
     * @var string A short, human-readable summary of the problem type
     */
    protected $title;
    /**
     * @var int The HTTP status code generated by the origin server for this occurrence of the problem
     */
    protected $status;
    /**
     * @var string A human-readable explanation specific to this occurrence of the problem
     */
    protected $detail;
    /**
     * @var \Psr\Http\Message\UriInterface An absolute URI that identifies the specific occurrence of the problem
     */
    protected $instance;
    /**
     * @var array<string,mixed> Map of `string` names to `mixed` values
     */
    protected $extensions = [];
    /**
     * @var array Cached output
     */
    protected $output;

    /**
     * Creates a new ProblemDetails.
     *
     * The `extensions` parameter, if provided, must be an associative array
     * matching names to values. Each name must follow the guidelines in the
     * RFC, namely start with a letter, be at least three characters long, and
     * only contain alpha, digit, and the underscore. The values can be of any
     * type, but be aware that the values must be easily converted to JSON. You
     * pretty much always want these values to be immutable.
     *
     * @param \Psr\Http\Message\UriInterface|null $type An absolute URI that identifies the problem type
     * @param string|null $title A short, human-readable summary of the problem type
     * @param int $status The HTTP status code generated by the origin server for this occurrence of the problem
     * @param string|null $detail A human-readable explanation specific to this occurrence of the problem
     * @param \Psr\Http\Message\UriInterface|null $instance An absolute URI that identifies the specific occurrence of the problem
     * @param array $extensions Additional members to the ProblemDetails
     */
    public function __construct(UriInterface $type = null, string $title = null, int $status = 0, string $detail = null, \Psr\Http\Message\UriInterface $instance = null, array $extensions = [])
    {
        $this->type = $type;
        $this->title = $title;
        $this->status = $status;
        $this->detail = $detail;
        $this->instance = $instance;
        array_walk($extensions, function ($v, $k) {
            if (!preg_match(self::REGEX_NAMES, (string) $k) || property_exists($this, (string) $k)) {
                throw new \InvalidArgumentException("Invalid extension name: '$k'");
            }
        });
        $this->extensions = $extensions;
    }

    /**
     * Gets the absolute URI that identifies the problem type
     *
     * @return \Psr\Http\Message\UriInterface|null The problem type URI (or null)
     */
    public function getType(): ?UriInterface
    {
        return $this->type;
    }

    /**
     * Gets the short, human-readable summary of the problem type.
     *
     * @return string|null A summary of the problem type
     */
    public function getTitle(): ?string
    {
        return $this->title;
    }

    /**
     * Gets the HTTP status code generated by the origin server for this occurrence of the problem
     *
     * @return int The status code
     */
    public function getStatus(): int
    {
        return $this->status;
    }

    /**
     * Gets a human readable explanation specific to this occurrence of the problem.
     *
     * @return string|null An explanation specific to this occurrence of the problem
     */
    public function getDetail(): ?string
    {
        return $this->detail;
    }

    /**
     * Gets the absolute URI that identifies the specific occurrence of the problem.
     *
     * @return \Psr\Http\Message\UriInterface|null The URI that identifies the specific occurrence of the problem (or null)
     */
    public function getInstance(): ?UriInterface
    {
        return $this->instance;
    }

    /**
     * Gets an array of any extension members defined.
     *
     * @return array Any extension members, never null.
     */
    public function getExtensions(): array
    {
        return $this->extensions;
    }

    /**
     * Returns a JSON representation of this problem.
     *
     * @return string The JSON representation
     */
    public function __toString(): string
    {
        return $this->toJson();
    }

    /**
     * A JSON representation of this problem.
     *
     * @return string The JSON representation
     */
    public function toJson(): string
    {
        return json_encode($this->toArray());
    }

    /**
     * Gets a serializable representation of this problem.
     *
     * @return array<string,mixed> This problem detail as an associative array
     */
    public function toArray(): array
    {
        if (empty($this->output)) {
            $problem = [
                'type' => $this->type ? (string)$this->type : 'about:blank'
            ];
            if ($this->title) {
                $problem['title'] = $this->title;
            }
            if ($this->status) {
                $problem['status'] = $this->status;
            }
            if ($this->detail) {
                $problem['detail'] = $this->detail;
            }
            if ($this->instance) {
                $problem['instance'] = (string)$this->instance;
            }
            $this->output = array_merge($problem, $this->extensions);
        }
        return $this->output;
    }

    /**
     * Returns the JSON representation.
     *
     * @return array<string,mixed> This problem detail as an associative array
     */
    public function jsonSerialize()
    {
        return $this->toArray();
    }

    /**
     * Adds this problem detail to a PSR-7 HTTP response.
     *
     * @param ResponseInterface $response The HTTP response
     * @return ResponseInterface The new response
     */
    public function send(ResponseInterface $response): ResponseInterface
    {
        $response->getBody()->write(json_encode($this->toArray()));
        return $response->withHeader('Content-Type', self::MIME_TYPE_JSON);
    }
}


<?php

namespace futuretek\shared;

use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberUtil;

/**
 * Class Validate
 *
 * @package futuretek\shared
 * @author  Lukas Cerny <lukas.cerny@futuretek.cz>
 * @license Apache-2.0
 * @link    http://www.futuretek.cz
 */
class Validate
{
    const PASSWORD_COMPLEXITY_WEAK = 2;
    const PASSWORD_COMPLEXITY_MEDIUM = 3;
    const PASSWORD_COMPLEXITY_STRONG = 4;
    const PASSWORD_COMPLEXITY_VERY_STRONG = 6;

    /**
     * Administrator password length
     */
    const ADMIN_PASSWORD_LENGTH = 8;
    /**
     * User password length
     */
    const PASSWORD_LENGTH = 5;

    /**
     * Check for e-mail validity
     *
     * @param string $email e-mail address to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isEmail($email)
    {
        return preg_match(
            '/^[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+(?:[.]?[_a-z\p{L}0-9-])*\.[a-z\p{L}0-9]+$/ui',
            $email
        );
    }

    /**
     * Check for MD5 string validity
     *
     * @param string $md5 MD5 string to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isMd5($md5)
    {
        return preg_match('/^[a-f0-9A-F]{32}$/', $md5);
    }

    /**
     * Check for SHA1 string validity
     *
     * @param string $sha1 SHA1 string to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isSha1($sha1)
    {
        return preg_match('/^[a-fA-F0-9]{40}$/', $sha1);
    }

    /**
     * Check for a float number validity
     *
     * @param float $float Float number to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isFloat($float)
    {
        return (string)(float)$float === (string)$float;
    }

    /**
     * Check for a unsigned float number validity
     *
     * @param float $float Float number to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isUnsignedFloat($float)
    {
        return (string)(float)$float === (string)$float && $float >= 0;
    }

    /**
     * Check for a float number validity (or empty)
     *
     * @param float $float Float number to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isOptFloat($float)
    {
        return $float === null || self::isFloat($float);
    }

    /**
     * Check for sender name validity
     *
     * @param string $mail_name Sender name to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isMailName($mail_name)
    {
        return (\is_string($mail_name) && preg_match('/^[^<>;=#{}]*$/u', $mail_name));
    }

    /**
     * Check for e-mail subject validity
     *
     * @param string $mail_subject e-mail subject to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isMailSubject($mail_subject)
    {
        return preg_match('/^[^<>]*$/u', $mail_subject);
    }

    /**
     * Check for price validity
     *
     * @param string $price Price to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isPrice($price)
    {
        return preg_match('/^\d{1,10}(\.\d{1,9})?$/', $price);
    }

    /**
     * Check for price validity (including negative price)
     *
     * @param string $price Price to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isNegativePrice($price)
    {
        return preg_match('/^[-]?\d{1,10}(\.\d{1,9})?$/', $price);
    }

    /**
     * Check for language code (ISO) validity
     *
     * @param string $iso_code Language code (ISO) to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isLanguageIsoCode($iso_code)
    {
        return preg_match('/^[a-zA-Z]{2,3}$/', $iso_code);
    }

    /**
     * Check for language code validity (eg. cs_CZ)
     *
     * @param string $s Language code to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isLanguageCode($s)
    {
        return preg_match('/^[a-zA-Z]{2}(-[a-zA-Z]{2})?$/', $s);
    }

    public static function isStateIsoCode($iso_code)
    {
        return preg_match('/^[a-zA-Z0-9]{1,4}((-)[a-zA-Z0-9]{1,4})?$/', $iso_code);
    }

    public static function isNumericIsoCode($iso_code)
    {
        return preg_match('/^\d{2,3}$/', $iso_code);
    }

    /**
     * Check for a postal address validity
     *
     * @param string $address Address to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isAddress($address)
    {
        return preg_match('/^[^!<>?=+@{}_$%]*$/u', $address);
    }

    /**
     * Check for city name validity
     *
     * @param string $city City name to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isCityName($city)
    {
        return preg_match('/^[^!<>;?=+@#"°{}_$%]*$/u', $city);
    }

    /**
     * Check for search query validity
     *
     * @param string $search Query to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isValidSearch($search)
    {
        return preg_match('/^[^<>;=#{}]{0,64}$/u', $search);
    }

    /**
     * Check for standard name validity
     *
     * @param string $name Name to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isGenericName($name)
    {
        return preg_match('/^[^<>={}]*$/u', $name);
    }

    /**
     * Check for HTML field validity (no XSS please !)
     *
     * @param string $html HTML field to validate
     * @param bool $allowIframe Allow iframe HTML tag
     *
     * @return bool Validity is ok or not
     */
    public static function isCleanHtml($html, $allowIframe = false)
    {
        $events = 'onmousedown|onmousemove|onmmouseup|onmouseover|onmouseout|onload|onunload|onfocus|onblur|onchange';
        $events .= '|onsubmit|ondblclick|onclick|onkeydown|onkeyup|onkeypress|onmouseenter|onmouseleave|onerror|onselect|onreset|onabort|ondragdrop|onresize|onactivate|onafterprint|onmoveend';
        $events .= '|onafterupdate|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditfocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onmove';
        $events .= '|onbounce|oncellchange|oncontextmenu|oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondeactivate|ondrag|ondragend|ondragenter|onmousewheel';
        $events .= '|ondragleave|ondragover|ondragstart|ondrop|onerrorupdate|onfilterchange|onfinish|onfocusin|onfocusout|onhashchange|onhelp|oninput|onlosecapture|onmessage|onmouseup|onmovestart';
        $events .= '|onoffline|ononline|onpaste|onpropertychange|onreadystatechange|onresizeend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onsearch|onselectionchange';
        $events .= '|onselectstart|onstart|onstop';

        if (preg_match('/<[\s]*script/im', $html) || preg_match('/(' . $events . ')[\s]*=/im', $html) ||
            preg_match('/script\:/im', $html)
        ) {
            return false;
        }

        return !(!$allowIframe && preg_match('/<[\s]*(i?frame|form|input|embed|object)/im', $html));
    }

    /**
     * Check for password validity
     *
     * @param string $passwd Password to validate
     * @param int $size
     *
     * @return boolean Validity is ok or not
     */
    public static function isPasswd($passwd, $size = Validate::PASSWORD_LENGTH)
    {
        return self::getPasswordComplexity($passwd, $size) >= self::PASSWORD_COMPLEXITY_MEDIUM;
    }

    public static function isPasswdAdmin($passwd)
    {
        return self::getPasswordComplexity($passwd, self::ADMIN_PASSWORD_LENGTH) >= self::PASSWORD_COMPLEXITY_STRONG;
    }

    /**
     * Check for configuration key validity
     *
     * @param string $config_name Configuration key to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isConfigName($config_name)
    {
        return preg_match('/^[a-zA-Z_0-9-]+$/', $config_name);
    }

    /**
     * Check for date format
     *
     * @param string $date Date to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isDateFormat($date)
    {
        return preg_match('/^(\d{4})-((0?\d)|(1[0-2]))-((0?\d)|([1-2]\d)|(3[01]))( \d{2}:\d{2}:\d{2})?$/', $date);
    }

    /**
     * Check for date validity
     *
     * @param string $date Date to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isDate($date)
    {
        if (!preg_match('/^(\d{4})-((?:0?\d)|(?:1[0-2]))-((?:0?\d)|(?:[1-2]\d)|(?:3[01]))( \d{2}:\d{2}:\d{2})?$/', $date, $matches)) {
            return false;
        }

        return checkdate((int)$matches[2], (int)$matches[3], (int)$matches[1]);
    }

    /**
     * Check for birthDate validity
     *
     * @param string $date birthdate to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isBirthDate($date)
    {
        if ($date === null || $date === '0000-00-00') {
            return true;
        }
        if (preg_match('/^(\d{4})-((?:0?[1-9])|(?:1[0-2]))-((?:0?[1-9])|(?:[1-2]\d)|(?:3[01]))(\d{2}:\d{2}:\d{2})?$/', $date, $birth_date)) {
            return !(($birth_date[1] > date('Y') && $birth_date[2] > date('m') && $birth_date[3] > date('d')) ||
                ($birth_date[1] === date('Y') && $birth_date[2] === date('m') && $birth_date[3] > date('d')) ||
                ($birth_date[1] === date('Y') && $birth_date[2] > date('m'))
            );
        }

        return false;
    }

    /**
     * Check for boolean validity
     *
     * @param boolean $bool Boolean to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isBool($bool)
    {
        return $bool === null || \is_bool($bool) || preg_match('/^0|1$/', $bool);
    }

    /**
     * Check for phone number validity
     *
     * @param string $number Phone number to validate
     * @param string $country Two digit uppercase country code (CZ, US, AU)
     *
     * @return boolean Validity is ok or not
     */
    public static function isPhoneNumber($number, $country)
    {
        return self::isPhoneNumber2($number, $country);
    }

    /**
     * Extended check for phone number validity (including specific country format)
     *
     * @param string $number Phone number to validate
     * @param string $country Two digit uppercase country code (CZ, US, AU)
     * @return bool Validity is ok or not
     */
    public static function isPhoneNumber2($number, $country)
    {
        if (empty($number)) {
            return false;
        }

        $phoneUtil = PhoneNumberUtil::getInstance();
        try {
            $numberProto = $phoneUtil->parse($number, strtoupper($country));

            return $phoneUtil->isValidNumber($numberProto);
        } catch (NumberParseException $e) {
            return false;
        }
    }

    /**
     * Check for time in hh:mm:ss format validity
     *
     * @param string $time Time
     *
     * @return boolean Validity is ok or not
     */
    public static function isTime($time)
    {
        return preg_match('/^(([0-1]\d)|([2][0-3])):([0-5]\d):([0-5]\d)$/', $time);
    }

    /**
     * Check for time in hh:mm:ss format validity. Accepts also null value
     *
     * @param string $time Time or null
     *
     * @return boolean Validity is ok or not
     */
    public static function isTimeOrNull($time)
    {
        return preg_match('/^(([0-1]\d)|([2][0-3])):([0-5]\d):([0-5]\d)$/', $time) or $time === null;
    }

    /**
     * Check for barcode validity (EAN-13)
     *
     * @param string $ean13 Barcode to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isEan13($ean13)
    {
        return preg_match('/^\d{0,13}$/', $ean13);
    }

    /**
     * Check for barcode validity (UPC)
     *
     * @param string $upc Barcode to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isUpc($upc)
    {
        return preg_match('/^\d{0,12}$/', $upc);
    }

    /**
     * Check for postal code validity
     *
     * @param string $postcode Postal code to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isPostCode($postcode)
    {
        return preg_match('/^[a-zA-Z 0-9-]+$/', $postcode);
    }

    /**
     * Check for zip code format validity
     *
     * @param string $zip_code zip code format to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isZipCodeFormat($zip_code)
    {
        return preg_match('/^[NLCnlc 0-9-]+$/', $zip_code);
    }

    /**
     * Check for table or identifier validity
     * Mostly used in database for ordering : ASC / DESC
     *
     * @param string $way Keyword to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isOrderWay($way)
    {
        return ($way === 'ASC' | $way === 'DESC' | $way === 'asc' | $way === 'desc');
    }

    /**
     * Check for table or identifier validity
     * Mostly used in database for ordering : ORDER BY field
     *
     * @param string $order Field to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isOrderBy($order)
    {
        return preg_match('/^[a-zA-Z0-9.!_-]+$/', $order);
    }

    /**
     * Check for tags list validity
     *
     * @param string $list List to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isTagsList($list)
    {
        return preg_match('/^[^!<>;?=+#"°{}_$%]*$/u', $list);
    }

    /**
     * Check for an integer validity
     *
     * @param integer $value Integer to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isInt($value)
    {
        return ((string)(int)$value === (string)$value || $value === false);
    }

    /**
     * Check for an integer validity (unsigned)
     *
     * @param integer $value Integer to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isUnsignedInt($value)
    {
        return (preg_match('#^\d+$#', (string)$value) && $value < 4294967296 && $value >= 0);
    }

    /**
     * Check for an percentage validity (between 0 and 100)
     *
     * @param float $value Float to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isPercentage($value)
    {
        return (self::isFloat($value) && $value >= 0 && $value <= 100);
    }

    /**
     * Check for an integer validity (unsigned)
     * Mostly used in database for auto-increment
     *
     * @param integer $id Integer to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isUnsignedId($id)
    {
        return self::isUnsignedInt($id); /* Because an id could be equal to zero when there is no association */
    }

    public static function isNullOrUnsignedId($id)
    {
        return $id === null || self::isUnsignedId($id);
    }

    /**
     * Check object validity
     *
     * @param object $object Object to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isLoadedObject($object)
    {
        return \is_object($object) && $object->id;
    }

    /**
     * Check hexadecimal color validity
     *
     * @param string $color Hexadecimal color to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isColor($color)
    {
        return preg_match('/^(#[0-9a-fA-F]{6}|[a-zA-Z0-9-]*)$/', $color);
    }

    /**
     * Check url validity (disallowed empty string)
     *
     * @param string $url Url to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isUrl($url)
    {
        return preg_match('/^[~:#,$%&_=\(\)\.\? \+\-@\/a-zA-Z0-9]+$/', $url);
    }

    /**
     * Check tracking number validity (disallowed empty string)
     *
     * @param string $tracking_number Tracking number to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isTrackingNumber($tracking_number)
    {
        return preg_match('/^[~:#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $tracking_number);
    }

    /**
     * Check url validity (allowed empty string)
     *
     * @param string $url Url to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isUrlOrEmpty($url)
    {
        return $url === null || self::isUrl($url);
    }

    /**
     * Check if URL is absolute
     *
     * @param string $url URL to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isAbsoluteUrl($url)
    {
        return preg_match('/^https?:\/\/[$~:;#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $url);
    }

    public static function isUnixName($data)
    {
        return preg_match('/^[a-z0-9\._-]+$/ui', $data);
    }

    public static function isTablePrefix($data)
    {
        // Even if "-" is theoretically allowed, it will be considered a syntax error if you do not add back quotes (`) around the table name
        return preg_match('/^[a-z0-9_]+$/ui', $data);
    }

    /**
     * Check for standard name file validity
     *
     * @param string $name Name to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isFileName($name)
    {
        return preg_match('/^[a-zA-Z0-9_.-]+$/', $name);
    }

    /**
     * Check for standard name directory validity
     *
     * @param string $dir Directory to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isDirName($dir)
    {
        return (bool)preg_match('/^[a-zA-Z0-9_.-]*$/', $dir);
    }

    public static function isWeightUnit($unit)
    {
        return (self::isGenericName($unit) & (\strlen($unit) < 5));
    }

    public static function isDistanceUnit($unit)
    {
        return (self::isGenericName($unit) & (\strlen($unit) < 5));
    }

    public static function isSubDomainName($domain)
    {
        return preg_match('/^[a-zA-Z0-9-_]*$/', $domain);
    }

    /**
     * Price display method validity
     *
     * @param string $data Data to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isString($data)
    {
        return \is_string($data);
    }

    /**
     * Check for PHP serialized data
     *
     * @param string $data Serialized data to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isSerializedArray($data)
    {
        return $data === null || (\is_string($data) && preg_match('/^a:\d+:{.*;}$/s', $data));
    }

    /**
     * Check for Latitude/Longitude
     *
     * @param string $data Coordinate to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isCoordinate($data)
    {
        return $data === null || preg_match('/^\-?\d{1,8}\.\d{1,8}$/', $data);
    }

    /**
     * Check for Language Iso Code
     *
     * @param string $iso_code
     *
     * @return boolean Validity is ok or not
     */
    public static function isLangIsoCode($iso_code)
    {
        return (bool)preg_match('/^[a-zA-Z]{2,3}$/', $iso_code);
    }

    /**
     *
     * @param array $ids
     *
     * @return boolean return true if the array contain only unsigned int value
     */
    public static function isArrayWithIds($ids)
    {
        if (\count($ids)) {
            foreach ($ids as $id) {
                if ((int)$id === 0 || !self::isUnsignedInt($id)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Check if the phone number is mobile
     *
     * @param string $phone Phone number
     *
     * @return bool Is phone number mobile
     * @static
     */
    public static function isMobilePhoneNumber($phone)
    {
        $phoneNumber = substr(Tools::removeSpace($phone), -9, 1);

        return (!self::isCzechPhoneNumber($phoneNumber) || ($phoneNumber === '6' || $phoneNumber === '7'));
    }

    /**
     * Determine whether the phone number is from Czech Republic
     *
     * @param string $phone Phone number
     *
     * @return bool Is Czech phone number
     * @static
     */
    public static function isCzechPhoneNumber($phone)
    {
        return (bool)preg_match("/^(\\+420)? ?\\d{3} ?\\d{3} ?\\d{3}$/", $phone);
    }

    /**
     * Check if the GUID is valid
     *
     * @param string $uuid GUID
     *
     * @return bool Whether the GUID is valid
     * @static
     */
    public static function isGuid($uuid)
    {
        return preg_match('/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?' . '[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/i', $uuid) === 1;
    }

    /**
     * Check if the birth number is valid
     *
     * @param string $no Birth number
     * @return bool Is valid
     */
    public static function isBirthNumber($no)
    {
        if (!preg_match('#^\s*(\d\d)(\d\d)(\d\d)[ /]*(\d\d\d)(\d?)\s*$#', $no, $matches)) {
            return false;
        }

        list(, $year, $month, $day, $ext, $c) = $matches;

        if ($c === '') {
            $year += $year < 54 ? 1900 : 1800;
        } else {
            $mod = ($year . $month . $day . $ext) % 11;
            if ($mod === 10) {
                $mod = 0;
            }
            if ($mod !== (int)$c) {
                return false;
            }
            $year += $year < 54 ? 2000 : 1900;
        }
        if ($year > 2003) {
            if ($month > 70) {
                $month -= 70;
            }
            if ($month > 20 && $month < 50) {
                $month -= 20;
            }
        }
        if ($month > 50) {
            $month -= 50;
        }

        return checkdate($month, $day, $year);
    }

    /**
     * Check if specified string is valid pretty time
     *
     * @param string $time Pretty time
     * @return bool Is valid
     */
    public static function isPrettyTime($time)
    {
        return (bool)preg_match('/^(?:(?<weeks>\d+)w\s*)?(?:(?<days>\d+)d\s*)?(?:(?<hours>\d+)h\s*)?(?:(?<minutes>\d+)m\s*)?(?:(?<seconds>\d+)s\s*)?$/', $time);
    }

    /**
     * Check if input string is link-rewrite
     *
     * @param string $name Name to validate
     *
     * @return boolean Validity is ok or not
     */
    public static function isLinkRewrite($name)
    {
        return preg_match('/^[a-z0-9-]*$/u', $name);
    }

    /**
     * Get password complexity
     *
     * @param string $password Password
     * @param int $minLength Minimal length
     * @return int Password score
     */
    public static function getPasswordComplexity($password, $minLength)
    {
        $group = [
            'upper' => '/[A-Z]/',
            'lower' => '/[a-z]/',
            'number' => '/[0-9]/',
            'special' => '/[^A-Za-z0-9]/',
        ];
        $score = 0;
        $length = \strlen($password);

        if ($length < $minLength) {
            return 0;
        }

        // Increment the score for each of these conditions
        foreach ($group as $pattern) {
            if (preg_match($pattern, $password)) {
                $score++;
            }
        }

        // Penalize if there aren't at least three char types
        if ($score < 3) {
            $score--;
        }

        // Increment the score for every 2 chars longer than the minimum
        if ($length > $minLength) {
            $score += (int)floor(($length - $minLength) / 2);
        }

        return $score;
    }
}


<?php

/**
 * This file is part of RawPHP - a PHP Framework.
 *
 * Copyright (c) 2014 RawPHP.org
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * PHP version 5.3
 *
 * @category  PHP
 * @package   RawPHP\RawRouter
 * @author    Tom Kaczocha <tom@rawphp.org>
 * @copyright 2014 Tom Kaczocha
 * @license   http://rawphp.org/license.txt MIT
 * @link      http://rawphp.org/
 */

namespace RawPHP\RawRouter;

use RawPHP\RawDispatcher\Contract\IDispatcher;
use RawPHP\RawDispatcher\Contract\IEvent;
use RawPHP\RawRouter\Contract\ILanguageController;
use RawPHP\RawRouter\Event\Events;
use RawPHP\RawRouter\Event\GetDefaultLanguageEvent;
use RawPHP\RawRouter\Event\GetLanguageDirEvent;
use RawPHP\RawSupport\Exception\RawException;

/**
 * Base controller class which all other controllers in the application
 * will extend.
 *
 * @category  PHP
 * @package   RawPHP\RawRouter
 * @author    Tom Kaczocha <tom@rawphp.org>
 * @copyright 2014 Tom Kaczocha
 * @license   http://rawphp.org/license.txt MIT
 * @link      http://rawphp.org/
 */
abstract class LEController extends Controller implements ILanguageController
{
    /** @var array */
    public $language = [ ];

    /**
     * Initialises for LE (language-enabled) Controller.
     *
     * This method hooks into the Controller::ON_LOAD_EXTRA_DATA_FILTER
     * hook to be able to extract language translations in the $e (extra)
     * variable.
     *
     * @param array $config configuration array
     */
    public function addDefaultListeners( $config = NULL )
    {
        parent::addDefaultListeners( $config );

//        $this->addFilter( self::ON_LOAD_EXTRA_DATA_FILTER,
//                          [ $this, 'loadLanguageCallback' ]
//        );
    }

    /**
     * Loads a language file for a controller.
     *
     * This method requires that LEController::ON_GET_LANG_DIR_FILTER hook has
     * a valid callback that sets the language directory for the controller.
     *
     * It also requires that LEController::ON_GET_DEFAULT_LANG_FILTER hook has
     * a valid callback that sets the default language to be used if the requested
     * language file is not found.
     *
     * @param string $controller the controller name
     * @param string $language   the language to load
     * @param bool   $return     whether to return the translations or to send them
     *                           to the view
     *
     * @return array returns the language array
     *
     * @throws RawException if there is something wrong with loading the language
     */
    public function loadLanguage( $controller, $language = 'en_US', $return = FALSE )
    {
        $langDirEvent = new GetLanguageDirEvent();

        $this->dispatcher->fire( Events::EVENT_GET_LANG_DIR, $langDirEvent );

        $langDir = $langDirEvent->getLangDir();

        $retVal = FALSE;

        if ( NULL === $langDir )
        {
            $retVal = FALSE;
        }
        else
        {
            $file = $langDir . $controller . DS . $language . '_lang.php';

            if ( !file_exists( $file ) )
            {
                $defaultLangEvent = new GetDefaultLanguageEvent();

                $this->dispatcher->fire( Events::EVENT_GET_DEFAULT_LANG, $defaultLangEvent );

                $defaultLang = $defaultLangEvent->getDefaultLanguage();

                if ( NULL === $defaultLang )
                {
                    $retval = FALSE;
                }
                else
                {
                    $file = $langDir
                        . $controller . DS
                        . $defaultLang
                        . '_lang.php';
                }
            }

            if ( NULL === $file )
            {
                throw new RawException( 'Failed to load language file for ' . $controller );
            }

            $lang = include_once $file;

            $this->language = array_merge( $this->language, $lang );

            $retVal = $lang;
        }

        return $retVal;
    }

    /**
     * The callback for Controller::ON_LOAD_EXTRA_DATA_FILTER. This method
     * adds the language translations to the global $_t variable.
     *
     * Make sure that you add key->value pairs to the array and not replace
     * the previous data in the $data array (unless that is your intention)
     *
     * @param array $data data already added by other callbacks
     *
     * @return array the data array with any added data
     */
    public function loadLanguageCallback( $data = [ ] )
    {
        $data[ '_t' ] = $this->language;

        return $data;
    }

    public function handle( IEvent $event, $name, IDispatcher $dispatcher )
    {
        parent::handle( $event, $name, $dispatcher );
    }
}


<?php

/**
 * This file is part of the Minion package.
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @license MIT License
 */

namespace Minion;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

/**
 * Class Controller.
 *
 * @package Minion
 * @author Damian Szczerbiński <dszczer@gmail.com>
 */
abstract class Controller implements ControllerInterface
{
    /** @var Application Framework */
    protected $container;

    /**
     * {@inheritdoc}
     */
    public function setContainer(Application $container) {
        $this->container = $container;
    }

    /**
     * {@inheritdoc}
     */
    public function render($path, array $arguments = []) {
        return new Response($this->renderText($path, $arguments));
    }

    /**
     * {@inheritdoc}
     */
    public function renderText($path, array $arguments = []) {
        if($this->container['minion.useTwig'])
            return $this->container['twig']->render($path, $arguments);
        else
            return Utils::renderPhpTemplate(Utils::fixPath($this->container->getRootDir() . '/src/' . $path), $arguments);
    }

    /**
     * {@inheritdoc}
     */
    public function createNotFoundException($message, \Exception $lastException = null) {
        $exception = new NotFoundHttpException($message, $lastException);

        return $this->container->minionError($exception, 404);
    }

    /**
     * {@inheritdoc}
     */
    public function createNotAllowedException($message, \Exception $lastException = null) {
        $exception = new AccessDeniedHttpException($message, $lastException);

        return $this->container->minionError($exception, 403);
    }

    /**
     * {@inheritdoc}
     */
    public function generateUrl($route, array $params = [], $flag = UrlGeneratorInterface::ABSOLUTE_URL) {
        return $this->container['url_generator']->generate($route, $params, $flag);
    }

    /**
     * {@inheritdoc}
     */
    public function getParameter($name, $default = null) {
        return $this->container['parameters']->get($name, $default);
    }
}


<?php
namespace Toxygene\StreamReader;

/**
 * Abstract stream reader
 *
 * @package Toxygene\StreamReader
 */
abstract class AbstractStreamReader implements StreamReaderInterface
{

    /**
     * {@inheritdoc}
     */
    public function readChars($count)
    {
        $chars = '';
        for ($i = 0; !$this->isEmpty() && $i < $count; ++$i) {
            $chars .= $this->readChar();
        }
        return $chars;
    }

}


<?php namespace Williamoliveira\Repository\Eloquent;

use Williamoliveira\Repository\Contracts\BaseRepository as BaseRepositoryInterface;
use Williamoliveira\Repository\Exceptions\NotFoundRepositoryException;
use Williamoliveira\Repository\Exceptions\UpdateFailedRepositoryException;
use Williamoliveira\Repository\Exceptions\StoreFailedRepositoryException;
use Williamoliveira\Repository\Exceptions\RepositoryException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Pagination\LengthAwarePaginator;
use Williamoliveira\Repository\Contracts\Criteria;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use ArrayAccess;
use Closure;

abstract class BaseRepository implements BaseRepositoryInterface
{

    /**
     * Query builder instance
     *
     * @var Builder
     */
    protected $query;

    /**
     * Default page size for pagination
     *
     * @var int
     */
    protected $defaultPageSize = 15;

    /**
     * The model's class name
     *
     * @var string
     */
    protected $modelClass;

    /**
     * Apply a query
     *
     * @param Criteria|Closure $criteria
     * @return mixed
     * @throws \Exception
     */
    public function applyCriteria($criteria)
    {
        $query = $this->getQuery();

        if($criteria instanceof Criteria){
            $criteria->apply($query);

            return $this;
        }

        if($criteria instanceof Closure){
            $criteria($query);

            return $this;
        }

        throw new RepositoryException("Must be an instance of " . Criteria::class . " or \\Closure");
    }

    /**
     * Find all models
     *
     * @param array $columns
     * @param bool $paginated
     * @param null $perPage
     * @return mixed
     */
    public function getMany($columns = ['*'], $paginated = false, $perPage = null)
    {
        $results = $paginated
            ? $this->getManyPaginated($perPage, $columns)
            : $this->getQuery()->get($columns);

        return $this->returnResults($results);
    }

    /**
     * Find all models but paginated
     *
     * @param null $perPage
     * @param array $columns
     * @return mixed
     */
    public function getManyPaginated($perPage = null, $columns = ['*'])
    {
        $query = $this->getQuery();
        $results = $query->paginate($perPage, $columns);

        return $this->returnResults($results);
    }

    /**
     * Find a single model by it's id
     *
     * @param $id
     * @param array $columns
     * @return mixed
     * @throws NotFoundRepositoryException
     */
    public function getById($id, $columns = ['*'])
    {
        try {
            $results = $this->getQuery()->findOrFail($id, $columns);
        }
        catch(ModelNotFoundException $e){
            throw new NotFoundRepositoryException($e);
        }

        return $this->returnResults($results);
    }

    /**
     * Find many models given an array of ids
     *
     * @param array $ids
     * @param array $columns
     * @return mixed
     */
    public function getManyByIds(array $ids, $columns = ['*'])
    {
        $results = $this->getQuery()->findMany($ids, $columns);

        return $this->returnResults($results);
    }

    /**
     * Create and persist a model given an array of attributes
     *
     * @param array $attributes
     * @return mixed
     * @throws \Exception
     */
    public function create(array $attributes = [])
    {
        $model = $this->newModel();
        $model->fill($attributes);

        $this->save($model);

        return $model;
    }

    /**
     * Persist a model
     *
     * @param Model $model
     * @return mixed
     * @throws StoreFailedRepositoryException
     */
    public function save($model)
    {
        if(!$model->save()){
            throw new StoreFailedRepositoryException();
        }

        return $model;
    }

    /**
     * Persist many models
     *
     * @param ArrayAccess $models
     * @return Collection
     * @throws StoreFailedRepositoryException
     */
    public function saveMany(ArrayAccess $models)
    {
        //transform to collection
        if(!$models instanceof Collection){
            $models = collect($models);
        }

        foreach ($models as $model) {
            $this->save($model);
        }

        return $models;
    }

    /**
     * Update a model given it's id and an array of attributes
     *
     * @param $id
     * @param array $newAttributes
     * @return mixed
     * @throws UpdateFailedRepositoryException
     */
    public function updateById($id, array $newAttributes)
    {
        $model = $this->getById($id);
        $results = $model->update($newAttributes);

        if(!$results){
            throw new UpdateFailedRepositoryException();
        }

        return $model;
    }

    /**
     * Update a model given a model and an array of new attributes
     *
     * @param Model $model
     * @param array $newAttributes
     * @return mixed
     * @throws UpdateFailedRepositoryException
     */
    public function update(Model $model, array $newAttributes)
    {
        $results = $model->update($newAttributes);

        if(!$results){
            throw new UpdateFailedRepositoryException();
        }

        return $model;
    }

    /**
     * Delete a given model
     *
     * @param $model
     * @return bool|null
     * @throws \Exception
     */
    public function delete(Model $model)
    {
        return $model->delete();
    }

    /**
     * Delete many models
     *
     * @param ArrayAccess $models
     * @return array
     */
    public function deleteMany(ArrayAccess $models)
    {
        $results = [];

        foreach ($models as $model) {
            $results[] = $this->delete($model);
        }

        return $this->returnResults($results);
    }

    /**
     * Delete a model by it's id (or ids)
     *
     * @param $id
     * @return int
     * @throws \Exception
     */
    public function deleteById($id)
    {
        return $this->newModel()->destroy($id);
    }

    /**
     * Make a new empty model
     *
     * @return Model
     * @throws \Exception
     */
    public function newModel()
    {
        $model = app()->make($this->modelClass);

        if (!$model instanceof Model) {
            throw new RepositoryException("Class {$this->modelClass} must be an instance of Illuminate\\Database\\Eloquent\\Model");
        }

        return $model;
    }

    /**
     * Paginate a given query
     *
     * @param int $page
     * @param int $perPage
     * @param array $columns
     * @return mixed
     */
    public function paginate($page = 1, $perPage = null, $columns = ['*'])
    {
        $perPage = $perPage ?: $this->defaultPageSize;

        $query = $this->getQuery();

        $total = $query->getQuery()->getCountForPagination($columns);
        $query->getQuery()->forPage($page, $perPage);
        $results = $query->get($columns);

        $results = new LengthAwarePaginator($results, $total, $perPage, $page);

        return $this->returnResults($results);
    }

    /**
     * @param $results
     * @return mixed
     */
    private function returnResults($results)
    {
        $this->destroyQuery();

        return $this->parseResults($results);
    }

    /**
     * You can override this to parse the results before returning
     *
     * @param $results
     * @return mixed
     */
    protected function parseResults($results)
    {
        return $this->returnResults($results);
    }

    /**
     * Make a new query
     *
     * @return Builder|QueryBuilder
     * @throws \Exception
     */
    protected function newQuery()
    {
        return $this->newModel()->newQuery();
    }

    /**
     * Set null to the instantiated query object
     */
    protected function destroyQuery()
    {
        $this->query = null;
    }

    /**
     * Get the current query
     *
     * @return Builder|QueryBuilder
     */
    protected function getQuery()
    {
        if(!$this->query){
            $this->query = $this->newQuery();
        }

        return $this->query;
    }
}


<?php

namespace Asoc\Dadatata\Filter\Php;

use Asoc\Dadatata\Exception\ProcessingFailedException;
use Asoc\Dadatata\Filter\BaseImageFilter;
use Asoc\Dadatata\Filter\OptionsInterface;
use Asoc\Dadatata\Model\ImageInterface;
use Asoc\Dadatata\Model\ThingInterface;
use Imagine\Image\Box;
use Imagine\Image\ImagineInterface;
use Neutron\TemporaryFilesystem\TemporaryFilesystemInterface;

class ImagineResize extends BaseImageFilter
{
    /**
     * @var string
     */
    protected $bin;

    /**
     * @var \Imagine\Image\ImagineInterface
     */
    private $imagine;

    /**
     * @var TemporaryFilesystemInterface
     */
    private $tmpFs;

    /**
     * @param \Imagine\Image\ImagineInterface $imagine
     * @param TemporaryFilesystemInterface    $tmpFs
     */
    public function __construct(ImagineInterface $imagine, TemporaryFilesystemInterface $tmpFs)
    {
        $this->imagine = $imagine;
        $this->tmpFs   = $tmpFs;
    }

    /**
     * @param ThingInterface   $thing
     * @param string           $sourcePath
     * @param OptionsInterface $options
     *
     * @return array Paths to generated files
     * @throws ProcessingFailedException
     */
    public function process(ThingInterface $thing, $sourcePath, OptionsInterface $options = null)
    {
        $image = $this->imagine->open($sourcePath);

        $options = $this->defaults->merge($options);

        $width  = $options->getWidth();
        $height = $options->getHeight();

        $size = new Box($width, $height);

        $transformation = $this->getTransformation($image, $size, $options);

        $tmpPath = $this->tmpFs->createTemporaryFile();
        $transformation->save(
            $tmpPath,
            [
                'format'  => $options->getFormat(),
                'quality' => $options->getQuality()
            ]
        );

        try {
            $transformation->apply($image);
        } catch (\Exception $e) {
            throw new ProcessingFailedException('Failed to create image: '.$e->getMessage());
        }

        return [$tmpPath];
    }

    protected function getTransformation(
        \Imagine\Image\ImageInterface $image,
        Box $size,
        OptionsInterface $options = null
    ) {
        $transformation = new \Imagine\Filter\Transformation();
        $transformation->resize($size, \Imagine\Image\ImageInterface::FILTER_LANCZOS);

        return $transformation;
    }

    /**
     * @param ThingInterface $thing
     *
     * @return boolean
     */
    public function canHandle(ThingInterface $thing)
    {
        return $thing instanceof ImageInterface;
    }
}


<?php
namespace T3v\T3vNavigations\Domain\Model;

use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;

/**
 * The overview navigation item class.
 *
 * @package T3v\T3vNavigations\Domain\Model
 */
class OverviewNavigationItem extends AbstractModel {
  /**
   * The overview navigation item's title.
   *
   * @var string
   */
  protected $title;

  /**
   * The overview navigation item's abstract.
   *
   * @var string
   */
  protected $abstract;

  /**
   * The overview navigation item's thumbnails.
   *
   * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
   * @lazy
   * @cascade remove
   */
  protected $thumbnails;

  /**
   * The overview navigation item's page (UID).
   *
   * @var int
   */
  protected $page;

  /**
   * The overview navigation item's link (typolink).
   *
   * @var string
   */
  protected $link;

  /**
   * The overview navigation item's label.
   *
   * @var string
   */
  protected $label;

  /**
   * Constructs a new overview navigation item.
   */
  public function __construct() {
    parent::__construct();

    $this->thumbnails = new ObjectStorage();
  }

  /**
   * Returns the overview navigation item's title.
   *
   * @return string The overview navigation item's title
   */
  public function getTitle() {
    return $this->title;
  }

  /**
   * Sets the overview navigation item's title.
   *
   * @param string $title The overview navigation item's title
   */
  public function setTitle($title) {
    $this->title = $title;
  }

  /**
   * Returns the overview navigation item's abstract.
   *
   * @return string The overview navigation item's abstract
   */
  public function getAbstract() {
    return $this->abstract;
  }

  /**
   * Sets the overview navigation item's abstract.
   *
   * @param string $abstract The overview navigation item's abstract
   */
  public function setAbstract($abstract) {
    $this->abstract = $abstract;
  }

  /**
   * Returns all thumbnails belonging to the overview navigation item.
   *
   * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> The overview navigation item's thumbnails
   */
  public function getThumbnails() {
    return $this->thumbnails;
  }

  /**
   * Adds a thumbnail to the overview navigation item.
   *
   * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $thumbnail The thumbnail to be added
   */
  public function addThumbnail(\TYPO3\CMS\Extbase\Domain\Model\FileReference $thumbnail) {
    $this->thumbnails->attach($thumbnail);
  }

  /**
   * Removes a thumbnail from the overview navigation item.
   *
   * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $thumbnail The thumbnail to be removed
   */
  public function removeThumbnail(\TYPO3\CMS\Extbase\Domain\Model\FileReference $thumbnail) {
    $this->thumbnails->detach($thumbnail);
  }

  /**
   * Removes all thumbnails from the overview navigation item.
   */
  public function removeAllThumbnails() {
    $this->thumbnails = new ObjectStorage();
  }

  /**
   * Returns the overview navigation item's page (UID).
   *
   * @return int The overview navigation item's page (UID)
   */
  public function getPage() {
    return $this->page;
  }

  /**
   * Sets the overview navigation item's page (UID).
   *
   * @param int $link The overview navigation item's link page (UID)
   */
  public function setPage($page) {
    $this->page = $page;
  }

  /**
   * Returns the overview navigation item's link (typolink).
   *
   * @return string The overview navigation item's link (typolink)
   */
  public function getLink() {
    return $this->link;
  }

  /**
   * Sets the overview navigation item's link (typolink).
   *
   * @param string $link The overview navigation item's link (typolink)
   */
  public function setLink($link) {
    $this->link = $link;
  }

  /**
   * Returns the overview navigation item's label.
   *
   * @return string The overview navigation item's label
   */
  public function getLabel() {
    $label = $this->label;
    $title = $this->title;

    if ($label) {
      return $label;
    } else {
      return $title;
    }
  }

  /**
   * Sets the overview navigation item's label.
   *
   * @param string $label The overview navigation item's label
   */
  public function setLabel($label) {
    $this->label = $label;
  }
}


<?php

declare(strict_types=1);
/**
 * This file is part of the BEAR.Accept package.
 *
 * @license http://opensource.org/licenses/MIT MIT
 */
namespace BEAR\Accept;

use BEAR\Accept\Annotation\Available;
use BEAR\Accept\Annotation\Produces;
use BEAR\AppMeta\AbstractAppMeta;
use BEAR\Package\AppInjector;
use BEAR\Resource\RenderInterface;
use Ray\Aop\MethodInterceptor;
use Ray\Aop\MethodInvocation;

final class AcceptInterceptor implements MethodInterceptor
{
    /**
     * @var array
     */
    private $available;

    /**
     * @var AbstractAppMeta
     */
    private $appMeta;

    /**
     * @Available("available")
     */
    public function __construct(array $available, AbstractAppMeta $appMeta)
    {
        $this->available = $available;
        $this->appMeta = $appMeta;
    }

    /**
     * {@inheritdoc}
     */
    public function invoke(MethodInvocation $invocation)
    {
        $produce = $invocation->getMethod()->getAnnotation(Produces::class);
        /* @var $produce \BEAR\Accept\Annotation\Produces */
        $accept = $this->getAccept($this->available['Accept'], $produce->value);
        $accept = new Accept(['Accept' => $accept]);
        list($context, $vary) = $accept->__invoke($_SERVER);
        $renderer = (new AppInjector($this->appMeta->name, $context))->getInstance(RenderInterface::class);
        $ro = $invocation->getThis();
        /* @var $ro \BEAR\Resource\ResourceObject */
        $ro->setRenderer($renderer);
        $ro = $invocation->proceed();
        $ro->headers['Vary'] = $vary;

        return $ro;
    }

    private function getAccept(array $default, array $produces) : array
    {
        $accept = [];
        foreach ($produces as $produce) {
            if (isset($default[$produce])) {
                $accept[$produce] = $default[$produce];
            }
        }
        $accept['*'] = $default['*'];

        return $accept;
    }
}


<?php
/**
 * Created by PhpStorm.
 * User: Frost Wong <frostwong@gmail.com>
 * Date: 11/16/16
 * Time: 4:47 PM
 */

namespace Spw\Connection;

use InvalidArgumentException;
use PDO;
use Psr\Log\LoggerInterface;
use Spw\Builder\SqlBuilder;
use Spw\Builder\StatementBuilder;
use Spw\Config\ConfigInterface;
use Spw\PdoFactory;
use Spw\Support\Str;

class Connection implements ConnectionInterface
{
    /**
     * The config of database.
     *
     * @var ConfigInterface
     */
    private $config;

    private $table;

    private $columns;

    private $limitOffset;

    private $limitCount;

    private $wheres;

    private $orderBy = [];

    private $values = [];

    private $counts = [];

    private $groupBy;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * The default PDO connection timeout
     * @var int
     */
    const TIME_OUT = 2;

    /**
     * The default PDO connection options
     * @var array
     */
    private $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_EMULATE_PREPARES => false,
        PDO::ATTR_TIMEOUT => self::TIME_OUT,
    ];

    const EXEC_RETURN_ROW_SET = 1;
    const EXEC_RETURN_ROW_COUNT = 2;
    const EXEC_RETURN_LAST_INSERT_ID = 3;

    public function __construct(ConfigInterface $config)
    {
        $this->config = $config;
    }

    public function getColumns()
    {
        return $this->columns;
    }

    /**
     * @return mixed
     * @throws \InvalidArgumentException
     */
    public function getTable()
    {
        return Str::quoteWith($this->table, '`');
    }

    /**
     * @return PDO
     * @throws \PDOException
     */
    private function connect()
    {
        try {
            return PdoFactory::makePdo($this->config, $this->options);
        } catch (\PDOException $e) {
            $this->logger->error('PDO construction error', [$e->getCode(), $e->getMessage(), $e->getTraceAsString()]);
            return null;
        }
    }

    public function from($table)
    {
        $this->reset();
        $this->table = $table;

        return $this;
    }

    /**
     * @param string|array $columns
     * @return mixed
     * @throws \PDOException
     */
    public function select($columns = '*')
    {
        $this->columns = $columns;

        $builtSql = SqlBuilder::buildSelectSql($this);

        if (is_array($builtSql)) {
            $sql = $builtSql[0];
            $values = $builtSql[1];
        } else {
            $sql = $builtSql;
        }

        if ($values === null) {
            $boundSth = $this->connect()->query($sql);
        } else {
            try {
                $preparedSth = $this->connect()->prepare($builtSql[0]);
            } catch (\PDOException $e) {
                $this->logger->error('Prepare statement error', [$e->getCode(), $e->getMessage(), $e->getTraceAsString()]);
                return null;
            }

            try {
                $boundSth = StatementBuilder::bindValues($preparedSth, $builtSql[1]);
            } catch (\PDOException $e) {
                $this->logger->error('PDOStatement bind values error', [$e->getCode(), $e->getMessage(), $e->getTraceAsString()]);
                return null;
            }

            try {
                $boundSth->execute();
            } catch (\PDOException $e) {
                $this->logger->error('PDOStatement execution error', [$e->getCode(), $e->getMessage(), $e->getTraceAsString()]);
                return null;
            }
        }

        try {
            return $boundSth->fetchAll(PDO::FETCH_ASSOC);
        } catch (\PDOException $e) {
            $this->logger->error('PDOStatement fetchAll error', [$e->getCode(), $e->getMessage(), $e->getTraceAsString()]);
            return null;
        }
    }

    /**
     * @param array $wheres
     * @return $this
     * @throws \InvalidArgumentException
     */
    public function where($wheres = [])
    {
        if (!is_array($wheres)) {
            throw new InvalidArgumentException('Where condition must be an array, string ' . $wheres . ' is given.');
        }
        $this->wheres = $wheres;
        return $this;
    }

    public function limit($offset, $count = 0)
    {
        $this->limitOffset = $offset;
        $this->limitCount = $count;

        return $this;
    }

    /**
     * @param array|string $columns
     * @return mixed
     * @throws \PDOException
     */
    public function selectOne($columns = '*')
    {
        return $this->limit(1)->select($columns)[0];
    }

    /**
     * @param array $values
     * @return mixed
     * @throws \InvalidArgumentException
     * @throws \PDOException
     */
    public function insert(array $values)
    {
        $this->values = $values;

        list($sql, $inputParams) = SqlBuilder::buildInsertSql($this);
        $preparedSth = $this->connect()->prepare($sql);
        $boundSth = StatementBuilder::bindValues($preparedSth, $inputParams);
        $boundSth->execute();
        return $this->connect()->lastInsertId();
    }

    /**
     * @param array $values
     * @return mixed
     * @throws \InvalidArgumentException
     * @throws \PDOException
     */
    public function replace(array $values)
    {
        $this->values = $values;

        list($sql, $inputParams) = SqlBuilder::buildReplaceSql($this);
        $preparedSth = $this->connect()->prepare($sql);
        $boundSth = StatementBuilder::bindValues($preparedSth, $inputParams);
        $boundSth->execute();
        return $this->connect()->lastInsertId();
    }

    /**
     * @param array $values
     * @return mixed
     * @throws \InvalidArgumentException
     * @throws \PDOException
     */
    public function update(array $values)
    {
        $this->values = $values;

        list($sql, $inputParams) = SqlBuilder::buildUpdateSql($this);
        $preparedSth = $this->connect()->prepare($sql);
        $boundSth = StatementBuilder::bindValues($preparedSth, $inputParams);
        $boundSth->execute();
        return $boundSth->rowCount();
    }

    /**
     * @return bool
     * @throws \PDOException
     */
    public function delete()
    {
        list($sql, $inputParams) = SqlBuilder::buildDeleteSql($this);
        $preparedSth = $this->connect()->prepare($sql);
        $boundSth = StatementBuilder::bindValues($preparedSth, $inputParams);
        $boundSth->execute();
        return $boundSth->rowCount();
    }

    public function orderBy($column, $asc = 'desc')
    {
        $this->orderBy[] = [$column, $asc];
        return $this;
    }

    /**
     * @return mixed
     */
    public function getLimit()
    {
        $limit = [];
        if (null !== $this->limitOffset) {
            $limit['offset'] = $this->limitOffset;
        }
        if (null !== $this->limitCount) {
            $limit['count'] = $this->limitCount;
        }
        return $limit;
    }

    /**
     * @return mixed
     */
    public function getOrderBy()
    {
        return $this->orderBy;
    }

    /**
     * @return array
     */
    public function getWheres()
    {
        return $this->wheres;
    }

    /**
     * @param $sql
     * @return \PDOStatement
     * @throws \PDOException
     */
    public function query($sql)
    {
        return $this->connect()->prepare($sql);
    }

    /**
     * @return array
     */
    public function getValues()
    {
        return $this->values;
    }

    /**
     * @param $table
     * @return $this
     */
    public function into($table)
    {
        $this->from($table);

        return $this;
    }

    /**
     * Count specified column.
     *
     * @param string $col
     * @param string $alias
     * @param bool $distinct
     * @return mixed
     */
    public function count($col, $alias, $distinct = false)
    {
        $this->counts[] = [$col, $alias, $distinct];

        return $this;
    }

    /**
     * Get count clause of a select SQL statement.
     *
     * @return array
     */
    public function getCounts()
    {
        return $this->counts;
    }

    /**
     * Run raw sql and return result.
     *
     * @param $sql
     * @param array $params
     * @return array|int
     * @throws \PDOException
     */
    public function raw($sql, array $params)
    {
        $stmt = $this->connect()->prepare($sql);
        $stmt->execute($params);

        if (stripos($sql, 'select') === 0) {
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        }

        if (stripos($sql, 'insert') === 0) {
            return $this->connect()->lastInsertId();
        }

//        if (stripos($sql, 'update') === 0 || stripos($sql, 'delete') === 0 || stripos($sql, 'replace') === 0) {
            return $stmt->execute();
//        }
    }

    /**
     * Get number of rows of specific condition.
     *
     * @return integer
     * @throws \PDOException
     */
    public function getNumRows()
    {
        $builtSql = SqlBuilder::buildRowCountSql($this);

        if (is_array($builtSql)) {
            $preparedSth = $this->connect()->prepare($builtSql[0]);
            $boundSth = StatementBuilder::bindValues($preparedSth, $builtSql[1]);
            $boundSth->execute();
        } else {
            $boundSth = $this->connect()->query($builtSql);
        }

        $result = $boundSth->fetch(PDO::FETCH_ASSOC);
        return (int)$result['total_count'];
    }

    public function reset()
    {
        $this->columns = '';
        $this->limitCount = null;
        $this->limitOffset = null;
        $this->wheres = [];
        $this->orderBy = [];
        $this->values = [];
        $this->counts = [];
        $this->groupBy = '';
    }

    /**
     * Construct group by clause of a SQL statement.
     *
     * @param $column
     * @return ConnectionInterface
     */
    public function groupBy($column)
    {
        $this->groupBy = $column;
        return $this;
    }

    /**
     * Get group by of a SQL statement.
     *
     * @return string
     */
    public function getGroupBy()
    {
        return $this->groupBy;
    }

    /**
     * Set logger to log queries.
     * @param LoggerInterface $logger
     * @return ConnectionInterface
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;

        return $this;
    }
}


<?php

/**
 * Melis Technology (http://www.melistechnology.com)
 *
 * @copyright Copyright (c) 2016 Melis Technology (http://www.melistechnology.com)
 *
 */

namespace MelisCmsPageHistoric\Model\Tables;

use Zend\Db\Sql\Expression;
use Zend\Db\TableGateway\TableGateway;
use MelisEngine\Model\Tables\MelisGenericTable;

use Zend\Db\Sql\Select;
use Zend\Db\Sql\Where;
use Zend\Db\Sql\Predicate\PredicateSet;
use Zend\Db\Sql\Predicate\Like;
use Zend\Db\Sql\Predicate\Operator;
use Zend\Db\Sql\Predicate\Predicate;

class MelisPageHistoricTable extends MelisGenericTable
{
    protected $tableGateway;
    protected $idField;

	public function __construct(TableGateway $tableGateway)
	{
		parent::__construct($tableGateway);
		$this->idField = 'hist_page_id';
	}

	/**
	 * Get Page Historic Data for MelisCms
	 * @param array $options
	 * @param string $fixedCriteria
	 */
	public function getPageHistoricData(array $options, $fixedCriteria = null, $user = null, $action = null)
	{
	    $select = $this->tableGateway->getSql()->select();
	    $result = $this->tableGateway->select();
	    $select->join('melis_core_user', 'melis_core_user.usr_id = melis_hist_page_historic.hist_user_id', ['fullname' => new Expression("CONCAT(usr_firstname, ' ', usr_lastname)")], $select::JOIN_INNER);

	    $where = !empty($options['where']['key']) ? $options['where']['key'] : '';
	    $whereValue = !empty($options['where']['value']) ? $options['where']['value'] : '';

	    $order = !empty($options['order']['key']) ? $options['order']['key'] : '';
	    $orderDir = !empty($options['order']['dir']) ? $options['order']['dir'] : 'ASC';

	    $start = (int) $options['start'];
	    $limit = (int) $options['limit'] === -1 ? $this->getTotalData() : (int) $options['limit'];

	    $columns = $options['columns'];

	    // check if there's an extra variable that should be included in the query
	    $dateFilter = $options['date_filter'];
	    $dateFilterSql = '';

	    if(count($dateFilter)) {
	        if(!empty($dateFilter['startDate']) && !empty($dateFilter['endDate'])) {
	            $dateFilterSql = '`' . $dateFilter['key'] . '` BETWEEN \'' . $dateFilter['startDate'] . '\' AND \'' . $dateFilter['endDate'] . '\'';
	        }
	    }

	    // this is used when searching
	    if(!empty($where)) {
	        $w = new Where();
	        $p = new PredicateSet();
	        $filters = array();
	        $likes = array();
	        foreach($columns as $colKeys)
	        {
	            $likes[] = new Like($colKeys, ''.$whereValue.'');
	        }

	        if(!empty($dateFilterSql))
	        {
	            $filters = array(new PredicateSet($likes,PredicateSet::COMBINED_BY_OR), new \Zend\Db\Sql\Predicate\Expression($dateFilterSql));
	        }
	        else
	        {
	            $filters = array(new PredicateSet($likes,PredicateSet::COMBINED_BY_OR));
	        }
	        $fixedWhere = array(new PredicateSet(array(new Operator('', '=', ''))));
	        if(is_null($fixedCriteria))
	        {
	            $select->where($filters);
	        }
	        else
	        {
	            $select->where(array(
	                $fixedWhere,
	                $filters,
	            ), PredicateSet::OP_AND);
	        }
	    }

	    if ($user) {
            $select->where(new \Zend\Db\Sql\Predicate\Expression("CONCAT(usr_firstname, ' ', usr_lastname) = '" . $user . "'"));
        }

        if ($action) {
            $select->where(['hist_action' => $action]);
        }

	    // used when column ordering is clicked
	    if(!empty($order))
	        $select->order($order . ' ' . $orderDir);

        $getCount = $this->tableGateway->selectWith($select);
        $this->setCurrentDataCount((int) $getCount->count());

        // this is used in paginations
        $select->limit($limit);
        $select->offset($start);

        $resultSet = $this->tableGateway->selectWith($select);

        $sql = $this->tableGateway->getSql();
        $raw = $sql->getSqlstringForSqlObject($select);

        return $resultSet;
	}

	public function getHistoryByPageId($pageId)
	{
        return $this->getEntryById($pageId);
	}

	public function getDescendingHistoric($histIdPage, $max = null)
	{
	    $select = $this->tableGateway->getSql()->select();

	    $select->order('hist_id DESC');
	    $select->where(array('hist_page_id' => (int) $histIdPage));
	    if ($max)
	    	$select->limit($max);
	    $resultSet = $this->tableGateway->selectWith($select);

	    return $resultSet;
	}

    public function getPagesHistoricForDashboard($max = 5)
    {
        $select = $this->tableGateway->getSql()->select();
        $select->columns(array(new \Zend\Db\Sql\Expression('DISTINCT(hist_page_id) as pageId'), 'hist_id'));
        $select->order('hist_id DESC');
        $select->limit($max);
        $resultSet = $this->tableGateway->selectWith($select);

        return $resultSet;

    }

    /**
     * This will return all distinct actions
     * @param string $order
     * @return mixed
     */
    public function getPageHistoricListOfActions($order = 'ASC')
    {
        $select = $this->tableGateway->getSql()->select();
        $select->columns(["action" => new Expression('DISTINCT(hist_action)')]);
        $select->order('hist_action' . ' '  . $order);
        $resultSet = $this->tableGateway->selectWith($select);

        return $resultSet;
    }

    /**
     * This will return all users
     * @return mixed
     */
    public function getUsers() {
        $select = $this->tableGateway->getSql()->select();
        $select->columns(["fullname" => new Expression("DISTINCT(CONCAT(usr_firstname, ' ', usr_lastname))")]);
        $select->join('melis_core_user',
            'melis_core_user.usr_id = melis_hist_page_historic.hist_user_id',
            [],
            $select::JOIN_INNER
        );
        $resultSet = $this->tableGateway->selectWith($select);

        return $resultSet;
    }
}


<?php

namespace Peyote;

/**
 * The DROP table class
 *
 * @package    Peyote
 * @author     Dave Widmer <dave@davewidmer.net>
 */
class Drop implements Builder
{
	/**
	 * @var string
	 */
	private $table = null;

	/**
	 * @var boolean
	 */
	private $if_exists = false;

	/**
	 * @var string
	 */
	private $type = "TABLE";

	/**
	 * @param string $table The table name
	 */
	public function __construct($table = null, $if_exists = false)
	{
		$this->setTable($table);
		$this->setIfExists($if_exists);
	}

	/**
	 * @return string  The type of object to change (DATABASE, TABLE, etc...)
	 */
	public function getType()
	{
		return $this->type;
	}

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

	/**
	 * @param string $table The table name to drop.
	 * @return \Peyote\Drop
	 */
	public function setTable($table)
	{
		$this->table = $table;
		return $this;
	}

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

	/**
	 * @param  boolean $exists Add the IF EXISTS clause?
	 * @return \Peyote\Drop
	 */
	public function setIfExists($exists)
	{
		$this->if_exists = (boolean) $exists;
		return $this;
	}

	/**
	 * {@inheritDoc}
	 */
	public function compile()
	{
		$query = array("DROP", $this->type, $this->getTable());

		if ($this->getIfExists() === true)
		{
			$query[] = "IF EXISTS";
		}

		return join(' ', $query);
	}

}