<?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\AbstractJavascriptVariableAsset;
use Ivory\GoogleMap\Base\Point;
use Ivory\GoogleMap\Base\Size;
use Ivory\GoogleMap\Exception\OverlayException;

/**
 * Marker image which describes a google map marker image.
 *
 * @see http://code.google.com/apis/maps/documentation/javascript/reference.html#MarkerImage
 * @author GeLo <geloen.eric@gmail.com>
 */
class MarkerImage extends AbstractJavascriptVariableAsset
{
    /** @var string */
    protected $url;

    /** @var \Ivory\GoogleMap\Base\Point */
    protected $anchor;

    /** @var \Ivory\GoogleMap\Base\Point */
    protected $origin;

    /** @var \Ivory\GoogleMap\Base\Size */
    protected $scaledSize;

    /** @var Ivory\GoogleMap\Base\Size */
    protected $size;

    /**
     * Create a marker image.
     */
    public function __construct(
        $url = '//maps.gstatic.com/mapfiles/markers/marker.png',
        Point $anchor = null,
        Point $origin = null,
        Size $scaledSize = null,
        Size $size = null
    ) {
        $this->setPrefixJavascriptVariable('marker_image_');
        $this->setUrl($url);

        if ($anchor !== null) {
            $this->setAnchor($anchor);
        }

        if ($origin !== null) {
            $this->setOrigin($origin);
        }

        if ($scaledSize !== null) {
            $this->setScaledSize($scaledSize);
        }

        if ($size !== null) {
            $this->setSize($size);
        }
    }

    /**
     * Gets the url of the marker image.
     *
     * @return string The url of the marker image.
     */
    public function getUrl()
    {
        return $this->url;
    }

    /**
     * Sets the url of the marker image.
     *
     * @param string $url The url of the marker image.
     *
     * @throws \Ivory\GoogleMap\Exception\OverlayException If the url is not valid.
     */
    public function setUrl($url)
    {
        if (!is_string($url)) {
            throw OverlayException::invalidMarkeImageUrl();
        }

        $this->url = $url;
    }

    /**
     * Checks if the marker image has an anchor.
     *
     * @return boolean TRUE if the marker image has an anchor else FALSE.
     */
    public function hasAnchor()
    {
        return $this->anchor !== null;
    }

    /**
     * Gets the anchor of the marker image.
     *
     * @return \Ivory\GoogleMap\Base\Point The marker image anchor.
     */
    public function getAnchor()
    {
        return $this->anchor;
    }

    /**
     * Sets the anchor of the marker image
     *
     * Available prototypes:
     *  - function setAnchor(Ivory\GoogleMap\Base\Point $anchor = null)
     *  - function setAnchor(double x, double y)
     *
     * @throws \Ivory\GoogleMap\Exception\OverlayException If the anchor is not valid (prototypes).
     */
    public function setAnchor()
    {
        $args = func_get_args();

        if ($args[0] instanceof Point) {
            $this->anchor = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            if ($this->anchor === null) {
                $this->anchor = new Point();
            }

            $this->anchor->setX($args[0]);
            $this->anchor->setY($args[1]);
        } elseif (!isset($args[0])) {
            $this->anchor = null;
        } else {
            throw OverlayException::invalidMarkerImageAnchor();
        }
    }

    /**
     * Checks if the marker image has an origin.
     *
     * @return boolean TRUE if the marker image has an origin else FALSE.
     */
    public function hasOrigin()
    {
        return $this->origin !== null;
    }

    /**
     * Gets the origin of the marker image.
     *
     * @return \Ivory\GoogleMap\Base\Point The marker image origin.
     */
    public function getOrigin()
    {
        return $this->origin;
    }

    /**
     * Sets the origin of the marker image
     *
     * Available prototypes:
     *  - function setOrigin(Ivory\GoogleMap\Base\Point $origin = null)
     *  - function setOrigin(double x, double y)
     *
     * @throws \Ivory\GoogleMap\Exception\OverlayException If the origin is not valid.
     */
    public function setOrigin()
    {
        $args = func_get_args();

        if (isset($args[0]) && ($args[0] instanceof Point)) {
            $this->origin = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            if ($this->origin === null) {
                $this->origin = new Point();
            }

            $this->origin->setX($args[0]);
            $this->origin->setY($args[1]);
        } elseif (!isset($args[0])) {
            $this->origin = null;
        } else {
            throw OverlayException::invalidMarkerImageOrigin();
        }
    }

    /**
     * Checks if the marker image has a scaled size else FALSE.
     *
     * @return boolean TRUE if the marker image has a scaled size else FALSE.
     */
    public function hasScaledSize()
    {
        return $this->scaledSize !== null;
    }

    /**
     * Gets the scaled size of the marker image.
     *
     * @return \Ivory\GoogleMap\Base\Size The marker image scaled size.
     */
    public function getScaledSize()
    {
        return $this->scaledSize;
    }

    /**
     * Sets the scaled size of the marker image
     *
     * Available prototypes:
     *  - function setScaledSize(Ivory\GoogleMap\Base\Size $scaledSize = null)
     *  - function setScaledSize(double $width, double $height, string $widthUnit = null, string $heightUnit = null)
     *
     * @throws \Ivory\GoogleMap\Exception\OverlayException If the scaled size is not valid.
     */
    public function setScaledSize()
    {
        $args = func_get_args();

        if (isset($args[0]) && ($args[0] instanceof Size)) {
            $this->scaledSize = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            if ($this->scaledSize === null) {
                $this->scaledSize = new Size();
            }

            $this->scaledSize->setWidth($args[0]);
            $this->scaledSize->setHeight($args[1]);

            if (isset($args[2]) && is_string($args[2])) {
                $this->scaledSize->setWidthUnit($args[2]);
            }

            if (isset($args[3]) && is_string($args[3])) {
                $this->scaledSize->setHeightUnit($args[3]);
            }
        } elseif (!isset($args[0])) {
            $this->scaledSize = null;
        } else {
            throw OverlayException::invalidMarkerImageScaledSize();
        }
    }

    /**
     * Checks if the marker image has a size.
     *
     * @return boolean TRUE if the marker image has a size else FALSE.
     */
    public function hasSize()
    {
        return $this->size !== null;
    }

    /**
     * Gets the size of the marker image.
     *
     * @return \Ivory\GoogleMap\Base\Size The marker image size.
     */
    public function getSize()
    {
        return $this->size;
    }

    /**
     * Sets the size of the marker image.
     *
     * Available prototypes:
     *  - function setSize(Ivory\GoogleMap\Base\Size $size = null)
     *  - function setSize(double $width, double $height, string $widthUnit = null, string $heightUnit = null)
     *
     * @throws \Ivory\GoogleMap\Exception\OverlayException If the size is not valid.
     */
    public function setSize()
    {
        $args = func_get_args();

        if (isset($args[0]) && ($args[0] instanceof Size)) {
            $this->size = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            if ($this->size === null) {
                $this->size = new Size($args[0], $args[1]);
            }

            $this->size->setWidth($args[0]);
            $this->size->setHeight($args[1]);

            if (isset($args[2]) && is_string($args[2])) {
                $this->size->setWidthUnit($args[2]);
            }

            if (isset($args[3]) && is_string($args[3])) {
                $this->size->setHeightUnit($args[3]);
            }
        } elseif (!isset($args[0])) {
            $this->size = null;
        } else {
            throw OverlayException::invalidMarkerImageSize();
        }
    }
}


<?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;
use Ivory\GoogleMap\Overlays\InfoWindow;

/**
 * Info window helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class InfoWindowHelper extends AbstractHelper
{
   /**
     * Renders an info window.
     *
     * @param \Ivory\GoogleMap\Overlays\InfoWindow $infoWindow     The info window.
     * @param boolean                              $renderPosition TRUE if the position is rendered else FALSE.
     *
     * @return string The JS output.
     */
    public function render(InfoWindow $infoWindow, $renderPosition = true)
    {
        $this->doRender($infoWindow, $renderPosition);

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

    /**
     * Renders the info window open flag.
     *
     * @param \Ivory\GoogleMap\Overlays\InfoWindow $infoWindow The info window.
     * @param \Ivory\GoogleMap\Map                 $map        The map.
     * @param \Ivory\GoogleMap\Overlays\Marker     $marker     The marker.
     *
     * @return string The JS output.
     */
    public function renderOpen(InfoWindow $infoWindow, Map $map, Marker $marker = null)
    {
        if ($marker !== null) {
            return sprintf(
                '%s.open(%s, %s);'.PHP_EOL,
                $infoWindow->getJavascriptVariable(),
                $map->getJavascriptVariable(),
                $marker->getJavascriptVariable()
            );
        }

        return sprintf('%s.open(%s);'.PHP_EOL, $infoWindow->getJavascriptVariable(), $map->getJavascriptVariable());
    }

    /**
     * Configures the json builder in order to render an info window.
     *
     * @param \Ivory\GoogleMap\Helper\Overlays\InfoWinfow $infoWindow     The info window.
     * @param boolean                                     $renderPosition TRUE if the position is rendered else FALSE.
     */
    protected function doRender(InfoWindow $infoWindow, $renderPosition)
    {
        $this->jsonBuilder->reset();

        if ($renderPosition) {
            $this->jsonBuilder->setValue('[position]', $infoWindow->getPosition()->getJavascriptVariable(), false);
        }

        if ($infoWindow->hasPixelOffset()) {
            $this->jsonBuilder->setValue(
                '[pixelOffset]',
                $infoWindow->getPixelOffset()->getJavascriptVariable(),
                false
            );
        }

        $this->jsonBuilder
            ->setValue('[content]', $infoWindow->getContent())
            ->setValues($infoWindow->getOptions());
    }
}


<?php
declare(strict_types=1);

namespace RabbitCMS\Modules\Managers;

use Illuminate\Foundation\Application;
use Illuminate\Routing\Router;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use RabbitCMS\Modules\Contracts\PackageContract;
use RabbitCMS\Modules\Contracts\PackagesManager;
use RabbitCMS\Modules\Exceptions\ModuleNotFoundException;
use RabbitCMS\Modules\Module;
use RuntimeException;

/**
 * Class Modules.
 *
 * @package RabbitCMS\Modules
 */
class Modules implements PackagesManager
{
    use ManagerImpl;

    /**
     * @var callable
     */
    protected $assetResolver;

    /**
     * @inheritdoc
     */
    protected function cacheFile(): string
    {
        return 'bootstrap/cache/modules.json';
    }

