<?php
/**
 * SRI utils.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * SRI utils.
 *
 * @since 170211.63148 SRI utils.
 */
class Sri extends Classes\Core\Base\Core implements Interfaces\ByteConstants
{
    /**
     * Map.
     *
     * @since 170215.53419
     *
     * @type string
     */
    protected $map;

    /**
     * Map file.
     *
     * @since 170215.53419
     *
     * @type string
     */
    protected $map_file;

    /**
     * Map cache.
     *
     * @since 170215.53419
     *
     * @type string
     */
    protected $map_cache;

    /**
     * Map cache file.
     *
     * @since 170215.53419
     *
     * @type string
     */
    protected $map_cache_file;

    /**
     * Memcache enabled?
     *
     * @since 170215.53419
     *
     * @type bool
     */
    protected $memcache_enabled;

    /**
     * Cache max age.
     *
     * @since 170215.53419
     *
     * @type int Timestamp.
     */
    protected $cache_max_age;

    /**
     * Cache expires in.
     *
     * @since 170215.53419
     *
     * @type int Seconds.
     */
    protected $cache_expires_in;

    /**
     * Counter.
     *
     * @since 170215.53419
     *
     * @type int
     */
    protected static $content_checks;

    /**
     * Max checks.
     *
     * @since 170215.53419
     *
     * @type int
     */
    protected $max_content_checks;

    /**
     * Current scheme.
     *
     * @since 170215.53419
     *
     * @type string
     */
    protected $current_scheme;

    /**
     * Current host.
     *
     * @since 170215.53419
     *
     * @type string
     */
    protected $current_host;

    /**
     * Class constructor.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param Classes\App $App  Instance.
     * @param array       $args Constructor args.
     */
    public function __construct(Classes\App $App, array $args = [])
    {
        parent::__construct($App);

        $default_args = [
            // NOTE: This is an instance-based configuration option.
            // However, checks are counted statically across all instances.
            // So while it's possible to increase the max for your instance, when doing so,
            // please remember the counter is based on all checks that occur in a single process.
            'max_content_checks' => 2,

            // Maximum age of any cache entry.
            'cache_max_age'      => strtotime('-30 days'),
        ];
        $args += $default_args; // Merge defaults.

        if (!$this->App->Config->©fs_paths['©sris_dir']) {
            throw $this->c::issue('Missing SRIs directory.');
        } elseif (!$this->App->Config->©fs_paths['©cache_dir']) {
            throw $this->c::issue('Missing cache directory.');
        }
        $this->map_file           = $this->App->Config->©fs_paths['©sris_dir'].'/sris.json';
        $this->map_cache_file     = $this->App->Config->©fs_paths['©cache_dir'].'/sris/map.json';
        $this->memcache_enabled   = $this->c::memcacheEnabled();

        $time                     = time(); // Current time.
        $this->cache_max_age      = max(0, min($time, (int) $args['cache_max_age']));
        $this->cache_expires_in   = $time - $this->cache_max_age;

        static::$content_checks   = static::$content_checks ?? 0;
        $this->max_content_checks = (int) $args['max_content_checks'];

        $is_cli                   = $this->c::isCli();
        $this->current_scheme     = $is_cli ? '' : $this->c::currentScheme();
        $this->current_host       = $is_cli ? '' : $this->c::currentHost();
    }

    /**
     * Acquire SRI hash.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url URI to hash.
     *
     * @return string SRI hash, else empty string.
     */
    public function __invoke(string $url): string
    {
        if (!$url) { // URL is empty?
            return ''; // Stop here.
        } elseif ($this->isLocal($url)) {
            return ''; // Unnecessary.
        }
        $sha1 = sha1($url); // Key for lookups.

        // ↑ NOTE: The sha is based on the URL given.
        // It's important not to alter the scheme here.
        // `https://` files may serve slightly different content.
        // e.g., A dynamic script that alters paths based on scheme.
        // However, when using a map, `//` can be used to cover all schemes.

        // ↓ NOTE: The way in which parent checks occur.
        // Each parent check will result in additional parent checks.
        // i.e., It runs all the way up the ladder recursively.

        // ↓ NOTE: Remember the in-process cache variables by &reference.
        // i.e., `&$sri` and `&$p_sri` are an in-process cache of all checks.

        $p = $this->App->Parent; // Possibly a parent application.
        $p = $p ? $p->Utils->©Sri : null; // Shorter reference.

        if (($sri = &$this->checkProcess($url, $sha1)) !== null) {
            return $sri; // Via in-process cache of the SRI.
        } elseif ($p && ($p_sri = &$p->checkProcess($url, $sha1)) !== null) {
            return $p_sri; // Via parent in-process cache.
        }
        if (($sri = $this->checkMemcache($url, $sha1)) !== null) {
            return $sri; // Via memcache; avoids disk IO.
        } elseif ($p && ($p_sri = $p->checkMemcache($url, $sha1)) !== null) {
            return $p_sri; // Via parent memcache.
        }
        if (($sri = $this->checkMap($url, $sha1)) !== null) {
            $this->memcacheIt($url, $sha1, $sri);
            return $sri; // Via one read of the map file.
        } elseif ($p && ($p_sri = $p->checkMap($url, $sha1)) !== null) {
            $p->memcacheIt($url, $sha1, $p_sri);
            return $p_sri; // Via parent map file.
        }
        if (($sri = $this->checkMapCache($url, $sha1)) !== null) {
            $this->memcacheIt($url, $sha1, $sri);
            return $sri; // Via additional read of map cache file.
        } elseif ($p && ($p_sri = $p->checkMapCache($url, $sha1)) !== null) {
            $p->memcacheIt($url, $sha1, $p_sri);
            return $p_sri; // Via parent map cache file.
        }
        if (($sri = $this->checkContents($url, $sha1)) !== null) {
            $this->cacheIt($url, $sha1, $sri);
            return $sri; // First-time SHA.
        }
        return $sri = ''; // Not possible at this time.
    }

    /**
     * Checks for SRI in process.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     *
     * @return string|null SRI hash, else `null`.
     */
    public function &checkProcess(string $url, string $sha1)
    {
        if (is_string($sri = &$this->cacheGet('sris', $sha1))) {
            return $sri; // Cached this already.
        } else { // Set in-process cache to `null`.
            $sri = null; // Not in the cache.
            return $sri; // By reference.
        }
    }

    /**
     * Checks for SRI in memcache.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     *
     * @return string|null SRI hash, else `null`.
     */
    public function checkMemcache(string $url, string $sha1)
    {
        if (!$this->memcache_enabled) {
            return $sri = null; // Not possible.
        } elseif (is_string($sri = $this->c::memcacheGet('sris', $sha1))) {
            return $sri; // Ideal; this avoids disk IO.
        }
        return $sri = null; // Not in the cache.
    }

    /**
     * Checks for SRI in map.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     *
     * @return string|null SRI hash, else `null`.
     */
    public function checkMap(string $url, string $sha1)
    {
        $this->map = $this->getMap();

        if (isset($this->map[$url]['sri'])) {
            return $sri = (string) $this->map[$url]['sri'];
        }
        if (mb_strpos($url, '//') !== 0) { // Should check `//`?
            ${'//'} = preg_replace('/^https?\:/ui', '', $url);

            if (isset($this->map[${'//'}]['sri'])) {
                return $sri = (string) $this->map[${'//'}]['sri'];
            } // i.e., If a map entry covers all schemes.
        }
        return $sri = null; // Not in the map.
    }

    /**
     * Checks for SRI in map cache.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     *
     * @return string|null SRI hash, else `null`.
     */
    public function checkMapCache(string $url, string $sha1)
    {
        $this->map_cache = $this->getMapCache();

        if (isset($this->map_cache[$url]['sri']) && $this->map_cache[$url]['time'] >= $this->cache_max_age) {
            return $sri = (string) $this->map_cache[$url]['sri'];
        }
        if (mb_strpos($url, '//') !== 0) { // Should check `//`?
            ${'//'} = preg_replace('/^https?\:/ui', '', $url);

            if (isset($this->map_cache[${'//'}]['sri']) && $this->map_cache[${'//'}]['time'] >= $this->cache_max_age) {
                return $sri = (string) $this->map_cache[${'//'}]['sri'];
            } // i.e., If a map entry covers all schemes.
        }
        return $sri = null; // Not in the map.
    }

    /**
     * Check contents.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     *
     * @return string|null SRI hash, else `null`.
     */
    public function checkContents(string $url, string $sha1)
    {
        if (static::$content_checks >= $this->max_content_checks) {
            return $sri = null; // Not possible at this time.
        } // There is a limit on the number of checks per process.

        if (mb_stripos($url, '//') === 0) {
            $url = ($this->current_scheme ?: 'http').':'.$url;
        } // Because we must have a scheme to do a lookup.

        $args = [ // HTTP args.
            'max_con_secs'    => 2,
            'max_stream_secs' => 6,
            'max_stream_size' => $this::BYTES_IN_MB * 2,
        ]; // Most servers can download 1MB+ in this time.

        ++static::$content_checks; // Increment counter.
        $response = $this->c::remoteResponse('GET::'.$url, $args);

        if ($response->code !== 200) {
            return $sri = ''; // Unable to determine.
            // However, we do return an empty SRI in this case anyway.

            // NOTE: This may (at times) return an empty SRI whenever
            // there is a temporary connectivity issue that is resolved later.

            // Rationale: If we chose not to cache failed responses, that could result in HTTP
            // requests occurring over and over again, which is want we need to avoid at all costs.
            // Therefore, if it fails, game is over until clearing the cache or adding a new map entry.
        }
        return $sri = 'sha384-'.base64_encode(hash('sha384', $response->body, true));
    }

    /**
     * Cache the SRI hash.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     * @param string $sri  The SRI hash.
     *
     * @note The `$sri` is allowed to be empty.
     */
    public function cacheIt(string $url, string $sha1, string $sri)
    {
        $this->memcacheIt($url, $sha1, $sri);
        $this->mapCacheIt($url, $sha1, $sri);
    }

    /**
     * Memcache the SRI hash.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     * @param string $sri  The SRI hash.
     *
     * @note The `$sri` is allowed to be empty.
     */
    public function memcacheIt(string $url, string $sha1, string $sri)
    {
        if ($this->memcache_enabled) {
            $this->c::memcacheSet('sris', $sha1, $sri, $this->cache_expires_in);
        } // This is, by far, the fastest way.
    }

