<?php
/**
 * @author Taylor Otwell
 *
 * Function added : capitalize
 */

namespace Neutrino\Support;

class Str
{
    /**
     * Transliterate a UTF-8 value to ASCII.
     *
     * @param  string $value
     *
     * @return string
     */
    public static function ascii($value)
    {
        foreach (Str::charsArray() as $key => $val) {
            $value = str_replace($val, $key, $value);
        }

        return preg_replace('/[^\x20-\x7E]/u', '', $value);
    }

    /**
     * Convert a value to camel case.
     *
     * @param  string $value
     *
     * @return string
     */
    public static function camel($value)
    {
        static $camelCache;

        if (isset($camelCache[$value])) {
            return $camelCache[$value];
        }

        return $camelCache[$value] = lcfirst(Str::studly($value));
    }

    /**
     * Determine if a given string contains a given substring.
     *
     * @param  string       $haystack
     * @param  string|array $needles
     *
     * @return bool
     */
    public static function contains($haystack, $needles)
    {
        foreach ((array)$needles as $needle) {
            if ($needle != '' && mb_strpos($haystack, $needle) !== false) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if a given string ends with a given substring.
     *
     * @param  string       $haystack
     * @param  string|array $needles
     *
     * @return bool
     */
    public static function endsWith($haystack, $needles)
    {
        foreach ((array)$needles as $needle) {
            if ((string)$needle === Str::substr($haystack, -Str::length($needle))) {
                return true;
            }
        }

        return false;
    }

    /**
     * Cap a string with a single instance of a given value.
     *
     * @param  string $value
     * @param  string $cap
     *
     * @return string
     */
    public static function finish($value, $cap)
    {
        $quoted = preg_quote($cap, '/');

        return preg_replace('/(?:' . $quoted . ')+$/u', '', $value) . $cap;
    }

    /**
     * Determine if a given string matches a given pattern.
     *
     * @param  string $pattern
     * @param  string $value
     *
     * @return bool
     */
    public static function is($pattern, $value)
    {
        if ($pattern == $value) {
            return true;
        }

        $pattern = preg_quote($pattern, '#');

        // Asterisks are translated into zero-or-more regular expression wildcards
        // to make it convenient to check if the strings starts with the given
        // pattern such as "library/*", making any string check convenient.
        $pattern = str_replace('\*', '.*', $pattern);

        return (bool)preg_match('#^' . $pattern . '\z#u', $value);
    }

    /**
     * Return the length of the given string.
     *
     * @param  string $value
     *
     * @return int
     */
    public static function length($value)
    {
        return mb_strlen($value);
    }

    /**
     * Sort a words list by their levenshtein distance of word.
     *
     * @param string   $word
     * @param string[] $words
     * @param int      $order
     * @param int      $sort_flags
     *
     * @return mixed
     */
    public static function levenshtein($word, $words, $order = SORT_ASC, $sort_flags = SORT_REGULAR)
    {
        foreach ($words as $w) {
            $result[$w] = levenshtein($word, $w);
        }

        if ($order & SORT_DESC) {
            arsort($result, $sort_flags);
        } else {
            asort($result, $sort_flags);
        }

        return $result;
    }

    /**
     * Limit the number of characters in a string.
     *
     * @param  string $value
     * @param  int    $limit
     * @param  string $end
     *
     * @return string
     */
    public static function limit($value, $limit = 100, $end = '...')
    {
        if (mb_strwidth($value, 'UTF-8') <= $limit) {
            return $value;
        }

        return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')) . $end;
    }

    /**
     * Convert the given string to lower-case.
     *
     * @param  string $value
     *
     * @return string
     */
    public static function lower($value)
    {
        return mb_strtolower($value, 'UTF-8');
    }

    /**
     * Limit the number of words in a string.
     *
     * @param  string $value
     * @param  int    $words
     * @param  string $end
     *
     * @return string
     */
    public static function words($value, $words = 100, $end = '...')
    {
        preg_match('/^\s*+(?:\S++\s*+){1,' . $words . '}/u', $value, $matches);
        if (!isset($matches[0]) || Str::length($value) === Str::length($matches[0])) {
            return $value;
        }

        return rtrim($matches[0]) . $end;
    }

    /**
     * Parse a "Class@method" style callback into class and method.
     *
     * @param  string $callback
     * @param  string $default
     *
     * @return array
     */
    public static function parseCallback($callback, $default)
    {
        return Str::contains($callback, '@')
            ? explode('@', $callback, 2)
            : [$callback, $default];
    }

    /**
     * Generate a more truly "random" alpha-numeric string.
     *
     * @param  int $length
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    public static function random($length = 16)
    {
        $string = '';
        while (($len = Str::length($string)) < $length) {
            $size = $length - $len;

            $bytes = Str::callRandom($size);

            $string .= Str::substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
        }

        return $string;
    }

    /**
     * Generate a "random" alpha-numeric string.
     *
     * Should not be considered sufficient for cryptography, etc.
     *
     * @param  int $length
     *
     * @return string
     */
    public static function quickRandom($length = 16)
    {
        return Str::substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $length)), 0, $length);
    }

    /**
     * Replace the first occurrence of a given value in the string.
     *
     * @param  string $search
     * @param  string $replace
     * @param  string $subject
     *
     * @return string
     */
    public static function replaceFirst($search, $replace, $subject)
    {
        $position = strpos($subject, $search);

        if ($position !== false) {
            return substr_replace($subject, $replace, $position, strlen($search));
        }

        return $subject;
    }

    /**
     * Replace the last occurrence of a given value in the string.
     *
     * @param  string $search
     * @param  string $replace
     * @param  string $subject
     *
     * @return string
     */
    public static function replaceLast($search, $replace, $subject)
    {
        $position = strrpos($subject, $search);

        if ($position !== false) {
            return substr_replace($subject, $replace, $position, strlen($search));
        }

        return $subject;
    }

    /**
     * Convert the given string to upper-case.
     *
     * @param  string $value
     *
     * @return string
     */
    public static function upper($value)
    {
        return mb_strtoupper($value, 'UTF-8');
    }

    /**
     * Convert the given string to title case.
     *
     * @param  string $value
     *
     * @return string
     */
    public static function title($value)
    {
        return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
    }

    /**
     * Generate a URL friendly "slug" from a given string.
     *
     * @param  string $title
     * @param  string $separator
     *
     * @return string
     */
    public static function slug($title, $separator = '-')
    {
        $title = Str::ascii($title);

        // Convert all dashes/underscores into separator
        $flip  = $separator == '-' ? '_' : '-';
        $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
        $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', mb_strtolower($title));
        // Replace all separator characters and whitespace by a single separator
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);

        return trim($title, $separator);
    }

    /**
     * Convert a string to snake case.
     *
     * @param  string $value
     * @param  string $delimiter
     *
     * @return string
     */
    public static function snake($value, $delimiter = '_')
    {
        static $snakeCache;

        $key = $value;
        if (isset($snakeCache[$key][$delimiter])) {
            return $snakeCache[$key][$delimiter];
        }
        if (!ctype_lower($value)) {
            $value = preg_replace('/\s+/u', '', $value);
            $value = Str::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
        }

        return $snakeCache[$key][$delimiter] = $value;
    }

    /**
     * Determine if a given string starts with a given substring.
     *
     * @param  string       $haystack
     * @param  string|array $needles
     *
     * @return bool
     */
    public static function startsWith($haystack, $needles)
    {
        foreach ((array)$needles as $needle) {
            if ($needle != '' && mb_strpos($haystack, $needle) === 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Convert a value to studly caps case.
     *
     * @param  string $value
     *
     * @return string
     */
    public static function studly($value)
    {
        static $studlyCache;

        $key = $value;

        if (isset($studlyCache[$key])) {
            return $studlyCache[$key];
        }

        $value = ucwords(str_replace(['-', '_'], ' ', $value));

        return $studlyCache[$key] = str_replace(' ', '', $value);
    }

    /**
     * Convert a value to Capitalize case.
     *
     * @param  string $value
     *
     * @return string
     */
    public static function capitalize($value)
    {
        static $capitalizeCache;

        $key = $value;

        if (isset($capitalizeCache[$key])) {
            return $capitalizeCache[$key];
        }

        return $capitalizeCache[$key] = ucwords(strtolower($value));
    }

    /**
     * Returns the portion of string specified by the start and length parameters.
     *
     * @param  string   $string
     * @param  int      $start
     * @param  int|null $length
     *
     * @return string
     */
    public static function substr($string, $start, $length = null)
    {
        return mb_substr($string, $start, $length, 'UTF-8');
    }

    /**
     * Make a string's first character uppercase.
     *
     * @param  string $string
     *
     * @return string
     */
    public static function ucfirst($string)
    {
        return Str::upper(Str::substr($string, 0, 1)) . Str::substr($string, 1);
    }

    /**
     * @deprecated use Path::normalize instead
     *
     * @param $path
     *
     * @return string
     */
    public static function normalizePath($path)
    {
        trigger_error('Deprecated: ' . __METHOD__ . '. Use ' . Path::class . '::normalize instead.', E_USER_DEPRECATED);

        if (empty($path)) {
            return '';
        }

        $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);

        $parts = explode('/', $path);

        $safe = [];
        foreach ($parts as $idx => $part) {
            if (($idx == 0 && empty($part))) {
                $safe[] = '';
            } elseif (trim($part) == "" || $part == '.') {
            } elseif ('..' == $part) {
                if (null === array_pop($safe) || empty($safe)) {
                    $safe[] = '';
                }
            } else {
                $safe[] = $part;
            }
        }

        if (count($safe) === 1 && $safe[0] === '') {
            return DIRECTORY_SEPARATOR;
        }

        return implode(DIRECTORY_SEPARATOR, $safe);
    }

    private static function callRandom($size)
    {
        static $randFunc;

        switch ($randFunc) {
            case 'random_bytes':
                return random_bytes($size);
            case '\Sodium\randombytes_buf':
                return \Sodium\randombytes_buf($size);
            case 'openssl_random_pseudo_bytes':
                return openssl_random_pseudo_bytes($size);
            case 'mcrypt_create_iv':
                return mcrypt_create_iv($size, MCRYPT_DEV_URANDOM);
            case '\Phalcon\Security\Random':
                static $random;
                if(!isset($random)){
                    $random = new \Phalcon\Security\Random();
                }

                return $random->bytes($size);
            default:
                if (function_exists('random_bytes')) {
                    $randFunc = 'random_bytes';
                } elseif (function_exists('\Sodium\randombytes_buf')) {
                    $randFunc = '\Sodium\randombytes_buf';
                } elseif (function_exists('openssl_random_pseudo_bytes')) {
                    $randFunc = 'openssl_random_pseudo_bytes';
                } elseif (function_exists('mcrypt_create_iv')) {
                    $randFunc = 'mcrypt_create_iv';
                } else {
                    $randFunc = '\Phalcon\Security\Random';
                }

                return Str::callRandom($size);
        }
    }

    /**
     * Returns the replacements for the ascii method.
     *
     * Note: Adapted from Stringy\Stringy.
     *
     * @see https://github.com/danielstjules/Stringy/blob/2.2.0/LICENSE.txt
     *
     * @return array
     */
    private static function charsArray()
    {
        static $charsArray;

        if (isset($charsArray)) {
            return $charsArray;
        }

        return $charsArray = [
            '0'    => ['°', '₀', '۰'],
            '1'    => ['¹', '₁', '۱'],
            '2'    => ['²', '₂', '۲'],
            '3'    => ['³', '₃', '۳'],
            '4'    => ['⁴', '₄', '۴', '٤'],
            '5'    => ['⁵', '₅', '۵', '٥'],
            '6'    => ['⁶', '₆', '۶', '٦'],
            '7'    => ['⁷', '₇', '۷'],
            '8'    => ['⁸', '₈', '۸'],
            '9'    => ['⁹', '₉', '۹'],
            'a'    => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å',
                       'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά',
                       'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا'],
            'b'    => ['б', 'β', 'Ъ', 'Ь', 'ب', 'ဗ', 'ბ'],
            'c'    => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
            'd'    => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ'],
            'e'    => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ',
                       'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ'],
            'f'    => ['ф', 'φ', 'ف', 'ƒ', 'ფ'],
            'g'    => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ'],
            'h'    => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ'],
            'i'    => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ',
                       'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი',
                       'इ'],
            'j'    => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج'],
            'k'    => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک'],
            'l'    => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'],
            'm'    => ['м', 'μ', 'م', 'မ', 'მ'],
            'n'    => ['ñ', 'ń', 'ň', 'ņ', 'ŉ', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ'],
            'o'    => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő',
                       'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ'],
            'p'    => ['п', 'π', 'ပ', 'პ', 'پ'],
            'q'    => ['ყ'],
            'r'    => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ'],
            's'    => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს'],
            't'    => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ'],
            'u'    => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ',
                       'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ'],
            'v'    => ['в', 'ვ', 'ϐ'],
            'w'    => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ'],
            'x'    => ['χ', 'ξ'],
            'y'    => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ'],
            'z'    => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ'],
            'aa'   => ['ع', 'आ', 'آ'],
            'ae'   => ['ä', 'æ', 'ǽ'],
            'ai'   => ['ऐ'],
            'at'   => ['@'],
            'ch'   => ['ч', 'ჩ', 'ჭ', 'چ'],
            'dj'   => ['ђ', 'đ'],
            'dz'   => ['џ', 'ძ'],
            'ei'   => ['ऍ'],
            'gh'   => ['غ', 'ღ'],
            'ii'   => ['ई'],
            'ij'   => ['ĳ'],
            'kh'   => ['х', 'خ', 'ხ'],
            'lj'   => ['љ'],
            'nj'   => ['њ'],
            'oe'   => ['ö', 'œ', 'ؤ'],
            'oi'   => ['ऑ'],
            'oii'  => ['ऒ'],
            'ps'   => ['ψ'],
            'sh'   => ['ш', 'შ', 'ش'],
            'shch' => ['щ'],
            'ss'   => ['ß'],
            'sx'   => ['ŝ'],
            'th'   => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
            'ts'   => ['ц', 'ც', 'წ'],
            'ue'   => ['ü'],
            'uu'   => ['ऊ'],
            'ya'   => ['я'],
            'yu'   => ['ю'],
            'zh'   => ['ж', 'ჟ', 'ژ'],
            '(c)'  => ['©'],
            'A'    => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą',
                       'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ',
                       'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ'],
            'B'    => ['Б', 'Β', 'ब'],
            'C'    => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
            'D'    => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'],
            'E'    => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ',
                       'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə'],
            'F'    => ['Ф', 'Φ'],
            'G'    => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
            'H'    => ['Η', 'Ή', 'Ħ'],
            'I'    => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ',
                       'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ'],
            'K'    => ['К', 'Κ'],
            'L'    => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल'],
            'M'    => ['М', 'Μ'],
            'N'    => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'],
            'O'    => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő',
                       'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ'],
            'P'    => ['П', 'Π'],
            'R'    => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'],
            'S'    => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
            'T'    => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
            'U'    => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ',
                       'Ǘ', 'Ǚ', 'Ǜ'],
            'V'    => ['В'],
            'W'    => ['Ω', 'Ώ', 'Ŵ'],
            'X'    => ['Χ', 'Ξ'],
            'Y'    => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ'],
            'Z'    => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
            'AE'   => ['Ä', 'Æ', 'Ǽ'],
            'CH'   => ['Ч'],
            'DJ'   => ['Ђ'],
            'DZ'   => ['Џ'],
            'GX'   => ['Ĝ'],
            'HX'   => ['Ĥ'],
            'IJ'   => ['Ĳ'],
            'JX'   => ['Ĵ'],
            'KH'   => ['Х'],
            'LJ'   => ['Љ'],
            'NJ'   => ['Њ'],
            'OE'   => ['Ö', 'Œ'],
            'PS'   => ['Ψ'],
            'SH'   => ['Ш'],
            'SHCH' => ['Щ'],
            'SS'   => ['ẞ'],
            'TH'   => ['Þ'],
            'TS'   => ['Ц'],
            'UE'   => ['Ü'],
            'YA'   => ['Я'],
            'YU'   => ['Ю'],
            'ZH'   => ['Ж'],
            ' '    => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84",
                       "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A",
                       "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80"],
        ];
    }
}