    /**
     * @inheritdoc
     */
    protected function restoreItem(array $item): PackageContract
    {
        return new Module($item);
    }

    /**
     * @inheritdoc
     */
    protected function checkPackage(string $dir, array $composer)
    {
        if (empty($composer['extra']['module']) || !is_array($composer['extra']['module'])) {
            return null;
        }
        $module = $composer['extra']['module'];
        if (empty($module['namespace'])) {
            if (isset($composer['autoload']['psr-4'])
                && is_array($composer['autoload']['psr-4'])
                && count($composer['autoload']['psr-4']) > 0
            ) {
                $module['namespace'] = trim(key($composer['autoload']['psr-4']), '\\');
            } else {
                throw new RuntimeException('Module namespace must be set.');
            }
        }

        if (empty($module['name'])) {
            $names = explode('/', $composer['name']);
            $module['name'] = $names[1];
        }

        $module['description'] = array_key_exists('description', $composer) ? $composer['description'] : '';
        $module['path'] = $dir;
        $module = new Module($module);

        $this->updateLink(
            $module->getPath('public'),
            public_path($this->getAssetsPath() . '/' . $module->getName())
        );

        return $module;
    }

    /**
     * @inheritdoc
     */
    public function getAssetsPath(): string
    {
        return $this->config('modulesAssets', 'modules');
    }

    /**
     * Register module providers.
     *
     * @param Application $app
     */
    public function register(Application $app)
    {
        $this->enabled()->each(function (Module $module) use ($app) {
            array_map(function ($class) use ($app) {
                /* @var ServiceProvider $provider */
                $provider = new $class($app);
                if ($provider->isDeferred()) {
                    $app->addDeferredServices(array_fill_keys($provider->provides(), $provider));
                } else {
                    $app->register($provider);
                }
            }, array_filter($module->getProviders(), 'class_exists'));
        });
    }

    /**
     * Get module asset.
     *
     * @param string $module
     * @param string $path
     * @param null   $secure
     *
     * @return string
     */
    public function asset(string $module, string $path, $secure = null): string
    {
        if ($this->assetResolver && ($url = call_user_func($this->assetResolver, $module, $path, $secure)) !== null) {
            return $url;
        }

        return $this->app->make('url')->asset($this->getAssetsPath() . "/{$module}/" . $path, $secure);
    }

    /**
     * @param callable $resolver
     */
    public function setAssetResolver(callable $resolver = null)
    {
        $this->assetResolver = $resolver;
    }

    /**
     * @inheritdoc
     */
    public function config(string $key, $default = null)
    {
        return $this->app->make('config')->get('modules.' . $key, $default);
    }

    /**
     * Load modules routes.
     *
     * @param string $scope
     */
    public function loadRoutes(string $scope = 'web')
    {
        $this->app->make('router')->group([
            'as' => $scope === 'web' ? '' : "{$scope}.",
        ], function (Router $router) use ($scope) {
            $this->enabled()->each(function (Module $module) use ($scope, $router) {
                $path = $module->getPath("routes/{$scope}.php");
                if (file_exists($path)) {
                    $router->group([
                        'namespace' => $module->getNamespace() . '\\Http\\Controllers',
                    ], function (Router $router) use ($module, $path, $scope) {
                        $options = array_merge([
                            'namespace'  => $scope === 'web' ? null : Str::studly($scope),
                            'as'         => $module->getName() . '.',
                            'prefix'     => $module->getName(),
                            'middleware' => $scope,
                        ], $module->config("routes.{$scope}", []));
                        $router->group($options, function (Router $router) use ($path, $module) {
                            require($path);
                        });
                    });
                }
            });
        });
    }

    protected $namespaces = null;

    protected $detect = [];

    /**
     * @param string $class
     *
     * @return Module
     * @throws ModuleNotFoundException
     */
    public function detect(string $class): Module
    {
        if (array_key_exists($class, $this->detect)) {
            return $this->get($this->detect[$class]);
        }

        if ($this->namespaces === null) {
            $this->namespaces = $this->all()->map(function (Module $module) {
                return $module->getNamespace();
            });
            arsort($this->namespaces);
        }

        foreach ($this->namespaces as $name => $namespace) {
            if (strpos($class, $namespace) === 0) {
                $this->detect[$class] = $name;

                return $this->get($name);
            }
        }
        throw new ModuleNotFoundException("Module for class '$class' not found.");
    }

    /**
     * @param string $class
     *
     * @return Module
     * @throws ModuleNotFoundException
     */
    public function getByNamespace(string $class): Module
    {
        return $this->detect($class);
    }
}


<?php
/**
 * Php has 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;

/**
 * Php has utilities.
 *
 * @since 150424 Initial release.
 */
class PhpHas extends Classes\Core\Base\Core
{
    /**
     * Global static cache.
     *
     * @since 160712 PhpHas utilities.
     *
     * @var array Global static cache.
     */
    protected static $cache;

    /**
     * PHP's language constructs.
     *
     * @since 160219 Adding constructs.
     *
     * @var array Constructs.
     */
    const CONSTRUCTS = [
        'die',
        'echo',
        'empty',
        'exit',
        'eval',
        'include',
        'include_once',
        'isset',
        'list',
        'require',
        'require_once',
        'return',
        'print',
        'unset',
        '__halt_compiler',
    ];

    /**
     * Is function callable?
     *
     * @since 150424 Initial release.
     *
     * @param string $function A PHP function.
     *
     * @return bool True if the function is callable.
     *
     * @internal This checks (among other things) if the function exists and that it's callable.
     *    It also checks INI `disable_functions` & `suhosin.executor.func.blacklist`.
     *    In addition, it also checks `suhosin.executor.disable_eval`.
     */
    public function callableFunc(string $function): bool
    {
        $function = mb_strtolower($function);

        if (isset(static::$cache[__FUNCTION__][$function])) {
            return static::$cache[__FUNCTION__][$function];
        }
        if (!isset(static::$cache[__FUNCTION__.'s_disabled'])) {
            static::$cache[__FUNCTION__.'s_disabled'] = []; // Initialize.
            $_functions_disabled                      = &static::$cache[__FUNCTION__.'s_disabled'];

            if (($_ini_disable_functions = (string) ini_get('disable_functions'))) {
                $_ini_disable_functions = mb_strtolower($_ini_disable_functions);
                $_functions_disabled    = array_merge($_functions_disabled, preg_split('/[\s;,]+/u', $_ini_disable_functions, -1, PREG_SPLIT_NO_EMPTY));
            }
            if (($_ini_suhosin_blacklist_functions = (string) ini_get('suhosin.executor.func.blacklist'))) {
                $_ini_suhosin_blacklist_functions = mb_strtolower($_ini_suhosin_blacklist_functions);
                $_functions_disabled              = array_merge($_functions_disabled, preg_split('/[\s;,]+/u', $_ini_suhosin_blacklist_functions, -1, PREG_SPLIT_NO_EMPTY));
            }
            if (($_ini_opcache_restrict_api = (string) ini_get('opcache.restrict_api')) && mb_stripos(__FILE__, $_ini_opcache_restrict_api) !== 0) {
                $_functions_disabled = array_merge($_functions_disabled, ['opcache_compile_file', 'opcache_get_configuration', 'opcache_get_status', 'opcache_invalidate', 'opcache_is_script_cached', 'opcache_reset']);
            }
            if (filter_var(@ini_get('suhosin.executor.disable_eval'), FILTER_VALIDATE_BOOLEAN)) {
                $_functions_disabled[] = 'eval'; // The `eval()` construct is disabled also.
            }
        } // We now have a full list of all disabled functions.

        static::$cache[__FUNCTION__][$function] = null; // Initialize.
        $has                                    = &static::$cache[__FUNCTION__][$function];
        $functions_disabled                     = &static::$cache[__FUNCTION__.'s_disabled'];

        if ($functions_disabled && in_array($function, $functions_disabled, true)) {
            return $has = false; // Not possible; e.g., `eval()`.
        } elseif ((!function_exists($function) || !is_callable($function)) && !in_array($function, $this::CONSTRUCTS, true)) {
            return $has = false; // Not possible.
        }
        return $has = true;
    }
}


<?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\GroundOverlay;

/**
 * Ground overlay helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class GroundOverlayHelper extends AbstractHelper
{
    /**
     * Renders a ground overlay.
     *
     * @param \Ivory\GoogleMap\Overlays\GroundOverlay $groundOverlay The ground overlay.
     * @param \Ivory\GoogleMap\Map                    $map           The map.
     *
     * @return string The JS output.
     */
    public function render(GroundOverlay $groundOverlay, Map $map)
    {
        $this->jsonBuilder
            ->reset()
            ->setValue('[map]', $map->getJavascriptVariable(), false)
            ->setValues($groundOverlay->getOptions());

        return sprintf(
            '%s = new google.maps.GroundOverlay("%s", %s, %s);'.PHP_EOL,
            $groundOverlay->getJavascriptVariable(),
            $groundOverlay->getUrl(),
            $groundOverlay->getBound()->getJavascriptVariable(),
            $this->jsonBuilder->build()
        );
    }
}


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

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;

/**
 * Cache members.
 *
 * @since 150424 Initial release.
 */
trait CacheMembers
{
    /**
     * Instance cache.
     *
     * @since 150424 Initial release.
     *
     * @type array Instance cache.
     */
    protected $x___cache = [];

    /**
     * Set a cache sub-key.
     *
     * @since 150424 Initial release.
     *
     * @param string     $primary_key Primary key.
     * @param string|int $sub_key     Sub-key to set.
     * @param mixed      $value       New cache key value.
     *
     * @return mixed|null Value (by reference) for the cache sub-key.
     *
     * @internal Returns by reference. The use of `&` is highly recommended when calling this utility.
     *    See also: <http://php.net/manual/en/language.references.return.php>
     */
    protected function &cacheSet(string $primary_key, $sub_key, $value)
    {
        if ($primary_key === 'x___keys' || $primary_key === 'x___refs') {
            throw $this->c::issue('Attempting to set a reserved primary key.');
        }
        $sub_key                                 = (string) $sub_key;
        $this->x___cache[$primary_key][$sub_key] = $value;
        return $this->x___cache[$primary_key][$sub_key];
    }

