<?php

namespace PhpOffice\PhpSpreadsheet\Cell;

use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;

class DataType
{
    // Data types
    const TYPE_STRING2 = 'str';
    const TYPE_STRING = 's';
    const TYPE_FORMULA = 'f';
    const TYPE_NUMERIC = 'n';
    const TYPE_BOOL = 'b';
    const TYPE_NULL = 'null';
    const TYPE_INLINE = 'inlineStr';
    const TYPE_ERROR = 'e';

    /**
     * List of error codes.
     *
     * @var array
     */
    private static $errorCodes = [
        '#NULL!' => 0,
        '#DIV/0!' => 1,
        '#VALUE!' => 2,
        '#REF!' => 3,
        '#NAME?' => 4,
        '#NUM!' => 5,
        '#N/A' => 6,
    ];

    /**
     * Get list of error codes.
     *
     * @return array
     */
    public static function getErrorCodes()
    {
        return self::$errorCodes;
    }

    /**
     * Check a string that it satisfies Excel requirements.
     *
     * @param null|RichText|string $pValue Value to sanitize to an Excel string
     *
     * @return null|RichText|string Sanitized value
     */
    public static function checkString($pValue)
    {
        if ($pValue instanceof RichText) {
            // TODO: Sanitize Rich-Text string (max. character count is 32,767)
            return $pValue;
        }

        // string must never be longer than 32,767 characters, truncate if necessary
        $pValue = StringHelper::substring($pValue, 0, 32767);

        // we require that newline is represented as "\n" in core, not as "\r\n" or "\r"
        $pValue = str_replace(["\r\n", "\r"], "\n", $pValue);

        return $pValue;
    }

    /**
     * Check a value that it is a valid error code.
     *
     * @param mixed $pValue Value to sanitize to an Excel error code
     *
     * @return string Sanitized value
     */
    public static function checkErrorCode($pValue)
    {
        $pValue = (string) $pValue;

        if (!isset(self::$errorCodes[$pValue])) {
            $pValue = '#NULL!';
        }

        return $pValue;
    }
}


<?php

namespace XQueue\Maileon\API\Reports;

use XQueue\Maileon\API\XML\AbstractXMLWrapper;
use XQueue\Maileon\API\Reports\ReportContact;

/**
 * This class represents a bounce containing the timestamp, the contact, and the ID of the mailing.
 *
 * @author Jannik Jochem
 * @author Marcus Ständer | Trusted Mails GmbH | marcus.staender@trusted-mails.com
 */
class Bounce extends AbstractXMLWrapper
{
    /**
     * @var String
     */
    public $timestamp;

    /**
     * @var com_maileon_api_reports_ReportContact
     */
    public $contact;

    /**
     * @var long
     */
    public $mailingId;

    /**
     * Can be transient or permanent
     * @var String
     */
    public $type;

    /**
     * In the form of X.Y.Z
     * @var String
     */
    public $statusCode;

    /**
     * Can be mta-listener or inbound
     * @var String
     */
    public $source;

    /**
     * @return \em string
     *  containing a human-readable representation of this bounce
     */
    function toString()
    {
        return "Bounce [timestamp=" . $this->timestamp .
        ", contact=" . $this->contact->toString() .
        ", mailingId=" . $this->mailingId .
        ", type=" . $this->type .
        ", statusCode=" . $this->statusCode .
        ", source=" . $this->source . "]";
    }

    /**
     * @return \em csv string
     *  containing a csv pepresentation of this bounce
     */
    function toCsvString()
    {
        return $this->timestamp .
        ";" . $this->contact->toCsvString() .
        ";" . $this->mailingId .
        ";" . $this->type .
        ";" . $this->statusCode .
        ";" . $this->source;
    }

    /**
     * Initializes this bounce from an XML representation.
     *
     * @param SimpleXMLElement $xmlElement
     *  the XML representation to use
     */
    function fromXML($xmlElement)
    {
        $this->contact = new ReportContact();
        $this->contact->fromXML($xmlElement->contact);

        if (isset($xmlElement->mailing_id)) $this->mailingId = $xmlElement->mailing_id;
        if (isset($xmlElement->timestamp)) $this->timestamp = $xmlElement->timestamp;
        if (isset($xmlElement->type)) $this->type = $xmlElement->type;
        if (isset($xmlElement->status_code)) $this->statusCode = $xmlElement->status_code;
        if (isset($xmlElement->source)) $this->source = $xmlElement->source;
    }

    /**
     * For future use, not implemented yet.
     *
     * @return \em SimpleXMLElement
     *  containing the XML serialization of this object
     */
    function toXML()
    {
        // Not implemented yet.
    }
}


<?php
/*
 * This file is part of the CleverAge/PermissionBundle package.
 *
 * Copyright (c) 2015-2018 Clever-Age
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CleverAge\PermissionBundle\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;

/**
 * Allows the access to data based on it's class
 *
 * @author Vincent Chalnot <vchalnot@clever-age.com>
 */
class DataVoter implements VoterInterface
{
    /** @var ClassVoter */
    protected $classVoter;

    /**
     * @param ClassVoter $classVoter
     */
    public function __construct(ClassVoter $classVoter)
    {
        $this->classVoter = $classVoter;
    }

    /**
     * {@inheritdoc}
     *
     * @throws \Exception
     */
    public function vote(TokenInterface $token, $object, array $attributes)
    {
        if (\is_object($object)) {
            return $this->classVoter->vote($token, \get_class($object), $attributes);
        }

        return VoterInterface::ACCESS_ABSTAIN;
    }
}


<?php declare(strict_types=1);

namespace AlecRabbit\ConsoleColour;

use AlecRabbit\Cli\Tools\Terminal;
use AlecRabbit\ConsoleColour\Contracts\Styles;
use AlecRabbit\ConsoleColour\Core\Contracts\ConsoleColorInterface;
use AlecRabbit\ConsoleColour\Exception\InvalidStyleException;
use const AlecRabbit\COLOR256_TERMINAL;
use const AlecRabbit\COLOR_TERMINAL;
use const AlecRabbit\ESC;

class ConsoleColor implements ConsoleColorInterface
{
    /** @var bool */
    protected $supported;

    /** @var bool */
    protected $forced;

    /** @var array */
    protected $themes = [];

    /** @var bool */
    protected $are256ColorsSupported;

    /**
     * ConsoleColor constructor.
     * @param null|bool $force
     * @param bool $force256Colors
     */
    public function __construct(?bool $force = null, bool $force256Colors = false)
    {
        $this->setColorSupport($force ?? false, $force256Colors);
        $this->forced = $force ?? false;
    }

    protected function setColorSupport(bool $force, bool $force256Colors): void
    {
        $terminal = new Terminal();
        $this->supported = $force || ($terminal->color() >= COLOR_TERMINAL);
        $this->are256ColorsSupported = $this->supported && ($force256Colors || $terminal->color() >= COLOR256_TERMINAL);
    }

    /** {@inheritdoc} */
    public function apply($styles, $text): string
    {
        if (!$this->isSupported()) {
            return $text;
        }

        $sequences =
            $this->getSequencesFrom(
                $this->refineStyles($styles)
            );

        if (empty($sequences)) {
            return $text;
        }

        return $this->applySequences($text, $sequences);
    }

    /** {@inheritdoc} */
    public function isSupported(): bool
    {
        return $this->supported;
    }

    /**
     * @param array $styles
     * @return array
     * @throws InvalidStyleException
     */
    protected function getSequencesFrom(array $styles): array
    {
        $sequences = [[]];

        foreach ($styles as $style) {
            if (isset($this->themes[$style])) {
                $sequences[] = $this->themeSequence($style);
            } elseif ($this->isValid($style)) {
                $sequences[][] = $this->styleSequence($style);
            } else {
                throw new InvalidStyleException($style);
            }
        }

        return
            array_filter(
                array_merge(...$sequences),
                /**
                 * @param mixed $val
                 * @return bool
                 * @psalm-suppress MissingClosureParamType
                 */
                static function ($val): bool {
                    return $val !== null;
                }
            );
    }

    /**
     * @param string $name
     * @return string[]|null[]
     */
    protected function themeSequence($name): array
    {
        $sequences = [];
        foreach ($this->themes[$name] as $style) {
            $sequences[] = $this->styleSequence($style);
        }
        return $sequences;
    }

    /**
     * @param string $style
     * @return null|string
     */
    protected function styleSequence($style): ?string
    {
        if (\array_key_exists($style, static::CODES)) {
            return static::CODES[$style];
        }

        if (!$this->are256ColorsSupported()) {
            return null;
        }

        return
            $this->process256ColorStyle($style);
    }

    /** {@inheritdoc} */
    public function are256ColorsSupported(): bool
    {
        return $this->are256ColorsSupported;
    }

    /**
     * @param string $style
     * @return string
     */
    protected function process256ColorStyle(string $style): string
    {
        preg_match(self::COLOR256_REGEXP, $style, $matches);
        return
            sprintf(
                '%s;5;%s',
                $matches[1] === self::BG ? self::BACKGROUND : self::FOREGROUND,
                $matches[2]
            );
    }

    /**
     * @param string $style
     * @return bool
     */
    protected function isValid($style): bool
    {
        return
            \array_key_exists($style, static::CODES) || (bool)preg_match(self::COLOR256_REGEXP, $style);
    }

    /**
     * @param int|string|array $styles
     * @return array
     */
    protected function refineStyles($styles): array
    {
        if (\is_int($styles) || \is_string($styles)) {
            $styles = [$styles];
        }
        $this->assertStyles($styles);
        return $styles;
    }

    /**
     * @param mixed $styles
     */
    protected function assertStyles($styles): void
    {
        if (!\is_array($styles)) {
            throw new \InvalidArgumentException('Styles must be type of int, string or array.');
        }
    }