    /**
     * Map-cache the SRI hash.
     *
     * @since 170211.63148 SRI utils.
     *
     * @param string $url  URL to get SRI for.
     * @param string $sha1 SHA-1 hash of URL.
     * @param string $sri  The SRI hash.
     *
     * @note The `$sri` is allowed to be empty.
     */
    public function mapCacheIt(string $url, string $sha1, string $sri)
    {
        $this->map_cache       = $this->getMapCache();
        $this->map_cache[$url] = ['time' => time(), 'sri' => $sri];

        if (mb_strpos($url, '//') === 0) {
            unset($this->map_cache['http:'.$url]);
            unset($this->map_cache['https:'.$url]);
        } // Don't need all schemes, `//` will suffice.

        foreach ($this->map_cache as $_url => $_entry) {
            if ($_entry['time'] < $this->cache_max_age) {
                unset($this->map_cache[$_url]);
            } // Purges stale cache entries.
        } // unset($_url, $_entry); // Housekeeping.

        $map_cache_dir   = dirname($this->map_cache_file);
        $transient_perms = $this->App->Config->©fs_permissions['©transient_dirs'];

        if (!is_dir($map_cache_dir)) {
            mkdir($map_cache_dir, $transient_perms, true);
        }
        file_put_contents($this->map_cache_file, json_encode($this->map_cache, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
    }

    /**
     * Get the SRIs map.
     *
     * @since 170215.53419 SRI utils.
     *
     * @return array Map of SRIs.
     */
    protected function &getMap(): array
    {
        if (!isset($this->map)) {
            $this->map = []; // Define.

            if (is_file($this->map_file)) {
                $this->map = file_get_contents($this->map_file);
                $this->map = json_decode($this->map, true);
                $this->map = is_array($this->map) ? $this->map : [];
            } // Only if file exists, otherwise empty array.
        }
        return $this->map;
    }

    /**
     * Get SRIs map cache.
     *
     * @since 170215.53419 SRI utils.
     *
     * @return array SRIs map cache.
     */
    protected function &getMapCache(): array
    {
        if (!isset($this->map_cache)) {
            $this->map_cache = []; // Define.

            if (is_file($this->map_cache_file)) {
                $this->map_cache = file_get_contents($this->map_cache_file);
                $this->map_cache = json_decode($this->map_cache, true);
                $this->map_cache = is_array($this->map_cache) ? $this->map_cache : [];
            } // Only if file exists, otherwise empty array.
        }
        return $this->map_cache;
    }

    /**
     * URL is local?
     *
     * @since 170215.53419 SRI utils.
     *
     * @param string $url URL to get SRI for.
     *
     * @return bool|null True if URL is local.
     */
    protected function isLocal(string $url)
    {
        if (mb_stripos($url, '//') === false) {
            return true; // Relative.
        } elseif ($this->current_host) {
            return mb_stripos($url, '//'.$this->current_host.'/') !== false;
        }
        return null; // Unable to determine.
    }
}


<?php
/**
 * Var utilities.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Var utilities.
 *
 * @since 160220 Initial release.
 */
class Varz extends Classes\Core\Base\Core implements Interfaces\VarConstants
{
    /**
     * Validate var.
     *
     * @since 160220 Initial release.
     *
     * @param string $var    Var.
     * @param bool   $strict Strict?
     *
     * @return bool True if var is valid.
     */
    public function isValid(string $var, bool $strict = true): bool
    {
        return (bool) preg_match($strict ? $this::VAR_STRICT_REGEX_VALID : $this::VAR_REGEX_VALID, $var);
    }

    /**
     * Convert var to name.
     *
     * @since 160220 Initial release.
     *
     * @param string $var Var.
     *
     * @return string Name; based on var.
     */
    public function toName(string $var): string
    {
        $name        = $var; // Initialize.
        $name        = preg_replace('/[^\p{L}\p{N}]+/u', ' ', $name);
        $name        = $this->c::mbUcWords($name);
        return $name = $this->c::mbTrim($name);
    }

    /**
     * Convert var to acronym.
     *
     * @since 160220 Initial release.
     *
     * @param string $var    Var.
     * @param bool   $strict Strict?
     *
     * @return string Acronym; based on var.
     */
    public function toAcronym(string $var, bool $strict = true): string
    {
        return $this->c::nameToAcronym($this->toName($var), $strict);
    }

    /**
     * Convert var to slug.
     *
     * @since 160220 Initial release.
     *
     * @param string $var    Var.
     * @param bool   $strict Strict?
     *
     * @return string Slug; based on var.
     */
    public function toSlug(string $var, bool $strict = true): string
    {
        $slug = $var; // Initialize.
        $slug = mb_strtolower($this->c::forceAscii($slug));
        $slug = preg_replace('/[^a-z0-9]+/u', '-', $slug);
        $slug = $this->c::mbTrim($slug, '', '-');

        if ($strict && $slug && !preg_match('/^[a-z]/u', $slug)) {
            $slug = 'x'.$slug; // Force `^[a-z]`.
        }
        return $slug;
    }

    /**
     * Convert var to camelCase.
     *
     * @since 170413.34876 Initial release.
     *
     * @param string $var    Var.
     * @param bool   $strict Strict?
     *
     * @return string camelCase; based on var.
     */
    public function toCamelCase(string $var, bool $strict = true): string
    {
        $var = mb_strtolower($this->c::forceAscii($var));
        $var = preg_replace('/[^a-z0-9]+/u', '_', $var);
        $var = $this->c::mbTrim($var, '', '_');

        if ($strict && $var && !preg_match('/^[a-z]/u', $var)) {
            $var = 'x'.$var; // Force `^[a-z]`.
        }
        return $camelCase = $var ? preg_replace_callback('/_(.)/u', function (array $m): string {
            return mb_strtoupper($m[1]); // e.g., `_x` becomes `X` for camelCase.
        }, $var) : $var; // Converts variable into camelCase variable.
    }
}


<?php

/*
 * This file is part of the Ivory Google Map package.
 *
 * (c) Eric GELOEN <geloen.eric@gmail.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Ivory\GoogleMap\Helper\Base;

use Ivory\GoogleMap\Base\Size;

/**
 * Size helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class SizeHelper
{
    /**
     * Renders a size.
     *
     * @param \Ivory\GoogleMap\Base\Size $size The size.
     *
     * @return string The JS output.
     */
    public function render(Size $size)
    {
        if ($size->hasUnits()) {
            return sprintf(
                '%s = new google.maps.Size(%s, %s, "%s", "%s");'.PHP_EOL,
                $size->getJavascriptVariable(),
                $size->getWidth(),
                $size->getHeight(),
                $size->getWidthUnit(),
                $size->getHeightUnit()
            );
        }

        return sprintf(
            '%s = new google.maps.Size(%s, %s);'.PHP_EOL,
            $size->getJavascriptVariable(),
            $size->getWidth(), $size->getHeight()
        );
    }
}


<?php
/**
 * Copyright (C) php-fn. See LICENSE file for license details.
 */
/** @noinspection PhpUndefinedClassConstantInspection */

namespace fn;

/**
 * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
 */
trait PropertiesReadWriteTrait
{
    /**
     * @var iterable
     */
    private $properties = [];

    /**
     * @param iterable $properties
     */
    private function initProperties(iterable $properties = null): void
    {
        if (defined('static::DEFAULT')) {
            $properties = $properties ?? [];
            if ($diff = array_diff(keys($properties), keys(static::DEFAULT))) {
                $diff = implode(',', $diff);
                fail\domain('magic properties (%s) are not defined in %s::DEFAULT', $diff, static::class);
            }
            $properties = merge(static::DEFAULT, $properties);
        }
        $properties === null || $this->properties = merge($this->properties, $properties);
    }

    /**
     * @param string $name
     * @param bool   $assert
     * @param mixed  ...$value
     *
     * @return $this|mixed
     */
    private function property(string $name, bool $assert, ...$value)
    {
        $has = hasKey($name, $this->properties);
        if ($assert) {
            $has || fail\domain('missing magic-property %s in %s', $name, static::class);
            if ($value) {
                $this->properties[$name] = $value[0];
                return $this;
            }
            return $this->properties[$name];
        }
        return $has;
    }

    /**
     * http://php.net/manual/language.oop5.overloading.php#object.isset
     *
     * @param string $name
     *
     * @return bool
     */
    public function __isset(string $name): bool
    {
        return $this->property($name, false);
    }

    /**
     * @see http://php.net/manual/language.oop5.overloading.php#object.get
     *
     * @param string $name
     *
     * @return mixed
     */
    public function __get(string $name)
    {
        return $this->property($name, true);
    }

    /**
     * @see http://php.net/manual/language.oop5.overloading.php#object.set
     *
     * @param string $name
     * @param mixed  $value
     */
    public function __set(string $name, $value): void
    {
        $this->property($name, true, $value);
    }

    /**
     * http://php.net/manual/language.oop5.overloading.php#object.unset
     *
     * @param string $name
     */
    public function __unset(string $name): void
    {
        $this->property($name, false) && $this->property($name, true, null);
    }
}


<?php
//------------------------
//· 上传类
//-------------------------
namespace denha;

/**
 * 我的文件上传类
 *
 * 未完成的功能：
 * 1.对目标目录是否存在的判断
 * 2.如果上传时出现重名，自动重命名
 *
 * @author M.Q
 */
class Upload
{
    /**
     * PHP上传类upload.php上传文件的信息，此值由构造函数取得，如果上传文件失败或出错或未上传，则此值为false
     *
     * @var array
     */
    public $file = false;
    public $path; //保存路径
    public $type; //保存类型
    public $size; //附件大小
    public $error = false; //错误提示;
    /**
     * 构造函数：取得上传文件的信息
     *
     * 如果在上传文件的工程中发生错误，那么出错的文件不会放在结果中返回，结果中的文件都是可用的
     *
     * @param string $tag form表单中<input>标签中name属性的值，例<input name="p" type="file">
     *
     * 例1，上传单个文件：
     * <input name="upfile" type="file">
     *
     * 例2，上传多个文件：
     * <input name="upfile[]" type="file">
     * <input name="upfile[]" type="file">
     *
     */
    public function __construct($tag = '')
    {

        $file = isset($_FILES[$tag]) ? $_FILES[$tag] : '';

        //判断上传文件
        if (!isset($file) || empty($file)) {
            return array('status' => false, 'msg' => '请先上传文件');
        }

        $num = count($file['name']); //PHP上传类upload.php上传文件的个数

        $data = array(); //用来保存上传文件的信息的数组
        //上传了多个文件
        if ($num > 1) {
            for ($i = 0; $i < $num; $i++) {
                $d             = array();
                $d['name']     = $file['name'][$i];
                $d['type']     = $file['type'][$i];
                $d['tmp_name'] = $file['tmp_name'][$i];
                $d['error']    = $file['error'][$i];
                $d['size']     = $file['size'][$i];
                $pics          = explode('.', $file['name'][$i]);
                $d['postfix']  = $pics[count($pics) - 1];
                $d['filename'] = date('Ymdh', time()) . rand(10000, 99999) . '.' . $d['postfix'];

                if ($d['error'] == 0) {
                    $data[] = $d;
                } else {
                    @unlink($d['tmp_name']);
                }
            }
        }
        //只上传了一个文件
        else {
            $d             = array();
            $d['name']     = $file['name'];
            $d['type']     = $file['type'];
            $d['tmp_name'] = $file['tmp_name'];
            $d['error']    = $file['error'];
            $pics          = explode('.', $file['name']);
            $d['postfix']  = $pics[count($pics) - 1];
            $d['filename'] = date('Ymdh', time()) . rand(10000, 99999) . '.' . $d['postfix'];

            if ($d['error'] == 0) {
                $data[] = $d;
            } else {
                @unlink($d['tmp_name']);
            }
        }

        if (empty($data)) {
            return;
        }

        $this->file = $data; //保存上传文件的信息
    }