    /**
     * Get a cache sub-key.
     *
     * @since 150424 Initial release.
     *
     * @param string     $primary_key Primary key.
     * @param string|int $sub_key     Sub-key to get.
     *
     * @return mixed|null Value (by reference) for the cache sub-key.
     *
     * @internal Returns by reference. The use of `&` is suggested when calling this utility.
     *    See also: <http://php.net/manual/en/language.references.return.php>
     */
    protected function &cacheGet(string $primary_key, $sub_key)
    {
        if ($primary_key === 'x___keys' || $primary_key === 'x___refs') {
            throw $this->c::issue('Attempting to get a reserved primary key.');
        }
        $sub_key = (string) $sub_key; // Force string.

        if (isset($this->x___cache[$primary_key][$sub_key])) {
            return $this->x___cache[$primary_key][$sub_key];
        } else {
            $this->x___cache[$primary_key][$sub_key] = null;
            return $this->x___cache[$primary_key][$sub_key];
        }
    }

    /**
     * Unset a cache sub-key.
     *
     * @since 150424 Initial release.
     *
     * @param string     $primary_key Primary key.
     * @param string|int $sub_key     Sub-key to unset.
     */
    protected function cacheUnset(string $primary_key, $sub_key)
    {
        if ($primary_key === 'x___keys' || $primary_key === 'x___refs') {
            throw $this->c::issue('Attempting to unset a reserved primary key.');
        }
        $sub_key                                 = (string) $sub_key;
        $this->x___cache[$primary_key][$sub_key] = null;
        unset($this->x___cache[$primary_key][$sub_key]);
    }

    /**
     * Unset a cache sub-key pattern.
     *
     * @since 150424 Initial release.
     *
     * @param string $primary_key     Primary key.
     * @param string $sub_key_pattern Sub-key pattern (watered-down regex).
     */
    protected function cacheUnsetPattern(string $primary_key, string $sub_key_pattern)
    {
        if ($primary_key === 'x___keys' || $primary_key === 'x___refs') {
            throw $this->c::issue('Attempting to unset a reserved primary key.');
        }
        if (empty($this->x___cache[$primary_key])) {
            return; // Nothing to do here.
        }
        $sub_key_regex = // Allow `**` to indicate everything quickly.
            $sub_key_pattern === '**' ? '' : $this->c::wRegx($sub_key_pattern, '/', true);

        if (!$sub_key_regex && $sub_key_pattern !== '**') {
            return; // Nothing to do; i.e., no regex.
        }
        foreach (array_keys($this->x___cache[$primary_key]) as $_sub_key) {
            if ($sub_key_pattern === '**' || preg_match($sub_key_regex.'i', (string) $_sub_key)) {
                $this->x___cache[$primary_key][$_sub_key] = null;
                unset($this->x___cache[$primary_key][$_sub_key]);
            }
        } // unset($_sub_key); // Housekeeping.
    }

    /**
     * Add a new cache ref-key.
     *
     * @since 150424 Initial release.
     *
     * @param string     $primary_key Primary key.
     * @param string|int $ref_key     Ref-key to set.
     * @param mixed      $value       New value (by reference).
     */
    protected function cacheAddByRef(string $primary_key, $ref_key, &$value)
    {
        $ref_key                                               = (string) $ref_key;
        $this->x___cache['x___refs'][$primary_key][$ref_key][] = &$value;
    }

    /**
     * Unset a cache ref-key.
     *
     * @since 150424 Initial release.
     *
     * @param string     $primary_key Primary key.
     * @param string|int $ref_key     Ref-key to unset.
     */
    protected function cacheUnsetByRef(string $primary_key, $ref_key)
    {
        $ref_key = (string) $ref_key; // Force string.

        if (empty($this->x___cache['x___refs'][$primary_key][$ref_key])) {
            return; // Nothing to do here.
        }
        foreach (array_keys($this->x___cache['x___refs'][$primary_key][$ref_key]) as $_key) {
            $this->x___cache['x___refs'][$primary_key][$ref_key][$_key] = null;
        } // unset($_key); // Housekeeping.
        unset($this->x___cache['x___refs'][$primary_key][$ref_key]);
    }

    /**
     * Unset a cache ref-key pattern.
     *
     * @since 150424 Initial release.
     *
     * @param string $primary_key     Primary key.
     * @param string $ref_key_pattern Ref-key pattern (watered-down regex).
     */
    protected function cacheUnsetByRefPattern(string $primary_key, string $ref_key_pattern)
    {
        if (empty($this->x___cache['x___refs'][$primary_key])) {
            return; // Nothing to do here.
        }
        $ref_key_regex = // Allow `**` to indicate everything quickly.
            $ref_key_pattern === '**' ? '' : $this->c::wRegx($ref_key_pattern, '/', true);

        if (!$ref_key_regex && $ref_key_pattern !== '**') {
            return; // Nothing to do; i.e., no regex.
        }
        foreach (array_keys($this->x___cache['x___refs'][$primary_key]) as $_ref_key) {
            if ($ref_key_pattern === '**' || preg_match($ref_key_regex.'i', (string) $_ref_key)) {
                foreach (array_keys($this->x___cache['x___refs'][$primary_key][$_ref_key]) as $_key) {
                    $this->x___cache['x___refs'][$primary_key][$_ref_key][$_key] = null;
                } // unset($_key); // Housekeeping.
                unset($this->x___cache['x___refs'][$primary_key][$_ref_key]);
            }
        } // unset($_ref_key); // Housekeeping.
    }

    /**
     * Cache key (or sub-key) based on args.
     *
     * @since 150424 Initial release.
     *
     * @param string      $primary_key Primary key.
     * @param mixed|array $args        Args to base key on.
     *
     * @return mixed|null Value (by reference) for the cache key. Default is `null`.
     *
     * @internal Returns by reference. The use of `&` is highly recommended when calling this utility.
     *    See also: <http://php.net/manual/en/language.references.return.php>
     */
    protected function &cacheKey(string $primary_key, $args = [])
    {
        $args = (array) $args; // Force an array of args.

        if (!isset($this->x___cache['x___keys'][$primary_key])) {
            $this->x___cache['x___keys'][$primary_key] = null;
        }
        $cache_key = &$this->x___cache['x___keys'][$primary_key];

        foreach ($args as $_arg) {
            switch (($_arg_type = gettype($_arg))) {
                case 'int':
                case 'integer':
                    $_key = (int) $_arg;
                    // Only integer key.
                    break; // Break switch handler.

                case 'double':
                case 'float':
                case 'real':
                    $_key = (string) $_arg;
                    // Only numeric string.
                    break; // Break switch handler.

                case 'bool':
                case 'boolean':
                    $_key = $_arg ? 'true' : 'false';
                    // Only string not sha1 or numeric.
                    break; // Break switch handler.

                case 'string':
                    $_key = sha1($_arg_type.$_arg);
                    break; // Break switch handler.

                case 'array':
                    $_key = sha1($_arg_type.serialize($_arg));
                    break; // Break switch handler.

                case 'object': // See: <http://php.net/manual/en/function.spl-object-hash.php>
                    $_key = spl_object_hash($_arg).sha1($_arg_type.get_class($_arg).serialize($_arg));
                    break; // Break switch handler.

                case 'null':
                case 'NULL':
                case 'resource':
                case 'unknown':
                case 'unknown type':
                    $_key = "\0".sha1($_arg_type.(string) $_arg);
                    break; // Break switch handler.

                default: // Default case handler.
                    throw $this->c::issue(sprintf('Unexpected arg type: `%1$s`.', $_arg_type));
            }
            if (!isset($cache_key[$_key])) {
                $cache_key[$_key] = null;
            }
            $cache_key = &$cache_key[$_key];
        } // unset($_arg, $_arg_type, $_key);

        return $cache_key;
    }

    /**
     * Clear cache (everything).
     *
     * @since 150424 Initial release.
     */
    protected function cacheClear()
    {
        if (!empty($this->x___cache['x___refs'])) { // Nullify underliers.
            foreach (array_keys($this->x___cache['x___refs']) as $_primary_key) {
                foreach (array_keys($this->x___cache['x___refs'][$_primary_key]) as $_ref_key) {
                    foreach (array_keys($this->x___cache['x___refs'][$_primary_key][$_ref_key]) as $_key) {
                        $this->x___cache['x___refs'][$_primary_key][$_ref_key][$_key] = null;
                    } // unset($_key); // Housekeeping.
                } // unset($_ref_key); // Housekeeping.
            } // unset($_primary_key); // Housekeeping.
        }
        $this->x___cache = []; // Clean slate.
    }
}


<?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\Base\Distance;
use Ivory\GoogleMap\Services\Base\Duration;
use Ivory\GoogleMap\Services\DistanceMatrix\DistanceMatrixElementStatus;

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

    /** @var null|\Ivory\GoogleMap\Services\Base\Distance */
    protected $distance;

    /** @var null|\Ivory\GoogleMap\Services\Base\Duration */
    protected $duration;

    /**
     * Create a distance matrix response element.
     *
     * @param \Ivory\GoogleMap\Services\Base\Distance $distance The element distance.
     * @param \Ivory\GoogleMap\Services\Base\Duration $duration The element duration.
     * @param string                                  $status   The element status.
     */
    public function __construct($status, Distance $distance = null, Duration $duration = null)
    {
        $this->setStatus($status);

        if ($distance !== null) {
            $this->setDistance($distance);
        }

        if ($duration !== null) {
            $this->setDuration($duration);
        }
    }

    /**
     * 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, DistanceMatrixElementStatus::getDistanceMatrixElementStatus())) {
            throw DistanceMatrixException::invalidDistanceMatrixResponseElementStatus();
        }

        $this->status = $status;
    }

    /**
     * Gets the step distance.
     *
     * @return \Ivory\GoogleMap\Services\Base\Distance The step distance.
     */
    public function getDistance()
    {
        return $this->distance;
    }

    /**
     * Sets the step distance.
     *
     * @param \Ivory\GoogleMap\Services\Base\Distance $distance The step distance.
     */
    public function setDistance(Distance $distance)
    {
        $this->distance = $distance;
    }

    /**
     * Gets the step duration.
     *
     * @return \Ivory\GoogleMap\Services\Base\Duration The step duration.
     */
    public function getDuration()
    {
        return $this->duration;
    }

    /**
     * Sets the step duration
     *
     * @param \Ivory\GoogleMap\Services\Base\Duration $duration The step duration.
     */
    public function setDuration(Duration $duration)
    {
        $this->duration = $duration;
    }
}


<?php
/**
 * Bitly 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;

/**
 * Bitly utilities.
 *
 * @since 160102 Adding bitly.
 */
