<?php

namespace persianyii\jalali;

/**
 * Description of Zjalali
 *
 * @author mehrdad
 */
class Jalali extends \yii\base\Widget {

    /** Software Hijri_Shamsi , Solar(Jalali) Date and Time
      Copyright(C)2011, Reza Gholampanahi , http://jdf.scr.ir
      version 2.55 :: 1391/08/24 = 1433/12/18 = 2012/11/15 */
    /* 	F	 */
    static public function jdate($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa') {

        $T_sec = 0; /* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */

        if ($time_zone != 'local')
            date_default_timezone_set(($time_zone == '') ? 'Asia/Tehran' : $time_zone);
        $ts = $T_sec + (($timestamp == '' or $timestamp == 'now') ? time() : self::tr_num($timestamp));
        $date = explode('_', date('H_i_j_n_O_P_s_w_Y', $ts));
        list($j_y, $j_m, $j_d) = self::gregorian_to_jalali($date[8], $date[3], $date[2]);
        $doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d - 1 : (($j_m - 7) * 30) + $j_d + 185;
        $kab = ($j_y % 33 % 4 - 1 == (int) ($j_y % 33 * .05)) ? 1 : 0;
        $sl = strlen($format);
        $out = '';
        for ($i = 0; $i < $sl; $i++) {
            $sub = substr($format, $i, 1);
            if ($sub == '\\') {
                $out.=substr($format, ++$i, 1);
                continue;
            }
            switch ($sub) {

                case'E':case'R':case'x':case'X':
                    $out.='http://jdf.scr.ir';
                    break;

                case'B':case'e':case'g':
                case'G':case'h':case'I':
                case'T':case'u':case'Z':
                    $out.=date($sub, $ts);
                    break;

                case'a':
                    $out.=($date[0] < 12) ? 'ق.ظ' : 'ب.ظ';
                    break;

                case'A':
                    $out.=($date[0] < 12) ? 'قبل از ظهر' : 'بعد از ظهر';
                    break;

                case'b':
                    $out.=(int) ($j_m / 3.1) + 1;
                    break;

                case'c':
                    $out.=$j_y . '/' . $j_m . '/' . $j_d . ' ،' . $date[0] . ':' . $date[1] . ':' . $date[6] . ' ' . $date[5];
                    break;

                case'C':
                    $out.=(int) (($j_y + 99) / 100);
                    break;

                case'd':
                    $out.=($j_d < 10) ? '0' . $j_d : $j_d;
                    break;

                case'D':
                    $out.=self::jdate_words(array('kh' => $date[7]), ' ');
                    break;

                case'f':
                    $out.=self::jdate_words(array('ff' => $j_m), ' ');
                    break;

                case'F':
                    $out.=self::jdate_words(array('mm' => $j_m), ' ');
                    break;

                case'H':
                    $out.=$date[0];
                    break;

                case'i':
                    $out.=$date[1];
                    break;

                case'j':
                    $out.=$j_d;
                    break;

                case'J':
                    $out.=self::jdate_words(array('rr' => $j_d), ' ');
                    break;

                case'k';
                    $out.=self::tr_num(100 - (int) ($doy / ($kab + 365) * 1000) / 10, $tr_num);
                    break;

                case'K':
                    $out.=self::tr_num((int) ($doy / ($kab + 365) * 1000) / 10, $tr_num);
                    break;

                case'l':
                    $out.=self::jdate_words(array('rh' => $date[7]), ' ');
                    break;

                case'L':
                    $out.=$kab;
                    break;

                case'm':
                    $out.=($j_m > 9) ? $j_m : '0' . $j_m;
                    break;

                case'M':
                    $out.=self::jdate_words(array('km' => $j_m), ' ');
                    break;

                case'n':
                    $out.=$j_m;
                    break;

                case'N':
                    $out.=$date[7] + 1;
                    break;

                case'o':
                    $jdw = ($date[7] == 6) ? 0 : $date[7] + 1;
                    $dny = 364 + $kab - $doy;
                    $out.=($jdw > ($doy + 3) and $doy < 3) ? $j_y - 1 : (((3 - $dny) > $jdw and $dny < 3) ? $j_y + 1 : $j_y);
                    break;

                case'O':
                    $out.=$date[4];
                    break;

                case'p':
                    $out.=self::jdate_words(array('mb' => $j_m), ' ');
                    break;

                case'P':
                    $out.=$date[5];
                    break;

                case'q':
                    $out.=self::jdate_words(array('sh' => $j_y), ' ');
                    break;

                case'Q':
                    $out.=$kab + 364 - $doy;
                    break;

                case'r':
                    $key = self::jdate_words(array('rh' => $date[7], 'mm' => $j_m));
                    $out.=$date[0] . ':' . $date[1] . ':' . $date[6] . ' ' . $date[4]
                            . ' ' . $key['rh'] . '، ' . $j_d . ' ' . $key['mm'] . ' ' . $j_y;
                    break;

                case's':
                    $out.=$date[6];
                    break;

                case'S':
                    $out.='ام';
                    break;

                case't':
                    $out.=($j_m != 12) ? (31 - (int) ($j_m / 6.5)) : ($kab + 29);
                    break;

                case'U':
                    $out.=$ts;
                    break;

                case'v':
                    $out.=self::jdate_words(array('ss' => substr($j_y, 2, 2)), ' ');
                    break;

                case'V':
                    $out.=self::jdate_words(array('ss' => $j_y), ' ');
                    break;

                case'w':
                    $out.=($date[7] == 6) ? 0 : $date[7] + 1;
                    break;

                case'W':
                    $avs = (($date[7] == 6) ? 0 : $date[7] + 1) - ($doy % 7);
                    if ($avs < 0)
                        $avs+=7;
                    $num = (int) (($doy + $avs) / 7);
                    if ($avs < 4) {
                        $num++;
                    } elseif ($num < 1) {
                        $num = ($avs == 4 or $avs == (($j_y % 33 % 4 - 2 == (int) ($j_y % 33 * .05)) ? 5 : 4)) ? 53 : 52;
                    }
                    $aks = $avs + $kab;
                    if ($aks == 7)
                        $aks = 0;
                    $out.=(($kab + 363 - $doy) < $aks and $aks < 3) ? '01' : (($num < 10) ? '0' . $num : $num);
                    break;

                case'y':
                    $out.=substr($j_y, 2, 2);
                    break;

                case'Y':
                    $out.=$j_y;
                    break;

                case'z':
                    $out.=$doy;
                    break;

                default:$out.=$sub;
            }
        }
        return($tr_num != 'en') ? self::tr_num($out, 'fa', '.') : $out;
    }

    /* 	F	 */

    static public function jstrftime($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa') {

        $T_sec = 0; /* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */

        if ($time_zone != 'local')
            date_default_timezone_set(($time_zone == '') ? 'Asia/Tehran' : $time_zone);
        $ts = $T_sec + (($timestamp == '' or $timestamp == 'now') ? time() : tr_num($timestamp));
        $date = explode('_', date('h_H_i_j_n_s_w_Y', $ts));
        list($j_y, $j_m, $j_d) = self::gregorian_to_jalali($date[7], $date[4], $date[3]);
        $doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d - 1 : (($j_m - 7) * 30) + $j_d + 185;
        $kab = ($j_y % 33 % 4 - 1 == (int) ($j_y % 33 * .05)) ? 1 : 0;
        $sl = strlen($format);
        $out = '';
        for ($i = 0; $i < $sl; $i++) {
            $sub = substr($format, $i, 1);
            if ($sub == '%') {
                $sub = substr($format, ++$i, 1);
            } else {
                $out.=$sub;
                continue;
            }
            switch ($sub) {

                /* Day */
                case'a':
                    $out.=self::jdate_words(array('kh' => $date[6]), ' ');
                    break;

                case'A':
                    $out.=self::jdate_words(array('rh' => $date[6]), ' ');
                    break;

                case'd':
                    $out.=($j_d < 10) ? '0' . $j_d : $j_d;
                    break;

                case'e':
                    $out.=($j_d < 10) ? ' ' . $j_d : $j_d;
                    break;

                case'j':
                    $out.=str_pad($doy + 1, 3, 0, STR_PAD_LEFT);
                    break;

                case'u':
                    $out.=$date[6] + 1;
                    break;

                case'w':
                    $out.=($date[6] == 6) ? 0 : $date[6] + 1;
                    break;

                /* Week */
                case'U':
                    $avs = (($date[6] < 5) ? $date[6] + 2 : $date[6] - 5) - ($doy % 7);
                    if ($avs < 0)
                        $avs+=7;
                    $num = (int) (($doy + $avs) / 7) + 1;
                    if ($avs > 3 or $avs == 1)
                        $num--;
                    $out.=($num < 10) ? '0' . $num : $num;
                    break;

                case'V':
                    $avs = (($date[6] == 6) ? 0 : $date[6] + 1) - ($doy % 7);
                    if ($avs < 0)
                        $avs+=7;
                    $num = (int) (($doy + $avs) / 7);
                    if ($avs < 4) {
                        $num++;
                    } elseif ($num < 1) {
                        $num = ($avs == 4 or $avs == (($j_y % 33 % 4 - 2 == (int) ($j_y % 33 * .05)) ? 5 : 4)) ? 53 : 52;
                    }
                    $aks = $avs + $kab;
                    if ($aks == 7)
                        $aks = 0;
                    $out.=(($kab + 363 - $doy) < $aks and $aks < 3) ? '01' : (($num < 10) ? '0' . $num : $num);
                    break;

                case'W':
                    $avs = (($date[6] == 6) ? 0 : $date[6] + 1) - ($doy % 7);
                    if ($avs < 0)
                        $avs+=7;
                    $num = (int) (($doy + $avs) / 7) + 1;
                    if ($avs > 3)
                        $num--;
                    $out.=($num < 10) ? '0' . $num : $num;
                    break;

                /* Month */
                case'b':
                case'h':
                    $out.=self::jdate_words(array('km' => $j_m), ' ');
                    break;

                case'B':
                    $out.=self::jdate_words(array('mm' => $j_m), ' ');
                    break;

                case'm':
                    $out.=($j_m > 9) ? $j_m : '0' . $j_m;
                    break;

                /* Year */
                case'C':
                    $out.=substr($j_y, 0, 2);
                    break;

                case'g':
                    $jdw = ($date[6] == 6) ? 0 : $date[6] + 1;
                    $dny = 364 + $kab - $doy;
                    $out.=substr(($jdw > ($doy + 3) and $doy < 3) ? $j_y - 1 : (((3 - $dny) > $jdw and $dny < 3) ? $j_y + 1 : $j_y), 2, 2);
                    break;

                case'G':
                    $jdw = ($date[6] == 6) ? 0 : $date[6] + 1;
                    $dny = 364 + $kab - $doy;
                    $out.=($jdw > ($doy + 3) and $doy < 3) ? $j_y - 1 : (((3 - $dny) > $jdw and $dny < 3) ? $j_y + 1 : $j_y);
                    break;

                case'y':
                    $out.=substr($j_y, 2, 2);
                    break;

                case'Y':
                    $out.=$j_y;
                    break;

                /* Time */
                case'H':
                    $out.=$date[1];
                    break;

                case'I':
                    $out.=$date[0];
                    break;

                case'l':
                    $out.=($date[0] > 9) ? $date[0] : ' ' . (int) $date[0];
                    break;

                case'M':
                    $out.=$date[2];
                    break;

                case'p':
                    $out.=($date[1] < 12) ? 'قبل از ظهر' : 'بعد از ظهر';
                    break;

                case'P':
                    $out.=($date[1] < 12) ? 'ق.ظ' : 'ب.ظ';
                    break;

                case'r':
                    $out.=$date[0] . ':' . $date[2] . ':' . $date[5] . ' ' . (($date[1] < 12) ? 'قبل از ظهر' : 'بعد از ظهر');
                    break;

                case'R':
                    $out.=$date[1] . ':' . $date[2];
                    break;

                case'S':
                    $out.=$date[5];
                    break;

                case'T':
                    $out.=$date[1] . ':' . $date[2] . ':' . $date[5];
                    break;

                case'X':
                    $out.=$date[0] . ':' . $date[2] . ':' . $date[5];
                    break;

                case'z':
                    $out.=date('O', $ts);
                    break;

                case'Z':
                    $out.=date('T', $ts);
                    break;

                /* Time and Date Stamps */
                case'c':
                    $key = self::jdate_words(array('rh' => $date[6], 'mm' => $j_m));
                    $out.=$date[1] . ':' . $date[2] . ':' . $date[5] . ' ' . date('P', $ts)
                            . ' ' . $key['rh'] . '، ' . $j_d . ' ' . $key['mm'] . ' ' . $j_y;
                    break;

                case'D':
                    $out.=substr($j_y, 2, 2) . '/' . (($j_m > 9) ? $j_m : '0' . $j_m) . '/' . (($j_d < 10) ? '0' . $j_d : $j_d);
                    break;

                case'F':
                    $out.=$j_y . '-' . (($j_m > 9) ? $j_m : '0' . $j_m) . '-' . (($j_d < 10) ? '0' . $j_d : $j_d);
                    break;

                case's':
                    $out.=$ts;
                    break;

                case'x':
                    $out.=substr($j_y, 2, 2) . '/' . (($j_m > 9) ? $j_m : '0' . $j_m) . '/' . (($j_d < 10) ? '0' . $j_d : $j_d);
                    break;

                /* Miscellaneous */
                case'n':
                    $out.="\n";
                    break;

                case't':
                    $out.="\t";
                    break;

                case'%':
                    $out.='%';
                    break;

                default:$out.=$sub;
            }
        }
        return($tr_num != 'en') ? self::tr_num($out, 'fa', '.') : $out;
    }