    /**
     * @param string $text
     * @param array $sequences
     * @return string
     */
    protected function applySequences(string $text, array $sequences): string
    {
        return
            $this->escSequence(implode(';', $sequences)) .
            $text .
            $this->escSequence((string)self::RESET);
    }

    /**
     * @param string $value
     * @return string
     */
    protected function escSequence(string $value): string
    {
        return
            ESC . '[' . $value . 'm';
    }

    /** {@inheritdoc} */
    public function isForced(): bool
    {
        return $this->forced;
    }

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

    /** {@inheritdoc} */
    public function setThemes(array $themes): void
    {
        $this->themes = [];
        foreach ($themes as $name => $styles) {
            $this->addTheme($name, $styles);
        }
    }

    /** {@inheritdoc} */
    public function addTheme($name, $styles, bool $override = false): void
    {
        if (\array_key_exists($name, $this->themes) && false === $override) {
            throw new \RuntimeException('Theme [' . $name . '] is already set.');
        }

        $styles = $this->refineStyles($styles);

        foreach ($styles as $style) {
            if (!$this->isValid($style)) {
                throw new InvalidStyleException($style);
            }
        }
        $this->themes[$name] = $styles;
    }

    /** {@inheritdoc} */
    public function hasTheme($name): bool
    {
        return isset($this->themes[$name]);
    }

    /** {@inheritdoc} */
    public function removeTheme($name): void
    {
        unset($this->themes[$name]);
    }

    /** {@inheritdoc} */
    public function getPossibleStyles(): array
    {
        return array_keys(Styles::NAMES);
    }
}


<?php

namespace PhpOffice\PhpSpreadsheet\Cell;

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;

class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder
{
    /**
     * Bind value to a cell.
     *
     * @param Cell $cell Cell to bind value to
     * @param mixed $value Value to bind in cell
     *
     * @return bool
     */
    public function bindValue(Cell $cell, $value = null)
    {
        // sanitize UTF-8 strings
        if (is_string($value)) {
            $value = StringHelper::sanitizeUTF8($value);
        }

        // Find out data type
        $dataType = parent::dataTypeForValue($value);

        // Style logic - strings
        if ($dataType === DataType::TYPE_STRING && !$value instanceof RichText) {
            //    Test for booleans using locale-setting
            if ($value == Calculation::getTRUE()) {
                $cell->setValueExplicit(true, DataType::TYPE_BOOL);

                return true;
            } elseif ($value == Calculation::getFALSE()) {
                $cell->setValueExplicit(false, DataType::TYPE_BOOL);

                return true;
            }

            // Check for number in scientific format
            if (preg_match('/^' . Calculation::CALCULATION_REGEXP_NUMBER . '$/', $value)) {
                $cell->setValueExplicit((float) $value, DataType::TYPE_NUMERIC);

                return true;
            }

            // Check for fraction
            if (preg_match('/^([+-]?)\s*(\d+)\s?\/\s*(\d+)$/', $value, $matches)) {
                // Convert value to number
                $value = $matches[2] / $matches[3];
                if ($matches[1] == '-') {
                    $value = 0 - $value;
                }
                $cell->setValueExplicit((float) $value, DataType::TYPE_NUMERIC);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode('??/??');

                return true;
            } elseif (preg_match('/^([+-]?)(\d*) +(\d*)\s?\/\s*(\d*)$/', $value, $matches)) {
                // Convert value to number
                $value = $matches[2] + ($matches[3] / $matches[4]);
                if ($matches[1] == '-') {
                    $value = 0 - $value;
                }
                $cell->setValueExplicit((float) $value, DataType::TYPE_NUMERIC);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode('# ??/??');

                return true;
            }

            // Check for percentage
            if (preg_match('/^\-?\d*\.?\d*\s?\%$/', $value)) {
                // Convert value to number
                $value = (float) str_replace('%', '', $value) / 100;
                $cell->setValueExplicit($value, DataType::TYPE_NUMERIC);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_PERCENTAGE_00);

                return true;
            }

            // Check for currency
            $currencyCode = StringHelper::getCurrencyCode();
            $decimalSeparator = StringHelper::getDecimalSeparator();
            $thousandsSeparator = StringHelper::getThousandsSeparator();
            if (preg_match('/^' . preg_quote($currencyCode, '/') . ' *(\d{1,3}(' . preg_quote($thousandsSeparator, '/') . '\d{3})*|(\d+))(' . preg_quote($decimalSeparator, '/') . '\d{2})?$/', $value)) {
                // Convert value to number
                $value = (float) trim(str_replace([$currencyCode, $thousandsSeparator, $decimalSeparator], ['', '', '.'], $value));
                $cell->setValueExplicit($value, DataType::TYPE_NUMERIC);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode(
                        str_replace('$', $currencyCode, NumberFormat::FORMAT_CURRENCY_USD_SIMPLE)
                    );

                return true;
            } elseif (preg_match('/^\$ *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) {
                // Convert value to number
                $value = (float) trim(str_replace(['$', ','], '', $value));
                $cell->setValueExplicit($value, DataType::TYPE_NUMERIC);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_SIMPLE);

                return true;
            }

            // Check for time without seconds e.g. '9:45', '09:45'
            if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) {
                // Convert value to number
                list($h, $m) = explode(':', $value);
                $days = $h / 24 + $m / 1440;
                $cell->setValueExplicit($days, DataType::TYPE_NUMERIC);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_TIME3);

                return true;
            }

            // Check for time with seconds '9:45:59', '09:45:59'
            if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) {
                // Convert value to number
                list($h, $m, $s) = explode(':', $value);
                $days = $h / 24 + $m / 1440 + $s / 86400;
                // Convert value to number
                $cell->setValueExplicit($days, DataType::TYPE_NUMERIC);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_TIME4);

                return true;
            }

            // Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10'
            if (($d = Date::stringToExcel($value)) !== false) {
                // Convert value to number
                $cell->setValueExplicit($d, DataType::TYPE_NUMERIC);
                // Determine style. Either there is a time part or not. Look for ':'
                if (strpos($value, ':') !== false) {
                    $formatCode = 'yyyy-mm-dd h:mm';
                } else {
                    $formatCode = 'yyyy-mm-dd';
                }
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getNumberFormat()->setFormatCode($formatCode);

                return true;
            }

            // Check for newline character "\n"
            if (strpos($value, "\n") !== false) {
                $value = StringHelper::sanitizeUTF8($value);
                $cell->setValueExplicit($value, DataType::TYPE_STRING);
                // Set style
                $cell->getWorksheet()->getStyle($cell->getCoordinate())
                    ->getAlignment()->setWrapText(true);

                return true;
            }
        }

        // Not bound yet? Use parent...
        return parent::bindValue($cell, $value);
    }
}


<?php

namespace PhpOffice\PhpSpreadsheet\Calculation;

class Logical
{
    /**
     * TRUE.
     *
     * Returns the boolean TRUE.
     *
     * Excel Function:
     *        =TRUE()
     *
     * @category Logical Functions
     *
     * @return bool True
     */
    public static function true()
    {
        return true;
    }

    /**
     * FALSE.
     *
     * Returns the boolean FALSE.
     *
     * Excel Function:
     *        =FALSE()
     *
     * @category Logical Functions
     *
     * @return bool False
     */
    public static function false()
    {
        return false;
    }

    /**
     * LOGICAL_AND.
     *
     * Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE.
     *
     * Excel Function:
     *        =AND(logical1[,logical2[, ...]])
     *
     *        The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays
     *            or references that contain logical values.
     *
     *        Boolean arguments are treated as True or False as appropriate
     *        Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
     *        If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
     *            the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value
     *
     * @category Logical Functions
     *
     * @param mixed ...$args Data values
     *
     * @return bool|string the logical AND of the arguments
     */
    public static function logicalAnd(...$args)
    {
        // Return value
        $returnValue = true;

        // Loop through the arguments
        $aArgs = Functions::flattenArray($args);
        $argCount = -1;
        foreach ($aArgs as $argCount => $arg) {
            // Is it a boolean value?
            if (is_bool($arg)) {
                $returnValue = $returnValue && $arg;
            } elseif ((is_numeric($arg)) && (!is_string($arg))) {
                $returnValue = $returnValue && ($arg != 0);
            } elseif (is_string($arg)) {
                $arg = strtoupper($arg);
                if (($arg == 'TRUE') || ($arg == Calculation::getTRUE())) {
                    $arg = true;
                } elseif (($arg == 'FALSE') || ($arg == Calculation::getFALSE())) {
                    $arg = false;
                } else {
                    return Functions::VALUE();
                }
                $returnValue = $returnValue && ($arg != 0);
            }
        }

        // Return
        if ($argCount < 0) {
            return Functions::VALUE();
        }

        return $returnValue;
    }

    /**
     * LOGICAL_OR.
     *
     * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE.
     *
     * Excel Function:
     *        =OR(logical1[,logical2[, ...]])
     *
     *        The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays
     *            or references that contain logical values.
     *
     *        Boolean arguments are treated as True or False as appropriate
     *        Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
     *        If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
     *            the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value
     *
     * @category Logical Functions
     *
     * @param mixed $args Data values
     *
     * @return bool|string the logical OR of the arguments
     */
    public static function logicalOr(...$args)
    {
        // Return value
        $returnValue = false;

        // Loop through the arguments
        $aArgs = Functions::flattenArray($args);
        $argCount = -1;
        foreach ($aArgs as $argCount => $arg) {
            // Is it a boolean value?
            if (is_bool($arg)) {
                $returnValue = $returnValue || $arg;
            } elseif ((is_numeric($arg)) && (!is_string($arg))) {
                $returnValue = $returnValue || ($arg != 0);
            } elseif (is_string($arg)) {
                $arg = strtoupper($arg);
                if (($arg == 'TRUE') || ($arg == Calculation::getTRUE())) {
                    $arg = true;
                } elseif (($arg == 'FALSE') || ($arg == Calculation::getFALSE())) {
                    $arg = false;
                } else {
                    return Functions::VALUE();
                }
                $returnValue = $returnValue || ($arg != 0);
            }
        }

        // Return
        if ($argCount < 0) {
            return Functions::VALUE();
        }

        return $returnValue;
    }