    /*获取file*/
    public function getFile($tag)
    {
        $file = $_FILES[$tag];

        if (!isset($file) || empty($file)) {
            return; //没有上传文件
        }

        $num = count($file['name']); //PHP上传类upload.php上传文件的个数

        $data = array(); //用来保存上传文件的信息的数组
        //上传了多个文件
        if ($num > 1) {
            for ($i = 0; $i < $num; $i++) {
                $d             = array();
                $d['name']     = $file['name'][$i];
                $d['type']     = $file['type'][$i];
                $d['tmp_name'] = $file['tmp_name'][$i];
                $d['error']    = $file['error'][$i];
                $d['size']     = $file['size'][$i];
                $pics          = explode('.', $file['name'][$i]);
                $d['postfix']  = $pics[count($pics) - 1];
                $d['filename'] = date('Ymdh', time()) . rand(10000, 99999) . '.' . $d['postfix'];

                if ($d['error'] == 0) {
                    $data[] = $d;
                } else {
                    @unlink($d['tmp_name']);
                }
            }
        }
        //只上传了一个文件
        else {
            $d             = array();
            $d['name']     = $file['name'];
            $d['type']     = $file['type'];
            $d['tmp_name'] = $file['tmp_name'];
            $d['error']    = $file['error'];
            $pics          = explode('.', $file['name']);
            $d['postfix']  = $pics[count($pics) - 1];
            $d['filename'] = date('Ymdh', time()) . rand(10000, 99999) . '.' . $d['postfix'];

            if ($d['error'] == 0) {
                $data[] = $d;
            } else {
                @unlink($d['tmp_name']);
            }
        }

        if (empty($data)) {
            return;
        }

        $this->file = $data; //保存上传文件的信息
    }

    /*执行*/
    public function upload()
    {

        if ($this->path == '') {
            $this->error = '请设置保存路径';
            return;
        }

        if (is_array($this->file)) {
            foreach ($this->file as $file) {
                $rest = $this->save($file, $this->path);
                for ($i = 0, $n = count($this->file); $i < $n; $i++) {
                    if ($rest) {
                        $this->file[$i]['url'] = 'http://' . $_SERVER['HTTP_HOST'] . $this->path . '/' . $this->file[$i]['filename'];
                    } else { $this->file[$i]['url'] = '';}
                }
            }
            return $rest;
        }
    }

    /*保存路径*/
    public function path($path)
    {
        $this->path = "/" . $path;
        if (!is_dir($_SERVER['DOCUMENT_ROOT'] . $this->path)) {
            mkdir($_SERVER['DOCUMENT_ROOT'] . $this->path);
        }
    }

    /*上次类型*/
    public function type($val)
    {
        $this->type = $val;
    }
    /**
     * 将上传的文件从临时文件夹移动到目标路径
     *
     * @param array $src 文件信息数组，是$file数组的其中一个元素（仍然是数组）
     * @param string $destpath 上传的目标路径
     * @param string $filename 上传后的文件名，如果为空，则使用上传时的文件名
     * @return bool
     */
    public function save($src, $destpath = '', $filename = null)
    {
        if ($src['error'] != 0) {return false;}

        if ($this->path != '') {$destpath = $_SERVER['DOCUMENT_ROOT'] . $this->path;}

        $srcTName = $src['tmp_name']; //原始上传文件的临时文件名
        $srcFName = $src['name']; //原始文件名

        //如果$filename参数为空，则使用上传时的文件名
        if (empty($filename)) {
            $filename = $src['filename'];

        }

        //$dest是文件最终要复制到的路径和文件名
        if (empty($destpath)) {
            $dest = $filename;
        } else {
            //修正路径中的斜杠，将末尾的\修改为/，如果末尾不是\也不是/，则给末尾添加一个/
            $pathend = $destpath[strlen($destpath) - 1]; //上传的目标路径的最后一个字符
            if ($pathend == '\\') {
                $dest = substr_replace($destpath, '/', strlen($destpath) - 1) . $filename;
            } else if ($pathend != '/') {
                $dest = $destpath . '/' . $filename;
            } else {
                $dest = $destpath . $filename;
            }
        }

        //上传文件成功
        if (@move_uploaded_file($srcTName, $dest)) {

            return true;
        } else {
            $this->error = '上传文件失败' . ":" . $filename;
            return false;
        }
    }

    //取得上传文件的信息
    public function getFileInfo()
    {
        return $this->file;
    }

    public function getError()
    {
        return $this->error;
    }
}


<?php
/**
 * Email utilities.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare (strict_types = 1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;
#
use PHPMailer;

/**
 * Email utilities.
 *
 * @since 151121 Email utilities.
 */
class Email extends Classes\Core\Base\Core implements Interfaces\EmailConstants
{
    /**
     * Send an email.
     *
     * @since 151121 Email utilities.
     *
     * @param string|array $to          Address(es).
     * @param string       $subject     Subject line.
     * @param string       $message     Message contents.
     * @param array        $attachments Files to attach.
     * @param array        $headers     Additional headers.
     * @param bool         $throw       Throw exceptions?
     *
     * @return bool True if the email was sent successfully.
     */
    public function __invoke($to, string $subject, string $message, array $attachments = [], array $headers = [], bool $throw = false)
    {
        if (!$this->App->Config->©email['©smtp_host'] || !$this->App->Config->©email['©smtp_port']) {
            throw $this->c::issue('Missing required email config values.');
        }
        $from_name  = $this->App->Config->©email['©from_name'];
        $from_email = $this->App->Config->©email['©from_email'];

        $reply_to_name  = $this->App->Config->©email['©reply_to_name'];
        $reply_to_email = $this->App->Config->©email['©reply_to_email'];

        $recipients = $this->parseAddresses($to);

        if ($this->c::isHtml($message)) {
            $message_html = $message; // HTML!
            $message_text = $this->c::htmlToText($message);
        } else {
            $message_text = $message; // Text!
            $message_html = $this->c::textToHtml($message);
        }
        if (!$message_text) { // Set a default plain text alternative in this case.
            $message_text = __('To view this email message, open it in a program that understands HTML.');
        }
        $headers = $this->parseHeaders($headers, [
            'from_name'     => &$from_name, 'from_email' => &$from_email,
            'reply_to_name' => &$reply_to_name, 'reply_to_email' => &$reply_to_email,
            'recipients'    => &$recipients,
        ]);
        unset($headers['content-type']); // We always send multipart messages w/ UTF-8 encoding.

        $attachments = $this->parseAttachments($attachments); // An array of file paths.

        if (!$from_email || !$recipients || !$subject || !$message_html || !$message_text) {
            return false; // Not possible. Missing vital argument value(s).
        }
        try { // Maybe catch exceptions.

            $mailer = new PHPMailer();
            $mailer->isSmtp();

            $mailer->SingleTo = count($recipients) > 1;

            $mailer->Host       = $this->App->Config->©email['©smtp_host'];
            $mailer->Port       = $this->App->Config->©email['©smtp_port'];
            $mailer->SMTPSecure = $this->App->Config->©email['©smtp_secure'];

            $mailer->SMTPAuth = (bool) $this->App->Config->©email['©smtp_username'];
            $mailer->Username = $this->App->Config->©email['©smtp_username'];
            $mailer->Password = $this->App->Config->©email['©smtp_password'];

            $mailer->SetFrom($from_email, $from_name);

            if ($reply_to_email) { // Special reply-to?
                $mailer->addReplyTo($reply_to_email, $reply_to_name);
            }
            foreach ($recipients as $_email => $_recipient) {
                $mailer->AddAddress($_recipient->email, $_recipient->name);
            } // unset($_email, $_recipient);

            $mailer->CharSet = 'utf-8';
            $mailer->Subject = $subject;

            $mailer->MsgHTML($message_html);
            $mailer->AltBody = $mailer->normalizeBreaks($message_text);

            foreach ($headers as $_header => $_value) {
                $mailer->AddCustomHeader($_header, $_value);
            } // unset($_header, $_value);

            foreach ($attachments as $_file_path => $_attachment) {
                $mailer->AddAttachment($_attachment);
            } // unset($_file_path, $_attachment);

            return $response = (bool) $mailer->Send();
        } catch (\Throwable $Throwable) {
            if ($throw) {
                throw $Throwable;
            }
            return false;
        }
    }

    /**
     * Valid email address?
     *
     * @since 151121 Email utilities.
     *
     * @param string $email Email address to check.
     *
     * @return bool True if email is valid.
     */
    public function isValid(string $email): bool
    {
        return (bool) preg_match($this::EMAIL_REGEX_VALID, $email);
    }

    /**
     * Is role-based address?
     *
     * @since 151121 Email utilities.
     *
     * @param string $email Email address to check.
     *
     * @return bool True if email is role-based.
     */
    public function isRoleBased(string $email): bool
    {
        $user = mb_strtolower(mb_strstr($email, '@', true));
        $user = str_replace(['-', '_', '.'], '', $user);

        if (!is_null($is = &$this->cacheKey(__FUNCTION__, $user))) {
            return $is; // Cached this already.
        }
        if (in_array($user, $this::EMAIL_ROLE_BASED_STRINGS, true)) {
            return $is = true;
        }
        foreach ($this::EMAIL_ROLE_BASED_REGEX_FRAGS as $_regex_frag) {
            if (preg_match('/^'.$_regex_frag.'$/ui', $user)) {
                return $is = true;
            }
        } // unset($_regex_frag); // Housekeeping.

        return $is = false;
    }