    /* 	F	 */

    static public function jmktime($h = '', $m = '', $s = '', $jm = '', $jd = '', $jy = '', $is_dst = -1) {
        date_default_timezone_set('Asia/Tehran');
        $h = self::tr_num($h);
        $m = self::tr_num($m);
        $s = self::tr_num($s);
        $jm = self::tr_num($jm);
        $jd = self::tr_num($jd);
        $jy = self::tr_num($jy);
        if ($h == '' and $m == '' and $s == '' and $jm == '' and $jd == '' and $jy == '') {
            return mktime();
        } else {
            list($year, $month, $day) = self::jalali_to_gregorian($jy, $jm, $jd);
            return mktime($h, $m, $s, $month, $day, $year, $is_dst);
        }
    }

    /* 	F	 */

    static public function jgetdate($timestamp = '', $none = '', $tz = 'Asia/Tehran', $tn = 'en') {
        $ts = ($timestamp == '') ? time() : self::tr_num($timestamp);
        $jdate = explode('_', self::jdate('F_G_i_j_l_n_s_w_Y_z', $ts, '', $tz, $tn));
        return array(
            'seconds' => self::tr_num((int) self::tr_num($jdate[6]), $tn),
            'minutes' => self::tr_num((int) self::tr_num($jdate[2]), $tn),
            'hours' => $jdate[1],
            'mday' => $jdate[3],
            'wday' => $jdate[7],
            'mon' => $jdate[5],
            'year' => $jdate[8],
            'yday' => $jdate[9],
            'weekday' => $jdate[4],
            'month' => $jdate[0],
            0 => self::tr_num($ts, $tn)
        );
    }

    /* 	F	 */

    static public function jcheckdate($jm, $jd, $jy) {
        $jm = self::tr_num($jm);
        $jd = self::tr_num($jd);
        $jy = self::tr_num($jy);
        $l_d = ($jm == 12) ? (($jy % 33 % 4 - 1 == (int) ($jy % 33 * .05)) ? 30 : 29) : 31 - (int) ($jm / 6.5);
        return($jm > 0 and $jd > 0 and $jy > 0 and $jm < 13 and $jd <= $l_d) ? true : false;
    }

    /* 	F	 */

    static public function tr_num($str, $mod = 'en', $mf = '٫') {
        $num_a = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.');
        $key_a = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', $mf);
        return($mod == 'fa') ? str_replace($num_a, $key_a, $str) : str_replace($key_a, $num_a, $str);
    }

    /* 	F	 */

    static public function jdate_words($array, $mod = '') {
        foreach ($array as $type => $num) {
            $num = (int) self::tr_num($num);
            switch ($type) {

                case'ss':
                    $sl = strlen($num);
                    $xy3 = substr($num, 2 - $sl, 1);
                    $h3 = $h34 = $h4 = '';
                    if ($xy3 == 1) {
                        $p34 = '';
                        $k34 = array('ده', 'یازده', 'دوازده', 'سیزده', 'چهارده', 'پانزده', 'شانزده', 'هفده', 'هجده', 'نوزده');
                        $h34 = $k34[substr($num, 2 - $sl, 2) - 10];
                    } else {
                        $xy4 = substr($num, 3 - $sl, 1);
                        $p34 = ($xy3 == 0 or $xy4 == 0) ? '' : ' و ';
                        $k3 = array('', '', 'بیست', 'سی', 'چهل', 'پنجاه', 'شصت', 'هفتاد', 'هشتاد', 'نود');
                        $h3 = $k3[$xy3];
                        $k4 = array('', 'یک', 'دو', 'سه', 'چهار', 'پنج', 'شش', 'هفت', 'هشت', 'نه');
                        $h4 = $k4[$xy4];
                    }
                    $array[$type] = (($num > 99) ? str_ireplace(array('12', '13', '14', '19', '20')
                                            , array('هزار و دویست', 'هزار و سیصد', 'هزار و چهارصد', 'هزار و نهصد', 'دوهزار')
                                            , substr($num, 0, 2)) . ((substr($num, 2, 2) == '00') ? '' : ' و ') : '') . $h3 . $p34 . $h34 . $h4;
                    break;

                case'mm':
                    $key = array
                        ('فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند');
                    $array[$type] = $key[$num - 1];
                    break;

                case'rr':
                    $key = array('یک', 'دو', 'سه', 'چهار', 'پنج', 'شش', 'هفت', 'هشت', 'نه', 'ده', 'یازده', 'دوازده', 'سیزده',
                        'چهارده', 'پانزده', 'شانزده', 'هفده', 'هجده', 'نوزده', 'بیست', 'بیست و یک', 'بیست و دو', 'بیست و سه',
                        'بیست و چهار', 'بیست و پنج', 'بیست و شش', 'بیست و هفت', 'بیست و هشت', 'بیست و نه', 'سی', 'سی و یک');
                    $array[$type] = $key[$num - 1];
                    break;

                case'rh':
                    $key = array('یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه');
                    $array[$type] = $key[$num];
                    break;

                case'sh':
                    $key = array('مار', 'اسب', 'گوسفند', 'میمون', 'مرغ', 'سگ', 'خوک', 'موش', 'گاو', 'پلنگ', 'خرگوش', 'نهنگ');
                    $array[$type] = $key[$num % 12];
                    break;

                case'mb':
                    $key = array('حمل', 'ثور', 'جوزا', 'سرطان', 'اسد', 'سنبله', 'میزان', 'عقرب', 'قوس', 'جدی', 'دلو', 'حوت');
                    $array[$type] = $key[$num - 1];
                    break;

                case'ff':
                    $key = array('بهار', 'تابستان', 'پاییز', 'زمستان');
                    $array[$type] = $key[(int) ($num / 3.1)];
                    break;

                case'km':
                    $key = array('فر', 'ار', 'خر', 'تی', 'مر', 'شه', 'مه', 'آب', 'آذ', 'دی', 'به', 'اس');
                    $array[$type] = $key[$num - 1];
                    break;

                case'kh':
                    $key = array('ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش');
                    $array[$type] = $key[$num];
                    break;

                default:$array[$type] = $num;
            }
        }
        return($mod == '') ? $array : implode($mod, $array);
    }

