<?php

namespace League\StackRobots;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class Robots implements HttpKernelInterface
{
    /**
     * @var \Symfony\Component\HttpKernel\HttpKernelInterface
     */
    private $app;

    /**
     * @var string
     */
    private $env;

    /**
     * @var string
     */
    private $envVar;

    /**
     * Constructor
     *
     * @param HttpKernelInterface $app
     * @param string              $env    The environment variable to compare against.
     * @param string              $envVar The environment variable to inspect.
     */
    public function __construct(HttpKernelInterface $app, $env = 'production', $envVar = 'SERVER_ENV')
    {
        $this->app = $app;
        $this->env = $env;
        $this->envVar = $envVar;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
    {
        if (getenv($this->envVar) !== $this->env) {
            if ($request->getPathInfo() === '/robots.txt') {
                return new Response("User-Agent: *\nDisallow: /", 200, array('Content-Type' => 'text/plain'));
            }

            $response = $this->app->handle($request, $type, $catch);

            $response->headers->set('X-Robots-Tag', 'noindex, nofollow, noarchive');

            return $response;
        }

        return $this->app->handle($request, $type, $catch);
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Templating\Twig\Bridge;

use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\Templating\StreamingEngineInterface;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
 * This engine knows how to render Twig templates.
 *
 * @author Tom Ellis
 *
 * Heavily based on the original by
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TwigEngine implements EngineInterface, StreamingEngineInterface
{
    /**
     * @var \Twig_Environment
     */
    protected $environment;

    /**
     * @var TemplateNameParserInterface
     */
    protected $parser;

    /**
     * Constructor.
     *
     * @param \Twig_Environment           $environment A \Twig_Environment instance
     * @param TemplateNameParserInterface $parser      A TemplateNameParserInterface instance
     */
    public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser)
    {
        $this->environment = $environment;
        $this->parser = $parser;
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     *
     * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template
     */
    public function render($name, array $parameters = array())
    {
        return $this->load($name)->render($parameters);
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     *
     * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template
     */
    public function stream($name, array $parameters = array())
    {
        $this->load($name)->display($parameters);
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     */
    public function exists($name)
    {
        if ($name instanceof \Twig_Template) {
            return true;
        }

        $loader = $this->environment->getLoader();

        if ($loader instanceof \Twig_ExistsLoaderInterface || method_exists($loader, 'exists')) {
            return $loader->exists((string) $name);
        }

        try {
            // cast possible TemplateReferenceInterface to string because the
            // EngineInterface supports them but Twig_LoaderInterface does not
            $loader->getSourceContext((string) $name)->getCode();
        } catch (\Twig_Error_Loader $e) {
            return false;
        }

        return true;
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     */
    public function supports($name)
    {
        if ($name instanceof \Twig_Template) {
            return true;
        }

        $template = $this->parser->parse($name);

        return 'twig' === $template->get('engine');
    }

    /**
     * Loads the given template.
     *
     * @param string|TemplateReferenceInterface|\Twig_Template $name A template name or an instance of
     *                                                               TemplateReferenceInterface or \Twig_Template
     *
     * @return \Twig_TemplateInterface A \Twig_TemplateInterface instance
     *
     * @throws \InvalidArgumentException if the template does not exist
     */
    protected function load($name)
    {
        if ($name instanceof \Twig_Template) {
            return $name;
        }

        try {
            return $this->environment->loadTemplate((string) $name);
        }
        catch (\Twig_Error_Loader $e) {
            throw new \InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Config;

use Tomahawk\Common\Str;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Config\Loader\LoaderInterface;

class ConfigManager implements ConfigInterface
{
    /**
     * @var LoaderInterface
     */
    protected $loader;

    /**
     * @var Finder
     */
    protected $finder;

    /**
     * @var
     */
    protected $configDirectories;

    /**
     * @var array
     */
    protected $config = array();

    /**
     * @var array
     */
    protected $parsed = array();

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

    public function __construct(LoaderInterface $loader, $configDirectories, $cacheFile = null)
    {
        $this->loader = $loader;
        $this->configDirectories = $configDirectories;
        $this->cacheFile = $cacheFile;
    }

    /**
     * @param null $key
     * @param null $default
     * @return array|null
     */
    public function get($key = null, $default = null)
    {
        return $this->arrayGet($this->config, $key, $default);
    }

    /**
     * @param $key
     * @param $value
     * @return $this
     */
    public function set($key, $value)
    {
        $this->arraySet($this->config, $key, $value);
        return $this;
    }

    /**
     * Check if a config value exists
     *
     * @param $key
     * @return bool
     */
    public function has($key)
    {
        $default = get_class() . time();

        return $default !== $this->get($key, $default);
    }

    /**
     * Load config files
     *
     * @param bool|false $force
     */
    public function load($force = false)
    {
        $this->config = array();

        // Check if we have a compiled cached file
        if ( ! $force && $this->cacheFile && file_exists($this->cacheFile)) {
            $this->config = include($this->cacheFile);
            return;
        }

        foreach ($this->configDirectories as $configDirectory) {

            $finder = new Finder();
            $finder->in($configDirectory)->depth('== 0')->files()->name('*.php');

            foreach ($finder as $file) {
                /**
                 * @var \Symfony\Component\Finder\SplFileInfo $file
                 */

                // If file starts with config_ its a compiled one so ignore
                if (Str::is($file->getFilename(), '*config_*')) {
                    continue;
                }

                $configName = substr($file->getFilename(), 0, -4);

                $values = $this->loader->load($file->getRealPath());

                foreach ($values as $config => $value) {

                    $key = sprintf('%s.%s', $configName, $config);

                    $this->set($key, $value);
                }
            }
        }

    }

    /**
     * Set an array item to a given value using "dot" notation.
     *
     * If no key is given to the method, the entire array will be replaced.
     *
     * @param  array   $array
     * @param  string  $key
     * @param  mixed   $value
     * @return array
     */
    protected function arraySet(&$array, $key, $value)
    {
        if (is_null($key)) {
            return $array = $value;
        }

        $keys = explode('.', $key);

        while (count($keys) > 1) {

            $key = array_shift($keys);

            // If the key doesn't exist at this depth, we will just create an empty array
            // to hold the next value, allowing us to create the arrays to hold final
            // values at the correct depth. Then we'll keep digging into the array.
            if ( ! isset($array[$key]) || ! is_array($array[$key])) {
                $array[$key] = array();
            }

            $array =& $array[$key];
        }

        $array[array_shift($keys)] = $value;

        return $array;
    }

    /**
     * Get an item from an array using "dot" notation.
     *
     * @param  array   $array
     * @param  string  $key
     * @param  mixed   $default
     * @return mixed
     */
    protected function arrayGet($array, $key = null, $default = null)
    {
        if (is_null($key)) {
            return $array;
        }

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

        foreach (explode('.', $key) as $segment) {
            if ( ! is_array($array) || ! array_key_exists($segment, $array)) {
                return $default;
            }
            $array = $array[$segment];
        }

        return $array;
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Routing;

use Symfony\Component\Routing\RouteCollection;

class Router
{
    /**
     * Whether we're in a route section
     *
     * @var bool
     */
    protected $inSection = false;

    /**
     * Whether we're in a route group
     *
     * @var bool
     */
    protected $inGroup = false;

    /**
     * @var RouteCollection
     */
    protected $routes;

    /**
     * @param RouteCollection $routes
     */
    public function __construct(RouteCollection $routes = null)
    {
        $this->routes = $routes ?: new RouteCollection();
    }

    /**
     * Set route collection
     *
     * @param RouteCollection $routes
     * @return $this
     */
    public function setRoutes(RouteCollection $routes)
    {
        $this->routes = $routes;
        return $this;
    }

    /**
     * Get route collection
     *
     * @return RouteCollection
     */
    public function getRoutes()
    {
        return $this->routes;
    }

    /**
     * GET Route
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function get($path, $name, $callback = null, array $schemes = [])
    {
        return $this->createRoute('GET', $path, $name, $callback, $schemes);
    }

    /**
     * POST Route
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function post($path, $name, $callback = null, array $schemes = [])
    {
        return $this->createRoute('POST', $path, $name, $callback, $schemes);
    }

    /**
     * PUT Route
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function put($path, $name, $callback = null, array $schemes = [])
    {
        return $this->createRoute('PUT', $path, $name, $callback, $schemes);
    }

    /**
     * PATCH Route
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function patch($path, $name, $callback = null, array $schemes = [])
    {
        return $this->createRoute('PATCH', $path, $name, $callback, $schemes);
    }

    /**
     * OPTIONS Route
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function options($path, $name, $callback = null, array $schemes = [])
    {
        return $this->createRoute('OPTIONS', $path, $name, $callback, $schemes);
    }

    /**
     * DELETE Route
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function delete($path, $name, $callback = null, array $schemes = [])
    {
        return $this->createRoute('DELETE', $path, $name, $callback, $schemes);
    }

    /**
     * ANY Route
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function any($path, $name, $callback = null, array $schemes = [])
    {
        return $this->createRoute(array(), $path, $name, $callback, $schemes);
    }

    /**
     * Match a given path
     *
     * You would proceed this method call by setting allowed methods
     *
     * @param $path
     * @param $name
     * @param null $callback
     * @param array $schemes
     * @return Route
     */
    public function match($path, $name, $callback = null, array $schemes = [])
    {
        return $this->any($path, $name, $callback, $schemes);
    }

    /**
     * @param $method
     * @param $path
     * @param $name
     * @param $callback
     * @param array $schemes
     * @return Route
     */
    public function createRoute($method, $path, $name, $callback, array $schemes = [])
    {
        $methods = is_array($method) ? $method : explode('|', $method);

        if ('/' !== $path) {
            $path = $this->formatPath($path); //Symfony always stores with a starting slash
        }

        // Create a new Route class
        $route = new Route($path, array('_controller' => $callback));
        $route->setSchemes($schemes);
        $route->setMethods($methods);

        // Add route to collection
        $this->routes->add($name, $route);

        return $route;
    }

    /**
     * Format Request Path
     *
     * @param $path
     * @return string
     */
    public function formatPath($path)
    {
        $path = '/' .trim(trim($path), '/');
        return $path;
    }

    /**
     * Create a route section
     *
     * @param $name
     * @param array $options
     * @param \Closure $callback
     *
     * @deprecated This method is deprecated as of 2.1 and will be removed in 3.0 use Router::group instead
     *
     * @return $this
     */
    public function section($name, $options = [], \Closure $callback)
    {
        $sub_collection = new RouteCollection();

        $sub_router = new self();
        $sub_router->setInSection(true);
        $sub_router->setRoutes($sub_collection);

        $callback($sub_router, $sub_collection);

        $sub_collection->addPrefix($name);
        $sub_collection->addDefaults($options);

        $this->getRoutes()->addCollection($sub_collection);

        return $this;
    }

    /**
     * Create a route group
     *
     * @param string|array $options
     * @param \Closure $callback
     * @return $this
     */
    public function group($options, \Closure $callback)
    {
        $prefix = null;

        if ( ! (is_string($options) || is_array($options))) {
            throw new \RuntimeException('Options must either be a string or array');
        }

        if (is_string($options)) {
            $prefix = $options;
            $options = [];
        }
        else if (is_array($options) && isset($options['prefix'])) {
            $prefix = $options['prefix'];
        }

        $subCollection = new RouteCollection();

        $subRouter = new self();
        $subRouter
            ->setInGroup(true)
            ->setRoutes($subCollection);

        $callback($subRouter, $subCollection);

        if ($prefix) {
            $subCollection->addPrefix($prefix);
        }

        if ($options) {
            if (isset($options['domain'])) {
                $subCollection->setHost($options['domain']);
            }

            if (isset($options['schemes'])) {
                $subCollection->setSchemes($options['schemes']);
            }

            if (isset($options['methods'])) {
                $subCollection->setMethods($options['methods']);
            }

            if (isset($options['defaults'])) {
                $subCollection->addDefaults($options['defaults']);
            }

            if (isset($options['options'])) {
                $subCollection->addOptions($options['options']);
            }

            if (isset($options['requirements'])) {
                $subCollection->addRequirements($options['requirements']);
            }
        }

        $this->getRoutes()->addCollection($subCollection);

        return $this;
    }

    /**
     * Set whether we are in a route section or not
     *
     * @deprecated This method is deprecated as of 2.1 and will be removed in 3.0
     *
     * @param boolean $inSection
     * @return $this
     */
    public function setInSection($inSection)
    {
        $this->inSection = $inSection;
        return $this;
    }

    /**
     * Get whether we are in a route section or not
     *
     * @deprecated This method is deprecated as of 2.1 and will be removed in 3.0
     *
     * @return boolean
     */
    public function getInSection()
    {
        return $this->inSection;
    }

    /**
     * Set whether we are in a route group or not
     *
     * @param boolean $inGroup
     * @return $this
     */
    public function setInGroup($inGroup)
    {
        $this->inGroup = $inGroup;
        return $this;
    }

    /**
     * Get whether we are in a route group or not
     *
     * @return boolean
     */
    public function getInGroup()
    {
        return $this->inGroup;
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Templating\Helper;

use Symfony\Component\Templating\Helper\Helper;

/**
 * BlocksHelper manages template blocks.
 *
 * @author Tom Elis <tellishtc@gmail.com>
 *
 * @api
 */
class BlocksHelper extends Helper
{
    protected $blocks = array();
    protected $openBlocks = array();
    protected $blockDefaults = array();

    /**
     * Starts a new block.
     *
     * This method starts an output buffer that will be
     * closed when the stop() method is called.
     *
     * @param string $name The block name
     *
     * @throws \InvalidArgumentException if a block with the same name is already started
     *
     * @api
     */
    public function start($name)
    {
        if (in_array($name, $this->openBlocks)) {
            throw new \InvalidArgumentException(sprintf('A block named "%s" is already started.', $name));
        }

        $this->openBlocks[] = $name;
        $this->blocks[$name] = '';

        ob_start();
        ob_implicit_flush(0);
    }

    public function startDefault($name)
    {
        if (in_array($name, $this->openBlocks)) {
            throw new \InvalidArgumentException(sprintf('A block named "%s" is already started.', $name));
        }

        $this->openBlocks[] = $name;
        $this->blockDefaults[$name] = '';

        ob_start();
        ob_implicit_flush(0);
    }

    /**
     * Stops a block.
     *
     * @throws \LogicException if no block has been started
     *
     * @api
     */
    public function stop()
    {
        if (!$this->openBlocks) {
            throw new \LogicException('No block started.');
        }

        $name = array_pop($this->openBlocks);

        $this->blocks[$name] = ob_get_clean();
    }

    public function stopDefault()
    {
        if (!$this->openBlocks) {
            throw new \LogicException('No block started.');
        }

        $name = array_pop($this->openBlocks);

        $this->blockDefaults[$name] = ob_get_clean();
    }
    /**
     * Returns true if the block exists.
     *
     * @param string $name The block name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasDefault($name)
    {
        return isset($this->blockDefaults[$name]);
    }

    /**
     * Gets the block value.
     *
     * @param string         $name    The block name
     * @param Boolean|string $default The default block content
     *
     * @return string The block content
     *
     * @api
     */
    public function getDefault($name, $default = false)
    {
        return isset($this->blockDefaults[$name]) ? $this->blockDefaults[$name] : $default;
    }

    /**
     * Sets a block value.
     *
     * @param string $name    The block name
     * @param string $content The block content
     *
     * @api
     */
    public function setDefault($name, $content)
    {
        $this->blockDefaults[$name] = $content;
    }

    /**
     * Returns true if the block exists.
     *
     * @param string $name The block name
     *
     * @return Boolean
     *
     * @api
     */
    public function has($name)
    {
        return isset($this->blocks[$name]);
    }

    /**
     * Gets the block value.
     *
     * @param string         $name    The block name
     * @param Boolean|string $default The default block content
     *
     * @return string The block content
     *
     * @api
     */
    public function get($name, $default = false)
    {
        return isset($this->blocks[$name]) ? $this->blocks[$name] : $default;
    }

    /**
     * Sets a block value.
     *
     * @param string $name    The block name
     * @param string $content The block content
     *
     * @api
     */
    public function set($name, $content)
    {
        $this->blocks[$name] = $content;
    }

    /**
     * Outputs a block.
     *
     * @param string $name The block name
     *
     * @param bool $default
     * @return Boolean true if the block is defined or if a default content has been provided, false otherwise
     *
     * @api
     */
    public function output($name, $default = false)
    {
        if (isset($this->blocks[$name])) {

            echo $this->blocks[$name];

            return true;
        }

        if (isset($this->blockDefaults[$name])) {

            echo $this->blockDefaults[$name];

            return true;
        }

        if (false !== $default) {
            echo $default;

            return true;
        }

        return false;
    }

    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     *
     * @api
     */
    public function getName()
    {
        return 'blocks';
    }
}


<?php

/*
 * This file is part of the Tomahawk package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Bundle\GeneratorBundle\Command;

use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Tomahawk\Bundle\GeneratorBundle\Generator\BundleGenerator;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Generates bundles.
 *
 * @author Tom Ellis
 *
 * Based on the Sensio Labs - SensioGeneratorBundle
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class GenerateBundleCommand extends GenerateCommand
{
    /**
     * @see Command
     */
    protected function configure()
    {
        $this
            ->setName('generate:bundle')
            ->setDescription('Generates a bundle')
            ->setDefinition(array(
                new InputOption('namespace', '', InputOption::VALUE_REQUIRED, 'The namespace of the bundle to create'),
                new InputOption('dir', '', InputOption::VALUE_REQUIRED, 'The directory where to create the bundle'),
                new InputOption('bundle-name', '', InputOption::VALUE_REQUIRED, 'The optional bundle name'),
            ))
            ->setHelp(<<<EOT
The <info>%command.name%</info> command creates a new bundle.

<info>php app/hatchet %command.name% --namespace="MyPackage\\Bundle" --bundle-name="UserBundle" --dir="./src"</info>
EOT
            );
    }

    /**
     * @see Command
     *
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int|null|void When namespace doesn't end with Bundle
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $io = new SymfonyStyle($input, $output);

        foreach (array('namespace', 'dir') as $option) {
            if (null === $input->getOption($option)) {
                throw new \RuntimeException(sprintf('The "%s" option must be provided.', $option));
            }
        }

        $namespace = Validators::validateBundleNamespace($input->getOption('namespace'));

        if (!$bundle = $input->getOption('bundle-name')) {
            $bundle = strtr($namespace, array('\\' => ''));
        }

        $bundle = Validators::validateBundleName($bundle);
        $dir = Validators::validateTargetDir($input->getOption('dir'), $bundle, $namespace);

        $io->writeln('Bundle generation');

        if (!$this->container->get('filesystem')->isAbsolutePath($dir)) {
            $dir = getcwd().'/'.$dir;
        }

        $generator = $this->getGenerator();
        $generator->generate($namespace, $bundle, $dir);

        $io->writeln('Generating the bundle code: <info>OK</info>');

        if ($msg = $this->checkAutoloader($output, $namespace, $bundle, $dir)) {
            $io->writeln($msg);
        }
    }

    /**
     * @param OutputInterface $output
     * @param $namespace
     * @param $bundle
     * @param $dir
     * @return array
     *
     * @codeCoverageIgnore
     */
    protected function checkAutoloader(OutputInterface $output, $namespace, $bundle, $dir)
    {
        $output->write('Checking that the bundle is autoloaded: ');
        if (!class_exists($namespace.'\\'.$bundle)) {
            return array(
                '- Edit the <comment>composer.json</comment> file and register the bundle',
                '  namespace in the "autoload" section:',
                '',
            );
        }

        $output->writeln('<info>OK</info>');
    }

    /**
     * @return BundleGenerator
     */
    public function getGenerator()
    {
        return $this->container->get('bundle_generator');
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * The is based on code originally distributed inside the Symfony framework.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Routing\Controller;

use ReflectionClass;
use Psr\Log\LoggerInterface;
use Tomahawk\DependencyInjection\ContainerAwareInterface;
use Tomahawk\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;

class ControllerResolver extends BaseControllerResolver
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var ControllerNameParser
     */
    protected $parser;

    /**
     * Constructor.
     *
     * @param ContainerInterface $container
     * @param LoggerInterface $logger A LoggerInterface instance
     * @param ControllerNameParser $parser
     */
    public function __construct(ContainerInterface $container, LoggerInterface $logger = null, ControllerNameParser $parser = null)
    {
        $this->container = $container;
        $this->parser = $parser;
        parent::__construct($logger);
    }

    /**
     * Returns a callable for the given controller.
     *
     * @param string $controller A Controller string
     *
     * @return mixed A PHP callable
     *
     * @throws \InvalidArgumentException
     */
    protected function createController($controller)
    {
        if (false === strpos($controller, '::')) {
            $count = substr_count($controller, ':');
            if (2 == $count && $this->parser) {
                // controller in the a:b:c notation then
                $controller = $this->parser->parse($controller);
            }
            else if (1 == $count) {
                // controller in the service:method notation
                list($service, $method) = explode(':', $controller, 2);
                return array($this->container->get($service), $method);
            }
            else if ($this->container->has($controller) && method_exists($service = $this->container->get($controller), '__invoke')) {
                return $service;
            }
            else {
                throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
            }
        }

        list($class, $method) = explode('::', $controller, 2);

        if (!class_exists($class)) {
            throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
        }

        $controller = $this->instantiateController($class);

        return array($controller, $method);
    }

    /**
     * Returns an instantiated controller
     *
     * @param string $class A class name
     *
     * @return object
     */
    protected function instantiateController($class)
    {
        $reflector = new ReflectionClass($class);

        $constructor = $reflector->getConstructor();

        if ($constructor && $constructor->getParameters()) {
            $controller = $this->container->get($class);
        }
        else {
            $controller = new $class();
        }

        if ($controller instanceof ContainerAwareInterface) {
            $controller->setContainer($this->container);
        }

        return $controller;
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Common;

use Patchwork\Utf8;

/**
 * Class Str
 *
 * A simple class for string manipulation
 *
 * @package Tomahawk\Common
 */
class Str
{
    public static $random = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    /**
     * Generic UTF-8 to ASCII transliteration
     *
     * @param  string  $value
     * @return string
     */
    public static function ascii($value)
    {
        return Utf8::toAscii($value);
    }

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

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

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

    /**
     * Convert string to camel case
     *
     * @param $value
     * @return string
     */
    public static function camelCase($value)
    {
        return lcfirst(static::studlyCase($value));
    }

    /**
     * Convert a value to studly case.
     *
     * @param $value
     * @return string
     */
    public static function studlyCase($value)
    {
        $value = ucwords(str_replace(array('-', '_'), ' ', $value));
        return str_replace(' ', '', $value);
    }

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

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

        $pattern = str_replace('\*', '.*', $pattern).'\z';

        return (bool) preg_match('/^'.$pattern.'/', $value);
    }

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

        // Convert all dashes/underscores into separator
        $flip = $separator == '-' ? '_' : '-';

        $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);

        // Remove all characters that are not the separator, letters, numbers, or whitespace.
        $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title));

        // Replace all separator characters and whitespace by a single separator
        $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);

        return trim($title, $separator);
    }

    /**
     * Check if string starts with passed search string(s)
     *
     * @param $string
     * @param $search
     * @return bool
     */
    public static function startsWith($string, $search)
    {
        if (!is_array($search)) {
            $search = array($search);
        }

        foreach ($search as $item) {
            if (0 === strpos($string, $item)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Check if string ends with passed search string(s)
     *
     * @param $string
     * @param $search
     * @return bool
     */
    public static function endsWith($string, $search)
    {
        if (!is_array($search)) {
            $search = array($search);
        }

        foreach ($search as $item) {
            if ((string) $item === substr($string, -strlen($item))) {
                return true;
            }
        }

        return false;
    }

    /**
     * Generate a more truly "random" alpha-numeric string.
     *
     * @param  int $length
     * @return string|boolean
     */
    public static function random($length = 16)
    {
        if (static::supportOpenSSL()) {

            $bytes = static::secureBytes($length);

            if (false !== $bytes) {
                return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
            }
            return false;
        }
        return static::quickRandom($length);
    }

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

    protected static function supportOpenSSL()
    {
        return function_exists('openssl_random_pseudo_bytes');
    }

    protected static function secureBytes($length)
    {
        return openssl_random_pseudo_bytes($length * 2);
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Url;

use Symfony\Component\Routing\Generator\UrlGenerator as SymfonyUrlGenerator;

class UrlGenerator extends SymfonyUrlGenerator implements UrlGeneratorInterface
{
    /**
     * @var bool
     */
    protected $sslOn = true;

    /**
     * @var array
     */
    protected $validUrlStartChars = array(
        '#',
        '//',
        'mailto:',
        'tel:'
    );

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

    /**
     * @return mixed|string
     */
    public function getCurrentUrl()
    {
        return $this->to($this->context->getPathInfo(), array(), 'https' === $this->context->getScheme());
    }

    /**
     * URL to an asset
     *
     * @param $path
     * @param array $extra
     * @param bool $secure
     * @return string
     */
    public function asset($path, array $extra = array(), $secure = false)
    {
        return $this->to($path, $extra, $secure, true);
    }

    /**
     * @param string $path
     * @param array $extra
     * @param bool $secure
     * @param bool $asset
     * @return mixed|string
     */
    public function to($path = '', array $extra = array(), $secure = false, $asset = false)
    {
        // Check if valid URL
        if ($this->validateURL($path)) {
            $extra = implode('/', array_map('rawurlencode', $extra));
            return rtrim($path, '/') . $extra;
        }

        $scheme = $this->context->getScheme();
        $host = $this->context->getHost();
        $base = '';

        if ( ! $asset) {
            $base = $this->context->getBaseUrl();
        }
        $port = '';

        // When in a test environment you might not have SSL enabled, so you can turn this off easily
        if ($secure && $this->sslOn) {
            $scheme = 'https';
        }
        else {
            $scheme = 'http';
        }

        if ('http' === $scheme && 80 != $this->context->getHttpPort()) {
            $port = ':'.$this->context->getHttpPort();
        }
        else if ('https' === $scheme && 443 != $this->context->getHttpsPort()) {
            $port = ':'.$this->context->getHttpsPort();
        }

        $extra = implode('/', array_map('rawurlencode', $extra));

        $path = trim($path . '/' . $extra, '/');

        $url = rtrim(sprintf('%s://%s%s%s/%s', $scheme, $host, $port, $base, $path), '/');

        return $url;
    }

    /**
     * @param string $url
     * @param array $extra
     * @param bool $secure
     * @param bool $asset
     * @return string
     */
    public function secureTo($url = '', array $extra = array(), $secure = true, $asset = false)
    {
        return $this->to($url, $extra, $secure, $asset);
    }

    /**
     * Determine if the given path is a valid URL.
     *
     * @param $url
     * @return bool
     */
    public function validateUrl($url)
    {
        foreach ($this->validUrlStartChars as $char) {
            if (0 === strpos($url, $char)) {
                return true;
            }
        }

        return false !== filter_var($url, FILTER_VALIDATE_URL);
    }

    /**
     * @param $name
     * @param array $data
     * @return mixed|string
     */
    public function route($name, $data = array())
    {
        return $this->generate($name, $data, self::ABSOLUTE_URL);
    }

    /**
     * @param boolean $sslOn
     */
    public function setSslOn($sslOn)
    {
        $this->sslOn = $sslOn;
    }

    /**
     * @return boolean
     */
    public function getSslOn()
    {
        return $this->sslOn;
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * The code is based off the Twig Bundle by the Symfony2 Project
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Templating\Twig\Loader;

use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;
use Twig_Error_Loader;

/**
 * FilesystemLoader extends the default Twig filesystem loader
 * to work with the Symfony paths and template references.
 *
 * @author Tom Ellis
 *
 * Heavily based on the original by:
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FilesystemLoader extends \Twig_Loader_Filesystem
{
    /**
     * @var FileLocatorInterface
     */
    protected $locator;

    /**
     * @var TemplateNameParserInterface
     */
    protected $parser;

    /**
     * Constructor.
     *
     * @param FileLocatorInterface        $locator  A FileLocatorInterface instance
     * @param TemplateNameParserInterface $parser   A TemplateNameParserInterface instance
     * @param string|null                 $rootPath The root path common to all relative paths (null for getcwd())
     */
    public function __construct(FileLocatorInterface $locator, TemplateNameParserInterface $parser, $rootPath = null)
    {
        parent::__construct(array(), $rootPath);

        $this->locator = $locator;
        $this->parser = $parser;
    }

    /**
     * {@inheritdoc}
     *
     * The name parameter might also be a TemplateReferenceInterface.
     */
    public function exists($name)
    {
        return parent::exists((string) $name);
    }

    /**
     * Returns the path to the template file.
     *
     * The file locator is used to locate the template when the naming convention
     * is the symfony one (i.e. the name can be parsed).
     * Otherwise the template is located using the locator from the twig library.
     *
     * @param string|TemplateReferenceInterface $template The template
     * @param bool                              $throw    When true, a \Twig_Error_Loader exception will be thrown if a template could not be found
     *
     * @return string The path to the template file
     *
     * @throws \Twig_Error_Loader if the template could not be found
     */
    protected function findTemplate($template, $throw = true)
    {
        $logicalName = (string) $template;

        if (isset($this->cache[$logicalName])) {
            return $this->cache[$logicalName];
        }

        $file = null;
        try {
            $file = parent::findTemplate($logicalName);
        } catch (\Twig_Error_Loader $e) {
            $twigLoaderException = $e;

            // for BC
            try {
                $template = $this->parser->parse($template);
                $file = $this->locator->locate($template);
            } catch (\Exception $e) {
            }
        }

        if (false === $file || null === $file) {
            if ($throw) {
                throw $twigLoaderException;
            }

            return false;
        }

        return $this->cache[$logicalName] = $file;
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * The is based on code originally distributed inside the Symfony/Doctrine framework.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 * (c) Doctrine Project, Benjamin Eberlei <kontakt@beberlei.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Bundle\DoctrineBundle\Command\Proxy;

use Tomahawk\Console\Application;
use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;

/**
 * Provides some helper and convenience methods to configure doctrine commands in the context of bundles
 * and multiple connections/entity managers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class CommandHelper
{
    /**
     * Convenience method to push the helper sets of a given entity manager into the application.
     *
     * @param Application $application
     * @param string      $emName
     */
    static public function setApplicationEntityManager(Application $application, $emName)
    {
        /** @var $em \Doctrine\ORM\EntityManager */
        $em = $application->getKernel()->getContainer()->get('doctrine')->getManager($emName);

        $helperSet = $application->getHelperSet();
        $helperSet->set(new ConnectionHelper($em->getConnection()), 'db');
        $helperSet->set(new EntityManagerHelper($em), 'em');
    }

    /**
     * Convenience method to push the helper sets of a given connection into the application.
     *
     * @param Application $application
     * @param string      $connName
     */
    static public function setApplicationConnection(Application $application, $connName)
    {
        $connection = $application->getKernel()->getContainer()->get('doctrine')->getConnection($connName);
        $helperSet = $application->getHelperSet();
        $helperSet->set(new ConnectionHelper($connection), 'db');
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Templating;

use Symfony\Component\Templating\TemplateNameParser as BaseTemplateNameParser;
use Symfony\Component\Templating\TemplateReferenceInterface;
use Tomahawk\HttpKernel\KernelInterface;

/**
 * Class TemplateNameParser
 * @package Tomahawk\Templating
 *
 * @author Tom Ellis
 *
 * Based on the original by:
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TemplateNameParser extends BaseTemplateNameParser
{
    /**
     * @var KernelInterface
     */
    protected $kernel;

    /**
     * @var array
     */
    protected $cache = array();

    /**
     * Constructor.
     *
     * @param KernelInterface $kernel A KernelInterface instance
     */
    public function __construct(KernelInterface $kernel)
    {
        $this->kernel = $kernel;
    }

    /**
     * {@inheritdoc}
     */
    public function parse($name)
    {
        if ($name instanceof TemplateReferenceInterface) {
            return $name;
        }

        // No extension? Default to php
        $ext = pathinfo($name, PATHINFO_EXTENSION);

        // This is horrible and I don't know why I did it
        // Will deprecate in a future version
        if ( ! $ext) {
            $name .= '.php';
        }

        if (isset($this->cache[$name])) {
            return $this->cache[$name];
        }

        // normalize name
        $name = str_replace(':/', ':', preg_replace('#/{2,}#', '/', strtr($name, '\\', '/')));

        if (false !== strpos($name, '..')) {
            throw new \RuntimeException(sprintf('Template name "%s" contains invalid characters.', $name));
        }

        if ($this->isAbsolutePath($name) || !preg_match('/^([^:]*):([^:]*):(.+)\.([^\.]+)$/', $name, $matches) || 0 === strpos($name, '@')) {
            return parent::parse($name);
        }

        $template = new TemplateReference($matches[1], $matches[2], $matches[3], $matches[4]);

        if ($template->get('bundle')) {
            try {
                $this->kernel->getBundle($template->get('bundle'));
            }
            catch (\Exception $e) {
                throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name), 0, $e);
            }
        }

        return $this->cache[$name] = $template;
    }

    /**
     * @param $file
     * @return bool
     */
    private function isAbsolutePath($file)
    {
        $isAbsolute = (bool) preg_match('#^(?:/|[a-zA-Z]:)#', $file);
        if ($isAbsolute) {
            @trigger_error('Absolute template path support is deprecated since Symfony 3.1 and will be removed in 4.0.', E_USER_DEPRECATED);
        }
        return $isAbsolute;
    }
}


<?php

namespace Understory;

use Doctrine\Common\Inflector\Inflector;
use Understory\Config;
use \Timber\Timber;
use Understory\Helpers\Svg;

class Site extends \Timber\Site
{
    protected static $themeSupport = [];
    protected $optionsPages = [];
    protected $editor;

    protected $views = array();

    protected $pageTitle;

    public function __construct()
    {
        Timber::$dirname = 'app/templates';

        self::addThemeSupport();

        static::registerComponents();
        static::addEditorConfig();

        \add_filter('timber_context', array( $this, 'initializeContext' ));
        \add_filter('get_twig', array( $this, 'addToTwig' ));

        \add_action('init', array( $this, 'registerViews' ), 11);
        \add_action('init', array( $this, 'registerTaxonomies' ), 12);
        \add_action('init', array( $this, 'registerPostTypes' ), 13);
        \add_action('init', array( $this, 'registerOptionsPages' ), 14);
        \add_action('init', array( $this, 'registerNavigations' ), 15);

        \add_action('admin_menu', array( $this, 'customizeAdminMenu' ), 10);

        \add_action('wp_enqueue_scripts', array( $this, 'enqueueScripts'), 100);
        \add_action('wp_enqueue_scripts', array( $this, 'enqueueStylesheets'), 102);
        \add_action('admin_enqueue_scripts', array( $this, 'enqueueAdminStylesheets'), 100);

        \add_filter('wp_title', array( $this, 'wpTitle' ));

        \add_filter('template_include', array( $this, 'renderView' ), 1000000);

        // Warm custom template cache
        \add_action('init', array( $this, 'loadPageTemplates' ), 1);

        parent::__construct();
    }

    public function loadPageTemplates()
    {
        \wp_get_theme()->get_page_templates(null);
    }

    protected function registerComponents()
    {
    }

    protected function addEditorConfig()
    {
        $this->editor = new Config\Editor();
    }

    protected function addThemeSupport()
    {
        foreach (static::$themeSupport as $themeSupport) {
            \add_theme_support($themeSupport);
        }
    }

    public function enqueueStylesheets()
    {
    }

    public function enqueueAdminStylesheets()
    {
    }

    public function enqueueScripts()
    {
    }

    public function registerNavigations()
    {
    }

    private function getFiles($dir)
    {
        $files = [];
        $themeDir = \get_stylesheet_directory();
        $parentDir = \get_template_directory();

        if (file_exists($themeDir . '/' . $dir)) {
            $files = scandir($themeDir . '/' . $dir);
        }

        if ($themeDir !== $parentDir && file_exists($parentDir . '/' . $dir)) {
            $parentFiles = scandir($parentDir . '/' . $dir);
            $files = array_merge($parentFiles, $files);
        }

        $files = array_map(function ($file) {
            return basename($file, '.php');
        }, array_filter($files, function ($file) {
            $fileInfo = pathinfo($file);
            return array_key_exists('extension', $fileInfo) && $fileInfo['extension'] === 'php';
        }));

        return $files;
    }

    private function fileToClass($file)
    {
        $file = ucwords($file, '-');
        $file = str_replace('-', '', $file);
        return $file;
    }

    /**
     * Register the post types in app/models automatically
     */
    public function registerPostTypes()
    {
        $modelFiles = $this->getFiles('app/Models');

        foreach ($modelFiles as $modelFile) {
            $modelClass = static::getSiteNamespace().'\\Models\\'.$this->fileToClass($modelFile);
            if (!class_exists($modelClass)) {
                $modelClass = static::getParentNamespace().'\\Models\\'.$this->fileToClass($modelFile);
            }

            if (new $modelClass instanceof CustomPostType) {
                $this->registerPostType($modelClass);
            }
        }
    }

    public function isUnderStoryView($viewFile)
    {
        $filePath = \get_stylesheet_directory().'/app/Views/'.$viewFile.'.php';
        $parentPath = \get_template_directory().'/app/Views/'.$viewFile.'.php';
        if (!file_exists($filePath)) {
            if (!file_exists($parentPath)) {
                return false;
            }
            $filePath = $parentPath;
        }

        $file_contents = file_get_contents($filePath);
        return strpos($file_contents, 'Understory\View') !== false;
    }

    /**
     * Register the views in app/models automatically
     */
    public function registerViews()
    {
        $viewFiles = $this->getFiles('app/Views');

        foreach ($viewFiles as $viewFile) {
            // Make sure the viewFile is a class

            if ($this->isUnderStoryView($viewFile)) {
                $viewClass = static::getSiteNamespace().'\\Views\\'.$this->fileToClass($viewFile);
                if (!class_exists($viewClass)) {
                    $viewClass = static::getParentNamespace().'\\Views\\'.$this->fileToClass($viewFile);
                }
                $this->registerView($viewClass);
            }
        }
    }

    public function registerTaxonomies()
    {
        $taxonomyFiles = $this->getFiles('app/Taxonomies');

        foreach ($taxonomyFiles as $taxonomyFile) {
            $taxonomyClass = static::getSiteNamespace().'\\Taxonomies\\'.$this->fileToClass($taxonomyFile);
            if (!class_exists($taxonomyClass)) {
                $taxonomyClass = static::getParentNamespace().'\\Taxonomies\\'.$this->fileToClass($taxonomyFile);
            }

            if (new $taxonomyClass instanceof CustomTaxonomy) {
                $this->registerTaxonomy($taxonomyClass);
            }
        }
    }

    public function registerOptionPages()
    {
    }

    public function customizeAdminMenu()
    {
    }

    public function registerPostType($postTypeClass)
    {
        $postType = new $postTypeClass();
        $postType->register();
    }

    public function registerTaxonomy($taxonomyClass)
    {
        $taxonomy = new $taxonomyClass();
        $taxonomy->register();
    }

    public function registerView($viewClass)
    {
        // Append the full namespace to the classname if it doesn't exist
        if (strpos($viewClass, static::getSiteNameSpace()) === false && strpos($viewClass, static::getParentNamespace()) === false) {
            $viewClass = static::getSiteNamespace().$viewClass;
        }

        $view = new $viewClass();
        $view->setSite($this);

        // Index the viewClass by its file name, so we can render it
        // when WordPress tries to include that file
        $viewPath = \get_stylesheet_directory().'/app/Views'.$view->getFileName().'.php';
        $parentViewPath = \get_template_directory().'/app/Views'.$view->getFileName().'.php';
        if (file_exists($viewPath)) {
            $this->views[$viewPath] = $view;
        } else if (file_exists($parentViewPath)) {
            $this->views[$parentViewPath] = $view;
        }

        // View may have a WordPress style filename, like home.php or single-post.php
        // Also on case insensative file systems, we need to make sure both Page.php and page.php load
        // the Page class
        $viewPath = \get_stylesheet_directory().'/app/Views'.$view->getFileNameDashedCase().'.php';
        $parentViewPath = \get_template_directory().'/app/Views'.$view->getFileNameDashedCase().'.php';
        if (file_exists($viewPath)) {
            $this->views[$viewPath] = $view;
        } else if (file_exists($parentViewPath)) {
            $this->views[$parentViewPath] = $view;
        }

        $view->register();
    }

    /**
     * Called by the WordPress include_template filter, so we can
     * intercept it and render our registered View object instead.
     *
     * This is not a great solution because WordPress filters should not
     * cause side effects, but in this case, on render is the only time
     * this filter should be called. Still, we will acknowledge that
     * it is a hack
     *
     * @param  string $template template file
     * @return string           template file, return false if rendering
     */
    public function renderView($template)
    {
        if (array_key_exists($template, $this->views)) {
            echo $this->views[$template]->render();
            return false;
        }

        return $template;
    }

    public function initializeContext($context)
    {
        $context['body_class'] = "site ".$context['body_class'];

        $context['site'] = $this;
        return $context;
    }

    public function setPageTitle($title)
    {
        $this->pageTitle = $title;
    }

    public function getPageTitle()
    {
        return $this->pageTitle;
    }

    public function wpTitle($title)
    {
        global $wp_query;
        if (empty($title)) {
            if ((is_home() || is_front_page())) {
                return $this->name;
            } else {
                $title = $this->getPageTitle();
            }
        }

        return $title . ' | ' . $this->name;
    }

    public function addToTwig(\Twig_Environment $twig)
    {
        /* this is where you can add your own functions to twig */
        $twig->addExtension(new \Twig_Extension_StringLoader());
        $twig->addFilter(new \Twig_SimpleFilter('svg', function($path) { Svg::embed($path); }));
        return $twig;
    }

    public static function getSiteNamespace()
    {
        $reflection = new \ReflectionClass(get_called_class());
        return $reflection->getNamespaceName();
    }
    public static function getParentNamespace()
    {
        $reflection = new \ReflectionClass(get_parent_class(static::class));

        return $reflection->getNamespaceName();
    }

    public static function getPost($post = null)
    {
        if (!$post) {
            $post = new Post();
            $post->load();
        }

        if (!$post->ID) {
            return null;
        }

        $namespace = static::getSiteNamespace().'\\Models\\';
        $className = $namespace.Inflector::classify($post->post_type);

        if (class_exists($className, false)) {
            return new $className($post);
        }

        return $post;
    }

    /**
     * Wraps Timber::get_posts($query) and intitialzes the each post as the correct
     * CustomPostType class.
     * @param mixed $query
     * @return array
     */
    public static function getPosts($query = false)
    {
        $namespace = $namespace = static::getSiteNamespace().'\\Models\\';

        return array_map(function ($post) use ($namespace) {
            $className = $namespace.$post->post_type;

            if (class_exists($className)) {
                return new $className($post);
            }

            return $post;
        }, Timber::get_posts($query));
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Forms;

use Tomahawk\Forms\Element\Element;
use Tomahawk\Forms\Exception\InvalidDataTransformerException;
use Tomahawk\Validation\ValidatorInterface;
use Tomahawk\Forms\Element\CheckableInterface;

class Form extends AttributeBuilder implements FormInterface
{
    /**
     * @var Element[]
     */
    protected $elements;

    /**
     * @var
     */
    protected $model;

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

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

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

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

    /**
     * @var ValidatorInterface
     */
    protected $validator;

    /**
     * @var DataTransformerInterface[]
     */
    protected $transformers = [];

    public function __construct($url, $method = 'POST', array $attributes = [])
    {
        $this->url = $url;
        $this->method = $method;
        $this->attributes = $attributes;
    }

    /**
     * @param ValidatorInterface $validator
     */
    public function setValidator(ValidatorInterface $validator)
    {
        $this->validator = $validator;
    }

    /**
     * @return ValidatorInterface
     */
    public function getValidator()
    {
        return $this->validator;
    }

    /**
     * @param mixed $model
     * @return $this
     */
    public function setModel($model)
    {
        $this->model = $model;
        return $this;
    }

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

    /**
     * @param Element $element
     * @return $this
     */
    public function add(Element $element)
    {
        $this->elements[$element->getName()] = $element;
        return $this;
    }

    /**
     * Open the form
     *
     * @return string
     */
    public function open()
    {
        $attributes = [
            'method' => $this->method,
            'action' => $this->url
        ];

        $attributes = array_merge($attributes, $this->attributes);

        return sprintf('<form%s>', $this->attributes($attributes));
    }

    /**
     * Close the form
     *
     * @return string
     */
    public function close()
    {
        return '</form>';
    }

    /**
     * @param $name
     * @param array $attributes
     * @return mixed
     */
    public function render($name, array $attributes = [])
    {
        $element = $this->elements[$name];

        $value = $this->getValue($name);

        $value = $this->applyTransform($name, $value);

        // Only set the value of an Element that isn't checkable
        if (($element instanceof CheckableInterface) && $value) {
            $element->setChecked($element->getValue() == $this->getValue($name));
        }
        else if ($value) {
            $element->setValue($value);
        }

        return $element->render($attributes);
    }

    /**
     * @param $input
     * @return $this
     */
    public function handleInput($input)
    {
        $this->setInput($input);

        if ($this->model) {

            foreach ($this->input as $name => $value) {

                $value = $this->applyReverseTransform($name, $value);

                $this->setValue($name, $value);
            }
        }

        return $this;
    }

    /**
     * @return bool
     */
    public function isValid()
    {
        if ( ! $this->getValidator()) {
            return true;
        }

        return $this->getValidator()->validate($this->input);
    }

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

    /**
     * @param string $url
     * @return $this
     */
    public function setUrl($url)
    {
        $this->url = $url;
        return $this;
    }

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

    /**
     * @param string $method
     * @return $this
     */
    public function setMethod($method)
    {
        $this->method = $method;
        return $this;
    }

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

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

        return $this;
    }

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

    /**
     * @param array $attributes
     * @return $this
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
        return $this;
    }

    /**
     * @return Element[]
     */
    public function getElements()
    {
        return $this->elements;
    }

    /**
     * Add a group of data transformers
     *
     * array (
     *  'date' => DataTransformerInterface
     * )
     *
     * @param array $dataTransformers
     * @return $this
     */
    public function addTransformers(array $dataTransformers)
    {
        foreach ($dataTransformers as $type => $dataTransformer) {

            if ( ! $dataTransformer instanceof DataTransformerInterface) {
                throw new InvalidDataTransformerException();
            }

            $this->addTransformer($type, $dataTransformer);
        }

        return $this;
    }

    /**
     * Add a data transformer
     *
     * @param $type
     * @param DataTransformerInterface $dataTransformer
     * @return $this
     */
    public function addTransformer($type, DataTransformerInterface $dataTransformer)
    {
        $this->transformers[$type] = $dataTransformer;

        return $this;
    }

    /**
     * Get all data tranformers
     *
     * @return DataTransformerInterface[]
     */
    public function getTransformers()
    {
        return $this->transformers;
    }

    protected function getValue($name)
    {
        if (isset($this->input[$name])) {
            return $this->input[$name];
        }
        else if ($this->model && method_exists($this->model, $method = $this->getElementGetMethod($name))) {
            return $this->model->$method();
        }
        else if ($this->model && property_exists($this->model, $name)) {
            return $this->model->$name;
        }

        return null;
    }

    protected function setValue($name, $value)
    {
        if ($this->model && method_exists($this->model, $method = $this->getElementSetMethod($name))) {
            $this->model->$method($value);
        }
        else if ($this->model && property_exists($this->model, $name)) {
            $this->model->$name = $value;
        }

        return $this;
    }

    protected function getElementGetMethod($element)
    {
        $method = ucwords(str_replace(['_', '-'], ' ', $element));

        return 'get' .str_replace(' ', '', $method);
    }

    protected function getElementSetMethod($element)
    {
        $method = ucwords(str_replace(['_', '-'], ' ', $element));

        return 'set' .str_replace(' ', '', $method);
    }

    protected function applyTransform($name, $value)
    {
        if ( ! isset($this->transformers[$name])) {
            return $value;
        }

        return $this->transformers[$name]->transform($value);
    }

    protected function applyReverseTransform($name, $value)
    {
        if ( ! isset($this->transformers[$name])) {
            return $value;
        }

        return $this->transformers[$name]->reverseTransform($value);
    }
}


<?php

/*
 * This file is part of the TomahawkPHP package.
 *
 * (c) Tom Ellis
 *
 * The is based on code originally distributed inside the Symfony framework.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tomahawk\Routing\Controller;

use Tomahawk\HttpKernel\KernelInterface;

/**
 * Class ExceptionListener
 *
 * Based on the Symfony2 FrameworkBundle ControllerNameParser
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @package Tomahawk\HttpKernel\Event
 */
class ControllerNameParser
{
    /**
     * @var KernelInterface
     */
    protected $kernel;

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

    /**
     * Converts a short notation a:b:c to a class::method.
     *
     * @param string $controller A short notation controller (a:b:c)
     *
     * @return string A string in the class::method notation
     *
     * @throws \InvalidArgumentException when the specified bundle is not enabled
     */
    public function parse($controller)
    {
        $originalController = $controller;

        if (3 !== count($parts = explode(':', $controller))) {
            throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "a:b:c" controller string.', $controller));
        }

        list($bundle, $controller, $action) = $parts;

        $controller = str_replace('/', '\\', $controller);

        $bundles = array();

        try {
            // this throws an exception if there is no such bundle
            $allBundles = $this->kernel->getBundle($bundle, false);
        }
        catch (\InvalidArgumentException $e) {
            $message = sprintf(
                'The "%s" (from the _controller value "%s") does not exist or is not enabled in your kernel!',
                $bundle,
                $originalController
            );

            throw new \InvalidArgumentException($message, 0, $e);
        }

        foreach ($allBundles as $b) {
            $try = $b->getNamespace().'\\Controller\\'.$controller.'Controller';

            if (class_exists($try)) {
                return $try.'::'.$action.'Action';
            }

            $bundles[] = $b->getName();
            $msg = sprintf('The _controller value "%s:%s:%s" maps to a "%s" class, but this class was not found. Create this class or check the spelling of the class and its namespace.', $bundle, $controller, $action, $try);
        }

        if (count($bundles) > 1) {
            $msg = sprintf('Unable to find controller "%s:%s" in bundles %s.', $bundle, $controller, implode(', ', $bundles));
        }

        throw new \InvalidArgumentException($msg);

    }

    /**
     * Converts a class::method notation to a short one (a:b:c).
     *
     * @param string $controller A string in the class::method notation
     *
     * @return string A short notation controller (a:b:c)
     *
     * @throws \InvalidArgumentException when the controller is not valid or cannot be found in any bundle
     */
    public function build($controller)
    {
        if (0 === preg_match('#^(.*?\\\\Controller\\\\(.+))Controller::(.+)Action#', $controller, $match)) {
            throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "class::method" string.', $controller));
        }

        $className = $match[1];

        $controllerName = $match[2];

        $actionName = $match[3];

        foreach ($this->kernel->getBundles() as $name => $bundle) {

            if (0 !== strpos($className, $bundle->getNamespace())) {
                continue;
            }

            return sprintf('%s:%s:%s', $name, $controllerName, $actionName);
        }

        throw new \InvalidArgumentException(sprintf('Unable to find a bundle that defines controller "%s".', $controller));
    }
}


<?php

namespace amnah\yii2\behaviors;

use yii\behaviors\TimestampBehavior;
use yii\base\Event;
use yii\db\ActiveRecord;

/**
 * SoftDelete
 * Usage:
 *
 * ~~~
 * public function behaviors() {
 *     return [
 *         'softDelete' => ['class' => 'amnah\yii2\behaviors\SoftDelete',
 *             'attribute' => 'delete_time',
 *             'timestamp' => time(),
 *             'safeMode' => true,
 *         ],
 *     ];
 * }
 * ~~~
 * @author amnah <amnah.dev@gmail.com>
 */
class SoftDelete extends TimestampBehavior {

    /**
     * @var string SoftDelete attribute
     */
    public $attribute = "delete_time";

    /**
     * @var bool If true, this behavior will process '$model->delete()' as a soft-delete. Thus, the
     *           only way to truly delete a record is to call '$model->forceDelete()'
     */
    public $safeMode = true;

    /**
     * @inheritdoc
     */
    public function events() {
        return [ActiveRecord::EVENT_BEFORE_DELETE => 'doDeleteTimestamp'];
    }

    /**
     * Set the attribute with the current timestamp to mark as deleted
     *
     * @param Event $event
     */
    public function doDeleteTimestamp($event) {

        // do nothing if safeMode is disabled. this will result in a normal deletion
        if (!$this->safeMode) {
            return;
        }

        // remove and mark as invalid to prevent real deletion
        $this->remove();
        $event->isValid = false;
    }

    /**
     * Remove (aka soft-delete) record
     */
    public function remove() {

        // evaluate timestamp and set attribute
        $timestamp = $this->getValue(null);
        $attribute = $this->attribute;
        $this->owner->$attribute = $timestamp;

        // save record
        $this->owner->save(false, [$attribute]);
    }

    /**
     * Restore soft-deleted record
     */
    public function restore() {

        // mark attribute as null
        $attribute = $this->attribute;
        $this->owner->$attribute = null;

        // save record
        $this->owner->save(false, [$attribute]);
    }

    /**
     * Delete record from database regardless of the $safeMode attribute
     */
    public function forceDelete() {

        // store model so that we can detach the behavior and delete as normal
        $model = $this->owner;
        $this->detach();
        $model->delete();
    }
}


<?php
namespace Pepijnolivier\Bittrex;

class Client implements ClientContract
{
    /**
     * @var string
     */
    public $marketUrl;

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

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

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

    /**
     * @var string
     */
    private $key;

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

    /**
     * Client constructor.
     *
     * @param array $auth
     * @param array $urls
     */
    public function __construct(array $auth, array $urls) {
        $this->marketUrl  = array_get($urls, 'market');
        $this->publicUrl  = array_get($urls, 'public');
        $this->publicUrlV2  = array_get($urls, 'publicv2');
        $this->accountUrl = array_get($urls, 'account');

        $this->key    = array_get($auth, 'key');
        $this->secret = array_get($auth, 'secret');
    }

    /**
     * Used to get the open and available trading markets at Bittrex along with other meta data.
     *
     * @return array
     */
    public function getMarkets() {
        return $this->public('getmarkets');
    }

    /**
     * Used to get all supported currencies at Bittrex along with other meta data.
     *
     * @return array
     */
    public function getCurrencies() {
        return $this->public('getcurrencies');
    }

    /**
     * Used to get the current tick values for a market.
     *
     * @param string $market a string literal for the market (ex: BTC-LTC)
     * @return array
     */
    public function getTicker($market) {
        return $this->public('getticker', [
            'market' => $market
        ]);
    }

    /**
     * Used to get the last 24 hour summary of all active exchanges
     *
     * @return array
     */
    public function getMarketSummaries() {
        return $this->public('getmarketsummaries');
    }

    /**
     * https://bittrex.com/api/v2.0/pub/Markets/GetMarketSummaries
     *
     * @return array
     */
    public function getMarketSummariesV2() {
        return $this->public('Markets/GetMarketSummaries', [
            // no extra data
        ], 'v2.0');
    }

    /**
     * Used to get the last 24 hour summary of all active exchanges
     *
     * @param string $market a string literal for the market (ex: BTC-LTC)
     * @return array
     */
    public function getMarketSummary($market) {
        return $this->public('getmarketsummary', [
            'market' => $market,
        ]);
    }

    /**
     * Used to get retrieve the orderbook for a given market
     *
     * @param string $market a string literal for the market (ex: BTC-LTC)
     * @param string $type buy, sell or both to identify the type of orderbook to return
     * @param int $depth defaults to 20 - how deep of an order book to retrieve. Max is 50
     * @return array
     */
    public function getOrderBook($market, $type, $depth=20) {
        return $this->public('getorderbook', [
            'market' => $market,
            'type' => $type,
            'depth' => $depth,
        ]);
    }

    /**
     * Used to retrieve the latest trades that have occured for a specific market.
     *
     * @param string $market a string literal for the market (ex: BTC-LTC)
     * @return array
     */
    public function getMarketHistory($market) {
        return $this->public('getmarkethistory', [
            'market' => $market,
        ]);
    }

    public function getValidChartDataTickIntervals() {
        $validTickIntervals = [
            '60' => 'oneMin',
            '300' => 'fiveMin',
            // fifteenMin
            '1800' => 'thirtyMin',
            '3600' => 'hour',
            '86400' => 'day',
            // threeDays
            // week
            // month
        ];

        return $validTickIntervals;
    }

    /**
     * This is an undocumented public API, that will return the chart data.
     * Valid tick intervals are: ['oneMin','fiveMin','thirtyMin','hour','day']
     *
     * @param string $market a string literal for the market (ex: BTC-LTC)
     * @param string $tickInterval
     * @return mixed
     */
    public function getChartData($marketName, $tickInterval='hour') {
        $timestamp = strtotime('now');
        return $this->public('market/GetTicks', [
            'marketName' => $marketName,
            'tickInterval' => $tickInterval,
            '_' => $timestamp,
        ], 'v2.0');
    }

    /**
     * Used to place a buy order in a specific market. Use buylimit to place limit orders.
     * Make sure you have the proper permissions set on your API keys for this call to work
     *
     * @param string $market a string literal for the market (ex: BTC-LTC)
     * @param string|float $quantity the amount to purchase
     * @param string|float rate the rate at which to place the order.
     *
     * @return array Returns you the order uuid
     */
    public function buyLimit($market, $quantity, $rate) {
        return $this->market('buylimit', [
            'market' => $market,
            'quantity' => $quantity,
            'rate' => $rate,
        ]);
    }

    /**
     * Used to place an sell order in a specific market. Use selllimit to place limit orders.
     * Make sure you have the proper permissions set on your API keys for this call to work
     *
     * @param string $market a string literal for the market (ex: BTC-LTC)
     * @param string|float $quantity the amount to sell
     * @param string|float rate the rate at which to place the order.
     *
     * @return array Returns you the order uuid
     *
     */
    public function sellLimit($market, $quantity, $rate) {
        return $this->market('selllimit', [
            'market' => $market,
            'quantity' => $quantity,
            'rate' => $rate,
        ]);
    }

    /**
     * Used to cancel a buy or sell order.
     *
     * @param string $uuid uuid of buy or sell order
     * @return array
     */
    public function cancelOrder($uuid) {
        return $this->market('cancel', [
            'uuid' => $uuid,
        ]);
    }

    /**
     * Get all orders that you currently have opened. A specific market can be requested
     *
     * @param string|null $market a string literal for the market (ie. BTC-LTC)
     * @return array
     */
    public function getOpenOrders($market=null) {
        return $this->market('getopenorders', [
            'market' => $market,
        ]);
    }

    /**
     * Used to retrieve all balances from your account
     *
     * @return array
     */
    public function getBalances() {
        return $this->account('getbalances');
    }

    /**
     * Used to retrieve the balance from your account for a specific currency.
     *
     * @param string $currency a string literal for the currency (ex: LTC)
     * @return array
     */
    public function getBalance($currency) {
        return $this->account('getbalance', [
            'currency' => $currency,
        ]);
    }

    /**
     * Used to retrieve or generate an address for a specific currency.
     * If one does not exist, the call will fail and return ADDRESS_GENERATING until one is available.
     *
     * @param string $currency a string literal for the currency (ex: LTC)
     * @return array
     */
    public function getDepositAddress($currency) {
        return $this->account('getdepositaddress', [
            'currency' => $currency,
        ]);
    }

    /**
     * Used to withdraw funds from your account.
     * note: please account for txfee.
     *
     * @param string $currency a string literal for the currency (ex: LTC)
     * @param string|float $quantity the quantity of coins to withdraw
     * @param string $address the address where to send the funds.
     * @param string $paymentId used for CryptoNotes/BitShareX/Nxt optional field (memo/paymentid)
     * @return array Returns you the withdrawal uuid
     */
    public function withdraw($currency, $quantity, $address, $paymentId=null) {
        return $this->account('withdraw', [
            'currency' => $currency,
            'quantity' => $quantity,
            'address' => $address,
            'paymentid' => $paymentId,
        ]);
    }

    /**
     * Used to retrieve a single order by uuid.
     *
     * @param string $uuid the uuid of the buy or sell order
     * @return array
     */
    public function getOrder($uuid) {
        return $this->account('getorder', [
            'uuid' => $uuid,
        ]);
    }

    /**
     * Used to retrieve your order history.
     *
     * @param string|null $market
     * @return array
     */
    public function getOrderHistory($market=null) {
        return $this->account('getorderhistory', [
            'market' => $market,
        ]);
    }

    /**
     * Used to retrieve your withdrawal history.
     *
     * @param string| null $currency a string literal for the currecy (ie. BTC). If omitted, will return for all currencies
     * @return array
     */
    public function getWithdrawalHistory($currency=null) {
        return $this->account('getwithdrawalhistory', [
            'currency' => $currency,
        ]);
    }

    /**
     * Used to retrieve your deposit history.
     *
     * @param string| null $currency a string literal for the currecy (ie. BTC). If omitted, will return for all currencies
     * @return array
     */
    public function getDepositHistory($currency=null) {
        return $this->account('getdeposithistory', [
            'currency' => $currency,
        ]);
    }

    /**
     * Execute a public API request
     *
     * @param $segment
     * @param array $parameters
     * @return array
     */
    function public ($segment, array $parameters=[], $version='v1.1') {
        $options = [
            'http' => [
                'method'  => 'GET',
                'timeout' => 10,
            ],
        ];

        $publicUrl = $this->getPublicUrl($version);
        $url = $publicUrl . $segment . '?' . http_build_query(array_filter($parameters));
        $feed = file_get_contents($url, false, stream_context_create($options));
        return json_decode($feed, true);
    }

    /**
     * Execute a market API request
     *
     * @param $segment
     * @param array $parameters
     * @return array
     */
    public function market($segment, array $parameters=[]) {
        $baseUrl = $this->marketUrl;
        return $this->nonPublicRequest($baseUrl, $segment, $parameters);
    }

    /**
     * Execute an account API request
     *
     * @param $segment
     * @param array $parameters
     * @return array
     */
    public function account($segment, array $parameters=[]) {
        $baseUrl = $this->accountUrl;
        return $this->nonPublicRequest($baseUrl, $segment, $parameters);
    }

    /**
     * Executes a non-public API request (market|account),
     * using nonce, key & secret
     *
     * @param $baseUrl
     * @param $segment
     * @param array $parameters
     * @return array
     */
    protected function nonPublicRequest($baseUrl, $segment, $parameters=[]) {
        $parameters = array_merge(array_filter($parameters), [
            'apiKey' => $this->key,
            'nonce' => time()
        ]);

        $uri = $baseUrl . $segment . '?' . http_build_query($parameters);
        $sign = hash_hmac('sha512', $uri, $this->secret);
        $ch = curl_init($uri);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "apisign:$sign",
        ]);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_USERAGENT,
            'Mozilla/4.0 (compatible; Bittrex PHP-Laravel Client; ' . php_uname('a') . '; PHP/' . phpversion() . ')'
        );

        $execResult = curl_exec($ch);
        $res = json_decode($execResult, true);
        return $res;
    }

    private function getPublicUrl($version)
    {
        switch($version) {
            case 'v1.1':
                return $this->publicUrl;
            case 'v2.0':
                return $this->publicUrlV2;
            default:
                throw new \Exception("Invalid Bittrex API version: $version");
        }
    }
}


<?php

namespace Nexmo\Service\Account;

use Nexmo\Entity\MatchingStrategy;
use Nexmo\Entity\NumberCollection;
use Nexmo\Exception;
use Nexmo\Service\Service;

/**
 * Get all inbound numbers associated with your account.
 *
 * @author Carson Full <carsonfull@gmail.com>
 */
class Numbers extends Service
{
    /**
     * @inheritdoc
     */
    public function getEndpoint()
    {
        return 'account/numbers';
    }

    /**
     * @param int        $index
     * @param int        $size
     * @param string|int $pattern
     * @param int        $searchPattern
     *
     * @return NumberCollection
     * @throws Exception
     */
    public function invoke($index = 1, $size = 10, $pattern = null, $searchPattern = MatchingStrategy::STARTS_WITH)
    {
        $size = min($size, 100);

        return new NumberCollection($this->exec([
            'index'          => $index,
            'size'           => $size,
            'pattern'        => $pattern,
            'search_pattern' => $searchPattern,
        ]));
    }

    /**
     * @inheritdoc
     */
    protected function validateResponse(array $json)
    {
        if (!isset($json['count'])) {
            throw new Exception('count property expected');
        }
        if (!isset($json['numbers']) || !is_array($json['numbers'])) {
            throw new Exception('numbers array property expected');
        }
        foreach ($json['numbers'] as $number) {
            if (!isset($number['country'])) {
                throw new Exception('number.country property expected');
            }
            if (!isset($number['msisdn'])) {
                throw new Exception('number.msisdn property expected');
            }
            if (!isset($number['type'])) {
                throw new Exception('number.type property expected');
            }
            if (!isset($number['features']) || !is_array($number['features'])) {
                throw new Exception('number.features array property expected');
            }
            if (!isset($number['moHttpUrl'])) {
                throw new Exception('number.moHttpUrl property expected');
            }
        }
    }
}


<?php

namespace Nexmo\Service\Account\Pricing;

use Nexmo\Entity;
use Nexmo\Exception;
use Nexmo\Service\Service;

/**
 * Retrieve Nexmo's outbound pricing for a given country.
 *
 * @author Carson Full <carsonfull@gmail.com>
 */
class Country extends Service
{
    /**
     * @inheritdoc
     */
    public function getEndpoint()
    {
        return 'account/get-pricing/outbound';
    }

    /**
     * @param string $country
     *
     * @return Entity\Pricing
     * @throws Exception
     */
    public function invoke($country = null)
    {
        if (!$country) {
            throw new Exception('$country parameter cannot be blank');
        }

        return new Entity\Pricing($this->exec([
            'country' => $country,
        ]));
    }

    /**
     * @inheritdoc
     */
    protected function validateResponse(array $json)
    {
        if (!isset($json['country'])) {
            throw new Exception('country property expected');
        }
        if (!isset($json['name'])) {
            throw new Exception('name property expected');
        }
        if (!isset($json['prefix'])) {
            throw new Exception('prefix property expected');
        }
        if (!isset($json['networks']) || !is_array($json['networks'])) {
            return;
        }
        foreach ($json['networks'] as $network) {
            if (!isset($network['code'])) {
                throw new Exception('network.code property expected');
            }
            if (!isset($network['network'])) {
                throw new Exception('network.network property expected');
            }
            if (!isset($network['mtPrice'])) {
                throw new Exception('network.mtPrice property expected');
            }
        }
    }
}


<?php namespace Arcanedev\LaravelSeo\Models;

use Arcanedev\LaravelSeo\Seo;
use Illuminate\Support\Arr;

/**
 * Class     Meta
 *
 * @package  Arcanedev\LaravelSeo\Models
 * @author   ARCANEDEV <arcanedev.maroc@gmail.com>
 *
 * @property  int                                  id
 * @property  int                                  seoable_id
 * @property  string                               seoable_type
 * @property  string                               title
 * @property  string                               description
 * @property  \Illuminate\Support\Collection       keywords
 * @property  boolean                              noindex
 * @property  \Illuminate\Support\Collection       extras
 * @property  \Carbon\Carbon                       created_at
 * @property  \Carbon\Carbon                       updated_at
 *
 * @property  \Illuminate\Database\Eloquent\Model  seoable
 */
class Meta extends AbstractModel
{
    /* -----------------------------------------------------------------
     |  Traits
     | -----------------------------------------------------------------
     */

    use Presenters\MetaPresenter;

    /* -----------------------------------------------------------------
     |  Properties
     | -----------------------------------------------------------------
     */

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['title', 'description', 'keywords', 'noindex', 'extras'];

    /**
     * The attributes that should be casted to native types.
     *
     * @var array
     */
    protected $casts = [
        'id'         => 'integer',
        'seoable_id' => 'integer',
        'keywords'   => 'collection',
        'noindex'    => 'boolean',
        'extras'     => 'collection',
    ];

    /* -----------------------------------------------------------------
     |  Constructor
     | -----------------------------------------------------------------
     */

    /**
     * Meta constructor.
     *
     * @param  array  $attributes
     */
    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);

        $this->setTable(Seo::getConfig('metas.table', 'metas'));
    }

    /* -----------------------------------------------------------------
     |  Relationships
     | -----------------------------------------------------------------
     */

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphTo
     */
    public function seoable()
    {
        return $this->morphTo();
    }

    /* -----------------------------------------------------------------
     |  Other Methods
     | -----------------------------------------------------------------
     */

    /**
     * Prepare the attributes.
     *
     * @param  array  $attributes
     *
     * @return array
     */
    public static function prepareAttributes(array $attributes)
    {
        return [
            'title'       => Arr::get($attributes, 'title'),
            'description' => Arr::get($attributes, 'description'),
            'keywords'    => Arr::get($attributes, 'keywords', []),
            'extras'      => Arr::get($attributes, 'extras', []),
            'noindex'     => Arr::get($attributes, 'noindex', false),
        ];
    }

    /**
     * Add an extra meta.
     *
     * @param  string  $key
     * @param  mixed   $value
     *
     * @return $this
     */
    public function addExtra($key, $value)
    {
        return $this->setExtras(
            $this->extras->put($key, $value)->all()
        );
    }

    /**
     * Add extra metas.
     *
     * @param  mixed  $extras
     *
     * @return $this
     */
    public function addExtras($extras)
    {
        return $this->setExtras(
            $this->extras->merge($extras)->all()
        );
    }

    /**
     * Set the extras.
     *
     * @param  mixed  $extras
     *
     * @return $this
     */
    public function setExtras($extras)
    {
        $this->extras = collect($extras);

        return $this;
    }
}


<?php
/**
 * ManiaLib - Lightweight PHP framework for Manialinks
 *
 * @see         http://code.google.com/p/manialib/
 * @copyright   Copyright (c) 2009-2011 NADEO (http://www.nadeo.com)
 * @license     http://www.gnu.org/licenses/lgpl.html LGPL License 3
 * @version     $Revision$:
 * @author      $Author$:
 * @date        $Date$:
 */

namespace ManiaLib\Database;

class RecordSet
{
    const FETCH_ASSOC = MYSQLI_ASSOC;
    const FETCH_NUM = MYSQLI_NUM;
    const FETCH_BOTH = MYSQLI_BOTH;

    protected $result;

    function __construct($result)
    {
        $this->result = $result;
    }

    function checkIfEmpty()
    {
        if ($this->recordCount() == 0) {
            throw new RecordNotFoundException('Record not found');
        }
    }

    /**
     * Get a result row as an enumerated array
     * @return array
     */
    function fetchRow()
    {
        return mysqli_fetch_row($this->result);
    }

    function fetchArrayOfRow()
    {
        $array = array();
        while ($row = $this->fetchRow()) {
            $array[] = $row;
        }
        return $array;
    }

    /**
     * Fetch a result row as an associative array
     * @return array
     */
    function fetchAssoc()
    {
        return mysqli_fetch_assoc($this->result);
    }

    function fetchArrayOfAssoc()
    {
        $array = array();
        while ($row = $this->fetchAssoc()) {
            $array[] = $row;
        }
        return $array;
    }

    /**
     * Fetch a result row as an associative, a numeric array, or both
     * @return array
     */
    function fetchArray($resultType = self::FETCH_ASSOC)
    {
        return mysqli_fetch_array($this->result, $resultType);
    }

    /**
     * Returns the current row of a result set as an object
     * @param string The name of the class to instantiate, set the properties of and return. If not specified, a \stdClass object is returned.
     * @param array An optional array of parameters to pass to the constructor for class_name objects.
     * @return object
     */
    function fetchObject($className = '\\stdClass', $params = array())
    {
        if ($className) {
            if ($params) {
                return mysqli_fetch_object($this->result, $className, $params);
            } else {
                return mysqli_fetch_object($this->result, $className);
            }
        } else {
            return mysqli_fetch_object($this->result);
        }
    }

    function fetchArrayOfObject($className = '\\stdClass', $params = array())
    {
        $array = array();
        while ($row = $this->fetchObject($className, $params)) {
            $array[] = $row;
        }
        return $array;
    }

    /**
     * Fetches a single value of the current row, or the default value if there's no row.
     * Typically useful for SELECT COUNT() queries.
     */
    function fetchSingleValue($default = 0, $throwException = false)
    {
        $row = $this->fetchRow();
        if ($row) {
            return reset($row);
        } elseif (!$throwException) {
            return $default;
        } else {
            throw new RecordNotFoundException('Record not found');
        }
    }

    function fetchArrayOfSingleValues()
    {
        $array = array();
        while ($row = mysqli_fetch_row($this->result)) {
            $array[] = reset($row);
        }
        return $array;
    }

    /**
     * Gets the number of rows in a result
     * @return int
     */
    function recordCount()
    {
        return mysqli_num_rows($this->result);
    }

}


<?php namespace Arcanedev\LaravelSeo;

use Arcanedev\Support\PackageServiceProvider;

/**
 * Class     LaravelSeoServiceProvider
 *
 * @package  Arcanedev\LaravelSeo
 * @author   ARCANEDEV <arcanedev.maroc@gmail.com>
 */
class LaravelSeoServiceProvider extends PackageServiceProvider
{
    /* -----------------------------------------------------------------
     |  Properties
     | -----------------------------------------------------------------
     */

    /**
     * Package name.
     *
     * @var string
     */
    protected $package = 'laravel-seo';

    /* -----------------------------------------------------------------
     |  Main Methods
     | -----------------------------------------------------------------
     */

    /**
     * Register the service provider.
     */
    public function register()
    {
        parent::register();

        $this->registerConfig();

        $this->registerProvider(Providers\RouteServiceProvider::class);

        $this->singleton(Contracts\RedirectorFactory::class, function ($app) {
            return new RedirectorManager($app);
        });
    }

    /**
     * Boot the service provider.
     */
    public function boot()
    {
        parent::boot();

        $this->publishConfig();

        $this->loadMigrations();
        $this->loadTranslations();
    }

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