<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Config;

use Autarky\Config\Loaders\CachingYamlFileLoader;
use Autarky\Config\Loaders\YamlFileLoader;
use Autarky\Container\ContainerInterface;
use Autarky\Files\PathResolver;
use Autarky\Providers\AbstractProvider;

/**
 * Provides config to the application.
 *
 * This service provider is vital to the framework.
 */
class ConfigProvider extends AbstractProvider
{
	/**
	 * The path in which config files are located.
	 *
	 * @var string
	 */
	protected $configPath;

	/**
	 * @param string $configPath The path in which config files are located.
	 */
	public function __construct($configPath)
	{
		$this->configPath = $configPath;
	}

	/**
	 * {@inheritdoc}
	 */
	public function register()
	{
		$this->app->setConfig($store = $this->getConfigStore());

		if ($store->has('app.configurators')) {
			foreach ($store->get('app.configurators') as $configurator) {
				$this->app->config($configurator);
			}
		}
	}

	protected function getConfigStore()
	{
		$dic = $this->app->getContainer();

		// set up the factory
		$loaderFactory = new LoaderFactory($dic);
		$dic->instance('Autarky\Config\Loaders\LoaderFactory', $loaderFactory);

		// set up the config store
		$store = new FileStore(
			new PathResolver($this->configPath),
			$loaderFactory,
			$this->app->getEnvironment()
		);
		$dic->instance('Autarky\Config\FileStore', $store);
		$dic->alias('Autarky\Config\FileStore', 'Autarky\Config\ConfigInterface');

		// set up the PHP file loader
		$dic->share('Autarky\Config\Loaders\PhpFileLoader');
		$loaderFactory->addLoader('.php', 'Autarky\Config\Loaders\PhpFileLoader');

		// set up the YAML config file loaders
		$dic->define('Autarky\Config\Loaders\YamlFileLoader', function(ContainerInterface $dic) {
			return new YamlFileLoader(
				$dic->resolve('Symfony\Component\Yaml\Parser')
			);
		});
		$dic->share('Autarky\Config\Loaders\YamlFileLoader');

		$yamlCachePath = $this->getYamlCachePath($store);
		$dic->define('Autarky\Config\Loaders\CachingYamlFileLoader', function(ContainerInterface $dic) use($yamlCachePath) {
			return new CachingYamlFileLoader(
				$dic->resolve('Symfony\Component\Yaml\Parser'),
				$yamlCachePath
			);
		});
		$dic->share('Autarky\Config\Loaders\CachingYamlFileLoader');

		$loader = $yamlCachePath
			? 'Autarky\Config\Loaders\CachingYamlFileLoader'
			: 'Autarky\Config\Loaders\YamlFileLoader';
		$loaderFactory->addLoader(['.yml', '.yaml'], $loader);

		// done!
		return $store;
	}

	protected function getYamlCachePath(ConfigInterface $config = null)
	{
		if (file_exists($this->configPath.'/path.yml')) {
			throw new \RuntimeException("The 'path' config file cannot be YAML when using the caching YAML config file loader.");
		}

		$config = $config ?: $this->app->getConfig();

		$path = $config->get('path.storage').'/yaml';

		if (is_dir($path) && is_writable($path)) {
			return $path;
		}

		return null;
	}
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Http;

use Exception;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\TerminableInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

use Autarky\Errors\ErrorHandlerInterface;
use Autarky\Routing\RouterInterface;

/**
 * The framework's HTTP kernel.
 *
 * @internal
 */
class Kernel implements HttpKernelInterface, TerminableInterface
{
	/**
	 * @var RouterInterface
	 */
	protected $router;

	/**
	 * @var RequestStack
	 */
	protected $requests;

	/**
	 * @var ErrorHandlerInterface
	 */
	protected $errorHandler;

	/**
	 * @var EventDispatcherInterface
	 */
	protected $eventDispatcher;

	/**
	 * @param ErrorHandlerInterface $errorHandler Optional
	 * @param EventDispatcherInterface $eventDispatcher Optional
	 */
	public function __construct(
		RouterInterface $router,
		RequestStack $requests,
		ErrorHandlerInterface $errorHandler = null,
		EventDispatcherInterface $eventDispatcher = null
	) {
		$this->router = $router;
		$this->requests = $requests;
		$this->errorHandler = $errorHandler;
		$this->eventDispatcher = $eventDispatcher;
	}

	/**
	 * {@inheritdoc}
	 */
	public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
	{
		try {
			return $this->innerHandle($request, $type);
		} catch (Exception $exception) {
			if (!$catch) {
				$this->finishRequest($request, $type);
				throw $exception;
			}

			return $this->handleException($exception, $request, $type);
		}
	}

	protected function innerHandle(Request $request, $type)
	{
		$this->requests->push($request);

		if ($this->eventDispatcher !== null) {
			$event = new GetResponseEvent($this, $request, $type);
			$this->eventDispatcher->dispatch(KernelEvents::REQUEST, $event);
			$response = $event->getResponse() ?: $this->router->dispatch($request);
		} else {
			$response = $this->router->dispatch($request);
		}

		return $this->filterResponse($response, $request, $type);
	}

	protected function handleException(Exception $exception, Request $request, $type)
	{
		if ($this->errorHandler === null) {
			throw $exception;
		}

		if ($this->eventDispatcher !== null) {
			$event = new GetResponseForExceptionEvent($this, $request, $type, $exception);
			$this->eventDispatcher->dispatch(KernelEvents::EXCEPTION, $event);
			$response = $event->getResponse() ?: $this->errorHandler->handle($exception);
		} else {
			$response = $this->errorHandler->handle($exception);
		}

		try {
			return $this->filterResponse($response, $request, $type);
		} catch (Exception $e) {
			return $response;
		}
	}

	protected function filterResponse(Response $response, Request $request, $type)
	{
		if ($this->eventDispatcher !== null) {
			$event = new FilterResponseEvent($this, $request, $type, $response);
			$this->eventDispatcher->dispatch(KernelEvents::RESPONSE, $event);
			$response = $event->getResponse();
		}

		$response->prepare($request);

		$this->finishRequest($request, $type);

		return $response;
	}

	protected function finishRequest(Request $request, $type)
	{
		if ($this->eventDispatcher !== null) {
			$event = new FinishRequestEvent($this, $request, $type);
			$this->eventDispatcher->dispatch(KernelEvents::FINISH_REQUEST, $event);
		}

		$this->requests->pop();
	}

	/**
	 * {@inheritdoc}
	 */
	public function terminate(Request $request, Response $response)
	{
		if ($this->eventDispatcher !== null) {
			$event = new PostResponseEvent($this, $request, $response);
			$this->eventDispatcher->dispatch(KernelEvents::TERMINATE, $event);
		}
	}
}


<?php

/**
 * Moo_EditableField is a base class for editable fields to extend.
 *
 * @author  Mohamed Alsharaf <mohamed.alsharaf@gmail.com>
 *
 * @property string $Title
 * @property string $Name
 * @property int    $Required
 * @property string $CustomErrorMessage
 * @property string $CustomSettings
 */
class Moo_EditableField extends DataObject
{
    private static $db = [
        'Name'               => 'Varchar',
        'Title'              => 'Varchar(255)',
        'Required'           => 'Boolean',
        'CustomErrorMessage' => 'Varchar(255)',
        'CustomSettings'     => 'Text',
    ];
    private static $singular_name = 'Editable Field';
    private static $plural_name   = 'Editable Fields';

    /**
     * List of fields names part of the custom settings.
     *
     * @var array
     */
    protected $customSettingsFields = [];

    /**
     * Instance of FormField.
     *
     * @var FormField
     */
    protected $field;

    /**
     * To prevent having tables for each fields minor settings we store it as
     * a serialized array in the database.
     *
     * @return array Return all the Settings
     */
    public function getSettings()
    {
        return (!empty($this->CustomSettings)) ? unserialize($this->CustomSettings) : [];
    }

    /**
     * Set the custom settings for this field as we store the minor details in
     * a serialized array in the database.
     *
     * @param array $settings the custom settings
     */
    public function setSettings($settings = [])
    {
        $this->CustomSettings = serialize($settings);
    }

    /**
     * Set a given field setting. Appends the option to the settings or overrides
     * the existing value.
     *
     * @param string $key
     * @param string $value
     */
    public function setSetting($key, $value)
    {
        $settings       = $this->getSettings();
        $settings[$key] = $value;

        $this->setSettings($settings);
    }

    /**
     * Return just one custom setting or empty string if it does
     * not exist.
     *
     * @param string $setting
     *
     * @return string
     */
    public function getSetting($setting)
    {
        $settings = $this->getSettings();
        if (isset($settings) && count($settings) > 0) {
            if (isset($settings[$setting])) {
                return $settings[$setting];
            }
        }

        return '';
    }

    /**
     * Get the path to the icon for this field type, relative to the site root.
     *
     * @return string
     */
    public function getIcon()
    {
        return 'editablefield/images/formfields/' . strtolower(substr($this->class, 4)) . '.png';
    }

    /**
     * Get the icon HTML tag.
     *
     * @return string
     */
    public function getIconTag()
    {
        return '<img src="' . $this->getIcon() . '"/>';
    }

    public function getCMSFields()
    {
        $fields = parent::getCMSFields();

        // Remove field to be recreated in separate tabs
        $fields->removeByName([
            'Required', 'CustomErrorMessage', 'CustomSettings', 'Options',
        ]);

        // Add default field configurations "custom settings"
        $fields->addFieldsToTab('Root.FieldConfiguration', [
            new TextField(
                $this->getSettingName('RightTitle'), _t('Moo_EditableField.RIGHTTITLE', 'Right Title'),
                $this->getSetting('RightTitle')
            ),
        ]);

        // Add default validation fields
        $validateFields = [
            new CheckboxField('Required', _t('Moo_EditableField.REQUIRED', 'Is this field Required?'), $this->Required),
            new TextField('CustomErrorMessage', _t('Moo_EditableField.CUSTOMERROR', 'Custom Error Message'), $this->CustomErrorMessage),
        ];
        $fields->addFieldsToTab('Root.Validation', $validateFields);

        // Add extra field configurations "custom settings" from the subclass
        if (method_exists($this, 'getFieldConfiguration')) {
            $fields->addFieldsToTab('Root.FieldConfiguration', $this->getFieldConfiguration());
        }

        // Add extra validation fields from the subclass
        if (method_exists($this, 'getFieldValidationOptions')) {
            $fields->addFieldsToTab('Root.Validation', $this->getFieldValidationOptions());
        }

        return $fields;
    }