    /** Convertor from and to Gregorian and Jalali (Hijri_Shamsi,Solar) Functions
      Copyright(C)2011, Reza Gholampanahi [ http://jdf.scr.ir/jdf ] version 2.50 */
    /* 	F	 */
    static public function gregorian_to_jalali($g_y, $g_m, $g_d, $mod = '') {
        $g_y = self::tr_num($g_y);
        $g_m = self::tr_num($g_m);
        $g_d = self::tr_num($g_d); /* <= :اين سطر ، جزء تابع اصلي نيست */
        $d_4 = $g_y % 4;
        $g_a = array(0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
        $doy_g = $g_a[(int) $g_m] + $g_d;
        if ($d_4 == 0 and $g_m > 2)
            $doy_g++;
        $d_33 = (int) ((($g_y - 16) % 132) * .0305);
        $a = ($d_33 == 3 or $d_33 < ($d_4 - 1) or $d_4 == 0) ? 286 : 287;
        $b = (($d_33 == 1 or $d_33 == 2) and ($d_33 == $d_4 or $d_4 == 1)) ? 78 : (($d_33 == 3 and $d_4 == 0) ? 80 : 79);
        if ((int) (($g_y - 10) / 63) == 30) {
            $a--;
            $b++;
        }
        if ($doy_g > $b) {
            $jy = $g_y - 621;
            $doy_j = $doy_g - $b;
        } else {
            $jy = $g_y - 622;
            $doy_j = $doy_g + $a;
        }
        if ($doy_j < 187) {
            $jm = (int) (($doy_j - 1) / 31);
            $jd = $doy_j - (31 * $jm++);
        } else {
            $jm = (int) (($doy_j - 187) / 30);
            $jd = $doy_j - 186 - ($jm * 30);
            $jm+=7;
        }
        return($mod == '') ? array($jy, $jm, $jd) : $jy . $mod . $jm . $mod . $jd;
    }

    /* 	F	 */

    static public function jalali_to_gregorian($j_y, $j_m, $j_d, $mod = '') {
        $j_y = self::tr_num($j_y);
        $j_m = self::tr_num($j_m);
        $j_d = self::tr_num($j_d); /* <= :اين سطر ، جزء تابع اصلي نيست */
        $d_4 = ($j_y + 1) % 4;
        $doy_j = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d : (($j_m - 7) * 30) + $j_d + 186;
        $d_33 = (int) ((($j_y - 55) % 132) * .0305);
        $a = ($d_33 != 3 and $d_4 <= $d_33) ? 287 : 286;
        $b = (($d_33 == 1 or $d_33 == 2) and ($d_33 == $d_4 or $d_4 == 1)) ? 78 : (($d_33 == 3 and $d_4 == 0) ? 80 : 79);
        if ((int) (($j_y - 19) / 63) == 20) {
            $a--;
            $b++;
        }
        if ($doy_j <= $a) {
            $gy = $j_y + 621;
            $gd = $doy_j + $b;
        } else {
            $gy = $j_y + 622;
            $gd = $doy_j - $a;
        }
        foreach (array(0, 31, ($gy % 4 == 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) as $gm => $v) {
            if ($gd <= $v)
                break;
            $gd-=$v;
        }
        return($mod == '') ? array($gy, $gm, $gd) : $gy . $mod . $gm . $mod . $gd;
    }

    /* [ jdf.php ] version 2.55 ?> Download new version from [ http://jdf.scr.ir ] */
}

?>


<?php
/**
 * FlorianWolters\Component\Core\DebugPrintExample
 *
 * PHP Version 5.4
 *
 * @author    Florian Wolters <wolters.fl@gmail.com>
 * @copyright 2012-2014 Florian Wolters (http://blog.florianwolters.de)
 * @license   http://gnu.org/licenses/lgpl.txt LGPL-3.0+
 * @link      http://github.com/FlorianWolters/PHP-Component-Core-DebugPrint
 */

namespace FlorianWolters\Example;

use FlorianWolters\Component\Core\DebugPrintInterface;
use FlorianWolters\Example\DebugPrintCustomImpl;
use FlorianWolters\Example\DebugPrintDefaultImpl;

require __DIR__ . '/../../vendor/autoload.php';

/**
 * The class {@see DebugPrintExample} implements a simple command line
 * application to demonstrate the component
 * **FlorianWolters\Component\Core\DebugPrint**.
 *
 * @since Class available since Release 0.2.0
 */
final class DebugPrintExample
{
    /**
     * Runs the {@see DebugPrintExample}.
     *
     * @param integer $argc The number of arguments.
     * @param array   $argv The arguments.
     *
     * @return integer Always `0`.
     */
    public static function main($argc, array $argv = array())
    {
        $self = new self;
        $self->demonstrateDefaultImplementation();
        $self->demonstrateCustomImplementation();

        return 0;
    }

    /**
     * @return void
     */
    private function demonstrateDefaultImplementation()
    {
        $first = new DebugPrintDefaultImpl;
        $second = new DebugPrintDefaultImpl;
        $this->output($first);
        $this->output($second);
    }

    /**
     * @return void
     */
    private function demonstrateCustomImplementation()
    {
        $first = new DebugPrintCustomImpl('foo');
        $second = new DebugPrintCustomImpl('bar');
        $this->output($first);
        $this->output($second);
    }

    /**
     * @param DebugPrintInterface $obj
     *
     * @return void
     */
    private function output(DebugPrintInterface $obj)
    {
        // Explicit call of the Debug Print Method __toString().
        $this->writeLine($obj->__toString());
        // Implicit call of the Debug Print Method __toString().
        $this->writeLine($obj);
    }

    /**
     * @param string $text
     *
     * @return void
     */
    private function writeLine($text = '')
    {
        echo $text . \PHP_EOL;
    }
}

exit(DebugPrintExample::main($argc, $argv));


<?php

namespace Ekyna\Bundle\CoreBundle\Doctrine\Repository;

use Doctrine\ORM\QueryBuilder;

/**
 * Trait EnabledFilterTrait
 * @package Ekyna\Bundle\CoreBundle\Doctrine\Repository
 * @author Étienne Dauvergne <contact@ekyna.com>
 */
trait EnabledFilterTrait
{
    /**
     * @var bool
     */
    protected $_filterEnabled = true;

    /**
     * Sets if the query builder should be configured or not.
     *
     * @param $boolean
     */
    public function setFilterEnabled($boolean)
    {
        $this->_filterEnabled = (bool) $boolean;
    }

    /**
     * Configures the query builder.
     *
     * @param QueryBuilder $qb
     */
    public function addFilterEnabledClause(QueryBuilder $qb)
    {
        if ($this->_filterEnabled) {
            $qb
                ->andWhere($qb->expr()->eq($qb->getRootAliases()[0].'.enabled', ':enabled'))
                ->setParameter('enabled', true)
            ;
        }
    }
}


<?php

/**
 * @copyright  Copyright (c) Flipbox Digital Limited
 * @license    https://flipboxfactory.com/software/domains/license
 * @link       https://www.flipboxfactory.com/software/domains/
 */

namespace flipbox\craft\sortable\associations\db\traits;

use Craft;
use craft\helpers\Db;
use yii\db\Expression;

trait SiteAttribute
{
    /**
     * @var int|int[]|false|null The site ID(s). Prefix IDs with "not " to exclude them.
     */
    public $siteId;

    /**
     * Adds an additional WHERE condition to the existing one.
     * The new condition and the existing one will be joined using the `AND` operator.
     * @param string|array|Expression $condition the new WHERE condition. Please refer to [[where()]]
     * on how to specify this parameter.
     * @param array $params the parameters (name => value) to be bound to the query.
     * @return $this the query object itself
     * @see where()
     * @see orWhere()
     */
    abstract public function andWhere($condition, $params = []);

    /**
     * @param $value
     * @return static
     */
    public function siteId($value)
    {
        $this->siteId = $value;
        return $this;
    }

    /**
     * @param $value
     * @return static
     */
    public function site($value)
    {
        return $this->siteId($value);
    }

    /**
     * Apply attribute conditions
     */
    protected function applySiteConditions()
    {
        if ($this->siteId !== null) {
            $this->andWhere(Db::parseParam('siteId', $this->siteId));
        } else {
            $this->andWhere(Db::parseParam('siteId', Craft::$app->getSites()->currentSite->id));
        }
    }
}


<?php

namespace Think;

use ReflectionClass;
use ReflectionException;
use ReflectionMethod;

/**
 * 应用程序类 执行应用过程管理
 * Class App
 * @package Think
 */
final class App
{

    /**
     * 应用程序初始化

     * @return void
     */
    protected static function init()
    {
        // 加载动态应用公共文件和配置
        load_ext_file(COMMON_PATH);

        // 日志目录转换为绝对路径 默认情况下存储到公共模块下面
        C('LOG_PATH', realpath(LOG_PATH).'/Common/');

        // 定义当前请求的系统常量
        define('NOW_TIME', $_SERVER['REQUEST_TIME']);
        define('REQUEST_METHOD', $_SERVER['REQUEST_METHOD']);
        define('IS_GET', REQUEST_METHOD == 'GET');
        define('IS_POST', REQUEST_METHOD == 'POST');
        define('IS_PUT', REQUEST_METHOD == 'PUT');
        define('IS_DELETE', REQUEST_METHOD == 'DELETE');

        // URL调度
        Dispatcher::dispatch();

        if (C('REQUEST_VARS_FILTER')) {
            // 全局安全过滤
            array_walk_recursive($_GET, 'think_filter');
            array_walk_recursive($_POST, 'think_filter');
            array_walk_recursive($_REQUEST, 'think_filter');
        }

        // URL调度结束标签

        define(
            'IS_AJAX',
            ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower(
                        $_SERVER['HTTP_X_REQUESTED_WITH']
                    ) == 'xmlhttprequest') || !empty(
                $_POST[C(
                    'VAR_AJAX_SUBMIT'
                )]
                ) || !empty($_GET[C('VAR_AJAX_SUBMIT')]))
        );

        // TMPL_EXCEPTION_FILE 改为绝对地址
        C('TMPL_EXCEPTION_FILE', realpath(C('TMPL_EXCEPTION_FILE')));

        return;
    }

    /**
     * 执行应用程序

     * @return void
     * @throws BaseException
     */
    protected static function exec()
    {
        // 安全检测
        if (!preg_match('/^[A-Za-z](\/|\w)*$/', CONTROLLER_NAME)) {
            $module = false;
        } else {
            //创建控制器实例
            $module = controller(CONTROLLER_NAME);
        }

        if (!$module) {
            // 是否定义Empty控制器
            $module = A('Empty');
            if (!$module) {
                throw new BaseException(L('_CONTROLLER_NOT_EXIST_').':'.CONTROLLER_NAME);
            }
        }

        // 获取当前操作名 支持动态路由
        if (!isset($action)) {
            $action = ACTION_NAME;
        }
        try {
            static::invokeAction($module, $action);
        } catch (ReflectionException $e) {
            // 方法调用发生异常后 引导到__call方法处理
            $method = new ReflectionMethod($module, '__call');
            $method->invokeArgs($module, [$action, '']);
        }

        return;
    }

    /**
     * @param $module
     * @param $action
     *
     * @throws BaseException
     * @throws ReflectionException
     */
    public static function invokeAction($module, $action)
    {
        if (!preg_match('/^[A-Za-z](\w)*$/', $action)) {
            // 非法操作
            throw new ReflectionException();
        }
        //执行当前操作
        $method = new ReflectionMethod($module, $action);
        if ($method->isUserDefined() && !$method->isStatic()) {
            $class = new ReflectionClass($module);
            // 前置操作
            if ($class->hasMethod('_before_'.$action)) {
                $before = $class->getMethod('_before_'.$action);
                if ($before->isUserDefined()) {
                    $before->invoke($module);
                }
            }
            // URL参数绑定检测
            if ($method->getNumberOfParameters() > 0 && C('URL_PARAMS_BIND')) {
                switch ($_SERVER['REQUEST_METHOD']) {
                    case 'POST':
                        $vars = array_merge($_GET, $_POST);
                        break;
                    case 'PUT':
                        parse_str(file_get_contents('php://input'), $vars);
                        break;
                    default:
                        $vars = $_GET;
                }
                $params = $method->getParameters();
                $paramsBindType = C('URL_PARAMS_BIND_TYPE');
                foreach ($params as $param) {
                    $name = $param->getName();
                    if (1 == $paramsBindType && !empty($vars)) {
                        $args[] = array_shift($vars);
                    } elseif (0 == $paramsBindType && isset($vars[$name])) {
                        $args[] = $vars[$name];
                    } elseif ($param->isDefaultValueAvailable()) {
                        $args[] = $param->getDefaultValue();
                    } else {
                        throw new BaseException(L('_PARAM_ERROR_').':'.$name);
                    }
                }
                array_walk_recursive($args, 'think_filter');
                $method->invokeArgs($module, $args);
            } else {
                $method->invoke($module);
            }
            // 后置操作
            if ($class->hasMethod('_after_'.$action)) {
                $after = $class->getMethod('_after_'.$action);
                if ($after->isUserDefined()) {
                    $after->invoke($module);
                }
            }
        } else {
            // 操作方法不是Public 抛出异常
            throw new ReflectionException();
        }
    }