    /**
     * Parse addresses.
     *
     * @since 151121 Email utilities.
     *
     * @param mixed $value  Any input value w/ recipients.
     * @param bool  $strict Optional. Defaults to `false` (faster). Parses all strings w/ `@` signs.
     *                      If `true`, validate each address; and only return 100% valid email addresses.
     *
     * @return \StdClass[] Each object in the array contains 3 properties: `name`, `fname`, `lname`, `email`.
     */
    public function parseAddresses($value, bool $strict = false): array
    {
        $addresses = []; // Initialize.

        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => $_value) {
                $addresses = array_merge($addresses, $this->parseAddresses($_value, $strict));
            } // unset($_key, $_value); // Housekeeping.
            return $addresses;
        }
        $string                      = (string) $value;
        $delimiter                   = mb_strpos($string, ';') !== false ? ';' : ',';
        $regex_delimitation_splitter = '/'.$delimiter.'+/u'; // `$this->c::escRegex()` unnecessary.

        $possible_addresses = preg_split($regex_delimitation_splitter, $string, -1, PREG_SPLIT_NO_EMPTY);
        $possible_addresses = $this->c::mbTrim($possible_addresses);

        foreach ($possible_addresses as $_address) {
            if (!$_address || mb_strpos($_address, '@', 1) === false) {
                continue; // NOT an email address.
            }
            if (mb_strpos($_address, '<') !== false && preg_match('/(?:"(?<name>[^"]+?)"\s*)?\<(?<email>.+?)\>/u', $_address, $_m)) {
                if ($_m['email'] && mb_strpos($_m['email'], '@', 1) !== false && (!$strict || $this->isValid($_m['email']))) {
                    $_email             = mb_strtolower($_m['email']);
                    $_name              = !empty($_m['name']) ? $_m['name'] : '';
                    $_fname             = $_name ? $this->c::fnameIn($_name) : '';
                    $_lname             = $_name ? $this->c::lnameIn($_name) : '';
                    $addresses[$_email] = (object) ['name' => $_name, 'fname' => $_fname, 'lname' => $_lname, 'email' => $_email];
                }
            } elseif (!$strict || $this->isValid($_address)) {
                $_email             = mb_strtolower($_address);
                $addresses[$_email] = (object) ['name' => '', 'fname' => '', 'lname' => '', 'email' => $_email];
            }
        } // unset($_address, $_m, $_email, $_name, $_fname, $_lname); // Housekeeping.

        return $addresses;
    }

    /**
     * Parse headers.
     *
     * @since 151121 Email utilities.
     *
     * @param mixed $value  Any input value w/ headers.
     * @param array $refs   An input array of references to fill; for special headers.
     * @param bool  $strict Optional. Defaults to `false` (faster). Parses all strings w/ `@` signs.
     *                      If `true`, validate each address, and only return 100% valid email addresses.
     *
     * @return array Unique/associative array of all parsed headers.
     */
    protected function parseHeaders($value, array $refs = [], bool $strict = false): array
    {
        $headers = []; // Initialize parsed headers.

        foreach ($this->c::parseHeaders($value) as $_header => $_value) {
            switch ($_header) { // Maybe populate refs.

                case 'from':
                    if (array_key_exists('from_name', $refs) && array_key_exists('from_email', $refs)) {
                        if (($_from_addresses = $this->parseAddresses($_value, $strict))) {
                            $_from              = array_shift($_from_addresses);
                            $refs['from_name']  = $this->c::mbTrim($_from->fname.' '.$_from->lname);
                            $refs['from_email'] = $_from->email; // By reference.
                        } // unset($_from_addresses, $_from);
                    } else {
                        $headers[$_header] = $_value;
                    }
                    break; // Break switch.

                case 'reply-to':
                    if (array_key_exists('reply_to_name', $refs) && array_key_exists('reply_to_email', $refs)) {
                        if (($_reply_to_addresses = $this->parseAddresses($_value, $strict))) {
                            $_reply_to              = array_shift($_reply_to_addresses);
                            $refs['reply_to_name']  = $this->c::mbTrim($_reply_to->fname.' '.$_reply_to->lname);
                            $refs['reply_to_email'] = $_reply_to->email; // By reference.
                        } // unset($_reply_to_addresses, $_reply_to);
                    } else {
                        $headers[$_header] = $_value;
                    }
                    break; // Break switch.

                case 'cc':
                case 'bcc':
                    if (array_key_exists('recipients', $refs)) {
                        if (($_recipient_addresses = $this->parseAddresses($_value, $strict))) {
                            $refs['recipients'] = array_merge($refs['recipients'], $_recipient_addresses);
                            $refs['recipients'] = array_unique($refs['recipients']);
                        } // unset($_recipient_addresses);
                    } else {
                        $headers[$_header] = $_value;
                    }
                    break; // Break switch.

                default: // Everything else (default).
                    $headers[$_header] = $_value;
                    break; // Break switch.
            }
        }
        return $headers;
    }

    /**
     * Parse attachments.
     *
     * @since 151121 Email utilities.
     *
     * @param mixed $value Any input value w/ attachments.
     *
     * @return array Unique/associative array of all attachments.
     */
    protected function parseAttachments($value): array
    {
        $attachments = []; // Initialize.

        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => $_value) {
                $attachments = array_merge($attachments, $this->parseAttachments($_value));
            } // unset($_key, $_value); // Housekeeping.
            return $attachments;
        }
        $string = (string) $value;

        if (is_file($string)) {
            $attachments[$string] = $string;
        }
        return $attachments;
    }
}


<?php
namespace Perry;

class Tool
{

    /**
     * Parse a content-type header to a representation name
     *
     * @param string $contentType
     * @return bool
     */
    public static function parseContentTypeToRepresentation($contentType)
    {
        $matches = array();

        preg_match('/^application\/(.*)\+json; charset=utf-8$/im', $contentType, $matches);

        if (count($matches) == 2) {
            return $matches[1];
        }

        return false;
    }

    /**
     * convert a representation name including version to the
     * corresponding class
     *
     * @param  string $inputRepresentation
     * @return string
     * @throws \Exception
     */
    public static function parseRepresentationToClass($inputRepresentation)
    {
        $version = substr($inputRepresentation, -2);
        $representation = substr($inputRepresentation, 0, -3);

        switch (substr($representation, 0, 7)) {
            case "vnd.ccp": // EVE
                $data = explode(".", $representation);
                array_shift($data);
                array_shift($data);
                array_shift($data);
                $classname = '\Perry\Representation\Eve\\'.$version.'\\'.$data[0];
                break;
            case "net.3rd": // OldApi
                $data = explode(".", $representation);
                array_shift($data);
                array_shift($data);
                array_shift($data);

                $classname = '\Perry\Representation\OldApi\\'.$version.'\\'.$data[0];
                if (count($data) > 1) {
                    $classname .= '\\'.$data[1];
                }
                break;
            default:
                throw new \Exception("wtf, what representation is this? ".$inputRepresentation);
        }

        return $classname;
    }
}


<?php
/**
 * Percent utilities.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare (strict_types = 1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Percent utilities.
 *
 * @since 150424 Percentage utils.
 */
class Percent extends Classes\Core\Base\Core
{
    /**
     * Calculates percentage difference.
     *
     * @param int|float $from          Calculate from (i.e., value then).
     * @param int|float $to            Calculate to (i.e., the value now).
     * @param int       $precision     Defaults to `0`; i.e., no decimal place.
     * @param bool      $format_string If true, formatted `+|-[percent]%`.
     *
     * @return int|float|string A float if `$precision` is passed, else an integer (default behavior).
     *                          If `$format_string`, converted to string format: `+|-[percent]%`.
     */
    public function diff(float $from, float $to, int $precision = 0, bool $format_string = false)
    {
        if (!$from) {
            ++$from;
            ++$to;
        } // Stop division by `0`.

        $precision = max(0, $precision);
        $percent   = ($to - $from) / $from * 100;

        if ($precision) {
            $percent = (float) number_format($percent, $precision, '.', '');
        } else {
            $percent = (int) $percent;
        }
        if ($format_string) { // e.g., add a prefix/suffix?
            $percent = $percent > 0 ? '+'.$percent.'%' : $percent.'%';
        }
        return $percent;
    }
}


<?php
/**
 * Base64 utilities.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare (strict_types = 1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Base64 utilities.
 *
 * @since 150424 Initial release.
 */
class Base64 extends Classes\Core\Base\Core
{
    /**
     * Base64 URL-safe encoding.
     *
     * @since 150424 Initial release.
     *
     * @param string $string             Input string to be base64 encoded.
     * @param array  $url_unsafe_chars   Optional array of un-safe characters. Defaults to: `['+', '/']`.
     * @param array  $url_safe_chars     Optional array of safe character replacements. Defaults to: `['-', '_']`.
     * @param string $trim_padding_chars Optional string of padding chars to right-trim. Defaults to: `=`.
     *
     * @throws Exception If the call to `base64_encode()` fails.
     *
     * @return string The base64 URL-safe encoded string.
     */
    public function urlSafeEncode(string $string, array $url_unsafe_chars = ['+', '/'], array $url_safe_chars = ['-', '_'], string $trim_padding_chars = '='): string
    {
        if (!is_string($base64_url_safe = base64_encode($string))) {
            throw $this->c::issue('Base64 encoding failure.');
        }
        $base64_url_safe = str_replace($url_unsafe_chars, $url_safe_chars, $base64_url_safe);
        $base64_url_safe = isset($trim_padding_chars[0]) ? rtrim($base64_url_safe, $trim_padding_chars) : $base64_url_safe;

        return $base64_url_safe;
    }