    /**
     * NOT.
     *
     * Returns the boolean inverse of the argument.
     *
     * Excel Function:
     *        =NOT(logical)
     *
     *        The argument must evaluate to a logical value such as TRUE or FALSE
     *
     *        Boolean arguments are treated as True or False as appropriate
     *        Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
     *        If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
     *            the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value
     *
     * @category Logical Functions
     *
     * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE
     *
     * @return bool|string the boolean inverse of the argument
     */
    public static function NOT($logical = false)
    {
        $logical = Functions::flattenSingleValue($logical);
        if (is_string($logical)) {
            $logical = strtoupper($logical);
            if (($logical == 'TRUE') || ($logical == Calculation::getTRUE())) {
                return false;
            } elseif (($logical == 'FALSE') || ($logical == Calculation::getFALSE())) {
                return true;
            }

            return Functions::VALUE();
        }

        return !$logical;
    }

    /**
     * STATEMENT_IF.
     *
     * Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE.
     *
     * Excel Function:
     *        =IF(condition[,returnIfTrue[,returnIfFalse]])
     *
     *        Condition is any value or expression that can be evaluated to TRUE or FALSE.
     *            For example, A10=100 is a logical expression; if the value in cell A10 is equal to 100,
     *            the expression evaluates to TRUE. Otherwise, the expression evaluates to FALSE.
     *            This argument can use any comparison calculation operator.
     *        ReturnIfTrue is the value that is returned if condition evaluates to TRUE.
     *            For example, if this argument is the text string "Within budget" and the condition argument evaluates to TRUE,
     *            then the IF function returns the text "Within budget"
     *            If condition is TRUE and ReturnIfTrue is blank, this argument returns 0 (zero). To display the word TRUE, use
     *            the logical value TRUE for this argument.
     *            ReturnIfTrue can be another formula.
     *        ReturnIfFalse is the value that is returned if condition evaluates to FALSE.
     *            For example, if this argument is the text string "Over budget" and the condition argument evaluates to FALSE,
     *            then the IF function returns the text "Over budget".
     *            If condition is FALSE and ReturnIfFalse is omitted, then the logical value FALSE is returned.
     *            If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned.
     *            ReturnIfFalse can be another formula.
     *
     * @category Logical Functions
     *
     * @param mixed $condition Condition to evaluate
     * @param mixed $returnIfTrue Value to return when condition is true
     * @param mixed $returnIfFalse Optional value to return when condition is false
     *
     * @return mixed The value of returnIfTrue or returnIfFalse determined by condition
     */
    public static function statementIf($condition = true, $returnIfTrue = 0, $returnIfFalse = false)
    {
        $condition = ($condition === null) ? true : (bool) Functions::flattenSingleValue($condition);
        $returnIfTrue = ($returnIfTrue === null) ? 0 : Functions::flattenSingleValue($returnIfTrue);
        $returnIfFalse = ($returnIfFalse === null) ? false : Functions::flattenSingleValue($returnIfFalse);

        return ($condition) ? $returnIfTrue : $returnIfFalse;
    }

    /**
     * IFERROR.
     *
     * Excel Function:
     *        =IFERROR(testValue,errorpart)
     *
     * @category Logical Functions
     *
     * @param mixed $testValue Value to check, is also the value returned when no error
     * @param mixed $errorpart Value to return when testValue is an error condition
     *
     * @return mixed The value of errorpart or testValue determined by error condition
     */
    public static function IFERROR($testValue = '', $errorpart = '')
    {
        $testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue);
        $errorpart = ($errorpart === null) ? '' : Functions::flattenSingleValue($errorpart);

        return self::statementIf(Functions::isError($testValue), $errorpart, $testValue);
    }
}


<?php
/**
 * Autoload file
 *
 * This file is part of periodic
 *
 * periodic is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; version 3 of the License.
 *
 * periodic is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with periodic; if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @package Core
 * @version $Revision$
 * @license http://www.gnu.org/licenses/lgpl-3.0.txt LGPL
 */

namespace Arbit\Periodic;

/**
 * Class providing easy means to access event times based on a given cron
 * string as defined by the vixie-cron daemon.
 */
class CronjobIterator implements \Iterator
{
    /**
     * Attributes of the class
     *
     * @var array
     */
    protected $attributes = array();

    /**
     * Pseudo key index incremented on every step and returned if asked for a
     * key
     *
     * @var int
     */
    protected $keyindex = 0;

    /**
     * A combination of months and days of the current year, which match the
     * given cron criteria. These two values are handled together because the
     * weekday depends on both of them
     *
     * @var array
     */
    protected $monthAndDays = array();

    /**
     * Hours in the current year which match the given cron criteria
     *
     * @var array
     */
    protected $hours = array();

    /**
     * Minutes in the current year which match the given cron criteria
     *
     * @var array
     */
    protected $minutes = array();

    /**
     * The year this iterator was instatiated in. This is needed if the
     * processing of the iterator takes place at a year boundary
     *
     * @var int
     */
    protected $year;

    /**
     * The year offset currently used
     *
     * @var int
     */
    protected $yearOffset = 0;

    /**
     * Constructor of the class taking a five tupel containing the values for
     * minute, hour, day of month, month, day of week in this order particular
     * order
     *
     * @param array $cronjob A five tupel of minute, hour, day of month, month
     * and day of week
     * @return void
     */
    public function __construct( array $cronjob )
    {
        $this->attributes = array(
            'minute'        =>  $cronjob[0],
            'hour'          =>  $cronjob[1],
            'dayOfMonth'    =>  $cronjob[2],
            'month'         =>  $cronjob[3],
            'dayOfWeek'     =>  $cronjob[4],
            'startTime'     =>  null,
        );

        if ( $this->validateColumns( $cronjob ) !== true )
        {
            throw new \UnexpectedValueException( 'The supplied cronjob data is invalid.' );
        }

        $this->year = (int)date( 'Y', $this->getCurrentTime() );
    }

    /**
     * Create a cronjobIterator based a complete cronjob definition line
     *
     * @param mixed $cronjobString The cronjob string to use for creation
     * @return CronjobIterator The cronjobIterator based on the given
     * cronjobString
     */
    public static function fromString( $cronjobString )
    {
        /*
         * @todo: maybe this splitting should be done using a regex to support
         * arbitrary whitespace characters
         */
        return new CronjobIterator(
            explode( ' ', $cronjobString )
        );
    }

    /**
     * Return the current time as a timestamp if the attribute startTime is not
     * set. Otherwise return the specified startTime.
     *
     * @return int Either the current time or the defined startTime.
     */
    protected function getCurrentTime()
    {
        return ( ( $this->attributes['startTime'] === null )
               ? ( time() )
               : ( $this->attributes['startTime'] ) );
    }

    /**
     * Validate all cron columns
     *
     * @param mixed $columns Array of cron columns to be checked
     * @return bool True if the columns are valid. Otherwise boolean false or
     * an interger indicating which column is invalid (zero indexed) is
     * returned.
     */
    protected function validateColumns( $columns )
    {
        $patterns = array(
            '((?P<minute>(?:\*|(?:(?:[0-9]|[1-5][0-9])(?:-(?:[0-9]|[1-5][0-9]))?)(?:,(?:[0-9]|[1-5][0-9])(?:-(?:[0-9]|[1-5][0-9]))?)*)(?:/(?:[1-9]|[1-5][0-9]))?)$)AD',
            '((?P<hour>(?:\*|(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3]))?)(?:,(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3]))?)*)(?:/(?:[1-9]|1[0-9]|2[0-3]))?)$)AD',
            '((?P<dayOfMonth>(?:\*|(?:(?:[1-9]|[1-2][0-9]|3[0-1])(?:-(?:[1-9]|[1-2][0-9]|3[0-1]))?)(?:,(?:[1-9]|[1-2][0-9]|3[0-1])(?:-(?:[1-9]|[1-2][0-9]|3[0-1]))?)*)(?:/(?:[1-9]|[1-2][0-9]|3[0-1]))?)$)AD',
            '((?P<month>(?:\*|(?:(?:[1-9]|1[0-2])(?:-(?:[1-9]|1[1-2]))?)(?:,(?:[1-9]|1[1-2])(?:-(?:[1-9]|1[1-2]))?)*)(?:/(?:[1-9]|1[1-2]))?)$)AD',
            '((?P<dayOfWeek>(?:\*|(?:(?:[0-7])(?:-(?:[0-7]))?)(?:,(?:[0-7])(?:-(?:[0-7]))?)*)(?:/(?:[1-7]))?)$)AD',
        );

        if ( count( $columns ) !== 5 )
        {
            return false;
        }

        foreach( $columns as $key => $column )
        {
            if ( preg_match( $patterns[$key], $column ) !== 1 )
            {
                return (int)$key;
            }
        }

        return true;
    }