    /**
     * 运行应用实例 入口文件使用的快捷方法

     * @return void
     */
    public static function run()
    {
        // 应用初始化标签
        Hook::listen('app_init');
        static::init();
        // 应用开始标签
        Hook::listen('app_begin');
        // Session初始化
        if (!IS_CLI) {
            session(C('SESSION_OPTIONS'));
        }
        // 记录应用初始化时间
        G('initTime');
        static::exec();
        // 应用结束标签
        Hook::listen('app_end');

        return;
    }

    /**
     * @return string
     */
    public static function logo()
    {
        return 'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAHlBMVEVmAMz///+MQNnZwPKzgOaBLNWgYN/j0Pbx6PvBmOsL4vlcAAAAdklEQVR4XmMAglGQPAGHhKMBLokWFyBQwCIhCAIOWCSajYEggYAdhCSCjYGgEWyUGYqEoiAciKBKCClBgTqahACMxUxABwE7UCRw2kF/y1EtIizBagwGhcLGxqhRxSSIAhwQOlzAYKIIhFbAaQcNJYINGEYQAAA5wB30z2L7JgAAAABJRU5ErkJggg==';
    }
}


<?php
namespace Core\Toolbox\Arrays;

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

    /**
     * Creates an multidimensional array out of an array with keynames
     *
     * @param array $keys
     *            The array holding the keys to use as values
     * @param mixed $value
     *            The value to assign to the last key
     */
    function assign(array $keys, $value)
    {
        foreach ($keys as $key) {
            $arr = &$this->array[$key];
        }

        $arr = $value;

        return $this->array;
    }
}


<?php
/**
 * PEAR_PackageFile, package.xml parsing utility class
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    CVS: $Id: PackageFile.php 313024 2011-07-06 19:51:24Z dufuz $
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * needed for PEAR_VALIDATE_* constants
 */
require_once 'PEAR/Validate.php';
/**
 * Error code if the package.xml <package> tag does not contain a valid version
 */
define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
/**
 * Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
 * currently
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
/**
 * Abstraction for the package.xml package description file
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.9.4
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile
{
    /**
     * @var PEAR_Config
     */
    var $_config;
    var $_debug;

    var $_logger = false;
    /**
     * @var boolean
     */
    var $_rawReturn = false;

    /**
     * helper for extracting Archive_Tar errors
     * @var array
     * @access private
     */
    var $_extractErrors = array();

    /**
     *
     * @param   PEAR_Config $config
     * @param   ?   $debug
     * @param   string @tmpdir Optional temporary directory for uncompressing
     *          files
     */
    function PEAR_PackageFile(&$config, $debug = false)
    {
        $this->_config = $config;
        $this->_debug = $debug;
    }

    /**
     * Turn off validation - return a parsed package.xml without checking it
     *
     * This is used by the package-validate command
     */
    function rawReturn()
    {
        $this->_rawReturn = true;
    }

    function setLogger(&$l)
    {
        $this->_logger = &$l;
    }

    /**
     * Create a PEAR_PackageFile_Parser_v* of a given version.
     * @param   int $version
     * @return  PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
     */
    function &parserFactory($version)
    {
        if (!in_array($version{0}, array('1', '2'))) {
            $a = false;
            return $a;
        }

        include_once 'PEAR/PackageFile/Parser/v' . $version{0} . '.php';
        $version = $version{0};
        $class = "PEAR_PackageFile_Parser_v$version";
        $a = new $class;
        return $a;
    }

    /**
     * For simpler unit-testing
     * @return string
     */
    function getClassPrefix()
    {
        return 'PEAR_PackageFile_v';
    }

    /**
     * Create a PEAR_PackageFile_v* of a given version.
     * @param   int $version
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v1
     */
    function &factory($version)
    {
        if (!in_array($version{0}, array('1', '2'))) {
            $a = false;
            return $a;
        }

        include_once 'PEAR/PackageFile/v' . $version{0} . '.php';
        $version = $version{0};
        $class = $this->getClassPrefix() . $version;
        $a = new $class;
        return $a;
    }

    /**
     * Create a PEAR_PackageFile_v* from its toArray() method
     *
     * WARNING: no validation is performed, the array is assumed to be valid,
     * always parse from xml if you want validation.
     * @param   array $arr
     * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
     * @uses    factory() to construct the returned object.
     */
    function &fromArray($arr)
    {
        if (isset($arr['xsdversion'])) {
            $obj = &$this->factory($arr['xsdversion']);
            if ($this->_logger) {
                $obj->setLogger($this->_logger);
            }

            $obj->setConfig($this->_config);
            $obj->fromArray($arr);
            return $obj;
        }

        if (isset($arr['package']['attribs']['version'])) {
            $obj = &$this->factory($arr['package']['attribs']['version']);
        } else {
            $obj = &$this->factory('1.0');
        }

        if ($this->_logger) {
            $obj->setLogger($this->_logger);
        }

        $obj->setConfig($this->_config);
        $obj->fromArray($arr);
        return $obj;
    }

    /**
     * Create a PEAR_PackageFile_v* from an XML string.
     * @access  public
     * @param   string $data contents of package.xml file
     * @param   int $state package state (one of PEAR_VALIDATE_* constants)
     * @param   string $file full path to the package.xml file (and the files
     *          it references)
     * @param   string $archive optional name of the archive that the XML was
     *          extracted from, if any
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @uses    parserFactory() to construct a parser to load the package.
     */
    function &fromXmlString($data, $state, $file, $archive = false)
    {
        if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) {
            if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
                return PEAR::raiseError('package.xml version "' . $packageversion[1] .
                    '" is not supported, only 1.0, 2.0, and 2.1 are supported.');
            }

            $object = &$this->parserFactory($packageversion[1]);
            if ($this->_logger) {
                $object->setLogger($this->_logger);
            }

            $object->setConfig($this->_config);
            $pf = $object->parse($data, $file, $archive);
            if (PEAR::isError($pf)) {
                return $pf;
            }

            if ($this->_rawReturn) {
                return $pf;
            }

            if (!$pf->validate($state)) {;
                if ($this->_config->get('verbose') > 0
                    && $this->_logger && $pf->getValidationWarnings(false)
                ) {
                    foreach ($pf->getValidationWarnings(false) as $warning) {
                        $this->_logger->log(0, 'ERROR: ' . $warning['message']);
                    }
                }

                $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                    2, null, null, $pf->getValidationWarnings());
                return $a;
            }

            if ($this->_logger && $pf->getValidationWarnings(false)) {
                foreach ($pf->getValidationWarnings() as $warning) {
                    $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                }
            }

            if (method_exists($pf, 'flattenFilelist')) {
                $pf->flattenFilelist(); // for v2
            }

            return $pf;
        } elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) {
            $a = PEAR::raiseError('package.xml file "' . $file .
                '" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
            return $a;
        } else {
            if (!class_exists('PEAR_ErrorStack')) {
                require_once 'PEAR/ErrorStack.php';
            }

            PEAR_ErrorStack::staticPush('PEAR_PackageFile',
                PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
                'warning', array('xml' => $data), 'package.xml "' . $file .
                    '" has no package.xml <package> version');
            $object = &$this->parserFactory('1.0');
            $object->setConfig($this->_config);
            $pf = $object->parse($data, $file, $archive);
            if (PEAR::isError($pf)) {
                return $pf;
            }

            if ($this->_rawReturn) {
                return $pf;
            }

            if (!$pf->validate($state)) {
                $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                    2, null, null, $pf->getValidationWarnings());
                return $a;
            }

            if ($this->_logger && $pf->getValidationWarnings(false)) {
                foreach ($pf->getValidationWarnings() as $warning) {
                    $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                }
            }

            if (method_exists($pf, 'flattenFilelist')) {
                $pf->flattenFilelist(); // for v2
            }

            return $pf;
        }
    }

    /**
     * Register a temporary file or directory.  When the destructor is
     * executed, all registered temporary files and directories are
     * removed.
     *
     * @param string  $file  name of file or directory
     * @return  void
     */
    function addTempFile($file)
    {
        $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
    }

    /**
     * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file.
     * @access  public
     * @param string contents of package.xml file
     * @param int package state (one of PEAR_VALIDATE_* constants)
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @using   Archive_Tar to extract the files
     * @using   fromPackageFile() to load the package after the package.xml
     *          file is extracted.
     */
    function &fromTgzFile($file, $state)
    {
        if (!class_exists('Archive_Tar')) {
            require_once 'Archive/Tar.php';
        }

        $tar = new Archive_Tar($file);
        if ($this->_debug <= 1) {
            $tar->pushErrorHandling(PEAR_ERROR_RETURN);
        }

        $content = $tar->listContent();
        if ($this->_debug <= 1) {
            $tar->popErrorHandling();
        }

        if (!is_array($content)) {
            if (is_string($file) && strlen($file < 255) &&
                  (!file_exists($file) || !@is_file($file))) {
                $ret = PEAR::raiseError("could not open file \"$file\"");
                return $ret;
            }

            $file = realpath($file);
            $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
                                     '. Invalid tgz file.');
            return $ret;
        }

        if (!count($content) && !@is_file($file)) {
            $ret = PEAR::raiseError("could not open file \"$file\"");
            return $ret;
        }

        $xml      = null;
        $origfile = $file;
        foreach ($content as $file) {
            $name = $file['filename'];
            if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
                $xml = $name;
                break;
            }

            if ($name == 'package.xml') {
                $xml = $name;
                break;
            } elseif (preg_match('/package.xml$/', $name, $match)) {
                $xml = $name;
                break;
            }
        }

        $tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear');
        if ($tmpdir === false) {
            $ret = PEAR::raiseError("there was a problem with getting the configured temp directory");
            return $ret;
        }

        PEAR_PackageFile::addTempFile($tmpdir);

        $this->_extractErrors();
        PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));

        if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
            $extra = implode("\n", $this->_extractErrors());
            if ($extra) {
                $extra = ' ' . $extra;
            }

            PEAR::staticPopErrorHandling();
            $ret = PEAR::raiseError('could not extract the package.xml file from "' .
                $origfile . '"' . $extra);
            return $ret;
        }

        PEAR::staticPopErrorHandling();
        $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
        return $ret;
    }

    /**
     * helper callback for extracting Archive_Tar errors
     *
     * @param PEAR_Error|null $err
     * @return array
     * @access private
     */
    function _extractErrors($err = null)
    {
        static $errors = array();
        if ($err === null) {
            $e = $errors;
            $errors = array();
            return $e;
        }
        $errors[] = $err->getMessage();
    }

    /**
     * Create a PEAR_PackageFile_v* from a package.xml file.
     *
     * @access public
     * @param   string  $descfile  name of package xml file
     * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
     * @param   string|false $archive name of the archive this package.xml came
     *          from, if any
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @uses    PEAR_PackageFile::fromXmlString to create the oject after the
     *          XML is loaded from the package.xml file.
     */
    function &fromPackageFile($descfile, $state, $archive = false)
    {
        $fp = false;
        if (is_string($descfile) && strlen($descfile) < 255 &&
             (
              !file_exists($descfile) || !is_file($descfile) || !is_readable($descfile)
              || (!$fp = @fopen($descfile, 'r'))
             )
        ) {
            $a = PEAR::raiseError("Unable to open $descfile");
            return $a;
        }

        // read the whole thing so we only get one cdata callback
        // for each block of cdata
        fclose($fp);
        $data = file_get_contents($descfile);
        $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
        return $ret;
    }

    /**
     * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
     *
     * This method is able to extract information about a package from a .tgz
     * archive or from a XML package definition file.
     *
     * @access public
     * @param   string  $info file name
     * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @uses    fromPackageFile() if the file appears to be XML
     * @uses    fromTgzFile() to load all non-XML files
     */
    function &fromAnyFile($info, $state)
    {
        if (is_dir($info)) {
            $dir_name = realpath($info);
            if (file_exists($dir_name . '/package.xml')) {
                $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package.xml', $state);
            } elseif (file_exists($dir_name .  '/package2.xml')) {
                $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package2.xml', $state);
            } else {
                $info = PEAR::raiseError("No package definition found in '$info' directory");
            }

            return $info;
        }

        $fp = false;
        if (is_string($info) && strlen($info) < 255 &&
             (file_exists($info) || ($fp = @fopen($info, 'r')))
        ) {

            if ($fp) {
                fclose($fp);
            }

            $tmp = substr($info, -4);
            if ($tmp == '.xml') {
                $info = &PEAR_PackageFile::fromPackageFile($info, $state);
            } elseif ($tmp == '.tar' || $tmp == '.tgz') {
                $info = &PEAR_PackageFile::fromTgzFile($info, $state);
            } else {
                $fp   = fopen($info, 'r');
                $test = fread($fp, 5);
                fclose($fp);
                if ($test == '<?xml') {
                    $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                } else {
                    $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                }
            }

            return $info;
        }

        $info = PEAR::raiseError("Cannot open '$info' for parsing");
        return $info;
    }
}