<?php namespace Fbf\LaravelCategories;

use Illuminate\Support\ServiceProvider;

class LaravelCategoriesServiceProvider 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('fbf/laravel-categories');

		\App::register('Baum\BaumServiceProvider');
		\App::register('Cviebrock\EloquentSluggable\SluggableServiceProvider');

		// Shortcut so developers don't need to add an Alias in app/config/app.php
		$this->app->booting(function()
		{
			$loader = \Illuminate\Foundation\AliasLoader::getInstance();
			$loader->alias('Sluggable', 'Cviebrock\EloquentSluggable\Facades\Sluggable');
		});
	}

	/**
	 * Register the service provider.
	 *
	 * @return void
	 */
	public function register()
	{
		//
	}

	/**
	 * Get the services provided by the provider.
	 *
	 * @return array
	 */
	public function provides()
	{
		return array();
	}

}


<?php

namespace Neutrino\Assets\Closure;

/**
 * Class JqueryIdHack
 *
 * @package Neutrino\Assets\Closure
 */
class JqueryIdPrecompilation extends Precompilation
{

    /**
     * Speed up jQuery ID Selector
     * Add function :
     * function jQuerySelectorSpeedhack(id) {
     *     return jQuery(document.getElementById(id))
     * }
     *
     * Replace :
     *  jQuery('#someid')   > jQuerySelectorSpeedhack('someid')
     *  $('#someid')        > jQuerySelectorSpeedhack('someid')
     *
     *  $('#someid .test')                      > jQuerySelectorSpeedhack('someid').find('.test')
     *  $('#someid li[data="test"]')            > jQuerySelectorSpeedhack('someid').find('li[data="test"]')
     *  $('#someid .item > span:not(.selected)')  > jQuerySelectorSpeedhack('someid').find('.item span:not(.selected)')
     *
     * @param $content
     *
     * @return string
     */
    public function precompile($content)
    {
        $selector = <<<JS
/**
* @param {string} id
* @return {(*|Window|Document|Element|Array<Element>|string|NodeList)}
*/
function jQuerySelectorSpeedhack(id) {
    return jQuery(document.getElementById(id))
}
JS;

        $content = preg_replace_callback(
            '/(jQuery|\$)\(\s*["\']#([\w\\\.-]+)["\']\s*\)/',
            function ($matches) {
                return "jQuerySelectorSpeedhack('" . str_replace('\\\\', '', $matches[2]) . "')";
            },
            $content
        );

        $content = preg_replace_callback(
            '/(jQuery|\$)\(\s*["\']#([\w\\\.-]+) ([ \w!"#$%&\'\(\)*+.\/:;<=>\?@\[\\\\\]^`\{\|\}~-]+)["\']\s*\)/',
            function ($matches) {
                return "jQuerySelectorSpeedhack('" . str_replace('\\\\', '', $matches[2]) . "').find('{$matches[3]}')";
            },
            $content
        );

        return $selector . $content;
    }
}


<?php

namespace Igniter\Flame\Geolite\Formatter;

use Igniter\Flame\Geolite\Model\AdminLevelCollection;
use Igniter\Flame\Geolite\Model\Location;

class StringFormatter
{
    const STREET_NUMBER = '%n';
    const STREET_NAME = '%S';
    const LOCALITY = '%L';
    const POSTAL_CODE = '%z';
    const SUB_LOCALITY = '%D';
    const ADMIN_LEVEL = '%A';
    const ADMIN_LEVEL_CODE = '%a';
    const COUNTRY_NAME = '%C';
    const COUNTRY_CODE = '%c';
    const TIMEZONE = '%T';

    /**
     * Transform a `Location` instance into a string representation.
     *
     * @param Location $location
     * @param string $format
     *
     * @return string
     */
    public function format(Location $location, string $format): string
    {
        $replace = [
            self::STREET_NUMBER => $location->getStreetNumber(),
            self::STREET_NAME => $location->getStreetName(),
            self::LOCALITY => $location->getLocality(),
            self::POSTAL_CODE => $location->getPostalCode(),
            self::SUB_LOCALITY => $location->getSubLocality(),
            self::COUNTRY_NAME => $location->getCountryName(),
            self::COUNTRY_CODE => $location->getCountryCode(),
            self::TIMEZONE => $location->getTimezone(),
        ];

        for ($level = 1; $level <= AdminLevelCollection::MAX_LEVEL_DEPTH; ++$level) {
            $adminLevel = $location->getAdminLevels()[$level] ?? null;
            $replace[self::ADMIN_LEVEL.$level] = $adminLevel ? $adminLevel->getName() : null;
            $replace[self::ADMIN_LEVEL_CODE.$level] = $adminLevel ? $adminLevel->getCode() : null;
        }

        return strtr($format, $replace);
    }
}