    /**
     * Base64 URL-safe decoding.
     *
     * @since 150424 Initial release.
     *
     * @param string $base64_url_safe    Input string to be base64 decoded.
     * @param array  $url_unsafe_chars   Optional array of un-safe characters. Defaults to: `['+', '/']`.
     * @param array  $url_safe_chars     Optional array of safe character replacements. Defaults to: `['-', '_']`.
     * @param string $trim_padding_chars Optional string of padding chars to right-trim. Defaults to: `=`.
     *
     * @throws Exception If the call to `base64_decode()` fails.
     *
     * @return string The decoded string value.
     */
    public function urlSafeDecode(string $base64_url_safe, array $url_unsafe_chars = ['+', '/'], array $url_safe_chars = ['-', '_'], string $trim_padding_chars = '='): string
    {
        $string = isset($trim_padding_chars[0]) ? rtrim($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
        $string = isset($trim_padding_chars[0]) ? str_pad($string, strlen($string) % 4, '=', STR_PAD_RIGHT) : $string;
        $string = str_replace($url_safe_chars, $url_unsafe_chars, $string);

        if (!is_string($string = base64_decode($string, true))) {
            throw $this->c::issue('Base64 decoding failure.');
        }
        return $string;
    }
}


<?php
/**
 * Nonce utils.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Nonce utils.
 *
 * @since 17xxxx Nonce utils.
 */
class Nonce extends Classes\Core\Base\Core implements Interfaces\SecondConstants
{
    /**
     * Nonce generator.
     *
     * @since 17xxxx Nonce utils.
     *
     * @param string|null   $action   Action.
     * @param callable|null $callback Callback.
     *
     * @return string New, unique nonce token.
     *                CaSe-insensitive, 32 bytes in length.
     *
     * @note Callback stores the token for future verification.
     * If no callback, a `$_SESSION` storage handler is used by default.
     */
    public function create(string $action = null, callable $callback = null): string
    {
        $Nonce = (object) [
            'token'       => $this->c::uuidV4(),
            'action'      => mb_strtolower($action ?? ''),
            'expire_time' => time() + $this::SECONDS_IN_DAY,
            'used'        => false, // Unused on creation.
        ];
        if (isset($callback)) {
            $callback($Nonce);
            return $Nonce->token;
        }
        if ($this->c::isActiveSession()) {
            $_SESSION['_nonce'] = $_SESSION['_nonce'] ?? [];
            $this->c::arrayUnshiftAssoc($_SESSION['_nonce'], $Nonce->token, $Nonce);
            $_SESSION['_nonce'] = array_slice($_SESSION['_nonce'], 0, 64, true);
            return $Nonce->token;
        }
        throw $this->c::issue('No storage handler.');
    }

    /**
     * Nonce input markup.
     *
     * @since 17xxxx Nonce utils.
     *
     * @param string|null   $action   Action.
     * @param callable|null $callback Callback.
     *
     * @return string Hidden input field with `_nonce` token.
     *                See also: {@link create()}
     */
    public function input(string $action = null, callable $callback = null): string
    {
        $token = $this->create($action, $callback);
        return '<input type="hidden" name="_nonce" value="'.$this->c::escAttr($token).'" />';
    }

    /**
     * Nonce verifier.
     *
     * @since 17xxxx Nonce utils.
     *
     * @param string|null   $action   Action.
     * @param string|null   $token    Token.
     * @param callable|null $callback Callback.
     *
     * @return bool True if token is verified.
     *
     * @note Callback verifies token and flags token as having been used once before.
     * Or, if there is no callback, a built-in `$_SESSION` storage handler is used by default.
     */
    public function verify(string $action = null, string $token = null, callable $callback = null): bool
    {
        if (!isset($token)) {
            $token = (string) $_REQUEST['_nonce'];
        } // Defaults to current request.

        $action = mb_strtolower($action ?? '');
        $token  = mb_strtolower($token);

        if (isset($callback)) {
            return $callback($action, $token);
        }
        if ($this->c::isActiveSession()) {
            if (!isset($_SESSION['_nonce'][$token])) {
                return false; // Bad token.
            } // Reference Nonce in session.
            $Nonce = &$_SESSION['_nonce'][$token];

            if ($action !== $Nonce->action) {
                return false;
            } elseif (time() >= $Nonce->expire_time) {
                return false;
            } elseif ($Nonce->used) {
                return false;
            }
            return $Nonce->used = true;
        }
        throw $this->c::issue('No verification handler.');
    }
}


<?php

/*
 * This file is part of the Ivory Google Map package.
 *
 * (c) Eric GELOEN <geloen.eric@gmail.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Ivory\GoogleMap\Services\DistanceMatrix;

use Ivory\GoogleMap\Exception\DistanceMatrixException;
use Ivory\GoogleMap\Services\DistanceMatrix\DistanceMatrixStatus;

/**
 * A distance matrix response wraps the distance results & the response status.
 *
 * @author GeLo <geloen.eric@gmail.com>
 * @author Tyler Sommer <sommertm@gmail.com>
 */
class DistanceMatrixResponse
{
    /** @var string */
    protected $status;

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

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

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

    /**
     * Create a distance matrix response.
     *
     * @param string $status       The response status.
     * @param array  $origins      The normalized origins.
     * @param array  $destinations The normalized destinations.
     * @param array  $rows         The rows of data returned.
     */
    public function __construct($status, array $origins, array $destinations, array $rows)
    {
        $this->setStatus($status);
        $this->setOrigins($origins);
        $this->setDestinations($destinations);
        $this->setRows($rows);
    }

    /**
     * Gets the distance matrix routes.
     *
     * @return array The distance matrix origins.
     */
    public function getOrigins()
    {
        return $this->origins;
    }

    /**
     * Sets the distance matrix routes.
     *
     * @param array $origins The distance matrix origins.
     */
    public function setOrigins(array $origins)
    {
        $this->origins = array();

        foreach ($origins as $origin) {
            $this->addOrigin($origin);
        }
    }

    /**
     * Add a distance matrix origin.
     *
     * @param string $origin The origin to add.
     */
    public function addOrigin($origin)
    {
        $this->origins[] = $origin;
    }

    /**
     * Gets the distance matrix destinations.
     *
     * @return array The distance matrix destinations.
     */
    public function getDestinations()
    {
        return $this->destinations;
    }

    /**
     * Sets the distance matrix destinations.
     *
     * @param array $destinations The distance matrix routes.
     */
    public function setDestinations(array $destinations)
    {
        $this->destinations = array();

        foreach ($destinations as $destination) {
            $this->addDestination($destination);
        }
    }

    /**
     * Add a distance matrix destination.
     *
     * @param string $destination The destination to add.
     */
    public function addDestination($destination)
    {
        $this->destinations[] = $destination;
    }

    /**
     * Gets the distance matrix routes.
     *
     * @return array The distance matrix rows.
     */
    public function getRows()
    {
        return $this->rows;
    }

    /**
     * Sets the distance matrix routes.
     *
     * @param array $rows The distance matrix routes.
     */
    public function setRows(array $rows)
    {
        $this->rows = array();

        foreach ($rows as $row) {
            $this->addRow($row);
        }
    }

    /**
     * Add a distance matrix route.
     *
     * @param \Ivory\GoogleMap\Services\DistanceMatrix\DistanceMatrixResponseRow $row The row to add.
     */
    public function addRow(DistanceMatrixResponseRow $row)
    {
        $this->rows[] = $row;
    }

    /**
     * Gets the distance matrix response status.
     *
     * @return string The distance matrix response status.
     */
    public function getStatus()
    {
        return $this->status;
    }

    /**
     * Sets the distance matrix response status.
     *
     * @param string $status The distance matrix status.
     *
     * @throws \Ivory\GoogleMap\Exception\DistanceMatrixException If the status is not valid.
     */
    public function setStatus($status)
    {
        if (!in_array($status, DistanceMatrixStatus::getDistanceMatrixStatus())) {
            throw DistanceMatrixException::invalidDistanceMatrixResponseStatus();
        }

        $this->status = $status;
    }
}


<?php
/**
 * Application.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Traits\Facades;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Application.
 *
 * @since 160102
 */
trait App
{
    /**
     * @since 160102 App.
     * @see Classes\App
     */
    public static function app()
    {
        return $GLOBALS[static::class];
    }

    /**
     * @since 160715 App parent.
     *
     * @param int $levels Up X levels.
     *
     * @return Classes\App|null Parent App; else `null`.
     */
    public static function appParent(int $levels = 1)
    {
        $levels        = max(1, $levels);
        $level_counter = 1; // Start from `1`.
        $Parent        = $GLOBALS[static::class]->Parent;

        while ($Parent && $level_counter < $levels) {
            $Parent = $Parent->Parent ?? null;
            ++$level_counter; // Counter.
        }
        return $Parent; // Possible `null`.
    }

    /**
     * @since 160715 App core.
     *
     * @return Classes\App Core.
     */
    public static function appCore(): Classes\App
    {
        if (!($Parent = $GLOBALS[static::class]->Parent)) {
            return $GLOBALS[static::class];
            //
        } else { // Find root core.
            while ($Parent->Parent) {
                $Parent = $Parent->Parent;
            }
            return $Parent;
        }
    }
}


<?php
/**
 * Arrays.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Traits\Facades;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Arrays.
 *
 * @since 160102
 */
trait Arrays
{
    /**
     * @since 160511 Array cloning.
     *
     * @param mixed ...$args Variadic args to underlying utility.
     *
     * @see Classes\Core\Utils\ArrayClone::__invoke()
     */
    public static function cloneArray(...$args)
    {
        return $GLOBALS[static::class]->Utils->©ArrayClone->__invoke(...$args);
    }

    /**
     * @since 17xxxx Change recursive.
     *
     * @param mixed ...$args Variadic args to underlying utility.
     *
     * @see Classes\Core\Utils\ArrayChangeRecursive::__invoke()
     */
    public static function arrayChangeRecursive(...$args)
    {
        return $GLOBALS[static::class]->Utils->©ArrayChangeRecursive->__invoke(...$args);
    }

    /**
     * @since 160102 App.
     * @see Classes\Core\Utils\ArrayUnshiftAssoc::__invoke()
     *
     * @param array      $array An input array; by reference.
     * @param string|int $key   New array key; string or integer.
     * @param mixed      $value New array value.
     */
    public static function arrayUnshiftAssoc(&$array, $key, $value)
    {
        return $GLOBALS[static::class]->Utils->©ArrayUnshiftAssoc->__invoke($array, $key, $value);
    }
}


<?php
/**
 * Time utilities.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Time utilities.
 *
 * @since 170124.74961 Initial release.
 */
class Time extends Classes\Core\Base\Core implements Interfaces\SecondConstants
{
    /**
     * Human time difference.
     *
     * @since 170124.74961 Initial release.
     *
     * @param int      $from   From time.
     * @param int|null $to     Defaults to current time.
     * @param string   $format Formatting option.
     *
     * @return string Human time difference.
     */
    public function humanDiff(int $from, int $to = null, string $format = ''): string
    {
        $to   = $to ?? time();
        $diff = (int) abs($to - $from);

        if ($format !== 'abbrev' && $format !== 'default') {
            $format = 'default'; // Must be valid.
        }
        if ($diff < $this::SECONDS_IN_MINUTE) {
            $diff            = max(1, $diff);
            $fmat['abbrev']  = ['%1$ss', '%1$ss'];
            $fmat['default'] = ['%1$s sec', '%1$s secs'];
        } elseif ($diff < $this::SECONDS_IN_HOUR) {
            $diff            = max(1, round($diff / $this::SECONDS_IN_MINUTE));
            $fmat['abbrev']  = ['%1$sm', '%1$sm'];
            $fmat['default'] = ['%1$s min', '%1$s mins'];
        } elseif ($diff < $this::SECONDS_IN_DAY) {
            $diff            = max(1, round($diff / $this::SECONDS_IN_HOUR));
            $fmat['abbrev']  = ['%1$sh', '%1$sh'];
            $fmat['default'] = ['%1$s hour', '%1$s hours'];
        } elseif ($diff < $this::SECONDS_IN_WEEK) {
            $diff            = max(1, round($diff / $this::SECONDS_IN_DAY));
            $fmat['abbrev']  = ['%1$sd', '%1$sd'];
            $fmat['default'] = ['%1$s day', '%1$s days'];
        } elseif ($diff < $this::SECONDS_IN_WEEK * 4) {
            $diff            = max(1, round($diff / $this::SECONDS_IN_WEEK));
            $fmat['abbrev']  = ['%1$sw', '%1$sw'];
            $fmat['default'] = ['%1$s week', '%1$s weeks'];
        } elseif ($diff < $this::SECONDS_IN_YEAR) {
            $diff            = max(1, round($diff / ($this::SECONDS_IN_WEEK * 4)));
            $fmat['abbrev']  = ['%1$smo', '%1$smo'];
            $fmat['default'] = ['%1$s month', '%1$s months'];
        } else {
            $diff            = max(1, round($diff / $this::SECONDS_IN_YEAR));
            $fmat['abbrev']  = ['%1$sy', '%1$sy'];
            $fmat['default'] = ['%1$s year', '%1$s years'];
        }
        return sprintf(_n($fmat[$format][0], $fmat[$format][1], $diff), $diff);
    }
}


<?php

namespace Perry\Cache\File;

use Psr\Cache\PoolInterface;

class FilePool implements PoolInterface
{
    /**
     * @var string
     */
    private $path;