class Bitly extends Classes\Core\Base\Core
{
    /**
     * Cache directory.
     *
     * @since 150424
     *
     * @type string
     */
    protected $cache_dir;

    /**
     * Class constructor.
     *
     * @since 160102 Adding bitly.
     *
     * @param Classes\App $App Instance of App.
     */
    public function __construct(Classes\App $App)
    {
        parent::__construct($App);

        if (!$this->App->Config->©fs_paths['©cache_dir']) {
            throw $this->c::issue('Missing cache directory.');
        }
        $this->cache_dir = $this->App->Config->©fs_paths['©cache_dir'].'/bitly';
    }

    /**
     * Shorten a URL.
     *
     * @since 160102 Adding bitly.
     *
     * @param string $long_url Long URL.
     * @param array  $args     Any additional args.
     *
     * @return string Short URL.
     */
    public function shorten(string $long_url, array $args = []): string
    {
        # Parse incoming arguments.

        if (!$long_url) {
            return ''; // Nothing to do.
        }
        $default_args = [
            'access_token' => $this->App->Config->©bitly['©api_key'],
            'longUrl'      => $long_url, // From above.
        ];
        $args = array_merge($default_args, $args);

        # Already cached this in memory?

        if (!is_null($short_url = &$this->cacheKey(__FUNCTION__, $args))) {
            return $short_url; // Cached this already.
        }
        # Prepare endpoint/request args.

        $endpoint_args = array_merge($args, [
            // Nothing more at this time.
        ]);
        $request_args = [
            'max_con_secs'    => 5,
            'max_stream_secs' => 5,
            'return'          => 'array',
        ];
        $endpoint = 'https://api-ssl.bitly.com/v3/shorten';
        $endpoint = $this->c::addUrlQueryArgs($endpoint_args, $endpoint);

        # Determine sharded cache directory and file.

        $endpoint_sha1         = sha1($endpoint);
        $cache_dir             = $this->cache_dir.'/'.$this->c::sha1ModShardId($endpoint_sha1, true);
        $cache_dir_permissions = $this->App->Config->©fs_permissions['©transient_dirs'];
        $cache_file            = $cache_dir.'/'.$endpoint_sha1;

        # Use cached response if at all possible.

        if (is_file($cache_file)) { // File exists?
            return $short_url = (string) file_get_contents($cache_file);
        }
        # Query for remote response via API endpoint URL.

        $response = $this->c::remoteRequest('GET::'.$endpoint, $request_args);

        # Validate response; no cache on any error.

        if ($response['code'] !== 200) {
            return $long_url; // Do not cache.
        }
        if (!is_object($json = json_decode($response['body']))) {
            return $long_url; // Do not cache.
        }
        if (!isset($json->status_txt) || $json->status_txt !== 'OK') {
            return $long_url; // Do not cache.
        }
        if (!isset($json->data->url) || !is_string($json->data->url)) {
            return $long_url; // Do not cache.
        }
        # Cache and return response.

        if (!is_dir($cache_dir)) {
            mkdir($cache_dir, $cache_dir_permissions, true);
        }
        $short_url = $json->data->url;
        file_put_contents($cache_file, $short_url);

        return $short_url;
    }

    /**
     * Link history.
     *
     * @since 160115 Bitly history.
     *
     * @param int   $page     Page.
     * @param int   $per_page Max per page.
     * @param array $args     Any additional args.
     *
     * @return array Link history array.
     */
    public function linkHistory(int $page = 1, int $per_page = 50, array $args = []): array
    {
        # Parse incoming arguments.

        $page     = max(1, $page);
        $per_page = max(1, $per_page);
        $offset   = ($page - 1) * $per_page;

        $default_args = [
            'access_token' => $this->App->Config->©bitly['©api_key'],
            'offset'       => $offset,
            'limit'        => $per_page,
            'private'      => 'off',
        ];
        $args = array_merge($default_args, $args);

        # Already cached this in memory?

        if (!is_null($history = &$this->cacheKey(__FUNCTION__, $args))) {
            return $history; // Cached this already.
        }
        # Prepare endpoint/request args.

        $endpoint_args = array_merge($args, [
            // Nothing more at this time.
        ]);
        $request_args = [
            'max_con_secs'    => 5,
            'max_stream_secs' => 5,
            'return'          => 'array',
        ];
        $endpoint = 'https://api-ssl.bitly.com/v3/user/link_history';
        $endpoint = $this->c::addUrlQueryArgs($endpoint_args, $endpoint);

        # Determine sharded cache directory and file.

        $endpoint_sha1         = sha1($endpoint);
        $cache_dir             = $this->cache_dir.'/'.$this->c::sha1ModShardId($endpoint_sha1, true);
        $cache_dir_permissions = $this->App->Config->©fs_permissions['©transient_dirs'];
        $cache_file            = $cache_dir.'/'.$endpoint_sha1;

        # Use cached response if at all possible.

        if (is_file($cache_file)) { // File exists?
            return $history = (array) unserialize(file_get_contents($cache_file));
        }
        # Query for remote response via API endpoint URL.

        $response = $this->c::remoteRequest('GET::'.$endpoint, $request_args);

        # Validate response; no cache on any error.

        if ($response['code'] !== 200) {
            return []; // Do not cache.
        }
        if (!is_object($json = json_decode($response['body']))) {
            return []; // Do not cache.
        }
        if (!isset($json->status_txt) || $json->status_txt !== 'OK') {
            return []; // Do not cache.
        }
        if (!isset($json->data->link_history) || !is_array($json->data->link_history)) {
            return []; // Do not cache.
        }
        # Cache and return response.

        if (!is_dir($cache_dir)) {
            mkdir($cache_dir, $cache_dir_permissions, true);
        }
        $history = $json->data->link_history;
        file_put_contents($cache_file, serialize($history));

        return $history;
    }
}


<?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\MapTypeControl;
use Ivory\GoogleMap\Helper\AbstractHelper;
use Ivory\GoogleMap\Helper\MapTypeIdHelper;

/**
 * Map type control helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class MapTypeControlHelper extends AbstractHelper
{
    /** @var \Ivory\GoogleMap\Helper\MapTypeIdHelper */
    protected $mapTypeIdHelper;

    /** @var \Ivory\GoogleMap\Helper\Controls\ControlPositionHelper */
    protected $controlPositionHelper;

    /** @var \Ivory\GoogleMap\Helper\Controls\MapTypeControleStyleHelper */
    protected $mapTypeControlStyleHelper;

    /**
     * Construct a map type control helper.
     *
     * @param \Ivory\GoogleMap\Helper\MapTypeIdHelper                     $mapTypeIdHelper           The map type ID helper.
     * @param \Ivory\GoogleMap\Helper\Controls\ControlPositionHelper      $controlPositionHelper     The control position helper.
     * @param \Ivory\GoogleMap\Helper\Controls\MapTypeControleStyleHelper $mapTypeControlStyleHelper The map type control style helper.
     */
    public function __construct(
        MapTypeIdHelper $mapTypeIdHelper = null,
        ControlPositionHelper $controlPositionHelper = null,
        MapTypeControlStyleHelper $mapTypeControlStyleHelper = null
    ) {
        parent::__construct();

        if ($mapTypeIdHelper === null) {
            $mapTypeIdHelper = new MapTypeIdHelper();
        }

        if ($controlPositionHelper === null) {
            $controlPositionHelper = new ControlPositionHelper();
        }

        if ($mapTypeControlStyleHelper === null) {
            $mapTypeControlStyleHelper = new MapTypeControlStyleHelper();
        }

        $this->setMapTypeIdHelper($mapTypeIdHelper);
        $this->setControlPositionHelper($controlPositionHelper);
        $this->setMapTypeControlStyleHelper($mapTypeControlStyleHelper);
    }

    /**
     * Gets the map type ID helper.
     *
     * @return \Ivory\GoogleMap\Helper\MapTypeIdHelper The map type ID helper.
     */
    public function getMapTypeIdHelper()
    {
        return $this->mapTypeIdHelper;
    }

    /**
     * Sets the map type ID helper.
     *
     * @param \Ivory\GoogleMap\Helper\MapTypeIdHelper $mapTypeIdHelper The map type ID helper.
     */
    public function setMapTypeIdHelper(MapTypeIdHelper $mapTypeIdHelper)
    {
        $this->mapTypeIdHelper = $mapTypeIdHelper;
    }

    /**
     * Gets the control position helper.
     *
     * @return \Ivory\GoogleMap\Helper\Controls\ControlPositionHelper The control position helper.
     */
    public function getControlPositionHelper()
    {
        return $this->controlPositionHelper;
    }

    /**
     * Sets the control position helper.
     *
     * @param \Ivory\GoogleMap\Helper\Controls\ControlPositionHelper $controlPositionHelper The control position helper.
     */
    public function setControlPositionHelper(ControlPositionHelper $controlPositionHelper)
    {
        $this->controlPositionHelper = $controlPositionHelper;
    }

    /**
     * Gets the map type control style helper.
     *
     * @return \Ivory\GoogleMap\Helper\Controls\MapTypeControlStyleHelper The map type control style helper.
     */
    public function getMapTypeControlStyleHelper()
    {
        return $this->mapTypeControlStyleHelper;
    }

    /**
     * Sets the map type control style helper.
     *
     * @param \Ivory\GoogleMap\Helper\Controls\MapTypeControlStyleHelper $mapTypeControlStyleHelper The map type
     *                                                                                control style
     *                                                                                helper.
     */
    public function setMapTypeControlStyleHelper(MapTypeControlStyleHelper $mapTypeControlStyleHelper)
    {
        $this->mapTypeControlStyleHelper = $mapTypeControlStyleHelper;
    }

    /**
     * Renders a map type control.
     *
     * @param \Ivory\GoogleMap\Controls\MapTypeControl $mapTypeControl The map type control.
     *
     * @return string The JS output.
     */
    public function render(MapTypeControl $mapTypeControl)
    {
        $this->jsonBuilder->reset();

        foreach ($mapTypeControl->getMapTypeIds() as $index => $mapTypeId) {
            $this->jsonBuilder->setValue(
                sprintf('[mapTypeIds][%d]', $index),
                $this->mapTypeIdHelper->render($mapTypeId),
                false
            );
        }

        return $this->jsonBuilder
            ->setValue(
                '[position]',
                $this->controlPositionHelper->render($mapTypeControl->getControlPosition()),
                false
            )
            ->setValue(
                '[style]',
                $this->mapTypeControlStyleHelper->render($mapTypeControl->getMapTypeControlStyle()),
                false
            )
            ->build();
    }
}