    /**
     * Generate a timetable array containing the timestamps of this cronjob for
     * the currently processed year
     *
     * @param int Offset in correlation to the current year to select the year
     * to process
     *
     * @return void
     */
    protected function generateTimetable( $yearOffset = 0 )
    {
        // Reset the current data arrays
        $this->monthAndDays = array();
        $this->hours        = array();
        $this->minutes      = array();

        $this->yearOffset = $yearOffset;
        $year = $this->year + $this->yearOffset;

        // If we are processing the year we are currently in we will need some
        // extra information ready for filtering events from the past
        if ( $this->yearOffset === 0 )
        {
            $currentMonth = (int)date( 'm', $this->getCurrentTime() );
            $currentDay   = (int)date( 'd', $this->getCurrentTime() );
        }

        // Read the columns and generate lists of possible dates
        $months  = $this->applyStepping(
            $this->extractRange( $this->attributes['month'], 1, 12 ),
            $this->extractStep( $this->attributes['month'] )
        );
        $days  = $this->applyStepping(
            $this->extractRange( $this->attributes['dayOfMonth'], 1, 31 ),
            $this->extractStep( $this->attributes['dayOfMonth'] )
        );
        $this->hours  = $this->applyStepping(
            $this->extractRange( $this->attributes['hour'], 0, 23 ),
            $this->extractStep( $this->attributes['hour'] )
        );
        $this->minutes  = $this->applyStepping(
            $this->extractRange( $this->attributes['minute'], 0, 59 ),
            $this->extractStep( $this->attributes['minute'] )
        );

        // If the current year is processed every month that lies before the
        // current one can be removed because it is definetly an event in the past
        if ( $this->yearOffset === 0 )
        {
            foreach ( $months as $nr => $month )
            {
                if ( $month < $currentMonth )
                {
                    unset( $months[$nr] );
                }
            }
        }

        // Combine the months and days into a single array to be able to handle
        // the dayOfWeek entries appropriately

        // There is one special case. If the dayOfWeek is specified, but the
        // dayOfMonth is not restricted (*), only the matching weekdays will
        // the used. Therefore the following processing can be skipped.
        if ( $this->attributes['dayOfMonth'] !== '*' || $this->attributes['dayOfWeek'] === '*' )
        {
            foreach( $months as $month )
            {
                foreach( $days as $day )
                {
                    // Check if we are in the past
                    if ( $this->yearOffset === 0 )
                    {
                        // It is only useful to check this in the first year ;)
                        if ( $month === $currentMonth ) // Use currentMonth which was stored before
                        {
                            if ( $day < $currentDay )
                            {
                                continue;
                            }

                        }
                    }

                    if ( $this->isValidDate( $year, $month, $day ) === true )
                    {
                        $this->monthAndDays[sprintf(
                            '%02d-%02d',
                            $month,
                            $day
                        )] = true;
                    }
                }
            }
        }

        /*
         * Retrieve every day that matches the given dayOfWeek definition if it
         * is restricted in any way
         */
        if ( $this->attributes['dayOfWeek'] !== '*' )
        {
            $weekdays = $this->applyStepping(
                $this->extractRange( $this->attributes['dayOfWeek'], 0, 7 ),
                $this->extractStep( $this->attributes['dayOfWeek'] )
            );

            // Sanitize the weekday array for later processing by ISO-8601
            // weekday specification
            $weekdays = array_flip( $weekdays );
            if( array_key_exists( 0, $weekdays ) )
            {
                unset( $weekdays[0] );
                $weekdays[7] = true;
            }

            /*
             * To get a list of all dates which lie on the given weekdays we
             * loop through every possible date of the year and check for the
             * weekday. We need to take into account the month restriction
             * though.
             */
            foreach( $months as $month )
            {
                for( $day = 1; $day <= 31; ++$day )
                {
                    // Check if we are in the past
                    if ( $this->yearOffset === 0 )
                    {
                        // It is only useful to check this in the first year ;)
                        if ( $month === $currentMonth ) // Use currentMonth which was stored before
                        {
                            if ( $day < $currentDay )
                            {
                                continue;
                            }

                        }
                    }

                    if ( $this->isValidDate( $year, $month, $day ) !== true )
                    {
                        break;
                    }

                    $isoWeekday = (int)date(
                        'N',
                        strtotime(
                            sprintf(
                                '%d-%02d-%02d',
                                $year,
                                $month,
                                $day
                            )
                        )
                    );
                    if ( array_key_exists( $isoWeekday, $weekdays ) )
                    {
                        $this->monthAndDays[sprintf(
                            '%02d-%02d',
                            $month,
                            $day
                        )] = true;
                    }
                }
            }
        }

        /*
         * Flip keys and values on the monthAndDays array and sort it to be easily
         * processable by foreach in the correct order
         */
        $this->monthAndDays = array_keys( $this->monthAndDays );
        sort( $this->monthAndDays );
    }

    /**
     * Check if the given year, month and day combination is a valid calendar
     * entry
     *
     * @param int $year Year to be checked
     * @param int $month Month to be checked
     * @param int $day Day to be checked
     * @return bool True if it is a valid date false otherwise
     */
    protected function isValidDate( $year, $month, $day )
    {
        // Some basic sanity checking
        if ( $month <= 0 || $month > 12 || $day <= 0 || $day > 31 )
        {
            return false;
        }

        // Check for months with 30 days
        if (   ( $month == 4 || $month == 6 || $month == 9 || $month == 11 )
            && ( $day == 31 ) )
        {
            return false;
        }

        // Check for februaries
        if ( $month == 2 )
        {
            // Februrary has a maximum of 29 dates (in a leap year)
            if ( $day > 29 )
            {
                return false;
            }
            // Check if it is a leap year
            $leap = date( 'L', strtotime( $year . '-01-01' ) );
            if ( $leap === '0' && $day > 28 )
            {
                return false;
            }
        }

        return true;
    }

    /**
     * Take a cron column as argument and return an array containing every item
     * in range of the definition
     *
     * @param mixed $definition Cron column/definition to use for extraction
     * @return array Array containing everything defined in the given range. Or
     * bool false if the range is not restricted And no ranges are specified.
     */
    protected function extractRange( $definition, $min = null, $max=null )
    {
        $resultSet = array();

        if ( substr( $definition, 0, 1 ) === '*' )
        {
            // We need ranges otherwise a full set can not be created
            if ( $min === null || $max === null )
            {
                return false;
            }

            for( $i=$min; $i<=$max; ++$i )
            {
                $resultSet[] = $i;
            }

            return $resultSet;
        }

        // Remove the stepping part if it is available
        if ( ( $position = strpos( $definition, '/' ) ) !== false )
        {
            $definition = substr( $definition, 0, $position );
        }

        // Split the definition into list elements. At least one elements needs
        // to be there
        $ranges = explode( ',', $definition );

        foreach( $ranges as $range )
        {
            // There might be a '-' sign which indicates a real range, split it accordingly.
            $entries = explode( '-', $range );
            // If there is only one entry just add it to the result array
            if ( count( $entries ) === 1 )
            {
                $resultSet[] = (int)$entries[0];
            }
            // If a range is defined it needs to be calculated
            else
            {
                $high = (int)max( $entries );
                $low  = (int)min( $entries );

                for( $i=$low; $i<=$high; ++$i )
                {
                    $resultSet[] = $i;
                }
            }
        }

        return $resultSet;
    }

    /**
     * Extract the stepping defined by a given cron column
     *
     * @param mixed $definition Cron definition to use for stepping extraction
     * @return bool false if the stepping does not exist. Otherwise the step is
     * returned as an int
     */
    protected function extractStep( $definition )
    {
        if ( ( $position = strpos( $definition, '/' ) ) !== false )
        {
            return (int)substr( $definition, $position + 1 );
        }
        return false;
    }

    /**
     * Take a range array and apply a defined stepping to it.
     *
     * @param array $range Range array to apply the stepping to
     * @param int $step Stepping to be applied
     * @return array Array with the given stepping applied
     */
    protected function applyStepping( $range, $step )
    {
        if ( $step === false || $step === 1 )
        {
            return $range;
        }

        foreach ( $range as $value => $tmp )
        {
            if ( ( $value % $step ) !== 0 )
            {
                unset( $range[$value] );
            }
        }
        return array_values( $range );
    }

    /**
     * Return the next timestamp which lies in the future. This function
     * handles the regeneration of the timetable information on year boundaries
     * correctly.
     *
     * @return int Timestamp of the next future event
     */
    protected function getNextFutureTimestamp()
    {
        /*
        * To save time in pregeneration we use the array traversal functions
        * here to create iteratively accessed foreach loops on monthAndDays,
        * hours and minutes
        */

        // These values are only used if we are inside the current year
        // Because they will not change significantly during the loop we are
        // just generating them once.
        if ( $this->yearOffset === 0 )
        {
            $currentHour   = (int)date( 'H', $this->getCurrentTime() );
            $currentMinute = (int)date( 'i', $this->getCurrentTime() );
            $currentDay    = (int)date( 'd', $this->getCurrentTime() );
            $currentMonth  = (int)date( 'm', $this->getCurrentTime() );
        }

        do
        {
            // Initialize all timetable values with their current value
            $minute      = current( $this->minutes );
            $hour        = current( $this->hours );
            $monthAndDay = current( $this->monthAndDays );

            // Advance one step
            $minute = next( $this->minutes );
            if ( $minute === false )
            {
                // We reached the end of the minutes array. Therefore we need
                // to advance hours and reset minutes
                $minute = reset( $this->minutes );
                $hour = next( $this->hours );
                if ( $hour === false )
                {
                    // We reached the end of the hours array. Therefore we need
                    // to advance monthAndDays and reset hours
                    $hour = reset( $this->hours );
                    $monthAndDay = next( $this->monthAndDays );
                    if( $monthAndDay === false )
                    {
                        // We reached the end of monthAndDays. Therefore we
                        // need to generate new tables for the next year.
                        $this->generateTimetable( $this->yearOffset + 1 );

                        // Use the first entry of every timetable array
                        $minute      = reset( $this->minutes );
                        $hour        = reset( $this->hours );
                        $monthAndDay = reset( $this->monthAndDays );
                    }
                }
            }

            /*
             * We could use strtotime and just check against the timestamp here.
             * Unfortunately this would be slower by factor 3. Therefore this
             * manual checking routine is used
             */
            // Only the current year is of interest everything else is in the
            // future anyway.
            if ( $this->yearOffset === 0 )
            {
                if ( ( $month = (int)substr( $monthAndDay, 0, 2 ) ) === $currentMonth )
                {
                    if ( ( $day = (int)substr( $monthAndDay, 3, 2 ) ) < $currentDay )
                    {
                        continue;
                    }
                    if ( $day === $currentDay )
                    {
                        if ( $hour < $currentHour )
                        {
                            continue;
                        }
                        if ( $hour === $currentHour )
                        {
                            if ( $minute < $currentMinute )
                            {
                                continue;
                            }
                        }
                    }
                }
            }

            $nextElement = strtotime(
                sprintf(
                    '%d-%s %02d:%02d:00',
                    $this->year + $this->yearOffset, $monthAndDay, $hour, $minute
                )
            );

            // The next element has been found, therefore the loop can be
            // broken
            break;

        } while( true );

        return $nextElement;
    }