<?php

namespace Neutrino\View\Engines\Volt\Compiler\Functions;

use Neutrino\View\Engines\Volt\Compiler\FunctionExtend;

/**
 * Class RouteFunction
 *
 * @package     Neutrino\View\Engines\Volt\Compiler
 */
class RouteFunction extends FunctionExtend
{

    /**
     * @param string $resolvedArgs
     * @param array  $exprArgs
     *
     * @return string|null
     */
    public function compileFunction($resolvedArgs, $exprArgs)
    {
        if (isset($exprArgs[1]['expr']['left'])) {
            $route = $this->compiler->expression([
                'type' => 360, // type array
                'left' => array_merge([
                    [
                        'name' => 'for',
                        'expr' => $exprArgs[0]['expr']
                    ]
                ], $exprArgs[1]['expr']['left'])
            ]);
        } else {
            $route = "['for' => " . $this->compiler->expression($exprArgs[0]['expr']) . "]";
        }

        $url = "\$this->url->get($route";
        if (isset($exprArgs[2])) {
            $url .= ', ' . $this->compiler->expression($exprArgs[2]['expr']);
        }
        $url .= ')';

        return $url;
    }
}


<?php

namespace Neutrino\Providers;

use Neutrino\Constants\Services;
use Neutrino\Support\Provider;

/**
 * Class Url
 *
 *  @package Neutrino\Foundation\Bootstrap
 */
class Url extends Provider
{
    protected $name = Services::URL;

    protected $shared = true;

    protected $aliases = [\Phalcon\Mvc\Url::class];

    /**
     * The URL component is used to generate all kind of urls in the application
     *
     * @return \Phalcon\Mvc\Url
     */
    protected function register()
    {
        $url = new \Phalcon\Mvc\Url();

        $appConf = $this->getDI()->getShared(Services::CONFIG)->app;

        $url->setBaseUri($appConf->base_uri);
        $url->setStaticBaseUri(isset($appConf->static_base_uri) ? $appConf->static_base_uri : $appConf->base_uri);

        return $url;
    }
}


<?php

namespace Neutrino\Optimizer\Composer;

/**
 * Class Script
 *
 * @package     Neutrino\Optimizer\Composer
 */
class Script
{
    /**
     * @var string
     */
    private $basePath;

    public function __construct($basePath = null)
    {
        $this->basePath = $basePath;
    }

    /**
     * Call the dump-autoload composer command.
     *
     * @param bool $optimize
     */
    public function dumpautoload($optimize = false)
    {
        $this->callComposer('dump-autoload', [
            'optimize' => $optimize
        ]);
    }

    /**
     * Return the base path, where composer will may get called
     *
     * @return string
     */
    public function getBasePath()
    {
        if (is_null($this->basePath)) {
            $this->setBasePath(getcwd());
        }

        return $this->basePath;
    }

    /**
     * Set the base path, where composer will may get called
     *
     * @param string $basePath
     */
    public function setBasePath($basePath)
    {
        $this->basePath = $basePath;
    }

    /**
     * Return the composer command line
     *
     * @return string
     */
    protected function getComposerCmd()
    {
        if (!file_exists($this->getBasePath() . '/composer.phar')) {
            return 'composer';
        }

        $binary = ($phpBinary = getenv('PHP_BINARY')) ? $phpBinary : PHP_BINARY;

        return $binary . ' composer.phar';
    }

    protected function buildComposerCmd($action, $options = [])
    {
        $cmd = trim($this->getComposerCmd() . ' ' . $action);

        foreach ($options as $key => $value) {
            if (is_bool($value)) {
                if ($value) {
                    $cmd .= ' --' . $key;
                }
            } else {
                $cmd .= ' --' . $key . '=' . $value;
            }
        }

        if (DIRECTORY_SEPARATOR === '\\') {
            $cmd = 'cmd /Q /C "' . $cmd . '" > NUL 2> NUL';
        } else {
            $cmd = $cmd . ' 1> /dev/null 2> /dev/null';
        }

        return $cmd;
    }

    /**
     * Call composer
     *
     * @param string $action
     * @param array  $options
     */
    protected function callComposer($action, $options = [])
    {
        $cmd = $this->buildComposerCmd($action, $options);

        $resource = proc_open($cmd, [], $pipes, $this->getBasePath());

        foreach ($pipes as $pipe) {
            fclose($pipe);
        }

        proc_close($resource);
    }
}


<?php

namespace Neutrino\HttpClient\Provider;

use Neutrino\Http\Standards\Method;
use Neutrino\HttpClient\Exception as HttpException;
use Neutrino\HttpClient\Provider\Exception as ProviderException;
use Neutrino\HttpClient\Request;
use Neutrino\HttpClient\Uri;

/**
 * Class StreamContext
 *
 * @package Neutrino\HttpClient\Provider
 */
class StreamContext extends Request
{
    private static $isAvailable;

    public static function checkAvailability()
    {
        if (!isset(self::$isAvailable)) {
            $wrappers = stream_get_wrappers();

            self::$isAvailable = in_array('http', $wrappers) && in_array('https', $wrappers);
        }

        if (!self::$isAvailable) {
            throw new ProviderException(static::class . ' HTTP or HTTPS stream wrappers not registered.');
        }
    }

    /**
     * StreamContext constructor.
     */
    public function __construct()
    {
        self::checkAvailability();

        parent::__construct();
    }

    /**
     * @inheritdoc
     */
    public function setTimeout($timeout)
    {
        return $this->setOption('timeout', $timeout);
    }

    /**
     * @inheritdoc
     */
    public function disableSsl()
    {
        return $this->setOption('ssl', ['verify_peer' => true]);
    }

    /**
     * @param $errno
     * @param $errstr
     *
     * @throws HttpException
     */
    protected function errorHandler($errno, $errstr)
    {
        $this->response->setError($errstr);
        $this->response->setErrorCode($errno);

        throw new HttpException($errstr, $errno);
    }

    /**
     * @return \Neutrino\HttpClient\Response
     */
    protected function makeCall()
    {
        try {
            $context = stream_context_create();

            $this->streamContextOptions($context);

            set_error_handler([$this, 'errorHandler']);

            $content = $this->streamContextExec($context);

            restore_error_handler();

            $this->response->setBody($content);

            return $this->response;
        } finally {
            $context = null;
        }
    }

    /**
     * @param $context
     */
    protected function streamContextOptions($context)
    {
        stream_context_set_option($context, ['http' => array_merge([
            'follow_location' => 1,
            'max_redirects'   => 20,
            'ignore_errors'   => true,
        ], $this->options, ['method' => $this->method])]);
    }

    /**
     * @param $context
     *
     * @return string
     */
    protected function streamContextExec($context)
    {
        if ($this->method !== Method::HEAD) {
            $content = file_get_contents($this->uri->build(), false, $context);

            $this->streamContextParseHeader($http_response_header);

            return ($this->fullResponse ? implode("\r\n", $http_response_header) . "\r\n\r\n" : '') . $content;
        }

        try {
            $handler = fopen($this->uri->build(), 'r', null, $context);

            $this->streamContextParseHeader($http_response_header);

            return '';
        } finally {
            if (isset($handler) && is_resource($handler)) {
                fclose($handler);
            }
        }
    }

    /**
     * @param $headers
     */
    protected function streamContextParseHeader($headers)
    {
        $this->response->getHeader()->parse($headers);

        $this->response->setCode($this->response->getHeader()->code);
    }

    /**
     * Construit les parametres de la requete.
     *
     * @return $this
     */
    protected function buildParams()
    {
            if ($this->isPostMethod()) {
                $params = $this->params;
                if ($this->isJsonRequest()) {
                    return $this
                        ->setOption('content', $params = json_encode($params))
                        ->setHeader('Content-Type', 'application/json')
                        ->setHeader('Content-Length', strlen($params));
                }

                if (!empty($params)) {
                    if (!is_string($params)) {
                        $params = http_build_query($params);
                    }

                    return $this
                        ->setOption('content', $params)
                        ->setHeader('Content-Type', 'application/x-www-form-urlencoded')
                        ->setHeader('Content-Length', strlen($params));
                }

                return $this;
            }

            return $this->buildUrl();
    }

    /**
     * Construit les headers de la requete.
     *
     * @return $this
     */
    protected function buildHeaders()
    {
        $headers = $this->header->build();

        return $this->setOption('header', implode(PHP_EOL, $headers));
    }

    /**
     * Construit le proxy de la requete
     *
     * @return $this
     */
    protected function buildProxy()
    {
        if (isset($this->proxy['host'])) {
            $uri = new Uri([
                'scheme' => 'tcp',
                'host'   => $this->proxy['host'],
                'port'   => isset($this->proxy['port']) ? $this->proxy['port'] : 80,
            ]);

            if (isset($this->proxy['access'])) {
                $uri->user = $this->proxy['access'];
            }

            $this->setOption('proxy', $uri->build());
        }

        return $this;
    }

    /**
     * Construit les cookies de la requete
     *
     * @return $this
     */
    protected function buildCookies()
    {
        if (!empty($this->cookies)) {
            return $this->setHeader('Cookie', $this->getCookies(true));
        }

        return $this;
    }
}


<?php

namespace Neutrino\Database\Cli\Tasks;

/**
 * Class ResetTask
 *
 * @package Neutrino\Database\Cli\Tasks
 */
class ResetTask extends BaseTask
{
    /**
     * @description Rollback all database migrations.
     *
     * @option      -f, --force : Force the operation to run when in production.
     * @option      --path : The path of migrations files to be executed.
     * @option      --step : The number of migrations to be reverted & re-run.
     * @option      --pretend : Dump the SQL queries that would be run.
     */
    public function mainAction()
    {
        if (!$this->confirmToProceed()) {
            return;
        }

        // First, we'll make sure that the migration table actually exists before we
        // start trying to rollback and re-run all of the migrations. If it's not
        // present we'll just bail out with an info message for the developers.
        if (!$this->migrator->storageExist()) {
            $this->notice('Migration table not found.');

            return;
        }

        $this->migrator->reset($this->getMigrationPaths(), [
            'pretend' => $this->getOption('pretend') ?: false
        ]);

        // Once the migrator has run we will grab the note output and send it out to
        // the console screen, since the migrator itself functions without having
        // any instances of the OutputInterface contract passed into the class.
        foreach ($this->migrator->getNotes() as $note) {
            $this->line($note);
        }
    }

}