<?php
/**
 * Escape 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;

/**
 * Escape utils.
 *
 * @since 150424 Escape utils.
 */
class Escape extends Classes\Core\Base\Core
{
    /**
     * Escape single-quote.
     *
     * @since 160708 Quotes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function sq($value)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->sq($_value);
            } // unset($_key, $_value);
            return $value;
        }
        return str_replace("'", "\\'", (string) $value);
    }

    /**
     * Single-quote encapsulation.
     *
     * @since 160708 Quotes.
     *
     * @param mixed $value         Input value.
     * @param bool  $maybe_use_sld Maybe; i.e., detect string-literals?
     *
     * @return string|array|object Output value.
     *
     * --- When `$maybe_use_sld` = `true` ...
     *
     * String literals are detected automatically; e.g., `'an already-quoted string'`.
     *
     * @note This trims existing 'single' and/or "double" quoted encapsulations before quoting again.
     * For that reason, escaped quotes inside an already-quoted string are always escaped again.
     * So if you're going to quote a string literal, you should NOT escape inner quotes.
     *
     * e.g., `'Here's a good example, don't escape inner quotes.'`.
     *
     * @note This function is used by our Simple Expression parser.
     */
    public function singleQuote($value, bool $maybe_use_sld = false)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->singleQuote($_value);
            } // unset($_key, $_value);
            return $value;
        }
        $string = (string) $value;

        if ($maybe_use_sld) {
            if (!isset($string[0])) {
                return "''"; // Empty string.
            } elseif ($string === "''" || $string === '""') {
                return "''"; // Empty string.
            } elseif (mb_strpos($string, "'") === 0 && mb_substr($string, -1) === "'") {
                return "'".str_replace("'", "\\'", mb_substr($string, 1, -1))."'";
            } elseif (mb_strpos($string, '"') === 0 && mb_substr($string, -1) === '"') {
                return "'".str_replace("'", "\\'", mb_substr($string, 1, -1))."'";
            } else {
                return "'".str_replace("'", "\\'", $string)."'"; // Defaul behavior.
            }
        } else {
            return "'".str_replace("'", "\\'", $string)."'"; // Defaul behavior.
        }
    }

    /**
     * Escape double-quote.
     *
     * @since 160708 Quotes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function dq($value)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->sq($_value);
            } // unset($_key, $_value);
            return $value;
        }
        return str_replace('"', '\\"', (string) $value);
    }

    /**
     * Double-quote encapsulation.
     *
     * @since 160708 Quotes.
     *
     * @param mixed $value   Input value.
     * @param bool  $for_csv Changes quote-style for CSV compat.
     *                       CSV quoting requires the use of a double-quote as the escape char.
     *
     * @return string|array|object Output value.
     *
     * @WARNING Double-quotes, in most languages, result in evaluation.
     */
    public function doubleQuote($value, bool $for_csv = false)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->doubleQuote($_value);
            } // unset($_key, $_value);
            return $value;
        }
        return '"'.str_replace('"', $for_csv ? '""' : '\\"', (string) $value).'"';
    }

    /**
     * Escape HTML markup.
     *
     * @since 151122 Escapes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function html($value)
    {
        return $this->App->Utils->©HtmlEntities->encode($value);
    }

    /**
     * Escape HTML chars.
     *
     * @since 170124.74961 Escapes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function htmlChars($value)
    {
        return $this->App->Utils->©HtmlEntities->encode($value, false, ENT_HTML5 | ENT_NOQUOTES | ENT_SUBSTITUTE);
    }

    /**
     * Escape `<textarea>` value.
     *
     * @since 151122 Escapes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function textarea($value)
    {
        return $this->App->Utils->©HtmlEntities->encode($value);
    }

    /**
     * Escape `attr=""` (other).
     *
     * @since 151122 Escapes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function attr($value)
    {
        return $this->App->Utils->©HtmlEntities->encode($value);
    }

    /**
     * Escape URL in `attr=""`.
     *
     * @since 151122 Escapes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function url($value)
    {
        return $this->App->Utils->©HtmlEntities->encode($value);
    }

    /**
     * Escape shell arg(s).
     *
     * @since 160110 Escapes.
     *
     * @param mixed $value Input value.
     *
     * @return string|array|object Output value.
     */
    public function shellArg($value)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->shellArg($_value);
            } // unset($_key, $_value);
            return $value;
        }
        return escapeshellarg((string) $value);
    }

    // NOTE: SQL-related escapes are in the `Sql` class.
    // NOTE: Regex-related escapes are in the `RegexEscape` class.
}


<?php
/**
 * Dump 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;

/**
 * Dump utilities.
 *
 * @since 150424 Initial release.
 */
class Dump extends Classes\Core\Base\Core
{
    /**
     * A better `var_dump()`.
     *
     * @param mixed  $var               Any input variable/expression to dump.
     * @param bool   $return_only       Defaults to `false`; i.e., echo the dump.
     * @param int    $indent_size       Defaults to `4`; for spaced indentation.
     * @param string $indent_char       Defaults to ` `; indentation using spaces.
     * @param bool   $dump_circular_ids Defaults to a value of `false` (cleaner output).
     *                                  If `true`, circular IDs will be included in the dump.
     *                                  Helpful when trying to determine the origin of circular references.
     *
     * @return string A dump of the input `$var`.
     */
    public function __invoke($var, bool $return_only = false, int $indent_size = 2, string $indent_char = ' ', bool $dump_circular_ids = false): string
    {
        return $this->dump($var, $return_only, $indent_size, $indent_char, $dump_circular_ids);
    }

    /**
     * A better `var_dump()` (helper routine, by reference).
     *
     * @param mixed  $var                    Any input variable/expression to dump.
     * @param bool   $return_only            Defaults to `false`; i.e., echo the dump.
     * @param int    $indent_size            Defaults to `4`; for spaced indentation.
     * @param string $indent_char            Defaults to ` `; indentation using spaces.
     * @param bool   $dump_circular_ids      Defaults to a value of `false` (cleaner output).
     *                                       If `true`, circular IDs will be included in the dump.
     *                                       Helpful when trying to determine the origin of circular references.
     * @param int    $___current_indent_size Used in recursion. For internal use only.
     * @param array  $___nested_circular_ids Used in recursion. For internal use only.
     * @param bool   $___recursion           Tracks recursion. For internal use only.
     *
     * @return string A dump of the input `$var` (always in string format).
     *
     * @internal This method has built-in protection against circular references.
     * @internal This was benchmarked a few times against PHP's own `var_dump()`, and also against `print_r()`.
     *    This routine is NOT faster than `var_dump()`, but it is MUCH faster than `print_r()`.
     * @internal This routine MUST be very careful that it does NOT write to any variables.
     *    Writing to a variable (or to a variable reference) could cause damage in other routines.
     */
    protected function dump(
        &$var,
        bool $return_only,
        int $indent_size,
        string $indent_char,
        bool $dump_circular_ids,
        int $___current_indent_size = 0,
        array $___nested_circular_ids = [],
        bool $___recursion = false
    ): string {
        if (!$___recursion) {
            $indent_size = max(1, $indent_size);
        }
        switch (($type = $display_type = gettype($var))) {
            case 'object': // Iterates each object property.
            case 'array': // Or, each array key (if this is an array).
                $longest_nested_key_prop_length = 0;
                $nested_dumps                   = [];

                $dump_indent_size        = $___current_indent_size + ($indent_size * 1);
                $nested_dump_indent_size = $___current_indent_size + ($indent_size * 2);

                $current_indents     = str_repeat($indent_char, $___current_indent_size);
                $dump_indents        = $current_indents.str_repeat($indent_char, $dump_indent_size);
                $nested_dump_indents = $current_indents.str_repeat($indent_char, $nested_dump_indent_size);

                $opening_encap      = $type === 'object' ? '{' : '[';
                $closing_encap      = $type === 'object' ? '}' : ']';
                $key_prop_value_sep = $type === 'object' ? ': ' : ' => ';

                if ($type === 'object') {
                    $display_type = ($dump_circular_ids ? spl_object_hash($var).' ' : '').get_class($var).' object';
                } elseif ($type === 'array') {
                    $display_type = $dump_circular_ids ? sha1(serialize($var)) : '';
                }
                $var_dump = $display_type."\n".$dump_indents.$opening_encap."\n";

                foreach ($type === 'object' && method_exists($var, '__debugInfo')
                        ? $var->__debugInfo() // Use magic properties.
                        : $var as $_nested_key_prop => $_nested_value) {
                    // See: <http://php.net/manual/en/language.oop5.magic.php#object.debuginfo>
                    // Do NOT use `&`. Some iterators CANNOT be iterated by reference.
                    if (is_string($_nested_key_prop)) {
                        $_nested_key_prop = "'".$_nested_key_prop."'";
                    }
                    $_nested_key_prop_length = mb_strlen((string) $_nested_key_prop);
                    if ($_nested_key_prop_length > $longest_nested_key_prop_length) {
                        $longest_nested_key_prop_length = $_nested_key_prop_length;
                    }
                    switch (($_nested_type = $_nested_display_type = gettype($_nested_value))) {
                        case 'int':
                        case 'integer':
                            $_nested_display_type            = 'int';
                            $nested_dumps[$_nested_key_prop] = (string) $_nested_value;
                            break; // Break switch.

                        case 'real':
                        case 'double':
                        case 'float':
                            $_nested_display_type            = 'float';
                            $nested_dumps[$_nested_key_prop] = (string) $_nested_value;
                            break; // Break switch.

                        case 'bool':
                        case 'boolean':
                            $_nested_display_type            = 'bool';
                            $nested_dumps[$_nested_key_prop] = ($_nested_value) ? 'true' : 'false';
                            break; // Break switch.

                        case 'string':
                            $nested_dumps[$_nested_key_prop] = "'".$_nested_value."'";
                            break; // Break switch.

                        case 'object': // Recurses into object values.
                            $_nested_circular_id_key = spl_object_hash($_nested_value);
                            $_nested_display_type    = ($dump_circular_ids ? $_nested_circular_id_key.' ' : '').get_class($_nested_value).' object';

                            if (isset($___nested_circular_ids[$_nested_circular_id_key])) {
                                $nested_dumps[$_nested_key_prop] = $_nested_display_type.'{} *circular*';
                            } elseif (($___nested_circular_ids[$_nested_circular_id_key] = -1)
                                && ($_nested_dump = $this->dump(
                                    $_nested_value,
                                    true,
                                    $indent_size,
                                    $indent_char,
                                    $dump_circular_ids,
                                    $dump_indent_size,
                                    $___nested_circular_ids,
                                    true
                                ))) {
                                $nested_dumps[$_nested_key_prop] = $_nested_dump;
                            } else {
                                $nested_dumps[$_nested_key_prop] = $_nested_display_type.'{}';
                            }
                            unset($_nested_display_type, $_nested_circular_id_key, $_nested_dump);

                            break; // Break switch.

                        case 'array': // Recurses into array values.
                            $_nested_circular_id_key = sha1(serialize($_nested_value));
                            $_nested_display_type .= $dump_circular_ids ? $_nested_circular_id_key : '';

                            if (isset($___nested_circular_ids[$_nested_circular_id_key])) {
                                $nested_dumps[$_nested_key_prop] = $_nested_display_type.'[] *circular*';
                            } elseif (($___nested_circular_ids[$_nested_circular_id_key] = -1)
                                    && ($_nested_dump = $this->dump(
                                        $_nested_value,
                                        true,
                                        $indent_size,
                                        $indent_char,
                                        $dump_circular_ids,
                                        $dump_indent_size,
                                        $___nested_circular_ids,
                                        true
                                    ))) {
                                $nested_dumps[$_nested_key_prop] = $_nested_dump;
                            } else {
                                $nested_dumps[$_nested_key_prop] = $_nested_display_type.'[]';
                            }
                            unset($_nested_display_type, $_nested_circular_id_key, $_nested_dump);
                            break; // Break switch.

                        case 'null':
                        case 'NULL':
                            $_nested_display_type            = 'null';
                            $nested_dumps[$_nested_key_prop] = 'null';
                            break; // Break switch.

                        case 'resource':
                            $nested_dumps[$_nested_key_prop] = '['.(string) $_nested_value.']';
                            break; // Break switch.

                        case 'unknown':
                        case 'unknown type':
                        default: // Default case handler.
                            $_nested_display_type            = 'unknown';
                            $nested_dumps[$_nested_key_prop] = (string) $_nested_value;
                            break; // Break switch.
                    }
                }
                unset($_nested_key_prop, $_nested_value, $_nested_type, $_nested_key_prop_length);

                if ($nested_dumps) {
                    foreach ($nested_dumps as $_nested_key_prop => $_nested_dump) {
                        $_aligning_spaces = str_repeat(' ', $longest_nested_key_prop_length - mb_strlen((string) $_nested_key_prop));
                        $var_dump .= $nested_dump_indents.$_nested_key_prop.$_aligning_spaces.$key_prop_value_sep.$_nested_dump."\n";
                    }
                    unset($_nested_key_prop, $_nested_dump, $_aligning_spaces);

                    $var_dump = $var_dump.$dump_indents.$closing_encap;
                } else {
                    $var_dump = $this->c::mbRTrim($var_dump, "\n".$indent_char.$opening_encap).$opening_encap.$closing_encap;
                }
                break; // Break switch.

            // Everything else is MUCH simpler to handle.

            case 'int':
            case 'integer':
                $display_type = 'int';
                $var_dump     = (string) $var;
                break; // Break switch.

            case 'real':
            case 'double':
            case 'float':
                $display_type = 'float';
                $var_dump     = '(float) '.(string) $var;
                break; // Break switch.

            case 'bool':
            case 'boolean':
                $display_type = 'bool';
                $var_dump     = $var ? 'true' : 'false';
                break; // Break switch.

            case 'string':
                $var_dump = "'".$var."'";
                break; // Break switch.

            case 'null':
            case 'NULL':
                $display_type = 'null';
                $var_dump     = 'null';
                break; // Break switch.

            case 'resource':
                $var_dump = '['.(string) $var.']';
                break; // Break switch.

            case 'unknown':
            case 'unknown type':
            default: // Default case handler.
                $display_type = 'unknown';
                $var_dump     = (string) $var;
                break; // Break switch.
        }
        if (!$return_only) {
            echo $var_dump."\n";
        }
        return $var_dump;
    }
}