    /**
     * Iterator interface function returning the current element
     *
     * @return int Current crontimestamp
     */
    public function current()
    {
        $minute      = current( $this->minutes );
        $hour        = current( $this->hours );
        $monthAndDay = current( $this->monthAndDays );

        $currentElement = strtotime(
            sprintf(
                '%d-%s %02d:%02d:00',
                $this->year + $this->yearOffset, $monthAndDay, $hour, $minute
            )
        );

        if ( $currentElement < $this->getCurrentTime() )
        {
            $currentElement = $this->getNextFutureTimestamp();
        }

        return $currentElement;
    }

    /**
     * Iterator interface function returning the next element
     *
     * @return int Next crontimestamp
     */
    public function next()
    {
        ++$this->keyindex;
        return $this->getNextFutureTimestamp();
    }

    /**
     * Iterator interface function returning the current key
     *
     * @return int current iterator key
     */
    public function key()
    {
        return $this->keyindex;
    }

    /**
     * Iterator interface function resetting the interator
     *
     * @return void
     */
    public function rewind()
    {
        /*
         * If we changed the years already we need to recalculate the data for
         * the first one
         */
        if ( $this->yearOffset !== 0 )
        {
            $this->generateTimetable( 0 );
        }
        else
        {
            // Just reset the current array pointers if the year is correct
            reset( $this->minutes );
            reset( $this->hours );
            reset( $this->monthAndDays );
        }
    }

    /**
     * Iterator interface function returning if the current element of the
     * iterator is valid
     *
     * @return bool
     */
    public function valid()
    {
        // There are always more entries
        return true;
    }

    /**
     * Interceptor method to handle writable attributes
     *
     * @param mixed $k
     * @param mixed $v
     * @return void
     */
    public function __set( $k, $v )
    {
        if ( array_key_exists( $k, $this->attributes ) !== true )
        {
            throw new AttributeException( AttributeException::NON_EXISTANT, $k );
        }

        switch( $k )
        {
            case 'startTime':
                // The crontable is minutes based therefore we need to ceil the
                // seconds value to the next full minute if it is not zero
                if ( ( ( $difference =  $v % 60 ) ) !== 0 )
                {
                    $v += 60 - $difference;
                }

                $this->attributes['startTime'] = (int)$v;
                // Set the newly provided year
                $this->year = (int)date( 'Y', $v );
                // The timetable needs to be regenerated
                $this->generateTimetable( 0 );
            break;
            default:
                throw new AttributeException( AttributeException::WRITE, $k );
        }
    }

    /**
     * Interceptor method to handle readable attributes
     *
     * @param mixed $k
     * @return mixed
     */
    public function __get( $k )
    {
        if ( array_key_exists( $k, $this->attributes ) !== true )
        {
            throw new AttributeException( AttributeException::NON_EXISTANT, $k );
        }

        // All existant attributes are readable
        switch( $k )
        {
            default:
                return $this->attributes[$k];
        };
    }
}


<?php namespace Scriptotek\Ncip;

use Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement;
use Carbon\Carbon;

class Response {

    /** @var QuiteSimpleXMLElement */
	protected $dom;

    /** @var bool */
	public $success;

    /** @var string */
	public $error;

    /** @var string */
	public $errorDetails;

    /** @var array */
	protected $args;

    /** @var array */
	protected $successArgs;

    /** @var array */
	protected $failureArgs;

	/**
	 * Create a new Response
	 *
	 * @param  QuiteSimpleXMLElement  $dom
	 * @return void
	 */
	public function __construct(QuiteSimpleXMLElement $dom = null)
	{
		$this->dom = $dom;
		$this->success = false;

		if (is_null($this->dom)) {
			return;
		}

		if ($this->dom->first('ns1:Problem')) {
			$this->error = $this->dom->text('ns1:Problem/ns1:ProblemType');
			$this->errorDetails = $this->dom->text('ns1:Problem/ns1:ProblemDetail');
		} else {
			$this->success = true;
		}

	}

	public function parseDateTime($datestring) {
		return new Carbon($datestring);
	}

	public function formatDateTime($datetime) {
		return $datetime->format(\DateTime::ISO8601); // does not include milliseconds
	}

	protected function parseBibliographicDescription($b)
	{
		$a = array(
			'title' => $b->text('ns1:Title'),
			'author' => $b->text('ns1:Author'),
			'publicationDate' => $b->text('ns1:PublicationDate'),
			'publisher' => $b->text('ns1:Publisher'),
			'objektid' => $b->text('ns1:BibliographicRecordId/ns1:BibliographicRecordIdentifier'),
			'edition' => $b->text('ns1:Edition'),
			'pagination' => $b->text('ns1:Pagination'),
			'language' => $b->text('ns1:Language'),
			'mediumType' => $b->text('ns1:MediumType')
		);
		return $a;
	}

	/**
	 * Validate a set of arguments
	 *
	 * @return void
	 */
	public function validateArgSet($set)
	{
		if (isset($set)) {
			foreach ($set as $arg) {
				if (!isset($this->{$arg})) {
					throw new \Exception('Response not valid: ' . $arg . ' has not been set!');
				}
			}
		}

	}

	/**
	 * Validate the response
	 *
	 * @return void
	 */
	protected function validate()
	{
		$this->validateArgSet($this->args);

		if ($this->success) {
			$this->validateArgSet($this->successArgs);
		}

		if (!$this->success) {
			$this->validateArgSet($this->failureArgs);
		}
	}

}


<?php

namespace Webcore\Validation\Rules;

use Webcore\Validation\AbstractRuleTrait;

trait EmailTrait
{
    use AbstractRuleTrait;

    /**
     * "I found some addresses that FILTER_VALIDATE_EMAIL rejects, but RFC5321 permits"
     * http://php.net/manual/en/function.filter-var.php#112492
     *
     * @param $value
     */
    private function validateEmail($value)
    {
        $isValid = filter_var($value, FILTER_VALIDATE_EMAIL);
        if ($isValid === false) {
            $this->throwInvalidArgumentMustBe("valid email");
        }
    }
}


<?php namespace Scriptotek\Ncip;

use Illuminate\Support\ServiceProvider;

class NcipServiceProvider extends ServiceProvider {

	/**
	 * Indicates if loading of the provider is deferred.
	 *
	 * @var bool
	 */
	protected $defer = false;

	/**
	 * Bootstrap the application events.
	 *
	 * @return void
	 */
	public function boot() {
		$this->package('danmichaelo/ncip');
	}

	/**
	 * Register the service provider.
	 *
	 * @return void
	 */
	public function register()
	{
		$this->app['ncip.client'] = $this->app->share(function($app)
		{
			//\Log::info( 'URL: ' . $app['config']['ncip::url'] );
			$conn = new NcipConnector(
				$app['config']['ncip::url'],
				$app['config']['ncip::user_agent'],
				$app['config']['ncip::agency_id']
			);
			$cli = new NcipClient($conn);
			if (array_get($app['config'], 'ncip::debug', false)) {
				$cli->on('message.send', function($msg) {
					\Log::debug('[NCIP SEND] ' . $msg);
				});
				$cli->on('message.recv', function($msg) {
					\Log::debug('[NCIP RECV] ' . $msg);
				});
			}
			return $cli;
		});

		$this->app['ncip.server'] = $this->app->share(function($app)
		{
			return new NcipServer($app['config']['ncip.agency_id']);
		});
	}

	/**
	 * Get the services provided by the provider.
	 *
	 * @return string[]
	 */
	public function provides()
	{
		return array('ncip.client', 'ncip.server');
	}

}


<?php namespace Cerbero\Auth\Pipes\Login;

use Cerbero\Auth\Exceptions\DisplayException;
use Cerbero\Auth\Pipes\AbstractPipe;
use Cerbero\Auth\Services\Throttling\ThrottlerInterface;

class Throttle extends AbstractPipe {

	/**
	 * Run before the job is handled.
	 *
	 * @param	Cerbero\Auth\Services\Throttling\ThrottlerInterface	$throttler
	 * @param	Cerbero\Auth\Jobs\LoginJob	$job
	 * @return	mixed
	 */
	public function before(ThrottlerInterface $throttler, $job)
	{
		$throttler->setSource($this->getSourceByJob($job));

		$throttler->incrementAttempts();

		if($throttler->tooManyAttempts() || $throttler->lockedOut())
		{
			$throttler->lockOut();

			$seconds = $throttler->getRemainingSeconds();

			throw new DisplayException('auth::throttling.error', compact('seconds'));
		}
	}