<?php
/**
 * Коллекция сущностей
 *
 * @version ${product.version}
 *
 * @copyright 2013, Михаил Красильников <m.krasilnikov@yandex.ru>
 * @license http://www.gnu.org/licenses/gpl.txt	GPL License 3
 * @author Михаил Красильников <m.krasilnikov@yandex.ru>
 *
 * Данная программа является свободным программным обеспечением. Вы
 * вправе распространять ее и/или модифицировать в соответствии с
 * условиями версии 3 либо (по вашему выбору) с условиями более поздней
 * версии Стандартной Общественной Лицензии GNU, опубликованной Free
 * Software Foundation.
 *
 * Мы распространяем эту программу в надежде на то, что она будет вам
 * полезной, однако НЕ ПРЕДОСТАВЛЯЕМ НА НЕЕ НИКАКИХ ГАРАНТИЙ, в том
 * числе ГАРАНТИИ ТОВАРНОГО СОСТОЯНИЯ ПРИ ПРОДАЖЕ и ПРИГОДНОСТИ ДЛЯ
 * ИСПОЛЬЗОВАНИЯ В КОНКРЕТНЫХ ЦЕЛЯХ. Для получения более подробной
 * информации ознакомьтесь со Стандартной Общественной Лицензией GNU.
 *
 * Вы должны были получить копию Стандартной Общественной Лицензии
 * GNU с этой программой. Если Вы ее не получили, смотрите документ на
 * <http://www.gnu.org/licenses/>
 *
 * @package ORM
 */

/**
 * Коллекция сущностей
 *
 * @package ORM
 * @since 3.00
 */
class ORM_Entity_Collection extends SplObjectStorage
{
    /**
     * Очищает коллекцию, удаляя все объекты
     */
    public function clear()
    {
        parent::rewind();
        while (parent::valid())
        {
            $this->detach(parent::current());
        }
    }

    /**
     * Возвращает true если в коллекции содержится указанный объект или объект с указанным ID
     *
     * @param ORM_Entity|int $entity
     * @return bool
     */
    public function contains($entity)
    {
        if ($entity instanceof ORM_Entity)
        {
            if ($entity->getEntityState() == ORM_Entity::IS_DELETED)
            {
                return false;
            }
            return parent::contains($entity);
        }
        else
        {
            $id = $entity;
            $this->rewind();
            while ($this->valid())
            {
                $entity = $this->current();
                if ($entity->getPrimaryKey() == $id)
                {
                    return true;
                }
                $this->next();
            }
            return false;
        }
    }

    /**
     * Возвращает количество объектов в коллекции
     *
     * Объекты со статусом IS_DELETED при подсчёте не учитываются
     *
     * @return int
     */
    public function count()
    {
        $count = 0;
        foreach ($this as $entity)
        {
            /** @var ORM_Entity $entity */
            if ($entity->getEntityState() != ORM_Entity::IS_DELETED)
            {
                $count++;
            }
        }
        return $count;
    }

    /**
     * Перемещает внутренний указатель к следующему объекту
     *
     * Объекты со статусом IS_DELETED пропускаются
     *
     * @return void
     */
    public function next()
    {
        do
        {
            parent::next();
        }
        while ($this->valid() && $this->isCurrentEntityDeleted());
    }

    /**
     * Перемещает внутренний указатель к началу списка
     *
     * Объекты со статусом IS_DELETED пропускаются
     *
     * @return void
     */
    public function rewind()
    {
        parent::rewind();
        if ($this->valid() && $this->isCurrentEntityDeleted())
        {
            $this->next();
        }
    }

    /**
     * Возвращает объект по объекту (да, по самому себе :) или его индексу
     *
     * @param int|object $offset
     *
     * @throws OutOfBoundsException
     *
     * @return ORM_Entity
     */
    public function offsetGet($offset)
    {
        if (is_object($offset))
        {
            return parent::offsetGet($offset);
        }

        if (!$this->valid() || $this->key() > $offset)
        {
            $this->rewind();
        }
        while ($this->key() < $offset && $this->valid())
        {
            $this->next();
        }
        if ($this->valid())
        {
            return $this->current();
        }
        else
        {
            throw new OutOfBoundsException(sprintf('Invalid index "%s"', $offset));
        }
    }

    /**
     * Возвращает true если текущая сущность помечена как удалённая
     *
     * @return bool
     */
    private function isCurrentEntityDeleted()
    {
        /** @var ORM_Entity $entity */
        $entity = $this->current();
        return $entity->getEntityState() == ORM_Entity::IS_DELETED;
    }
}


<?php
/*
 * Copyright (c) 2014 David Negrier
 *
 * See the file LICENSE.txt for copying permission.
 */

namespace Mouf\Utils\Common\Doctrine\Cache;

use Mouf\Utils\Cache\CacheInterface;
use Doctrine\Common\Cache\Cache;
use Doctrine\Common\Cache\CacheProvider;

/**
 * This class is an adapter that turns a Doctrine cache into a Mouf cache.
 */
class DoctrineCacheAdapter implements CacheInterface {

	private $doctrineCache;

	public function __construct(Cache $doctrineCache) {
		$this->doctrineCache = $doctrineCache;
	}

	/**
	 * (non-PHPdoc)
	 * @see \Mouf\Utils\Cache\CacheInterface::get()
	 */
	function get($key) {
		// Note: on miss, we return null, not false.
		$result = $this->doctrineCache->fetch($key);
		if ($result == false) {
			if ($this->doctrineCache->has($key)) {
				return false;
			} else {
				return null;
			}
		} else {
			return $result;
		}
	}

	/**
	 * (non-PHPdoc)
	 * @see \Mouf\Utils\Cache\CacheInterface::set()
	 */
	function set($key, $value, $timeToLive = null) {
		$this->doctrineCache->save($key, $value, $timeToLive);
	}

	/**
	 * (non-PHPdoc)
	 * @see \Mouf\Utils\Cache\CacheInterface::purge()
	 */
	function purge($key) {
		$this->doctrineCache->delete($key);
	}

	/**
	 * (non-PHPdoc)
	 * @see \Mouf\Utils\Cache\CacheInterface::purgeAll()
	 */
	function purgeAll() {
		if ($this->doctrineCache instanceof CacheProvider) {
			$this->doctrineCache->deleteAll();
		} else {
			$this->doctrineCache->delete("*");
		}
	}
}


<?php

namespace Soluble\Normalist\Driver;

use Soluble\Schema\Source;
use Zend\Db\Adapter\Adapter;
use Zend\Config\Writer;

class ZeroConfDriver implements DriverInterface
{
    /**
     * @var Source\AbstractSchemaSource
     */
    protected $metadata;

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

    /**
     *
     * @var array
     */
    protected $default_options = [
        'alias' => 'default',
        'path' => null,
        'version' => 'latest',
        'schema' => null,
        'permissions' => 0666
    ];

    /**
     *
     * @var array
     */
    protected static $metadataCache = [];

    /**
     * Underlying database adapter
     * @var Adapter
     */
    protected $adapter;

    /**
     * Construct a new Zero configuration driver
     *
     * $params allows you to specify the
     *   path    : where to store the model definition (default to sys_get_temp_dir())
     *   alias   : the alias to use when using multiple schemas, default: 'default'
     *   version : the version to use, default to 'latest'
     *   schema  : the database schema name, default to current adapter connection
     *   permissions: by default the model file is created with permission 0666
     *
     *
     * @param Adapter $adapter
     * @param array|Traversable $params [alias,path,version]
     * @throws Exception\ModelPathNotFoundException
     * @throws Exception\InvalidArgumentException
     */
    public function __construct(Adapter $adapter, $params = [])
    {
        $this->setDbAdapter($adapter);

        if (!is_array($params) && !$params instanceof \Traversable) {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' $params parameter expects an array or Traversable object');
        }