<?php

namespace webignition\InternetMediaType\Parameter\Parser;

use webignition\InternetMediaType\Parameter\Parameter;
use webignition\InternetMediaType\Parser\Configuration;
use webignition\InternetMediaTypeInterface\ParameterInterface;

/**
 * Parses a parameter string value into a Parameter object
 *
 * Defined as:
 *
 * parameter               = attribute "=" value
 * attribute               = token
 * value                   = token | quoted-string
 *
 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6
 *
 * Linear white space (LWS) MUST NOT be used between the type and subtype, nor between an attribute and its value.
 *
 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
 *
 */
class Parser
{
    /**
     * @var Configuration
     */
    private $configuration;

    public function __construct()
    {
        $this->configuration = new Configuration();
    }

    public function setConfiguration(Configuration  $configuration)
    {
        $this->configuration = $configuration;
    }

    public function getConfiguration(): Configuration
    {
        return $this->configuration;
    }

    /**
     * @param string $parameterString
     *
     * @return ParameterInterface
     *
     * @throws AttributeParserException
     */
    public function parse(string $parameterString): ParameterInterface
    {
        $inputString = trim($parameterString);
        $attribute = $this->createAttributeParser()->parse($inputString);

        if (empty($attribute)) {
            return new Parameter('', '');
        }

        $value = $this->createValueParser($attribute)->parse($parameterString);

        $parameter = new Parameter($attribute, $value);

        return $parameter;
    }

    private function createAttributeParser(): AttributeParser
    {
        $attributeParser = new AttributeParser();
        $attributeParser->setConfiguration($this->getConfiguration());

        return $attributeParser;
    }

    private function createValueParser(string $attribute): ValueParser
    {
        $valueParser = new ValueParser();
        $valueParser->setAttribute($attribute);
        return $valueParser;
    }
}


<?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\MapTypeControlStyle;
use Ivory\GoogleMap\Exception\HelperException;

/**
 * Map type control style helper.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class MapTypeControlStyleHelper
{
    /**
     * Renders a map type control style.
     *
     * @param string $mapTypeControlStyle The map type control style.
     *
     * @throws \Ivory\GoogleMap\Exception\ControlException If the map type control style is not valid.
     *
     * @return string The JS output.
     */
    public function render($mapTypeControlStyle)
    {
        switch ($mapTypeControlStyle) {
            case MapTypeControlStyle::DEFAULT_:
            case MapTypeControlStyle::DROPDOWN_MENU:
            case MapTypeControlStyle::HORIZONTAL_BAR:
                return sprintf('google.maps.MapTypeControlStyle.%s', strtoupper($mapTypeControlStyle));
            default:
                throw HelperException::invalidMapTypeControlStyle();
        }
    }
}


<?php
namespace Perry\Representation\Eve\v1;

use \Perry\Representation\Reference as Reference;
use \Perry\Representation\Uri as Uri;
use \Perry\Representation\Base as Base;

class Alliance extends Base
{
    public $startDate;

    public $corporationsCount;

    public $description;

    public $executorCorporation;

    public $primeHour;

    public $deleted;

    public $creatorCorporation;

    public $url;

    public $creatorCharacter;

    public $capitalSystem;

    public $corporations = [];

    public $shortName;

    public $id;

    public $name;

    // by Warringer\Types\String
    public function setStartDate($startDate)
    {
        $this->startDate = $startDate;
    }

    // by Warringer\Types\Long
    public function setCorporationsCount($corporationsCount)
    {
        $this->corporationsCount = $corporationsCount;
    }

    // by Warringer\Types\String
    public function setDescription($description)
    {
        $this->description = $description;
    }

    // by Warringer\Types\Dict
    public function setExecutorCorporation($executorCorporation)
    {
        // by Warringer\Types\Dict
        $converters = [];
        $converters['isNPC'] = function ($value) { return $value; };
        $converters['logo'] = function ($value) { return $value; };
        $converters['href'] = function ($value) { return new Uri($value); };
        $converters['id'] = function ($value) { return $value; };
        $converters['name'] = function ($value) { return $value; };

        $func = function ($value) use($converters) {
            $return = new \ArrayObject($value, \ArrayObject::ARRAY_AS_PROPS);
            $return['isNPC'] = isset($value->{'isNPC'}) ? $converters['isNPC']($value->{'isNPC'}) : null;
            $return['logo'] = isset($value->{'logo'}) ? $converters['logo']($value->{'logo'}) : null;
            $return['href'] = isset($value->{'href'}) ? $converters['href']($value->{'href'}) : null;
            $return['id'] = isset($value->{'id'}) ? $converters['id']($value->{'id'}) : null;
            $return['name'] = isset($value->{'name'}) ? $converters['name']($value->{'name'}) : null;
            return $return;
        };
        $this->executorCorporation = $func($executorCorporation);
    }

    // by Warringer\Types\Long
    public function setPrimeHour($primeHour)
    {
        $this->primeHour = $primeHour;
    }

    // by Warringer\Types\Base
    public function setDeleted($deleted)
    {
        $this->deleted = $deleted;
    }

    // by Warringer\Types\Dict
    public function setCreatorCorporation($creatorCorporation)
    {
        // by Warringer\Types\Dict
        $converters = [];
        $converters['isNPC'] = function ($value) { return $value; };
        $converters['logo'] = function ($value) { return $value; };
        $converters['href'] = function ($value) { return new Uri($value); };
        $converters['id'] = function ($value) { return $value; };
        $converters['name'] = function ($value) { return $value; };

        $func = function ($value) use($converters) {
            $return = new \ArrayObject($value, \ArrayObject::ARRAY_AS_PROPS);
            $return['isNPC'] = isset($value->{'isNPC'}) ? $converters['isNPC']($value->{'isNPC'}) : null;
            $return['logo'] = isset($value->{'logo'}) ? $converters['logo']($value->{'logo'}) : null;
            $return['href'] = isset($value->{'href'}) ? $converters['href']($value->{'href'}) : null;
            $return['id'] = isset($value->{'id'}) ? $converters['id']($value->{'id'}) : null;
            $return['name'] = isset($value->{'name'}) ? $converters['name']($value->{'name'}) : null;
            return $return;
        };
        $this->creatorCorporation = $func($creatorCorporation);
    }

    // by Warringer\Types\String
    public function setUrl($url)
    {
        $this->url = $url;
    }