	/**
	 * Create source by using the given job.
	 *
	 * @author	Andrea Marco Sartori
	 * @param	type	$job
	 * @return	string
	 */
	private function getSourceByJob($job)
	{
		$login = head(array_except($job->credentials, 'password'));

		return $login . app('request')->ip();
	}

	/**
	 * Run after the handled job.
	 *
	 * @param	Cerbero\Auth\Services\Throttling\ThrottlerInterface	$throttler
	 * @param	mixed	$handled
	 * @param	Cerbero\Auth\Jobs\LoginJob	$job
	 * @return	mixed
	 */
	public function after(ThrottlerInterface $throttler, $handled, $job)
	{
		$throttler->resetAttempts();
	}

	/**
	 * Determine whether the whole pipe has to be processed.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	boolean
	 */
	protected function isEnabled()
	{
		return config('_auth.login.throttling.enabled');
	}

}


<?php namespace Cerbero\Auth\Pipes;

use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;

/**
 * Abstract implementation of a pipe that dispatches events.
 *
 * @author	Andrea Marco Sartori
 */
abstract class AbstractEventDispatcherPipe extends AbstractPipe {

	/**
	 * @author	Andrea Marco Sartori
	 * @var		Illuminate\Contracts\Events\Dispatcher	$dispatcher	Event dispatcher.
	 */
	protected $dispatcher;

	/**
	 * Set the dependencies.
	 *
	 * @author	Andrea Marco Sartori
	 * @param	Illuminate\Contracts\Container\Container	$container
	 * @param	Illuminate\Contracts\Events\Dispatcher	$dispatcher
	 * @return	void
	 */
	public function __construct(Container $container, Dispatcher $dispatcher)
	{
		parent::__construct($container);

		$this->dispatcher = $dispatcher;
	}

	/**
	 * Run before the job is handled.
	 *
	 * @param	mixed	$job
	 * @return	mixed
	 */
	public function before($job)
	{
		$this->fireEventOn('start', $job);
	}

	/**
	 * Fire an event at some point.
	 *
	 * @author	Andrea Marco Sartori
	 * @param	string	$action
	 * @param	mixed	$payload
	 * @return	void
	 */
	private function fireEventOn($action, $payload)
	{
		$event = $this->getEventName();

		$this->dispatcher->fire("auth.{$event}.{$action}", $payload);
	}

	/**
	 * Retrieve the event name.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	string
	 */
	protected function getEventName()
	{
		$chunks = explode('\\', get_class($this));

		$name = $chunks[count($chunks) - 2];

		return strtolower($name);
	}

	/**
	 * Run after the handled job.
	 *
	 * @param	mixed	$handled
	 * @param	mixed	$job
	 * @return	mixed
	 */
	public function after($handled, $job)
	{
		$this->fireEventOn('end', [$handled, $job]);
	}

}


<?php

/*
 * This file is part of the ONGR package.
 *
 * (c) NFQ Technologies UAB <info@nfq.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace ONGR\ConnectionsBundle\EventListener;

use ONGR\ConnectionsBundle\Import\DoctrineImportIterator;
use ONGR\ConnectionsBundle\Pipeline\Event\SourcePipelineEvent;

/**
 * Class ImportSourceEventListener - gets items from Doctrine, creates empty Elasticsearch documents.
 */
class ImportSourceEventListener extends AbstractImportSourceEventListener
{
    /**
     * Gets all documents by given type.
     *
     * @return DoctrineImportIterator
     */
    public function getAllDocuments()
    {
        return new DoctrineImportIterator(
            $this->getDoctrineManager()->createQuery("SELECT e FROM {$this->getentityClass()} e")->iterate(),
            $this->getDoctrineManager(),
            $this->getElasticsearchManager()->getRepository($this->getDocumentClass())
        );
    }

    /**
     * Gets data and adds source.
     *
     * @param SourcePipelineEvent $event
     */
    public function onSource(SourcePipelineEvent $event)
    {
        $event->addSource($this->getAllDocuments());
    }
}


<?php

/**
 * Payload description
 *
 * Unauthorized copying or dissemination of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 *
 * @author    Jorge Torres <jorge.torres@wondeotec.com>
 * @copyright Copyright (C) Wondeotec SA - All Rights Reserved
 * @license   LICENSE.txt
 */

namespace EB\SDK\Webhook;

/**
 * Payload
 */
class Payload implements \JsonSerializable
{
    /**
     * @var string The event IP address
     */
    protected $ipAddress;

    /**
     * @var string The action
     */
    protected $action;

    /**
     * @var int The Emailbidding campaign Id where this event relates to
     */
    protected $campaignId;

    /**
     * @var string The recipient list external Id (publisher's database Id)
     */
    protected $listExternalId;

    /**
     * @var string The reason of the event
     */
    protected $reason;

    /**
     * @var string The recipient email address
     */
    protected $recipientEmailAddress;

    /**
     * @var string The recipient email address hash
     */
    protected $hash;

    /**
     * @var string The recipient external Id (Id in the publisher's database)
     */
    protected $recipientExternalId;

    /**
     * @var \DateTime The event date
     */
    protected $triggerDate;

    /**
     * @var string The event type
     */
    protected $type;

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

    /**
     * @param string $ipAddress
     *
     * @return Payload
     */
    public function setIpAddress($ipAddress)
    {
        $this->ipAddress = $ipAddress;

        return $this;
    }

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

    /**
     * @param string $action
     *
     * @return Payload
     * @throws \Exception
     */
    public function setAction($action)
    {
        if (! Type::isValidWebhookType($action)) {
            throw new \Exception(sprintf('The action "%s" isn\'t supported!', $action));
        }

        $this->action = $action;

        return $this;
    }

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

    /**
     * @param int $campaignId
     *
     * @return Payload
     */
    public function setCampaignId($campaignId)
    {
        $this->campaignId = $campaignId;

        return $this;
    }

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

    /**
     * @param string $listExternalId
     *
     * @return Payload
     */
    public function setListExternalId($listExternalId)
    {
        $this->listExternalId = $listExternalId;

        return $this;
    }

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

    /**
     * @param string $reason
     *
     * @return Payload
     *
     * @throws \Exception
     */
    public function setReason($reason)
    {
        if (! Type::isValidReason($reason)) {
            throw new \Exception(sprintf('The action "%s" isn\'t supported!', $reason));
        }

        $this->reason = $reason;

        return $this;
    }

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

    /**
     * @param string $recipientEmailAddress
     *
     * @return Payload
     */
    public function setRecipientEmailAddress($recipientEmailAddress)
    {
        $this->recipientEmailAddress = $recipientEmailAddress;

        return $this;
    }

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

    /**
     * @param string $hash
     *
     * @return Payload
     */
    public function setHash($hash)
    {
        $this->hash = $hash;

        return $this;
    }

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

    /**
     * @param string $recipientExternalId
     *
     * @return Payload
     */
    public function setRecipientExternalId($recipientExternalId)
    {
        $this->recipientExternalId = $recipientExternalId;

        return $this;
    }

    /**
     * @return \DateTime
     */
    public function getTriggerDate()
    {
        return $this->triggerDate;
    }

    /**
     * @param \DateTime $triggerDate
     *
     * @return Payload
     */
    public function setTriggerDate(\DateTime $triggerDate)
    {
        $this->triggerDate = $triggerDate;

        return $this;
    }

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

    /**
     * @param string $type
     *
     * @return Payload
     * @throws \Exception
     */
    public function setType($type)
    {
        if (! Type::isValidWebhookType($type)) {
            throw new \Exception(sprintf('The action "%s" isn\'t supported!', $type));
        }

        $this->type = $type;

        return $this;
    }

    /**
     * (PHP 5 >= 5.4.0)

     * Specify data which should be serialized to JSON
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
     * @return mixed data which can be serialized by json_encode,
     * which is a value of any type other than a resource.
     */
    public function jsonSerialize()
    {
        return [
            'ip_address' => $this->getIpAddress(),
            'action'  => $this->getAction(),
            'campaign_id' => (int)$this->getCampaignId(),
            'list_external_id' => $this->getListExternalId(),
            'reason' => $this->getReason(),
            'recipient_email_address' => $this->getRecipientEmailAddress(),
            'hash' => $this->getHash(),
            'recipient_external_id' => (string)$this->getRecipientExternalId(),
            'trigger_date' => $this->getTriggerDate()->format('Y-m-d h:i:s'),
            'type' => $this->getType()
        ];
    }
}


<?php

namespace Cerbero\Auth\Services\Throttling;

use Illuminate\Contracts\Cache\Repository as Cache;

/**
 * Login throttler using cache.
 *
 * @author	Andrea Marco Sartori
 */
class CachingThrottler implements ThrottlerInterface
{

	/**
	 * @author	Andrea Marco Sartori
	 * @var		Illuminate\Contracts\Cache\Repository	$cache	Cache repository.
	 */
	protected $cache;

	/**
	 * @author	Andrea Marco Sartori
	 * @var		string	$key	Source where attempts come from.
	 */
	protected $key;

	/**
	 * @author	Andrea Marco Sartori
	 * @var		string	$lockOutKey	Key to store lock out time in.
	 */
	protected $lockOutKey;

	/**
	 * Set the dependencies.
	 *
	 * @author	Andrea Marco Sartori
	 * @param	Illuminate\Contracts\Cache\Repository	$cache
	 * @return	void
	 */
	public function __construct(Cache $cache)
	{
		$this->cache = $cache;
	}

	/**
	 * Set univocal source where attempts come from.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	boolean
	 */
	public function setSource($source)
	{
		$this->key = $source;

		$this->lockOutKey = "{$source}:lockout";
	}