    /**
     * @param string $path
     * @throws \Exception
     */
    public function __construct($path)
    {
        if (!file_exists($path) && !mkdir($path)) {
            throw new \Exception("does not exist, and can not be created");
        }

        if (!is_dir($path) || !is_writable($path)) {
            throw new \Exception("$path is no directory, or can't be written to");
        }

        $this->path = $path;
    }

    /**
     * Returns a Cache Item representing the specified key.
     *
     * This method must always return an ItemInterface object, even in case of
     * a cache miss. It MUST NOT return null.
     *
     * @param string $key
     *   The key for which to return the corresponding Cache Item.
     * @return \Psr\Cache\ItemInterface
     *   The corresponding Cache Item.
     * @throws \Psr\Cache\InvalidArgumentException
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     */
    public function getItem($key)
    {
        // no check for legality atm, since we can use everything as a key
        // usually you want that to reflect the limitations put in place by psr-6
        $map = self::mapKey($key);

        if (!file_exists($this->path .'/'. $map['dir'])) {
            mkdir($this->path .'/'. $map['dir']);
        }

        return FileItem::fromFile($this->path .'/'. $map['dir'] . '/' . $map['file'], $key);
    }

    /**
     * Returns a traversable set of cache items.
     *
     * @param array $keys
     *   An indexed array of keys of items to retrieve.
     * @return \Traversable
     *   A traversable collection of Cache Items in the same order as the $keys
     *   parameter, keyed by the cache keys of each item. If no items are found
     *   an empty Traversable collection will be returned.
     */
    public function getItems(array $keys)
    {
        $result = array();

        foreach ($keys as $key) {
            $result[$key] = $this->getItem($key);
        }

        return $result;
    }

    /**
     * Deletes all items in the pool.
     *
     * @return \Psr\Cache\PoolInterface
     *   The current pool.
     */
    public function clear()
    {
        // we don't clear the files atm
        return $this;
    }

    /**
     * @param string $key
     * @return string
     */
    public static function mapKey($key)
    {
        $key = sha1($key);

        // we will use the first 4 as directory
        // to prevent issues on some filesystems
        return [
            "file" => substr($key, 4),
            "dir" => substr($key, 0, 4)
        ];
    }
}


<?php

/*
 * This file is part of the Ivory Google Map package.
 *
 * (c) Eric GELOEN <geloen.eric@gmail.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Ivory\GoogleMap\Helper\Overlays;

use Ivory\GoogleMap\Helper\AbstractHelper;
use Ivory\GoogleMap\Map;
use Ivory\GoogleMap\Overlays\Marker;

/**
 * Marker helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class MarkerHelper extends AbstractHelper
{
    /** @var \Ivory\GoogleMap\Helper\Overlays\AnimationHelper */
    protected $animationHelper;

    /**
     * Creates a marker helper.
     *
     * @param \Ivory\GoogleMap\Helper\Overlays\AnimationHelper $animationHelper The animation helper.
     */
    public function __construct(AnimationHelper $animationHelper = null)
    {
        parent::__construct();

        if ($animationHelper === null) {
            $animationHelper = new AnimationHelper();
        }

        $this->setAnimationHelper($animationHelper);
    }

    /**
     * Gets the animation helper.
     *
     * @return \Ivory\GoogleMap\Helper\Overlays\AnimationHelper The animation helper.
     */
    public function getAnimationHelper()
    {
        return $this->animationHelper;
    }

    /**
     * Sets the animation helper.
     *
     * @param \Ivory\GoogleMap\Helper\Overlays\AnimationHelper $animationHelper The animation helper.
     */
    public function setAnimationHelper(AnimationHelper $animationHelper)
    {
        $this->animationHelper = $animationHelper;
    }

    /**
     * Renders a marker.
     *
     * @param Ivory\GoogleMap\Overlays\Marker $marker The marker.
     * @param Ivory\GoogleMap\Map             $map    The map.
     *
     * @return string The JS output.
     */
    public function render(Marker $marker, Map $map = null)
    {
        $this->jsonBuilder
            ->reset()
            ->setValue('[position]', $marker->getPosition()->getJavascriptVariable(), false);

        if ($map !== null) {
            $this->jsonBuilder->setValue('[map]', $map->getJavascriptVariable(), false);
        }

        if ($marker->hasAnimation()) {
            $this->jsonBuilder->setValue('[animation]', $this->animationHelper->render($marker->getAnimation()), false);
        }

        if ($marker->hasIcon()) {
            $this->jsonBuilder->setValue('[icon]', $marker->getIcon()->getJavascriptVariable(), false);
        }

        if ($marker->hasShadow()) {
            $this->jsonBuilder->setValue('[shadow]', $marker->getShadow()->getJavascriptVariable(), false);
        }

        if ($marker->hasShape()) {
            $this->jsonBuilder->setValue('[shape]', $marker->getShape()->getJavascriptVariable(), false);
        }

        $this->jsonBuilder->setValues($marker->getOptions());

        return sprintf(
            '%s = new google.maps.Marker(%s);'.PHP_EOL,
            $marker->getJavascriptVariable(),
            $this->jsonBuilder->build()
        );
    }
}


<?php
namespace Perry\Fetcher;

use Perry\Cache\CacheManager;
use Perry\Perry;
use Perry\Response;
use Perry\Setup;
use Perry\Tool;

/**
 * Class FileFetcher
 *
 * @package Perry\Fetcher
 * @deprecated
 */
class FileFetcher implements CanFetch
{

    /**
     * form the opts array
     *
     * @param string $representation
     * @return array
     */
    private function getOpts($representation)
    {
        $opts = array(
            'http' => array(
                'method' => "GET",
            ),
            'socket' => [
                'bindto' => Setup::$bindToIp
            ]
        );

        if (is_null($representation)) {
            $header = "Accept-language: en\r\nUser-Agent: Perry/".Perry::$version.' '.Setup::$userAgent."\r\n";
        } else {
            $header = "Accept-language: en\r\nUser-Agent: Perry/".
                Perry::$version.' '.Setup::$userAgent."\r\nAccept: application/$representation+json\r\n";
        }

        $opts['http']['header'] = $header;

        $opts = array_merge_recursive(Setup::$fetcherOptions, $opts);

        return $opts;
    }

    /**
     * @param string $url
     * @param string $representation
     * @throws \Exception
     * @return \Perry\Response
     */
    public function doGetRequest($url, $representation)
    {

        if ($data = CacheManager::getInstance()->load($url)) {
            return new Response($data['value'], $data['representation']);
        }

        $context = stream_context_create($this->getOpts($representation));

        if (false === ($data = @file_get_contents($url, false, $context))) {

            if (false === $headers = (@get_headers($url, 1))) {
                throw new \Exception("could not connect to api");
            }

            throw new \Exception("an error occured with the http request: ".$headers[0]);
        } else {
            $headers = @get_headers($url, 1);
            if (isset($headers['Content-Type'])) {
                if (false !== ($retrep = Tool::parseContentTypeToRepresentation($headers['Content-Type']))) {
                    $representation = $retrep;
                }
            }

        }

        CacheManager::getInstance()->save($url, ["representation" => $representation, "value" => $data]);

        return new Response($data, $representation);
    }
}


<?php
namespace Xuma\Bfxm;

class Builder
{
    public $json = array();

    public function __construct()
    {
        $this->json = array("bfxm"=>array("version"=>1));
    }

    /**
     *  Play specific file.
     *
     * @param $url
     * @return $this
     */
    public function play($url)
    {
        $this->add(array("action"=>"play","args"=>array("url"=>$url)));

        return $this;
    }

    /**
     * Request input from user.
     *
     * @param $array
     * @return $this
     */
    public function gather($array)
    {
        $this->add(array(
            "action"=>"gather",
            "args"=>$array
        ));

        return $this;
    }

    /**
     * Hangup call.
     *
     * @return $this
     */
    public function hangup()
    {
        $this->add(array(
            "action"=>"hangup"
        ));

        return $this;
    }

    /**
     * Reject the call.
     *
     * @return $this
     */
    public function reject()
    {
        $this->add(array(
            "action"=>"reject"
        ));

        return $this;
    }

    /**
     * Set caller name for call.
     *
     * @param $name
     * @return $this
     */
    public function set_caller($name)
    {
        $this->add(array(
            "action"=>"set_caller_name",
            "args"=>array(
                "caller_name"=>$name
            )

        ));

        return $this;
    }

    /**
     * Read specific text.
     *
     * @param $lang
     * @param $text
     * @return $this
     */
    public function say($lang,$text)
    {
        $this->add(array(
            "action"=>"say",
            "args"=>array(
                "lang"=>$lang,
                "text"=>$text
            )
        ));

        return $this;
    }

    /**
     * Dial or redirect a number.
     *
     * @param $num
     * @return $this
     */
    public function dial($num,$display_caller=false)
    {
        $this->add(array(
            "action"=>"dial",
            "args"=>array(
                "destination"=>$num,
                "hide_cli_on_diversion"=>$display_caller
            )
        ));

        return $this;
    }