    // by Warringer\Types\Dict
    public function setCreatorCharacter($creatorCharacter)
    {
        // by Warringer\Types\Dict
        $converters = [];
        $converters['name'] = function ($value) { return $value; };
        $converters['isNPC'] = function ($value) { return $value; };
        $converters['mercenary'] = function ($value) { return new Reference($value); };
        $converters['href'] = function ($value) { return new Uri($value); };
        $converters['capsuleer'] = function ($value) { return new Reference($value); };
        $converters['portrait'] = function ($value) { return $value; };
        $converters['id'] = function ($value) { return $value; };

        $func = function ($value) use($converters) {
            $return = new \ArrayObject($value, \ArrayObject::ARRAY_AS_PROPS);
            $return['name'] = isset($value->{'name'}) ? $converters['name']($value->{'name'}) : null;
            $return['isNPC'] = isset($value->{'isNPC'}) ? $converters['isNPC']($value->{'isNPC'}) : null;
            $return['mercenary'] = isset($value->{'mercenary'}) ? $converters['mercenary']($value->{'mercenary'}) : null;
            $return['href'] = isset($value->{'href'}) ? $converters['href']($value->{'href'}) : null;
            $return['capsuleer'] = isset($value->{'capsuleer'}) ? $converters['capsuleer']($value->{'capsuleer'}) : null;
            $return['portrait'] = isset($value->{'portrait'}) ? $converters['portrait']($value->{'portrait'}) : null;
            $return['id'] = isset($value->{'id'}) ? $converters['id']($value->{'id'}) : null;
            return $return;
        };
        $this->creatorCharacter = $func($creatorCharacter);
    }

    // by Warringer\Types\Dict
    public function setCapitalSystem($capitalSystem)
    {
        // by Warringer\Types\Dict
        $converters = [];
        $converters['href'] = function ($value) { return new Uri($value); };
        $converters['id'] = function ($value) { return $value; };
        $converters['name'] = function ($value) { return $value; };

        $func = function ($value) use($converters) {
            $return = new \ArrayObject($value, \ArrayObject::ARRAY_AS_PROPS);
            $return['href'] = isset($value->{'href'}) ? $converters['href']($value->{'href'}) : null;
            $return['id'] = isset($value->{'id'}) ? $converters['id']($value->{'id'}) : null;
            $return['name'] = isset($value->{'name'}) ? $converters['name']($value->{'name'}) : null;
            return $return;
        };
        $this->capitalSystem = $func($capitalSystem);
    }

    // by Warringer\Types\ArrayType
    public function setCorporations($corporations)
    {
        // by Warringer\Types\Dict
        $converters = [];
        $converters['isNPC'] = function ($value) { return $value; };
        $converters['logo'] = function ($value) { return $value; };
        $converters['href'] = function ($value) { return new Uri($value); };
        $converters['id'] = function ($value) { return $value; };
        $converters['name'] = function ($value) { return $value; };

        $func = function ($value) use($converters) {
            $return = new \ArrayObject($value, \ArrayObject::ARRAY_AS_PROPS);
            $return['isNPC'] = isset($value->{'isNPC'}) ? $converters['isNPC']($value->{'isNPC'}) : null;
            $return['logo'] = isset($value->{'logo'}) ? $converters['logo']($value->{'logo'}) : null;
            $return['href'] = isset($value->{'href'}) ? $converters['href']($value->{'href'}) : null;
            $return['id'] = isset($value->{'id'}) ? $converters['id']($value->{'id'}) : null;
            $return['name'] = isset($value->{'name'}) ? $converters['name']($value->{'name'}) : null;
            return $return;
        };

        foreach ($corporations as $key => $value) {
            $this->corporations[$key] = $func($value);
        }
    }

    // by Warringer\Types\String
    public function setShortName($shortName)
    {
        $this->shortName = $shortName;
    }

    // by Warringer\Types\Long
    public function setId($id)
    {
        $this->id = $id;
    }

    // by Warringer\Types\String
    public function setName($name)
    {
        $this->name = $name;
    }

}


<?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;

/**
 * Google Map business account.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class BusinessAccount
{
    /** @var string */
    protected $clientId;

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

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

    /**
     * Creates a business account.
     *
     * @param string $clientId The client identifier.
     * @param string $secret   The secret.
     * @param string $channel  The channel.
     */
    public function __construct($clientId, $secret, $channel = null)
    {
        $this->setClientId($clientId);
        $this->setSecret($secret);
        $this->setChannel($channel);
    }

    /**
     * Gets the client identifier.
     *
     * @return string The client identifier.
     */
    public function getClientId()
    {
        return $this->clientId;
    }

    /**
     * Sets the client identifier.
     *
     * @param string $clientId The client identifier.
     */
    public function setClientId($clientId)
    {
        $this->clientId = $clientId;
    }

    /**
     * Gets the secret.
     *
     * @return string The secret.
     */
    public function getSecret()
    {
        return $this->secret;
    }

    /**
     * Sets the secret.
     *
     * @param string $secret The secret.
     */
    public function setSecret($secret)
    {
        $this->secret = $secret;
    }

    /**
     * Checks if the business account has a channel.
     *
     * @return boolean TRUE if the business account has a channel else FALSE.
     */
    public function hasChannel()
    {
        return $this->channel !== null;
    }

    /**
     * Sets the channel.
     *
     * @return string The channel.
     */
    public function getChannel()
    {
        return $this->channel;
    }

    /**
     * Sets the channel.
     *
     * @param string $channel The channel.
     */
    public function setChannel($channel)
    {
        $this->channel = $channel;
    }

    /**
     * Sign an url for business purpose.
     *
     * @param string $url The url.
     *
     * @return string The signed url.
     */
    public function signUrl($url)
    {
        $url .= sprintf('&client=gme-%s', $this->clientId);

        if ($this->hasChannel()) {
            $url .= sprintf('&channel=%s', $this->channel);
        }

        $urlParts = parse_url($url);
        $data = sprintf('%s?%s', $urlParts['path'], $urlParts['query']);
        $key = base64_decode(str_replace(array('-', '_'), array('+', '/'), $this->secret));
        $signature = base64_encode(hash_hmac('sha1', $data, $key, true));

        $url .= sprintf('&signature=%s', str_replace(array('+', '/'), array('-', '_'), $signature));

        return $url;
    }
}


<?php
/**
 * Search terms.
 *
 * @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;

/**
 * Search terms.
 *
 * @since 161006 Search terms.
 */
class SearchTerms extends Classes\Core\Base\Core
{
    /**
     * Get search highlighter.
     *
     * @since 161006 Search terms.
     *
     * @param string $q    Input search query.
     * @param array  $args Additional arguments.
     *
     * @return Classes\Core\SearchTermHighlighter Instance.
     */
    public function getHighlighter(string $q, array $args = []): Classes\Core\SearchTermHighlighter
    {
        return $this->App->Di->get(Classes\Core\SearchTermHighlighter::class, compact('q', 'args'));
    }
}


<?php
/**
 * SHA-1 modulus.
 *
 * @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;

/**
 * SHA-1 modulus.
 *
 * @since 150424 SHA-1 modulus.
 */
class Sha1Mod extends Classes\Core\Base\Core
{
    /**
     * Total MySQL DB shards.
     *
     * @since 160225 SHA-1 modulus.
     *
     * @type int Total MySQL DB shards.
     */
    protected $total_mysql_db_shards;

    /**
     * Class constructor.
     *
     * @since 150424 SHA-1 modulus.
     *
     * @param Classes\App $App Instance of App.
     */
    public function __construct(Classes\App $App)
    {
        parent::__construct($App);

        $this->total_mysql_db_shards = count($this->App->Config->©mysql_db['©shards']);
    }

    /**
     * SHA-1 modulus.
     *
     * @since 150424 SHA-1 modulus.
     *
     * @param string $string  String or a SHA-1 hash.
     * @param int    $divisor Maximum allowable value.
     * @param bool   $is_sha1 String is already a SHA-1 hash?
     *
     * @return int SHA-1 modulus.
     */
    public function __invoke(string $string, int $divisor, bool $is_sha1 = false): int
    {
        if ($is_sha1) {
            if (!$this->c::isSha1($sha1 = $string)) {
                throw $this->c::issue('Invalid SHA-1 hash.');
            }
        } else {
            $sha1 = sha1($string);
        }
        $sha1_first_15 = substr($sha1, 0, 15);
        $dividend      = hexdec($sha1_first_15);
        $divisor       = max(1, $divisor);

        return $dividend % $divisor;
    }

    /**
     * SHA-1 modulus shard ID.
     *
     * @since 150424 SHA-1 modulus.
     *
     * @param string $string       String or a SHA-1 hash.
     * @param bool   $is_sha1      String is already a SHA-1 hash?
     * @param int    $total_shards Total shards; defaults to `65536`.
     *
     * @return int SHA-1 modulus; i.e., a shard ID.
     *
     * @internal Shard IDs are always zero-based, because a modulus will never be >= to the divisor.
     *  If `$total_shards is `65536`, min shard ID is `0`, max shard ID is `65535`.
     */
    public function shardId(string $string, bool $is_sha1 = false, int $total_shards = 65536): int
    {
        return $this->__invoke($string, $total_shards, $is_sha1);
    }

    /**
     * Assign shard ID.
     *
     * @since 150424 SHA-1 modulus.
     *
     * @param string $string  String or a SHA-1 hash.
     * @param bool   $is_sha1 String is already a SHA-1 hash?
     *
     * @return int Assigned shard ID; based on `sha1($string)`.
     *
     * @internal This one is based on the actual number of configured shards;
     *  i.e., not on the upper limit of the shard ID itself. `65536` is not used here.
     */
    public function assignShardId(string $string, bool $is_sha1 = false)
    {
        if ($this->total_mysql_db_shards < 1) {
            throw $this->c::issue('No MySQL DB shards available.');
        }
        return $this->shardId($string, $is_sha1, $this->total_mysql_db_shards);
    }
}


<?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\Directions;

use Ivory\GoogleMap\Base\Coordinate;
use Ivory\GoogleMap\Exception\DirectionsException;
use Ivory\GoogleMap\Overlays\EncodedPolyline;
use Ivory\GoogleMap\Services\Base\Distance;
use Ivory\GoogleMap\Services\Base\Duration;
use Ivory\GoogleMap\Services\Base\TravelMode;

/**
 * A directions step which describes a google map directions step.
 *
 * @see http://code.google.com/apis/maps/documentation/javascript/reference.html#DirectionsStep
 * @author GeLo <geloen.eric@gmail.com>
 */