        $this->params = array_merge($this->default_options, (array) $params);
        if ($this->params['path'] == '') {
            $this->params['path'] = sys_get_temp_dir();
        }
        if (!is_dir($this->params['path'])) {
            $path = (string) $this->params['path'];
            throw new Exception\ModelPathNotFoundException(__METHOD__ . " Model directory not found '" . $path . "'");
        }
        $this->checkParams();
    }

    /**
     * Checks model configuration params
     * @throws Exception\InvalidArgumentException
     *
     */
    protected function checkParams()
    {
        if (!is_string($this->params['alias']) || trim($this->params['alias']) == '') {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' $params["alias"] parameter expects valid string');
        }
        if ($this->params['schema'] !== null &&
                (!is_string($this->params['schema']) || trim($this->params['schema']) == '')) {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' $params["schema"] parameter expects valid string');
        }
        if (!is_scalar($this->params['version']) || trim($this->params['version']) == '') {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' $params["version"] parameter expects valid scalar value');
        }
        if (!is_string($this->params['path']) || trim($this->params['path']) == '') {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' $params["path"] parameter expects valid string value');
        }
        if ($this->params['permissions'] != '' && !is_scalar($this->params['permissions'])) {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' $params["permission"] parameter expects string|interger|octal value');
        }
    }

    /**
     * Return models configuration file
     * @return string
     */
    public function getModelsConfigFile()
    {
        $o = $this->params;
        $file = $o['path'] . DIRECTORY_SEPARATOR . 'normalist_zeroconf_cache_' . $o['alias'] . '_' . $o['version'] . '.php';
        return $file;
    }

    /**
     * Get models definition according to options
     *
     * @throws Exception\ModelFileNotFoundException
     * @throws Exception\ModelFileCorruptedException
     * @return array
     */
    public function getModelsDefinition()
    {
        $file = $this->getModelsConfigFile();
        if (!file_exists($file) || !is_readable($file)) {
            throw new Exception\ModelFileNotFoundException(__METHOD__ . " Model configuration file '$file' does not exists or not readable");
        }

        if (defined('HHVM_VERSION')) {
            // As an 'evil' workaround, waiting for hhvm to comply
            // see https://github.com/facebook/hhvm/issues/1447
            $definition = false;
            $file_content = file_get_contents($file);
            $file_content = trim(str_replace('<?php', '', $file_content));
            $file_content = trim(str_replace('return array(', '$definition = array(', $file_content));
            eval($file_content);
        } else {
            $definition = include $file;
        }

        if (!$definition) {
            throw new Exception\ModelFileCorruptedException(__METHOD__ . " Model configuration file '$file' cannot be included");
        }
        if (!is_array($definition)) {
            throw new Exception\ModelFileCorruptedException(__METHOD__ . " Model configuration file '$file' was included but is not a valid array");
        }

        return $definition;
    }

    /**
     * Save model definition
     *
     * @throws Exception\ModelFileNotWritableException
     * @param array $models_definition
     * @return DriverInterface
     */
    protected function saveModelsDefinition(array $models_definition)
    {
        $file = $this->getModelsConfigFile();
        if (file_exists($file) && !is_writable($file)) {
            throw new Exception\ModelFileNotWritableException(__METHOD__ . "Model configuration file '$file' cannot be overwritten, not writable.");
        }

        //$config = new Config($models_defintion, true);
        $writer = new Writer\PhpArray();
        $models_definition['normalist'] = ['model_version' => Metadata\NormalistModels::VERSION];
        $writer->toFile($file, $models_definition, $exclusiveLock = true);
        $perms = $this->params['permissions'];
        if ($perms != '') {
            if (decoct(octdec($perms)) == $perms) {
                $perms = octdec($perms);
            }
            chmod($file, $perms);
        }
        return $this;
    }

    /**
     * Set underlying database adapter
     *
     * @param Adapter $adapter
     * @return DriverInterface
     */
    protected function setDbAdapter(Adapter $adapter)
    {
        $this->adapter = $adapter;
        return $this;
    }

    /**
     * Get underlying database adapter
     *
     * @return Adapter
     */
    public function getDbAdapter()
    {
        return $this->adapter;
    }

    /**
     * Get internal metadata reader
     *
     * @return Source\AbstractSchemaSource
     */
    public function getMetadata()
    {
        $cache_key = md5(serialize($this->params));
        if (!array_key_exists($cache_key, self::$metadataCache)) {
            if ($this->metadata === null) {
                self::$metadataCache[$cache_key] = $this->getDefaultMetadata();
            } else {
                self::$metadataCache[$cache_key] = $this->metadata;
            }
        }
        return self::$metadataCache[$cache_key];
    }

    /**
     *
     * @return ZeroConfDriver
     */
    public function clearMetadataCache()
    {
        self::$metadataCache = [];
        return $this;
    }

    /**
     *
     * @return Metadata\NormalistModels
     */
    protected function getDefaultMetadata()
    {
        try {
            $model_definition = $this->getModelsDefinition();
        } catch (Exception\ExceptionInterface $e) {
            // means model definition does not exists
            // lets load it from the current connection
            if ($this->params['schema'] == '') {
                $schema = null;
            } else {
                $schema = $this->params['schema'];
            }
            $conn = $this->adapter->getDriver()->getConnection()->getResource();
            $md = new Source\MysqlInformationSchema($conn, $schema);
            $model_definition = (array) $md->getSchemaConfig();

            // For later use we save the models definition
            $this->saveModelsDefinition($model_definition);
        }
        return new Metadata\NormalistModels($model_definition);
    }

    /**
     * Set internal metadata reader
     *
     * @param Source\AbstractSchemaSource $metadata
     * @return ZeroConfDriver
     */
    public function setMetadata(Source\AbstractSchemaSource $metadata)
    {
        $this->metadata = $metadata;
        return $this;
    }
}


<?php

use Delatbabel\Keylists\Models\Keytype;
use Delatbabel\Keylists\Models\Keyvalue;
use Illuminate\Database\Seeder;

class KeyListsCountriesSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
        // Create a keytype for country codes.
        //
        /** @var Keytype $keytype */
        $keytype = Keytype::create([
            'name'          => 'country_dialling',
            'description'   => 'Country Dialling Codes',
            'created_by'    => 'loader',
            'updated_by'    => 'loader',
        ]);

        // Read all of the country data from the supplied data file.
        $file = fopen(base_path('vendor') . '/delatbabel/keylists/database/data/country_dialling_codes.csv', 'rb');
        while ($line = fgetcsv($file)) {
            list($id, $country_name, $country_code, $country_iso, $country_iso3) = $line;

            if (! is_numeric($id)) {
                continue;
            }

            try {
                Keyvalue::create([
                    'keytype_id'    => $keytype->id,
                    'keyvalue'      => $country_iso,
                    'keyname'       => $country_name,
                    'extended_data' => [
                        'dialling_code'     => $country_code,
                        'iso3'              => $country_iso3,
                    ]
                ]);
            } catch (\Exception $e) {

                // There are regions with duplicate ISO codes that match their parent update
                Keyvalue::create([
                    'keytype_id'    => $keytype->id,
                    'keyvalue'      => $country_iso . '-' . $id,
                    'keyname'       => $country_name,
                    'extended_data' => [
                        'dialling_code'     => $country_code,
                        'iso3'              => $country_iso3,
                    ]
                ]);
            }
        }
    }
}


<?php
    /**
     * Bu Dosya AnonymFramework'e ait bir dosyadır.
     *
     * @author vahitserifsaglam <vahit.serif119@gmail.com>
     * @see http://gemframework.com
     *
     */

    namespace Anonym\Components\Crypt;

    /**
     * Class Crypter
     * @package Anonym\Components\Crypt
     */
    class Crypter
    {

        /**
         * @var CrypterEncodeableInterface
         */
        private $crypter;

        /**
         *  Sınııf başlatır ve şifreleyici olarak ön tanımlı olarak atananı kullanır
         *
         *
         */
        public function __construct()
        {
            $this->useDefaultCrypter();
        }

        /**
         * Default olarak AnonymCrypt sınıfı eklenir
         */
        private function useDefaultCrypter()
        {
            $this->setCrypter( new AnonymCrypt());
        }
        /**
         * Veriyi şifreler
         *
         * @param string $encode
         * @return string
         */
        public function encode($encode = ''){
            $crypter = $this->getCrypter();

            if($crypter instanceof CrypterEncodeableInterface){
                return $crypter->encode($encode);
            }else{
                return false;
            }
        }

        /**
         * Şifrelenmiş veriyi çözer
         *
         * @param string $decode
         * @return string
         */
        public function decode($decode = ''){
            $crypter = $this->getCrypter();

            if($crypter instanceof CrypterDecodeableInterface){
                return $crypter->decode($decode);
            }else{
                return false;
            }
        }

        /**
         * @return CrypterEncodeableInterface
         */
        public function getCrypter()
        {
            return $this->crypter;
        }

        /**
         * @param CrypterEncodeableInterface $crypter
         * @return Crypter
         */
        public function setCrypter($crypter)
        {
            $this->crypter = $crypter;

            return $this;
        }
    }


<?php

/*
 * This file is part of vaibhavpandeyvpz/katora package.
 *
 * (c) Vaibhav Pandey <contact@vaibhavpandey.com>
 *
 * This source file is subject to the MIT license that is bundled with this source code in the LICENSE file.
 */

namespace Katora;

use Psr\Container\ContainerInterface;

/**
 * Class Container
 * @package Katora
 */
class Container implements ContainerInterface, \ArrayAccess
{
    /**
     * @var array
     */
    protected $entries;

    /**
     * Container constructor.
     * @param array $entries
     */
    public function __construct(array $entries = array())
    {
        $this->entries = $entries;
    }

    // <editor-fold desc="Property access">

    /**
     * @param string $name
     * @return mixed
     */
    public function __get($name)
    {
        return $this->get($name);
    }

    /**
     * @param string $name
     * @return bool
     */
    public function __isset($name)
    {
        return $this->has($name);
    }

    /**
     * @param string $name
     * @param mixed $value
     */
    public function __set($name, $value)
    {
        $this->set($name, $value);
    }

    /**
     * @param string $name
     */
    public function __unset($name)
    {
    }

    // </editor-fold>

    /**
     * {@inheritdoc}
     */
    public function get($id)
    {
        if ($this->has($id)) {
            $entry = $this->entries[$id];
            if (is_callable($entry)) {
                $entry = call_user_func($entry, $this);
            }
            return $entry;
        }
        throw new NotFoundException("Service with ID '$id' not found.");
    }

    /**
     * {@inheritdoc}
     */
    public function has($id)
    {
        if (is_string($id)) {
            return isset($this->entries[$id]);
        }
        throw new ContainerException(sprintf(
            'Service ID must be a string, %s given.',
            is_scalar($id) ? gettype($id) : get_class($id)
        ));
    }

    /**
     * @param ServiceProviderInterface $provider
     * @return static
     */
    public function install(ServiceProviderInterface $provider)
    {
        $provider->provide($this);
        return $this;
    }

    // <editor-fold desc="Array access">

    /**
     * {@inheritdoc}
     */
    public function offsetExists($offset)
    {
        return $this->has($offset);
    }

    /**
     * {@inheritdoc}
     */
    public function offsetGet($offset)
    {
        return $this->get($offset);
    }

    /**
     * {@inheritdoc}
     */
    public function offsetSet($offset, $value)
    {
        return $this->set($offset, $value);
    }