    /**
     * Build json for Bulutfonxm
     *
     * @param bool $build
     * @return bool|string
     */
    public function build($build=false)
    {
        if($build){
            header('Content-Type: application/json');
            echo json_encode($this->json);
            return true;
        }

        return json_encode($this->json);
    }

    public function return_data($data)
    {
        $this->add(array(
            "action"=>"return_data",
            "args"=>$data
        ));

        return $this;
    }

    private function add($array)
    {
        if(isset($this->json["seq"]))
        {
            array_push($this->json["seq"],$array);
            return;
        }

        $this->json =  array_merge($this->json,array("seq"=>array($array)));
    }
}


<?php

/*
 * This file is part of the Ivory Google Map package.
 *
 * (c) Eric GELOEN <geloen.eric@gmail.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Ivory\GoogleMap\Helper\Overlays;

use Ivory\GoogleMap\Overlays\MarkerShape;

/**
 * Marker shape helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class MarkerShapeHelper
{
    /**
     * Renders a marker shape.
     *
     * @param \Ivory\GoogleMap\Overlays\MarkerShape $markerShape The marker shape.
     *
     * @return string The JS output.
     */
    public function render(MarkerShape $markerShape)
    {
        return sprintf(
            '%s = new google.maps.MarkerShape(%s);'.PHP_EOL,
            $markerShape->getJavascriptVariable(),
            json_encode(array('type' => $markerShape->getType(), 'coords' => $markerShape->getCoordinates()))
        );
    }
}


<?php

/*
 * This file is part of the Ivory Google Map package.
 *
 * (c) Eric GELOEN <geloen.eric@gmail.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Ivory\GoogleMap\Helper\Controls;

use Ivory\GoogleMap\Controls\ScaleControlStyle;
use Ivory\GoogleMap\Exception\HelperException;

/**
 * Scale control style helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class ScaleControlStyleHelper
{
    /**
     * Renders a scale control style.
     *
     * @param string $scaleControlStyle The scale control style.
     *
     * @throws \Ivory\GoogleMap\Exception\HelperException If the scale control style is not valid.
     *
     * @return string The JS output.
     */
    public function render($scaleControlStyle)
    {
        switch ($scaleControlStyle) {
            case ScaleControlStyle::DEFAULT_:
                return sprintf('google.maps.ScaleControlStyle.%s', strtoupper($scaleControlStyle));
            default:
                throw HelperException::invalidScaleControlStyle();
        }
    }
}


<?php
/**
 * Slug utilities.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Classes\Core\Utils;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Slug utilities.
 *
 * @since 150424 Initial release.
 */
class Slug extends Classes\Core\Base\Core implements Interfaces\SlugConstants
{
    /**
     * Validate slug.
     *
     * @since 150424 Initial release.
     *
     * @param string $slug   Slug.
     * @param bool   $strict Strict?
     *
     * @return bool True if slug is valid.
     */
    public function isValid(string $slug, bool $strict = true): bool
    {
        return (bool) preg_match($strict ? $this::SLUG_STRICT_REGEX_VALID : $this::SLUG_REGEX_VALID, $slug);
    }

    /**
     * Is slug reserved?
     *
     * @since 150424 Reserved slugs.
     *
     * @param string $slug Slug.
     *
     * @return bool True if slug is reserved.
     */
    public function isReserved(string $slug): bool
    {
        $slug = mb_strtolower($slug);
        $slug = str_replace(['-', '_', '.'], '', $slug);

        if (($is = &$this->cacheKey(__FUNCTION__, $slug)) !== null) {
            return $is; // Cached this already.
        }
        if (mb_strlen($slug) < 3) {
            return $is = true;
        } elseif (in_array($slug, $this::SLUG_RESERVED_STRINGS, true)) {
            return $is = true;
        }
        foreach ($this::SLUG_RESERVED_REGEX_FRAGS as $_regex_frag) {
            if (preg_match('/^'.$_regex_frag.'$/ui', $slug)) {
                return $is = true;
            }
        } // unset($_regex_frag); // Housekeeping.

        return $is = false;
    }

    /**
     * Convert slug to name.
     *
     * @since 150424 Initial release.
     *
     * @param string $slug Slug.
     *
     * @return string Name; based on slug.
     */
    public function toName(string $slug): string
    {
        $name = $slug; // Initialize.
        $name = preg_replace('/[^\p{L}\p{N}]+/u', ' ', $name);
        $name = $this->c::mbUcWords($name);
        $name = $this->c::mbTrim($name);

        return $name;
    }

    /**
     * Convert slug to acronym.
     *
     * @since 160220 Initial release.
     *
     * @param string $slug   Slug.
     * @param bool   $strict Strict?
     *
     * @return string Acronym; based on slug.
     */
    public function toAcronym(string $slug, bool $strict = true): string
    {
        return $this->c::nameToAcronym($this->toName($slug), $strict);
    }

    /**
     * Convert slug to var.
     *
     * @since 160220 Initial release.
     *
     * @param string $slug   Slug.
     * @param bool   $strict Strict?
     *
     * @return string Var; based on slug.
     */
    public function toVar(string $slug, bool $strict = true): string
    {
        $var = $slug; // Initialize.
        $var = mb_strtolower($this->c::forceAscii($var));
        $var = preg_replace('/[^a-z0-9]+/u', '_', $var);
        $var = $this->c::mbTrim($var, '', '_');

        if ($strict && $var && !preg_match('/^[a-z]/u', $var)) {
            $var = 'x'.$var; // Force `^[a-z]`.
        }
        return $var;
    }
}


<?php

/*
 * This file is part of the Ivory Google Map package.
 *
 * (c) Eric GELOEN <geloen.eric@gmail.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Ivory\GoogleMap\Overlays;

use Ivory\GoogleMap\Assets\AbstractOptionsAsset;
use Ivory\GoogleMap\Base\Coordinate;
use Ivory\GoogleMap\Exception\OverlayException;

/**
 * Polyline which describes a google map polyline.
 *
 * @see http://code.google.com/apis/maps/documentation/javascript/reference.html#Polyline
 * @author GeLo <geloen.eric@gmail.com>
 */
class Polyline extends AbstractOptionsAsset implements ExtendableInterface
{
    /** @var array */
    protected $coordinates;

    /**
     * Creates a polyline.
     *
     * @param array $coordinates The polyline coordinates.
     */
    public function __construct(array $coordinates = array())
    {
        parent::__construct();

        $this->setPrefixJavascriptVariable('polyline_');
        $this->setCoordinates($coordinates);
    }

    /**
     * Checks if the polyline has coordinates.
     *
     * @return boolean TRUE if the polyline has coordinates else FALSE.
     */
    public function hasCoordinates()
    {
        return !empty($this->coordinates);
    }

    /**
     * Gets the polyline coordinates.
     *
     * @return array The polyline coordinates.
     */
    public function getCoordinates()
    {
        return $this->coordinates;
    }

    /**
     * Sets the polyline coordinates.
     *
     * @param array $coordinates The polyline coordinates.
     */
    public function setCoordinates($coordinates)
    {
        $this->coordinates = array();

        foreach ($coordinates as $coordinate) {
            $this->addCoordinate($coordinate);
        }
    }

    /**
     * Add a coordinate to the polyline.
     *
     * Available prototypes:
     *  - function addCoordinate(Ivory\GoogleMap\Base\Coordinate $coordinate)
     *  - function addCoordinate(double $latitude, double $longitude, boolean $noWrap = true)
     *
     * @throws \Ivory\GoogleMap\Exception\OverlayException If the coordinate is not valid.
     */
    public function addCoordinate()
    {
        $args = func_get_args();

        if (isset($args[0]) && ($args[0] instanceof Coordinate)) {
            $this->coordinates[] = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            $coordinate = new Coordinate($args[0], $args[1]);

            if (isset($args[2]) && is_bool($args[2])) {
                $coordinate->setNoWrap($args[2]);
            }

            $this->coordinates[] = $coordinate;
        } else {
            throw OverlayException::invalidPolylineCoordinate();
        }
    }
}


<?php
declare(strict_types = 1);
namespace RabbitCMS\Modules\Managers;

use Illuminate\Contracts\Foundation\Application;
use RabbitCMS\Modules\Contracts\PackageContract;
use RabbitCMS\Modules\Repository;
use RuntimeException;
use SplFileInfo;

/**
 * Class ManagerImpl
 * @package RabbitCMS\Modules\Managers
 */
trait ManagerImpl
{
    /**
     * @var Repository
     */
    protected $repository;

    /**
     * @var Application
     */
    protected $app;

    /**
     * Manager constructor.
     *
     * @param Application $app
     */
    public function __construct(Application $app)
    {
        $this->app = $app;
        $this->restore();
    }

    /**
     * @inheritdoc
     */
    public function restore(): bool
    {
        if (empty($cacheFile = $this->cacheFile()) || !is_file($file = base_path($cacheFile))) {
            return false;
        }
        $repository = new Repository();

        $data = (array)json_decode(file_get_contents($file), true);

        foreach ($data as $module) {
            $module = $this->restoreItem($module);
            if (!is_dir($module->getPath())) {
                //disable modules if not exist
                $module->setEnabled(false);
            }
            $repository->add($module);
        }

        $this->repository = $repository;

        return true;
    }

    /**
     * Store modules for fast load.
     */
    public function store()
    {
        if (empty($cacheFile = $this->cacheFile())) {
            return;
        }
        file_put_contents(
            base_path($cacheFile),
            json_encode($this->all()->toArray(), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
        );
    }

    /**
     * Get all modules.
     *
     * @return Repository
     */
    public function all(): Repository
    {
        if ($this->repository === null && !$this->restore()) {
            $this->repository = new Repository();
            $this->scan();
        }

        return $this->repository;
    }

    /**
     * @inheritdoc
     */
    public function disable($name)
    {
        $module = $this->all()->get($name);
        if ($module->isSystem()) {
            throw new RuntimeException('Don\'t disable system module.');
        }
        $module->setEnabled(false);
        $this->store();
    }

    /**
     * @inheritdoc
     */
    public function enable($name)
    {
        $this->all()->get($name)->setEnabled(true);
        $this->store();
    }

    /**
     * @inheritdoc
     */
    public function enabled(): Repository
    {
        return $this->all()->filter(
            function (PackageContract $module) {
                return $module->isEnabled();
            }
        );
    }

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

    /**
     * @inheritdoc
     */
    public function get($name): PackageContract
    {
        return $this->all()->get($name);
    }

    /**
     * Get the specified configuration value.
     *
     * @param string $key
     * @param mixed $default
     *
     * @return mixed
     */
    abstract public function config(string $key, $default = null);

    /**
     * @param string $link
     * @param string $path
     */
    protected function updateLink(string $link, string $path)
    {
        if (is_link($path)) {
            unlink($path);
        }
        if (is_dir($link) && $link !== public_path()) {
            if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
                $link = $this->getRelativePath($path, $link);
            }
            symlink($link, $path);
        }
    }