class DirectionsStep
{
    /** @var \Ivory\GoogleMap\Services\Base\Distance */
    protected $distance;

    /** @var \Ivory\GoogleMap\Services\Base\Duration */
    protected $duration;

    /** @var \Ivory\GoogleMap\Base\Coordinate */
    protected $endLocation;

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

    /** @var \Ivory\GoogleMap\Overlays\EncodedPolyline */
    protected $encodedPolyline;

    /** @var \Ivory\GoogleMap\Base\Coordinate */
    protected $startLocation;

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

    /**
     * Creates a directions step.
     *
     * @param \Ivory\GoogleMap\Services\Base\Distance   $distance        The distance.
     * @param \Ivory\GoogleMap\Services\Base\Duration   $duration        The duration.
     * @param \Ivory\GoogleMap\Base\Coordinate          $endLocation     The end location.
     * @param string                                    $instructions    The instructions.
     * @param \Ivory\GoogleMap\Overlays\EncodedPolyline $encodedPolyline The encoded polyline.
     * @param \Ivory\GoogleMap\Base\Coordinate          $startLocation   The start location.
     * @param string                                    $travelMode      The travel mode.
     */
    public function __construct(
        Distance $distance,
        Duration $duration,
        Coordinate $endLocation,
        $instructions,
        EncodedPolyline $encodedPolyline,
        Coordinate $startLocation,
        $travelMode
    ) {
        $this->setDistance($distance);
        $this->setDuration($duration);
        $this->setEndLocation($endLocation);
        $this->setInstructions($instructions);
        $this->setEncodedPolyline($encodedPolyline);
        $this->setStartLocation($startLocation);
        $this->setTravelMode($travelMode);
    }

    /**
     * Gets the step distance.
     *
     * @return \Ivory\GoogleMap\Services\Base\Distance The step distance.
     */
    public function getDistance()
    {
        return $this->distance;
    }

    /**
     * Sets the step distance.
     *
     * @param \Ivory\GoogleMap\Services\Base\Distance $distance The step distance.
     */
    public function setDistance(Distance $distance)
    {
        $this->distance = $distance;
    }

    /**
     * Gets the step duration.
     *
     * @return \Ivory\GoogleMap\Services\Base\Duration The step duration.
     */
    public function getDuration()
    {
        return $this->duration;
    }

    /**
     * Sets the step duration
     *
     * @param \Ivory\GoogleMap\Services\Base\Duration $duration The step duration.
     */
    public function setDuration(Duration $duration)
    {
        $this->duration = $duration;
    }

    /**
     * Gets the step end location.
     *
     * @return \Ivory\GoogleMap\Base\Coordinate The step end location.
     */
    public function getEndLocation()
    {
        return $this->endLocation;
    }

    /**
     * Sets the step end location.
     *
     * @param \Ivory\GoogleMap\Base\Coordinate $endLocation The step end location.
     */
    public function setEndLocation(Coordinate $endLocation)
    {
        $this->endLocation = $endLocation;
    }

    /**
     * Gets the step instructions.
     *
     * @return string The step instructions.
     */
    public function getInstructions()
    {
        return $this->instructions;
    }

    /**
     * Sets the step instructions.
     *
     * @param string $instructions The step instructions.
     *
     * @throws \Ivory\GoogleMap\Exception\DirectionsException If the instructions is not valid.
     */
    public function setInstructions($instructions)
    {
        if (!is_string($instructions)) {
            throw DirectionsException::invalidDirectionsStepInstructions();
        }

        $this->instructions = $instructions;
    }

    /**
     * Gets the encoded polyline which describes the step.
     *
     * @return \Ivory\GoogleMap\Overlays\EncodedPolyline The encoded polyline.
     */
    public function getEncodedPolyline()
    {
        return $this->encodedPolyline;
    }

    /**
     * Sets the encoded polyline which describes the step.
     *
     * @param \Ivory\GoogleMap\Overlays\EncodedPolyline $encodedPolyline The encoded polyline.
     */
    public function setEncodedPolyline(EncodedPolyline $encodedPolyline)
    {
        $this->encodedPolyline = $encodedPolyline;
    }

    /**
     * Gets the step start location.
     *
     * @return \Ivory\GoogleMap\Base\Coordinate The step start location.
     */
    public function getStartLocation()
    {
        return $this->startLocation;
    }

    /**
     * Sets the step start location.
     *
     * @param \Ivory\GoogleMap\Base\Coordinate $startLocation The step start position.
     */
    public function setStartLocation(Coordinate $startLocation)
    {
        $this->startLocation = $startLocation;
    }

    /**
     * Gets the step travel mode.
     *
     * @return string The step travel mode.
     */
    public function getTravelMode()
    {
        return $this->travelMode;
    }

    /**
     * Sets the step travel mode.
     *
     * @param string $travelMode The step travel mode.
     *
     * @throws \Ivory\GoogleMap\Exception\DirectionsException If the travel mode is not valid.
     */
    public function setTravelMode($travelMode)
    {
        if (!in_array($travelMode, TravelMode::getTravelModes())) {
            throw DirectionsException::invalidDirectionsStepTravelMode();
        }

        $this->travelMode = $travelMode;
    }
}


<?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\Assets;

use Ivory\GoogleMap\Exception\AssetException;

/**
 * Allow easy generation of unique javascript variable for any class model that requires it.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
abstract class AbstractJavascriptVariableAsset
{
    /** @var string */
    protected $javascriptVariable;

    /**
     * Creates a javascript variable asset.
     */
    public function __construct($javascriptVariable = null)
    {
        if ($javascriptVariable === null) {
            $javascriptVariable = $this->generateJavascriptVariable();
        }

        $this->setJavascriptVariable($javascriptVariable);
    }

    /**
     * Sets the prefix of the javascript variable.
     *
     * @param string $prefixJavascriptVariable The prefix of the javascript variable.
     *
     * @throws \Ivory\GoogleMap\Exception\AssetException If the prefix javascript variable is not valid.
     */
    public function setPrefixJavascriptVariable($prefixJavascriptVariable)
    {
        if (!is_string($prefixJavascriptVariable)) {
            throw AssetException::invalidPrefixJavascriptVariable();
        }

        $this->javascriptVariable = $this->generateJavascriptVariable($prefixJavascriptVariable);
    }

    /**
     * Gets the javascript variable which describes the asset.
     *
     * @return string The javascript variable.
     */
    public function getJavascriptVariable()
    {
        return $this->javascriptVariable;
    }

    /**
     * Sets the javascript variable which describes the asset
     *
     * @param string $javascriptVariable The javascript variable.
     *
     * @throws \Ivory\GoogleMap\Exception\AssetException If the javascript variable is not valid.
     */
    public function setJavascriptVariable($javascriptVariable)
    {
        if (!is_string($javascriptVariable)) {
            throw AssetException::invalidJavascriptVariable();
        }

        $this->javascriptVariable = $javascriptVariable;
    }

    /**
     * Generates a unique javascript variable which can be prefixed.
     *
     * @param string $prefix The prefix.
     *
     * @return string The unique javascript variable.
     */
    protected function generateJavascriptVariable($prefix = null)
    {
        return str_replace('.', '', uniqid($prefix, true));
    }
}


<?php
/**
 * Country 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 League\ISO3166\ISO3166;

/**
 * Country utilities.
 *
 * @since 170329.13807 Country utils.
 */
class Country extends Classes\Core\Base\Core
{
    /**
     * ISO3166.
     *
     * @since 170329.13807
     *
     * @type ISO3166.
     */
    protected $ISO3166;

    /**
     * Class constructor.
     *
     * @since 170329.13807 Stripe utils.
     *
     * @param Classes\App $App Instance of App.
     */
    public function __construct(Classes\App $App)
    {
        parent::__construct($App);

        $this->ISO3166 = new ISO3166();
    }

    /**
     * Select menu options.
     *
     * @since 170329.13807 Country utils.
     *
     * @param string $selected Selected value.
     * @param array  $args     Any behavioral args.
     *
     * @return string HTML markup.
     */
    public function selectOptions(string $selected = '', array $args = []): string
    {
        $default_args = [
            'ip'     => null,
            'use_ip' => true,
        ];
        $args += $default_args;

        $is_cli = $this->c::isCli();

        if (!isset($args['ip']) && $args['use_ip']) {
            $args['ip'] = $is_cli ? '' : $this->c::currentIp();
        }
        $args['ip']     = (string) $args['ip'];
        $args['use_ip'] = (bool) $args['use_ip'];

        if (!$selected && $args['ip'] && $args['use_ip']) {
            $selected = $is_cli ? '' : $this->c::ipCountry($args['ip']);
        }
        $markup   = ''; // Initialize.
        $selected = mb_strtoupper($selected);

        foreach ($this->ISO3166->getAll() as $_country) {
            $markup .= '<option value="'.$_country['alpha2'].'"'.($selected ? $this->c::selected($selected, $_country['alpha2']) : '').'>'.$_country['name'].'</option>';
        } // unset($_country); // Housekeeping.

        return $markup;
    }

    /**
     * Dropdown menu items.
     *
     * @since 170329.13807 Country utils.
     *
     * @param string $active Active value.
     * @param array  $args   Any behavioral args.
     *
     * @return string HTML markup.
     */
    public function dropdownItems(string $active = '', array $args = []): string
    {
        $default_args = [
            'ip'     => null,
            'use_ip' => true,
            'flags'  => false,
        ];
        $args += $default_args;

        $is_cli = $this->c::isCli();

        if (!isset($args['ip']) && $args['use_ip']) {
            $args['ip'] = $is_cli ? '' : $this->c::currentIp();
        }
        $args['ip']     = (string) $args['ip'];
        $args['use_ip'] = (bool) $args['use_ip'];
        $args['flags']  = (bool) $args['flags'];

        if (!$active && $args['ip'] && $args['use_ip']) {
            $active = $is_cli ? '' : $this->c::ipCountry($args['ip']);
        }
        $markup = ''; // Initialize.
        $active = mb_strtoupper($active);

        foreach ($this->ISO3166->getAll() as $_country) {
            $_alpha2_lc = mb_strtolower($_country['alpha2']);
            $_flag      = $args['flags'] ? '' : '';
            $markup .= '
c::activeSelected($active, $_country['alpha2']) : '').'" data-value="'.$_country['alpha2'].'">'.$_flag.$_country['name'].'
';
        } // unset($_country, $_alpha2_lc, $_flag); // Housekeeping.

        return $markup;
    }
}