<?php

namespace Igniter\Flame\Pagic\Concerns;

use Illuminate\Contracts\Events\Dispatcher;

trait HasEvents
{
    /**
     * The event map for the model.
     *
     * Allows for object-based events for native Eloquent events.
     *
     * @var array
     */
    protected $dispatchesEvents = [];

    /**
     * User exposed observable events.
     *
     * These are extra user-defined events observers may subscribe to.
     *
     * @var array
     */
    protected $observables = [];

    /**
     * Register an observer with the Model.
     *
     * @param  object|string $class
     *
     * @return void
     */
    public static function observe($class)
    {
        $instance = new static;

        $className = is_string($class) ? $class : get_class($class);

        // When registering a model observer, we will spin through the possible events
        // and determine if this observer has that method. If it does, we will hook
        // it into the model's event system, making it convenient to watch these.
        foreach ($instance->getObservableEvents() as $event) {
            if (method_exists($class, $event)) {
                static::registerModelEvent($event, $className.'@'.$event);
            }
        }
    }

    /**
     * Get the observable event names.
     *
     * @return array
     */
    public function getObservableEvents()
    {
        return array_merge(
            [
                'retrieved', 'creating', 'created', 'updating',
                'updated', 'deleting', 'deleted', 'saving',
                'saved', 'restoring', 'restored',
            ],
            $this->observables
        );
    }

    /**
     * Set the observable event names.
     *
     * @param  array $observables
     *
     * @return $this
     */
    public function setObservableEvents(array $observables)
    {
        $this->observables = $observables;

        return $this;
    }

    /**
     * Add an observable event name.
     *
     * @param  array|mixed $observables
     *
     * @return void
     */
    public function addObservableEvents($observables)
    {
        $this->observables = array_unique(array_merge(
            $this->observables, is_array($observables) ? $observables : func_get_args()
        ));
    }

    /**
     * Remove an observable event name.
     *
     * @param  array|mixed $observables
     *
     * @return void
     */
    public function removeObservableEvents($observables)
    {
        $this->observables = array_diff(
            $this->observables, is_array($observables) ? $observables : func_get_args()
        );
    }

    /**
     * Register a model event with the dispatcher.
     *
     * @param  string $event
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    protected static function registerModelEvent($event, $callback, $priority = 0)
    {
        if (isset(static::$dispatcher)) {
            $name = static::class;

            static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback, $priority);
        }
    }

    /**
     * Bind some nicer events to this model, in the format of method overrides.
     */
    protected function bootNicerEvents()
    {
        $class = get_called_class();

        if (isset(static::$eventsBooted[$class])) {
            return;
        }

        $radicals = ['creat', 'sav', 'updat', 'delet', 'retriev'];
        $hooks = ['before' => 'ing', 'after' => 'ed'];

        foreach ($radicals as $radical) {
            foreach ($hooks as $hook => $event) {

                $eventMethod = $radical.$event; // saving / saved
                $method = $hook.ucfirst($radical); // beforeSave / afterSave
                if ($radical != 'fetch') $method .= 'e';

                self::$eventMethod(function ($model) use ($method) {
                    $model->fireEvent('model.'.$method);

                    if ($model->methodExists($method))
                        return $model->$method();
                });
            }
        }

        /*
         * Hook to boot events
         */
        static::registerModelEvent('booted', function ($model) {
            $model->fireEvent('model.afterBoot');
            if ($model->methodExists('afterBoot'))
                return $model->afterBoot();
        });

        static::$eventsBooted[$class] = TRUE;
    }

    /**
     * Fire the given event for the model.
     *
     * @param  string $event
     * @param  bool $halt
     *
     * @return mixed
     */
    protected function fireModelEvent($event, $halt = TRUE)
    {
        if (!isset(static::$dispatcher)) {
            return TRUE;
        }

        // First, we will get the proper method to call on the event dispatcher, and then we
        // will attempt to fire a custom, object based event for the given event. If that
        // returns a result we can return that result, or we'll call the string events.
        $method = $halt ? 'until' : 'fire';

        $result = $this->filterModelEventResults(
            $this->fireCustomModelEvent($event, $method)
        );

        if ($result === FALSE) {
            return FALSE;
        }

        return !empty($result) ? $result : static::$dispatcher->{$method}(
            "eloquent.{$event}: ".static::class, $this
        );
    }

    /**
     * Fire a custom model event for the given event.
     *
     * @param  string $event
     * @param  string $method
     *
     * @return mixed|null
     */
    protected function fireCustomModelEvent($event, $method)
    {
        if (!isset($this->dispatchesEvents[$event])) {
            return;
        }

        $result = static::$dispatcher->$method(new $this->dispatchesEvents[$event]($this));

        if (!is_null($result)) {
            return $result;
        }
    }

    /**
     * Filter the model event results.
     *
     * @param  mixed $result
     *
     * @return mixed
     */
    protected function filterModelEventResults($result)
    {
        if (is_array($result)) {
            $result = array_filter($result, function ($response) {
                return !is_null($response);
            });
        }

        return $result;
    }

    /**
     * Create a new native event for handling beforeFetch().
     *
     * @param \Closure|string $callback
     *
     * @return void
     */
    public static function retrieving($callback)
    {
        static::registerModelEvent('retrieving', $callback);
    }

    /**
     * Register a retrieved model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     *
     * @return void
     */
    public static function retrieved($callback)
    {
        static::registerModelEvent('retrieved', $callback);
    }

    /**
     * Register a saving model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function saving($callback, $priority = 0)
    {
        static::registerModelEvent('saving', $callback, $priority);
    }

    /**
     * Register a saved model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function saved($callback, $priority = 0)
    {
        static::registerModelEvent('saved', $callback, $priority);
    }

    /**
     * Register an updating model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function updating($callback, $priority = 0)
    {
        static::registerModelEvent('updating', $callback, $priority);
    }

    /**
     * Register an updated model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function updated($callback, $priority = 0)
    {
        static::registerModelEvent('updated', $callback, $priority);
    }

    /**
     * Register a creating model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function creating($callback, $priority = 0)
    {
        static::registerModelEvent('creating', $callback, $priority);
    }

    /**
     * Register a created model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function created($callback, $priority = 0)
    {
        static::registerModelEvent('created', $callback, $priority);
    }

    /**
     * Register a deleting model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function deleting($callback, $priority = 0)
    {
        static::registerModelEvent('deleting', $callback, $priority);
    }

    /**
     * Register a deleted model event with the dispatcher.
     *
     * @param  \Closure|string $callback
     * @param  int $priority
     *
     * @return void
     */
    public static function deleted($callback, $priority = 0)
    {
        static::registerModelEvent('deleted', $callback, $priority);
    }

    /**
     * Remove all of the event listeners for the model.
     *
     * @return void
     */
    public static function flushEventListeners()
    {
        if (!isset(static::$dispatcher)) {
            return;
        }

        $instance = new static;

        foreach ($instance->getObservableEvents() as $event) {
            static::$dispatcher->forget("eloquent.{$event}: ".static::class);
        }
    }

    /**
     * Get the event dispatcher instance.
     *
     * @return \Illuminate\Contracts\Events\Dispatcher
     */
    public static function getEventDispatcher()
    {
        return static::$dispatcher;
    }

    /**
     * Set the event dispatcher instance.
     *
     * @param  \Illuminate\Contracts\Events\Dispatcher $dispatcher
     *
     * @return void
     */
    public static function setEventDispatcher(Dispatcher $dispatcher)
    {
        static::$dispatcher = $dispatcher;
    }

    /**
     * Unset the event dispatcher for models.
     *
     * @return void
     */
    public static function unsetEventDispatcher()
    {
        static::$dispatcher = null;
    }
}


<?php

namespace Neutrino\Cli\Output;

use Neutrino\Constants\Services;

/**
 * Class ConsoleOutput
 *
 * @package Neutrino\Cli\Output
 */
class Writer
{
    /**
     * @var bool
     */
    protected $quiet;

    /**
     * ConsoleOutput constructor.
     *
     * @param bool $quiet
     */
    public function __construct($quiet = false)
    {
        $this->quiet = $quiet;

        if ($this->quiet) {
            ob_start();
        }
    }

    /**
     * Write a string.
     *
     * @param string $str
     */
    public function line($str)
    {
        $this->write($str, true);
    }

    /**
     * Write a string as information output.
     *
     * @param string $str
     */
    public function info($str)
    {
        $this->write(Decorate::info($str), true);
    }

    /**
     * Write a string as notice output.
     *
     * @param string $str
     */
    public function notice($str)
    {
        $this->write(Decorate::notice($str), true);
    }

    /**
     * Write a string as warning output.
     *
     * @param string $str
     */
    public function warn($str)
    {
        $this->write(Decorate::warn($str), true);
    }

    /**
     * Write a string as error output.
     *
     * @param string $str
     */
    public function error($str)
    {
        $this->write(Decorate::error($str), true);
    }

    /**
     * Write a string as question output.
     *
     * @param string $str
     */
    public function question($str)
    {
        $this->write(Decorate::question($str), true);
    }

    /**
     * {@inheritdoc}
     */
    public function write($message, $newline)
    {
        if ($this->quiet) {
            return;
        }

        if (false === @fwrite(STDOUT, $message) || ($newline && (false === @fwrite(STDOUT, PHP_EOL)))) {
            // should never happen
            throw new \RuntimeException('Unable to write output.');
        }

        fflush(STDOUT);
    }

    public function clean()
    {
        if ($this->quiet) {
            ob_end_clean();
        }
    }
}


<?php

namespace Igniter\Flame\Location;

use Closure;
use Igniter\Flame\Geolite\Contracts\CoordinatesInterface;
use Igniter\Flame\Location\Contracts;
use Igniter\Flame\Traits\EventEmitter;
use Session;

/**
 * Location Manager Class
 * @package        Igniter\Flame\Location\Manager.php
 */
abstract class Manager
{
    use EventEmitter;

    protected $sessionKey = 'local_info';

    /**
     * @var \Igniter\Flame\Location\Models\AbstractLocation
     */
    protected $model;

    protected $defaultLocation;

    protected $locationModel;

    protected $loaded;

    protected static $schedulesCache;

    /**
     * The route parameter resolver callback.
     *
     * @var \Closure
     */
    protected static $locationSlugResolver;

    /**
     * Helper to get the current location instance.
     *
     * @return \Igniter\Flame\Location\Manager
     */
    public function instance()
    {
        return $this;
    }