    /**
     * @param string $from
     * @param string $path
     * @return string
     */
    private function getRelativePath(string $from, string $path): string
    {
        // some compatibility fixes for Windows paths
        $from = is_dir($from) ? rtrim($from, '\/') . '/' : $from;
        $path = is_dir($path) ? rtrim($path, '\/') . '/' : $path;
        $from = str_replace('\\', '/', $from);
        $path = str_replace('\\', '/', $path);

        $from = explode('/', $from);
        $path = explode('/', $path);
        $relPath = $path;

        foreach ($from as $depth => $dir) {
            // find first non-matching dir
            if ($dir === $path[$depth]) {
                // ignore this directory
                array_shift($relPath);
            } else {
                // get number of remaining dirs to $from
                $remaining = count($from) - $depth;
                if ($remaining > 1) {
                    // add traversals up to first matching dir
                    $padLength = (count($relPath) + $remaining - 1) * -1;
                    $relPath = array_pad($relPath, $padLength, '..');
                    break;
                } else {
                    $relPath[0] = './' . $relPath[0];
                }
            }
        }

        return implode('/', $relPath);
    }

    /**
     * @inheritdoc
     */
    public function scan($store = true)
    {
        $repository = new Repository();
        foreach ((array)$this->config('paths', []) as $path) {
            foreach (glob($path, GLOB_NOSORT | GLOB_BRACE | GLOB_ONLYDIR) as $dir) {
                /* @var SplFileInfo $file */
                if (!is_dir($dir)) {
                    continue;
                }
                if (!is_file($composerFile = $dir . '/composer.json')) {
                    continue;
                }
                $composer = json_decode(file_get_contents($composerFile), true);

                $package = $this->checkPackage($dir, $composer);
                if ($package !== null) {
                    if ($this->repository && $this->repository->has($package->getName())) {
                        $package->setEnabled($this->repository->get($package->getName())->isEnabled());
                    }
                    $repository->add($package);
                }
            }
        }

        $this->repository = $repository;
        if ($store) {
            $this->store();
        }
    }

    /**
     * @param array $item
     * @return PackageContract
     */
    abstract protected function restoreItem(array $item): PackageContract;

    /**
     * @param string $dir
     * @param array $composer
     * @return PackageContract|null
     */
    abstract protected function checkPackage(string $dir, array $composer);

    /**
     * Get cache file path.
     * @return string
     */
    abstract protected function cacheFile():string;
}


<?php
/**
 * Template.
 *
 * @author @jaswrks
 * @copyright WebSharks™
 */
declare(strict_types=1);
namespace WebSharks\Core\Classes\Core;

use WebSharks\Core\Classes;
use WebSharks\Core\Interfaces;
use WebSharks\Core\Traits;
#
use WebSharks\Core\Classes\Core\Error;
use WebSharks\Core\Classes\Core\Base\Exception;
#
use function assert as debug;
use function get_defined_vars as vars;

/**
 * Template.
 *
 * @since 150424 Initial release.
 */
class Template extends Classes\Core\Base\Core
{
    /**
     * Directory.
     *
     * @since 150424
     *
     * @var string
     */
    protected $dir;

    /**
     * File path.
     *
     * @since 150424
     *
     * @var string
     */
    protected $file;

    /**
     * File ext.
     *
     * @since 150424
     *
     * @var string
     */
    protected $ext;

    /**
     * Parent files.
     *
     * @since 150424
     *
     * @var array
     */
    protected $parents;

    /**
     * Parent vars.
     *
     * @since 150424
     *
     * @var array
     */
    protected $parent_vars;

    /**
     * Variables.
     *
     * @since 150424
     *
     * @var array
     */
    protected $vars;

    /**
     * Route.
     *
     * @since 161008
     *
     * @var null|Classes\Core\Route
     */
    protected $Route;

    /**
     * Parse counter.
     *
     * @since 161008
     *
     * @var int
     */
    protected $parsed;

    /**
     * Class constructor.
     *
     * @since 150424 Initial release.
     *
     * @param Classes\App $App  Instance of App.
     * @param string      $dir  Template file directory.
     * @param string      $file Relative to directory.
     * @param array       $args Additional args.
     */
    public function __construct(Classes\App $App, string $dir, string $file, array $args = [])
    {
        parent::__construct($App);

        if (!($template = $this->c::locateTemplate($file, $dir))) {
            throw $this->c::issue(sprintf('Missing template: `%1$s`.', $dir.'/'.$file));
        }
        $default_args = [
            'parents'     => [],
            'parent_vars' => [],
            'Route'       => null,
        ];
        $args += $default_args;

        $this->dir         = $template['dir'];
        $this->file        = $template['file'];
        $this->ext         = $template['ext'];
        $this->parents     = (array) $args['parents'];
        $this->parent_vars = (array) $args['parent_vars'];
        $this->vars        = []; // Initialize.
        $this->Route       = $args['Route'];
        $this->parsed      = 0;

        $this->setAdditionalProps();
    }

    /**
     * Reserved for extenders.
     *
     * @since 160715 Initial release.
     */
    protected function setAdditionalProps()
    {
        // Reserved for extenders.
    }

    /**
     * Parse template.
     *
     * @since 150424 Initial release.
     *
     * @param array $vars Template vars.
     *
     * @return string Parsed template contents.
     */
    public function parse(array $vars = []): string
    {
        ++$this->parsed; // Parsing now.

        if ($this->ext === 'php') {
            $_this = $this; // `$this` in symbol table.
            // ↑ Strange magic makes it possible for `$this` to be used from
            // inside the template file also. We just need to reference it here.
            // See: <http://stackoverflow.com/a/4994799/1219741>

            unset($_this, $vars['this']); // Avoid conflicts.
            $this->vars = $vars; // Set current template variables.
            unset($vars); // Don't include as a part of template variables.

            extract($this->vars); // Extract for template.

            ob_start(); // Output buffer.
            require $this->dir.'/'.$this->file;
            return ob_get_clean();
        } else {
            return file_get_contents($this->dir.'/'.$this->file);
        }
    }

    /**
     * Set template vars.
     *
     * @since 150424 Initial release.
     *
     * @param array $defaults Default vars.
     * @param array ...$vars Variadic template vars.
     *
     * @return array New template vars.
     */
    protected function setVars(array $defaults, array ...$vars): array
    {
        return $this->vars = array_replace_recursive($defaults, $this->vars, ...$vars);
    }

    /**
     * Has a parent?
     *
     * @since 150424 Initial release.
     *
     * @param string|null $file Template file.
     *
     * @return bool True if child has a parent.
     */
    protected function hasParent(string $file = null): bool
    {
        if (isset($file)) {
            return in_array($file, $this->parents, true);
        }
        return !empty($this->parents);
    }

    /**
     * Parent template vars.
     *
     * @since 150424 Initial release.
     *
     * @param string|null $file Template file.
     *
     * @return array Parent template vars.
     */
    protected function parentVars(string $file = null): array
    {
        if (isset($file)) {
            return $this->parent_vars[$file] ?? [];
        }
        $closest_ancestor_vars = end($this->parent_vars);
        return $parent_vars    = $closest_ancestor_vars ?: [];
    }

    /**
     * Main template file.
     *
     * @since 160926 Initial release.
     *
     * @return string Main template file.
     */
    protected function mainFile(): string
    {
        if ($this->parents) {
            return $this->parents[0];
        }
        return $this->file;
    }

    /**
     * Main template file slug.
     *
     * @since 160926 Initial release.
     *
     * @return string Main template file slug.
     */
    protected function mainFileSlug(): string
    {
        return $this->c::nameToSlug($this->mainFile());
    }

    /**
     * Main template file is?
     *
     * @since 160926 Initial release.
     *
     * @param string $file File to match.
     *
     * @return bool True if main template file is.
     */
    protected function mainFileIs(string $file): bool
    {
        return $this->mainFile() === $file;
    }

    /**
     * Main template file matches?
     *
     * @since 160926 Initial release.
     *
     * @param string $regex Regex to match.
     *
     * @return bool True if main template file matches.
     */
    protected function mainFileMatches(string $regex): bool
    {
        return (bool) preg_match($regex, $this->mainFile());
    }

    /**
     * Get a child template.
     *
     * @since 150424 Initial release.
     *
     * @param string $new_child_file Relative to templates dir.
     * @param array  $new_child_vars Template vars for the include.
     * @param string $new_child_dir  From a specific directory?
     *
     * @return string Parsed template contents for child template.
     */
    protected function get(string $new_child_file, array $new_child_vars = [], string $new_child_dir = ''): string
    {
        $new_child_parents     = array_merge($this->parents, [$this->file]);
        $new_child_parent_vars = array_merge($this->parent_vars, [$this->file => &$this->vars]);
        $new_child_Template    = $this->c::getTemplate($new_child_file, $new_child_dir, [
            'parents'     => $new_child_parents,
            'parent_vars' => $new_child_parent_vars,
            'Route'       => $this->Route,
        ]);
        // Variables from the closest ancestors take precedence over further/older ancestors.
        // File-specific variables in those ancestors take precedence over those that aren't file-specific.

        foreach (array_reverse($new_child_parent_vars, true) as $_parent_file => $_parent_vars) {
            if (isset($_parent_vars[$new_child_file]) && is_array($_parent_vars[$new_child_file])) {
                $new_child_vars = array_replace_recursive($_parent_vars[$new_child_file], $new_child_vars);
            }
            $_parent_vars_not_file_specific = array_diff_key($_parent_vars, $new_child_parent_vars + [$new_child_file => 0]);
            $new_child_vars                 = array_replace_recursive($_parent_vars_not_file_specific, $new_child_vars);
        } // unset($_parent_file, $_parent_vars, $_parent_vars_not_file_specific); // Housekeeping.

        return $new_child_Template->parse($new_child_vars);
    }
}


<?php
declare(strict_types = 1);
namespace RabbitCMS\Modules\Console;

use RabbitCMS\Modules\Seeders\DatabaseSeeder;

/**
 * Class SeedCommand.
 * @package RabbitCMS\Modules
 */
class SeedCommand extends \Illuminate\Database\Console\Seeds\SeedCommand
{
    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        $options = parent::getOptions();
        foreach ($options as &$option) {
            if ($option[0] === 'class') {
                $option[4] = DatabaseSeeder::class;
            }
        }

        return $options;
    }
}