    public function getCMSValidator()
    {
        return new RequiredFields(
            'Title', 'Name'
        );
    }

    /**
     * Returns the Title for rendering in the front-end (with XML values escaped).
     *
     * @return string
     */
    public function getTitle()
    {
        return Convert::raw2att($this->getField('Title'));
    }

    /**
     * Generate a name for the Setting field.
     *
     * @param string $field
     *
     * @return string
     */
    public function getSettingName($field)
    {
        return 'CustomSettings[' . $field . ']';
    }

    /**
     * How to save the data submitted in this field into the database object
     * which this field represents.
     *
     * Any class's which call this should also call
     * {@link parent::populateFromPostData()} to ensure that this method is
     * called
     *
     * @throws ValidationException
     */
    public function onBeforeWrite()
    {
        $return = parent::onBeforeWrite();

        // Field name must be unique
        $exists = self::get()->filter('Name', $this->Name)->exclude('ID', $this->ID);
        if ($exists->count()) {
            throw new ValidationException(
                _t('Moo_EditableField.UNIQUENAME', 'Field name "{name}" must be unique', '',
                    ['name' => $this->Name])
            );
        }

        // Filter field name from un-supported HTML attribute value
        $this->Name = preg_replace('/[^a-zA-Z0-9_]+/', '', $this->Name);

        // Get custom settings from the current object of request POST
        $customSettings = $this->getSettings();
        if (empty($customSettings)) {
            $customSettings = (array) Controller::curr()->getRequest()->postVar('CustomSettings');
        }

        // Filter out any un-supported settings by the subclasss
        if (!empty($this->customSettingsFields)) {
            $customSettings = array_intersect_key($customSettings, array_flip((array) $this->customSettingsFields));
        }

        // Set the filtered settings
        $this->setSettings($customSettings);

        return $return;
    }

    /**
     * Return a FormField.
     *
     * @return FormField
     */
    public function getFormField()
    {
        if (null === $this->field) {
            $this->field = $this->initFormField();
        }

        return $this->field;
    }

    /**
     * Initiate a form field.
     *
     * @return FormField
     */
    protected function initFormField()
    {
        throw new DomainException(sprintf('%s must be implemented by the class %s', __METHOD__, $this->class));
    }

    /**
     * Return the error message for this field. Either uses the custom
     * one (if provided) or the default SilverStripe message.
     *
     * @return Varchar
     */
    public function getErrorMessage()
    {
        $title    = strip_tags("'" . ($this->Title ? $this->Title : $this->Name) . "'");
        $standard = _t('Form.FIELDISREQUIRED', '{name} is required', ['name' => $title]);

        // only use CustomErrorMessage if it has a non empty value
        $errorMessage = (!empty($this->CustomErrorMessage)) ? $this->CustomErrorMessage : $standard;

        return DBField::create_field('Varchar', $errorMessage);
    }