    /**
     * Resolve the location slug from route parameter.
     *
     * @return string
     */
    public function resolveLocationSlug()
    {
        if (isset(static::$locationSlugResolver)) {
            return call_user_func(static::$locationSlugResolver);
        }
    }

    /**
     * Set the location route parameter resolver callback.
     *
     * @param  \Closure $resolver
     * @return void
     */
    public function locationSlugResolver(Closure $resolver)
    {
        static::$locationSlugResolver = $resolver;
    }

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

    /**
     * @param string $defaultLocation
     */
    public function setDefaultLocation($defaultLocation)
    {
        $this->defaultLocation = $defaultLocation;
    }

    public function getDefault()
    {
        return $this->getById($this->getDefaultLocation());
    }

    public function current()
    {
        if (!is_null($this->model))
            return $this->model;

        $model = null;
        if ($slug = $this->resolveLocationSlug())
            $model = $this->getBySlug($slug);

        if (!$model) {
            $id = $this->getSession('id');
            if (!$id OR !$model = $this->getById($id))
                $model = $this->getById($this->defaultLocation);
        }

        if ($model)
            $this->setCurrent($model);

        return $this->model;
    }

    /**
     * @param \Igniter\Flame\Location\Contracts\LocationInterface $locationModel
     */
    public function setCurrent(Contracts\LocationInterface $locationModel)
    {
        $this->setModel($locationModel);

        $this->putSession('id', $locationModel->getKey());

        $this->fireSystemEvent('location.current.updated', [$locationModel]);
    }

    public function getModel()
    {
        if (is_null($this->model)) {
            $this->current();
        }

        return $this->model;
    }

    public function setModel(Contracts\LocationInterface $model)
    {
        $this->model = $model;

        return $this;
    }

    public function setModelById($id)
    {
        $this->model = $this->getById($id);

        return $this;
    }

    public function setModelClass($className)
    {
        $this->locationModel = $className;
    }

    /**
     * Creates a new instance of the location model
     * @return \Igniter\Flame\Location\Models\AbstractLocation
     */
    public function createLocationModel()
    {
        $class = '\\'.ltrim($this->locationModel, '\\');
        $model = new $class();

        return $model;
    }

    /**
     * Prepares a query derived from the location model.
     */
    protected function createLocationModelQuery()
    {
        $model = $this->createLocationModel();
        $query = $model->newQuery();
        $this->extendLocationQuery($query);

        return $query;
    }

    /**
     * Extend the query used for finding the location.
     *
     * @param \Igniter\Flame\Database\Builder $query
     *
     * @return void
     */
    public function extendLocationQuery($query)
    {
    }

    /**
     * Retrieve a location by their unique identifier.
     *
     * @param  mixed $identifier
     *
     * @return \Igniter\Flame\Location\Models\AbstractLocation|null
     */
    public function getById($identifier)
    {
        $query = $this->createLocationModelQuery();
        $location = $query->find($identifier);

        return $location ?: null;
    }

    /**
     * Retrieve a location by their unique slug.
     *
     * @param  string $slug
     *
     * @return \Igniter\Flame\Location\Contracts\LocationInterface|null
     */
    public function getBySlug($slug)
    {
        $model = $this->createLocationModel();
        $query = $this->createLocationModelQuery();
        $location = $query->where($model->getSlugKeyName(), $slug)->first();

        return $location ?: null;
    }

    public function searchByCoordinates(CoordinatesInterface $coordinates, $limit = 20)
    {
        $query = $this->createLocationModelQuery();
        $query->select('*')->selectDistance(
            $coordinates->getLatitude(),
            $coordinates->getLongitude()
        );

        return $query->isEnabled()->limit($limit)->get();
    }

    public function workingSchedule($type, $days = null)
    {
        $cacheKey = sprintf('%s.%s', $this->getModel()->getKey(), $type);

        if (isset(self::$schedulesCache[$cacheKey]))
            return self::$schedulesCache[$cacheKey];

        $schedule = $this->getModel()->newWorkingSchedule($type, $days);

        self::$schedulesCache[$cacheKey] = $schedule;

        return $schedule;
    }

    //
    // Session
    //

    /**
     * Retrieves key/value pair from session data.
     *
     * @param string $key Unique key for the data store.
     * @param string $default A default value to use when value is not found.
     *
     * @return mixed
     */
    public function getSession($key = null, $default = null)
    {
        $sessionData = Session::get($this->sessionKey);

        return is_null($key) ? $sessionData : array_get($sessionData, $key, $default);
    }

    public function putSession($key, $value)
    {
        $sessionData = $this->getSession();
        $sessionData[$key] = $value;

        Session::put($this->sessionKey, $sessionData);
    }

    public function forgetSession($key = null)
    {
        if (is_null($key)) {
            Session::forget($this->sessionKey);

            return;
        }

        $sessionData = $this->getSession();
        unset($sessionData[$key]);

        Session::put($this->sessionKey, $sessionData);
    }
}


<?php

namespace TypiCMS\Modules\Blocks\Http\Controllers;

use TypiCMS\Modules\Blocks\Http\Requests\FormRequest;
use TypiCMS\Modules\Blocks\Models\Block;
use TypiCMS\Modules\Blocks\Repositories\EloquentBlock;
use TypiCMS\Modules\Core\Http\Controllers\BaseAdminController;

class AdminController extends BaseAdminController
{
    public function __construct(EloquentBlock $block)
    {
        parent::__construct($block);
    }

    /**
     * List models.
     *
     * @return \Illuminate\View\View
     */
    public function index()
    {
        return view('blocks::admin.index');
    }