	/**
	 * Determine whether the user has been locked out.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	boolean
	 */
	public function lockedOut()
	{
		return $this->cache->has($this->lockOutKey);
	}

	/**
	 * Retrieve the number of remaining seconds before the next attempt.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	integer
	 */
	public function getRemainingSeconds()
	{
		return $this->cache->get($this->lockOutKey) - time();
	}

	/**
	 * Increment the number of failed attempts.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	void
	 */
	public function incrementAttempts()
	{
		$this->cache->add($this->key, 0, $this->getExpiry());

		$this->cache->increment($this->key);
	}

	/**
	 * Retrieve the minutes after which keys expire.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	integer
	 */
	private function getExpiry()
	{
		return (int) $this->getDelay() / 60;
	}

	/**
	 * Retrieve the seconds to wait before the next attempt.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	integer
	 */
	private function getDelay()
	{
		return config('_auth.login.throttling.delay');
	}

	/**
	 * Determine whether a user has performed too many attempts.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	boolean
	 */
	public function tooManyAttempts()
	{
		$maximum = config('_auth.login.throttling.max_attempts');

		return $this->cache->get($this->key, 0) > $maximum;
	}

	/**
	 * Lock a user out.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	void
	 */
	public function lockOut()
	{
		$this->resetAttempts();

		$this->cache->add($this->lockOutKey, $this->getDelay() + time(), $this->getExpiry());
	}

	/**
	 * Reset the attempts counter.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	void
	 */
	public function resetAttempts()
	{
		$this->cache->forget($this->key);
	}

}


<?php

/**
 * @package Flextype Components
 *
 * @author Sergey Romanenko <awilum@yandex.ru>
 * @link http://components.flextype.org
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Flextype\Component\ErrorHandler;

class ErrorHandler
{

    /**
     * Error Levels
     */
    public static $levels = array (
        E_ERROR             => 'Fatal Error',
        E_PARSE             => 'Parse Error',
        E_COMPILE_ERROR     => 'Compile Error',
        E_COMPILE_WARNING   => 'Compile Warning',
        E_STRICT            => 'Strict Mode Error',
        E_NOTICE            => 'Notice',
        E_WARNING           => 'Warning',
        E_RECOVERABLE_ERROR => 'Recoverable Error',
        E_USER_NOTICE       => 'Notice',
        E_USER_WARNING      => 'Warning',
        E_USER_ERROR        => 'Error',
    );

    /**
     * Returns an array of lines from a file.
     *
     * @param  string $file    File in which you want to highlight a line
     * @param  int    $line    Line number to highlight
     * @param  int    $padding (optional) Number of padding lines
     * @return array
     */
    protected static function highlightCode(string $file, int $line, int $padding = 6) : array
    {
        if ( ! is_readable($file)) {
            return false;
        }

        $handle      = fopen($file, 'r');
        $lines       = array();
        $currentLine = 0;

        while ( ! feof($handle)) {
            $currentLine++;

            $temp = fgets($handle);

            if ($currentLine > $line + $padding) {
                break; // Exit loop after we have found what we were looking for
            }

            if ($currentLine >= ($line - $padding) && $currentLine <= ($line + $padding)) {
                $lines[] = array
                (
                    'number'      => str_pad($currentLine, 4, ' ', STR_PAD_LEFT),
                    'highlighted' => ($currentLine === $line),
                    'code'        => ErrorHandler::highlightString($temp),
                );
            }
        }

        fclose($handle);

        return $lines;
    }

    /**
     * Converts errors to ErrorExceptions.
     *
     * @param  int     $code    The error code
     * @param  string  $message The error message
     * @param  string  $file    The filename where the error occurred
     * @param  int     $line    The line number where the error occurred
     * @return bool
     */
    public static function error(int $code, string $message, string $file, int $line) : bool
    {
        // If isset error_reporting and $code then throw new error exception
        if ((error_reporting() & $code) !== 0) {

            /**
             * Dont thow NOTICE exception for PRODUCTION Environment. Just write to log.
             */
            if (DEVELOPMENT == false && $code == 8) {

                // Get exception info
                $error['code']    = $code;
                $error['message'] = $message;
                $error['file']    = $file;
                $error['line']    = $line;
                $error['type']    = 'ErrorException: ';

                $codes = array (
                    E_USER_NOTICE       => 'Notice',
                );

                $error['type'] .= in_array($error['code'], array_keys($codes)) ? $codes[$error['code']] : 'Unknown Error';

                // Write to log
                ErrorHandler::writeLogs("{$error['type']}: {$error['message']} in {$error['file']} at line {$error['line']}");

            } else {
                throw new \ErrorException($message, $code, 0, $file, $line);
            }
        }

        // Don't execute PHP internal error handler
        return true;
    }

    /**
     * Highlight string
     *
     * @param  string $string String
     * @return string
     */
    protected static function highlightString(string $string) : string
    {
        $search  = array("\r\n", "\n\r", "\r", "\n", '', '', '<?php ', '#$@r4!/*');
        $replace = array('', '', '', '', '', '', '', '/*');

        return str_replace($search, $replace, highlight_string('<?php ' . str_replace('/*', '#$@r4!/*', $string), true));
    }

    /**
     * Modifies the backtrace array.
     *
     * @param  array $backtrace Array returned by the getTrace() method of an exception object
     * @return array
     */
    protected static function formatBacktrace(array $backtrace) : array
    {
        if (is_array($backtrace) === false || count($backtrace) === 0) {
            return $backtrace;
        }

        /**
         * Remove unnecessary info from backtrace
         */
        if ($backtrace[0]['function'] == '{closure}') {
            unset($backtrace[0]);
        }

        /**
         * Format backtrace
         */
        $trace = [];

        foreach ($backtrace as $entry) {

            /**
             * Function
             */
            $function = '';

            if (isset($entry['class'])) {
                $function .= $entry['class'] . $entry['type'];
            }

            $function .= $entry['function'] . '()';

            /**
             * Arguments
             */
            $arguments = [];

            if (isset($entry['args']) && count($entry['args']) > 0) {
                foreach ($entry['args'] as $arg) {
                    ob_start();

                    var_dump($arg);

                    $arg = htmlspecialchars(ob_get_contents());

                    ob_end_clean();

                    $arguments[] = $arg;
                }
            }

            /**
             * Location
             */
            $location = [];

            if (isset($entry['file'])) {
                $location['file'] = $entry['file'];
                $location['line'] = $entry['line'];
                $location['code'] = self::highlightCode($entry['file'], $entry['line']);
            }

            /**
             * Compile into array
             */
            $trace[] = array
            (
                'function'  => $function,
                'arguments' => $arguments,
                'location'  => $location,
            );
        }

        return $trace;
    }

    /**
     * Convert errors not caught by the error handler to ErrorExceptions.
     */
    public static function fatal()
    {
        $e = error_get_last();

        if ($e !== null && (error_reporting() & $e['type']) !== 0) {
            ErrorHandler::exception(new \ErrorException($e['message'], $e['type'], 0, $e['file'], $e['line']));

            exit(1);
        }
    }

    /**
     * Writes message to log.
     *
     * @param  string  $message The message to write to the log
     * @return bool
     */
    public static function writeLogs(string $message) : bool
    {
        return (bool) file_put_contents(rtrim(LOGS_PATH, '/') . '/' . gmdate('Y_m_d') . '.log',
                                        '[' . gmdate('d-M-Y H:i:s') . '] ' . $message . PHP_EOL,
                                        FILE_APPEND);
    }

    /**
     * Handles uncaught exceptions and returns a pretty error screen.
     *
     * @param Exception $exception An exception object
     */
    public static function exception($exception)
    {
        try {

            // Empty output buffers
            while(ob_get_level() > 0) ob_end_clean();

            // Get exception info
            $error['code']    = $exception->getCode();
            $error['message'] = $exception->getMessage();
            $error['file']    = $exception->getFile();
            $error['line']    = $exception->getLine();

            // Determine error type
            if ($exception instanceof \ErrorException) {
                $error['type'] = 'ErrorException: ';
                $error['type'] .= in_array($error['code'], array_keys(ErrorHandler::$levels)) ? ErrorHandler::$levels[$error['code']] : 'Unknown Error';
            } else {
                $error['type'] = get_class($exception);
            }

            // Write to log
            ErrorHandler::writeLogs("{$error['type']}: {$error['message']} in {$error['file']} at line {$error['line']}");

            // Send headers and output
            @header('Content-Type: text/html; charset=UTF-8');

            if (DEVELOPMENT) {

                $error['backtrace'] = $exception->getTrace();

                if ($exception instanceof \ErrorException) {
                    $error['backtrace'] = array_slice($error['backtrace'], 1); //Remove call to error handler from backtrace
                }

                $error['backtrace']   = self::formatBacktrace($error['backtrace']);
                $error['highlighted'] = self::highlightCode($error['file'], $error['line']);

                @header('HTTP/1.1 500 Internal Server Error');
                include 'views/exception.php';

            } else {

                @header('HTTP/1.1 500 Internal Server Error');
                include 'views/production.php';

            }

        } catch (Exception $e) {

            // Empty output buffers
            while(ob_get_level() > 0) ob_end_clean();

            echo $e->getMessage() . ' in ' . $e->getFile() . ' (line ' . $e->getLine() . ').';
        }

        exit(1);
    }
}


<?php
/**
 * Arbit Xml node list
 *
 * This file is part of Arbit.
 *
 * Arbit is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; version 3 of the License.
 *
 * Arbit is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Arbit; if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @package XML
 * @version $Revision$
 * @license http://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
 */

namespace Arbit\Xml;

/*
 * XML node list
 *
 * Single element node in an XML document mostly behaving like a
 * SimpleXMLElement node list.
 */