    /**
     * {@inheritdoc}
     */
    public function offsetUnset($offset)
    {
    }

    // </editor-fold>

    /**
     * @param callable $entry
     * @return callable
     */
    public function raw($entry)
    {
        return function () use ($entry) {
            return $entry;
        };
    }

    /**
     * @param string $id
     * @param mixed $entry
     * @return static
     */
    public function set($id, $entry)
    {
        if (is_string($id)) {
            $this->entries[$id] = $entry;
            return $this;
        }
        throw new ContainerException(sprintf(
            'Service ID must be a string, %s given.',
            is_scalar($id) ? gettype($id) : get_class($id)
        ));
    }

    /**
     * @param callable $entry
     * @return callable
     */
    public function share($entry)
    {
        return function ($container) use ($entry) {
            static $called = false, $resolved;
            if (true !== $called) {
                $resolved = call_user_func($entry, $container);
                $called = true;
            }
            return $resolved;
        };
    }
}


<?php

namespace Orbt\StyleMirror\Css;

use Orbt\ResourceMirror\Resource\Collection;
use Orbt\ResourceMirror\Resource\LocalResource;
use Orbt\StyleMirror\Resource\CssResource;
use Orbt\ResourceMirror\Resource\MaterializedResource;
use Orbt\ResourceMirror\ResourceMirror;

/**
 * CSS aggregator service.
 */
class Aggregator
{
    /**
     * @var ResourceMirror
     */
    protected $mirror;

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

    /**
     * Constructs an aggregator.
     * @param ResourceMirror $mirror
     * @param string $prefix
     */
    public function __construct($mirror, $prefix = 'style_')
    {
        $this->mirror = $mirror;
        $this->prefix = $prefix;
    }

    /**
     * Aggregates a collection of CSS resources.
     *
     * @param Collection $collection
     * @return LocalResource
     */
    public function aggregate($collection)
    {
        // Ensure the collection is materialized.
        $collection = $this->mirror->materializeCollection($collection);

        // Create aggregate collection to accumulate style sheets.
        $aggregate = new StyleAggregate();
        foreach ($collection as $resource) {
            if ($resource instanceof MaterializedResource) {
                $internalResource = $resource->getResource();
                $mediaType = 'all';
                if ($internalResource instanceof CssResource) {
                    $mediaType = $internalResource->getMediaType();
                }
                $aggregate->addStyle($resource, $mediaType);
            }
        }

        // Create resource with the aggregate style sheet.
        $data = $aggregate->getAggregateStyle();
        $hash = sha1($data);
        $file = $this->prefix.$hash.'.css';
        $resource = new LocalResource($file, $data);
        return $resource;
    }
}


<?php namespace alct\noapi;

class NoAPI
{
    public function twitter($query)
    {
        return (new Twitter)->twitter($query);
    }

    /**
     * Download and return a resource.
     *
     * @param string $url URL of the target page
     *
     * @return string|bool false on error
     */
    public static function curl($url)
    {
        $req = curl_init();

        $opt = [
            CURLOPT_AUTOREFERER    => true,
            CURLOPT_COOKIEJAR      => tempnam(sys_get_temp_dir(), 'curl'),
            CURLOPT_FAILONERROR    => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HEADER         => true,
            CURLOPT_HTTPHEADER     => ['DNT: 1', 'Accept-Language: en-us,en;q=0.5'],
            CURLOPT_MAXREDIRS      => 5,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_URL            => $url,
            CURLOPT_USERAGENT      => 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0',
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_TIMEOUT        => 10,
        ];

        curl_setopt_array($req, $opt);

        if (! $res = curl_exec($req)) return false;

        curl_close($req);

        // mb_convert_encoding is used to avoid encoding issues related to DOMDocument::loadHTML
        // see https://secure.php.net/manual/en/domdocument.loadhtml.php#52251
        return mb_convert_encoding($res, 'HTML-ENTITIES', 'UTF-8');
    }

    /**
     * Create local copy of remote images.
     *
     * Hotlinking third party content raises privacy and security concerns. This
     * method allows for easy copying of remote images.
     *
     * Copying remote content raises other kind of security concerns, we
     * mitigate the risks by : checking the mime type against a predefined set ;
     * ignoring the original file name, extension and metadata ; enforcing part
     * of the path (prepending "noapi_" to the file name).
     *
     * @param string $url       URL of the remote image
     * @param string $filename  name of the target image
     * @param string $directory target directory without a ending slash
     * @param bool   $overwrite true to overwrite existing image
     *
     * @return string|bool false on error
     */
    public static function imageProxy($url, $filename, $directory, $overwrite = null)
    {
        $allowedmimetype = [ 'image/gif', 'image/jpeg', 'image/png', 'image/x-icon' ];

        $localpath = $directory . '/noapi_' . $filename;

        if (! $overwrite && file_exists($localpath)) return $localpath;

        $image = file_get_contents($url);
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        $mimetype = $finfo->buffer($image);

        if (! in_array($mimetype, $allowedmimetype)) return false;

        if (file_put_contents($localpath, $image) === false) return false;

        return $localpath;
    }
}


<?php

namespace Reaction\Validators;

use Reaction;
use Reaction\Base\Component;
use Reaction\Exceptions\NotSupportedException;
use Reaction\I18n\I18N;
use function Reaction\Promise\allInOrder;
use Reaction\Promise\ExtendedPromiseInterface;

/**
 * Validator is the base class for all validators.
 *
 * Child classes should override the [[validateValue()]] and/or [[validateAttribute()]] methods to provide the actual
 * logic of performing data validation. Child classes may also override [[clientValidateAttribute()]]
 * to provide client-side validation support.
 *
 * Validator declares a set of [[builtInValidators|built-in validators]] which can
 * be referenced using short names. They are listed as follows:
 *
 * - `boolean`: [[BooleanValidator]]
 * - `captcha`: [[\yii\captcha\CaptchaValidator]]
 * - `compare`: [[CompareValidator]]
 * - `date`: [[DateValidator]]
 * - `datetime`: [[DateValidator]]
 * - `time`: [[DateValidator]]
 * - `default`: [[DefaultValueValidator]]
 * - `double`: [[NumberValidator]]
 * - `each`: [[EachValidator]]
 * - `email`: [[EmailValidator]]
 * - `exist`: [[ExistValidator]]
 * - `file`: [[FileValidator]]
 * - `filter`: [[FilterValidator]]
 * - `image`: [[ImageValidator]]
 * - `in`: [[RangeValidator]]
 * - `integer`: [[NumberValidator]]
 * - `match`: [[RegularExpressionValidator]]
 * - `required`: [[RequiredValidator]]
 * - `safe`: [[SafeValidator]]
 * - `string`: [[StringValidator]]
 * - `trim`: [[FilterValidator]]
 * - `unique`: [[UniqueValidator]]
 * - `url`: [[UrlValidator]]
 * - `ip`: [[IpValidator]]
 *
 * For more details and usage information on Validator, see the [guide article on validators](guide:input-validation).
 *
 * @property array $attributeNames Attribute names. This property is read-only.
 *
 * Borrowed from yii2
 */
class Validator extends Component
{
    /**
     * @var array list of built-in validators (name => class or configuration)
     */
    public static $builtInValidators = [
        'boolean' => 'yii\validators\BooleanValidator',
        'captcha' => 'yii\captcha\CaptchaValidator',
        'compare' => 'yii\validators\CompareValidator',
        'date' => 'yii\validators\DateValidator',
        'datetime' => [
            'class' => 'yii\validators\DateValidator',
            'type' => DateValidator::TYPE_DATETIME,
        ],
        'time' => [
            'class' => 'yii\validators\DateValidator',
            'type' => DateValidator::TYPE_TIME,
        ],
        'default' => 'yii\validators\DefaultValueValidator',
        'double' => 'yii\validators\NumberValidator',
        'each' => 'yii\validators\EachValidator',
        'email' => 'yii\validators\EmailValidator',
        'exist' => 'yii\validators\ExistValidator',
        'file' => 'yii\validators\FileValidator',
        'filter' => 'yii\validators\FilterValidator',
        'image' => 'yii\validators\ImageValidator',
        'in' => 'yii\validators\RangeValidator',
        'integer' => [
            'class' => 'yii\validators\NumberValidator',
            'integerOnly' => true,
        ],
        'match' => 'yii\validators\RegularExpressionValidator',
        'number' => 'yii\validators\NumberValidator',
        'required' => 'yii\validators\RequiredValidator',
        'safe' => 'yii\validators\SafeValidator',
        'string' => 'yii\validators\StringValidator',
        'trim' => [
            'class' => 'yii\validators\FilterValidator',
            'filter' => 'trim',
            'skipOnArray' => true,
        ],
        'unique' => 'yii\validators\UniqueValidator',
        'url' => 'yii\validators\UrlValidator',
        'ip' => 'yii\validators\IpValidator',
    ];
    /**
     * @var array|string attributes to be validated by this validator. For multiple attributes,
     * please specify them as an array; for single attribute, you may use either a string or an array.
     */
    public $attributes = [];
    /**
     * @var string the user-defined error message. It may contain the following placeholders which
     * will be replaced accordingly by the validator:
     *
     * - `{attribute}`: the label of the attribute being validated
     * - `{value}`: the value of the attribute being validated
     *
     * Note that some validators may introduce other properties for error messages used when specific
     * validation conditions are not met. Please refer to individual class API documentation for details
     * about these properties. By convention, this property represents the primary error message
     * used when the most important validation condition is not met.
     */
    public $message;
    /**
     * @var array|string scenarios that the validator can be applied to. For multiple scenarios,
     * please specify them as an array; for single scenario, you may use either a string or an array.
     */
    public $on = [];
    /**
     * @var array|string scenarios that the validator should not be applied to. For multiple scenarios,
     * please specify them as an array; for single scenario, you may use either a string or an array.
     */
    public $except = [];
    /**
     * @var bool whether this validation rule should be skipped if the attribute being validated
     * already has some validation error according to some previous rules. Defaults to true.
     */
    public $skipOnError = true;
    /**
     * @var bool whether this validation rule should be skipped if the attribute value
     * is null or an empty string.
     */
    public $skipOnEmpty = true;
    /**
     * @var bool whether to enable client-side validation for this validator.
     * The actual client-side validation is done via the JavaScript code returned
     * by [[clientValidateAttribute()]]. If that method returns null, even if this property
     * is true, no client-side validation will be done by this validator.
     */
    public $enableClientValidation = true;
    /**
     * @var callable a PHP callable that replaces the default implementation of [[isEmpty()]].
     * If not set, [[isEmpty()]] will be used to check if a value is empty. The signature
     * of the callable should be `function ($value)` which returns a boolean indicating
     * whether the value is empty.
     */
    public $isEmpty;
    /**
     * @var callable a PHP callable whose return value determines whether this validator should be applied.
     * The signature of the callable should be `function ($model, $attribute)`, where `$model` and `$attribute`
     * refer to the model and the attribute currently being validated. The callable should return a boolean value.
     *
     * This property is mainly provided to support conditional validation on the server-side.
     * If this property is not set, this validator will be always applied on the server-side.
     *
     * The following example will enable the validator only when the country currently selected is USA:
     *
     * ```php
     * function ($model) {
     *     return $model->country == Country::USA;
     * }
     * ```
     *
     * @see whenClient
     */
    public $when;
    /**
     * @var string a JavaScript function name whose return value determines whether this validator should be applied
     * on the client-side. The signature of the function should be `function (attribute, value)`, where
     * `attribute` is an object describing the attribute being validated (see [[clientValidateAttribute()]])
     * and `value` the current value of the attribute.
     *
     * This property is mainly provided to support conditional validation on the client-side.
     * If this property is not set, this validator will be always applied on the client-side.
     *
     * The following example will enable the validator only when the country currently selected is USA:
     *
     * ```javascript
     * function (attribute, value) {
     *     return $('#country').val() === 'USA';
     * }
     * ```
     *
     * @see when
     */
    public $whenClient;