    /**
     * Create form for a new resource.
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
        $model = $this->repository->createModel();

        return view('blocks::admin.create')
            ->with(compact('model'));
    }

    /**
     * Edit form for the specified resource.
     *
     * @param \TypiCMS\Modules\Blocks\Models\Block $block
     *
     * @return \Illuminate\View\View
     */
    public function edit(Block $block)
    {
        return view('blocks::admin.edit')
            ->with(['model' => $block]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param \TypiCMS\Modules\Blocks\Http\Requests\FormRequest $request
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(FormRequest $request)
    {
        $block = $this->repository->create($request->all());

        return $this->redirect($request, $block);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param \TypiCMS\Modules\Blocks\Models\Block              $block
     * @param \TypiCMS\Modules\Blocks\Http\Requests\FormRequest $request
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(Block $block, FormRequest $request)
    {
        $this->repository->update($request->id, $request->all());

        return $this->redirect($request, $block);
    }
}


<?php

namespace Neutrino\Cli\Question;

/**
 * Class ChoiceQuestion
 *
 * @package Neutrino\Cli\Question
 */
class ChoiceQuestion extends Question
{
    /** @var array */
    private $choices;

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

    /**
     * Question constructor.
     *
     * @param string      $question
     * @param array       $choices
     * @param null|string $default
     * @param null|int    $maxAttempts
     */
    public function __construct($question, array $choices, $default = null, $maxAttempts = null)
    {
        parent::__construct($question, $default);

        $this
            ->setChoices($choices)
            ->setMaxAttempts($maxAttempts);
    }

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

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

    /**
     * @param array $choices
     *
     * @return $this
     */
    public function setChoices($choices)
    {
        $this->choices = $choices;

        return $this;
    }

    /**
     * @param int $maxAttempts
     *
     * @return $this
     */
    public function setMaxAttempts($maxAttempts)
    {
        if (null !== $maxAttempts && $maxAttempts < 1) {
            throw new \InvalidArgumentException('Maximum number of attempts must be a positive value.');
        }

        $this->maxAttempts = $maxAttempts;

        return $this;
    }
}


<?php

namespace Igniter\Flame\Flash;

class FlashBag
{
    protected $sessionKey = '_ti_flash';

    /**
     * The session store.
     * @var FlashStore
     */
    protected $store;

    /**
     * The messages collection.
     *
     * @var \Illuminate\Support\Collection
     */
    public $messages;

    /**
     * Create a new FlashNotifier instance.
     *
     * @param FlashStore $store
     */
    public function __construct(FlashStore $store)
    {
        $this->store = $store;
    }

    public function setSessionKey($key)
    {
        $this->sessionKey = $key;
    }

    public function messages()
    {
        if ($this->messages)
            return $this->messages;

        return $this->messages = $this->store->get($this->sessionKey, collect());
    }

    /**
     * Gets all the flash messages
     *
     * @return array
     */
    public function all()
    {
        $messages = $this->messages();

        $this->clear();

        return $messages;
    }

    public function set($level = null, $message = null)
    {
        return $this->message($message, $level);
    }

    /**
     * Flash a generic message.
     *
     * @param  string|null $message
     *
     * @return $this
     */
    public function alert($message)
    {
        return $this->message($message);
    }

    /**
     * Flash an information message.
     *
     * @param  string|null $message
     *
     * @return $this
     */
    public function info($message = null)
    {
        return $this->message($message, 'info');
    }

    /**
     * Flash a success message.
     *
     * @param  string|null $message
     *
     * @return $this
     */
    public function success($message = null)
    {
        return $this->message($message, 'success');
    }

    /**
     * Flash an error message.
     *
     * @param  string|null $message
     *
     * @return $this
     */
    public function error($message = null)
    {
        return $this->message($message, 'danger');
    }

    /**
     * Flash an error message.
     *
     * @param  string|null $message
     *
     * @return $this
     */
    public function danger($message = null)
    {
        return $this->error($message);
    }

    /**
     * Flash a warning message.
     *
     * @param  string|null $message
     *
     * @return $this
     */
    public function warning($message = null)
    {
        return $this->message($message, 'warning');
    }

    /**
     * Flash a general message.
     *
     * @param  string|null $message
     * @param  string|null $level
     *
     * @return $this
     */
    public function message($message = null, $level = null)
    {
        // If no message was provided, we should update
        // the most recently added message.
        if (!$message) {
            return $this->updateLastMessage(compact('level'));
        }

        if (!$message instanceof Message) {
            $message = new Message(compact('message', 'level'));
        }

        $this->messages()->push($message);

        return $this->flash();
    }

    /**
     * Modify the most recently added message.
     *
     * @param  array $overrides
     *
     * @return $this
     */
    protected function updateLastMessage($overrides = [])
    {
        $this->messages()->last()->update($overrides);

        return $this;
    }

    /**
     * Flash an overlay modal.
     *
     * @param  string|null $message
     * @param  string $title
     *
     * @return $this
     */
    public function overlay($message = null, $title = '')
    {
        if (!$message) {
            return $this->updateLastMessage(['title' => $title, 'overlay' => TRUE]);
        }

        return $this->message(
            new OverlayMessage(compact('title', 'message'))
        );
    }

    /**
     * Add a "now" flash to the store.
     * @return $this
     */
    public function now()
    {
        return $this->updateLastMessage(['now' => TRUE]);
    }

    /**
     * Add an "important" flash to the store.
     * @return $this
     */
    public function important()
    {
        return $this->updateLastMessage(['important' => TRUE]);
    }

    /**
     * Clear all registered messages.
     * @return $this
     */
    public function clear()
    {
        $this->store->forget($this->sessionKey);

        $this->messages = collect();

        return $this;
    }

    /**
     * Flash all messages to the store.
     */
    protected function flash()
    {
        $this->store->flash($this->sessionKey, $this->messages());

        return $this;
    }
}


<?php

namespace Neutrino\Cli;

/**
 * Class Router
 *
 *  @package Neutrino\Cli
 */
class Router extends \Phalcon\Cli\Router
{
    /**
     * Adds a route to the router, with task as class.
     *
     * ex : $router->addTask('some', SomeTask::class);
     *
     * @param string      $command
     * @param string      $class
     * @param string|null $action
     * @param array       $params
     *
     * @return \Phalcon\Cli\Router\Route|\Phalcon\Cli\Router\RouteInterface
     */
    public function addTask($command, $class, $action = null, array $params = [])
    {
        $params['task'] = $class;

        $params['action'] = $action;

        preg_match_all('/\{([\w_]+)\}/', $command, $matches);

        foreach ($matches[0] as $k => $match) {
            $command = str_replace($match, '([[:word:]]+)', $command);

            $params[substr($match, 1, -1)] = $k + 1;
        }

        return $this->add($command, $params);
    }
}


<?php

namespace Neutrino\Database\Providers;

use Neutrino\Constants\Services;
use Neutrino\Database\Migrations\MigrationCreator;
use Neutrino\Database\Migrations\Migrator;
use Neutrino\Database\Migrations\Prefix\PrefixInterface;
use Neutrino\Database\Migrations\Storage\StorageInterface;
use Neutrino\Interfaces\Providable;
use Phalcon\Di;
use Phalcon\DiInterface;

/**
 * Class MigrationProvider
 *
 * @package Neutrino\Database\Providers
 */
class MigrationsServicesProvider implements Providable
{
    /**
     * Called upon bootstrap the application.
     * Adds to container services desired services.
     *
     * @return void
     */
    public function registering()
    {
        $di = Di::getDefault();

        $this->registerPrefix($di);
        $this->registerStorage($di);
        $this->registerMigrator($di);
        $this->registerMigrationCreator($di);
    }

    /**
     * Register Migrations\Prefix
     *
     * @param \Phalcon\DiInterface $di
     */
    protected function registerPrefix(DiInterface $di)
    {
        $di->set(PrefixInterface::class, function () {
            $config = $this->get(Services::CONFIG);

            return new $config->migrations->prefix;
        }, true);
    }

    /**
     * Register Migrations\Storage
     *
     * @param \Phalcon\DiInterface $di
     */
    protected function registerStorage(DiInterface $di)
    {
        $di->set(StorageInterface::class, function () {
            $config = $this->get(Services::CONFIG);

            return new $config->migrations->storage;
        }, true);
    }

    /**
     * Register Migrations\Migrator
     *
     * @param \Phalcon\DiInterface $di
     */
    protected function registerMigrator(DiInterface $di)
    {
        $di->set(Migrator::class, [
            'className' => Migrator::class,
            'arguments' => [
                [
                    'type' => 'service',
                    'name' => StorageInterface::class,
                ],
                [
                    'type' => 'service',
                    'name' => PrefixInterface::class,
                ]
            ]
        ]);
    }

    /**
     * Register Migrations\MigrationCreator
     *
     * @param \Phalcon\DiInterface $di
     */
    protected function registerMigrationCreator(DiInterface $di)
    {
        $di->set(MigrationCreator::class, [
            'className' => MigrationCreator::class,
            'arguments' => [
                [
                    'type' => 'service',
                    'name' => PrefixInterface::class,
                ]
            ]
        ]);
    }
}


<?php

namespace Igniter\Flame\Foundation\Providers;

use File;
use Illuminate\Support\ServiceProvider;

abstract class AppServiceProvider extends ServiceProvider
{
    /**
     * The application instance.
     *
     * @var \Igniter\Flame\Foundation\Application
     */
    protected $app;

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

    /**
     * Boot the service provider.
     * @return void
     */
    public function boot()
    {
        if ($module = $this->getModule(func_get_args())) {
            // Register paths for: config, translator, view
            $modulePath = app_path($module);
            $this->loadTranslationsFrom($modulePath.DIRECTORY_SEPARATOR.'language', $module);
            $this->loadViewsFrom($modulePath.DIRECTORY_SEPARATOR.'views', $module);
        }
    }

    /**
     * Register the service provider.
     * @return void
     */
    public function register()
    {
        if ($module = $this->getModule(func_get_args())) {
            $routesFile = app_path($module.'/routes.php');
            if (File::isFile($routesFile))
                require $routesFile;
        }
    }

    public function getModule($args)
    {
        $module = (isset($args[0]) and is_string($args[0])) ? $args[0] : null;

        return $module;
    }

    /**
     * Registers a new console (artisan) command
     *
     * @param string $key The command name
     * @param string $class The command class
     *
     * @return void
     */
    public function registerConsoleCommand($key, $class)
    {
        $key = 'command.'.$key;
        $this->app->singleton($key, function () use ($class) {
            return new $class;
        });

        $this->commands($key);
    }

    /**
     * Get the services provided by the provider.
     * @return array
     */
    public function provides()
    {
        return [];
    }
}


<?php
/*
 * Copyright 2008 Sven Sanzenbacher
 *
 * This file is part of the naucon package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Naucon\HtmlBuilder;

/**
 * Html Select Class
 *
 * @package    HtmlBuilder
 * @author     Sven Sanzenbacher
 */
class HtmlSelect extends HtmlElementUniversalAbstract
{
    /**
     * @access      protected
     * @var         string                  html element tag
     */
    protected $tag = 'select';

    /**
     * Constructor
     *
     * @param       string      $name       select attribute name
     * @param       bool        $multiple   select attribute multiple
     */
    public function __construct($name, $multiple = false)
    {
        $this->setName($name);
        $this->setMultiple($multiple);
    }

    /**
     * @return      string                  html element attribute name
     */
    public function getName()
    {
        return $this->getAttribute('name');
    }

    /**
     * @param       string      $name       html element attribute name
     * @return      HtmlSelect
     */
    public function setName($name)
    {
        $this->setAttribute('name', $name);
        return $this;
    }

    /**
     * @return      bool                    html element attribute multiple
     */
    public function getMultiple()
    {
        if ($this->getAttribute('multiple') == 'multiple') {
            return true;
        }
        return false;
    }

    /**
     * @param       bool        $multiple   html element attribute multiple
     * @return      HtmlSelect
     */
    public function setMultiple($multiple)
    {
        if ($multiple) {
            $this->setAttribute('multiple', 'multiple');
        } else {
            $this->setAttribute('multiple', null);
        }
        return $this;
    }

    /**
     * @return      bool                    html element attribute autocomplete
     */
    public function getAutoComplete()
    {
        switch ($this->getAttribute('autocomplete')) {
            case null:
            case 'on':
                return true;
            default:
            case 'off':
                return false;
        }
    }

    /**
     * @param       bool    $autocomplete   html element attribute autocomplete
     * @return      HtmlSelect
     */
    public function setAutoComplete($autocomplete = true)
    {
        if (is_null($autocomplete)) {
            $this->setAttribute('autocomplete', null);
        } elseif ($autocomplete) {
            $this->setAttribute('autocomplete', 'on');
        } else {
            $this->setAttribute('autocomplete', 'off');
        }
        return $this;
    }

    /**
     * @return      int                     html element attribute tabindex
     */
    public function getTabIndex()
    {
        return $this->getAttribute('tabindex');
    }

    /**
     * @param       int     $tabIndex       html element attribute tabindex
     * @return      HtmlSelect
     */
    public function setTabIndex($tabIndex)
    {
        $this->setAttribute('tabindex', $tabIndex);
        return $this;
    }

    /**
     * @return      bool                    html element attribute disabled
     */
    public function getDisabled()
    {
        if ($this->getAttribute('disabled') == 'disabled') {
            return true;
        }
        return false;
    }

    /**
     * @param       bool        $disabled   html element attribute disabled
     * @return      HtmlSelect
     */
    public function setDisabled($disabled)
    {
        if ($disabled) {
            $this->setAttribute('disabled', 'disabled');
        } else {
            $this->setAttribute('disabled', null);
        }
        return $this;
    }

    /**
     * @return      string                  html element attribute onblur
     */
    public function getOnBlur()
    {
        return $this->getAttribute('onblur');
    }

    /**
     * @param       string      $event      html element attribute onblur
     * @return      HtmlSelect
     */
    public function setOnBlur($event)
    {
        $this->setAttribute('onblur', $event);
        return $this;
    }

    /**
     * @return      string                  html element attribute onchange
     */
    public function getOnChange()
    {
        return $this->getAttribute('onchange');
    }

    /**
     * @param       string      $event      html element attribute onchange
     * @return      HtmlSelect
     */
    public function setOnChange($event)
    {
        $this->setAttribute('onchange', $event);
        return $this;
    }

    /**
     * @return      string                  html element attribute onfocus
     */
    public function getOnFocus()
    {
        return $this->getAttribute('onfocus');
    }

    /**
     * @param       string      $event      html element attribute onfocus
     * @return      HtmlSelect
     */
    public function setOnFocus($event)
    {
        $this->setAttribute('onfocus', $event);
        return $this;
    }

    /**
     * add select option
     *
     * @param       string      $content    select option content
     * @param       string      $value      select option attribute value
     * @param       bool        $selected   select option attribute selected
     * @return      HtmlSelect
     */
    public function addOption($content, $value = null, $selected = false)
    {
        $this->addChildElement(new HtmlSelectOption($content, $value, $selected));
        return $this;
    }
}


<?php

namespace Igniter\Flame\Database;

use Illuminate\Database\Eloquent\Builder as BuilderBase;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;

/**
 * TastyIgniter Database Manager Class
 * @package        Igniter\Flame\Database\Manager.php
 */
class Builder extends BuilderBase
{
    /**
     * Get an array with the values of a given column.
     *
     * @param  string $column
     * @param  string|null $key
     *
     * @return \Illuminate\Support\Collection
     */
    public function lists($column, $key = null)
    {
        return $this->pluck($column, $key);
    }

    /**
     * Get an array with the values of a given column.
     *
     * @param  string $column
     * @param  string|null $key
     *
     * @return \Illuminate\Support\Collection
     */
    public function dropdown($column, $key = null)
    {
        $key = !is_null($key) ? $key : $this->model->getKeyName();

        return $this->lists($column, $key);
    }

    /**
     * Perform a search on this query for term found in columns.
     *
     * @param  string $term Search query
     * @param  array $columns Table columns to search
     * @param  string $mode Search mode: all, any, exact.
     *
     * @return self
     */
    public function search($term, $columns = [], $mode = 'all')
    {
        return $this->searchInternal($term, $columns, $mode, 'and');
    }

    /**
     * Add an "or search where" clause to the query.
     *
     * @param  string $term Search query
     * @param  array $columns Table columns to search
     * @param  string $mode Search mode: all, any, exact.
     *
     * @return self
     */
    public function orSearch($term, $columns = [], $mode = 'all')
    {
        return $this->searchInternal($term, $columns, $mode, 'or');
    }

    /**
     * Convenient method for where like clause
     *
     * @param  string $column
     * @param $value
     * @param string $side
     * @param string $boolean
     *
     * @return \Igniter\Flame\Database\Builder
     */
    public function like($column, $value, $side = 'both', $boolean = 'and')
    {
        return $this->likeInternal($column, $value, $side, $boolean);
    }

    /**
     * Convenient method for or where like clause
     *
     * @param  string $column
     * @param $value
     * @param string $side
     *
     * @return self
     */
    public function orLike($column, $value, $side = 'both')
    {
        return $this->likeInternal($column, $value, $side, 'or');
    }

    /**
     * Internal method to apply a search constraint to the query.
     * Mode can be any of these options:
     * - all: result must contain all words
     * - any: result can contain any word
     * - exact: result must contain the exact phrase
     *
     * @param $term
     * @param array $columns
     * @param $mode
     * @param $boolean
     *
     * @return $this
     */
    protected function searchInternal($term, $columns = [], $mode, $boolean)
    {
        if (!is_array($columns))
            $columns = [$columns];

        if (!$mode)
            $mode = 'all';

        if ($mode === 'exact') {
            $this->where(function ($query) use ($columns, $term) {
                foreach ($columns as $field) {
                    if (!strlen($term)) continue;
                    $query->orLike($field, $term, 'both');
                }
            }, null, null, $boolean);
        }
        else {
            $words = explode(' ', $term);
            $wordBoolean = $mode === 'any' ? 'or' : 'and';

            $this->where(function ($query) use ($columns, $words, $wordBoolean) {
                foreach ($columns as $field) {
                    $query->orWhere(function ($query) use ($field, $words, $wordBoolean) {
                        foreach ($words as $word) {
                            if (!strlen($word)) continue;
                            $query->like($field, $word, 'both', $wordBoolean);
                        }
                    });
                }
            }, null, null, $boolean);
        }

        return $this;
    }

    protected function likeInternal($column, $value, $side = null, $boolean = 'and')
    {
        $column = $this->toBase()->raw(sprintf("lower(%s)", $column));
        $value = trim(mb_strtolower($value));

        if ($side === 'none') {
            $value = $value;
        }
        elseif ($side === 'before') {
            $value = "%{$value}";
        }
        elseif ($side === 'after') {
            $value = "{$value}%";
        }
        else {
            $value = "%{$value}%";
        }

        return $this->where($column, 'like', $value, $boolean);
    }

    /**
     * Get an array with the values of dates.
     *
     * @param  string $column
     * @param string $keyFormat
     * @param string $valueFormat
     *
     * @return array
     */
    public function pluckDates($column, $keyFormat = '%Y-%m', $valueFormat = '%F %Y')
    {
        $dates = [];

        $collection = $this->selectRaw("{$column}, MONTH({$column}) as month, YEAR({$column}) as year")
                           ->groupBy([$column, 'month', 'year'])->get();

        if ($collection) {
            foreach ($collection as $date) {
                $key = mdate($keyFormat, strtotime($date[$column]));
                $value = mdate($valueFormat, strtotime($date[$column]));
                $dates[$key] = $value;
            }
        }

        return $dates;
    }

    /**
     * Paginate the given query.
     *
     * @param  int $perPage
     * @param  array $columns
     * @param  string $pageName
     * @param  int|null $page
     *
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     * @throws \InvalidArgumentException
     */
    public function paginate($perPage = null, $page = null, $columns = ['*'], $pageName = 'page')
    {
        if (is_array($page)) {
            $columns = $page;
            $page = null;
        }

        $page = $page ?: Paginator::resolveCurrentPage($pageName);

        $perPage = $perPage ?: $this->model->getPerPage();

        $results = ($total = $this->toBase()->getCountForPagination())
            ? $this->forPage($page, $perPage)->get($columns)
            : $this->model->newCollection();

        return new LengthAwarePaginator($results, $total, $perPage, $page, [
            'path'     => Paginator::resolveCurrentPath(),
            'pageName' => $pageName,
        ]);
    }

    /**
     * Paginate the given query into a simple paginator.
     *
     * @param  int $perPage
     * @param  array $columns
     * @param  string $pageName
     * @param  int|null $page
     *
     * @return \Illuminate\Contracts\Pagination\Paginator
     */
    public function simplePaginate($perPage = null, $page = null, $columns = ['*'], $pageName = 'page')
    {
        if (is_array($page)) {
            $columns = $page;
            $page = null;
        }

        $page = $page ?: Paginator::resolveCurrentPage($pageName);

        $perPage = $perPage ?: $this->model->getPerPage();

        // Next we will set the limit and offset for this query so that when we get the
        // results we get the proper section of results. Then, we'll create the full
        // paginator instances for these results with the given page and per page.
        $this->skip(($page - 1) * $perPage)->take($perPage + 1);

        return new Paginator($this->get($columns), $perPage, $page, [
            'path' => Paginator::resolveCurrentPath(),
        ]);
    }

    /**
     * Find a model by its primary key or return fresh model instance
     * with filled attributes to use with forms.
     *
     * @param  mixed $id
     * @param  array $columns
     *
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function findOrNew($id, $columns = ['*'])
    {
        if (!is_null($model = $this->find($id, $columns))) {
            return $model;
        }

        $attributes = $this->toBase()->getConnection()->getSchemaBuilder()->getColumnListing($this->model->getTable());

        return $this->model->newInstance(array_fill_keys(array_values($attributes), null))->setConnection(
            $this->toBase()->getConnection()->getName()
        );
    }
}


<?php

namespace Neutrino\Auth;

use Neutrino\Constants\Services;
use Neutrino\Foundation\Auth\User;
use Neutrino\Interfaces\Auth\Authenticable as AuthenticableInterface;
use Neutrino\Support\Arr;
use Neutrino\Support\Str;
use Phalcon\Di\Injectable;

/**
 * Class Auth
 *
 *  @package Neutrino\Auth
 */
class Manager extends Injectable
{
    /**
     * User AuthenticableInterface
     *
     * @var \Neutrino\Foundation\Auth\User
     */
    protected $user;

    /**
     * Indicates if the logout method has been called.
     *
     * @var bool
     */
    protected $loggedOut = false;

    /**
     * Model Class used. Defined in config->auth->model
     *
     * @var string
     */
    protected $model;

    /**
     * Return the user authenticated
     *
     * @return \Neutrino\Foundation\Auth\User|null
     */
    public function user()
    {
        if ($this->loggedOut) {
            return null;
        }

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

        $user = null;

        if (!is_null($id = $this->retrieveIdentifier())) {
            $user = $this->retrieveUserByIdentifier($id);
        }

        if (empty($user)) {
            /** @var \Phalcon\Http\Response\Cookies $cookies */
            $cookies = $this->{Services::COOKIES};
            if ($cookies->has('remember_me')) {
                $recaller = $cookies->get('remember_me')->getValue();

                list($identifier, $token) = explode('|', $recaller);

                if ($identifier && $token) {
                    $user = $this->retrieveUserByToken($identifier, $token);

                    if ($user) {
                        $this->{Services::SESSION}->set($this->sessionKey(), $user->getAuthIdentifier());
                    }
                }
            }
        }

        $this->user = $user;

        return $this->user;
    }

    /**
     * If user is NOT logged into the system return true else false;
     *
     * @return bool Guest is true, Loggedin is false
     */
    public function guest()
    {
        return !$this->check();
    }

    /**
     * authenticate user
     *
     * @param array $credentials
     * @param bool  $remember
     *
     * @return \Neutrino\Foundation\Auth\User
     */
    public function attempt(array $credentials = [], $remember = false)
    {
        $user = $this->retrieveUserByCredentials($credentials);

        if (!empty($user)) {
            $this->login($user, $remember);

            return $user;
        }

        return null;
    }

    /**
     * Determine if user is authenticated
     *
     * @return bool
     */
    public function check()
    {
        return !is_null($this->user());
    }

    /**
     * Log out of the application
     */
    public function logout()
    {
        $this->user      = null;
        $this->loggedOut = true;

        $this->{Services::SESSION}->destroy();
        $this->{Services::COOKIES}->delete('remember_me');
    }

    /**
     * Get currently logged user's id
     *
     * @return mixed|null
     */
    public function retrieveIdentifier()
    {
        return $this->{Services::SESSION}->get($this->sessionKey());
    }

    /**
     * Log a user into the application
     *
     * @param User $user
     * @param bool $remember
     *
     * @return bool
     */
    public function login(User $user, $remember = false)
    {
        if (!$user) {
            return false;
        }

        $this->regenerateSessionId();

        $this->{Services::SESSION}->set($this->sessionKey(), $user->getAuthIdentifier());

        if ($remember) {
            $rememberToken = Str::random(60);

            /** @var \Phalcon\Http\Response\Cookies|\Phalcon\Http\Response\CookiesInterface $cookies */
            $cookies = $this->{Services::COOKIES};
            $cookies->set('remember_me', $user->getAuthIdentifier() . '|' . $rememberToken, time() + (100 * 365 * 24 * 60 * 60));

            $user->setRememberToken($rememberToken);

            $user->save();
        }

        $this->user = $user;

        return true;
    }

    /**
     * Log a user into the application using id
     *
     * @param int $id
     *
     * @return AuthenticableInterface|\Phalcon\Mvc\Model
     */
    public function loginUsingId($id)
    {
        $this->login($user = $this->retrieveUserById($id));

        return $user;
    }

    /**
     * Retrieve a user by his id
     *
     * @param int $id
     *
     * @return User
     */
    protected function retrieveUserById($id)
    {
        $class = $this->modelClass();

        return $class::findFirst($id);
    }

    /**
     * Retrieve a user by his identifier
     *
     * @param int $id
     *
     * @return User
     */
    protected function retrieveUserByIdentifier($id)
    {
        $class = $this->modelClass();

        return $class::findFirst([
            'conditions' => $class::getAuthIdentifierName() . ' = :auth_identifier:',
            'bind'      => [
                'auth_identifier' => $id
            ]
        ]);
    }

    /**
     * Retrieve a user by his identifier & remember token.
     *
     * @param string $identifier
     * @param string $token
     *
     * @return AuthenticableInterface|\Phalcon\Mvc\Model
     */
    protected function retrieveUserByToken($identifier, $token)
    {
        $user = $this->retrieveUserByIdentifier($identifier);

        if (!empty($user) && $user->getRememberToken() === $token) {
            return $user;
        }

        return null;
    }

    /**
     * Retrieve a user by credentials
     *
     * @param array $credentials
     *
     * @return \Neutrino\Foundation\Auth\User
     */
    protected function retrieveUserByCredentials(array $credentials)
    {
        $class = $this->modelClass();

        $identifier = $class::getAuthIdentifierName();
        $password   = $class::getAuthPasswordName();

        $user = $this->retrieveUserByIdentifier(Arr::fetch($credentials, $identifier));

        if ($user) {
            /** @var \Phalcon\Security $security */
            $security = $this->{Services::SECURITY};

            if($security->checkHash(Arr::fetch($credentials, $password), $user->getAuthPassword())){
                return $user;
            }
        }

        return null;
    }

    /**
     * Regenerate Session ID
     */
    protected function regenerateSessionId()
    {
        $this->{Services::SESSION}->regenerateId();
    }

    /**
     * Retrieve session id
     *
     * @return mixed
     */
    private function sessionKey()
    {
        return $this->{Services::CONFIG}->session->id;
    }

    /**
     * @return string|\Neutrino\Foundation\Auth\User
     */
    private function modelClass()
    {
        if (!isset($this->model)) {
            $this->model = '\\' . $this->{Services::CONFIG}->auth->model;
        }

        return $this->model;
    }
}


<?php

namespace Neutrino\Debug;

use Neutrino\Constants\Events;
use Neutrino\Constants\Services;
use Neutrino\Error\Handler;
use Phalcon\Cli\Console;
use Phalcon\Db\Adapter;
use Phalcon\Db\Profiler;
use Phalcon\Di;
use Phalcon\Events\Event;
use Phalcon\Events\EventsAwareInterface;
use Phalcon\Events\Manager;
use Phalcon\Mvc\View;

/**
 * Class DebugProvider
 *
 * Neutrino
 */
class Debugger
{
    /** @var array */
    private static $viewProfiles;

    /** @var Profiler[] */
    private static $profilers;

    /** @var self */
    private static $instance;

    /** @var View\Simple */
    private static $view;

    /** @var \Neutrino\Debug\DebugEventsManagerWrapper */
    private $em;

    private function __construct()
    {
        self::$instance = $this;

        $di = Di::getDefault();

        if ($di->get(Services::APP) instanceof Console) {
            return;
        }

        Handler::addWriter(DebugErrorLogger::class);

        $this->registerGlobalEventManager();

        $this->listenLoader();

        $this->listenServices();

        DebugToolbar::register();
    }

    /**
     * @return \Phalcon\Events\Manager
     */
    private function registerGlobalEventManager()
    {
        /** @var Di $di */
        $di = Di::getDefault();

        if ($di->has(Services::EVENTS_MANAGER)) {
            $di->setShared(Services::EVENTS_MANAGER, $gem = new DebugEventsManagerWrapper($di->get(Services::EVENTS_MANAGER)));
        } else {
            $di->setShared(Services::EVENTS_MANAGER, $gem = new DebugEventsManagerWrapper(new Manager()));
        }

        $app = $di->get(Services::APP);
        $em = $app->getEventsManager();
        if (is_null($em)) {
            $app->setEventsManager($gem);
        } else {
            $app->setEventsManager($gem = new DebugEventsManagerWrapper($em));
        }

        $em = $di->getInternalEventsManager();
        if (is_null($em)) {
            $di->setInternalEventsManager($gem);
        } else {
            $di->setInternalEventsManager($gem = new DebugEventsManagerWrapper($em));
        }

        return $this->em = $gem;
    }

    private function listenLoader()
    {
        global $loader;

        /** @var \Phalcon\Loader $loader */
        if (isset($loader)) {
            $this->attachEventsManager($loader);
        }
    }

    private function listenServices()
    {
        $this->em->attach('di:afterServiceResolve', function ($ev, $src, $data) {
            static $resolved;

            if (isset($resolved[$data['name']])) {
                return;
            }

            $resolved[$data['name']] = true;

            $this->tryAttachEventsManager($data['instance']);

            if ($data['instance'] instanceof Adapter\Pdo) {
                $this->dbProfilerRegister();
            }
            if ($data['instance'] instanceof View) {
                try {
                    $engines = (array)Reflexion::get($data['instance'], '_engines');
                } catch (\Exception $e) {
                    $engines = [];
                }
                foreach ($engines as $engine) {
                    $this->tryAttachEventsManager($engine);
                }
                $this->viewProfilerRegister();
            }
        });
    }

    private function tryAttachEventsManager($service)
    {
        if ($service instanceof EventsAwareInterface
          || (method_exists($service, 'getEventsManager') && method_exists($service, 'setEventsManager'))) {
            $this->attachEventsManager($service);
        }
    }

    /**
     * @param EventsAwareInterface $service
     */
    private function attachEventsManager($service)
    {
        $em = $service->getEventsManager();
        if ($em) {
            if (!($em instanceof DebugEventsManagerWrapper)) {
                $service->setEventsManager(new DebugEventsManagerWrapper($em));
            }
        } else {
            $service->setEventsManager($this->em);
        }
    }

    /**
     * Register db profiler
     */
    private function dbProfilerRegister()
    {
        $profiler = self::registerProfiler('db', '<i class="nuc db"></i>');

        $this->em->attach(
          Events::DB,
          function (Event $event, Adapter\Pdo $connection) use ($profiler) {
              $eventType = $event->getType();
              if ($eventType === 'beforeQuery') {
                  // Start a profile with the active connection
                  $profiler->startProfile(
                    $connection->getSQLStatement(),
                    $connection->getSqlVariables(),
                    $connection->getSQLBindTypes()
                  );
              }
              if ($eventType === 'afterQuery') {
                  // Stop the active profile
                  $profiler->stopProfile();
              }
          }
        );
    }

    /**
     * Register view profiler
     */
    private function viewProfilerRegister()
    {
        $this->em->attach(
          Events::VIEW,
          function (Event $event, $src, $data) {
              $eventType = $event->getType();
              if ($eventType === 'beforeRender') {
                  self::$viewProfiles['render'][] = self::$viewProfiles['__render'][] = [
                    'initialTime' => microtime(true)
                  ];
              } elseif ($eventType === 'beforeRenderView') {
                  self::$viewProfiles['__renderViews'][] = self::$viewProfiles['renderViews'][] = [
                    'file' => $data,
                    'initialTime' => microtime(true)
                  ];
              } elseif ($eventType === 'afterRenderView') {
                  $profile = array_pop(self::$viewProfiles['__renderViews']);
                  $profile['finalTime'] = microtime(true);
                  $profile['elapsedTime'] = $profile['finalTime'] - $profile['initialTime'];

                  self::$viewProfiles['renderViews'][count(self::$viewProfiles['__renderViews'])] = $profile;
              } elseif ($eventType === 'notFoundView') {
                  self::$viewProfiles['notFoundView'][] = $data;
              } elseif ($eventType === 'afterRender') {
                  $profile = array_pop(self::$viewProfiles['__render']);
                  $profile['finalTime'] = microtime(true);
                  $profile['elapsedTime'] = $profile['finalTime'] - $profile['initialTime'];

                  self::$viewProfiles['render'][count(self::$viewProfiles['__render'])] = $profile;
              }
          }
        );
    }

    public static function register()
    {
        if (self::isEnable()) {
            return;
        }

        new self;
    }

    public static function isEnable()
    {
        return isset(self::$instance);
    }

    public static function getGlobalEventsManager()
    {
        if (!isset(self::$instance)) {
            throw new \Exception("Debugger wasn't registered");
        }

        return self::$instance->em;
    }

    public static function getBuildInfo()
    {
        $build = [
          'php' => [
            'version' => PHP_VERSION,
          ],
          'zend' => [
            'version' => zend_version(),
          ],
          'phalcon' => [
            'version' => \Phalcon\Version::get(),
          ],
          'neutrino' => [
            'version' => \Neutrino\Version::get(),
          ],
        ];

        foreach (get_loaded_extensions(true) as $extension) {
            $build['zend']['extensions'][$extension] = phpversion($extension);
        }
        foreach (get_loaded_extensions(false) as $extension) {
            $build['php']['extensions'][$extension] = phpversion($extension);
        }

        $build['phalcon']['ini'] = ini_get_all('phalcon');

        return $build;
    }

    /**
     * @return array
     */
    public static function getViewProfiles()
    {
        return self::$viewProfiles;
    }

    public static function getRegisteredProfilers()
    {
        return self::$profilers;
    }

    /**
     * @param string $file
     * @param array $params
     *
     * @return string|null
     */
    public static function internalRender($file, array $params = [])
    {
        if(!isset(self::$view)){
            include __DIR__ . '/helpers/functions.php';
            $view = new View\Simple();
            $view->setDI(new Di());
            $view->setViewsDir(__DIR__ . '/resources/');
            $view->registerEngines(['.html.php' => View\Engine\Php::class]);
            self::$view = $view;
        }

        return self::$view->setVars($params)->render($file);
    }

    /**
     * @param string $name
     * @param string|null $icon
     *
     * @return \Phalcon\Db\Profiler
     */
    public static function registerProfiler($name, $icon = null)
    {
        if (isset(self::$profilers[$name])) {
            return self::$profilers[$name]['profiler'];
        }

        self::$profilers[$name] = [
          'icon' => $icon,
          'profiler' => $profiler = new Profiler()
        ];

        return $profiler;
    }
}