Commit 458bb244 authored by Dries's avatar Dries

- Patch #1497182 by Crell, BTMash: Update to latest Symfony 2.1 code. This is...

- Patch #1497182 by Crell, BTMash: Update to latest Symfony 2.1 code. This is commit c4dfe931f1ce8827f8c02975bc0ab405bdc8d27c out of Symfony.
parent c16a978c
......@@ -55,7 +55,7 @@ static public function load($classes, $cacheDir, $name, $autoReload, $adaptive =
$reload = false;
if ($autoReload) {
$metadata = $cacheDir.'/'.$name.$extension.'.meta';
if (!file_exists($metadata) || !file_exists($cache)) {
if (!is_file($metadata) || !is_file($cache)) {
$reload = true;
} else {
$time = filemtime($cache);
......@@ -65,7 +65,7 @@ static public function load($classes, $cacheDir, $name, $autoReload, $adaptive =
$reload = true;
} else {
foreach ($meta[0] as $resource) {
if (!file_exists($resource) || filemtime($resource) > $time) {
if (!is_file($resource) || filemtime($resource) > $time) {
$reload = true;
break;
......@@ -75,7 +75,7 @@ static public function load($classes, $cacheDir, $name, $autoReload, $adaptive =
}
}
if (!$reload && file_exists($cache)) {
if (!$reload && is_file($cache)) {
require_once $cache;
return;
......
......@@ -38,6 +38,7 @@ static public function enable()
$loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks());
$loader->registerNamespaces($function[0]->getNamespaces());
$loader->registerPrefixes($function[0]->getPrefixes());
$loader->useIncludePath($function[0]->getUseIncludePath());
$function[0] = $loader;
}
......
Copyright (c) 2004-2011 Fabien Potencier
Copyright (c) 2004-2012 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -41,6 +41,10 @@
* 'Swift_' => __DIR__.'/Swift',
* ));
*
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->useIncludePath(true);
*
* // activate the autoloader
* $loader->register();
*
......@@ -60,6 +64,29 @@ class UniversalClassLoader
private $prefixes = array();
private $namespaceFallbacks = array();
private $prefixFallbacks = array();
private $useIncludePath = false;
/**
* Turns on searching the include for class files. Allows easy loading
* of installed PEAR packages
*
* @param Boolean $useIncludePath
*/
public function useIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return Boolean
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Gets the configured namespaces.
......@@ -114,7 +141,17 @@ public function registerNamespaceFallbacks(array $dirs)
}
/**
* Registers the directory to use as a fallback for class prefixes.
* Registers a directory to use as a fallback for namespaces.
*
* @param string $dir A directory
*/
public function registerNamespaceFallback($dir)
{
$this->namespaceFallbacks[] = $dir;
}
/**
* Registers directories to use as a fallback for class prefixes.
*
* @param array $dirs An array of directories
*
......@@ -125,6 +162,16 @@ public function registerPrefixFallbacks(array $dirs)
$this->prefixFallbacks = $dirs;
}
/**
* Registers a directory to use as a fallback for class prefixes.
*
* @param string $dir A directory
*/
public function registerPrefixFallback($dir)
{
$this->prefixFallbacks[] = $dir;
}
/**
* Registers an array of namespaces
*
......@@ -219,47 +266,54 @@ public function findFile($class)
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$namespace = substr($class, 0, $pos);
$className = substr($class, $pos + 1);
$normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
foreach ($this->namespaces as $ns => $dirs) {
if (0 !== strpos($namespace, $ns)) {
continue;
}
foreach ($dirs as $dir) {
$className = substr($class, $pos + 1);
$file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
if (file_exists($file)) {
$file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
if (is_file($file)) {
return $file;
}
}
}
foreach ($this->namespaceFallbacks as $dir) {
$file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file)) {
$file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
if (is_file($file)) {
return $file;
}
}
} else {
// PEAR-like class name
$normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
foreach ($this->prefixes as $prefix => $dirs) {
if (0 !== strpos($class, $prefix)) {
continue;
}
foreach ($dirs as $dir) {
$file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file)) {
$file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
if (is_file($file)) {
return $file;
}
}
}
foreach ($this->prefixFallbacks as $dir) {
$file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file)) {
$file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
if (is_file($file)) {
return $file;
}
}
}
if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) {
return $file;
}
}
}
......@@ -21,5 +21,10 @@
"autoload": {
"psr-0": { "Symfony\\Component\\ClassLoader": "" }
},
"target-dir": "Symfony/Component/ClassLoader"
"target-dir": "Symfony/Component/ClassLoader",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
}
}
......@@ -39,10 +39,6 @@ class EventDispatcher implements EventDispatcherInterface
*/
public function dispatch($eventName, Event $event = null)
{
if (!isset($this->listeners[$eventName])) {
return;
}
if (null === $event) {
$event = new Event();
}
......@@ -50,7 +46,13 @@ public function dispatch($eventName, Event $event = null)
$event->setDispatcher($this);
$event->setName($eventName);
if (!isset($this->listeners[$eventName])) {
return $event;
}
$this->doDispatch($this->getListeners($eventName), $eventName, $event);
return $event;
}
/**
......
......@@ -28,8 +28,10 @@ interface EventDispatcherInterface
* @param string $eventName The name of the event to dispatch. The name of
* the event is the name of the method that is
* invoked on listeners.
* @param Event $event The event to pass to the event handlers/listeners.
* If not supplied, an empty Event instance is created.
* @param Event $event The event to pass to the event handlers/listeners.
* If not supplied, an empty Event instance is created.
*
* @return Event
*
* @api
*/
......@@ -48,7 +50,9 @@ function dispatch($eventName, Event $event = null);
function addListener($eventName, $listener, $priority = 0);
/**
* Adds an event subscriber. The subscriber is asked for all the events he is
* Adds an event subscriber.
*
* The subscriber is asked for all the events he is
* interested in and added as a listener for these events.
*
* @param EventSubscriberInterface $subscriber The subscriber.
......@@ -60,35 +64,33 @@ function addSubscriber(EventSubscriberInterface $subscriber);
/**
* Removes an event listener from the specified events.
*
* @param string|array $eventName The event(s) to remove a listener from.
* @param object $listener The listener object to remove.
* @param string|array $eventName The event(s) to remove a listener from
* @param callable $listener The listener to remove
*/
function removeListener($eventName, $listener);
/**
* Removes an event subscriber.
*
* @param EventSubscriberInterface $subscriber The subscriber.
* @param EventSubscriberInterface $subscriber The subscriber
*/
function removeSubscriber(EventSubscriberInterface $subscriber);
/**
* Gets the listeners of a specific event or all listeners.
*
* @param string $eventName The name of the event.
* @param string $eventName The name of the event
*
* @return array The event listeners for the specified event, or all event
* listeners by event name.
* @return array The event listeners for the specified event, or all event listeners by event name
*/
function getListeners($eventName = null);
/**
* Checks whether an event has any registered listeners.
*
* @param string $eventName The name of the event.
* @param string $eventName The name of the event
*
* @return Boolean TRUE if the specified event has any listeners, FALSE
* otherwise.
* @return Boolean true if the specified event has any listeners, false otherwise
*/
function hasListeners($eventName = null);
}
Copyright (c) 2004-2011 Fabien Potencier
Copyright (c) 2004-2012 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -4,7 +4,6 @@
"description": "Symfony EventDispatcher Component",
"keywords": [],
"homepage": "http://symfony.com",
"version": "2.1.0",
"license": "MIT",
"authors": [
{
......@@ -22,5 +21,10 @@
"autoload": {
"psr-0": { "Symfony\\Component\\EventDispatcher": "" }
},
"target-dir": "Symfony/Component/EventDispatcher"
"target-dir": "Symfony/Component/EventDispatcher",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
}
}
<?php
/*
* This file is part of the Symfony package.
*
* (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 Symfony\Component\HttpFoundation\File\MimeType;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
/**
* Guesses the mime type using the PHP function mime_content_type().
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class ContentTypeMimeTypeGuesser implements MimeTypeGuesserInterface
{
/**
* Returns whether this guesser is supported on the current OS/PHP setup
*
* @return Boolean
*/
static public function isSupported()
{
return function_exists('mime_content_type');
}
/**
* Guesses the mime type of the file with the given path
*
* @see MimeTypeGuesserInterface::guess()
*/
public function guess($path)
{
if (!is_file($path)) {
throw new FileNotFoundException($path);
}
if (!is_readable($path)) {
throw new AccessDeniedException($path);
}
if (!self::isSupported()) {
return null;
}
$type = mime_content_type($path);
// remove charset (added as of PHP 5.3)
if (false !== $pos = strpos($type, ';')) {
$type = substr($type, 0, $pos);
}
return $type;
}
}
......@@ -21,6 +21,23 @@
*/
class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
{
private $cmd;
/**
* Constructor.
*
* The $cmd pattern must contain a "%s" string that will be replaced
* with the file name to guess.
*
* The command output must start with the mime type of the file.
*
* @param string $cmd The command to run to get the mime type of a file
*/
public function __construct($cmd = 'file -b --mime %s 2>/dev/null')
{
$this->cmd = $cmd;
}
/**
* Returns whether this guesser is supported on the current OS
*
......@@ -28,8 +45,9 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
*/
static public function isSupported()
{
return !strstr(PHP_OS, 'WIN');
return !defined('PHP_WINDOWS_VERSION_BUILD');
}
/**
* Guesses the mime type of the file with the given path
*
......@@ -52,7 +70,7 @@ public function guess($path)
ob_start();
// need to use --mime instead of -i. see #6641
passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($path)), $return);
passthru(sprintf($this->cmd, escapeshellarg($path)), $return);
if ($return > 0) {
ob_end_clean();
......
......@@ -67,10 +67,6 @@ private function __construct()
$this->register(new FileBinaryMimeTypeGuesser());
}
if (ContentTypeMimeTypeGuesser::isSupported()) {
$this->register(new ContentTypeMimeTypeGuesser());
}
if (FileinfoMimeTypeGuesser::isSupported()) {
$this->register(new FileinfoMimeTypeGuesser());
}
......
......@@ -18,7 +18,7 @@
*
* @api
*/
class HeaderBag
class HeaderBag implements \IteratorAggregate, \Countable
{
protected $headers;
protected $cacheControl;
......@@ -267,6 +267,26 @@ public function removeCacheControlDirective($key)
$this->set('Cache-Control', $this->getCacheControlHeader());
}
/**
* Returns an iterator for headers.
*
* @return \ArrayIterator An \ArrayIterator instance
*/
public function getIterator()
{
return new \ArrayIterator($this->headers);
}
/**
* Returns the number of headers.
*
* @return int The number of headers
*/
public function count()
{
return count($this->headers);
}
protected function getCacheControlHeader()
{
$parts = array();
......
Copyright (c) 2004-2011 Fabien Potencier
Copyright (c) 2004-2012 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -18,8 +18,13 @@
*
* @api
*/
class ParameterBag
class ParameterBag implements \IteratorAggregate, \Countable
{
/**
* Parameter storage.
*
* @var array
*/
protected $parameters;
/**
......@@ -224,7 +229,8 @@ public function getAlnum($key, $default = '', $deep = false)
*/
public function getDigits($key, $default = '', $deep = false)
{
return preg_replace('/[^[:digit:]]/', '', $this->get($key, $default, $deep));
// we need to remove - and + because they're allowed in the filter
return str_replace(array('-', '+'), '', $this->filter($key, $default, $deep, FILTER_SANITIZE_NUMBER_INT));
}
/**
......@@ -242,4 +248,54 @@ public function getInt($key, $default = 0, $deep = false)
{
return (int) $this->get($key, $default, $deep);
}
/**
* Filter key.
*
* @param string $key Key.
* @param mixed $default Default = null.
* @param boolean $deep Default = false.
* @param integer $filter FILTER_* constant.
* @param mixed $options Filter options.
*
* @see http://php.net/manual/en/function.filter-var.php
*
* @return mixed
*/
public function filter($key, $default = null, $deep = false, $filter=FILTER_DEFAULT, $options=array())
{
$value = $this->get($key, $default, $deep);
// Always turn $options into an array - this allows filter_var option shortcuts.
if (!is_array($options) && $options) {
$options = array('flags' => $options);
}
// Add a convenience check for arrays.
if (is_array($value) && !isset($options['flags'])) {
$options['flags'] = FILTER_REQUIRE_ARRAY;
}
return filter_var($value, $filter, $options);
}
/**
* Returns an iterator for parameters.
*
* @return \ArrayIterator An \ArrayIterator instance
*/
public function getIterator()
{
return new \ArrayIterator($this->parameters);
}
/**
* Returns the number of parameters.
*
* @return int The number of parameters
*/
public function count()
{
return count($this->parameters);
}
}
......@@ -20,22 +20,27 @@
*/
class RedirectResponse extends Response
{
protected $targetUrl;
/**
* Creates a redirect response so that it conforms to the rules defined for a redirect status code.
*
* @param string $url The URL to redirect to
* @param integer $status The status code (302 by default)
* @param string $url The URL to redirect to
* @param integer $status The status code (302 by default)
* @param array $headers The headers (Location is always set to the given url)
*
* @see http://tools.ietf.org/html/rfc2616#section-10.3
*
* @api
*/
public function __construct($url, $status = 302)
public function __construct($url, $status = 302, $headers = array())
{
if (empty($url)) {
throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
}
$this->targetUrl = $url;
parent::__construct(
sprintf('<!DOCTYPE html>
<html>
......@@ -50,11 +55,29 @@ public function __construct($url, $status = 302)
</body>
</html>', htmlspecialchars($url, ENT_QUOTES, 'UTF-8')),
$status,
array('Location' => $url)
array_merge($headers, array('Location' => $url))
);
if (!$this->isRedirect()) {
throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status));
}
}
/**
* {@inheritDoc}
*/
static public function create($url = '', $status = 302, $headers = array())
{
return new static($url, $status, $headers);
}
/**
* Returns the target URL.
*
* @return string target URL
*/
public function getTargetUrl()
{
return $this->targetUrl;
}
}
......@@ -20,10 +20,31 @@
*/
class RequestMatcher implements RequestMatcherInterface
{
/**
* @var string
*/
private $path;
/**
* @var string
*/
private $host;
/**
* @var string
*/
private $methods;
/**
* @var string
*/
private $ip;
/**
* Attributes.
*
* @var array
*/
private $attributes;
public function __construct($path = null, $host = null, $methods = null, $ip = null, array $attributes = array())
......@@ -122,6 +143,14 @@ public function matches(Request $request)
return true;
}
/**
* Validates an IP address.
*
* @param string $requestIp
* @param string $ip
*
* @return boolean True valid, false if not.
*/
protected function checkIp($requestIp, $ip)
{
// IPv6 address
......@@ -132,6 +161,14 @@ protected function checkIp($requestIp, $ip)
}
}
/**
* Validates an IPv4 address.
*
* @param string $requestIp
* @param string $ip
*
* @return boolean True valid, false if not.
*/
protected function checkIp4($requestIp, $ip)
{
if (false !== strpos($ip, '/')) {
......@@ -149,8 +186,15 @@ protected function checkIp4($requestIp, $ip)
}
/**
* Validates an IPv6 address.
*
* @author David Soria Parra <dsp at php dot net>