    public function onBeforeDuplicate(Moo_EditableField $field)
    {
        // The name field must be unique, this is temporary workaround
        $this->setField('Name', $field->Name . uniqid());
    }
}


<?php

namespace Singo\Bus\Middleware;

use League\Tactician\Middleware;
use Psr\Log\LoggerInterface;
use Singo\Bus\Exception\InvalidCommandException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validator;

/**
 * Class CommandValidationMiddleware
 * @package Singo\Bus\Middleware
 */
class CommandValidationMiddleware implements Middleware
{
    /**
     * @var Validator\ValidatorInterface
     */
    private $validator;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @param Validator\ValidatorInterface $validator
     * @param LoggerInterface $logger
     */
    public function __construct(Validator\ValidatorInterface $validator, LoggerInterface $logger)
    {
        $this->validator = $validator;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function execute($command, callable $next)
    {
        $command_name = get_class($command);

        $this->logger->info("validating {$command_name}");

        $violation = $this->validator->validate($command);
        if ($violation->count() > 0) {
            $message = str_replace(
                "This value",
                ucfirst($violation->get(0)->getPropertyPath()),
                $violation->get(0)->getMessage()
            );
            $this->logger->error("{$command_name} : {$message}");
            throw new InvalidCommandException($message, Response::HTTP_BAD_REQUEST);
        }

        $this->logger->info("{$command_name} has passed validation");
        return $next($command);
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Files;

/**
 * Class that performs a locking file read/write operation.
 *
 * The object will add a file lock before writing and release it right after the
 * contents have been written. This can be used to prevent corruption of data
 * when multiple requests try to write to the same file at the same time.
 */
class LockingFilesystem
{
	/**
	 * Read from a file.
	 *
	 * @param  string $path Path to the file.
	 * @param  bool   $blocking Wait for other locks to expire rather than
	 * throwing an error when a lock cannot be aquired.
	 *
	 * @return string
	 *
	 * @throws IOException
	 */
	public function read($path, $blocking = false)
	{
		$size = filesize($path);

		if ($size === 0) {
			return '';
		}

		$flockFlags = $blocking ? LOCK_SH : LOCK_SH | LOCK_NB;

		$file = fopen($path, 'r');

		if (!flock($file, $flockFlags)) {
			fclose($file);
			throw new IOException("Could not aquire file lock for file: $path");
		}

		$contents = fread($file, $size);
		flock($file, LOCK_UN | LOCK_NB);
		fclose($file);

		return $contents;
	}

	/**
	 * Write to the file.
	 *
	 * @param  string $path Path to the file.
	 * @param  string $contents Contents to write to the file.
	 * @param  bool   $blocking Wait for other locks to expire rather than
	 * throwing an error when a lock cannot be aquired.
	 *
	 * @return void
	 *
	 * @throws IOException
	 */
	public function write($path, $contents, $blocking = false)
	{
		$flockFlags = $blocking ? LOCK_EX : LOCK_EX | LOCK_NB;

		$file = fopen($path, 'c');

		if (!flock($file, $flockFlags)) {
			fclose($file);
			throw new IOException("Could not aquire file lock for file: $path");
		}

		ftruncate($file, 0);
		fwrite($file, $contents);
		fflush($file);
		flock($file, LOCK_UN | LOCK_NB);
		fclose($file);
	}
}


<?php

namespace Aptoma\Security\Http\Firewall;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Aptoma\Security\Authentication\Token\ApiKeyToken;

class ApiKeyAuthenticationListener implements ListenerInterface
{
    private $tokenStorage;
    private $authenticationManager;

    public function __construct(
        TokenStorageInterface $tokenStorage,
        AuthenticationManagerInterface $authenticationManager
    ) {
        $this->tokenStorage = $tokenStorage;
        $this->authenticationManager = $authenticationManager;
    }

    /**
     * Handles API key authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    public function handle(GetResponseEvent $event)
    {
        $apiKey = $this->getApiKeyFromQueryOrHeader($event->getRequest());

        if (false === $apiKey) {
            return;
        }

        try {
            $token = $this->authenticationManager->authenticate(new ApiKeyToken($apiKey));
            $this->tokenStorage->setToken($token);
        } catch (AuthenticationException $failed) {
            $this->tokenStorage->setToken(null);
            $this->doFailureResponse($event);
        }
    }

    /**
     * Failure response
     *
     * Can be overridden if a different response is needed
     *
     * @param GetResponseEvent $event
     */
    protected function doFailureResponse(GetResponseEvent $event)
    {
        $headers = array();
        $content = 'Forbidden';
        if (in_array('application/json', $event->getRequest()->getAcceptableContentTypes())) {
            $headers['Content-Type'] = 'application/json';
            $content = json_encode(array('message' => $content));
        }

        $event->setResponse(new Response($content, 403, $headers));
    }

    /**
     * @param Request $request
     * @return string|boolean
     */
    private function getApiKeyFromQueryOrHeader(Request $request)
    {
        $apiKey = $request->get('apikey', false);
        if ($apiKey) {
            return $apiKey;
        }

        $apiKeyHeader = $request->headers->get('authorization');
        if (!($apiKeyHeader && mb_strpos($apiKeyHeader, 'apikey') === 0)) {
            return false;
        }
        $apiKeyHeadersParts = explode(' ', $apiKeyHeader);

        if (!isset($apiKeyHeadersParts[1])) {
            return false;
        }

        return $apiKeyHeadersParts[1];
    }
}


<?php

namespace BurnBright\ExternalURLField;

use SilverStripe\Forms\TextField;

/**
 * ExternalURLField
 *
 * Form field for entering, saving, validating external urls.
 */
class ExternalURLField extends TextField
{
    /**
     * Default configuration
     *
     * URL validation regular expression was sourced from
     * @see https://gist.github.com/dperini/729294
     * @var array
     */
    private static $default_config = array(
        'defaultparts' => array(
            'scheme' => 'http'
        ),
        'removeparts' => array(
            'scheme' => false,
            'user' => true,
            'pass' => true,
            'host' => false,
            'port' => false,
            'path' => false,
            'query' => false,
            'fragment' => false
        ),
        'html5validation' => true,
        'validregex' => '%^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu'
    );

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

    public function __construct($name, $title = null, $value = null)
    {
        $this->config = $this->config()->default_config;

        parent::__construct($name, $title, $value);
    }

    public function Type()
    {
        return 'url text';
    }

    /**
     * @param string $name
     * @param mixed $val
     */
    public function setConfig($name, $val = null)
    {
        if (is_array($name) && $val == null) {
            foreach ($name as $n => $value) {
                $this->setConfig($n, $value);
            }

            return $this;
        }
        if (is_array($this->config[$name])) {
            if (!is_array($val)) {
                user_error("The value for $name must be an array");
            }
            $this->config[$name] = array_merge($this->config[$name], $val);
        } elseif (isset($this->config[$name])) {
            $this->config[$name] = $val;
        }

        return $this;
    }

    /**
     * @param String $name Optional, returns the whole configuration array if empty
     * @return mixed|array
     */
    public function getConfig($name = null)
    {
        if ($name) {
            return isset($this->config[$name]) ? $this->config[$name] : null;
        } else {
            return $this->config;
        }
    }

    /**
     * Set additional attributes
     * @return array Attributes
     */
    public function getAttributes()
    {
        $attributes = array(
            'placeholder' => $this->config['defaultparts']['scheme'] . "://example.com" //example url
        );
        if ($this->config['html5validation']) {
            $attributes += array(
                'type' => 'url', //html5 field type
                'pattern' => 'https?://.+', //valid urls only
            );
        }

        return array_merge(
            parent::getAttributes(),
            $attributes
        );
    }

    /**
     * Rebuild url on save
     * @param string $url
     */
    public function setValue($url)
    {
        if ($url) {
            $url = $this->rebuildURL($url);
        }
        parent::setValue($url);
    }

    /**
     * Add config scheme, if missing.
     * Remove the parts of the url we don't want.
     * Set any defaults, if missing.
     * Remove any trailing slash, and rebuild.
     * @return string
     */
    protected function rebuildURL($url)
    {
        $defaults = $this->config['defaultparts'];
        if (!preg_match('#^[a-zA-Z]+://#', $url)) {
            $url = $defaults['scheme'] . "://" . $url;
        }
        $parts = parse_url($url);
        if (!$parts) {
            //can't parse url, abort
            return "";
        }
        foreach ($parts as $part => $value) {
            if ($this->config['removeparts'][$part] === true) {
                unset($parts[$part]);
            }
        }
        //set defaults, if missing
        foreach ($defaults as $part => $default) {
            if (!isset($parts[$part])) {
                $parts[$part] = $default;
            }
        }

        return rtrim(http_build_url($defaults, $parts), "/");
    }

    /**
     * Server side validation, using a regular expression.
     */
    public function validate($validator)
    {
        $this->value = trim($this->value);
        $regex = $this->config['validregex'];
        if ($this->value && $regex && !preg_match($regex, $this->value)) {
            $validator->validationError(
                $this->name,
                _t('ExternalURLField.VALIDATION', "Please enter a valid URL"),
                "validation"
            );
            return false;
        }
        return true;
    }
}


<?php

/**
 * Moo_EditableFieldGroup is a data object class for editable field group.
 *
 * @author  Mohamed Alsharaf <mohamed.alsharaf@gmail.com>
 *
 * @method ManyManyList Fields()
 */
class Moo_EditableFieldGroup extends DataObject
{
    private static $db = [
        'Title' => 'Varchar(255)',
    ];

    private static $many_many = [
        'Fields' => 'Moo_EditableField',
    ];

    private static $many_many_extraFields = [
        'Fields' => [
            'Sort' => 'Int',
        ],
    ];

    private static $default_sort = '"Title"';

    private static $singular_name = 'Group';

    private static $plural_name = 'Groups';

    /**
     * Make sure the title is required field.
     *
     * @return RequiredFields
     */
    public function getCMSValidator()
    {
        return new RequiredFields('Title');
    }

    /**
     * Returns form fields for adding/editing the data object.
     *
     * @return FieldList
     */
    public function getCMSFields()
    {
        $fields = parent::getCMSFields();

        // Field visible on edit only
        if ($this->isInDB()) {
            $config = GridFieldConfig_RelationEditor::create();
            $config
                ->getComponentByType('GridFieldPaginator')
                ->setItemsPerPage(10);
            $config->removeComponentsByType('GridFieldAddNewButton');
            $config->removeComponentsByType('GridFieldEditButton');
            $config
                ->getComponentByType('GridFieldDataColumns')
                ->setDisplayFields([
                    'Name'  => _t('Moo_EditableFieldGroup.NAME', 'Name'),
                    'Title' => _t('Moo_EditableFieldGroup.TITLE', 'Title'),
                    'Sort'  => _t('Moo_EditableFieldGroup.SORT', 'Sort'),
                ]);
            $config->addComponent(new GridFieldOrderableRows('Sort'));
            $field = new GridField('Fields', 'Fields', $this->Fields(), $config);
            $fields->addFieldToTab('Root.Fields', $field);
        }

        return $fields;
    }
}


<?php

namespace Singo\Bus\Middleware;

use League\Tactician\Middleware;
use Psr\Log\LoggerInterface;

/**
 * Class CommandLoggerMiddleware
 * @package Singo\Bus\Middleware
 */
class CommandLoggerMiddleware implements Middleware
{
    /**
     * @var LoggerInterface
     */
    private $logger;

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

    /**
     * {@inheritdoc}
     */
    public function execute($command, callable $next)
    {
        $command_name = get_class($command);

        $this->logger->info("executing {$command_name}");

        $return_value = $next($command);

        $this->logger->info("{$command_name} executed with no error");

        return $return_value;
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Files;

/**
 * Class that resolves possible paths based on various factors.
 */
class PathResolver
{
	/**
	 * Main paths.
	 *
	 * @var string[]
	 */
	protected $paths;

	/**
	 * External paths mounted onto locations on the main path.
	 *
	 * @var string[][]
	 */
	protected $mounts;

	/**
	 * Constructor
	 *
	 * @param string|array $pathOrPaths
	 */
	public function __construct($pathOrPaths = [])
	{
		$this->paths = (array) $pathOrPaths;
	}

	/**
	 * Add a main path.
	 *
	 * @param string $path
	 */
	public function addPath($path)
	{
		$this->paths[] = $path;
	}

	/**
	 * Mount a path onto a location.
	 *
	 * @param  string $location
	 * @param  string $path
	 */
	public function mount($location, $path)
	{
		$this->mounts[$location][] = $path;
	}

	/**
	 * Resolve possible paths for a relative path.
	 *
	 * @param  string $path
	 *
	 * @return array
	 */
	public function resolve($path)
	{
		$paths = [];

		foreach ($this->paths as $configuredPath) {
			$paths[] = $configuredPath.'/'.$path;
		}

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

		// this doesn't change behaviour but will save some performance
		if (count($parts) == 1) {
			return $paths;
		}

		$current = '';
		$mountPaths = [];
		foreach ($parts as $part) {
			if ($current) {
				$current .= '/'.$part;
			} else {
				$current = $part;
			}

			if (isset($this->mounts[$current])) {
				foreach ($this->mounts[$current] as $mount) {
					// relative to mount directory
					$relativePath = str_replace($current, '', $path);
					$mountPaths[] = $mount.$relativePath;
				}
			}
		}

		return array_merge($mountPaths, $paths);
	}

	/**
	 * Based on a set of basenames (filename without extension) and a set of
	 * possible extensions, find the files that exist.
	 *
	 * @param  string|string[] $basenameOrNames
	 * @param  string|string[] $extensionOrExtensions
	 *
	 * @return string[]
	 */
	public function locate($basenameOrNames, $extensionOrExtensions)
	{
		$basenames = (array) $basenameOrNames;
		$extensions = (array) $extensionOrExtensions;

		$located = [];

		foreach ($basenames as $basename) {
			foreach ($extensions as $ext) {
				$path = $basename.$ext;
				if (file_exists($path)) {
					$located[] = $path;
				}
			}
		}

		return $located;
	}
}


<?php

namespace DMR\Mapping;

use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
use Doctrine\Common\Cache\ArrayCache;
use DMR\Mapping\Driver\AnnotationDriverInterface;

/**
 * Metadata factory.
 *
 * @author Marcos Passos <marcos@marcospassos.com>
 */
class DriverFactory
{
    /**
     * Returns the annotation reader.
     *
     * @return \Doctrine\Common\Annotations\Reader
     */
    protected static function getAnnotationReader()
    {
        return new CachedReader(new AnnotationReader(), new ArrayCache());
    }

    /**
     * Creates a driver based on original driver that is being used by Doctrine.
     *
     * @param MappingDriver $originalDriver The instance of MappingDriver
     * @param string        $namespace      The namespace where the drivers are located
     *
     * @throws \Exception
     * @throws \RuntimeException
     *
     * @return DriverInterface
     */
    public static function getDriver(MappingDriver $originalDriver, $namespace)
    {
        /*if (\Doctrine\Common\Version::compare('2.3.0') > -1) {
            throw new \Exception('The DMR library requires Doctrine 2.3.0 or higher.');
        }*/

        if ($originalDriver instanceof MappingDriverChain) {
            $driver = new Driver\Chain();
            foreach ($originalDriver->getDrivers() as $nestedNamespace => $nestedDriver) {
                $driver->addDriver(static::getDriver($nestedDriver, $namespace), $nestedNamespace);
            }

            if ($originalDriver->getDefaultDriver() !== null) {
                $driver->setDefaultDriver(static::getDriver($originalDriver->getDefaultDriver(), $namespace));
            }

            return $driver;
        }

        preg_match('/(?P<type>Xml|Yaml|Annotation)Driver$/', get_class($originalDriver), $m);
        $type = isset($m['type']) ? $m['type'] : null;
        $driverClass = sprintf('%s\Mapping\Driver\%s', $namespace, $type);

        // Fallback driver
        if (!$type || !class_exists($driverClass)) {
            $driverClass = sprintf('%s\Mapping\Driver\Annotation', $namespace);

            if (!class_exists($driverClass)) {
                throw new \RuntimeException(sprintf('Failed to fallback to annotation driver: (%s), extension driver was not found.', $driverClass));
            }
        }

        $driver = new $driverClass();
        $driver->setOriginalDriver($originalDriver);

        if ($driver instanceof Driver\File) {
            $driver->setLocator($originalDriver->getLocator());
        } elseif ($driver instanceof AnnotationDriverInterface) {
            $reader = static::getAnnotationReader();
            $driver->setAnnotationReader($reader);
        }

        return $driver;
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Events;

use Symfony\Component\EventDispatcher\EventDispatcher as SymfonyEventDispatcher;

/**
 * Event dispatcher.
 *
 * Override Symfony's class to have access to resolving classes from the
 * container as event listeners.
 */
class EventDispatcher extends SymfonyEventDispatcher
{
	/**
	 * @var \Autarky\Events\ListenerResolver
	 */
	protected $resolver;

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

	/**
	 * {@inheritdoc}
	 *
	 * The listener can be a string of 'Class:method' or just 'Class'. If no
	 * method is provided, the method 'handle' is used.
	 */
	public function addListener($name, $listener, $priority = 0)
	{
		if (is_string($listener) && !is_callable($listener)) {
			$listener = [$listener, 'handle'];
		}

		if (is_array($listener) && is_string($listener[0])) {
			list($class, $method) = $listener;
			$listener = function($event) use($class, $method) {
				return $this->resolver->resolve($class)
					->$method($event);
			};
		}

		parent::addListener($name, $listener, $priority);
	}
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Config\Loaders;

use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Exception\ParseException;

use Autarky\Config\LoadException;
use Autarky\Config\LoaderInterface;
use Autarky\Files\LockingFilesystem;

/**
 * YAML/YML config file loader.
 */
class YamlFileLoader implements LoaderInterface
{
	/**
	 * The symfony YAML parser instance.
	 *
	 * @var Parser
	 */
	protected $parser;

	/**
	 * The filesystem instance.
	 *
	 * @var LockingFilesystem
	 */
	protected $filesys;

	/**
	 * @param Parser $parser
	 */
	public function __construct(Parser $parser)
	{
		$this->parser = $parser;
		$this->filesys = new LockingFilesystem;
	}

	/**
	 * {@inheritdoc}
	 */
	public function load($path)
	{
		$yaml = $this->filesys->read($path);

		try {
			return $this->parser->parse($yaml);
		} catch (ParseException $e) {
			throw new LoadException($e->getMessage(), $e->getCode(), $e);
		}
	}
}


<?php

/**
 * This file is part of the Pathfinder package.
 *
 * (c) bitExpert AG
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare(strict_types = 1);

namespace bitExpert\Pathfinder;

use Psr\Http\Message\ServerRequestInterface;

/**
 * Implementation of an {@link \bitExpert\Pathfinder\Router\Router} which will map
 * the current request path to a configured target.
 *
 * @api
 */
class Psr7Router extends AbstractRouter
{
    /**
     * {@inheritdoc}
     */
    public function match(ServerRequestInterface $request) : RoutingResult
    {
        $requestPath = $request->getUri()->getPath();

        $this->logger->debug(sprintf('Analysing request path "%s"', $requestPath));

        $candidates = [];

        /** @var array $routeDefinition */
        foreach ($this->routes as $routeDefinition) {
            $route = $routeDefinition['route'];
            $identifier = $this->getRouteIdentifier($route);

            $this->logger->debug(sprintf('Trying to match requested path to route "%s"', $identifier));

            $urlVars = [];

            if (preg_match_all($routeDefinition['pathMatcher'], $requestPath, $urlVars)) {
                $method = strtoupper(trim($request->getMethod()));
                if (!in_array($method, $route->getMethods())) {
                    $candidates[] = [
                        'route' => $route,
                        'failure' => RoutingResult::FAILED_METHOD_NOT_ALLOWED
                    ];
                    continue;
                }

                // remove all elements which should not be set in the request,
                // e.g. the matching url string as well as all numeric items
                $params = $this->mapParams($urlVars);

                if (!$this->matchParams($route, $params)) {
                    $candidates[] = [
                        'route' => $route,
                        'failure' => RoutingResult::FAILED_BAD_REQUEST
                    ];

                    continue;
                }

                $this->logger->debug(
                    sprintf(
                        'Route "%s" matches. Applying its target...',
                        $identifier
                    )
                );

                return RoutingResult::forSuccess($route, $params);
            }
        }

        $this->logger->debug('No matching route found.');

        if (count($candidates)) {
            $candidate = $candidates[0];
            return RoutingResult::forFailure($candidate['failure'], $candidate['route']);
        }

        return RoutingResult::forFailure(RoutingResult::FAILED_NOT_FOUND);
    }

    /**
     * {@inheritdoc}
     */
    public function generateUri($routeIdentifier, array $params = []) : string
    {
        if (empty($routeIdentifier)) {
            throw new \InvalidArgumentException(
                'Please provide a route identifier, otherwise a link cannot be created!'
            );
        }

        // try to find path for given $target
        $determinedRouteDefinition = null;
        /** @var array $routeDefinition */
        foreach ($this->routes as $routeDefinition) {
            $route = $routeDefinition['route'];

            $identifier = $this->getRouteIdentifier($route);
            if ($routeIdentifier === $identifier) {
                $determinedRouteDefinition = $routeDefinition;
                break;
            }
        }

        // when no path for the given $target can be found,
        // stop processing...
        if (null === $determinedRouteDefinition) {
            throw new \InvalidArgumentException(sprintf('No route found for identifier "%s"', $routeIdentifier));
        }

        $pathMatcher = $determinedRouteDefinition['pathMatcher'];
        $route = $determinedRouteDefinition['route'];

        $detectedParams = [];

        preg_match_all($pathMatcher, $route->getPath(), $detectedParams);

        $this->validateParams($route, $params, array_keys($this->mapParams($detectedParams)));
        $link = $route->getPath();

        foreach ($params as $name => $value) {
            $link = str_replace('[:' . $name . ']', urlencode((string) $value), $link);
        }

        return $link;
    }

    /**
     * Maps resulting params of a regex match to name=>value array.
     *
     * @param array $params
     * @return array
     */
    protected function mapParams(array $params) : array
    {
        unset($params[0]);
        foreach ($params as $name => $value) {
            if (!is_string($name)) {
                unset($params[$name]);
            } else {
                $params[$name] = urldecode($value[0]);
            }
        }

        return $params;
    }

    /**
     * {@inheritdoc}
     */
    protected function getPathMatcherForRoute(Route $route) : string
    {
        $pathMatcher = preg_replace('#\[:(.+?)\]#i', '(?P<$1>[^/]+?)/?', $route->getPath());
        return sprintf('#^%s$#i', $pathMatcher);
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Database;

use InvalidArgumentException;
use PDO;
use PDOException;

/**
 * Connection factory.
 *
 * @internal
 */
class ConnectionFactory implements ConnectionFactoryInterface
{
	/**
	 * PDO instantiator instance.
	 *
	 * @var PDOInstantiator
	 */
	protected $instantiator;

	/**
	 * The default PDO options.
	 *
	 * @var array
	 */
	protected $defaultPdoOptions = [
		PDO::ATTR_CASE               => PDO::CASE_NATURAL,
		PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
		PDO::ATTR_EMULATE_PREPARES   => false,
		PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
		PDO::ATTR_ORACLE_NULLS       => PDO::NULL_NATURAL,
		PDO::ATTR_STRINGIFY_FETCHES  => false,
	];

	/**
	 * Constructor.
	 *
	 * @param PDOInstantiator|null $instantiator
	 */
	public function __construct(PDOInstantiator $instantiator = null)
	{
		$this->instantiator = $instantiator ?: new PDOInstantiator;
	}

	/**
	 * Create a new PDO instance.
	 *
	 * @param  array  $config
	 * @param  string $connection Name of the connection - used for exception
	 * messages
	 *
	 * @return PDO
	 *
	 * @throws InvalidArgumentException If connection is incorrectly configured
	 * @throws CannotConnectException If construction of PDO object fails
	 */
	public function makePdo(array $config, $connection = null)
	{
		if (!isset($config['driver']) && !isset($config['dsn'])) {
			throw new InvalidArgumentException('DSN or driver must be set');
		}

		$options = isset($config['pdo_options']) ? $config['pdo_options'] : [];
		unset($config['pdo_options']);
		$options = array_replace($this->defaultPdoOptions, $options);

		$initCommands = isset($config['pdo_init_commands'])
			? $config['pdo_init_commands'] : [];
		unset($config['pdo_init_commands']);

		// SQLite needs special treatment
		if (isset($config['driver']) && $config['driver'] == 'sqlite') {
			$this->validate($config, 'path', $connection);
			$dsn = $this->makeSqliteDsn($config['path']);
			return $this->makePdoInner($dsn, null, null, $options, $initCommands);
		} elseif (isset($config['dsn']) && strpos($config['dsn'], 'sqlite:') === 0) {
			return $this->makePdoInner($config['dsn'], null, null,
				$options, $initCommands);
		}

		$this->validate($config, 'username', $connection, false);
		$username = $config['username'];
		unset($config['username']);

		$this->validate($config, 'password', $connection, true);
		$password = $config['password'];
		unset($config['password']);

		if (isset($config['dsn'])) {
			$dsn = $config['dsn'];
		} else {
			$driver = $config['driver'];
			unset($config['driver']);
			$this->validate($config, 'host', $connection);
			$this->validate($config, 'dbname', $connection);
			$dsn = $this->makeDsn($driver, $config);
		}

		return $this->makePdoInner($dsn, $username, $password, $options, $initCommands);
	}

	protected function makePdoInner($dsn, $username, $password, array $options, array $initCommands)
	{
		try {
			$pdo = $this->instantiator->instantiate(
				$dsn, $username, $password, $options);
		} catch (PDOException $e) {
			$newException = new CannotConnectException(
				$e->getMessage(), $e->getCode(), $e);
			$newException->errorInfo = $e->errorInfo;
			throw $newException;
		}

		foreach ($initCommands as $command) {
			$pdo->exec($command);
		}

		return $pdo;
	}

	protected function makeSqliteDsn($path)
	{
		return "sqlite:$path";
	}

	protected function makeDsn($driver, array $values)
	{
		$valuestrings = [];

		foreach ($values as $key => $value) {
			$valuestrings[] = $key.'='.$value;
		}

		return $driver.':'.implode(';', $valuestrings);
	}

	protected function validate(array &$config, $key, $connection, $allowEmpty = false)
	{
		if (!array_key_exists($key, $config) || (!$allowEmpty && !$config[$key])) {
			throw new InvalidArgumentException("Missing $key for connection: $connection");
		}
	}
}


<?php

/**
 * This file is part of the Pathfinder package.
 *
 * (c) bitExpert AG
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare(strict_types = 1);

namespace bitExpert\Pathfinder;

/**
 * This class wraps route creation in order to offer a convenient readable way for defining a route
 * without allowing the route to be in an inconsistent state.
 */
class RouteBuilder
{
    /**
     * @var string
     */
    protected static $defaultRouteClass = Route::class;
    /**
     * @var string
     */
    protected $routeClass;
    /**
     * @var string[]
     */
    protected $methods;
    /**
     * @var string
     */
    protected $path;
    /**
     * @var string
     */
    protected $target;
    /**
     * @var callable[]
     */
    protected $matchers;
    /**
     * @var string
     */
    protected $name;

    /**
     * RouteBuilder constructor.
     *
     * @param string $routeClass The route class to build the route from
     * @throws \InvalidArgumentException
     */
    protected function __construct($routeClass)
    {
        if (!is_a($routeClass, Route::class, true)) {
            throw new \InvalidArgumentException(sprintf(
                'The configured route class "%s" is not of or does not inherit class "%s"',
                $routeClass,
                Route::class
            ));
        }

        $this->routeClass = $routeClass;

        $this->path = null;
        $this->target = null;
        $this->name = null;
        $this->methods = [];
        $this->matchers = [];
    }

    /**
     * Sets the route class to build the route from globally.
     *
     * @param string $defaultRouteClass
     */
    public static function setDefaultRouteClass($defaultRouteClass = Route::class)
    {
        self::$defaultRouteClass = $defaultRouteClass;
    }

    /**
     * Creates a new {@link bitExpert\Pathfinder\RouteBuilder} instance using the given
     * $routeClass to create a new route from.
     *
     * @param string|null $routeClass
     * @return RouteBuilder
     */
    public static function route(string $routeClass = null) : RouteBuilder
    {
        $routeClass = $routeClass ? $routeClass : self::$defaultRouteClass;

        return new static($routeClass);
    }

    /**
     * Builds a route using the provided configuration.
     *
     * @return Route
     */
    public function build() : Route
    {
        return new $this->routeClass($this->methods, $this->path, $this->target, $this->matchers, $this->name);
    }

    /**
     * Creates a new HEAD accepting route.
     *
     * @param string $path
     * @return RouteBuilder
     */
    public function head(string $path) : RouteBuilder
    {
        return $this->from($path)->accepting('HEAD');
    }

    /**
     * Creates a new GET accepting route.
     *
     * @param string $path
     * @return RouteBuilder
     */
    public function get(string $path) : RouteBuilder
    {
        return $this->from($path)->accepting('GET');
    }

    /**
     * Creates a new POST accepting route.
     *
     * @param string $path
     * @return RouteBuilder
     */
    public function post(string $path) : RouteBuilder
    {
        return $this->from($path)->accepting('POST');
    }

    /**
     * Creates a new PUT accepting route.
     *
     * @param string $path
     * @return RouteBuilder
     */
    public function put(string $path) : RouteBuilder
    {
        return $this->from($path)->accepting('PUT');
    }

    /**
     * Creates a new DELETE accepting route.
     *
     * @param string $path
     * @return RouteBuilder
     */
    public function delete(string $path) : RouteBuilder
    {
        return $this->from($path)->accepting('DELETE');
    }

    /**
     * Creates a new OPTIONS accepting route.
     *
     * @param string $path
     * @return RouteBuilder
     */
    public function options(string $path) : RouteBuilder
    {
        return $this->from($path)->accepting('OPTIONS');
    }

    /**
     * Creates a new PATCH accepting route.
     *
     * @param string $path
     * @return RouteBuilder
     */
    public function patch(string $path) : RouteBuilder
    {
        return $this->from($path)->accepting('PATCH');
    }

    /**
     * Sets the method(s) which the route should accept.
     *
     * @param string $method The HTTP method(s) the route should handle
     * @return RouteBuilder
     */
    public function accepting(string $method) : RouteBuilder
    {
        $method = strtoupper($method);
        $this->methods = array_unique(array_merge($this->methods, [$method]));

        return $this;
    }

    /**
     * Removes given method(s) from the set of methods the
     * route should handle.
     *
     * @param string $method The HTTP method(s) the route should no longer handle
     * @return RouteBuilder
     */
    public function refusing(string $method) : RouteBuilder
    {
        $method = strtoupper($method);
        $this->methods = array_diff($this->methods, [$method]);

        return $this;
    }

    /**
     * Sets matcher(s) which the given param should match
     * for the route to be active.
     *
     * @param string $param The param name to set the matcher(s) for
     * @param callable $matcher The matcher or array of matchers for the param
     * @return RouteBuilder
     * @throws \InvalidArgumentException
     */
    public function ifMatches(string $param, callable $matcher) : RouteBuilder
    {
        if (!array_key_exists($param, $this->matchers)) {
            $this->matchers[$param] = [];
        }

        $this->matchers[$param][] = $matcher;

        return $this;
    }

    /**
     * Returns a route having removed all formerly set matchers
     * for the param with given name.
     *
     * @param string $param The name of the param all matchers should be removed for
     * @return RouteBuilder
     */
    public function whateverMatches(string $param) : RouteBuilder
    {
        if (array_key_exists($param, $this->matchers)) {
            unset($this->matchers[$param]);
        }

        return $this;
    }

    /**
     * Returns the route with a new source configuration.
     *
     * @param string $path The new path
     * @return RouteBuilder
     */
    public function from(string $path) : RouteBuilder
    {
        $this->path = $path;
        return $this;
    }

    /**
     * Returns the route with a new target.
     *
     * @param mixed $target The new target
     * @return RouteBuilder
     */
    public function to($target) : RouteBuilder
    {
        $this->target = $target;
        return $this;
    }

    /**
     * Returns a new instance of the route carrying the given name.
     *
     * @param string $name
     * @return RouteBuilder
     */
    public function named(string $name) : RouteBuilder
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Returns a new instance of the route having the name unset.
     *
     * @return RouteBuilder
     */
    public function noName() : RouteBuilder
    {
        $this->name = null;
        return $this;
    }
}


<?php

/**
 * This file is part of the Pathfinder package.
 *
 * (c) bitExpert AG
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare(strict_types = 1);

namespace bitExpert\Pathfinder\Matcher;

/**
 * Matcher which matches against a set of constants defined by class and pattern
 */
class ConstantSetMatcher extends ValueSetMatcher
{
    /**
     * Creates a new {@link \bitExpert\Pathfinder\Matcher\ConstantSetMatcher}.
     *
     * @param mixed $classIdentifier Class or object to get the constants from
     * @param string $pattern A simplified expression using * as placeholder
     */
    public function __construct($classIdentifier, string $pattern)
    {
        $regex = $this->transformPatternToRegEx($pattern);
        $values = $this->getConstantValues($classIdentifier, $regex);

        parent::__construct($values);
    }

    /**
     * Returns the constant values of the given class when its name matches
     * the given regex.
     *
     * @param string $classIdentifier
     * @param string $regex
     * @return array
     */
    protected function getConstantValues(string $classIdentifier, string $regex) : array
    {
        $reflectionClass = new \ReflectionClass($classIdentifier);
        $constants = $reflectionClass->getConstants();

        $validValues = array_filter($constants, function ($constantName) use ($regex) {
            return preg_match($regex, $constantName);
        }, ARRAY_FILTER_USE_KEY);

        return $validValues;
    }

    /**
     * Transforms a simplified pattern (* for multiple characters ? for one)
     * to a regular expression.
     *
     * @param string $pattern
     * @return string
     */
    protected function transformPatternToRegEx(string $pattern) : string
    {
        $pattern = str_replace('*', '.*', $pattern);
        $pattern = str_replace('?', '.', $pattern);
        return '/^' . $pattern . '$/';
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Config\Loaders;

use Symfony\Component\Yaml\Parser;

/**
 * Caching wrapper for the YAML/YML config file loader.
 */
class CachingYamlFileLoader extends YamlFileLoader
{
	/**
	 * The directory in which to look for cached files.
	 *
	 * @var string
	 */
	protected $cacheDir;

	/**
	 * Whether or not to check if cache files are outdated.
	 *
	 * @var bool
	 */
	protected $stat;

	/**
	 * Constructor.
	 *
	 * @param Parser $parser
	 * @param string $cacheDir
	 * @param bool   $stat
	 */
	public function __construct(Parser $parser, $cacheDir, $stat = true)
	{
		parent::__construct($parser);
		$this->cacheDir = $cacheDir;
		$this->stat = (bool) $stat;
	}

	/**
	 * {@inheritdoc}
	 */
	public function load($path)
	{
		$cachePath = $this->cacheDir.'/'.md5($path);

		if ($this->shouldLoadCache($path, $cachePath)) {
			return require $cachePath;
		}

		$data = parent::load($path);

		$this->filesys->write($cachePath, '<?php return '.var_export($data, true).";\n");

		return $data;
	}

	protected function shouldLoadCache($path, $cachePath)
	{
		if (!file_exists($cachePath)) {
			return false;
		}

		if (!$this->stat) {
			return true;
		}

		// if the cache file is more recent than the real file,
		// the cache file should be loaded
		return filemtime($cachePath) > filemtime($path);
	}
}


<?php

namespace DMR\Mapping\Driver;

use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
use Doctrine\Common\Persistence\Mapping\Driver\FileLocator;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;

/**
 * The mapping FileDriver abstract class, defines the metadata
 * extraction function common among all drivers used on these
 * extensions by file based drivers.
 *
 * @author Marcos Passos <marcos@marcospassos.com>
 */
abstract class File implements DriverInterface
{
    /**
     * @var FileLocator
     */
    protected $locator;

    /**
     * @var MappingDriver|null
     */
    protected $originalDriver;

    /**
     * Loads a mapping file with the given name and returns a map
     * from class/entity names to their corresponding elements.
     *
     * @param string $file The mapping file to load.
     *
     * @return array
     */
    abstract protected function loadMappingFile($file);

    /**
     * {@inheritDoc}
     */
    public function getOriginalDriver()
    {
        return $this->originalDriver;
    }

    /**
     * {@inheritDoc}
     */
    public function setOriginalDriver(MappingDriver $driver)
    {
        $this->originalDriver = $driver;
    }

    /**
     * Gets the file locator.
     *
     * @return FileLocator
     */
    public function getLocator()
    {
        return $this->locator;
    }

    /**
     * Sets the file locator.
     *
     * @param FileLocator $locator
     */
    public function setLocator(FileLocator $locator)
    {
        $this->locator = $locator;
    }

    /**
     * Tries to get a mapping for a given class
     *
     * @param string $className
     *
     * @return null|array|object
     */
    public function getMapping($className)
    {
        // Try loading mapping from original driver first
        $mapping = null;
        if (null != $this->originalDriver) {
            if ($this->originalDriver instanceof FileDriver) {
                $mapping = $this->originalDriver->getElement($className);
            }
        }

        // If no mapping found try to load mapping file again
        if (null == $mapping) {
            $mappings = $this->loadMappingFile($this->locator->findMappingFile($className));
            $mapping = $mappings[$className];
        }

        return $mapping;
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Config;

use Autarky\Utils\ArrayUtil;
use Autarky\Files\PathResolver;

/**
 * File-based config implementation.
 *
 * Reads files from one or multiple directories, with the possibility of
 * cascading for different environments and overriding of namespaces.
 */
class FileStore implements ConfigInterface
{
	/**
	 * The path resolver instance.
	 *
	 * @var PathResolver
	 */
	protected $pathResolver;

	/**
	 * The loader factory instance.
	 *
	 * @var LoaderFactory
	 */
	protected $loaderFactory;

	/**
	 * The current environment.
	 *
	 * @var string
	 */
	protected $environment;

	/**
	 * The loaded config data.
	 *
	 * @var array
	 */
	protected $data = [];

	/**
	 * Constructor.
	 *
	 * @param PathResolver  $pathResolver
	 * @param LoaderFactory $loaderFactory
	 * @param string|null   $environment
	 */
	public function __construct(
		PathResolver $pathResolver,
		LoaderFactory $loaderFactory,
		$environment = null
	) {
		$this->pathResolver = $pathResolver;
		$this->loaderFactory = $loaderFactory;
		$this->environment = $environment;
	}

	/**
	 * Get the loader factory instance.
	 *
	 * @return LoaderFactory
	 */
	public function getLoaderFactory()
	{
		return $this->loaderFactory;
	}

	/**
	 * {@inheritdoc}
	 */
	public function mount($location, $path)
	{
		$this->pathResolver->mount($location, $path);
	}

	/**
	 * {@inheritdoc}
	 */
	public function setEnvironment($environment)
	{
		$this->environment = $environment;
	}

	/**
	 * {@inheritdoc}
	 */
	public function has($key)
	{
		$this->loadData($key);

		return ArrayUtil::has($this->data, $key);
	}

	/**
	 * {@inheritdoc}
	 */
	public function get($key, $default = null)
	{
		$this->loadData($key);

		return ArrayUtil::get($this->data, $key, $default);
	}

	/**
	 * {@inheritdoc}
	 */
	public function set($key, $value)
	{
		$this->loadData($key);

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

	protected function loadData($key)
	{
		$basename = $this->getBasename($key);

		if (array_key_exists($basename, $this->data)) {
			return;
		}

		$paths = $this->getPaths($basename);

		foreach ($paths as $path) {
			$data = $this->getDataFromFile($path);

			if (isset($this->data[$basename])) {
				$this->data[$basename] = array_replace(
					$this->data[$basename], $data);
			} else {
				$this->data[$basename] = $data;
			}
		}
	}

	protected function getBasename($key)
	{
		return current(explode('.', $key));
	}

	protected function getPaths($basename)
	{
		$basenames = $this->pathResolver->resolve($basename);

		if ($this->environment) {
			$envBasenames = array_map(function($basename) {
				return $basename.'.'.$this->environment;
			}, $basenames);

			$basenames = array_merge($basenames, $envBasenames);
		}

		$extensions = $this->loaderFactory->getExtensions();

		return $this->pathResolver->locate($basenames, $extensions);
	}

	protected function getDataFromFile($path)
	{
		if (!is_readable($path)) {
			throw new LoadException("File is not readable: $path");
		}

		$loader = $this->loaderFactory->getForPath($path);

		return $loader->load($path);
	}
}


<?php

/**
 * Moo_EditableFieldMultipleOption is a base class for multiple option fields to extend.
 *
 * @see     Moo_EditableFieldCheckboxGroup, Moo_EditableFieldDropdown
 *
 * @package editablefield
 *
 * @author  Mohamed Alsharaf <mohamed.alsharaf@gmail.com>
 *
 * @method  HasManyList Options()
 *
 * @property string $Name
 * @property string $Title
 */
class Moo_EditableFieldMultipleOption extends Moo_EditableField
{
    private static $has_many = [
        'Options' => 'Moo_EditableFieldOption',
    ];

    /**
     * Deletes all the options attached to this field before deleting the
     * field. Keeps stray options from floating around.
     *
     * @return void
     */
    public function delete()
    {
        $options = $this->Options();

        if ($options) {
            foreach ($options as $option) {
                $option->delete();
            }
        }

        parent::delete();
    }

    /**
     * Duplicate a pages content. We need to make sure all the fields attached
     * to that page go with it.
     *
     * @param bool $doWrite
     *
     * @return DataObject
     */
    public function duplicate($doWrite = true)
    {
        $clonedNode = parent::duplicate($doWrite);

        if ($this->Options()) {
            foreach ($this->Options() as $field) {
                $newField           = $field->duplicate();
                $newField->ParentID = $clonedNode->ID;
                $newField->write();
            }
        }

        return $clonedNode;
    }

    /**
     * Get extra configuration fields.
     *
     * @return array
     */
    public function getFieldConfiguration()
    {
        if (!$this->isInDB()) {
            $field = LiteralField::create('Options', '
Once you save this field you will be able to add options
');
        } else {
            $config = GridFieldConfig_RelationEditor::create()
                ->addComponent(new GridFieldOrderableRows('Sort'));

            $config
                ->getComponentByType('GridFieldDataColumns')
                ->setDisplayFields([
                    'Name'    => 'Name',
                    'Title'   => 'Title',
                    'Default' => 'Default',
                ])
                ->setFieldFormatting([
                    'Default' => function ($_, Moo_EditableFieldOption $option) {
                        return $option->Default ? 'Yes' : 'No';
                    },
                ]);
            $field = GridField::create('Options', 'Options', $this->Options(), $config);
        }

        return [
            $field,
        ];
    }

    /**
     * Return the form field for this object in the front end form view.
     *
     * @return FormField
     */
    protected function initFormField()
    {
        $options = $this->Options()->map('EscapedTitle', 'Title');

        return new OptionsetField($this->Name, $this->Title, $options);
    }
}


<?php

/**
 * Moo_EditableFieldHeading is an object representing generic heading created by CMS admin.
 *
 * @package editablefield
 *
 * @author  Mohamed Alsharaf <mohamed.alsharaf@gmail.com>
 */
class Moo_EditableFieldHeading extends Moo_EditableField
{
    private static $singular_name   = 'Heading';
    private static $plural_name     = 'Headings';

    /**
     * List of allowed custom settings fields.
     *
     * @var array
     */
    protected $customSettingsFields = [
        'Level',
    ];

    public function getCMSFields()
    {
        $fields = parent::getCMSFields();

        // Remove validation tab & fields
        $fields->removeByName(['Root.Validation', 'Required', 'CustomErrorMessage']);

        return $fields;
    }

    /**
     * Get extra configuration fields.
     *
     * @return array
     */
    public function getFieldConfiguration()
    {
        $levels = [
            '1' => '1',
            '2' => '2',
            '3' => '3',
            '4' => '4',
            '5' => '5',
            '6' => '6',
        ];

        $level = ($this->getSetting('Level')) ? $this->getSetting('Level') : 3;
        $label = _t('Moo_EditableFieldHeading.LEVEL', 'Select Heading Level');

        return [
            new DropdownField($this->getSettingName('Level'), $label, $levels, $level),
        ];
    }

    protected function initFormField()
    {
        $labelField = new HeaderField($this->Name, $this->Title, $this->getSetting('Level'));
        $labelField->addExtraClass('FormHeading');

        return $labelField;
    }
}


<?php

namespace DMR\Mapping;

use Doctrine\Common\Persistence\ObjectManager;

/**
 * Metadata factory.
 *
 * @author Marcos Passos <marcos@marcospassos.com>
 */
abstract class AbstractReader implements ReaderInterface
{
	/**
	 * Returns the manager for an object.
	 *
	 * @param string $class
     *
     * @return ObjectManager
	 */
    abstract protected function getManagerForClass($class);

    /**
     * Returns the driver implementation correspondent to
     * current in use natively by Doctrine.
     *
     * @param ObjectManager $manager   The impementation of ObjectManager
     * @param string        $namespace The namespace prefix where the drivers are
     *
     * @return Driver\DriverInterface
     */
    public function getDriverForManager(ObjectManager $manager, $namespace)
    {
    	return DriverFactory::getDriver($manager->getConfiguration()->getMetadataDriverImpl(), $namespace);
    }

    /**
    * {@inheritDoc}
    */
    public function read($object, $namespace)
    {
        $className = is_object($object) ? get_class($object) : $object;
        $manager = $this->getManagerForClass($className);
        $factory = $manager->getMetadataFactory();
        $meta = $factory->getMetadataFor($className);

        if ($meta->isMappedSuperclass) {
            return;
        }

        $cacheDriver = $factory->getCacheDriver();
        $cacheId = static::getCacheId($meta->name, $namespace);

        if ($cacheDriver && ($cached = $cacheDriver->fetch($cacheId)) !== false) {
            return $cached;
        }

        $metadata = array();
        // Collect metadata from inherited classes
        if (null !== $meta->reflClass) {
        	$driver = $this->getDriverForManager($manager, $namespace);

            foreach (array_reverse(class_parents($meta->name)) as $parentClass) {
                // read only inherited mapped classes
                if ($factory->hasMetadataFor($parentClass)) {
                    $class = $manager->getClassMetadata($parentClass);
                    $driver->read($class, $metadata);
                }
            }

            $driver->read($meta, $metadata);
        }

        /* Cache the metadata (even if it's empty). Caching empty
         * metadata will prevent re-parsing non-existent annotations
         */
        if ($cacheDriver) {
            $cacheDriver->save($cacheId, $metadata, null);
        }

        return $metadata;
    }

    /**
     * Gets the cache id.
     *
     * @param string $className The class name
     * @param string $namespace The namespace
     *
     * @return string
     */
    public static function getCacheId($className, $namespace)
    {
        return $className . '\\$' . strtoupper(str_replace('\\', '_', $namespace)) . '_CLASSMETADATA';
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Config;

use Autarky\Container\ClassResolverInterface;

/**
 * Factory for file-based loaders.
 *
 * Keeps an array of extension => class, where the class is lazily resolved out
 * of the framework's service container when needed.
 */
class LoaderFactory
{
	/**
	 * The container instance.
	 *
	 * @var ClassResolverInterface
	 */
	protected $container;

	/**
	 * The loader classes.
	 *
	 * @var string[]
	 */
	protected $loaderClasses = [];

	/**
	 * The loader class instances.
	 *
	 * @var LoaderInterface[]
	 */
	protected $loaders = [];

	/**
	 * The registered extensions.
	 *
	 * @var string[]
	 */
	protected $extensions = [];

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

	/**
	 * Add a loader.
	 *
	 * @param  string $extensions
	 * @param  string|LoaderInterface $loaderClass
	 *
	 * @return void
	 */
	public function addLoader($extensions, $loaderClass)
	{
		foreach ((array) $extensions as $extension) {
			$this->extensions[] = $extension;
			if (is_string($loaderClass)) {
				$this->loaderClasses[$extension] = $loaderClass;
			} elseif ($loaderClass instanceof LoaderInterface) {
				$this->loaders[$extension] = $loaderClass;
			}
		}
	}

	/**
	 * Get the available extensions.
	 *
	 * @return array
	 */
	public function getExtensions()
	{
		return $this->extensions;
	}

	/**
	 * Get the loader for a given path.
	 *
	 * @param  string $path
	 *
	 * @return LoaderInterface
	 */
	public function getForPath($path)
	{
		$extension = $this->getExtension($path);

		if (!isset($this->loaders[$extension])) {
			$this->resolveLoader($extension);
		}

		return $this->loaders[$extension];
	}

	protected function resolveLoader($extension)
	{
		if (!isset($this->loaderClasses[$extension])) {
			throw new LoadException("No loader registered for extension: $extension");
		}

		$this->loaders[$extension] = $this->container
			->resolve($this->loaderClasses[$extension]);
	}

	protected function getExtension($path)
	{
		return substr($path, strrpos($path, '.'));
	}
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Routing;

/**
 * Class representation of a routing config, which can be used instead of
 * manually adding routes onto the Router object.
 */
class Configuration
{
	/**
	 * @var RouterInterface
	 */
	protected $router;

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

	/**
	 * @var string|null
	 */
	protected $namespace;

	/**
	 * @param RouterInterface $router
	 * @param array           $routes
	 * @param string|null     $namespace
	 */
	public function __construct(RouterInterface $router, array $routes, $namespace = null)
	{
		$this->router = $router;
		$this->routes = $routes;

		if ($namespace) {
			$this->namespace = $namespace;
		}
	}

	/**
	 * Override an existing route.
	 *
	 * @param  string $name
	 * @param  array  $routeData
	 *
	 * @return void
	 */
	public function override($name, array $routeData)
	{
		if (!isset($this->routes[$name])) {
			throw new \InvalidArgumentException("No route for name $name defined");
		}

		$this->routes[$name] = $routeData + $this->routes[$name];
	}

	/**
	 * Merge more routes into the configuration.
	 *
	 * @param  array  $routes
	 *
	 * @return void
	 */
	public function merge(array $routes)
	{
		foreach ($routes as $name => $route) {
			$this->override($name, $route);
		}
	}

	/**
	 * Mount the configuration.
	 *
	 * @param  string|null $prefix
	 *
	 * @return void
	 */
	public function mount($prefix = null)
	{
		if ($prefix) {
			$this->router->group(['prefix' => $prefix], function() {
				$this->registerRoutes();
			});
		} else {
			$this->registerRoutes();
		}
	}

	protected function registerRoutes()
	{
		foreach ($this->routes as $name => $route) {
			if ($this->namespace) {
				$name = $this->namespace . ':' . $name;
			}

			$this->registerRoute($route, $name);
		}
	}

	protected function registerRoute($route, $name)
	{
		$path = $route['path'];

		if (isset($route['methods'])) {
			$methods = (array) $route['methods'];
		} elseif (isset($route['method'])) {
			$methods = (array) $route['method'];
		} else {
			$methods = ['GET'];
		}

		$options = [];
		if (isset($route['params'])) {
			$options['params'] = $route['params'];
		}
		if (isset($route['constructor_params'])) {
			$options['constructor_params'] = $route['constructor_params'];
		}

		// it is possible to provide a subarray to 'methods', which means the same
		// route will serve multiple HTTP methods, but with different controllers
		// for each method. if that is the case, iterate through the methods and
		// add the route for each of them.
		if (array_filter(array_keys($methods), 'is_string')) {
			foreach ($methods as $method => $controller) {
				$this->router->addRoute([$method], $path, $controller, $name, $options);

				// only set the name for the first route added. the URLs will be
				// identical so it doesn't matter for URL generation.
				$name = null;
			}
		} else {
			// only a single method is being mapped
			$controller = isset($route['controller']) ?
				$route['controller'] : $route['handler'];
			$this->router->addRoute($methods, $path, $controller, $name, $options);
		}
	}
}


<?php

namespace Singo;

use Pimple\ServiceProviderInterface;
use Singo\Contracts\Module\CliCommandProviderInterface;
use Singo\Contracts\Module\CommandHandlerProviderInterface;
use Singo\Contracts\Module\ModuleInterface;
use Singo\Provider\AnnotationRouting;
use Symfony\Component\Console\Application as CLI;

/**
 * Class ModuleBooter
 * @package Singo
 */
trait ModuleBooter
{
    /**
     * boot module
     */
    protected function bootModule()
    {
        $base_namespace = self::$container["config"]->get("modules/base_namespace");
        $modules = self::$container["config"]->get("modules/modules");

        $controllers = [];

        foreach ($modules as $module)
        {
            $module_namespace = $base_namespace . "\\" . key($module);
            $module_class = $module_namespace . "\\Module";
            $module_object = new $module_class();

            if (! $module_object instanceof ModuleInterface) {
                throw new \InvalidArgumentException(
                    "Module {$module_class} must be instance of ServiceProviderInterface"
                );
            }

            /**
             * register service provider and command handler
             */
            $this
                ->bootModuleServiceProvider($module_object)
                ->bootModuleCommand($module_object)
                ->bootModuleCli($module_object);

            /**
             * replace controller with full namespace
             */
            if (isset($module[key($module)]["controllers"])) {
                $routes = $module[key($module)]["controllers"];
                array_walk($routes, function (&$item) use ($module_namespace) {
                    $item = $module_namespace . "\\Controllers\\" . $item;
                });

                $controllers = array_merge($controllers, $routes);
            }
        }

        /**
         * register annotation controller
         */
        self::$container->register(
            new AnnotationRouting(),
            [
                "annot.cache" => (isset(self::$container["cache.factory"])) ? self::$container["cache.factory"] : null,
                "annot.controllers" => $controllers
            ]
        );
    }

    /**
     * @param ModuleInterface $module
     * @return $this
     */
    protected function bootModuleServiceProvider(ModuleInterface $module)
    {
        if ($module instanceof ServiceProviderInterface) {
            self::$container->register($module);
        }

        return $this;
    }

    /**
     * @param ModuleInterface $module
     * @return $this
     */
    protected function bootModuleCommand(ModuleInterface $module)
    {
        if ($module instanceof CommandHandlerProviderInterface) {
            $module->command(self::$container);
        }

        return $this;
    }

    /**
     * @param ModuleInterface $module
     * @return $this
     */
    protected function bootModuleCli(ModuleInterface $module)
    {
        if ($module instanceof CliCommandProviderInterface && $this instanceof CLI) {
            $module->cli($this, self::$container);
        }

        return $this;
    }
}


<?php
/**
 * This file is part of the Autarky package.
 *
 * (c) Andreas Lutro <anlutro@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Autarky\Console;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * "route:dispatch" command.
 */
class RouteDispatchCommand extends Command
{
	/**
	 * {@inheritdoc}
	 */
	public function configure()
	{
		$this->setName('route:dispatch')
			->setDescription('Given a URL, see what route is matched')
			->addArgument('method', InputArgument::REQUIRED, 'HTTP method')
			->addArgument('path', InputArgument::REQUIRED, 'URL path')
			->setHelp(<<<'EOS'
This command fakes an HTTP request and returns information about the route that was matched against the request. For example:

	php bin/console.php route:dispatch GET /foo/bar/baz

This example will fake a HTTP GET request to the path /foo/bar/baz.
EOS
);
	}

	/**
	 * {@inheritdoc}
	 */
	protected function execute(InputInterface $input, OutputInterface $output)
	{
		/** @var \Autarky\Routing\Router $router */
		$router = $this->app->getContainer()
			->resolve('Autarky\Routing\Router');

		$request = Request::create($input->getArgument('path'), $input->getArgument('method'));
		$route = $router->getRouteForRequest($request);

		$controller = $route->getController();

		if (is_array($controller)) {
			$controller = implode('::', $controller);
		} else if ($controller instanceof \Closure) {
			$controller = 'Closure';
		}

		$output->writeln('<info>Route name:</info> '.$route->getName());
		$output->writeln('<info>Route controller:</info> '.$controller);
		$output->writeln('<info>Route path:</info> '.$route->getPattern());
		$output->writeln('<info>HTTP methods:</info> '.implode('|', $route->getMethods()));

		if ($hooks = $route->getBeforeHooks()) {
			$output->writeln('<info>Before hooks:</info> '.implode(', ', $hooks));
		}
		if ($hooks = $route->getAfterHooks()) {
			$output->writeln('<info>After hooks:</info> '.implode(', ', $hooks));
		}

		return 0;
	}
}


<?php

namespace PhpOffice\PhpSpreadsheet;

use PhpOffice\PhpSpreadsheet\Shared\File;

/**
 * Factory to create readers and writers easily.
 *
 * It is not required to use this class, but it should make it easier to read and write files.
 * Especially for reading files with an unknown format.
 */
abstract class IOFactory
{
    private static $readers = [
        'Xlsx' => Reader\Xlsx::class,
        'Xls' => Reader\Xls::class,
        'Xml' => Reader\Xml::class,
        'Ods' => Reader\Ods::class,
        'Slk' => Reader\Slk::class,
        'Gnumeric' => Reader\Gnumeric::class,
        'Html' => Reader\Html::class,
        'Csv' => Reader\Csv::class,
    ];

    private static $writers = [
        'Xls' => Writer\Xls::class,
        'Xlsx' => Writer\Xlsx::class,
        'Ods' => Writer\Ods::class,
        'Csv' => Writer\Csv::class,
        'Html' => Writer\Html::class,
        'Tcpdf' => Writer\Pdf\Tcpdf::class,
        'Dompdf' => Writer\Pdf\Dompdf::class,
        'Mpdf' => Writer\Pdf\Mpdf::class,
    ];

    /**
     * Create Writer\IWriter.
     *
     * @param Spreadsheet $spreadsheet
     * @param string $writerType Example: Xlsx
     *
     * @throws Writer\Exception
     *
     * @return Writer\IWriter
     */
    public static function createWriter(Spreadsheet $spreadsheet, $writerType)
    {
        if (!isset(self::$writers[$writerType])) {
            throw new Writer\Exception("No writer found for type $writerType");
        }

        // Instantiate writer
        $className = self::$writers[$writerType];
        $writer = new $className($spreadsheet);

        return $writer;
    }

    /**
     * Create Reader\IReader.
     *
     * @param string $readerType Example: Xlsx
     *
     * @throws Reader\Exception
     *
     * @return Reader\IReader
     */
    public static function createReader($readerType)
    {
        if (!isset(self::$readers[$readerType])) {
            throw new Reader\Exception("No reader found for type $readerType");
        }

        // Instantiate reader
        $className = self::$readers[$readerType];
        $reader = new $className();

        return $reader;
    }

    /**
     * Loads Spreadsheet from file using automatic Reader\IReader resolution.
     *
     * @param string $pFilename The name of the spreadsheet file
     *
     * @throws Reader\Exception
     *
     * @return Spreadsheet
     */
    public static function load($pFilename)
    {
        $reader = self::createReaderForFile($pFilename);

        return $reader->load($pFilename);
    }

    /**
     * Identify file type using automatic Reader\IReader resolution.
     *
     * @param string $pFilename The name of the spreadsheet file to identify
     *
     * @throws Reader\Exception
     *
     * @return string
     */
    public static function identify($pFilename)
    {
        $reader = self::createReaderForFile($pFilename);
        $className = get_class($reader);
        $classType = explode('\\', $className);
        unset($reader);

        return array_pop($classType);
    }

    /**
     * Create Reader\IReader for file using automatic Reader\IReader resolution.
     *
     * @param string $filename The name of the spreadsheet file
     *
     * @throws Reader\Exception
     *
     * @return Reader\IReader
     */
    public static function createReaderForFile($filename)
    {
        File::assertFile($filename);

        // First, lucky guess by inspecting file extension
        $guessedReader = self::getReaderTypeFromExtension($filename);
        if ($guessedReader !== null) {
            $reader = self::createReader($guessedReader);

            // Let's see if we are lucky
            if (isset($reader) && $reader->canRead($filename)) {
                return $reader;
            }
        }

        // If we reach here then "lucky guess" didn't give any result
        // Try walking through all the options in self::$autoResolveClasses
        foreach (self::$readers as $type => $class) {
            //    Ignore our original guess, we know that won't work
            if ($type !== $guessedReader) {
                $reader = self::createReader($type);
                if ($reader->canRead($filename)) {
                    return $reader;
                }
            }
        }

        throw new Reader\Exception('Unable to identify a reader for this file');
    }

    /**
     * Guess a reader type from the file extension, if any.
     *
     * @param string $filename
     *
     * @return null|string
     */
    private static function getReaderTypeFromExtension($filename)
    {
        $pathinfo = pathinfo($filename);
        if (!isset($pathinfo['extension'])) {
            return null;
        }

        switch (strtolower($pathinfo['extension'])) {
            case 'xlsx': // Excel (OfficeOpenXML) Spreadsheet
            case 'xlsm': // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded)
            case 'xltx': // Excel (OfficeOpenXML) Template
            case 'xltm': // Excel (OfficeOpenXML) Macro Template (macros will be discarded)
                return 'Xlsx';
            case 'xls': // Excel (BIFF) Spreadsheet
            case 'xlt': // Excel (BIFF) Template
                return 'Xls';
            case 'ods': // Open/Libre Offic Calc
            case 'ots': // Open/Libre Offic Calc Template
                return 'Ods';
            case 'slk':
                return 'Slk';
            case 'xml': // Excel 2003 SpreadSheetML
                return 'Xml';
            case 'gnumeric':
                return 'Gnumeric';
            case 'htm':
            case 'html':
                return 'Html';
            case 'csv':
                // Do nothing
                // We must not try to use CSV reader since it loads
                // all files including Excel files etc.
                return null;
            default:
                return null;
        }
    }

    /**
     * Register a writer with its type and class name.
     *
     * @param string $writerType
     * @param string $writerClass
     */
    public static function registerWriter($writerType, $writerClass)
    {
        if (!is_a($writerClass, Writer\IWriter::class, true)) {
            throw new Writer\Exception('Registered writers must implement ' . Writer\IWriter::class);
        }

        self::$writers[$writerType] = $writerClass;
    }

    /**
     * Register a reader with its type and class name.
     *
     * @param string $readerType
     * @param string $readerClass
     */
    public static function registerReader($readerType, $readerClass)
    {
        if (!is_a($readerClass, Reader\IReader::class, true)) {
            throw new Reader\Exception('Registered readers must implement ' . Reader\IReader::class);
        }

        self::$readers[$readerType] = $readerClass;
    }
}


<?php

namespace PhpOffice\PhpSpreadsheet\Worksheet;

use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;

class RowIterator implements \Iterator
{
    /**
     * Worksheet to iterate.
     *
     * @var Worksheet
     */
    private $subject;

    /**
     * Current iterator position.
     *
     * @var int
     */
    private $position = 1;

    /**
     * Start position.
     *
     * @var int
     */
    private $startRow = 1;

    /**
     * End position.
     *
     * @var int
     */
    private $endRow = 1;

    /**
     * Create a new row iterator.
     *
     * @param Worksheet $subject The worksheet to iterate over
     * @param int $startRow The row number at which to start iterating
     * @param int $endRow Optionally, the row number at which to stop iterating
     */
    public function __construct(Worksheet $subject, $startRow = 1, $endRow = null)
    {
        // Set subject
        $this->subject = $subject;
        $this->resetEnd($endRow);
        $this->resetStart($startRow);
    }

    /**
     * Destructor.
     */
    public function __destruct()
    {
        unset($this->subject);
    }

    /**
     * (Re)Set the start row and the current row pointer.
     *
     * @param int $startRow The row number at which to start iterating
     *
     * @throws PhpSpreadsheetException
     *
     * @return RowIterator
     */
    public function resetStart($startRow = 1)
    {
        if ($startRow > $this->subject->getHighestRow()) {
            throw new PhpSpreadsheetException("Start row ({$startRow}) is beyond highest row ({$this->subject->getHighestRow()})");
        }

        $this->startRow = $startRow;
        if ($this->endRow < $this->startRow) {
            $this->endRow = $this->startRow;
        }
        $this->seek($startRow);

        return $this;
    }

    /**
     * (Re)Set the end row.
     *
     * @param int $endRow The row number at which to stop iterating
     *
     * @return RowIterator
     */
    public function resetEnd($endRow = null)
    {
        $this->endRow = ($endRow) ? $endRow : $this->subject->getHighestRow();

        return $this;
    }

    /**
     * Set the row pointer to the selected row.
     *
     * @param int $row The row number to set the current pointer at
     *
     * @throws PhpSpreadsheetException
     *
     * @return RowIterator
     */
    public function seek($row = 1)
    {
        if (($row < $this->startRow) || ($row > $this->endRow)) {
            throw new PhpSpreadsheetException("Row $row is out of range ({$this->startRow} - {$this->endRow})");
        }
        $this->position = $row;

        return $this;
    }

    /**
     * Rewind the iterator to the starting row.
     */
    public function rewind()
    {
        $this->position = $this->startRow;
    }

    /**
     * Return the current row in this worksheet.
     *
     * @return Row
     */
    public function current()
    {
        return new Row($this->subject, $this->position);
    }

    /**
     * Return the current iterator key.
     *
     * @return int
     */
    public function key()
    {
        return $this->position;
    }

    /**
     * Set the iterator to its next value.
     */
    public function next()
    {
        ++$this->position;
    }

    /**
     * Set the iterator to its previous value.
     *
     * @throws PhpSpreadsheetException
     */
    public function prev()
    {
        if ($this->position <= $this->startRow) {
            throw new PhpSpreadsheetException("Row is already at the beginning of range ({$this->startRow} - {$this->endRow})");
        }

        --$this->position;
    }

    /**
     * Indicate if more rows exist in the worksheet range of rows that we're iterating.
     *
     * @return bool
     */
    public function valid()
    {
        return $this->position <= $this->endRow;
    }
}