class NodeList implements \ArrayAccess, \Iterator, \Countable
{
    /**
     * Nodes in node list
     *
     * @var array(Node)
     */
    protected $nodes;

    /**
     * Create new configuration node list.
     *
     * Create new configuration node list.
     *
     * @return void
     */
    public function __construct()
    {
        $this->nodes = array();
    }

    /**
     * Access property in node list
     *
     * Accessing a property directly on a node list will return a new node list
     * with all childs with this name of all nodes in the current node list.
     *
     * @param string $childName
     * @return NodeList
     */
    public function __get( $childName )
    {
        // Create new list to fill up
        $list = new NodeList();

        // Iterate over all nodes and check if a child with the requested name
        // exists.
        foreach ( $this->nodes as $node )
        {
            if ( $node->$childName )
            {
                // If such a node exists iterate over returned node list and
                // append all childs to returned node list.
                foreach ( $node->$childName as $childNode )
                {
                    $list[] = $childNode;
                }
            }
        }

        return $list;
    }

    /**
     * Access childs through object properties
     *
     * Access childs through object properties
     *
     * @param string $property
     * @param mixed $value
     * @return Node
     */
    public function __set( $property, $value )
    {
        throw new AccessException( $property, 'Setting not allowed' );
    }

    /**
     * Check if a property exists
     *
     * Check if a property given by its name as object property exists. This is
     * a quite expensive operation on a node list.
     *
     * @param string $childName
     * @return bool
     */
    public function __isset( $childName )
    {
        // Iterate over all nodes and check if a child with the requested name
        // exists.
        foreach ( $this->nodes as $node )
        {
            if ( isset( $node->$childName ) )
            {
                // We found something, so that we can immediatly exit with
                // true. The general count is out of interest here.
                return true;
            }
        }

        // Return false, if no such property could be found before...
        return false;
    }

    /**
     * Set object state after var_export.
     *
     * Set object state after var_export.
     *
     * @param array $array
     * @return void
     */
    public static function __set_state( array $array )
    {
        $list = new NodeList();

        // Just append all known nodes using array access.
        foreach ( $array['nodes'] as $node )
        {
            $list[] = $node;
        }

        return $list;
    }

    /**
     * String representation of node list
     *
     * String representation of node list returns the string representation of
     * the first node in the list.
     *
     * @return string
     */
    public function __toString()
    {
        $firstNode = reset( $this->nodes );
        return (string) $firstNode;
    }

    /*
     * ArrayAccess
     */

    /**
     * Check if node exists in node list.
     *
     * Check if node exists in node list.
     *
     * @param int $item
     * @return void
     */
    public function offsetExists( $item )
    {
        return array_key_exists( $item, $this->nodes );
    }

    /**
     * Get node from node list.
     *
     * Get node from node list by its number.
     *
     * @param int $item
     * @return Node
     */
    public function offsetGet( $item )
    {
        if ( $this->offsetExists( $item ) )
        {
            return $this->nodes[$item];
        }

        return false;
    }

    /**
     * Append node to node list
     *
     * Append node to node list
     *
     * @param int $item
     * @param Node $node
     * @return void
     */
    public function offsetSet( $item, $node )
    {
        // We only allow to append nodes to node list, so that we bail out on
        // all other array keys then null.
        if ( $item !== null )
        {
            throw new ValueException( $item, 'null' );
        }

        return $this->nodes[] = $node;
    }

    /**
     * Remove node from node list.
     *
     * Removing nodes from the node list is not allowed. You may only add nodes
     * here.
     *
     * @param int $item
     * @return void
     */
    public function offsetUnset( $item )
    {
        throw new ValueException( 'unset', 'Removing nodes not allowed.' );
    }

    /**
     * Iterator
     */

    /**
     * Implements current() for Iterator
     *
     * @return mixed
     */
    public function current()
    {
        return current( $this->nodes );
    }

    /**
     * Implements key() for Iterator
     *
     * @return int
     */
    public function key()
    {
        return key( $this->nodes );
    }

    /**
     * Implements next() for Iterator
     *
     * @return mixed
     */
    public function next()
    {
        return next( $this->nodes );
    }

    /**
     * Implements rewind() for Iterator
     *
     * @return mixed
     */
    public function rewind()
    {
        // If no nodes are in subtree return false
        if ( !count( $this->nodes ) )
        {
            return false;
        }

        return reset( $this->nodes );
    }

    /**
     * Implements valid() for Iterator
     *
     * @return boolean
     */
    public function valid()
    {
        return ( current( $this->nodes ) !== false );
    }

    /**
     * Countable
     */

    /**
     * Return count of nodes in node list.
     *
     * Return count of nodes in node list.
     *
     * @return int
     */
    public function count()
    {
        return count( $this->nodes );
    }
}


<?php namespace Cerbero\Auth\Http\Controllers;

use Cerbero\Auth\Jobs\LoginJob;
use Cerbero\Auth\Jobs\LogoutJob;
use Cerbero\Auth\Jobs\RegisterJob;
use Cerbero\Auth\Jobs\RecoverJob;
use Cerbero\Auth\Jobs\ResetJob;
use Cerbero\Auth\Http\Requests\LoginRequest;
use Cerbero\Auth\Http\Requests\RecoverRequest;
use Cerbero\Auth\Http\Requests\RegisterRequest;
use Cerbero\Auth\Http\Requests\ResetRequest;
use Cerbero\Auth\Services\Dispatcher\DispatcherInterface;
use Illuminate\Routing\Controller;

class AuthController extends Controller {

	/**
	 * @author	Andrea Marco Sartori
	 * @var		Cerbero\Auth\Services\Dispatcher\DispatcherInterface	$bus	Bus dispatcher.
	 */
	protected $bus;

	/**
	 * @author	Andrea Marco Sartori
	 * @var		array	$loginPipes	List of pipes for the login process.
	 */
	protected $loginPipes = ['DispatchEvent', 'Throttle'];

	/**
	 * @author	Andrea Marco Sartori
	 * @var		array	$logoutPipes	List of pipes for the logout process.
	 */
	protected $logoutPipes = ['DispatchEvent'];

	/**
	 * @author	Andrea Marco Sartori
	 * @var		array	$registerPipes	List of pipes for the register process.
	 */
	protected $registerPipes = ['DispatchEvent', 'Login', 'Notify', 'Hash'];

	/**
	 * @author	Andrea Marco Sartori
	 * @var		array	$recoverPipes	List of pipes for the password recover process.
	 */
	protected $recoverPipes = ['DispatchEvent', 'Notify', 'Store'];

	/**
	 * @author	Andrea Marco Sartori
	 * @var		array	$resetPipes	List of pipes for the password reset process.
	 */
	protected $resetPipes = ['DispatchEvent'];

	/**
	 * Set the dependencies.
	 *
	 * @author	Andrea Marco Sartori
	 * @param	Cerbero\Auth\Services\Dispatcher\DispatcherInterface	$bus
	 * @return	void
	 */
	public function __construct(DispatcherInterface $bus)
	{
		$this->bus = $bus;
	}

	/**
	 * Display the login page.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\Response
	 */
	public function showLogin()
	{
		$login = config('_auth.login.view');

		return view($login);
	}

	/**
	 * Log the user in.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\RedirectResponse
	 */
	public function login(LoginRequest $request)
	{
		$this->bus->pipeThrough($this->pipesOf('login'))->dispatchFrom(LoginJob::class, $request);

		return redirect()->route(config('_auth.login.redirect'));
	}

	/**
	 * Retrieve the pipes of a given process.
	 *
	 * @author	Andrea Marco Sartori
	 * @param	string	$process
	 * @return	array
	 */
	protected function pipesOf($process)
	{
		$Process = ucfirst($process);

		return array_map(function($pipe) use($Process)
		{
			return "Cerbero\Auth\Pipes\\{$Process}\\{$pipe}";

		}, $this->{"{$process}Pipes"});
	}

	/**
	 * Log the user out.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\RedirectResponse
	 */
	public function logout()
	{
		$this->bus->pipeThrough($this->pipesOf('logout'))->dispatchNow(new LogoutJob);

		return redirect()->route(config('_auth.logout.redirect'));
	}

	/**
	 * Display the registration page.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\Response
	 */
	public function showRegister()
	{
		$register = config('_auth.register.view');

		return view($register);
	}

	/**
	 * Register the user.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\RedirectResponse
	 */
	public function register(RegisterRequest $request)
	{
		$this->bus->pipeThrough($this->pipesOf('register'))->dispatchFrom(RegisterJob::class, $request);

		return redirect()->route(config('_auth.register.redirect'))->withSuccess(trans('auth::register.success'));
	}

	/**
	 * Display the recover page.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\Response
	 */
	public function showRecover()
	{
		$recover = config('_auth.recover.view');

		return view($recover);
	}

	/**
	 * Remember the user password.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\RedirectResponse
	 */
	public function recover(RecoverRequest $request)
	{
		$this->bus->pipeThrough($this->pipesOf('recover'))->dispatchFrom(RecoverJob::class, $request);

		return back()->withSuccess(trans('auth::recover.success'));
	}

	/**
	 * Display the reset page.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\Response
	 */
	public function showReset($token)
	{
		$reset = config('_auth.reset.view');

		return view($reset);
	}

	/**
	 * Reset the user password.
	 *
	 * @author	Andrea Marco Sartori
	 * @return	Illuminate\Http\RedirectResponse
	 */
	public function reset(ResetRequest $request, $token)
	{
		$this->bus->pipeThrough($this->pipesOf('reset'))->dispatchFrom(ResetJob::class, $request, compact('token'));

		return redirect()->route('login.index')->withSuccess(trans('auth::reset.success'));
	}

}