    /**
     * Creates a validator object.
     * @param string|\Closure $type the validator type. This can be either:
     *  * a built-in validator name listed in [[builtInValidators]];
     *  * a method name of the model class;
     *  * an anonymous function;
     *  * a validator class name.
     * @param \Reaction\Base\Model $model the data model to be validated.
     * @param array|string $attributes list of attributes to be validated. This can be either an array of
     * the attribute names or a string of comma-separated attribute names.
     * @param array $params initial values to be applied to the validator properties.
     * @return Validator the validator
     */
    public static function createValidator($type, $model, $attributes, $params = [])
    {
        $params['attributes'] = $attributes;

        if ($type instanceof \Closure || ($model->hasMethod($type) && !isset(static::$builtInValidators[$type]))) {
            // method-based validator
            $params['class'] = __NAMESPACE__ . '\InlineValidator';
            $params['method'] = $type;
        } else {
            if (isset(static::$builtInValidators[$type])) {
                $type = static::$builtInValidators[$type];
            }
            if (is_array($type)) {
                $params = array_merge($type, $params);
            } else {
                $params['class'] = $type;
            }
        }

        return Reaction::create($params);
    }

    /**
     * {@inheritdoc}
     */
    public function init()
    {
        parent::init();
        $this->attributes = (array)$this->attributes;
        $this->on = (array)$this->on;
        $this->except = (array)$this->except;
    }

    /**
     * Validates the specified object.
     * @param \Reaction\Base\Model $model the data model being validated
     * @param array|null           $attributes the list of attributes to be validated.
     * Note that if an attribute is not associated with the validator - it will be
     * ignored. If this parameter is null, every attribute listed in [[attributes]] will be validated.
     * @return ExtendedPromiseInterface
     */
    public function validateAttributes($model, $attributes = null)
    {
        if (is_array($attributes)) {
            $newAttributes = [];
            $attributeNames = $this->getAttributeNames();
            foreach ($attributes as $attribute) {
                if (in_array($attribute, $attributeNames, true)) {
                    $newAttributes[] = $attribute;
                }
            }
            $attributes = $newAttributes;
        } else {
            $attributes = $this->getAttributeNames();
        }

        $promises = [];
        foreach ($attributes as $attribute) {
            $skip = $this->skipOnError && $model->hasErrors($attribute)
                || $this->skipOnEmpty && $this->isEmpty($model->$attribute);
            if (!$skip) {
                if ($this->when === null || call_user_func($this->when, $model, $attribute)) {
                    $promise = $this->validateAttribute($model, $attribute);
                    if ($promise !== null) {
                        $promises[] = $promise;
                    }
                }
            }
        }

        return allInOrder($promises)->then(function() { return true; });
    }

    /**
     * Validates a single attribute.
     * Child classes must implement this method to provide the actual validation logic.
     * @param \Reaction\Base\Model $model the data model to be validated
     * @param string               $attribute the name of the attribute to be validated.
     * @return ExtendedPromiseInterface|null Some validators may return a promise if DB or other async components used
     */
    public function validateAttribute($model, $attribute)
    {
        $result = $this->validateValue($model->$attribute);
        if ($result instanceof ExtendedPromiseInterface) {
            return $result->then(function($_result) use ($model, $attribute) {
                if (!empty($_result)) {
                    $this->addError($model, $attribute, $_result[0], $_result[1]);
                }
            });
        }
        if (!empty($result)) {
            $this->addError($model, $attribute, $result[0], $result[1]);
        }
        return null;
    }

    /**
     * Validates a given value.
     * You may use this method to validate a value out of the context of a data model.
     * @param mixed $value the data value to be validated.
     * @param string $error the error message to be returned, if the validation fails.
     * @return bool whether the data is valid.
     */
    public function validate($value, &$error = null)
    {
        $result = $this->validateValue($value);
        if (empty($result)) {
            return true;
        }

        list($message, $params) = $result;
        $params['attribute'] = Reaction::t('rct', 'the input value');
        if (is_array($value)) {
            $params['value'] = 'array()';
        } elseif (is_object($value)) {
            $params['value'] = 'object';
        } else {
            $params['value'] = $value;
        }
        $error = $this->formatMessage($message, $params);

        return false;
    }

    /**
     * Validates a value.
     * A validator class can implement this method to support data validation out of the context of a data model.
     * @param mixed $value the data value to be validated.
     * @return array|null|ExtendedPromiseInterface the error message and the array of parameters to be inserted into the error message.
     * ```php
     * if (!$valid) {
     *     return [$this->message, [
     *         'param1' => $this->param1,
     *         'formattedLimit' => Yii::$app->formatter->asShortSize($this->getSizeLimit()),
     *         'mimeTypes' => implode(', ', $this->mimeTypes),
     *         'param4' => 'etc...',
     *     ]];
     * }
     *
     * return null;
     * Some validators may return a promise if DB or other async components used
     * ```
     * for this example `message` template can contain `{param1}`, `{formattedLimit}`, `{mimeTypes}`, `{param4}`
     *
     * Null should be returned if the data is valid.
     * @throws NotSupportedException if the validator does not supporting data validation without a model
     */
    protected function validateValue($value)
    {
        throw new NotSupportedException(get_class($this) . ' does not support validateValue().');
    }

    /**
     * Returns the JavaScript needed for performing client-side validation.
     *
     * Calls [[getClientOptions()]] to generate options array for client-side validation.
     *
     * You may override this method to return the JavaScript validation code if
     * the validator can support client-side validation.
     *
     * The following JavaScript variables are predefined and can be used in the validation code:
     *
     * - `attribute`: an object describing the the attribute being validated.
     * - `value`: the value being validated.
     * - `messages`: an array used to hold the validation error messages for the attribute.
     * - `deferred`: an array used to hold deferred objects for asynchronous validation
     * - `$form`: a jQuery object containing the form element
     *
     * The `attribute` object contains the following properties:
     * - `id`: a unique ID identifying the attribute (e.g. "loginform-username") in the form
     * - `name`: attribute name or expression (e.g. "[0]content" for tabular input)
     * - `container`: the jQuery selector of the container of the input field
     * - `input`: the jQuery selector of the input field under the context of the form
     * - `error`: the jQuery selector of the error tag under the context of the container
     * - `status`: status of the input field, 0: empty, not entered before, 1: validated, 2: pending validation, 3: validating
     *
     * @param \Reaction\Base\Model $model the data model being validated
     * @param string $attribute the name of the attribute to be validated.
     * @param \Reaction\Web\View $view the view object that is going to be used to render views or view files
     * containing a model form with this validator applied.
     * @return string|null the client-side validation script. Null if the validator does not support
     * client-side validation.
     * @see getClientOptions()
     * @see \yii\widgets\ActiveForm::enableClientValidation
     */
    public function clientValidateAttribute($model, $attribute, $view)
    {
        return null;
    }

    /**
     * Returns the client-side validation options.
     * This method is usually called from [[clientValidateAttribute()]]. You may override this method to modify options
     * that will be passed to the client-side validation.
     * @param \Reaction\Base\Model $model the model being validated
     * @param string $attribute the attribute name being validated
     * @return array the client-side validation options
     */
    public function getClientOptions($model, $attribute)
    {
        return [];
    }

    /**
     * Returns a value indicating whether the validator is active for the given scenario and attribute.
     *
     * A validator is active if
     *
     * - the validator's `on` property is empty, or
     * - the validator's `on` property contains the specified scenario
     *
     * @param string $scenario scenario name
     * @return bool whether the validator applies to the specified scenario.
     */
    public function isActive($scenario)
    {
        return !in_array($scenario, $this->except, true) && (empty($this->on) || in_array($scenario, $this->on, true));
    }

    /**
     * Adds an error about the specified attribute to the model object.
     * This is a helper method that performs message selection and internationalization.
     * @param \Reaction\Base\Model $model the data model being validated
     * @param string $attribute the attribute being validated
     * @param string $message the error message
     * @param array $params values for the placeholders in the error message
     */
    public function addError($model, $attribute, $message, $params = [])
    {
        $params['attribute'] = $model->getAttributeLabel($attribute);
        if (!isset($params['value'])) {
            $value = $model->$attribute;
            if (is_array($value)) {
                $params['value'] = 'array()';
            } elseif (is_object($value) && !method_exists($value, '__toString')) {
                $params['value'] = '(object)';
            } else {
                $params['value'] = $value;
            }
        }
        $model->addError($attribute, $this->formatMessage($message, $params));
    }

    /**
     * Checks if the given value is empty.
     * A value is considered empty if it is null, an empty array, or an empty string.
     * Note that this method is different from PHP empty(). It will return false when the value is 0.
     * @param mixed $value the value to be checked
     * @return bool whether the value is empty
     */
    public function isEmpty($value)
    {
        if ($this->isEmpty !== null) {
            return call_user_func($this->isEmpty, $value);
        }

        return $value === null || $value === [] || $value === '';
    }

    /**
     * Formats a message using the I18N, or simple strtr if `\Reaction::$app` is not available.
     * @param string $message
     * @param array $params
     * @return string
     */
    protected function formatMessage($message, $params)
    {
        // TODO: Add working i18n component
        /*if (\Reaction::$app !== null) {
            return \Reaction::$app->getI18n()->format($message, $params, \Reaction::$app->language);
        }*/

        $placeholders = [];
        foreach ((array)$params as $name => $value) {
            $placeholders['{' . $name . '}'] = $value;
        }

        return ($placeholders === []) ? $message : strtr($message, $placeholders);
    }

    /**
     * Returns cleaned attribute names without the `!` character at the beginning.
     * @return array attribute names.
     */
    public function getAttributeNames()
    {
        return array_map(function($attribute) {
            return ltrim($attribute, '!');
        }, $this->attributes);
    }
}