diff --git a/core/vendor/Symfony/Component/ClassLoader/ApcClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/ApcClassLoader.php new file mode 100644 index 0000000..3508db6 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/ApcClassLoader.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader; + +/** + * ApcClassLoader implements a wrapping autoloader cached in APC for PHP 5.3. + * + * It expects an object implementing a findFile method to find the file. This + * allow using it as a wrapper around the other loaders of the component (the + * ClassLoader and the UniversalClassLoader for instance) but also around any + * other autoloader following this convention (the Composer one for instance) + * + * $loader = new ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * $cachedLoader = new ApcClassLoader('my_prefix', $loader); + * + * // activate the cached autoloader + * $cachedLoader->register(); + * + * // eventually deactivate the non-cached loader if it was registered previously + * // to be sure to use the cached one. + * $loader->unregister(); + * + * @author Fabien Potencier + * @author Kris Wallsmith + * + * @api + */ +class ApcClassLoader +{ + private $prefix; + private $classFinder; + + /** + * Constructor. + * + * @param string $prefix A prefix to create a namespace in APC + * @param object $classFinder + * + * @api + */ + public function __construct($prefix, $classFinder) + { + if (!extension_loaded('apc')) { + throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.'); + } + + if (!method_exists($classFinder, 'findFile')) { + throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); + } + + $this->prefix = $prefix; + $this->classFinder = $classFinder; + } + + /** + * Registers this instance as an autoloader. + * + * @param Boolean $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return Boolean|null True, if loaded + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + require $file; + + return true; + } + } + + /** + * Finds a file by class name while caching lookups to APC. + * + * @param string $class A class name to resolve to file + * + * @return string|null + */ + public function findFile($class) + { + if (false === $file = apc_fetch($this->prefix.$class)) { + apc_store($this->prefix.$class, $file = $this->classFinder->findFile($class)); + } + + return $file; + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php index 49d3da3..894900b 100644 --- a/core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ b/core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php @@ -181,7 +181,7 @@ class ClassCollectionLoader { $tmpFile = tempnam(dirname($file), basename($file)); if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { - chmod($file, 0644); + chmod($file, 0666 & ~umask()); return; } diff --git a/core/vendor/Symfony/Component/ClassLoader/ClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/ClassLoader.php new file mode 100644 index 0000000..b94bdb9 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/ClassLoader.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader; + +/** + * ClassLoader implements an PSR-0 class loader + * + * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md + * + * $loader = new ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * @author Fabien Potencier + * @author Jordi Boggiano + */ +class ClassLoader +{ + private $prefixes = array(); + private $fallbackDirs = array(); + private $useIncludePath = false; + + public function getPrefixes() + { + return $this->prefixes; + } + + public function getFallbackDirs() + { + return $this->fallbackDirs; + } + + public function addPrefixes(array $prefixes) + { + foreach ($prefixes as $prefix => $path) { + $this->addPrefix($prefix, $path); + } + } + + /** + * Registers a set of classes + * + * @param string $prefix The classes prefix + * @param array|string $paths The location(s) of the classes + */ + public function addPrefix($prefix, $paths) + { + if (!$prefix) { + foreach ((array) $paths as $path) { + $this->fallbackDirs[] = $path; + } + + return; + } + if (isset($this->prefixes[$prefix])) { + $this->prefixes[$prefix] = array_merge( + $this->prefixes[$prefix], + (array) $paths + ); + } else { + $this->prefixes[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include for class files. + * + * @param Boolean $useIncludePath + */ + public function setUseIncludePath($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; + } + + /** + * Registers this instance as an autoloader. + * + * @param Boolean $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return Boolean|null True, if loaded + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + require $file; + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|null The path, if found + */ + public function findFile($class) + { + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR; + $className = substr($class, $pos + 1); + } else { + // PEAR-like class name + $classPath = null; + $className = $class; + } + + $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; + + foreach ($this->prefixes as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { + return $dir . DIRECTORY_SEPARATOR . $classPath; + } + } + } + } + + foreach ($this->fallbackDirs as $dir) { + if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { + return $dir . DIRECTORY_SEPARATOR . $classPath; + } + } + + if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) { + return $file; + } + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/DebugClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/DebugClassLoader.php new file mode 100644 index 0000000..b6f7968 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/DebugClassLoader.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader; + +/** + * Autoloader checking if the class is really defined in the file found. + * + * The DebugClassLoader will wrap all registered autoloaders providing a + * findFile method and will throw an exception if a file is found but does + * not declare the class. + * + * @author Fabien Potencier + * @author Christophe Coevoet + * + * @api + */ +class DebugClassLoader +{ + private $classFinder; + + /** + * Constructor. + * + * @param object $classFinder + * + * @api + */ + public function __construct($classFinder) + { + $this->classFinder = $classFinder; + } + + /** + * Replaces all autoloaders implementing a findFile method by a DebugClassLoader wrapper. + */ + static public function enable() + { + if (!is_array($functions = spl_autoload_functions())) { + return; + } + + foreach ($functions as $function) { + spl_autoload_unregister($function); + } + + foreach ($functions as $function) { + if (is_array($function) && method_exists($function[0], 'findFile')) { + $function = array(new static($function[0]), 'loadClass'); + } + + spl_autoload_register($function); + } + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return Boolean|null True, if loaded + */ + public function loadClass($class) + { + if ($file = $this->classFinder->findFile($class)) { + require $file; + + if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { + throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); + } + + return true; + } + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/README.md b/core/vendor/Symfony/Component/ClassLoader/README.md index bdfcb8e..5a83c5f 100644 --- a/core/vendor/Symfony/Component/ClassLoader/README.md +++ b/core/vendor/Symfony/Component/ClassLoader/README.md @@ -58,3 +58,16 @@ class loader: Furthermore, the component provides tools to aggregate classes into a single file, which is especially useful to improve performance on servers that do not provide byte caches. + +Resources +--------- + +You can run the unit tests with the following command: + + phpunit -c src/Symfony/Component/ClassLoader/ + +If you also want to run the unit tests that depend on other Symfony +Components, declare the following environment variables before running +PHPUnit: + + export SYMFONY_FINDER=../path/to/Finder diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php b/core/vendor/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php new file mode 100644 index 0000000..9a7acfd --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php @@ -0,0 +1,192 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader\Tests; + +use Symfony\Component\ClassLoader\ApcUniversalClassLoader; + +class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!extension_loaded('apc')) { + $this->markTestSkipped('The apc extension is not available.'); + } + + if (!(ini_get('apc.enabled') && ini_get('apc.enable_cli'))) { + $this->markTestSkipped('The apc extension is available, but not enabled.'); + } else { + apc_clear_cache('user'); + } + } + + protected function tearDown() + { + if (ini_get('apc.enabled') && ini_get('apc.enable_cli')) { + apc_clear_cache('user'); + } + } + + public function testConstructor() + { + $loader = new ApcUniversalClassLoader('test.prefix.'); + $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + + $this->assertEquals($loader->findFile('\Apc\Namespaced\FooBar'), apc_fetch('test.prefix.\Apc\Namespaced\FooBar'), '__construct() takes a prefix as its first argument'); + } + + /** + * @dataProvider getLoadClassTests + */ + public function testLoadClass($className, $testClassName, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.'); + $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassTests() + { + return array( + array('\\Apc\\Namespaced\\Foo', '\\Apc\\Namespaced\\Foo', '->loadClass() loads Apc\Namespaced\Foo class'), + array('Apc_Pearlike_Foo', 'Apc_Pearlike_Foo', '->loadClass() loads Apc_Pearlike_Foo class'), + array('\\Apc\\Namespaced\\Bar', '\\Apc\\Namespaced\\Bar', '->loadClass() loads Apc\Namespaced\Bar class with a leading slash'), + array('Apc_Pearlike_Bar', '\\Apc_Pearlike_Bar', '->loadClass() loads Apc_Pearlike_Bar class with a leading slash'), + ); + } + + /** + * @dataProvider getLoadClassFromFallbackTests + */ + public function testLoadClassFromFallback($className, $testClassName, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.fallback'); + $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/fallback')); + $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/fallback')); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassFromFallbackTests() + { + return array( + array('\\Apc\\Namespaced\\Baz', '\\Apc\\Namespaced\\Baz', '->loadClass() loads Apc\Namespaced\Baz class'), + array('Apc_Pearlike_Baz', 'Apc_Pearlike_Baz', '->loadClass() loads Apc_Pearlike_Baz class'), + array('\\Apc\\Namespaced\\FooBar', '\\Apc\\Namespaced\\FooBar', '->loadClass() loads Apc\Namespaced\Baz class from fallback dir'), + array('Apc_Pearlike_FooBar', 'Apc_Pearlike_FooBar', '->loadClass() loads Apc_Pearlike_Baz class from fallback dir'), + ); + } + + /** + * @dataProvider getLoadClassNamespaceCollisionTests + */ + public function testLoadClassNamespaceCollision($namespaces, $className, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.collision.'); + $loader->registerNamespaces($namespaces); + + $loader->loadClass($className); + + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassNamespaceCollisionTests() + { + return array( + array( + array( + 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', + 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', + ), + '\Apc\NamespaceCollision\A\Foo', + '->loadClass() loads NamespaceCollision\A\Foo from alpha.', + ), + array( + array( + 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', + 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', + ), + '\Apc\NamespaceCollision\A\Bar', + '->loadClass() loads NamespaceCollision\A\Bar from alpha.', + ), + array( + array( + 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', + 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', + ), + '\Apc\NamespaceCollision\A\B\Foo', + '->loadClass() loads NamespaceCollision\A\B\Foo from beta.', + ), + array( + array( + 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', + 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', + ), + '\Apc\NamespaceCollision\A\B\Bar', + '->loadClass() loads NamespaceCollision\A\B\Bar from beta.', + ), + ); + } + + /** + * @dataProvider getLoadClassPrefixCollisionTests + */ + public function testLoadClassPrefixCollision($prefixes, $className, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.collision.'); + $loader->registerPrefixes($prefixes); + + $loader->loadClass($className); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassPrefixCollisionTests() + { + return array( + array( + array( + 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', + 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', + ), + 'ApcPrefixCollision_A_Foo', + '->loadClass() loads ApcPrefixCollision_A_Foo from alpha.', + ), + array( + array( + 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', + 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', + ), + 'ApcPrefixCollision_A_Bar', + '->loadClass() loads ApcPrefixCollision_A_Bar from alpha.', + ), + array( + array( + 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', + 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', + ), + 'ApcPrefixCollision_A_B_Foo', + '->loadClass() loads ApcPrefixCollision_A_B_Foo from beta.', + ), + array( + array( + 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', + 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', + ), + 'ApcPrefixCollision_A_B_Bar', + '->loadClass() loads ApcPrefixCollision_A_B_Bar from beta.', + ), + ); + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php b/core/vendor/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php new file mode 100644 index 0000000..cd1c439 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader\Tests; + +use Symfony\Component\ClassLoader\ClassCollectionLoader; + +class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase +{ + public function testFixNamespaceDeclarations() + { + $source = <<assertEquals($expected, ClassCollectionLoader::fixNamespaceDeclarations($source)); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testUnableToLoadClassException() + { + ClassCollectionLoader::load(array('SomeNotExistingClass'), '', 'foo', false); + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php b/core/vendor/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php new file mode 100644 index 0000000..c9fe382 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader\Tests; + +use Symfony\Component\ClassLoader\ClassLoader; + +class ClassLoaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getLoadClassTests + */ + public function testLoadClass($className, $testClassName, $message) + { + $loader = new ClassLoader(); + $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassTests() + { + return array( + array('\\Namespaced2\\Foo', 'Namespaced2\\Foo', '->loadClass() loads Namespaced2\Foo class'), + array('\\Pearlike2_Foo', 'Pearlike2_Foo', '->loadClass() loads Pearlike2_Foo class'), + array('\\Namespaced2\\Bar', '\\Namespaced2\\Bar', '->loadClass() loads Namespaced2\Bar class with a leading slash'), + array('\\Pearlike2_Bar', '\\Pearlike2_Bar', '->loadClass() loads Pearlike2_Bar class with a leading slash'), + ); + } + + public function testUseIncludePath() + { + $loader = new ClassLoader(); + $this->assertFalse($loader->getUseIncludePath()); + + $this->assertNull($loader->findFile('Foo')); + + $includePath = get_include_path(); + + $loader->setUseIncludePath(true); + $this->assertTrue($loader->getUseIncludePath()); + + set_include_path(__DIR__.'/Fixtures/includepath' . PATH_SEPARATOR . $includePath); + + $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo')); + + set_include_path($includePath); + } + + /** + * @dataProvider getLoadClassFromFallbackTests + */ + public function testLoadClassFromFallback($className, $testClassName, $message) + { + $loader = new ClassLoader(); + $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->addPrefix('', array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback')); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassFromFallbackTests() + { + return array( + array('\\Namespaced2\\Baz', 'Namespaced2\\Baz', '->loadClass() loads Namespaced2\Baz class'), + array('\\Pearlike2_Baz', 'Pearlike2_Baz', '->loadClass() loads Pearlike2_Baz class'), + array('\\Namespaced2\\FooBar', 'Namespaced2\\FooBar', '->loadClass() loads Namespaced2\Baz class from fallback dir'), + array('\\Pearlike2_FooBar', 'Pearlike2_FooBar', '->loadClass() loads Pearlike2_Baz class from fallback dir'), + ); + } + + /** + * @dataProvider getLoadClassNamespaceCollisionTests + */ + public function testLoadClassNamespaceCollision($namespaces, $className, $message) + { + $loader = new ClassLoader(); + $loader->addPrefixes($namespaces); + + $loader->loadClass($className); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassNamespaceCollisionTests() + { + return array( + array( + array( + 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'NamespaceCollision\C\Foo', + '->loadClass() loads NamespaceCollision\C\Foo from alpha.', + ), + array( + array( + 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'NamespaceCollision\C\Bar', + '->loadClass() loads NamespaceCollision\C\Bar from alpha.', + ), + array( + array( + 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'NamespaceCollision\C\B\Foo', + '->loadClass() loads NamespaceCollision\C\B\Foo from beta.', + ), + array( + array( + 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'NamespaceCollision\C\B\Bar', + '->loadClass() loads NamespaceCollision\C\B\Bar from beta.', + ), + array( + array( + 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'PrefixCollision_C_Foo', + '->loadClass() loads PrefixCollision_C_Foo from alpha.', + ), + array( + array( + 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'PrefixCollision_C_Bar', + '->loadClass() loads PrefixCollision_C_Bar from alpha.', + ), + array( + array( + 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'PrefixCollision_C_B_Foo', + '->loadClass() loads PrefixCollision_C_B_Foo from beta.', + ), + array( + array( + 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'PrefixCollision_C_B_Bar', + '->loadClass() loads PrefixCollision_C_B_Bar from beta.', + ), + ); + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php b/core/vendor/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php new file mode 100644 index 0000000..6cebd38 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader\Tests; + +use Symfony\Component\ClassLoader\ClassMapGenerator; + +class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @dataProvider getTestCreateMapTests + */ + public function testCreateMap($directory, $expected) + { + $this->assertEqualsNormalized($expected, ClassMapGenerator::createMap($directory)); + } + + public function getTestCreateMapTests() + { + $data = array( + array(__DIR__.'/Fixtures/Namespaced', array( + 'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php', + 'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php', + 'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php', + ) + ), + array(__DIR__.'/Fixtures/beta/NamespaceCollision', array( + 'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php', + 'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php', + 'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php', + 'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php', + )), + array(__DIR__.'/Fixtures/Pearlike', array( + 'Pearlike_Foo' => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php', + 'Pearlike_Bar' => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php', + 'Pearlike_Baz' => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php', + )), + array(__DIR__.'/Fixtures/classmap', array( + 'Foo\\Bar\\A' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php', + 'Foo\\Bar\\B' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php', + 'A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', + 'Alpha\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', + 'Alpha\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', + 'Beta\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', + 'Beta\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', + 'ClassMap\\SomeInterface' => realpath(__DIR__).'/Fixtures/classmap/SomeInterface.php', + 'ClassMap\\SomeParent' => realpath(__DIR__).'/Fixtures/classmap/SomeParent.php', + 'ClassMap\\SomeClass' => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php', + )), + ); + + if (version_compare(PHP_VERSION, '5.4', '>=')) { + $data[] = array(__DIR__.'/Fixtures/php5.4', array( + 'TFoo' => __DIR__.'/Fixtures/php5.4/traits.php', + 'CFoo' => __DIR__.'/Fixtures/php5.4/traits.php', + 'Foo\\TBar' => __DIR__.'/Fixtures/php5.4/traits.php', + 'Foo\\IBar' => __DIR__.'/Fixtures/php5.4/traits.php', + 'Foo\\TFooBar' => __DIR__.'/Fixtures/php5.4/traits.php', + 'Foo\\CBar' => __DIR__.'/Fixtures/php5.4/traits.php', + )); + } + + return $data; + } + + public function testCreateMapFinderSupport() + { + if (!class_exists('Symfony\\Component\\Finder\\Finder')) { + $this->markTestSkipped('Finder component is not available'); + } + + $finder = new \Symfony\Component\Finder\Finder(); + $finder->files()->in(__DIR__ . '/Fixtures/beta/NamespaceCollision'); + + $this->assertEqualsNormalized(array( + 'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php', + 'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php', + 'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php', + 'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php', + ), ClassMapGenerator::createMap($finder)); + } + + protected function assertEqualsNormalized($expected, $actual, $message = null) + { + foreach ($expected as $ns => $path) { + $expected[$ns] = strtr($path, '\\', '/'); + } + foreach ($actual as $ns => $path) { + $actual[$ns] = strtr($path, '\\', '/'); + } + $this->assertEquals($expected, $actual, $message); + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php new file mode 100644 index 0000000..4259f14 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\Namespaced; + +class Bar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php new file mode 100644 index 0000000..3ddb595 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\Namespaced; + +class Baz +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php new file mode 100644 index 0000000..cf0a4b7 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\Namespaced; + +class Foo +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php new file mode 100644 index 0000000..bbbc815 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\Namespaced; + +class FooBar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php new file mode 100644 index 0000000..e774cb9 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php @@ -0,0 +1,6 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\NamespaceCollision\A; + +class Bar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php new file mode 100644 index 0000000..184a1b1 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\NamespaceCollision\A; + +class Foo +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php new file mode 100644 index 0000000..3892f70 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php @@ -0,0 +1,6 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\NamespaceCollision\A\B; + +class Bar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php new file mode 100644 index 0000000..450eeb5 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\NamespaceCollision\A\B; + +class Foo +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php new file mode 100644 index 0000000..96f2f76 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php @@ -0,0 +1,6 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Apc\Namespaced; + +class FooBar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php new file mode 100644 index 0000000..02b589d --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Namespaced; + +class Bar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php new file mode 100644 index 0000000..0b0bbd0 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Namespaced; + +class Baz +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php new file mode 100644 index 0000000..df5e1f4 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Namespaced; + +class Foo +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php new file mode 100644 index 0000000..7bf42ab --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php @@ -0,0 +1,8 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace NamespaceCollision\A; + +class Bar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php new file mode 100644 index 0000000..aee6a08 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace NamespaceCollision\A; + +class Foo +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php new file mode 100644 index 0000000..c1b8dd6 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php @@ -0,0 +1,8 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace NamespaceCollision\A\B; + +class Bar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php new file mode 100644 index 0000000..f5f2d72 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace NamespaceCollision\A\B; + +class Foo +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php new file mode 100644 index 0000000..4bb03dc --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php @@ -0,0 +1,8 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ClassMap; + +class SomeClass extends SomeParent implements SomeInterface +{ + +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php new file mode 100644 index 0000000..09d7a8f --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ClassMap; + +interface SomeInterface +{ + +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php new file mode 100644 index 0000000..5a859a9 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ClassMap; + +abstract class SomeParent +{ + +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php new file mode 100644 index 0000000..d19e07f --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Foo\Bar; + +class A {} +class B {} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php new file mode 100644 index 0000000..0fd29ef --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Namespaced; + +class FooBar +{ + public static $loaded = true; +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php new file mode 100644 index 0000000..1036d43 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php @@ -0,0 +1,8 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader\Tests; + +use Symfony\Component\ClassLoader\UniversalClassLoader; + +class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getLoadClassTests + */ + public function testLoadClass($className, $testClassName, $message) + { + $loader = new UniversalClassLoader(); + $loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassTests() + { + return array( + array('\\Namespaced\\Foo', 'Namespaced\\Foo', '->loadClass() loads Namespaced\Foo class'), + array('\\Pearlike_Foo', 'Pearlike_Foo', '->loadClass() loads Pearlike_Foo class'), + array('\\Namespaced\\Bar', '\\Namespaced\\Bar', '->loadClass() loads Namespaced\Bar class with a leading slash'), + array('\\Pearlike_Bar', '\\Pearlike_Bar', '->loadClass() loads Pearlike_Bar class with a leading slash'), + ); + } + + public function testUseIncludePath() + { + $loader = new UniversalClassLoader(); + $this->assertFalse($loader->getUseIncludePath()); + + $this->assertNull($loader->findFile('Foo')); + + $includePath = get_include_path(); + + $loader->useIncludePath(true); + $this->assertTrue($loader->getUseIncludePath()); + + set_include_path(__DIR__.'/Fixtures/includepath' . PATH_SEPARATOR . $includePath); + + $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo')); + + set_include_path($includePath); + } + + /** + * @dataProvider getLoadClassFromFallbackTests + */ + public function testLoadClassFromFallback($className, $testClassName, $message) + { + $loader = new UniversalClassLoader(); + $loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback')); + $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback')); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassFromFallbackTests() + { + return array( + array('\\Namespaced\\Baz', 'Namespaced\\Baz', '->loadClass() loads Namespaced\Baz class'), + array('\\Pearlike_Baz', 'Pearlike_Baz', '->loadClass() loads Pearlike_Baz class'), + array('\\Namespaced\\FooBar', 'Namespaced\\FooBar', '->loadClass() loads Namespaced\Baz class from fallback dir'), + array('\\Pearlike_FooBar', 'Pearlike_FooBar', '->loadClass() loads Pearlike_Baz class from fallback dir'), + ); + } + + public function testRegisterPrefixFallback() + { + $loader = new UniversalClassLoader(); + $loader->registerPrefixFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'); + $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'), $loader->getPrefixFallbacks()); + } + + public function testRegisterNamespaceFallback() + { + $loader = new UniversalClassLoader(); + $loader->registerNamespaceFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback'); + $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback'), $loader->getNamespaceFallbacks()); + } + + /** + * @dataProvider getLoadClassNamespaceCollisionTests + */ + public function testLoadClassNamespaceCollision($namespaces, $className, $message) + { + $loader = new UniversalClassLoader(); + $loader->registerNamespaces($namespaces); + + $loader->loadClass($className); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassNamespaceCollisionTests() + { + return array( + array( + array( + 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'NamespaceCollision\A\Foo', + '->loadClass() loads NamespaceCollision\A\Foo from alpha.', + ), + array( + array( + 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'NamespaceCollision\A\Bar', + '->loadClass() loads NamespaceCollision\A\Bar from alpha.', + ), + array( + array( + 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'NamespaceCollision\A\B\Foo', + '->loadClass() loads NamespaceCollision\A\B\Foo from beta.', + ), + array( + array( + 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'NamespaceCollision\A\B\Bar', + '->loadClass() loads NamespaceCollision\A\B\Bar from beta.', + ), + ); + } + + /** + * @dataProvider getLoadClassPrefixCollisionTests + */ + public function testLoadClassPrefixCollision($prefixes, $className, $message) + { + $loader = new UniversalClassLoader(); + $loader->registerPrefixes($prefixes); + + $loader->loadClass($className); + $this->assertTrue(class_exists($className), $message); + } + + public function getLoadClassPrefixCollisionTests() + { + return array( + array( + array( + 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'PrefixCollision_A_Foo', + '->loadClass() loads PrefixCollision_A_Foo from alpha.', + ), + array( + array( + 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'PrefixCollision_A_Bar', + '->loadClass() loads PrefixCollision_A_Bar from alpha.', + ), + array( + array( + 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + ), + 'PrefixCollision_A_B_Foo', + '->loadClass() loads PrefixCollision_A_B_Foo from beta.', + ), + array( + array( + 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', + 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', + ), + 'PrefixCollision_A_B_Bar', + '->loadClass() loads PrefixCollision_A_B_Bar from beta.', + ), + ); + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/Tests/bootstrap.php b/core/vendor/Symfony/Component/ClassLoader/Tests/bootstrap.php new file mode 100644 index 0000000..3364e14 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/Tests/bootstrap.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + foreach (array( + 'SYMFONY_FINDER' => 'Finder', + ) as $env => $name) { + if (isset($_SERVER[$env]) && 0 === strpos(ltrim($class, '/'), 'Symfony\Component\\'.$name)) { + if (file_exists($file = $_SERVER[$env].'/'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\\'.$name)).'.php')) { + require_once $file; + } + } + } + + if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\ClassLoader')) { + if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\ClassLoader')).'.php')) { + require_once $file; + } + } +}); diff --git a/core/vendor/Symfony/Component/ClassLoader/XcacheClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/XcacheClassLoader.php new file mode 100644 index 0000000..2eaaba2 --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/XcacheClassLoader.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader; + +/** + * XcacheClassLoader implements a wrapping autoloader cached in Xcache for PHP 5.3. + * + * It expects an object implementing a findFile method to find the file. This + * allows using it as a wrapper around the other loaders of the component (the + * ClassLoader and the UniversalClassLoader for instance) but also around any + * other autoloader following this convention (the Composer one for instance) + * + * $loader = new ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * $cachedLoader = new XcacheClassLoader('my_prefix', $loader); + * + * // activate the cached autoloader + * $cachedLoader->register(); + * + * // eventually deactivate the non-cached loader if it was registered previously + * // to be sure to use the cached one. + * $loader->unregister(); + * + * @author Fabien Potencier + * @author Kris Wallsmith + * @author Kim Hemsø Rasmussen + * + * @api + */ +class XcacheClassLoader +{ + private $prefix; + private $classFinder; + + /** + * Constructor. + * + * @param string $prefix A prefix to create a namespace in Xcache + * @param object $classFinder + * + * @api + */ + public function __construct($prefix, $classFinder) + { + if (!extension_loaded('Xcache')) { + throw new \RuntimeException('Unable to use XcacheClassLoader as Xcache is not enabled.'); + } + + if (!method_exists($classFinder, 'findFile')) { + throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); + } + + $this->prefix = $prefix; + $this->classFinder = $classFinder; + } + + /** + * Registers this instance as an autoloader. + * + * @param Boolean $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return Boolean|null True, if loaded + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + require $file; + return true; + } + } + + /** + * Finds a file by class name while caching lookups to Xcache. + * + * @param string $class A class name to resolve to file + * + * @return string|null + */ + public function findFile($class) + { + if (xcache_isset($this->prefix.$class)) { + $file = xcache_get($this->prefix.$class); + } else { + xcache_set($this->prefix.$class, $file = $this->classFinder->findFile($class)); + } + + return $file; + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/phpunit.xml.dist b/core/vendor/Symfony/Component/ClassLoader/phpunit.xml.dist new file mode 100644 index 0000000..bc7a21e --- /dev/null +++ b/core/vendor/Symfony/Component/ClassLoader/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php index 4f353d1..9cb3ff0 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php index ad55b34..e536331 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php index 2cf957a..2cd5480 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php index d271d9b..436dc74 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php b/core/vendor/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php index daee911..0c6c90d 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php b/core/vendor/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php index 0f6ff5a..d97d923 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/core/vendor/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index 5242f41..53c6f52 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Container.php b/core/vendor/Symfony/Component/DependencyInjection/Container.php index 759bd45..cf29685 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Container.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Container.php @@ -59,7 +59,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; * * @api */ -class Container implements ContainerInterface +class Container implements IntrospectableContainerInterface { protected $parameterBag; protected $services; @@ -265,6 +265,18 @@ class Container implements ContainerInterface throw new ServiceNotFoundException($id); } } + + /** + * Returns true if the given service has actually been initialized + * + * @param string $id The service identifier + * + * @return Boolean true if service has already been initialized, false otherwise + */ + public function initialized($id) + { + return isset($this->services[strtolower($id)]); + } /** * Gets all service ids. diff --git a/core/vendor/Symfony/Component/DependencyInjection/Definition.php b/core/vendor/Symfony/Component/DependencyInjection/Definition.php index ed5976f..1c974a6 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Definition.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Definition.php @@ -162,7 +162,7 @@ class Definition } /** - * Sets the service class. + * Gets the service class. * * @return string The service class * @@ -452,6 +452,22 @@ class Definition } /** + * Clears all tags for a given name. + * + * @param string $name The tag name + * + * @return Definition + */ + public function clearTag($name) + { + if (isset($this->tags[$name])) { + unset($this->tags[$name]); + } + + return $this; + } + + /** * Clears the tags for this definition. * * @return Definition The current instance diff --git a/core/vendor/Symfony/Component/DependencyInjection/DefinitionDecorator.php b/core/vendor/Symfony/Component/DependencyInjection/DefinitionDecorator.php index 083fc5b..8652d80 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/DefinitionDecorator.php +++ b/core/vendor/Symfony/Component/DependencyInjection/DefinitionDecorator.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/core/vendor/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index 2af81b4..6a91b99 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -21,7 +21,7 @@ use Symfony\Component\DependencyInjection\Exception\RuntimeException; * XmlDumper dumps a service container as an XML string. * * @author Fabien Potencier - * @author Martin Haso? + * @author Martin Hasoň * * @api */ diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php index 8072ed8..959238e 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php index 3dc2759..24d1ca0 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/LogicException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/LogicException.php index 502c4fa..17a070c 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/LogicException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/LogicException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php index 75946b5..a61f143 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/RuntimeException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/RuntimeException.php index 64c822c..5c24541 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/RuntimeException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/RuntimeException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php index fbc7385..f23374f 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php index fc0b50e..d463453 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php b/core/vendor/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php index fc9898f..f9af1ea 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; diff --git a/core/vendor/Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php b/core/vendor/Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php new file mode 100644 index 0000000..726652c --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * IntrospectableContainerInterface defines additional introspection functionality + * for containers, allowing logic to be implemented based on a Container's state. + * + * @author Evan Villemez + * + */ +interface IntrospectableContainerInterface extends ContainerInterface +{ + /** + * Check for whether or not a service has been initialized. + * + * @param string $id + * + * @return Boolean true if the service has been initialized, false otherwise + * + */ + function initialized($id); + +} \ No newline at end of file diff --git a/core/vendor/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/core/vendor/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 35dbc75..e163219 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -193,7 +193,8 @@ class YamlFileLoader extends FileLoader if (isset($service['calls'])) { foreach ($service['calls'] as $call) { - $definition->addMethodCall($call[0], $this->resolveServices($call[1])); + $args = isset($call[1]) ? $this->resolveServices($call[1]) : array(); + $definition->addMethodCall($call[0], $args); } } @@ -210,6 +211,12 @@ class YamlFileLoader extends FileLoader $name = $tag['name']; unset($tag['name']); + foreach ($tag as $attribute => $value) { + if (!is_scalar($value)) { + throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s" in %s.', $id, $name, $file)); + } + } + $definition->addTag($name, $tag); } } diff --git a/core/vendor/Symfony/Component/DependencyInjection/README.md b/core/vendor/Symfony/Component/DependencyInjection/README.md index 6add4cb..06ebe3d 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/README.md +++ b/core/vendor/Symfony/Component/DependencyInjection/README.md @@ -18,9 +18,61 @@ Here is a simple example that shows how to register services and parameters: $sc->get('foo'); +Method Calls (Setter Injection): + + $sc = new ContainerBuilder(); + + $sc + ->register('bar', '%bar.class%') + ->addMethodCall('setFoo', array(new Reference('foo'))) + ; + $sc->setParameter('bar.class', 'Bar'); + + $sc->get('bar'); + +Factory Class: + +If your service is retrieved by calling a static method: + + $sc = new ContainerBuilder(); + + $sc + ->register('bar', '%bar.class%') + ->setFactoryClass('%bar.class%') + ->setFactoryMethod('getInstance') + ->addArgument('Aarrg!!!') + ; + $sc->setParameter('bar.class', 'Bar'); + + $sc->get('bar'); + +File Include: + +For some services, especially those that are difficult or impossible to +autoload, you may need the container to include a file before +instantiating your class. + + $sc = new ContainerBuilder(); + + $sc + ->register('bar', '%bar.class%') + ->setFile('/path/to/file') + ->addArgument('Aarrg!!!') + ; + $sc->setParameter('bar.class', 'Bar'); + + $sc->get('bar'); + Resources --------- -Unit tests: +You can run the unit tests with the following command: + + phpunit -c src/Symfony/Component/DependencyInjection/ + +If you also want to run the unit tests that depend on other Symfony +Components, declare the following environment variables before running +PHPUnit: -https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/DependencyInjection + export SYMFONY_CONFIG=../path/to/Config + export SYMFONY_YAML=../path/to/Yaml diff --git a/core/vendor/Symfony/Component/DependencyInjection/Scope.php b/core/vendor/Symfony/Component/DependencyInjection/Scope.php index 6bc6acb..161229e 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/Scope.php +++ b/core/vendor/Symfony/Component/DependencyInjection/Scope.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; diff --git a/core/vendor/Symfony/Component/DependencyInjection/ScopeInterface.php b/core/vendor/Symfony/Component/DependencyInjection/ScopeInterface.php index 42ac3e2..44b8c5d 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/ScopeInterface.php +++ b/core/vendor/Symfony/Component/DependencyInjection/ScopeInterface.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php new file mode 100644 index 0000000..5257781 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Compiler\Compiler; +use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; +use Symfony\Component\DependencyInjection\Compiler\RepeatedPass; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class AnalyzeServiceReferencesPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + + $a = $container + ->register('a') + ->addArgument($ref1 = new Reference('b')) + ; + + $b = $container + ->register('b') + ->addMethodCall('setA', array($ref2 = new Reference('a'))) + ; + + $c = $container + ->register('c') + ->addArgument($ref3 = new Reference('a')) + ->addArgument($ref4 = new Reference('b')) + ; + + $d = $container + ->register('d') + ->setProperty('foo', $ref5 = new Reference('b')) + ; + + $graph = $this->process($container); + + $this->assertCount(3, $edges = $graph->getNode('b')->getInEdges()); + $this->assertSame($ref1, $edges[0]->getValue()); + $this->assertSame($ref4, $edges[1]->getValue()); + $this->assertSame($ref5, $edges[2]->getValue()); + } + + public function testProcessDetectsReferencesFromInlinedDefinitions() + { + $container = new ContainerBuilder(); + + $container + ->register('a') + ; + + $container + ->register('b') + ->addArgument(new Definition(null, array($ref = new Reference('a')))) + ; + + $graph = $this->process($container); + + $this->assertCount(1, $refs = $graph->getNode('a')->getInEdges()); + $this->assertSame($ref, $refs[0]->getValue()); + } + + public function testProcessDoesNotSaveDuplicateReferences() + { + $container = new ContainerBuilder(); + + $container + ->register('a') + ; + $container + ->register('b') + ->addArgument(new Definition(null, array($ref1 = new Reference('a')))) + ->addArgument(new Definition(null, array($ref2 = new Reference('a')))) + ; + + $graph = $this->process($container); + + $this->assertCount(2, $graph->getNode('a')->getInEdges()); + } + + protected function process(ContainerBuilder $container) + { + $pass = new RepeatedPass(array(new AnalyzeServiceReferencesPass())); + $pass->process($container); + + return $container->getCompiler()->getServiceReferenceGraph(); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php new file mode 100644 index 0000000..25f816b --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Reference; + +use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass; + +use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; + +use Symfony\Component\DependencyInjection\Compiler\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class CheckCircularReferencesPassTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \RuntimeException + */ + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('a')->addArgument(new Reference('b')); + $container->register('b')->addArgument(new Reference('a')); + + $this->process($container); + } + + /** + * @expectedException \RuntimeException + */ + public function testProcessWithAliases() + { + $container = new ContainerBuilder(); + $container->register('a')->addArgument(new Reference('b')); + $container->setAlias('b', 'c'); + $container->setAlias('c', 'a'); + + $this->process($container); + } + + /** + * @expectedException \RuntimeException + */ + public function testProcessDetectsIndirectCircularReference() + { + $container = new ContainerBuilder(); + $container->register('a')->addArgument(new Reference('b')); + $container->register('b')->addArgument(new Reference('c')); + $container->register('c')->addArgument(new Reference('a')); + + $this->process($container); + } + + public function testProcessIgnoresMethodCalls() + { + $container = new ContainerBuilder(); + $container->register('a')->addArgument(new Reference('b')); + $container->register('b')->addMethodCall('setA', array(new Reference('a'))); + + $this->process($container); + } + + protected function process(ContainerBuilder $container) + { + $compiler = new Compiler(); + $passConfig = $compiler->getPassConfig(); + $passConfig->setOptimizationPasses(array( + new AnalyzeServiceReferencesPass(true), + new CheckCircularReferencesPass(), + )); + $passConfig->setRemovingPasses(array()); + + $compiler->compile($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php new file mode 100644 index 0000000..06845a2 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CheckDefinitionValidityPass; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class CheckDefinitionValidityPassTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \RuntimeException + */ + public function testProcessDetectsSyntheticNonPublicDefinitions() + { + $container = new ContainerBuilder(); + $container->register('a')->setSynthetic(true)->setPublic(false); + + $this->process($container); + } + + /** + * @expectedException \RuntimeException + */ + public function testProcessDetectsSyntheticPrototypeDefinitions() + { + $container = new ContainerBuilder(); + $container->register('a')->setSynthetic(true)->setScope(ContainerInterface::SCOPE_PROTOTYPE); + + $this->process($container); + } + + /** + * @expectedException \RuntimeException + */ + public function testProcessDetectsNonSyntheticNonAbstractDefinitionWithoutClass() + { + $container = new ContainerBuilder(); + $container->register('a')->setSynthetic(false)->setAbstract(false); + + $this->process($container); + } + + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('a', 'class'); + $container->register('b', 'class')->setSynthetic(true)->setPublic(true); + $container->register('c', 'class')->setAbstract(true); + $container->register('d', 'class')->setSynthetic(true); + + $this->process($container); + } + + protected function process(ContainerBuilder $container) + { + $pass = new CheckDefinitionValidityPass(); + $pass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php new file mode 100644 index 0000000..cbf9934 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Definition; + +use Symfony\Component\DependencyInjection\Compiler\CheckExceptionOnInvalidReferenceBehaviorPass; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class CheckExceptionOnInvalidReferenceBehaviorPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + + $container + ->register('a', '\stdClass') + ->addArgument(new Reference('b')) + ; + $container->register('b', '\stdClass'); + } + + /** + * @expectedException Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + */ + public function testProcessThrowsExceptionOnInvalidReference() + { + $container = new ContainerBuilder(); + + $container + ->register('a', '\stdClass') + ->addArgument(new Reference('b')) + ; + + $this->process($container); + } + + /** + * @expectedException Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + */ + public function testProcessThrowsExceptionOnInvalidReferenceFromInlinedDefinition() + { + $container = new ContainerBuilder(); + + $def = new Definition(); + $def->addArgument(new Reference('b')); + + $container + ->register('a', '\stdClass') + ->addArgument($def) + ; + + $this->process($container); + } + + private function process(ContainerBuilder $container) + { + $pass = new CheckExceptionOnInvalidReferenceBehaviorPass(); + $pass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php new file mode 100644 index 0000000..ee18e5c --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Scope; + +use Symfony\Component\DependencyInjection\Compiler\CheckReferenceValidityPass; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class CheckReferenceValidityPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcessIgnoresScopeWideningIfNonStrictReference() + { + $container = new ContainerBuilder(); + $container->register('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false)); + $container->register('b')->setScope('prototype'); + + $this->process($container); + } + + /** + * @expectedException \RuntimeException + */ + public function testProcessDetectsScopeWidening() + { + $container = new ContainerBuilder(); + $container->register('a')->addArgument(new Reference('b')); + $container->register('b')->setScope('prototype'); + + $this->process($container); + } + + public function testProcessIgnoresCrossScopeHierarchyReferenceIfNotStrict() + { + $container = new ContainerBuilder(); + $container->addScope(new Scope('a')); + $container->addScope(new Scope('b')); + + $container->register('a')->setScope('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false)); + $container->register('b')->setScope('b'); + + $this->process($container); + } + + /** + * @expectedException \RuntimeException + */ + public function testProcessDetectsCrossScopeHierarchyReference() + { + $container = new ContainerBuilder(); + $container->addScope(new Scope('a')); + $container->addScope(new Scope('b')); + + $container->register('a')->setScope('a')->addArgument(new Reference('b')); + $container->register('b')->setScope('b'); + + $this->process($container); + } + + /** + * @expectedException \RuntimeException + */ + public function testProcessDetectsReferenceToAbstractDefinition() + { + $container = new ContainerBuilder(); + + $container->register('a')->setAbstract(true); + $container->register('b')->addArgument(new Reference('a')); + + $this->process($container); + } + + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('a')->addArgument(new Reference('b')); + $container->register('b'); + + $this->process($container); + } + + protected function process(ContainerBuilder $container) + { + $pass = new CheckReferenceValidityPass(); + $pass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php new file mode 100644 index 0000000..f22f0da --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Scope; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; +use Symfony\Component\DependencyInjection\Compiler\Compiler; +use Symfony\Component\DependencyInjection\Compiler\RepeatedPass; +use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class InlineServiceDefinitionsPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container + ->register('inlinable.service') + ->setPublic(false) + ; + + $container + ->register('service') + ->setArguments(array(new Reference('inlinable.service'))) + ; + + $this->process($container); + + $arguments = $container->getDefinition('service')->getArguments(); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $arguments[0]); + $this->assertSame($container->getDefinition('inlinable.service'), $arguments[0]); + } + + public function testProcessDoesNotInlineWhenAliasedServiceIsNotOfPrototypeScope() + { + $container = new ContainerBuilder(); + $container + ->register('foo') + ->setPublic(false) + ; + $container->setAlias('moo', 'foo'); + + $container + ->register('service') + ->setArguments(array($ref = new Reference('foo'))) + ; + + $this->process($container); + + $arguments = $container->getDefinition('service')->getArguments(); + $this->assertSame($ref, $arguments[0]); + } + + public function testProcessDoesInlineServiceOfPrototypeScope() + { + $container = new ContainerBuilder(); + $container + ->register('foo') + ->setScope('prototype') + ; + $container + ->register('bar') + ->setPublic(false) + ->setScope('prototype') + ; + $container->setAlias('moo', 'bar'); + + $container + ->register('service') + ->setArguments(array(new Reference('foo'), $ref = new Reference('moo'), new Reference('bar'))) + ; + + $this->process($container); + + $arguments = $container->getDefinition('service')->getArguments(); + $this->assertEquals($container->getDefinition('foo'), $arguments[0]); + $this->assertNotSame($container->getDefinition('foo'), $arguments[0]); + $this->assertSame($ref, $arguments[1]); + $this->assertEquals($container->getDefinition('bar'), $arguments[2]); + $this->assertNotSame($container->getDefinition('bar'), $arguments[2]); + } + + public function testProcessInlinesIfMultipleReferencesButAllFromTheSameDefinition() + { + $container = new ContainerBuilder(); + + $a = $container->register('a')->setPublic(false); + $b = $container + ->register('b') + ->addArgument(new Reference('a')) + ->addArgument(new Definition(null, array(new Reference('a')))) + ; + + $this->process($container); + + $arguments = $b->getArguments(); + $this->assertSame($a, $arguments[0]); + + $inlinedArguments = $arguments[1]->getArguments(); + $this->assertSame($a, $inlinedArguments[0]); + } + + public function testProcessInlinesOnlyIfSameScope() + { + $container = new ContainerBuilder(); + + $container->addScope(new Scope('foo')); + $a = $container->register('a')->setPublic(false)->setScope('foo'); + $b = $container->register('b')->addArgument(new Reference('a')); + + $this->process($container); + $arguments = $b->getArguments(); + $this->assertEquals(new Reference('a'), $arguments[0]); + $this->assertTrue($container->hasDefinition('a')); + } + + protected function process(ContainerBuilder $container) + { + $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass())); + $repeatedPass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php new file mode 100644 index 0000000..c16e9e0 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * This class tests the integration of the different compiler passes + */ +class IntegrationTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + /** + * This tests that the following dependencies are correctly processed: + * + * A is public, B/C are private + * A -> C + * B -> C + */ + public function testProcessRemovesAndInlinesRecursively() + { + $container = new ContainerBuilder(); + + $a = $container + ->register('a', '\stdClass') + ->addArgument(new Reference('c')) + ; + + $b = $container + ->register('b', '\stdClass') + ->addArgument(new Reference('c')) + ->setPublic(false) + ; + + $c = $container + ->register('c', '\stdClass') + ->setPublic(false) + ; + + $container->compile(); + + $this->assertTrue($container->hasDefinition('a')); + $arguments = $a->getArguments(); + $this->assertSame($c, $arguments[0]); + $this->assertFalse($container->hasDefinition('b')); + $this->assertFalse($container->hasDefinition('c')); + } + + public function testProcessInlinesReferencesToAliases() + { + $container = new ContainerBuilder(); + + $a = $container + ->register('a', '\stdClass') + ->addArgument(new Reference('b')) + ; + + $container->setAlias('b', new Alias('c', false)); + + $c = $container + ->register('c', '\stdClass') + ->setPublic(false) + ; + + $container->compile(); + + $this->assertTrue($container->hasDefinition('a')); + $arguments = $a->getArguments(); + $this->assertSame($c, $arguments[0]); + $this->assertFalse($container->hasAlias('b')); + $this->assertFalse($container->hasDefinition('c')); + } + + public function testProcessInlinesWhenThereAreMultipleReferencesButFromTheSameDefinition() + { + $container = new ContainerBuilder(); + + $container + ->register('a', '\stdClass') + ->addArgument(new Reference('b')) + ->addMethodCall('setC', array(new Reference('c'))) + ; + + $container + ->register('b', '\stdClass') + ->addArgument(new Reference('c')) + ->setPublic(false) + ; + + $container + ->register('c', '\stdClass') + ->setPublic(false) + ; + + $container->compile(); + + $this->assertTrue($container->hasDefinition('a')); + $this->assertFalse($container->hasDefinition('b')); + $this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php new file mode 100644 index 0000000..d7e5521 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; +use Symfony\Component\DependencyInjection\Compiler\Compiler; +use Symfony\Component\DependencyInjection\Compiler\RepeatedPass; +use Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class RemoveUnusedDefinitionsPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container + ->register('foo') + ->setPublic(false) + ; + $container + ->register('bar') + ->setPublic(false) + ; + $container + ->register('moo') + ->setArguments(array(new Reference('bar'))) + ; + + $this->process($container); + + $this->assertFalse($container->hasDefinition('foo')); + $this->assertTrue($container->hasDefinition('bar')); + $this->assertTrue($container->hasDefinition('moo')); + } + + public function testProcessRemovesUnusedDefinitionsRecursively() + { + $container = new ContainerBuilder(); + $container + ->register('foo') + ->setPublic(false) + ; + $container + ->register('bar') + ->setArguments(array(new Reference('foo'))) + ->setPublic(false) + ; + + $this->process($container); + + $this->assertFalse($container->hasDefinition('foo')); + $this->assertFalse($container->hasDefinition('bar')); + } + + public function testProcessWorksWithInlinedDefinitions() + { + $container = new ContainerBuilder(); + $container + ->register('foo') + ->setPublic(false) + ; + $container + ->register('bar') + ->setArguments(array(new Definition(null, array(new Reference('foo'))))) + ; + + $this->process($container); + + $this->assertTrue($container->hasDefinition('foo')); + $this->assertTrue($container->hasDefinition('bar')); + } + + protected function process(ContainerBuilder $container) + { + $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass())); + $repeatedPass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php new file mode 100644 index 0000000..a445a20 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\ReplaceAliasByActualDefinitionPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +class ReplaceAliasByActualDefinitionPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + + $container->register('a', '\stdClass'); + + $bDefinition = new Definition('\stdClass'); + $bDefinition->setPublic(false); + $container->setDefinition('b', $bDefinition); + + $container->setAlias('a_alias', 'a'); + $container->setAlias('b_alias', 'b'); + + $this->process($container); + + $this->assertTrue($container->has('a'), '->process() does nothing to public definitions.'); + $this->assertTrue($container->hasAlias('a_alias')); + $this->assertFalse($container->has('b'), '->process() removes non-public definitions.'); + $this->assertTrue( + $container->has('b_alias') && !$container->hasAlias('b_alias'), + '->process() replaces alias to actual.' + ); + } + + protected function process(ContainerBuilder $container) + { + $pass = new ReplaceAliasByActualDefinitionPass(); + $pass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php new file mode 100644 index 0000000..f3c5b15 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\DefinitionDecorator; +use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('parent', 'foo')->setArguments(array('moo', 'b'))->setProperty('foo', 'moo'); + $container->setDefinition('child', new DefinitionDecorator('parent')) + ->replaceArgument(0, 'a') + ->setProperty('foo', 'bar') + ->setClass('bar') + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertNotInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $def); + $this->assertEquals('bar', $def->getClass()); + $this->assertEquals(array('a', 'b'), $def->getArguments()); + $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); + } + + public function testProcessAppendsMethodCallsAlways() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->addMethodCall('foo', array('bar')) + ; + + $container + ->setDefinition('child', new DefinitionDecorator('parent')) + ->addMethodCall('bar', array('foo')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertEquals(array( + array('foo', array('bar')), + array('bar', array('foo')), + ), $def->getMethodCalls()); + } + + public function testProcessDoesNotCopyAbstract() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->setAbstract(true) + ; + + $container + ->setDefinition('child', new DefinitionDecorator('parent')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertFalse($def->isAbstract()); + } + + public function testProcessDoesNotCopyScope() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->setScope('foo') + ; + + $container + ->setDefinition('child', new DefinitionDecorator('parent')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertEquals(ContainerInterface::SCOPE_CONTAINER, $def->getScope()); + } + + public function testProcessDoesNotCopyTags() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->addTag('foo') + ; + + $container + ->setDefinition('child', new DefinitionDecorator('parent')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertEquals(array(), $def->getTags()); + } + + public function testProcessHandlesMultipleInheritance() + { + $container = new ContainerBuilder(); + + $container + ->register('parent', 'foo') + ->setArguments(array('foo', 'bar', 'c')) + ; + + $container + ->setDefinition('child2', new DefinitionDecorator('child1')) + ->replaceArgument(1, 'b') + ; + + $container + ->setDefinition('child1', new DefinitionDecorator('parent')) + ->replaceArgument(0, 'a') + ; + + $this->process($container); + + $def = $container->getDefinition('child2'); + $this->assertEquals(array('a', 'b', 'c'), $def->getArguments()); + $this->assertEquals('foo', $def->getClass()); + } + + protected function process(ContainerBuilder $container) + { + $pass = new ResolveDefinitionTemplatesPass(); + $pass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php new file mode 100644 index 0000000..a18ba73 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Compiler\ResolveInvalidReferencesPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class ResolveInvalidReferencesPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $def = $container + ->register('foo') + ->setArguments(array(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE))) + ->addMethodCall('foo', array(new Reference('moo', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))) + ; + + $this->process($container); + + $arguments = $def->getArguments(); + $this->assertNull($arguments[0]); + $this->assertCount(0, $def->getMethodCalls()); + } + + public function testProcessIgnoreNonExistentServices() + { + $container = new ContainerBuilder(); + $def = $container + ->register('foo') + ->setArguments(array(new Reference('bar'))) + ; + + $this->process($container); + + $arguments = $def->getArguments(); + $this->assertEquals('bar', (string) $arguments[0]); + } + + public function testProcessRemovesPropertiesOnInvalid() + { + $container = new ContainerBuilder(); + $def = $container + ->register('foo') + ->setProperty('foo', new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)) + ; + + $this->process($container); + + $this->assertEquals(array(), $def->getProperties()); + } + + protected function process(ContainerBuilder $container) + { + $pass = new ResolveInvalidReferencesPass(); + $pass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php new file mode 100644 index 0000000..ca089a5 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Compiler\ResolveReferencesToAliasesPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class ResolveReferencesToAliasesPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container->setAlias('bar', 'foo'); + $def = $container + ->register('moo') + ->setArguments(array(new Reference('bar'))) + ; + + $this->process($container); + + $arguments = $def->getArguments(); + $this->assertEquals('foo', (string) $arguments[0]); + } + + public function testProcessRecursively() + { + $container = new ContainerBuilder(); + $container->setAlias('bar', 'foo'); + $container->setAlias('moo', 'bar'); + $def = $container + ->register('foobar') + ->setArguments(array(new Reference('moo'))) + ; + + $this->process($container); + + $arguments = $def->getArguments(); + $this->assertEquals('foo', (string) $arguments[0]); + } + + protected function process(ContainerBuilder $container) + { + $pass = new ResolveReferencesToAliasesPass(); + $pass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php new file mode 100644 index 0000000..bedcecb --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -0,0 +1,554 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests; + +require_once __DIR__.'/Fixtures/includes/classes.php'; +require_once __DIR__.'/Fixtures/includes/ProjectExtension.php'; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\Config\Resource\FileResource; + +class ContainerBuilderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinitions + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinitions + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinition + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinition + */ + public function testDefinitions() + { + $builder = new ContainerBuilder(); + $definitions = array( + 'foo' => new Definition('FooClass'), + 'bar' => new Definition('BarClass'), + ); + $builder->setDefinitions($definitions); + $this->assertEquals($definitions, $builder->getDefinitions(), '->setDefinitions() sets the service definitions'); + $this->assertTrue($builder->hasDefinition('foo'), '->hasDefinition() returns true if a service definition exists'); + $this->assertFalse($builder->hasDefinition('foobar'), '->hasDefinition() returns false if a service definition does not exist'); + + $builder->setDefinition('foobar', $foo = new Definition('FooBarClass')); + $this->assertEquals($foo, $builder->getDefinition('foobar'), '->getDefinition() returns a service definition if defined'); + $this->assertTrue($builder->setDefinition('foobar', $foo = new Definition('FooBarClass')) === $foo, '->setDefinition() implements a fluid interface by returning the service reference'); + + $builder->addDefinitions($defs = array('foobar' => new Definition('FooBarClass'))); + $this->assertEquals(array_merge($definitions, $defs), $builder->getDefinitions(), '->addDefinitions() adds the service definitions'); + + try { + $builder->getDefinition('baz'); + $this->fail('->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); + } catch (\InvalidArgumentException $e) { + $this->assertEquals('The service definition "baz" does not exist.', $e->getMessage(), '->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::register + */ + public function testRegister() + { + $builder = new ContainerBuilder(); + $builder->register('foo', 'FooClass'); + $this->assertTrue($builder->hasDefinition('foo'), '->register() registers a new service definition'); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $builder->getDefinition('foo'), '->register() returns the newly created Definition instance'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::has + */ + public function testHas() + { + $builder = new ContainerBuilder(); + $this->assertFalse($builder->has('foo'), '->has() returns false if the service does not exist'); + $builder->register('foo', 'FooClass'); + $this->assertTrue($builder->has('foo'), '->has() returns true if a service definition exists'); + $builder->set('bar', new \stdClass()); + $this->assertTrue($builder->has('bar'), '->has() returns true if a service exists'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get + */ + public function testGet() + { + $builder = new ContainerBuilder(); + try { + $builder->get('foo'); + $this->fail('->get() throws an InvalidArgumentException if the service does not exist'); + } catch (\InvalidArgumentException $e) { + $this->assertEquals('The service definition "foo" does not exist.', $e->getMessage(), '->get() throws an InvalidArgumentException if the service does not exist'); + } + + $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument'); + + $builder->register('foo', 'stdClass'); + $this->assertInternalType('object', $builder->get('foo'), '->get() returns the service definition associated with the id'); + $builder->set('bar', $bar = new \stdClass()); + $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id'); + $builder->register('bar', 'stdClass'); + $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined'); + + $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz'))); + try { + @$builder->get('baz'); + $this->fail('->get() throws a ServiceCircularReferenceException if the service has a circular reference to itself'); + } catch (\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException $e) { + $this->assertEquals('Circular reference detected for service "baz", path: "baz".', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself'); + } + + $builder->register('foobar', 'stdClass')->setScope('container'); + $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getServiceIds + */ + public function testGetServiceIds() + { + $builder = new ContainerBuilder(); + $builder->register('foo', 'stdClass'); + $builder->bar = $bar = new \stdClass(); + $builder->register('bar', 'stdClass'); + $this->assertEquals(array('foo', 'bar', 'service_container'), $builder->getServiceIds(), '->getServiceIds() returns all defined service ids'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAlias + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::hasAlias + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAlias + */ + public function testAliases() + { + $builder = new ContainerBuilder(); + $builder->register('foo', 'stdClass'); + $builder->setAlias('bar', 'foo'); + $this->assertTrue($builder->hasAlias('bar'), '->hasAlias() returns true if the alias exists'); + $this->assertFalse($builder->hasAlias('foobar'), '->hasAlias() returns false if the alias does not exist'); + $this->assertEquals('foo', (string) $builder->getAlias('bar'), '->getAlias() returns the aliased service'); + $this->assertTrue($builder->has('bar'), '->setAlias() defines a new service'); + $this->assertTrue($builder->get('bar') === $builder->get('foo'), '->setAlias() creates a service that is an alias to another one'); + + try { + $builder->getAlias('foobar'); + $this->fail('->getAlias() throws an InvalidArgumentException if the alias does not exist'); + } catch (\InvalidArgumentException $e) { + $this->assertEquals('The service alias "foobar" does not exist.', $e->getMessage(), '->getAlias() throws an InvalidArgumentException if the alias does not exist'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAliases + */ + public function testGetAliases() + { + $builder = new ContainerBuilder(); + $builder->setAlias('bar', 'foo'); + $builder->setAlias('foobar', 'foo'); + $builder->setAlias('moo', new Alias('foo', false)); + + $aliases = $builder->getAliases(); + $this->assertEquals('foo', (string) $aliases['bar']); + $this->assertTrue($aliases['bar']->isPublic()); + $this->assertEquals('foo', (string) $aliases['foobar']); + $this->assertEquals('foo', (string) $aliases['moo']); + $this->assertFalse($aliases['moo']->isPublic()); + + $builder->register('bar', 'stdClass'); + $this->assertFalse($builder->hasAlias('bar')); + + $builder->set('foobar', 'stdClass'); + $builder->set('moo', 'stdClass'); + $this->assertCount(0, $builder->getAliases(), '->getAliases() does not return aliased services that have been overridden'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAliases + */ + public function testSetAliases() + { + $builder = new ContainerBuilder(); + $builder->setAliases(array('bar' => 'foo', 'foobar' => 'foo')); + + $aliases = $builder->getAliases(); + $this->assertTrue(isset($aliases['bar'])); + $this->assertTrue(isset($aliases['foobar'])); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addAliases + */ + public function testAddAliases() + { + $builder = new ContainerBuilder(); + $builder->setAliases(array('bar' => 'foo')); + $builder->addAliases(array('foobar' => 'foo')); + + $aliases = $builder->getAliases(); + $this->assertTrue(isset($aliases['bar'])); + $this->assertTrue(isset($aliases['foobar'])); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addCompilerPass + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getCompilerPassConfig + */ + public function testAddGetCompilerPass() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $builder = new ContainerBuilder(); + $builderCompilerPasses = $builder->getCompiler()->getPassConfig()->getPasses(); + $builder->addCompilerPass($this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface')); + $this->assertEquals(sizeof($builderCompilerPasses) + 1, sizeof($builder->getCompiler()->getPassConfig()->getPasses())); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateService() + { + $builder = new ContainerBuilder(); + $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); + $this->assertInstanceOf('\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition'); + $builder->register('foo2', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/%file%.php'); + $builder->setParameter('file', 'foo'); + $this->assertInstanceOf('\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateServiceClass() + { + $builder = new ContainerBuilder(); + $builder->register('foo1', '%class%'); + $builder->setParameter('class', 'stdClass'); + $this->assertInstanceOf('\stdClass', $builder->get('foo1'), '->createService() replaces parameters in the class provided by the service definition'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateServiceArguments() + { + $builder = new ContainerBuilder(); + $builder->register('bar', 'stdClass'); + $builder->register('foo1', 'FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'))); + $builder->setParameter('value', 'bar'); + $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar')), $builder->get('foo1')->arguments, '->createService() replaces parameters and service references in the arguments provided by the service definition'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateServiceFactoryMethod() + { + $builder = new ContainerBuilder(); + $builder->register('bar', 'stdClass'); + $builder->register('foo1', 'FooClass')->setFactoryClass('FooClass')->setFactoryMethod('getInstance')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'))); + $builder->setParameter('value', 'bar'); + $this->assertTrue($builder->get('foo1')->called, '->createService() calls the factory method to create the service instance'); + $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar')), $builder->get('foo1')->arguments, '->createService() passes the arguments to the factory method'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateServiceFactoryService() + { + $builder = new ContainerBuilder(); + $builder->register('baz_service')->setFactoryService('baz_factory')->setFactoryMethod('getInstance'); + $builder->register('baz_factory', 'BazClass'); + + $this->assertInstanceOf('BazClass', $builder->get('baz_service')); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateServiceMethodCalls() + { + $builder = new ContainerBuilder(); + $builder->register('bar', 'stdClass'); + $builder->register('foo1', 'FooClass')->addMethodCall('setBar', array(array('%value%', new Reference('bar')))); + $builder->setParameter('value', 'bar'); + $this->assertEquals(array('bar', $builder->get('bar')), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateServiceConfigurator() + { + $builder = new ContainerBuilder(); + $builder->register('foo1', 'FooClass')->setConfigurator('sc_configure'); + $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator'); + + $builder->register('foo2', 'FooClass')->setConfigurator(array('%class%', 'configureStatic')); + $builder->setParameter('class', 'BazClass'); + $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator'); + + $builder->register('baz', 'BazClass'); + $builder->register('foo3', 'FooClass')->setConfigurator(array(new Reference('baz'), 'configure')); + $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator'); + + $builder->register('foo4', 'FooClass')->setConfigurator('foo'); + try { + $builder->get('foo4'); + $this->fail('->createService() throws an InvalidArgumentException if the configure callable is not a valid callable'); + } catch (\InvalidArgumentException $e) { + $this->assertEquals('The configure callable for class "FooClass" is not a callable.', $e->getMessage(), '->createService() throws an InvalidArgumentException if the configure callable is not a valid callable'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::resolveServices + */ + public function testResolveServices() + { + $builder = new ContainerBuilder(); + $builder->register('foo', 'FooClass'); + $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Reference('foo')), '->resolveServices() resolves service references to service instances'); + $this->assertEquals(array('foo' => array('foo', $builder->get('foo'))), $builder->resolveServices(array('foo' => array('foo', new Reference('foo')))), '->resolveServices() resolves service references to service instances in nested arrays'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge + */ + public function testMerge() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo'))); + $config = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); + $container->merge($config); + $this->assertEquals(array('bar' => 'foo', 'foo' => 'bar'), $container->getParameterBag()->all(), '->merge() merges current parameters with the loaded ones'); + + $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo'))); + $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%'))); + $container->merge($config); +////// FIXME + $container->compile(); + $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones'); + + $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo'))); + $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%', 'baz' => '%foo%'))); + $container->merge($config); +////// FIXME + $container->compile(); + $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo', 'baz' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones'); + + $container = new ContainerBuilder(); + $container->register('foo', 'FooClass'); + $container->register('bar', 'BarClass'); + $config = new ContainerBuilder(); + $config->setDefinition('baz', new Definition('BazClass')); + $config->setAlias('alias_for_foo', 'foo'); + $container->merge($config); + $this->assertEquals(array('foo', 'bar', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones'); + + $aliases = $container->getAliases(); + $this->assertTrue(isset($aliases['alias_for_foo'])); + $this->assertEquals('foo', (string) $aliases['alias_for_foo']); + + $container = new ContainerBuilder(); + $container->register('foo', 'FooClass'); + $config->setDefinition('foo', new Definition('BazClass')); + $container->merge($config); + $this->assertEquals('BazClass', $container->getDefinition('foo')->getClass(), '->merge() overrides already defined services'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge + * @expectedException LogicException + */ + public function testMergeLogicException() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + $container->compile(); + $container->merge(new ContainerBuilder()); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findTaggedServiceIds + */ + public function testfindTaggedServiceIds() + { + $builder = new ContainerBuilder(); + $builder + ->register('foo', 'FooClass') + ->addTag('foo', array('foo' => 'foo')) + ->addTag('bar', array('bar' => 'bar')) + ->addTag('foo', array('foofoo' => 'foofoo')) + ; + $this->assertEquals($builder->findTaggedServiceIds('foo'), array( + 'foo' => array( + array('foo' => 'foo'), + array('foofoo' => 'foofoo'), + ) + ), '->findTaggedServiceIds() returns an array of service ids and its tag attributes'); + $this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findDefinition + */ + public function testFindDefinition() + { + $container = new ContainerBuilder(); + $container->setDefinition('foo', $definition = new Definition('FooClass')); + $container->setAlias('bar', 'foo'); + $container->setAlias('foobar', 'bar'); + $this->assertEquals($definition, $container->findDefinition('foobar'), '->findDefinition() returns a Definition'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getResources + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addResource + */ + public function testResources() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + $container->addResource($a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml')); + $container->addResource($b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml')); + $resources = array(); + foreach ($container->getResources() as $resource) { + if (false === strpos($resource, '.php')) { + $resources[] = $resource; + } + } + $this->assertEquals(array($a, $b), $resources, '->getResources() returns an array of resources read for the current configuration'); + $this->assertSame($container, $container->setResources(array())); + $this->assertEquals(array(), $container->getResources()); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::registerExtension + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtension + */ + public function testExtension() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + + $container->registerExtension($extension = new \ProjectExtension()); + $this->assertTrue($container->getExtension('project') === $extension, '->registerExtension() registers an extension'); + + $this->setExpectedException('LogicException'); + $container->getExtension('no_registered'); + } + + public function testRegisteredButNotLoadedExtension() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface'); + $extension->expects($this->once())->method('getAlias')->will($this->returnValue('project')); + $extension->expects($this->never())->method('load'); + + $container = new ContainerBuilder(); + $container->registerExtension($extension); + $container->compile(); + } + + public function testRegisteredAndLoadedExtension() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface'); + $extension->expects($this->exactly(2))->method('getAlias')->will($this->returnValue('project')); + $extension->expects($this->once())->method('load')->with(array(array('foo' => 'bar'))); + + $container = new ContainerBuilder(); + $container->registerExtension($extension); + $container->loadFromExtension('project', array('foo' => 'bar')); + $container->compile(); + } + + public function testPrivateServiceUser() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $fooDefinition = new Definition('BarClass'); + $fooUserDefinition = new Definition('BarUserClass', array(new Reference('bar'))); + $container = new ContainerBuilder(); + + $fooDefinition->setPublic(false); + + $container->addDefinitions(array( + 'bar' => $fooDefinition, + 'bar_user' => $fooUserDefinition + )); + + $container->compile(); + $this->assertInstanceOf('BarClass', $container->get('bar_user')->bar); + } + + /** + * @expectedException BadMethodCallException + */ + public function testThrowsExceptionWhenSetServiceOnAFrozenContainer() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + $container->compile(); + $container->set('a', new \stdClass()); + } + + /** + * @expectedException BadMethodCallException + */ + public function testThrowsExceptionWhenSetDefinitionOnAFrozenContainer() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + $container->compile(); + $container->setDefinition('a', new Definition()); + } +} + + +class FooClass {} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/ContainerTest.php new file mode 100644 index 0000000..1be5106 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -0,0 +1,450 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests; + +use Symfony\Component\DependencyInjection\Scope; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; + +class ContainerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\Container::__construct + */ + public function testConstructor() + { + $sc = new Container(); + $this->assertSame($sc, $sc->get('service_container'), '__construct() automatically registers itself as a service'); + + $sc = new Container(new ParameterBag(array('foo' => 'bar'))); + $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '__construct() takes an array of parameters as its first argument'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::compile + */ + public function testCompile() + { + $sc = new Container(new ParameterBag(array('foo' => 'bar'))); + $sc->compile(); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag', $sc->getParameterBag(), '->compile() changes the parameter bag to a FrozenParameterBag instance'); + $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '->compile() copies the current parameters to the new parameter bag'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::isFrozen + */ + public function testIsFrozen() + { + $sc = new Container(new ParameterBag(array('foo' => 'bar'))); + $this->assertFalse($sc->isFrozen(), '->isFrozen() returns false if the parameters are not frozen'); + $sc->compile(); + $this->assertTrue($sc->isFrozen(), '->isFrozen() returns true if the parameters are frozen'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::getParameterBag + */ + public function testGetParameterBag() + { + $sc = new Container(); + $this->assertEquals(array(), $sc->getParameterBag()->all(), '->getParameterBag() returns an empty array if no parameter has been defined'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::setParameter + * @covers Symfony\Component\DependencyInjection\Container::getParameter + */ + public function testGetSetParameter() + { + $sc = new Container(new ParameterBag(array('foo' => 'bar'))); + $sc->setParameter('bar', 'foo'); + $this->assertEquals('foo', $sc->getParameter('bar'), '->setParameter() sets the value of a new parameter'); + + $sc->setParameter('foo', 'baz'); + $this->assertEquals('baz', $sc->getParameter('foo'), '->setParameter() overrides previously set parameter'); + + $sc->setParameter('Foo', 'baz1'); + $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase'); + $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase'); + + try { + $sc->getParameter('baba'); + $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); + $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::getServiceIds + */ + public function testGetServiceIds() + { + $sc = new Container(); + $sc->set('foo', $obj = new \stdClass()); + $sc->set('bar', $obj = new \stdClass()); + $this->assertEquals(array('service_container', 'foo', 'bar'), $sc->getServiceIds(), '->getServiceIds() returns all defined service ids'); + + $sc = new ProjectServiceContainer(); + $this->assertEquals(array('scoped', 'scoped_foo', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'service_container'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::set + */ + public function testSet() + { + $sc = new Container(); + $sc->set('foo', $foo = new \stdClass()); + $this->assertEquals($foo, $sc->get('foo'), '->set() sets a service'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testSetDoesNotAllowPrototypeScope() + { + $c = new Container(); + $c->set('foo', new \stdClass(), 'prototype'); + } + + /** + * @expectedException \RuntimeException + */ + public function testSetDoesNotAllowInactiveScope() + { + $c = new Container(); + $c->addScope(new Scope('foo')); + $c->set('foo', new \stdClass(), 'foo'); + } + + public function testSetAlsoSetsScopedService() + { + $c = new Container(); + $c->addScope(new Scope('foo')); + $c->enterScope('foo'); + $c->set('foo', $foo = new \stdClass(), 'foo'); + + $services = $this->getField($c, 'scopedServices'); + $this->assertTrue(isset($services['foo']['foo'])); + $this->assertSame($foo, $services['foo']['foo']); + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::get + */ + public function testGet() + { + $sc = new ProjectServiceContainer(); + $sc->set('foo', $foo = new \stdClass()); + $this->assertEquals($foo, $sc->get('foo'), '->get() returns the service for the given id'); + $this->assertEquals($sc->__bar, $sc->get('bar'), '->get() returns the service for the given id'); + $this->assertEquals($sc->__foo_bar, $sc->get('foo_bar'), '->get() returns the service if a get*Method() is defined'); + $this->assertEquals($sc->__foo_baz, $sc->get('foo.baz'), '->get() returns the service if a get*Method() is defined'); + + $sc->set('bar', $bar = new \stdClass()); + $this->assertEquals($bar, $sc->get('bar'), '->get() prefers to return a service defined with set() than one defined with a getXXXMethod()'); + + try { + $sc->get(''); + $this->fail('->get() throws a \InvalidArgumentException exception if the service is empty'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws a ServiceNotFoundException exception if the service is empty'); + } + $this->assertNull($sc->get('', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + } + + public function testGetCircularReference() + { + + $sc = new ProjectServiceContainer(); + try { + $sc->get('circular'); + $this->fail('->get() throws a ServiceCircularReferenceException if it contains circular reference'); + } catch (\Exception $e) { + $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException', $e, '->get() throws a ServiceCircularReferenceException if it contains circular reference'); + $this->assertStringStartsWith('Circular reference detected for service "circular"', $e->getMessage(), '->get() throws a \LogicException if it contains circular reference'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::has + */ + public function testHas() + { + $sc = new ProjectServiceContainer(); + $sc->set('foo', new \stdClass()); + $this->assertFalse($sc->has('foo1'), '->has() returns false if the service does not exist'); + $this->assertTrue($sc->has('foo'), '->has() returns true if the service exists'); + $this->assertTrue($sc->has('bar'), '->has() returns true if a get*Method() is defined'); + $this->assertTrue($sc->has('foo_bar'), '->has() returns true if a get*Method() is defined'); + $this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Container::initialized + */ + public function testInitialized() + { + $sc = new ProjectServiceContainer(); + $sc->set('foo', new \stdClass()); + $this->assertTrue($sc->initialized('foo'), '->initialized() returns true if service is loaded'); + $this->assertFalse($sc->initialized('foo1'), '->initialized() returns false if service is not loaded'); + $this->assertFalse($sc->initialized('bar'), '->initialized() returns false if a service is defined, but not currently loaded'); + } + + public function testEnterLeaveCurrentScope() + { + $container = new ProjectServiceContainer(); + $container->addScope(new Scope('foo')); + + $container->enterScope('foo'); + $scoped1 = $container->get('scoped'); + $scopedFoo1 = $container->get('scoped_foo'); + + $container->enterScope('foo'); + $scoped2 = $container->get('scoped'); + $scoped3 = $container->get('scoped'); + $scopedFoo2 = $container->get('scoped_foo'); + + $container->leaveScope('foo'); + $scoped4 = $container->get('scoped'); + $scopedFoo3 = $container->get('scoped_foo'); + + $this->assertNotSame($scoped1, $scoped2); + $this->assertSame($scoped2, $scoped3); + $this->assertSame($scoped1, $scoped4); + $this->assertNotSame($scopedFoo1, $scopedFoo2); + $this->assertSame($scopedFoo1, $scopedFoo3); + } + + public function testEnterLeaveScopeWithChildScopes() + { + $container = new Container(); + $container->addScope(new Scope('foo')); + $container->addScope(new Scope('bar', 'foo')); + + $this->assertFalse($container->isScopeActive('foo')); + + $container->enterScope('foo'); + $container->enterScope('bar'); + + $this->assertTrue($container->isScopeActive('foo')); + $this->assertFalse($container->has('a')); + + $a = new \stdClass(); + $container->set('a', $a, 'bar'); + + $services = $this->getField($container, 'scopedServices'); + $this->assertTrue(isset($services['bar']['a'])); + $this->assertSame($a, $services['bar']['a']); + + $this->assertTrue($container->has('a')); + $container->leaveScope('foo'); + + $services = $this->getField($container, 'scopedServices'); + $this->assertFalse(isset($services['bar'])); + + $this->assertFalse($container->isScopeActive('foo')); + $this->assertFalse($container->has('a')); + } + + public function testLeaveScopeNotActive() + { + $container = new Container(); + $container->addScope(new Scope('foo')); + + try { + $container->leaveScope('foo'); + $this->fail('->leaveScope() throws a \LogicException if the scope is not active yet'); + } catch (\Exception $e) { + $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope is not active yet'); + $this->assertEquals('The scope "foo" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope is not active yet'); + } + + try { + $container->leaveScope('bar'); + $this->fail('->leaveScope() throws a \LogicException if the scope does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope does not exist'); + $this->assertEquals('The scope "bar" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope does not exist'); + } + } + + /** + * @expectedException \InvalidArgumentException + * @dataProvider getBuiltInScopes + */ + public function testAddScopeDoesNotAllowBuiltInScopes($scope) + { + $container = new Container(); + $container->addScope(new Scope($scope)); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testAddScopeDoesNotAllowExistingScope() + { + $container = new Container(); + $container->addScope(new Scope('foo')); + $container->addScope(new Scope('foo')); + } + + /** + * @expectedException \InvalidArgumentException + * @dataProvider getInvalidParentScopes + */ + public function testAddScopeDoesNotAllowInvalidParentScope($scope) + { + $c = new Container(); + $c->addScope(new Scope('foo', $scope)); + } + + public function testAddScope() + { + $c = new Container(); + $c->addScope(new Scope('foo')); + $c->addScope(new Scope('bar', 'foo')); + + $this->assertSame(array('foo' => 'container', 'bar' => 'foo'), $this->getField($c, 'scopes')); + $this->assertSame(array('foo' => array('bar'), 'bar' => array()), $this->getField($c, 'scopeChildren')); + } + + public function testHasScope() + { + $c = new Container(); + + $this->assertFalse($c->hasScope('foo')); + $c->addScope(new Scope('foo')); + $this->assertTrue($c->hasScope('foo')); + } + + public function testIsScopeActive() + { + $c = new Container(); + + $this->assertFalse($c->isScopeActive('foo')); + $c->addScope(new Scope('foo')); + + $this->assertFalse($c->isScopeActive('foo')); + $c->enterScope('foo'); + + $this->assertTrue($c->isScopeActive('foo')); + $c->leaveScope('foo'); + + $this->assertFalse($c->isScopeActive('foo')); + } + + public function testGetThrowsException() + { + $c = new ProjectServiceContainer(); + + try { + $c->get('throw_exception'); + $this->fail(); + } catch (\Exception $e) { + $this->assertEquals('Something went terribly wrong!', $e->getMessage()); + } + + try { + $c->get('throw_exception'); + $this->fail(); + } catch (\Exception $e) { + $this->assertEquals('Something went terribly wrong!', $e->getMessage()); + } + } + + public function getInvalidParentScopes() + { + return array( + array(ContainerInterface::SCOPE_PROTOTYPE), + array('bar'), + ); + } + + public function getBuiltInScopes() + { + return array( + array(ContainerInterface::SCOPE_CONTAINER), + array(ContainerInterface::SCOPE_PROTOTYPE), + ); + } + + protected function getField($obj, $field) + { + $reflection = new \ReflectionProperty($obj, $field); + $reflection->setAccessible(true); + + return $reflection->getValue($obj); + } +} + +class ProjectServiceContainer extends Container +{ + public $__bar, $__foo_bar, $__foo_baz; + + public function __construct() + { + parent::__construct(); + + $this->__bar = new \stdClass(); + $this->__foo_bar = new \stdClass(); + $this->__foo_baz = new \stdClass(); + } + + protected function getScopedService() + { + if (!isset($this->scopedServices['foo'])) { + throw new \RuntimeException('Invalid call'); + } + + return $this->services['scoped'] = $this->scopedServices['foo']['scoped'] = new \stdClass(); + } + + protected function getScopedFooService() + { + if (!isset($this->scopedServices['foo'])) { + throw new \RuntimeException('invalid call'); + } + + return $this->services['scoped_foo'] = $this->scopedServices['foo']['scoped_foo'] = new \stdClass(); + } + + protected function getBarService() + { + return $this->__bar; + } + + protected function getFooBarService() + { + return $this->__foo_bar; + } + + protected function getFoo_BazService() + { + return $this->__foo_baz; + } + + protected function getCircularService() + { + return $this->get('circular'); + } + + protected function getThrowExceptionService() + { + throw new \Exception('Something went terribly wrong!'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php new file mode 100644 index 0000000..557c207 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Config\FileLocator; + +class CrossCheckTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + static public function setUpBeforeClass() + { + self::$fixturesPath = __DIR__.'/Fixtures/'; + + require_once self::$fixturesPath.'/includes/classes.php'; + require_once self::$fixturesPath.'/includes/foo.php'; + } + + /** + * @dataProvider crossCheckLoadersDumpers + */ + public function testCrossCheck($fixture, $type) + { + $loaderClass = 'Symfony\\Component\\DependencyInjection\\Loader\\'.ucfirst($type).'FileLoader'; + $dumperClass = 'Symfony\\Component\\DependencyInjection\\Dumper\\'.ucfirst($type).'Dumper'; + + $tmp = tempnam('sf_service_container', 'sf'); + + file_put_contents($tmp, file_get_contents(self::$fixturesPath.'/'.$type.'/'.$fixture)); + + $container1 = new ContainerBuilder(); + $loader1 = new $loaderClass($container1, new FileLocator()); + $loader1->load($tmp); + + $dumper = new $dumperClass($container1); + file_put_contents($tmp, $dumper->dump()); + + $container2 = new ContainerBuilder(); + $loader2 = new $loaderClass($container2, new FileLocator()); + $loader2->load($tmp); + + unlink($tmp); + + $this->assertEquals($container2->getAliases(), $container1->getAliases(), 'loading a dump from a previously loaded container returns the same container'); + $this->assertEquals($container2->getDefinitions(), $container1->getDefinitions(), 'loading a dump from a previously loaded container returns the same container'); + $this->assertEquals($container2->getParameterBag()->all(), $container1->getParameterBag()->all(), '->getParameterBag() returns the same value for both containers'); + + $this->assertEquals(serialize($container2), serialize($container1), 'loading a dump from a previously loaded container returns the same container'); + + $services1 = array(); + foreach ($container1 as $id => $service) { + $services1[$id] = serialize($service); + } + $services2 = array(); + foreach ($container2 as $id => $service) { + $services2[$id] = serialize($service); + } + + unset($services1['service_container'], $services2['service_container']); + + $this->assertEquals($services2, $services1, 'Iterator on the containers returns the same services'); + } + + public function crossCheckLoadersDumpers() + { + return array( + array('services1.xml', 'xml'), + array('services2.xml', 'xml'), + array('services6.xml', 'xml'), + array('services8.xml', 'xml'), + array('services9.xml', 'xml'), + + array('services1.yml', 'yaml'), + array('services2.yml', 'yaml'), + array('services6.yml', 'yaml'), + array('services8.yml', 'yaml'), + array('services9.yml', 'yaml'), + ); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php new file mode 100644 index 0000000..bf1bab1 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests; + +use Symfony\Component\DependencyInjection\DefinitionDecorator; + +class DefinitionDecoratorTest extends \PHPUnit_Framework_TestCase +{ + public function testConstructor() + { + $def = new DefinitionDecorator('foo'); + + $this->assertEquals('foo', $def->getParent()); + $this->assertEquals(array(), $def->getChanges()); + } + + /** + * @dataProvider getPropertyTests + */ + public function testSetProperty($property, $changeKey) + { + $def = new DefinitionDecorator('foo'); + + $getter = 'get'.ucfirst($property); + $setter = 'set'.ucfirst($property); + + $this->assertNull($def->$getter()); + $this->assertSame($def, $def->$setter('foo')); + $this->assertEquals('foo', $def->$getter()); + $this->assertEquals(array($changeKey => true), $def->getChanges()); + } + + public function getPropertyTests() + { + return array( + array('class', 'class'), + array('factoryClass', 'factory_class'), + array('factoryMethod', 'factory_method'), + array('factoryService', 'factory_service'), + array('configurator', 'configurator'), + array('file', 'file'), + ); + } + + public function testSetPublic() + { + $def = new DefinitionDecorator('foo'); + + $this->assertTrue($def->isPublic()); + $this->assertSame($def, $def->setPublic(false)); + $this->assertFalse($def->isPublic()); + $this->assertEquals(array('public' => true), $def->getChanges()); + } + + public function testSetArgument() + { + $def = new DefinitionDecorator('foo'); + + $this->assertEquals(array(), $def->getArguments()); + $this->assertSame($def, $def->replaceArgument(0, 'foo')); + $this->assertEquals(array('index_0' => 'foo'), $def->getArguments()); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testReplaceArgumentShouldRequireIntegerIndex() + { + $def = new DefinitionDecorator('foo'); + + $def->replaceArgument('0', 'foo'); + } + + public function testReplaceArgument() + { + $def = new DefinitionDecorator('foo'); + + $def->setArguments(array(0 => 'foo', 1 => 'bar')); + $this->assertEquals('foo', $def->getArgument(0)); + $this->assertEquals('bar', $def->getArgument(1)); + + $this->assertSame($def, $def->replaceArgument(1, 'baz')); + $this->assertEquals('foo', $def->getArgument(0)); + $this->assertEquals('baz', $def->getArgument(1)); + + $this->assertEquals(array(0 => 'foo', 1 => 'bar', 'index_1' => 'baz'), $def->getArguments()); + } + + /** + * @expectedException OutOfBoundsException + */ + public function testGetArgumentShouldCheckBounds() + { + $def = new DefinitionDecorator('foo'); + + $def->setArguments(array(0 => 'foo')); + $def->replaceArgument(0, 'foo'); + + $def->getArgument(1); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php new file mode 100644 index 0000000..46ea75d --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -0,0 +1,292 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests; + +use Symfony\Component\DependencyInjection\Definition; + +class DefinitionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\Definition::__construct + */ + public function testConstructor() + { + $def = new Definition('stdClass'); + $this->assertEquals('stdClass', $def->getClass(), '__construct() takes the class name as its first argument'); + + $def = new Definition('stdClass', array('foo')); + $this->assertEquals(array('foo'), $def->getArguments(), '__construct() takes an optional array of arguments as its second argument'); + } + + public function testSetGetFactoryClass() + { + $def = new Definition('stdClass'); + $this->assertNull($def->getFactoryClass()); + $this->assertSame($def, $def->setFactoryClass('stdClass2'), "->setFactoryClass() implements a fluent interface."); + $this->assertEquals('stdClass2', $def->getFactoryClass(), "->getFactoryClass() returns current class to construct this service."); + } + + public function testSetGetFactoryMethod() + { + $def = new Definition('stdClass'); + $this->assertNull($def->getFactoryMethod()); + $this->assertSame($def, $def->setFactoryMethod('foo'), '->setFactoryMethod() implements a fluent interface'); + $this->assertEquals('foo', $def->getFactoryMethod(), '->getFactoryMethod() returns the factory method name'); + } + + public function testSetGetFactoryService() + { + $def = new Definition('stdClass'); + $this->assertNull($def->getFactoryService()); + $this->assertSame($def, $def->setFactoryService('foo.bar'), "->setFactoryService() implements a fluent interface."); + $this->assertEquals('foo.bar', $def->getFactoryService(), "->getFactoryService() returns current service to construct this service."); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setClass + * @covers Symfony\Component\DependencyInjection\Definition::getClass + */ + public function testSetGetClass() + { + $def = new Definition('stdClass'); + $this->assertSame($def, $def->setClass('foo'), '->setClass() implements a fluent interface'); + $this->assertEquals('foo', $def->getClass(), '->getClass() returns the class name'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setArguments + * @covers Symfony\Component\DependencyInjection\Definition::getArguments + * @covers Symfony\Component\DependencyInjection\Definition::addArgument + */ + public function testArguments() + { + $def = new Definition('stdClass'); + $this->assertSame($def, $def->setArguments(array('foo')), '->setArguments() implements a fluent interface'); + $this->assertEquals(array('foo'), $def->getArguments(), '->getArguments() returns the arguments'); + $this->assertSame($def, $def->addArgument('bar'), '->addArgument() implements a fluent interface'); + $this->assertEquals(array('foo', 'bar'), $def->getArguments(), '->addArgument() adds an argument'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setMethodCalls + * @covers Symfony\Component\DependencyInjection\Definition::addMethodCall + * @covers Symfony\Component\DependencyInjection\Definition::hasMethodCall + * @covers Symfony\Component\DependencyInjection\Definition::removeMethodCall + */ + public function testMethodCalls() + { + $def = new Definition('stdClass'); + $this->assertSame($def, $def->setMethodCalls(array(array('foo', array('foo')))), '->setMethodCalls() implements a fluent interface'); + $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->getMethodCalls() returns the methods to call'); + $this->assertSame($def, $def->addMethodCall('bar', array('bar')), '->addMethodCall() implements a fluent interface'); + $this->assertEquals(array(array('foo', array('foo')), array('bar', array('bar'))), $def->getMethodCalls(), '->addMethodCall() adds a method to call'); + $this->assertTrue($def->hasMethodCall('bar'), '->hasMethodCall() returns true if first argument is a method to call registered'); + $this->assertFalse($def->hasMethodCall('no_registered'), '->hasMethodCall() returns false if first argument is not a method to call registered'); + $this->assertSame($def, $def->removeMethodCall('bar'), '->removeMethodCall() implements a fluent interface'); + $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->removeMethodCall() removes a method to call'); + } + + /** + * @expectedException Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Method name cannot be empty. + */ + public function testExceptionOnEmptyMethodCall() + { + $def = new Definition('stdClass'); + $def->addMethodCall(''); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setFile + * @covers Symfony\Component\DependencyInjection\Definition::getFile + */ + public function testSetGetFile() + { + $def = new Definition('stdClass'); + $this->assertSame($def, $def->setFile('foo'), '->setFile() implements a fluent interface'); + $this->assertEquals('foo', $def->getFile(), '->getFile() returns the file to include'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setScope + * @covers Symfony\Component\DependencyInjection\Definition::getScope + */ + public function testSetGetScope() + { + $def = new Definition('stdClass'); + $this->assertEquals('container', $def->getScope()); + $this->assertSame($def, $def->setScope('foo')); + $this->assertEquals('foo', $def->getScope()); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setPublic + * @covers Symfony\Component\DependencyInjection\Definition::isPublic + */ + public function testSetIsPublic() + { + $def = new Definition('stdClass'); + $this->assertTrue($def->isPublic(), '->isPublic() returns true by default'); + $this->assertSame($def, $def->setPublic(false), '->setPublic() implements a fluent interface'); + $this->assertFalse($def->isPublic(), '->isPublic() returns false if the instance must not be public.'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setSynthetic + * @covers Symfony\Component\DependencyInjection\Definition::isSynthetic + */ + public function testSetIsSynthetic() + { + $def = new Definition('stdClass'); + $this->assertFalse($def->isSynthetic(), '->isSynthetic() returns false by default'); + $this->assertSame($def, $def->setSynthetic(true), '->setSynthetic() implements a fluent interface'); + $this->assertTrue($def->isSynthetic(), '->isSynthetic() returns true if the instance must not be public.'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setAbstract + * @covers Symfony\Component\DependencyInjection\Definition::isAbstract + */ + public function testSetIsAbstract() + { + $def = new Definition('stdClass'); + $this->assertFalse($def->isAbstract(), '->isAbstract() returns false by default'); + $this->assertSame($def, $def->setAbstract(true), '->setAbstract() implements a fluent interface'); + $this->assertTrue($def->isAbstract(), '->isAbstract() returns true if the instance must not be public.'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::setConfigurator + * @covers Symfony\Component\DependencyInjection\Definition::getConfigurator + */ + public function testSetGetConfigurator() + { + $def = new Definition('stdClass'); + $this->assertSame($def, $def->setConfigurator('foo'), '->setConfigurator() implements a fluent interface'); + $this->assertEquals('foo', $def->getConfigurator(), '->getConfigurator() returns the configurator'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::clearTags + */ + public function testClearTags() + { + $def = new Definition('stdClass'); + $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface'); + $def->addTag('foo', array('foo' => 'bar')); + $def->clearTags(); + $this->assertEquals(array(), $def->getTags(), '->clearTags() removes all current tags'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::clearTags + */ + public function testClearTag() + { + $def = new Definition('stdClass'); + $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface'); + $def->addTag('1foo1', array('foo1' => 'bar1')); + $def->addTag('2foo2', array('foo2' => 'bar2')); + $def->addTag('3foo3', array('foo3' => 'bar3')); + $def->clearTag('2foo2'); + $this->assertTrue($def->hasTag('1foo1')); + $this->assertFalse($def->hasTag('2foo2')); + $this->assertTrue($def->hasTag('3foo3')); + $def->clearTag('1foo1'); + $this->assertFalse($def->hasTag('1foo1')); + $this->assertTrue($def->hasTag('3foo3')); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::addTag + * @covers Symfony\Component\DependencyInjection\Definition::getTag + * @covers Symfony\Component\DependencyInjection\Definition::getTags + * @covers Symfony\Component\DependencyInjection\Definition::hasTag + */ + public function testTags() + { + $def = new Definition('stdClass'); + $this->assertEquals(array(), $def->getTag('foo'), '->getTag() returns an empty array if the tag is not defined'); + $this->assertFalse($def->hasTag('foo')); + $this->assertSame($def, $def->addTag('foo'), '->addTag() implements a fluent interface'); + $this->assertTrue($def->hasTag('foo')); + $this->assertEquals(array(array()), $def->getTag('foo'), '->getTag() returns attributes for a tag name'); + $def->addTag('foo', array('foo' => 'bar')); + $this->assertEquals(array(array(), array('foo' => 'bar')), $def->getTag('foo'), '->addTag() can adds the same tag several times'); + $def->addTag('bar', array('bar' => 'bar')); + $this->assertEquals($def->getTags(), array( + 'foo' => array(array(), array('foo' => 'bar')), + 'bar' => array(array('bar' => 'bar')), + ), '->getTags() returns all tags'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Definition::replaceArgument + */ + public function testSetArgument() + { + $def = new Definition('stdClass'); + + $def->addArgument('foo'); + $this->assertSame(array('foo'), $def->getArguments()); + + $this->assertSame($def, $def->replaceArgument(0, 'moo')); + $this->assertSame(array('moo'), $def->getArguments()); + + $def->addArgument('moo'); + $def + ->replaceArgument(0, 'foo') + ->replaceArgument(1, 'bar') + ; + $this->assertSame(array('foo', 'bar'), $def->getArguments()); + } + + /** + * @expectedException OutOfBoundsException + */ + public function testGetArgumentShouldCheckBounds() + { + $def = new Definition('stdClass'); + + $def->addArgument('foo'); + $def->getArgument(1); + } + + /** + * @expectedException OutOfBoundsException + */ + public function testReplaceArgumentShouldCheckBounds() + { + $def = new Definition('stdClass'); + + $def->addArgument('foo'); + $def->replaceArgument(1, 'bar'); + } + + public function testSetGetProperties() + { + $def = new Definition('stdClass'); + + $this->assertEquals(array(), $def->getProperties()); + $this->assertSame($def, $def->setProperties(array('foo' => 'bar'))); + $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); + } + + public function testSetProperty() + { + $def = new Definition('stdClass'); + + $this->assertEquals(array(), $def->getProperties()); + $this->assertSame($def, $def->setProperty('foo', 'bar')); + $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php new file mode 100644 index 0000000..69e775d --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Dumper; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\GraphvizDumper; + +class GraphvizDumperTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + static public function setUpBeforeClass() + { + self::$fixturesPath = __DIR__.'/../Fixtures/'; + } + + public function testDump() + { + $dumper = new GraphvizDumper($container = new ContainerBuilder()); + + $this->assertStringEqualsFile(self::$fixturesPath.'/graphviz/services1.dot', $dumper->dump(), '->dump() dumps an empty container as an empty dot file'); + + $container = include self::$fixturesPath.'/containers/container9.php'; + $dumper = new GraphvizDumper($container); + $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services9.dot')), $dumper->dump(), '->dump() dumps services'); + + $container = include self::$fixturesPath.'/containers/container10.php'; + $dumper = new GraphvizDumper($container); + $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10.dot')), $dumper->dump(), '->dump() dumps services'); + + $container = include self::$fixturesPath.'/containers/container10.php'; + $dumper = new GraphvizDumper($container); + $this->assertEquals($dumper->dump(array( + 'graph' => array('ratio' => 'normal'), + 'node' => array('fontsize' => 13, 'fontname' => 'Verdana', 'shape' => 'square'), + 'edge' => array('fontsize' => 12, 'fontname' => 'Verdana', 'color' => 'white', 'arrowhead' => 'closed', 'arrowsize' => 1), + 'node.instance' => array('fillcolor' => 'green', 'style' => 'empty'), + 'node.definition' => array('fillcolor' => 'grey'), + 'node.missing' => array('fillcolor' => 'red', 'style' => 'empty'), + )), str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10-1.dot')), '->dump() dumps services'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php new file mode 100644 index 0000000..a072356 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Dumper; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Definition; + +class PhpDumperTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + static public function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); + } + + public function testDump() + { + $dumper = new PhpDumper($container = new ContainerBuilder()); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class'); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1-1.php', $dumper->dump(array('class' => 'Container', 'base_class' => 'AbstractContainer')), '->dump() takes a class and a base_class options'); + + $container = new ContainerBuilder(); + new PhpDumper($container); + } + + public function testDumpOptimizationString() + { + $definition = new Definition(); + $definition->setClass('stdClass'); + $definition->addArgument(array( + 'only dot' => '.', + 'concatenation as value' => '.\'\'.', + 'concatenation from the start value' => '\'\'.', + '.' => 'dot as a key', + '.\'\'.' => 'concatenation as a key', + '\'\'.' =>'concatenation from the start key', + 'optimize concatenation' => "string1%some_string%string2", + 'optimize concatenation with empty string' => "string1%empty_value%string2", + 'optimize concatenation from the start' => '%empty_value%start', + 'optimize concatenation at the end' => 'end%empty_value%', + )); + + $container = new ContainerBuilder(); + $container->setDefinition('test', $definition); + $container->setParameter('empty_value', ''); + $container->setParameter('some_string', '-'); + $container->compile(); + + $dumper = new PhpDumper($container); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services10.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testExportParameters() + { + $dumper = new PhpDumper(new ContainerBuilder(new ParameterBag(array('foo' => new Reference('foo'))))); + $dumper->dump(); + } + + public function testAddParameters() + { + $container = include self::$fixturesPath.'/containers/container8.php'; + $dumper = new PhpDumper($container); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services8.php', $dumper->dump(), '->dump() dumps parameters'); + } + + public function testAddService() + { + $container = include self::$fixturesPath.'/containers/container9.php'; + $dumper = new PhpDumper($container); + $this->assertEquals(str_replace('%path%', str_replace('\\','\\\\',self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services'); + + $dumper = new PhpDumper($container = new ContainerBuilder()); + $container->register('foo', 'FooClass')->addArgument(new \stdClass()); + try { + $dumper->dump(); + $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + } catch (\Exception $e) { + $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + } + } + + public function testOverrideServiceWhenUsingADumpedContainer() + { + require_once self::$fixturesPath.'/php/services9.php'; + require_once self::$fixturesPath.'/includes/foo.php'; + + $container = new \ProjectServiceContainer(); + $container->set('bar', $bar = new \stdClass()); + $container->setParameter('foo_bar', 'foo_bar'); + + $this->assertEquals($bar, $container->get('bar'), '->set() overrides an already defined service'); + } + + public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne() + { + require_once self::$fixturesPath.'/php/services9.php'; + require_once self::$fixturesPath.'/includes/foo.php'; + require_once self::$fixturesPath.'/includes/classes.php'; + + $container = new \ProjectServiceContainer(); + $container->set('bar', $bar = new \stdClass()); + + $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php new file mode 100644 index 0000000..6618982 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Dumper; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\XmlDumper; + +class XmlDumperTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + static public function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); + } + + public function testDump() + { + $dumper = new XmlDumper($container = new ContainerBuilder()); + + $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services1.xml', $dumper->dump(), '->dump() dumps an empty container as an empty XML file'); + + $container = new ContainerBuilder(); + $dumper = new XmlDumper($container); + } + + public function testExportParameters() + { + $container = include self::$fixturesPath.'//containers/container8.php'; + $dumper = new XmlDumper($container); + $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters'); + } + + public function testAddParameters() + { + $container = include self::$fixturesPath.'//containers/container8.php'; + $dumper = new XmlDumper($container); + $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters'); + } + + public function testAddService() + { + $container = include self::$fixturesPath.'/containers/container9.php'; + $dumper = new XmlDumper($container); + $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/xml/services9.xml')), $dumper->dump(), '->dump() dumps services'); + + $dumper = new XmlDumper($container = new ContainerBuilder()); + $container->register('foo', 'FooClass')->addArgument(new \stdClass()); + try { + $dumper->dump(); + $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + } catch (\Exception $e) { + $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + } + } + + public function testDumpAnonymousServices() + { + include self::$fixturesPath.'/containers/container11.php'; + $dumper = new XmlDumper($container); + $this->assertEquals(" + + + + + + + + + + + + + +", $dumper->dump()); + } + + public function testDumpEntities() + { + include self::$fixturesPath.'/containers/container12.php'; + $dumper = new XmlDumper($container); + $this->assertEquals(" + + + + + foo<>&bar + + + +", $dumper->dump()); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php new file mode 100644 index 0000000..2dcb3b8 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Dumper; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\YamlDumper; + +class YamlDumperTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + static public function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); + } + + public function testDump() + { + $dumper = new YamlDumper($container = new ContainerBuilder()); + + $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services1.yml', $dumper->dump(), '->dump() dumps an empty container as an empty YAML file'); + + $container = new ContainerBuilder(); + $dumper = new YamlDumper($container); + } + + public function testAddParameters() + { + $container = include self::$fixturesPath.'/containers/container8.php'; + $dumper = new YamlDumper($container); + $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services8.yml', $dumper->dump(), '->dump() dumps parameters'); + } + + public function testAddService() + { + $container = include self::$fixturesPath.'/containers/container9.php'; + $dumper = new YamlDumper($container); + $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services'); + + $dumper = new YamlDumper($container = new ContainerBuilder()); + $container->register('foo', 'FooClass')->addArgument(new \stdClass()); + try { + $dumper->dump(); + $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + } catch (\Exception $e) { + $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); + } + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php new file mode 100644 index 0000000..a16ca9f --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php @@ -0,0 +1,14 @@ + + register('foo', 'FooClass')-> + addArgument(new Reference('bar')) +; + +return $container; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php new file mode 100644 index 0000000..3e6cafc --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php @@ -0,0 +1,12 @@ + + register('foo', 'FooClass')-> + addArgument(new Definition('BarClass', array(new Definition('BazClass')))) +; + +return $container; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php new file mode 100644 index 0000000..0dc8679 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php @@ -0,0 +1,13 @@ + + register('foo', 'FooClass\\Foo')-> + addArgument('foo<>&bar')-> + addTag('foo"bar\\bar', array('foo' => 'foo"barřž€')) +; + +return $container; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php new file mode 100644 index 0000000..28c6536 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php @@ -0,0 +1,13 @@ + '%baz%', + 'baz' => 'bar', + 'bar' => 'foo is %%foo bar', + 'values' => array(true, false, null, 0, 1000.3, 'true', 'false', 'null'), +))); + +return $container; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php new file mode 100644 index 0000000..663f2a7 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -0,0 +1,58 @@ + + register('foo', 'FooClass')-> + addTag('foo', array('foo' => 'foo'))-> + addTag('foo', array('bar' => 'bar'))-> + setFactoryClass('FooClass')-> + setFactoryMethod('getInstance')-> + setArguments(array('foo', new Reference('foo.baz'), array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, new Reference('service_container')))-> + setProperties(array('foo' => 'bar', 'moo' => new Reference('foo.baz')))-> + setScope('prototype')-> + addMethodCall('setBar', array(new Reference('bar')))-> + addMethodCall('initialize')-> + setConfigurator('sc_configure') +; +$container-> + register('bar', 'FooClass')-> + setArguments(array('foo', new Reference('foo.baz'), new Parameter('foo_bar')))-> + setScope('container')-> + setConfigurator(array(new Reference('foo.baz'), 'configure')) +; +$container-> + register('foo.baz', '%baz_class%')-> + setFactoryClass('%baz_class%')-> + setFactoryMethod('getInstance')-> + setConfigurator(array('%baz_class%', 'configureStatic1')) +; +$container->register('foo_bar', '%foo_class%'); +$container->getParameterBag()->clear(); +$container->getParameterBag()->add(array( + 'baz_class' => 'BazClass', + 'foo_class' => 'FooClass', + 'foo' => 'bar', +)); +$container->setAlias('alias_for_foo', 'foo'); +$container-> + register('method_call1', 'FooClass')-> + setFile(realpath(__DIR__.'/../includes/foo.php'))-> + addMethodCall('setBar', array(new Reference('foo')))-> + addMethodCall('setBar', array(new Reference('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)))-> + addMethodCall('setBar', array(new Reference('foo3', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))-> + addMethodCall('setBar', array(new Reference('foobaz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))) +; +$container-> + register('factory_service')-> + setFactoryService('foo.baz')-> + setFactoryMethod('getInstance') +; + +return $container; diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php new file mode 100644 index 0000000..27503a3 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php @@ -0,0 +1,25 @@ +setParameter('cla', 'Fo'); +$container->setParameter('ss', 'Class'); + +$definition = new Definition('%cla%o%ss%'); +$container->setDefinition('foo', $definition); + +return $container; + +if (!class_exists('FooClass')) { + class FooClass + { + public $bar; + + public function setBar($bar) + { + $this->bar = $bar; + } + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php new file mode 100644 index 0000000..a851901 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php @@ -0,0 +1,34 @@ +setDefinition('barFactory', $factoryDefinition); + +$definition = new Definition(); +$definition->setFactoryService('barFactory'); +$definition->setFactoryMethod('createBarClass'); +$container->setDefinition('bar', $definition); + +return $container; + +class BarClass +{ + public $foo; + + public function setBar($foo) + { + $this->foo = $foo; + } +} + +class BarClassFactory +{ + public function createBarClass() + { + return new BarClass(); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dot b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dot new file mode 100644 index 0000000..1bb7c30 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dot @@ -0,0 +1,7 @@ +digraph sc { + ratio="compress" + node [fontsize="11" fontname="Arial" shape="record"]; + edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; + + node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot new file mode 100644 index 0000000..0e578b1 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot @@ -0,0 +1,10 @@ +digraph sc { + ratio="normal" + node [fontsize="13" fontname="Verdana" shape="square"]; + edge [fontsize="12" fontname="Verdana" color="white" arrowhead="closed" arrowsize="1"]; + + node_foo [label="foo\nFooClass\n", shape=square, fillcolor="grey", style="filled"]; + node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=square, fillcolor="green", style="empty"]; + node_bar [label="bar\n\n", shape=square, fillcolor="red", style="empty"]; + node_foo -> node_bar [label="" style="filled"]; +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot new file mode 100644 index 0000000..f17857f --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot @@ -0,0 +1,10 @@ +digraph sc { + ratio="compress" + node [fontsize="11" fontname="Arial" shape="record"]; + edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; + + node_foo [label="foo\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; + node_bar [label="bar\n\n", shape=record, fillcolor="#ff9999", style="filled"]; + node_foo -> node_bar [label="" style="filled"]; +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot new file mode 100644 index 0000000..fdff221 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -0,0 +1,25 @@ +digraph sc { + ratio="compress" + node [fontsize="11" fontname="Arial" shape="record"]; + edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; + + node_foo [label="foo (alias_for_foo)\nFooClass\n", shape=record, fillcolor="#eeeeee", style="dotted"]; + node_bar [label="bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_foo_baz [label="foo.baz\nBazClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_foo_bar [label="foo_bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_method_call1 [label="method_call1\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_factory_service [label="factory_service\n\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; + node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"]; + node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"]; + node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"]; + node_foo -> node_foo_baz [label="" style="filled"]; + node_foo -> node_service_container [label="" style="filled"]; + node_foo -> node_foo_baz [label="" style="dashed"]; + node_foo -> node_bar [label="setBar()" style="dashed"]; + node_bar -> node_foo_baz [label="" style="filled"]; + node_method_call1 -> node_foo [label="setBar()" style="dashed"]; + node_method_call1 -> node_foo2 [label="setBar()" style="dashed"]; + node_method_call1 -> node_foo3 [label="setBar()" style="dashed"]; + node_method_call1 -> node_foobaz [label="setBar()" style="dashed"]; +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php new file mode 100644 index 0000000..81ff7aa --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php @@ -0,0 +1,41 @@ +setDefinition('project.service.bar', new Definition('FooClass')); + $configuration->setParameter('project.parameter.bar', isset($config['foo']) ? $config['foo'] : 'foobar'); + + $configuration->setDefinition('project.service.foo', new Definition('FooClass')); + $configuration->setParameter('project.parameter.foo', isset($config['foo']) ? $config['foo'] : 'foobar'); + + return $configuration; + } + + public function getXsdValidationBasePath() + { + return false; + } + + public function getNamespace() + { + return 'http://www.example.com/schema/project'; + } + + public function getAlias() + { + return 'project'; + } + + public function getConfiguration(array $config, ContainerBuilder $container) + { + return null; + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php new file mode 100644 index 0000000..2ee2f12 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php @@ -0,0 +1,19 @@ +configure(); +} + +class BarClass +{ +} + +class BazClass +{ + public function configure($instance) + { + $instance->configure(); + } + + static public function getInstance() + { + return new self(); + } + + static public function configureStatic($instance) + { + $instance->configure(); + } + + static public function configureStatic1() + { + } +} + +class BarUserClass +{ + public $bar; + + public function __construct(BarClass $bar) + { + $this->bar = $bar; + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php new file mode 100644 index 0000000..a593351 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php @@ -0,0 +1,47 @@ +addFromString('ProjectWithXsdExtensionInPhar.php',<<addFromString('schema/project-1.0.xsd', << + + + + + + + + + +EOT +); +$phar->setStub(''); diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php new file mode 100644 index 0000000..2c53122 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php @@ -0,0 +1,36 @@ +arguments = $arguments; + } + + static public function getInstance($arguments = array()) + { + $obj = new self($arguments); + $obj->called = true; + + return $obj; + } + + public function initialize() + { + $this->initialized = true; + } + + public function configure() + { + $this->configured = true; + } + + public function setBar($value = null) + { + $this->bar = $value; + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd new file mode 100644 index 0000000..282884e --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini new file mode 100644 index 0000000..9f84a60 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini @@ -0,0 +1,2 @@ +{NOT AN INI FILE} +{JUST A PLAIN TEXT FILE} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini new file mode 100644 index 0000000..df92f75 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini @@ -0,0 +1,3 @@ +[parameters] + foo = bar + bar = %foo% diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini new file mode 100644 index 0000000..e50f722 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini @@ -0,0 +1,3 @@ +[parameters] + FOO = foo + baz = baz diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini new file mode 100644 index 0000000..75fbac6 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini @@ -0,0 +1,2 @@ +[parameters] + imported_from_ini = true diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php new file mode 100644 index 0000000..de4b642 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -0,0 +1,28 @@ +parameters = $this->getDefaultParameters(); + + $this->services = + $this->scopedServices = + $this->scopeStacks = array(); + + $this->set('service_container', $this); + + $this->scopes = array(); + $this->scopeChildren = array(); + } + + /** + * Gets the 'test' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return stdClass A stdClass instance. + */ + protected function getTestService() + { + return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end')); + } + + /** + * {@inheritdoc} + */ + public function getParameter($name) + { + $name = strtolower($name); + + if (!array_key_exists($name, $this->parameters)) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + + return $this->parameters[$name]; + } + + /** + * {@inheritdoc} + */ + public function hasParameter($name) + { + return array_key_exists(strtolower($name), $this->parameters); + } + + /** + * {@inheritdoc} + */ + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + /** + * {@inheritDoc} + */ + public function getParameterBag() + { + if (null === $this->parameterBag) { + $this->parameterBag = new FrozenParameterBag($this->parameters); + } + + return $this->parameterBag; + } + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'empty_value' => '', + 'some_string' => '-', + ); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php new file mode 100644 index 0000000..77e4183 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -0,0 +1,52 @@ +getDefaultParameters())); + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'foo' => '%baz%', + 'baz' => 'bar', + 'bar' => 'foo is %%foo bar', + 'values' => array( + 0 => true, + 1 => false, + 2 => NULL, + 3 => 0, + 4 => 1000.3, + 5 => 'true', + 6 => 'false', + 7 => 'null', + ), + ); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php new file mode 100644 index 0000000..5ab7bab --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -0,0 +1,159 @@ +getDefaultParameters())); + } + + /** + * Gets the 'bar' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return FooClass A FooClass instance. + */ + protected function getBarService() + { + $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar')); + + $this->get('foo.baz')->configure($instance); + + return $instance; + } + + /** + * Gets the 'factory_service' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return Object An instance returned by foo.baz::getInstance(). + */ + protected function getFactoryServiceService() + { + return $this->services['factory_service'] = $this->get('foo.baz')->getInstance(); + } + + /** + * Gets the 'foo' service. + * + * @return FooClass A FooClass instance. + */ + protected function getFooService() + { + $a = $this->get('foo.baz'); + + $instance = call_user_func(array('FooClass', 'getInstance'), 'foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo'), 'bar' => $this->getParameter('foo')), true, $this); + + $instance->setBar($this->get('bar')); + $instance->initialize(); + $instance->foo = 'bar'; + $instance->moo = $a; + sc_configure($instance); + + return $instance; + } + + /** + * Gets the 'foo.baz' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return Object A %baz_class% instance. + */ + protected function getFoo_BazService() + { + $this->services['foo.baz'] = $instance = call_user_func(array($this->getParameter('baz_class'), 'getInstance')); + + call_user_func(array($this->getParameter('baz_class'), 'configureStatic1'), $instance); + + return $instance; + } + + /** + * Gets the 'foo_bar' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return Object A %foo_class% instance. + */ + protected function getFooBarService() + { + $class = $this->getParameter('foo_class'); + return $this->services['foo_bar'] = new $class(); + } + + /** + * Gets the 'method_call1' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return FooClass A FooClass instance. + */ + protected function getMethodCall1Service() + { + require_once '%path%foo.php'; + + $this->services['method_call1'] = $instance = new \FooClass(); + + $instance->setBar($this->get('foo')); + $instance->setBar($this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + if ($this->has('foo3')) { + $instance->setBar($this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + } + if ($this->has('foobaz')) { + $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + } + + return $instance; + } + + /** + * Gets the alias_for_foo service alias. + * + * @return FooClass An instance of the foo service + */ + protected function getAliasForFooService() + { + return $this->get('foo'); + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'baz_class' => 'BazClass', + 'foo_class' => 'FooClass', + 'foo' => 'bar', + ); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php new file mode 100644 index 0000000..aa4df99 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php @@ -0,0 +1,3 @@ +setParameter('foo', 'foo'); diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml new file mode 100644 index 0000000..52df38d --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml new file mode 100644 index 0000000..21a7ef5 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml new file mode 100644 index 0000000..792fa07 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml @@ -0,0 +1,19 @@ + + + + + + BAR + + + + + + + + + %project.parameter.foo% + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml new file mode 100644 index 0000000..67d462b --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml @@ -0,0 +1,19 @@ + + + + + + BAR + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml new file mode 100644 index 0000000..c23f02a --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml @@ -0,0 +1,19 @@ + + + + + + BAR + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml new file mode 100644 index 0000000..2c33c3a --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml new file mode 100644 index 0000000..0eaaff2 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml new file mode 100644 index 0000000..a9c0103 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml new file mode 100644 index 0000000..e77780d --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml new file mode 100644 index 0000000..e7b5bc9 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml @@ -0,0 +1,3 @@ + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml new file mode 100644 index 0000000..6aa5732 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml @@ -0,0 +1,2 @@ + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xml new file mode 100644 index 0000000..1ac4938 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xml @@ -0,0 +1,9 @@ + + + + + true + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml new file mode 100644 index 0000000..bada1c8 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml @@ -0,0 +1,31 @@ + + + + + a string + bar + + 0 + 4 + null + true + true + false + on + off + 1.3 + 1,000.3 + a string + + foo + bar + + + + + value + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml new file mode 100644 index 0000000..87bf183 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml @@ -0,0 +1,13 @@ + + + + + foo + + true + false + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml new file mode 100644 index 0000000..03ad9f8 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xml new file mode 100644 index 0000000..0b7f10a --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml new file mode 100644 index 0000000..787b4ef --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml new file mode 100644 index 0000000..45bc042 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + %path%/foo.php + + + foo + + + true + false + + + + + + + + + + + + + + + + + foo + + + true + false + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xml new file mode 100644 index 0000000..824d8b5 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml new file mode 100644 index 0000000..f11d606 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml @@ -0,0 +1,21 @@ + + + + + %baz% + bar + foo is %%foo bar + + true + false + null + 0 + 1000.3 + true + false + null + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml new file mode 100644 index 0000000..a73fb3e --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -0,0 +1,56 @@ + + + + BazClass + FooClass + bar + + + + + + foo + + + foo is %foo% + %foo% + + true + + bar + + + + + + + + + foo + + %foo_bar% + + + + + + + + %path%foo.php + + + + + + + + + + + + + + + + + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.yml new file mode 100644 index 0000000..14536fd --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.yml @@ -0,0 +1,5 @@ +services: + foo_service: + class: FooClass + # tags is not an array + tags: string diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml new file mode 100644 index 0000000..9028814 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml @@ -0,0 +1,6 @@ +services: + foo_service: + class: FooClass + tags: + # tag is missing the name key + foo_tag: { foo: bar } diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml new file mode 100644 index 0000000..8137fab --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml @@ -0,0 +1,6 @@ +services: + foo_service: + class: FooClass + tags: + # tag-attribute is not a scalar + - { name: foo, foo: { foo: foo, bar: bar } } diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml new file mode 100644 index 0000000..4eddb87 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml @@ -0,0 +1,2 @@ +foo: + bar diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml new file mode 100644 index 0000000..c508d53 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml @@ -0,0 +1 @@ +false diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml @@ -0,0 +1 @@ + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml new file mode 100644 index 0000000..f2f8d95 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml @@ -0,0 +1,9 @@ +parameters: + project.parameter.foo: BAR + +services: + project.service.foo: + class: BAR + +project: + test: %project.parameter.foo% diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml new file mode 100644 index 0000000..40126f0 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml @@ -0,0 +1 @@ +foobarfoobar: {} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.yml new file mode 100644 index 0000000..d52d355 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.yml @@ -0,0 +1,3 @@ +# used to test imports in XML +parameters: + imported_from_yaml: true diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml new file mode 100644 index 0000000..8ddfe0d --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml @@ -0,0 +1,11 @@ +parameters: + FOO: bar + values: + - true + - false + - 0 + - 1000.3 + bar: foo + foo_bar: @foo_bar + MixedCase: + MixedCaseKey: value diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.yml new file mode 100644 index 0000000..0e92cdf --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.yml @@ -0,0 +1,5 @@ +parameters: + foo: foo + values: + - true + - false diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml new file mode 100644 index 0000000..18f1065 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml @@ -0,0 +1,6 @@ +imports: + - { resource: services2.yml } + - { resource: services3.yml } + - { resource: "../ini/parameters.ini", class: Symfony\Component\DependencyInjection\Loader\IniFileLoader } + - { resource: "../ini/parameters2.ini" } + - { resource: "../xml/services13.xml" } diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml new file mode 100644 index 0000000..f7089fc --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml @@ -0,0 +1,2 @@ +imports: + - { resource: foo_fake.yml, ignore_errors: true } diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml new file mode 100644 index 0000000..eaa52bd --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml @@ -0,0 +1,26 @@ +services: + foo: { class: FooClass } + baz: { class: BazClass } + scope.container: { class: FooClass, scope: container } + scope.custom: { class: FooClass, scope: custom } + scope.prototype: { class: FooClass, scope: prototype } + constructor: { class: FooClass, factory_method: getInstance } + file: { class: FooClass, file: %path%/foo.php } + arguments: { class: FooClass, arguments: [foo, @foo, [true, false]] } + configurator1: { class: FooClass, configurator: sc_configure } + configurator2: { class: FooClass, configurator: [@baz, configure] } + configurator3: { class: FooClass, configurator: [BazClass, configureStatic] } + method_call1: + class: FooClass + calls: + - [ setBar, [] ] + - [ setBar ] + method_call2: + class: FooClass + calls: + - [ setBar, [ foo, @foo, [true, false] ] ] + alias_for_foo: @foo + another_alias_for_foo: + alias: foo + public: false + factory_service: { class: BazClass, factory_method: getInstance, factory_service: baz_factory } diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml new file mode 100644 index 0000000..09064f2 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml @@ -0,0 +1,2 @@ +services: + foo: { class: BarClass } diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml new file mode 100644 index 0000000..5e74748 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml @@ -0,0 +1,6 @@ +parameters: + foo: '%baz%' + baz: bar + bar: 'foo is %%foo bar' + values: [true, false, null, 0, 1000.3, 'true', 'false', 'null'] + diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml new file mode 100644 index 0000000..2aa47a5 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -0,0 +1,43 @@ +parameters: + baz_class: BazClass + foo_class: FooClass + foo: bar + +services: + foo: + class: FooClass + tags: + - { name: foo, foo: foo } + - { name: foo, bar: bar } + factory_method: getInstance + arguments: [foo, '@foo.baz', { '%foo%': 'foo is %foo%', bar: '%foo%' }, true, '@service_container'] + properties: { foo: bar, moo: '@foo.baz' } + calls: + - [setBar, ['@bar']] + - [initialize, { }] + + scope: prototype + configurator: sc_configure + bar: + class: FooClass + arguments: [foo, '@foo.baz', '%foo_bar%'] + configurator: ['@foo.baz', configure] + foo.baz: + class: %baz_class% + factory_method: getInstance + configurator: ['%baz_class%', configureStatic1] + foo_bar: + class: %foo_class% + method_call1: + class: FooClass + file: %path%foo.php + calls: + - [setBar, ['@foo']] + - [setBar, ['@?foo2']] + - [setBar, ['@?foo3']] + - [setBar, ['@?foobaz']] + + factory_service: + factory_method: getInstance + factory_service: foo.baz + alias_for_foo: @foo diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php new file mode 100644 index 0000000..85f02a2 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Loader; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\ClosureLoader; + +class ClosureLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::supports + */ + public function testSupports() + { + $loader = new ClosureLoader(new ContainerBuilder()); + + $this->assertTrue($loader->supports(function ($container) {}), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::load + */ + public function testLoad() + { + $loader = new ClosureLoader($container = new ContainerBuilder()); + + $loader->load(function ($container) + { + $container->setParameter('foo', 'foo'); + }); + + $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a \Closure resource'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php new file mode 100644 index 0000000..448934c --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Loader; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\IniFileLoader; +use Symfony\Component\Config\FileLocator; + +class IniFileLoaderTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected $container; + protected $loader; + + static public function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); + } + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $this->container = new ContainerBuilder(); + $this->loader = new IniFileLoader($this->container, new FileLocator(self::$fixturesPath.'/ini')); + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct + * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load + */ + public function testIniFileCanBeLoaded() + { + $this->loader->load('parameters.ini'); + $this->assertEquals(array('foo' => 'bar', 'bar' => '%foo%'), $this->container->getParameterBag()->all(), '->load() takes a single file name as its first argument'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct + * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load + */ + public function testExceptionIsRaisedWhenIniFileDoesNotExist() + { + try { + $this->loader->load('foo.ini'); + $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist'); + $this->assertStringStartsWith('The file "foo.ini" does not exist (in: ', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct + * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load + */ + public function testExceptionIsRaisedWhenIniFileCannotBeParsed() + { + try { + @$this->loader->load('nonvalid.ini'); + $this->fail('->load() throws an InvalidArgumentException if the loaded file is not parseable'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file is not parseable'); + $this->assertEquals('The "nonvalid.ini" file is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file is not parseable'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::supports + */ + public function testSupports() + { + $loader = new IniFileLoader(new ContainerBuilder(), new FileLocator()); + + $this->assertTrue($loader->supports('foo.ini'), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php new file mode 100644 index 0000000..3a97dc2 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Loader; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\Config\FileLocator; + +class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::supports + */ + public function testSupports() + { + $loader = new PhpFileLoader(new ContainerBuilder(), new FileLocator()); + + $this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::load + */ + public function testLoad() + { + $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator()); + + $loader->load(__DIR__.'/../Fixtures/php/simple.php'); + + $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a PHP file resource'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php new file mode 100644 index 0000000..12fa718 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -0,0 +1,320 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Loader; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\Loader\IniFileLoader; +use Symfony\Component\Config\Loader\LoaderResolver; +use Symfony\Component\Config\FileLocator; + +class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + static public function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); + require_once self::$fixturesPath.'/includes/foo.php'; + require_once self::$fixturesPath.'/includes/ProjectExtension.php'; + require_once self::$fixturesPath.'/includes/ProjectWithXsdExtension.php'; + } + + public function testLoad() + { + $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini')); + + try { + $loader->load('foo.xml'); + $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist'); + $this->assertStringStartsWith('The file "foo.xml" does not exist (in:', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist'); + } + } + + public function testParseFile() + { + $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini')); + $r = new \ReflectionObject($loader); + $m = $r->getMethod('parseFile'); + $m->setAccessible(true); + + try { + $m->invoke($loader, self::$fixturesPath.'/ini/parameters.ini'); + $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); + $this->assertStringStartsWith('[ERROR 4] Start tag expected, \'<\' not found (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); + } + + $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/xml')); + + try { + $m->invoke($loader, self::$fixturesPath.'/xml/nonvalid.xml'); + $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD'); + $this->assertStringStartsWith('[ERROR 1845] Element \'nonvalid\': No matching global declaration available for the validation root. (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD'); + } + + $xml = $m->invoke($loader, self::$fixturesPath.'/xml/services1.xml'); + $this->assertEquals('Symfony\\Component\\DependencyInjection\\SimpleXMLElement', get_class($xml), '->parseFile() returns an SimpleXMLElement object'); + } + + public function testLoadParameters() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services2.xml'); + + $actual = $container->getParameterBag()->all(); + $expected = array('a string', 'foo' => 'bar', 'values' => array(0, 'integer' => 4, 100 => null, 'true', true, false, 'on', 'off', 'float' => 1.3, 1000.3, 'a string', array('foo', 'bar')), 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value')); + + $this->assertEquals($expected, $actual, '->load() converts XML values to PHP ones'); + } + + public function testLoadImports() + { + $container = new ContainerBuilder(); + $resolver = new LoaderResolver(array( + new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), + new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), + )); + $loader->setResolver($resolver); + $loader->load('services4.xml'); + + $actual = $container->getParameterBag()->all(); + $expected = array('a string', 'foo' => 'bar', 'values' => array(true, false), 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value'), 'bar' => '%foo%', 'imported_from_ini' => true, 'imported_from_yaml' => true); + + $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files'); + + // Bad import throws no exception due to ignore_errors value. + $loader->load('services4_bad_import.xml'); + } + + public function testLoadAnonymousServices() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services5.xml'); + $services = $container->getDefinitions(); + $this->assertEquals(3, count($services), '->load() attributes unique ids to anonymous services'); + $args = $services['foo']->getArguments(); + $this->assertEquals(1, count($args), '->load() references anonymous services as "normal" ones'); + $this->assertEquals('Symfony\\Component\\DependencyInjection\\Reference', get_class($args[0]), '->load() converts anonymous services to references to "normal" services'); + $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones'); + $inner = $services[(string) $args[0]]; + $this->assertEquals('BarClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones'); + + $args = $inner->getArguments(); + $this->assertEquals(1, count($args), '->load() references anonymous services as "normal" ones'); + $this->assertEquals('Symfony\\Component\\DependencyInjection\\Reference', get_class($args[0]), '->load() converts anonymous services to references to "normal" services'); + $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones'); + $inner = $services[(string) $args[0]]; + $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones'); + } + + public function testLoadServices() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services6.xml'); + $services = $container->getDefinitions(); + $this->assertTrue(isset($services['foo']), '->load() parses elements'); + $this->assertEquals('Symfony\\Component\\DependencyInjection\\Definition', get_class($services['foo']), '->load() converts element to Definition instances'); + $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute'); + $this->assertEquals('container', $services['scope.container']->getScope()); + $this->assertEquals('custom', $services['scope.custom']->getScope()); + $this->assertEquals('prototype', $services['scope.prototype']->getScope()); + $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory-method attribute'); + $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag'); + $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags'); + $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag'); + $this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag'); + $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag'); + $this->assertEquals(array(array('setBar', array())), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); + $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag'); + $this->assertNull($services['factory_service']->getClass()); + $this->assertEquals('getInstance', $services['factory_service']->getFactoryMethod()); + $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService()); + + $aliases = $container->getAliases(); + $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses elements'); + $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases'); + $this->assertTrue($aliases['alias_for_foo']->isPublic()); + $this->assertTrue(isset($aliases['another_alias_for_foo'])); + $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']); + $this->assertFalse($aliases['another_alias_for_foo']->isPublic()); + } + + public function testConvertDomElementToArray() + { + $doc = new \DOMDocument("1.0"); + $doc->loadXML('bar'); + $this->assertEquals('bar', XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); + + $doc = new \DOMDocument("1.0"); + $doc->loadXML(''); + $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); + + $doc = new \DOMDocument("1.0"); + $doc->loadXML('bar'); + $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); + + $doc = new \DOMDocument("1.0"); + $doc->loadXML('barbar'); + $this->assertEquals(array('foo' => array('value' => 'bar', 'foo' => 'bar')), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); + + $doc = new \DOMDocument("1.0"); + $doc->loadXML(''); + $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); + + $doc = new \DOMDocument("1.0"); + $doc->loadXML(''); + $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); + + $doc = new \DOMDocument("1.0"); + $doc->loadXML(''); + $this->assertEquals(array('foo' => array(array('foo' => 'bar'), array('foo' => 'bar'))), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); + } + + public function testExtensions() + { + $container = new ContainerBuilder(); + $container->registerExtension(new \ProjectExtension()); + $container->registerExtension(new \ProjectWithXsdExtension()); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + + // extension without an XSD + $loader->load('extensions/services1.xml'); + $container->compile(); + $services = $container->getDefinitions(); + $parameters = $container->getParameterBag()->all(); + + $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements'); + $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements'); + + $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements'); + $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements'); + + // extension with an XSD + $container = new ContainerBuilder(); + $container->registerExtension(new \ProjectExtension()); + $container->registerExtension(new \ProjectWithXsdExtension()); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('extensions/services2.xml'); + $container->compile(); + $services = $container->getDefinitions(); + $parameters = $container->getParameterBag()->all(); + + $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements'); + $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements'); + + $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements'); + $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements'); + + $container = new ContainerBuilder(); + $container->registerExtension(new \ProjectExtension()); + $container->registerExtension(new \ProjectWithXsdExtension()); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + + // extension with an XSD (does not validate) + try { + $loader->load('extensions/services3.xml'); + $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); + $this->assertRegexp('/The attribute \'bar\' is not allowed/', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); + } + + // non-registered extension + try { + $loader->load('extensions/services4.xml'); + $this->fail('->load() throws an InvalidArgumentException if the tag is not valid'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid'); + $this->assertStringStartsWith('There is no extension able to load the configuration for "project:bar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid'); + } + } + + public function testExtensionInPhar() + { + if (extension_loaded('suhosin') && false === strpos(ini_get('suhosin.executor.include.whitelist'), 'phar')) { + $this->markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.'); + } + + require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar'; + + // extension with an XSD in PHAR archive + $container = new ContainerBuilder(); + $container->registerExtension(new \ProjectWithXsdExtensionInPhar()); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('extensions/services6.xml'); + + // extension with an XSD in PHAR archive (does not validate) + try { + $loader->load('extensions/services7.xml'); + $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); + $this->assertRegexp('/The attribute \'bar\' is not allowed/', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\XmlFileLoader::supports + */ + public function testSupports() + { + $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator()); + + $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + } + + public function testNoNamingConflictsForAnonymousServices() + { + $container = new ContainerBuilder(); + + $loader1 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension1')); + $loader1->load('services.xml'); + $services = $container->getDefinitions(); + $this->assertEquals(2, count($services), '->load() attributes unique ids to anonymous services'); + $loader2 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension2')); + $loader2->load('services.xml'); + $services = $container->getDefinitions(); + $this->assertEquals(4, count($services), '->load() attributes unique ids to anonymous services'); + + $services = $container->getDefinitions(); + $args1 = $services['extension1.foo']->getArguments(); + $inner1 = $services[(string) $args1[0]]; + $this->assertEquals('BarClass1', $inner1->getClass(), '->load() uses the same configuration as for the anonymous ones'); + $args2 = $services['extension2.foo']->getArguments(); + $inner2 = $services[(string) $args2[0]]; + $this->assertEquals('BarClass2', $inner2->getClass(), '->load() uses the same configuration as for the anonymous ones'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php new file mode 100644 index 0000000..35b5985 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -0,0 +1,211 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Loader; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\Loader\IniFileLoader; +use Symfony\Component\Config\Loader\LoaderResolver; +use Symfony\Component\Config\FileLocator; + +class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\Loader\Loader')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + if (!class_exists('Symfony\Component\Yaml\Yaml')) { + $this->markTestSkipped('The "Yaml" component is not available'); + } + } + + static public function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); + require_once self::$fixturesPath.'/includes/foo.php'; + require_once self::$fixturesPath.'/includes/ProjectExtension.php'; + } + + public function testLoadFile() + { + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini')); + $r = new \ReflectionObject($loader); + $m = $r->getMethod('loadFile'); + $m->setAccessible(true); + + try { + $m->invoke($loader, 'foo.yml'); + $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist'); + $this->assertEquals('The service file "foo.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist'); + } + + try { + $m->invoke($loader, 'parameters.ini'); + $this->fail('->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); + $this->assertEquals('The service file "parameters.ini" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); + } + + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); + + foreach (array('nonvalid1', 'nonvalid2') as $fixture) { + try { + $m->invoke($loader, $fixture.'.yml'); + $this->fail('->load() throws an InvalidArgumentException if the loaded file does not validate'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not validate'); + $this->assertStringMatchesFormat('The service file "nonvalid%d.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not validate'); + } + } + } + + public function testLoadParameters() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services2.yml'); + $this->assertEquals(array('foo' => 'bar', 'mixedcase' => array('MixedCaseKey' => 'value'), 'values' => array(true, false, 0, 1000.3), 'bar' => 'foo', 'foo_bar' => new Reference('foo_bar')), $container->getParameterBag()->all(), '->load() converts YAML keys to lowercase'); + } + + public function testLoadImports() + { + $container = new ContainerBuilder(); + $resolver = new LoaderResolver(array( + new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), + new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), + )); + $loader->setResolver($resolver); + $loader->load('services4.yml'); + + $actual = $container->getParameterBag()->all(); + $expected = array('foo' => 'bar', 'values' => array(true, false), 'bar' => '%foo%', 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value'), 'imported_from_ini' => true, 'imported_from_xml' => true); + $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files'); + + // Bad import throws no exception due to ignore_errors value. + $loader->load('services4_bad_import.yml'); + } + + public function testLoadServices() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services6.yml'); + $services = $container->getDefinitions(); + $this->assertTrue(isset($services['foo']), '->load() parses service elements'); + $this->assertEquals('Symfony\\Component\\DependencyInjection\\Definition', get_class($services['foo']), '->load() converts service element to Definition instances'); + $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute'); + $this->assertEquals('container', $services['scope.container']->getScope()); + $this->assertEquals('custom', $services['scope.custom']->getScope()); + $this->assertEquals('prototype', $services['scope.prototype']->getScope()); + $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory_method attribute'); + $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag'); + $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags'); + $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag'); + $this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag'); + $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag'); + $this->assertEquals(array(array('setBar', array()), array('setBar', array())), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); + $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag'); + $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService()); + + $aliases = $container->getAliases(); + $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses aliases'); + $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases'); + $this->assertTrue($aliases['alias_for_foo']->isPublic()); + $this->assertTrue(isset($aliases['another_alias_for_foo'])); + $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']); + $this->assertFalse($aliases['another_alias_for_foo']->isPublic()); + } + + public function testExtensions() + { + $container = new ContainerBuilder(); + $container->registerExtension(new \ProjectExtension()); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services10.yml'); + $container->compile(); + $services = $container->getDefinitions(); + $parameters = $container->getParameterBag()->all(); + + $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements'); + $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements'); + + $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements'); + $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements'); + + try { + $loader->load('services11.yml'); + $this->fail('->load() throws an InvalidArgumentException if the tag is not valid'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid'); + $this->assertStringStartsWith('There is no extension able to load the configuration for "foobarfoobar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\Loader\YamlFileLoader::supports + */ + public function testSupports() + { + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator()); + + $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + } + + public function testNonArrayTagThrowsException() + { + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); + try { + $loader->load('badtag1.yml'); + $this->fail('->load() should throw an exception when the tags key of a service is not an array'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tags key is not an array'); + $this->assertStringStartsWith('Parameter "tags" must be an array for service', $e->getMessage(), '->load() throws an InvalidArgumentException if the tags key is not an array'); + } + } + + public function testTagWithoutNameThrowsException() + { + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); + try { + $loader->load('badtag2.yml'); + $this->fail('->load() should throw an exception when a tag is missing the name key'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag is missing the name key'); + $this->assertStringStartsWith('A "tags" entry is missing a "name" key for service ', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag is missing the name key'); + } + } + + public function testTagWithAttributeArrayThrowsException() + { + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); + try { + $loader->load('badtag3.yml'); + $this->fail('->load() should throw an exception when a tag-attribute is not a scalar'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar'); + $this->assertStringStartsWith('A "tags" attribute must be of a scalar-type for service ', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar'); + } + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php new file mode 100644 index 0000000..e6e7fea --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\ParameterBag; + +use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; + +class FrozenParameterBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::__construct + */ + public function testConstructor() + { + $parameters = array( + 'foo' => 'foo', + 'bar' => 'bar', + ); + $bag = new FrozenParameterBag($parameters); + $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::clear + * @expectedException \LogicException + */ + public function testClear() + { + $bag = new FrozenParameterBag(array()); + $bag->clear(); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::set + * @expectedException \LogicException + */ + public function testSet() + { + $bag = new FrozenParameterBag(array()); + $bag->set('foo', 'bar'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::add + * @expectedException \LogicException + */ + public function testAdd() + { + $bag = new FrozenParameterBag(array()); + $bag->add(array()); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php new file mode 100644 index 0000000..5f5f265 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php @@ -0,0 +1,215 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\ParameterBag; + +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; +use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +class ParameterBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::__construct + */ + public function testConstructor() + { + $bag = new ParameterBag($parameters = array( + 'foo' => 'foo', + 'bar' => 'bar', + )); + $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::clear + */ + public function testClear() + { + $bag = new ParameterBag($parameters = array( + 'foo' => 'foo', + 'bar' => 'bar', + )); + $bag->clear(); + $this->assertEquals(array(), $bag->all(), '->clear() removes all parameters'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::get + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::set + */ + public function testGetSet() + { + $bag = new ParameterBag(array('foo' => 'bar')); + $bag->set('bar', 'foo'); + $this->assertEquals('foo', $bag->get('bar'), '->set() sets the value of a new parameter'); + + $bag->set('foo', 'baz'); + $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter'); + + $bag->set('Foo', 'baz1'); + $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase'); + $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase'); + + try { + $bag->get('baba'); + $this->fail('->get() throws an \InvalidArgumentException if the key does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws an \InvalidArgumentException if the key does not exist'); + $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->get() throws an \InvalidArgumentException if the key does not exist'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::has + */ + public function testHas() + { + $bag = new ParameterBag(array('foo' => 'bar')); + $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined'); + $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase'); + $this->assertFalse($bag->has('bar'), '->has() returns false if a parameter is not defined'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolveValue + */ + public function testResolveValue() + { + $bag = new ParameterBag(array()); + $this->assertEquals('foo', $bag->resolveValue('foo'), '->resolveValue() returns its argument unmodified if no placeholders are found'); + + $bag = new ParameterBag(array('foo' => 'bar')); + $this->assertEquals('I\'m a bar', $bag->resolveValue('I\'m a %foo%'), '->resolveValue() replaces placeholders by their values'); + $this->assertEquals(array('bar' => 'bar'), $bag->resolveValue(array('%foo%' => '%foo%')), '->resolveValue() replaces placeholders in keys and values of arrays'); + $this->assertEquals(array('bar' => array('bar' => array('bar' => 'bar'))), $bag->resolveValue(array('%foo%' => array('%foo%' => array('%foo%' => '%foo%')))), '->resolveValue() replaces placeholders in nested arrays'); + $this->assertEquals('I\'m a %%foo%%', $bag->resolveValue('I\'m a %%foo%%'), '->resolveValue() supports % escaping by doubling it'); + $this->assertEquals('I\'m a bar %%foo bar', $bag->resolveValue('I\'m a %foo% %%foo %foo%'), '->resolveValue() supports % escaping by doubling it'); + $this->assertEquals(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar'))), $bag->resolveValue(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')))), '->resolveValue() supports % escaping by doubling it'); + + $bag = new ParameterBag(array('foo' => true)); + $this->assertTrue($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings'); + $bag = new ParameterBag(array('foo' => null)); + $this->assertNull($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings'); + + $bag = new ParameterBag(array('foo' => 'bar', 'baz' => '%%%foo% %foo%%% %%foo%% %%%foo%%%')); + $this->assertEquals('%%bar bar%% %%foo%% %%bar%%', $bag->resolveValue('%baz%'), '->resolveValue() replaces params placed besides escaped %'); + + $bag = new ParameterBag(array('baz' => '%%s?%%s')); + $this->assertEquals('%%s?%%s', $bag->resolveValue('%baz%'), '->resolveValue() is not replacing greedily'); + + $bag = new ParameterBag(array()); + try { + $bag->resolveValue('%foobar%'); + $this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); + } catch (ParameterNotFoundException $e) { + $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter'); + } + + try { + $bag->resolveValue('foo %foobar% bar'); + $this->fail('->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter'); + } catch (ParameterNotFoundException $e) { + $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter'); + } + + $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => array())); + try { + $bag->resolveValue('%foo%'); + $this->fail('->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter'); + } catch (RuntimeException $e) { + $this->assertEquals('A string value must be composed of strings and/or numbers, but found parameter "bar" of type array inside string value "a %bar%".', $e->getMessage(), '->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter'); + } + + $bag = new ParameterBag(array('foo' => '%bar%', 'bar' => '%foobar%', 'foobar' => '%foo%')); + try { + $bag->resolveValue('%foo%'); + $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); + } catch (ParameterCircularReferenceException $e) { + $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); + } + + $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => 'a %foobar%', 'foobar' => 'a %foo%')); + try { + $bag->resolveValue('%foo%'); + $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); + } catch (ParameterCircularReferenceException $e) { + $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); + } + + $bag = new ParameterBag(array('host' => 'foo.bar', 'port' => 1337)); + $this->assertEquals('foo.bar:1337', $bag->resolveValue('%host%:%port%')); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve + */ + public function testResolveIndicatesWhyAParameterIsNeeded() + { + $bag = new ParameterBag(array('foo' => '%bar%')); + + try { + $bag->resolve(); + } catch (ParameterNotFoundException $e) { + $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage()); + } + + $bag = new ParameterBag(array('foo' => '%bar%')); + + try { + $bag->resolve(); + } catch (ParameterNotFoundException $e) { + $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage()); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve + */ + public function testResolveUnescapesValue() + { + $bag = new ParameterBag(array( + 'foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')), + 'bar' => 'I\'m a %%foo%%', + )); + + $bag->resolve(); + + $this->assertEquals('I\'m a %foo%', $bag->get('bar'), '->resolveValue() supports % escaping by doubling it'); + $this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %foo %bar')), $bag->get('foo'), '->resolveValue() supports % escaping by doubling it'); + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve + * @dataProvider stringsWithSpacesProvider + */ + public function testResolveStringWithSpacesReturnsString($expected, $test, $description) + { + $bag = new ParameterBag(array('foo' => 'bar')); + + try { + $this->assertEquals($expected, $bag->resolveString($test), $description); + } catch (ParameterNotFoundException $e) { + $this->fail(sprintf('%s - "%s"', $description, $expected)); + } + } + + public function stringsWithSpacesProvider() + { + return array( + array('bar', '%foo%', 'Parameters must be wrapped by %.'), + array('% foo %', '% foo %', 'Parameters should not have spaces.'), + array('{% set my_template = "foo" %}', '{% set my_template = "foo" %}', 'Twig-like strings are not parameters.'), + array('50% is less than 100%', '50% is less than 100%', 'Text between % signs is allowed, if there are spaces.'), + ); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterTest.php new file mode 100644 index 0000000..bed188e --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/ParameterTest.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests; + +use Symfony\Component\DependencyInjection\Parameter; + +class ParameterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\Parameter::__construct + */ + public function testConstructor() + { + $ref = new Parameter('foo'); + $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the parameter, which is used for the __toString() method'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/ReferenceTest.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/ReferenceTest.php new file mode 100644 index 0000000..f14e99f --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/ReferenceTest.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests; + +use Symfony\Component\DependencyInjection\Reference; + +class ReferenceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\Reference::__construct + */ + public function testConstructor() + { + $ref = new Reference('foo'); + $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the reference, which is used for the __toString() method'); + } + + public function testCaseInsensitive() + { + $ref = new Reference('FooBar'); + $this->assertEquals('foobar', (string) $ref, 'the id is lowercased as the container is case insensitive'); + } +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/Tests/bootstrap.php b/core/vendor/Symfony/Component/DependencyInjection/Tests/bootstrap.php new file mode 100644 index 0000000..77fe275 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/Tests/bootstrap.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + foreach (array( + 'SYMFONY_CONFIG' => 'Config', + 'SYMFONY_YAML' => 'Yaml', + ) as $env => $name) { + if (isset($_SERVER[$env]) && 0 === strpos(ltrim($class, '/'), 'Symfony\Component\\'.$name)) { + if (file_exists($file = $_SERVER[$env].'/'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\\'.$name)).'.php')) { + require_once $file; + } + } + } + + if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\DependencyInjection')) { + if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\DependencyInjection')).'.php')) { + require_once $file; + } + } +}); diff --git a/core/vendor/Symfony/Component/DependencyInjection/composer.json b/core/vendor/Symfony/Component/DependencyInjection/composer.json index fd3ef3a..adf6f11 100644 --- a/core/vendor/Symfony/Component/DependencyInjection/composer.json +++ b/core/vendor/Symfony/Component/DependencyInjection/composer.json @@ -18,11 +18,9 @@ "require": { "php": ">=5.3.2" }, - "recommend": { - "symfony/config": "self.version" - }, "suggest": { - "symfony/yaml": "self.version" + "symfony/yaml": "self.version", + "symfony/config": "self.version" }, "autoload": { "psr-0": { "Symfony\\Component\\DependencyInjection": "" } @@ -33,4 +31,4 @@ "dev-master": "2.1-dev" } } -} \ No newline at end of file +} diff --git a/core/vendor/Symfony/Component/DependencyInjection/phpunit.xml.dist b/core/vendor/Symfony/Component/DependencyInjection/phpunit.xml.dist new file mode 100644 index 0000000..bb81f45 --- /dev/null +++ b/core/vendor/Symfony/Component/DependencyInjection/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + + + + diff --git a/core/vendor/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/core/vendor/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php new file mode 100644 index 0000000..53a0f67 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -0,0 +1,200 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Lazily loads listeners and subscribers from the dependency injection + * container + * + * @author Fabien Potencier + * @author Bernhard Schussek + * @author Jordan Alliot + */ +class ContainerAwareEventDispatcher extends EventDispatcher +{ + /** + * The container from where services are loaded + * @var ContainerInterface + */ + private $container; + + /** + * The service IDs of the event listeners and subscribers + * @var array + */ + private $listenerIds = array(); + + /** + * The services registered as listeners + * @var array + */ + private $listeners = array(); + + /** + * Constructor. + * + * @param ContainerInterface $container A ContainerInterface instance + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Adds a service as event listener + * + * @param string $eventName Event for which the listener is added + * @param array $callback The service ID of the listener service & the method + * name that has to be called + * @param integer $priority The higher this value, the earlier an event listener + * will be triggered in the chain. + * Defaults to 0. + */ + public function addListenerService($eventName, $callback, $priority = 0) + { + if (!is_array($callback) || 2 !== count($callback)) { + throw new \InvalidArgumentException('Expected an array("service", "method") argument'); + } + + $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); + } + + public function removeListener($eventName, $listener) + { + $this->lazyLoad($eventName); + + if (isset($this->listeners[$eventName])) { + foreach ($this->listeners[$eventName] as $key => $l) { + foreach ($this->listenerIds[$eventName] as $i => $args) { + list($serviceId, $method, $priority) = $args; + if ($key === $serviceId.'.'.$method) { + if ($listener === array($l, $method)) { + unset($this->listeners[$eventName][$key]); + if (empty($this->listeners[$eventName])) { + unset($this->listeners[$eventName]); + } + unset($this->listenerIds[$eventName][$i]); + if (empty($this->listenerIds[$eventName])) { + unset($this->listenerIds[$eventName]); + } + } + } + } + } + } + + parent::removeListener($eventName, $listener); + } + + /** + * @see EventDispatcherInterface::hasListeners + */ + public function hasListeners($eventName = null) + { + if (null === $eventName) { + return (Boolean) count($this->listenerIds) || (Boolean) count($this->listeners); + } + + if (isset($this->listenerIds[$eventName])) { + return true; + } + + return parent::hasListeners($eventName); + } + + /** + * @see EventDispatcherInterface::getListeners + */ + public function getListeners($eventName = null) + { + if (null === $eventName) { + foreach (array_keys($this->listenerIds) as $serviceEventName) { + $this->lazyLoad($serviceEventName); + } + } else { + $this->lazyLoad($eventName); + } + + return parent::getListeners($eventName); + } + + /** + * Adds a service as event subscriber + * + * @param string $serviceId The service ID of the subscriber service + * @param string $class The service's class name (which must implement EventSubscriberInterface) + */ + public function addSubscriberService($serviceId, $class) + { + foreach ($class::getSubscribedEvents() as $eventName => $params) { + if (is_string($params)) { + $this->listenerIds[$eventName][] = array($serviceId, $params, 0); + } elseif (is_string($params[0])) { + $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); + } else { + foreach ($params as $listener) { + $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); + } + } + } + } + + /** + * {@inheritDoc} + * + * Lazily loads listeners for this event from the dependency injection + * container. + * + * @throws \InvalidArgumentException if the service is not defined + */ + public function dispatch($eventName, Event $event = null) + { + $this->lazyLoad($eventName); + + return parent::dispatch($eventName, $event); + } + + public function getContainer() + { + return $this->container; + } + + /** + * Lazily loads listeners for this event from the dependency injection + * container. + * + * @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. + */ + protected function lazyLoad($eventName) + { + if (isset($this->listenerIds[$eventName])) { + foreach ($this->listenerIds[$eventName] as $args) { + list($serviceId, $method, $priority) = $args; + $listener = $this->container->get($serviceId); + + $key = $serviceId.'.'.$method; + if (!isset($this->listeners[$eventName][$key])) { + $this->addListener($eventName, array($listener, $method), $priority); + } elseif ($listener !== $this->listeners[$eventName][$key]) { + parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); + $this->addListener($eventName, array($listener, $method), $priority); + } + + $this->listeners[$eventName][$key] = $listener; + } + } + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcherInterface.php b/core/vendor/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php similarity index 92% rename from core/vendor/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcherInterface.php rename to core/vendor/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php index 622acd6..0a53876 100644 --- a/core/vendor/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcherInterface.php +++ b/core/vendor/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpKernel\Debug; +namespace Symfony\Component\EventDispatcher\Debug; /** * @author Fabien Potencier diff --git a/core/vendor/Symfony/Component/EventDispatcher/EventDispatcher.php b/core/vendor/Symfony/Component/EventDispatcher/EventDispatcher.php index 8f712f1..b2fb51a 100644 --- a/core/vendor/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/core/vendor/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -123,7 +123,7 @@ class EventDispatcher implements EventDispatcherInterface if (is_string($params)) { $this->addListener($eventName, array($subscriber, $params)); } elseif (is_string($params[0])) { - $this->addListener($eventName, array($subscriber, $params[0]), $params[1]); + $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); diff --git a/core/vendor/Symfony/Component/EventDispatcher/GenericEvent.php b/core/vendor/Symfony/Component/EventDispatcher/GenericEvent.php new file mode 100644 index 0000000..0e792d0 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/GenericEvent.php @@ -0,0 +1,180 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * Event encapsulation class. + * + * Encapsulates events thus decoupling the observer from the subject they encapsulate. + * + * @author Drak + */ +class GenericEvent extends Event implements \ArrayAccess +{ + /** + * Observer pattern subject. + * + * @var mixed usually object or callable + */ + protected $subject; + + /** + * Array of arguments. + * + * @var array + */ + protected $arguments; + + /** + * Encapsulate an event with $subject, $args, and $data. + * + * @param mixed $subject The subject of the event, usually an object. + * @param array $arguments Arguments to store in the event. + */ + public function __construct($subject = null, array $arguments = array()) + { + $this->subject = $subject; + $this->arguments = $arguments; + } + + /** + * Getter for subject property. + * + * @return mixed $subject The observer subject. + */ + public function getSubject() + { + return $this->subject; + } + + /** + * Get argument by key. + * + * @param string $key Key. + * + * @throws \InvalidArgumentException If key is not found. + * + * @return mixed Contents of array key. + */ + public function getArgument($key) + { + if ($this->hasArgument($key)) { + return $this->arguments[$key]; + } + + throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName())); + } + + /** + * Add argument to event. + * + * @param string $key Argument name. + * @param mixed $value Value. + * + * @return GenericEvent + */ + public function setArgument($key, $value) + { + $this->arguments[$key] = $value; + + return $this; + } + + /** + * Getter for all arguments. + * + * @return array + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Set args property. + * + * @param array $args Arguments. + * + * @return GenericEvent + */ + public function setArguments(array $args = array()) + { + $this->arguments = $args; + + return $this; + } + + /** + * Has argument. + * + * @param string $key Key of arguments array. + * + * @return boolean + */ + public function hasArgument($key) + { + return array_key_exists($key, $this->arguments); + } + + /** + * ArrayAccess for argument getter. + * + * @param string $key Array key. + * + * @throws \InvalidArgumentException If key does not exist in $this->args. + * + * @return mixed + */ + public function offsetGet($key) + { + return $this->getArgument($key); + } + + /** + * ArrayAccess for argument setter. + * + * @param string $key Array key to set. + * @param mixed $value Value. + * + * @return void + */ + public function offsetSet($key, $value) + { + $this->setArgument($key, $value); + } + + /** + * ArrayAccess for unset argument. + * + * @param string $key Array key. + * + * @return void + */ + public function offsetUnset($key) + { + if ($this->hasArgument($key)) { + unset($this->arguments[$key]); + } + } + + /** + * ArrayAccess has argument. + * + * @param string $key Array key. + * + * @return boolean + */ + public function offsetExists($key) + { + return $this->hasArgument($key); + } +} diff --git a/core/vendor/Symfony/Component/EventDispatcher/README.md b/core/vendor/Symfony/Component/EventDispatcher/README.md index 9427d75..421b8c6 100644 --- a/core/vendor/Symfony/Component/EventDispatcher/README.md +++ b/core/vendor/Symfony/Component/EventDispatcher/README.md @@ -18,6 +18,13 @@ pattern. Resources --------- -Unit tests: +You can run the unit tests with the following command: -https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/EventDispatcher + phpunit -c src/Symfony/Component/EventDispatcher/ + +If you also want to run the unit tests that depend on other Symfony +Components, declare the following environment variables before running +PHPUnit: + + export SYMFONY_DEPENDENCY_INJECTION=../path/to/DependencyInjection + export SYMFONY_HTTP_KERNEL=../path/to/HttpKernel diff --git a/core/vendor/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php b/core/vendor/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php new file mode 100644 index 0000000..10f5e17 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php @@ -0,0 +1,256 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests; + +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\Scope; +use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\DependencyInjection\Container')) { + $this->markTestSkipped('The "DependencyInjection" component is not available'); + } + } + + public function testAddAListenerService() + { + $event = new Event(); + + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $service + ->expects($this->once()) + ->method('onEvent') + ->with($event) + ; + + $container = new Container(); + $container->set('service.listener', $service); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); + + $dispatcher->dispatch('onEvent', $event); + } + + public function testAddASubscriberService() + { + $event = new Event(); + + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\SubscriberService'); + + $service + ->expects($this->once()) + ->method('onEvent') + ->with($event) + ; + + $container = new Container(); + $container->set('service.subscriber', $service); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addSubscriberService('service.subscriber', 'Symfony\Component\EventDispatcher\Tests\SubscriberService'); + + $dispatcher->dispatch('onEvent', $event); + } + + public function testPreventDuplicateListenerService() + { + $event = new Event(); + + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $service + ->expects($this->once()) + ->method('onEvent') + ->with($event) + ; + + $container = new Container(); + $container->set('service.listener', $service); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 5); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 10); + + $dispatcher->dispatch('onEvent', $event); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testTriggerAListenerServiceOutOfScope() + { + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $scope = new Scope('scope'); + $container = new Container(); + $container->addScope($scope); + $container->enterScope('scope'); + + $container->set('service.listener', $service, 'scope'); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); + + $container->leaveScope('scope'); + $dispatcher->dispatch('onEvent'); + } + + public function testReEnteringAScope() + { + $event = new Event(); + + $service1 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $service1 + ->expects($this->exactly(2)) + ->method('onEvent') + ->with($event) + ; + + $scope = new Scope('scope'); + $container = new Container(); + $container->addScope($scope); + $container->enterScope('scope'); + + $container->set('service.listener', $service1, 'scope'); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); + $dispatcher->dispatch('onEvent', $event); + + $service2 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $service2 + ->expects($this->once()) + ->method('onEvent') + ->with($event) + ; + + $container->enterScope('scope'); + $container->set('service.listener', $service2, 'scope'); + + $dispatcher->dispatch('onEvent', $event); + + $container->leaveScope('scope'); + + $dispatcher->dispatch('onEvent'); + } + + public function testHasListenersOnLazyLoad() + { + $event = new Event(); + + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $container = new Container(); + $container->set('service.listener', $service); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); + + $event->setDispatcher($dispatcher); + $event->setName('onEvent'); + + $service + ->expects($this->once()) + ->method('onEvent') + ->with($event) + ; + + $this->assertTrue($dispatcher->hasListeners()); + + if ($dispatcher->hasListeners('onEvent')) { + $dispatcher->dispatch('onEvent'); + } + } + + public function testGetListenersOnLazyLoad() + { + $event = new Event(); + + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $container = new Container(); + $container->set('service.listener', $service); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); + + $listeners = $dispatcher->getListeners(); + + $this->assertTrue(isset($listeners['onEvent'])); + + $this->assertCount(1, $dispatcher->getListeners('onEvent')); + } + + public function testRemoveAfterDispatch() + { + $event = new Event(); + + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $container = new Container(); + $container->set('service.listener', $service); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); + + $dispatcher->dispatch('onEvent', new Event()); + $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); + $this->assertFalse($dispatcher->hasListeners('onEvent')); + } + + public function testRemoveBeforeDispatch() + { + $event = new Event(); + + $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + + $container = new Container(); + $container->set('service.listener', $service); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); + + $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); + $this->assertFalse($dispatcher->hasListeners('onEvent')); + } +} + +class Service +{ + function onEvent(Event $e) + { + } +} + +class SubscriberService implements EventSubscriberInterface +{ + static function getSubscribedEvents() { + return array( + 'onEvent' => 'onEvent', + 'onEvent' => array('onEvent', 10), + 'onEvent' => array('onEvent'), + ); + } + + function onEvent(Event $e) + { + } +} diff --git a/core/vendor/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php b/core/vendor/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php new file mode 100644 index 0000000..f38c695 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php @@ -0,0 +1,297 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests; + +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class EventDispatcherTest extends \PHPUnit_Framework_TestCase +{ + /* Some pseudo events */ + const preFoo = 'pre.foo'; + const postFoo = 'post.foo'; + const preBar = 'pre.bar'; + const postBar = 'post.bar'; + + private $dispatcher; + + private $listener; + + protected function setUp() + { + $this->dispatcher = new EventDispatcher(); + $this->listener = new TestEventListener(); + } + + protected function tearDown() + { + $this->dispatcher = null; + $this->listener = null; + } + + public function testInitialState() + { + $this->assertEquals(array(), $this->dispatcher->getListeners()); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); + } + + public function testAddListener() + { + $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); + $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); + $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo)); + $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo)); + $this->assertCount(2, $this->dispatcher->getListeners()); + } + + public function testGetListenersSortsByPriority() + { + $listener1 = new TestEventListener(); + $listener2 = new TestEventListener(); + $listener3 = new TestEventListener(); + $listener1->name = '1'; + $listener2->name = '2'; + $listener3->name = '3'; + + $this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10); + $this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10); + $this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo')); + + $expected = array( + array($listener2, 'preFoo'), + array($listener3, 'preFoo'), + array($listener1, 'preFoo'), + ); + + $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo')); + } + + public function testGetAllListenersSortsByPriority() + { + $listener1 = new TestEventListener(); + $listener2 = new TestEventListener(); + $listener3 = new TestEventListener(); + $listener4 = new TestEventListener(); + $listener5 = new TestEventListener(); + $listener6 = new TestEventListener(); + + $this->dispatcher->addListener('pre.foo', $listener1, -10); + $this->dispatcher->addListener('pre.foo', $listener2); + $this->dispatcher->addListener('pre.foo', $listener3, 10); + $this->dispatcher->addListener('post.foo', $listener4, -10); + $this->dispatcher->addListener('post.foo', $listener5); + $this->dispatcher->addListener('post.foo', $listener6, 10); + + $expected = array( + 'pre.foo' => array($listener3, $listener2, $listener1), + 'post.foo' => array($listener6, $listener5, $listener4), + ); + + $this->assertSame($expected, $this->dispatcher->getListeners()); + } + + public function testDispatch() + { + $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); + $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); + $this->dispatcher->dispatch(self::preFoo); + $this->assertTrue($this->listener->preFooInvoked); + $this->assertFalse($this->listener->postFooInvoked); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent')); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo)); + $event = new Event(); + $return = $this->dispatcher->dispatch(self::preFoo, $event); + $this->assertEquals('pre.foo', $event->getName()); + $this->assertSame($event, $return); + } + + public function testDispatchForClosure() + { + $invoked = 0; + $listener = function () use (&$invoked) { + $invoked++; + }; + $this->dispatcher->addListener('pre.foo', $listener); + $this->dispatcher->addListener('post.foo', $listener); + $this->dispatcher->dispatch(self::preFoo); + $this->assertEquals(1, $invoked); + } + + public function testStopEventPropagation() + { + $otherListener = new TestEventListener(); + + // postFoo() stops the propagation, so only one listener should + // be executed + // Manually set priority to enforce $this->listener to be called first + $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10); + $this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo')); + $this->dispatcher->dispatch(self::postFoo); + $this->assertTrue($this->listener->postFooInvoked); + $this->assertFalse($otherListener->postFooInvoked); + } + + public function testDispatchByPriority() + { + $invoked = array(); + $listener1 = function () use (&$invoked) { + $invoked[] = '1'; + }; + $listener2 = function () use (&$invoked) { + $invoked[] = '2'; + }; + $listener3 = function () use (&$invoked) { + $invoked[] = '3'; + }; + $this->dispatcher->addListener('pre.foo', $listener1, -10); + $this->dispatcher->addListener('pre.foo', $listener2); + $this->dispatcher->addListener('pre.foo', $listener3, 10); + $this->dispatcher->dispatch(self::preFoo); + $this->assertEquals(array('3', '2', '1'), $invoked); + } + + public function testRemoveListener() + { + $this->dispatcher->addListener('pre.bar', $this->listener); + $this->assertTrue($this->dispatcher->hasListeners(self::preBar)); + $this->dispatcher->removeListener('pre.bar', $this->listener); + $this->assertFalse($this->dispatcher->hasListeners(self::preBar)); + $this->dispatcher->removeListener('notExists', $this->listener); + } + + public function testAddSubscriber() + { + $eventSubscriber = new TestEventSubscriber(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); + } + + public function testAddSubscriberWithPriorities() + { + $eventSubscriber = new TestEventSubscriber(); + $this->dispatcher->addSubscriber($eventSubscriber); + + $eventSubscriber = new TestEventSubscriberWithPriorities(); + $this->dispatcher->addSubscriber($eventSubscriber); + + $listeners = $this->dispatcher->getListeners('pre.foo'); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertCount(2, $listeners); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]); + } + + public function testAddSubscriberWithMultipleListeners() + { + $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); + $this->dispatcher->addSubscriber($eventSubscriber); + + $listeners = $this->dispatcher->getListeners('pre.foo'); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertCount(2, $listeners); + $this->assertEquals('preFoo2', $listeners[0][1]); + } + + public function testRemoveSubscriber() + { + $eventSubscriber = new TestEventSubscriber(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); + $this->dispatcher->removeSubscriber($eventSubscriber); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); + } + + public function testRemoveSubscriberWithPriorities() + { + $eventSubscriber = new TestEventSubscriberWithPriorities(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->dispatcher->removeSubscriber($eventSubscriber); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + } + + public function testRemoveSubscriberWithMultipleListeners() + { + $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo)); + $this->dispatcher->removeSubscriber($eventSubscriber); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + } + + public function testEventReceivesTheDispatcherInstance() + { + $test = $this; + $this->dispatcher->addListener('test', function ($event) use (&$dispatcher) { + $dispatcher = $event->getDispatcher(); + }); + $this->dispatcher->dispatch('test'); + $this->assertSame($this->dispatcher, $dispatcher); + } +} + +class TestEventListener +{ + public $preFooInvoked = false; + public $postFooInvoked = false; + + /* Listener methods */ + + public function preFoo(Event $e) + { + $this->preFooInvoked = true; + } + + public function postFoo(Event $e) + { + $this->postFooInvoked = true; + + $e->stopPropagation(); + } +} + +class TestEventSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo'); + } +} + +class TestEventSubscriberWithPriorities implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return array( + 'pre.foo' => array('preFoo', 10), + 'post.foo' => array('postFoo'), + ); + } +} + +class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return array('pre.foo' => array( + array('preFoo1'), + array('preFoo2', 10) + )); + } +} diff --git a/core/vendor/Symfony/Component/EventDispatcher/Tests/EventTest.php b/core/vendor/Symfony/Component/EventDispatcher/Tests/EventTest.php new file mode 100644 index 0000000..cbc3910 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/Tests/EventTest.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests; + +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; + +/** + * Test class for Event. + */ +class EventTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\EventDispatcher\Event + */ + protected $event; + + /** + * @var \Symfony\Component\EventDispatcher\EventDispatcher + */ + protected $dispatcher; + + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + $this->event = new Event; + $this->dispatcher = new EventDispatcher(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + $this->event = null; + $this->eventDispatcher = null; + } + + public function testIsPropagationStopped() + { + $this->assertFalse($this->event->isPropagationStopped()); + } + + public function testStopPropagationAndIsPropagationStopped() + { + $this->event->stopPropagation(); + $this->assertTrue($this->event->isPropagationStopped()); + } + + public function testSetDispatcher() + { + $this->event->setDispatcher($this->dispatcher); + $this->assertSame($this->dispatcher, $this->event->getDispatcher()); + } + + public function testGetDispatcher() + { + $this->assertNull($this->event->getDispatcher()); + } + + public function testGetName() + { + $this->assertNull($this->event->getName()); + } + + public function testSetName() + { + $this->event->setName('foo'); + $this->assertEquals('foo', $this->event->getName()); + } +} diff --git a/core/vendor/Symfony/Component/EventDispatcher/Tests/GenericEventTest.php b/core/vendor/Symfony/Component/EventDispatcher/Tests/GenericEventTest.php new file mode 100644 index 0000000..6c9a610 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/Tests/GenericEventTest.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests; + +use Symfony\Component\EventDispatcher\GenericEvent; + +/** + * Test class for Event. + */ +class GenericEventTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @var GenericEvent + */ + private $event; + + private $subject; + + /** + * Prepares the environment before running a test. + */ + protected function setUp() + { + parent::setUp(); + + $this->subject = new \StdClass(); + $this->event = new GenericEvent($this->subject, array('name' => 'Event'), 'foo'); + } + + /** + * Cleans up the environment after running a test. + */ + protected function tearDown() + { + $this->subject = null; + $this->event = null; + + parent::tearDown(); + } + + public function test__construct() + { + $this->assertEquals($this->event, new GenericEvent($this->subject, array('name' => 'Event'))); + } + + /** + * Tests Event->getArgs() + */ + public function testGetArguments() + { + // test getting all + $this->assertSame(array('name' => 'Event'), $this->event->getArguments()); + } + + public function testSetArguments() + { + $result = $this->event->setArguments(array('foo' => 'bar')); + $this->assertAttributeSame(array('foo' => 'bar'), 'arguments', $this->event); + $this->assertSame($this->event, $result); + } + + public function testSetArgument() + { + $result = $this->event->setArgument('foo2', 'bar2'); + $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event); + $this->assertEquals($this->event, $result); + } + + public function testGetArgument() + { + // test getting key + $this->assertEquals('Event', $this->event->getArgument('name')); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testGetArgException() + { + $this->event->getArgument('nameNotExist'); + } + + public function testOffsetGet() + { + // test getting key + $this->assertEquals('Event', $this->event['name']); + + // test getting invalid arg + $this->setExpectedException('InvalidArgumentException'); + $this->assertFalse($this->event['nameNotExist']); + } + + public function testOffsetSet() + { + $this->event['foo2'] = 'bar2'; + $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event); + } + + public function testOffsetUnset() + { + unset($this->event['name']); + $this->assertAttributeSame(array(), 'arguments', $this->event); + } + + public function testOffsetIsset() + { + $this->assertTrue(isset($this->event['name'])); + $this->assertFalse(isset($this->event['nameNotExist'])); + } + + public function testHasArgument() + { + $this->assertTrue($this->event->hasArgument('name')); + $this->assertFalse($this->event->hasArgument('nameNotExist')); + } + + public function testGetSubject() + { + $this->assertSame($this->subject, $this->event->getSubject()); + } +} diff --git a/core/vendor/Symfony/Component/EventDispatcher/Tests/bootstrap.php b/core/vendor/Symfony/Component/EventDispatcher/Tests/bootstrap.php new file mode 100644 index 0000000..b71ee52 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/Tests/bootstrap.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + foreach (array( + 'SYMFONY_DEPENDENCY_INJECTION' => 'DependencyInjection', + 'SYMFONY_HTTP_KERNEL' => 'HttpKernel', + ) as $env => $name) { + if (isset($_SERVER[$env]) && 0 === strpos(ltrim($class, '/'), 'Symfony\Component\\'.$name)) { + if (file_exists($file = $_SERVER[$env].'/'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\\'.$name)).'.php')) { + require_once $file; + } + } + } + + if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\EventDispatcher')) { + if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\EventDispatcher')).'.php')) { + require_once $file; + } + } +}); diff --git a/core/vendor/Symfony/Component/EventDispatcher/composer.json b/core/vendor/Symfony/Component/EventDispatcher/composer.json index 0c8d455..d93d09f 100644 --- a/core/vendor/Symfony/Component/EventDispatcher/composer.json +++ b/core/vendor/Symfony/Component/EventDispatcher/composer.json @@ -18,6 +18,10 @@ "require": { "php": ">=5.3.2" }, + "suggest": { + "symfony/dependency-injection": "self.version", + "symfony/http-kernel": "self.version" + }, "autoload": { "psr-0": { "Symfony\\Component\\EventDispatcher": "" } }, diff --git a/core/vendor/Symfony/Component/EventDispatcher/phpunit.xml.dist b/core/vendor/Symfony/Component/EventDispatcher/phpunit.xml.dist new file mode 100644 index 0000000..cb261a4 --- /dev/null +++ b/core/vendor/Symfony/Component/EventDispatcher/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + + + + diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/File.php b/core/vendor/Symfony/Component/HttpFoundation/File/File.php index 3134ccd..20a80ca 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/File/File.php +++ b/core/vendor/Symfony/Component/HttpFoundation/File/File.php @@ -122,7 +122,7 @@ class File extends \SplFileInfo throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); } - chmod($target, 0666); + chmod($target, 0666 & ~umask()); return new File($target); } diff --git a/core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php b/core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php index 9670fed..88ad1af 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php @@ -50,16 +50,13 @@ class HeaderBag implements \IteratorAggregate, \Countable return ''; } - $beautifier = function ($name) { - return preg_replace_callback('/\-(.)/', function ($match) { return '-'.strtoupper($match[1]); }, ucfirst($name)); - }; - $max = max(array_map('strlen', array_keys($this->headers))) + 1; $content = ''; ksort($this->headers); foreach ($this->headers as $name => $values) { + $name = implode('-', array_map('ucfirst', explode('-', $name))); foreach ($values as $value) { - $content .= sprintf("%-{$max}s %s\r\n", $beautifier($name).':', $value); + $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php b/core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php index db54134..b4fa676 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php +++ b/core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php @@ -109,7 +109,7 @@ class ParameterBag implements \IteratorAggregate, \Countable $value = $this->parameters[$root]; $currentKey = null; - for ($i=$pos,$c=strlen($path); $i<$c; $i++) { + for ($i = $pos, $c = strlen($path); $i < $c; $i++) { $char = $path[$i]; if ('[' === $char) { @@ -240,7 +240,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * - * @return string The filtered value + * @return integer The filtered value * * @api */ diff --git a/core/vendor/Symfony/Component/HttpFoundation/README.md b/core/vendor/Symfony/Component/HttpFoundation/README.md index 88adfed..8e5d8cf 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/README.md +++ b/core/vendor/Symfony/Component/HttpFoundation/README.md @@ -38,10 +38,9 @@ If you are using PHP 5.3.x you must add the following to your autoloader: $loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs'); } - Resources --------- -Unit tests: +You can run the unit tests with the following command: -https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/HttpFoundation + phpunit -c src/Symfony/Component/HttpFoundation/ diff --git a/core/vendor/Symfony/Component/HttpFoundation/Request.php b/core/vendor/Symfony/Component/HttpFoundation/Request.php index 87dace3..b4fd7ac 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Request.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Request.php @@ -16,6 +16,14 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Request represents an HTTP request. * + * The methods dealing with URL accept / return a raw path (% encoded): + * * getBasePath + * * getBaseUrl + * * getPathInfo + * * getRequestUri + * * getUri + * * getUriForPath + * * @author Fabien Potencier * * @api @@ -568,9 +576,10 @@ class Request * * * http://localhost/mysite returns an empty string * * http://localhost/mysite/about returns '/about' + * * htpp://localhost/mysite/enco%20ded returns '/enco%20ded' * * http://localhost/mysite/about?var=1 returns '/about' * - * @return string + * @return string The raw path (i.e. not urldecoded) * * @api */ @@ -588,11 +597,12 @@ class Request * * Suppose that an index.php file instantiates this request object: * - * * http://localhost/index.php returns an empty string - * * http://localhost/index.php/page returns an empty string - * * http://localhost/web/index.php return '/web' + * * http://localhost/index.php returns an empty string + * * http://localhost/index.php/page returns an empty string + * * http://localhost/web/index.php returns '/web' + * * http://localhost/we%20b/index.php returns '/we%20b' * - * @return string + * @return string The raw path (i.e. not urldecoded) * * @api */ @@ -613,7 +623,7 @@ class Request * This is similar to getBasePath(), except that it also includes the * script filename (e.g. index.php) if one exists. * - * @return string + * @return string The raw url (i.e. not urldecoded) * * @api */ @@ -698,7 +708,7 @@ class Request /** * Returns the requested URI. * - * @return string + * @return string The raw URI (i.e. not urldecoded) * * @api */ @@ -833,7 +843,7 @@ class Request // Remove port number from host $host = preg_replace('/:\d+$/', '', $host); - // host is lowercase as per RFC2616 + // host is lowercase as per RFC 952/2181 return trim(strtolower($host)); } @@ -1017,6 +1027,18 @@ class Request } /** + * Checks if the request method is of specified type. + * + * @param string $method Uppercase request method (GET, POST etc). + * + * @return Boolean + */ + public function isMethod($method) + { + return $this->getMethod() === strtoupper($method); + } + + /** * Checks whether the method is safe or not. * * @return Boolean @@ -1289,14 +1311,14 @@ class Request // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); - if ($baseUrl && 0 === strpos($requestUri, $baseUrl)) { + if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { // full $baseUrl matches - return $baseUrl; + return $prefix; } - if ($baseUrl && 0 === strpos($requestUri, dirname($baseUrl))) { + if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl))) { // directory portion of $baseUrl matches - return rtrim(dirname($baseUrl), '/'); + return rtrim($prefix, '/'); } $truncatedRequestUri = $requestUri; @@ -1305,7 +1327,7 @@ class Request } $basename = basename($baseUrl); - if (empty($basename) || !strpos($truncatedRequestUri, $basename)) { + if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { // no match whatsoever; set it blank return ''; } @@ -1366,7 +1388,7 @@ class Request $requestUri = substr($requestUri, 0, $pos); } - if ((null !== $baseUrl) && (false === ($pathInfo = substr(urldecode($requestUri), strlen(urldecode($baseUrl)))))) { + if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) { // If substr() returns false then PATH_INFO is set to an empty string return '/'; } elseif (null === $baseUrl) { @@ -1411,4 +1433,28 @@ class Request } catch (\Exception $e) { } } + + /* + * Returns the prefix as encoded in the string when the string starts with + * the given prefix, false otherwise. + * + * @param string $string The urlencoded string + * @param string $prefix The prefix not encoded + * + * @return string|false The prefix as it is encoded in $string, or false + */ + private function getUrlencodedPrefix($string, $prefix) + { + if (0 !== strpos(rawurldecode($string), $prefix)) { + return false; + } + + $len = strlen($prefix); + + if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) { + return $match[0]; + } + + return false; + } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php b/core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php index 0ca082d..09c548c 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php +++ b/core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php @@ -127,7 +127,7 @@ class RequestMatcher implements RequestMatcherInterface if (null !== $this->path) { $path = str_replace('#', '\\#', $this->path); - if (!preg_match('#'.$path.'#', $request->getPathInfo())) { + if (!preg_match('#'.$path.'#', rawurldecode($request->getPathInfo()))) { return false; } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/Response.php b/core/vendor/Symfony/Component/HttpFoundation/Response.php index 3a0a22e..5d443ef 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Response.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Response.php @@ -83,6 +83,7 @@ class Response 305 => 'Use Proxy', 306 => 'Reserved', 307 => 'Temporary Redirect', + 308 => 'Permanent Redirect', // RFC-reschke-http-status-308-07 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', @@ -165,7 +166,7 @@ class Response /** * Returns the Response as an HTTP string. * - * The string representation of the Resonse is the same as the + * The string representation of the Response is the same as the * one that will be sent to the client only if the prepare() method * has been called before. * @@ -197,6 +198,8 @@ class Response * the Request that is "associated" with this Response. * * @param Request $request A Request instance + * + * @return Response The current response. */ public function prepare(Request $request) { @@ -236,6 +239,8 @@ class Response $headers->set('Content-Length', $length); } } + + return $this; } /** diff --git a/core/vendor/Symfony/Component/HttpFoundation/ServerBag.php b/core/vendor/Symfony/Component/HttpFoundation/ServerBag.php index 9b57f9e..6a077f4 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/ServerBag.php +++ b/core/vendor/Symfony/Component/HttpFoundation/ServerBag.php @@ -33,7 +33,7 @@ class ServerBag extends ParameterBag } // CONTENT_* are not prefixed with HTTP_ elseif (in_array($key, array('CONTENT_LENGTH', 'CONTENT_MD5', 'CONTENT_TYPE'))) { - $headers[$key] = $this->parameters[$key]; + $headers[$key] = $value; } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php index 48ccf05..7da1227 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php @@ -21,6 +21,14 @@ use Symfony\Component\HttpFoundation\Session\SessionBagInterface; interface FlashBagInterface extends SessionBagInterface { /** + * Adds a flash message for type. + * + * @param string $type + * @param string $message + */ + public function add($type, $message); + + /** * Registers a message for a given type. * * @param string $type diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Session.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Session.php index 145f964..0c40c1c 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Session.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Session.php @@ -57,13 +57,13 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable { $this->storage = $storage ?: new NativeSessionStorage(); - $attributeBag = $attributes ?: new AttributeBag(); - $this->attributeName = $attributeBag->getName(); - $this->registerBag($attributeBag); + $attributes = $attributes ?: new AttributeBag(); + $this->attributeName = $attributes->getName(); + $this->registerBag($attributes); - $flashBag = $flashes ?: new FlashBag(); - $this->flashName = $flashBag->getName(); - $this->registerBag($flashBag); + $flashes = $flashes ?: new FlashBag(); + $this->flashName = $flashes->getName(); + $this->registerBag($flashes); } /** @@ -131,21 +131,41 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable } /** + * Returns an iterator for attributes. + * + * @return \ArrayIterator An \ArrayIterator instance + */ + public function getIterator() + { + return new \ArrayIterator($this->storage->getBag($this->attributeName)->all()); + } + + /** + * Returns the number of attributes. + * + * @return int The number of attributes + */ + public function count() + { + return count($this->storage->getBag($this->attributeName)->all()); + } + + /** * {@inheritdoc} */ - public function invalidate() + public function invalidate($lifetime = null) { $this->storage->clear(); - return $this->storage->regenerate(true); + return $this->migrate(true, $lifetime); } /** * {@inheritdoc} */ - public function migrate($destroy = false) + public function migrate($destroy = false, $lifetime = null) { - return $this->storage->regenerate($destroy); + return $this->storage->regenerate($destroy, $lifetime); } /** @@ -189,9 +209,15 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable } /** - * Registers a SessionBagInterface with the session. - * - * @param SessionBagInterface $bag + * {@iheritdoc} + */ + public function getMetadataBag() + { + return $this->storage->getMetadataBag(); + } + + /** + * {@iheritdoc} */ public function registerBag(SessionBagInterface $bag) { @@ -199,11 +225,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable } /** - * Get's a bag instance. - * - * @param string $name - * - * @return SessionBagInterface + * {@iheritdoc} */ public function getBag($name) { @@ -310,24 +332,4 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable { return $this->getBag($this->flashName)->clear(); } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator An \ArrayIterator instance - */ - public function getIterator() - { - return new \ArrayIterator($this->storage->getBag('attributes')->all()); - } - - /** - * Returns the number of attributes. - * - * @return int The number of attributes - */ - public function count() - { - return count($this->storage->getBag('attributes')->all()); - } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/SessionInterface.php b/core/vendor/Symfony/Component/HttpFoundation/Session/SessionInterface.php index 4e4962d..15b4c29 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/SessionInterface.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/SessionInterface.php @@ -71,23 +71,32 @@ interface SessionInterface * Clears all session attributes and flashes and regenerates the * session and deletes the old session from persistence. * + * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. + * * @return Boolean True if session invalidated, false if error. * * @api */ - function invalidate(); + function invalidate($lifetime = null); /** * Migrates the current session to a new session id while maintaining all * session attributes. * - * @param Boolean $destroy Whether to delete the old session or leave it to garbage collection. + * @param Boolean $destroy Whether to delete the old session or leave it to garbage collection. + * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. * * @return Boolean True if session migrated, false if error. * * @api */ - function migrate($destroy = false); + function migrate($destroy = false, $lifetime = null); /** * Force the session to be saved and closed. @@ -164,4 +173,27 @@ interface SessionInterface * @api */ function clear(); + + /** + * Registers a SessionBagInterface with the session. + * + * @param SessionBagInterface $bag + */ + public function registerBag(SessionBagInterface $bag); + + /** + * Gets a bag instance by name. + * + * @param string $name + * + * @return SessionBagInterface + */ + public function getBag($name); + + /** + * Gets session meta. + * + * @return MetadataBag + */ + public function getMetadataBag(); } diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index 00488fd..fe29832 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -117,7 +117,10 @@ class MemcacheSessionHandler implements \SessionHandlerInterface */ public function write($sessionId, $data) { - return $this->memcache->set($this->prefix.$sessionId, $data, 0, $this->memcacheOptions['expiretime']); + if (!$this->memcache->replace($this->prefix.$sessionId, $data, 0, $this->memcacheOptions['expiretime'])) { + return $this->memcache->set($this->prefix.$sessionId, $data, 0, $this->memcacheOptions['expiretime']); + } + return true; } /** diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php index baacf29..4fea88b 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php @@ -51,13 +51,16 @@ class NativeMemcacheSessionHandler extends NativeSessionHandler */ protected function setOptions(array $options) { + $validOptions = array_flip(array( + 'memcache.allow_failover', 'memcache.max_failover_attempts', + 'memcache.chunk_size', 'memcache.default_port', 'memcache.hash_strategy', + 'memcache.hash_function', 'memcache.protocol', 'memcache.redundancy', + 'memcache.session_redundancy', 'memcache.compress_threshold', + 'memcache.lock_timeout', + )); + foreach ($options as $key => $value) { - if (in_array($key, array( - 'memcache.allow_failover', 'memcache.max_failover_attempts', - 'memcache.chunk_size', 'memcache.default_port', 'memcache.hash_strategy', - 'memcache.hash_function', 'memcache.protocol', 'memcache.redundancy', - 'memcache.session_redundancy', 'memcache.compress_threshold', - 'memcache.lock_timeout'))) { + if (isset($validOptions[$key])) { ini_set($key, $value); } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php index d84bdfb..8f64660 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php @@ -51,12 +51,15 @@ class NativeMemcachedSessionHandler extends NativeSessionHandler */ protected function setOptions(array $options) { + $validOptions = array_flip(array( + 'memcached.sess_locking', 'memcached.sess_lock_wait', + 'memcached.sess_prefix', 'memcached.compression_type', + 'memcached.compression_factor', 'memcached.compression_threshold', + 'memcached.serializer', + )); + foreach ($options as $key => $value) { - if (in_array($key, array( - 'memcached.sess_locking', 'memcached.sess_lock_wait', - 'memcached.sess_prefix', 'memcached.compression_type', - 'memcached.compression_factor', 'memcached.compression_threshold', - 'memcached.serializer'))) { + if (isset($validOptions[$key])) { ini_set($key, $value); } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php new file mode 100644 index 0000000..892d004 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php @@ -0,0 +1,160 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + +/** + * Metadata container. + * + * Adds metadata to the session. + * + * @author Drak + */ +class MetadataBag implements SessionBagInterface +{ + const CREATED = 'c'; + const UPDATED = 'u'; + const LIFETIME = 'l'; + + /** + * @var string + */ + private $name = '__metadata'; + + /** + * @var string + */ + private $storageKey; + + /** + * @var array + */ + protected $meta = array(); + + /** + * Unix timestamp. + * + * @var integer + */ + private $lastUsed; + + /** + * Constructor. + * + * @param string $storageKey The key used to store bag in the session. + */ + public function __construct($storageKey = '_sf2_meta') + { + $this->storageKey = $storageKey; + $this->meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0); + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$array) + { + $this->meta = &$array; + + if (isset($array[self::CREATED])) { + $this->lastUsed = $this->meta[self::UPDATED]; + $this->meta[self::UPDATED] = time(); + } else { + $this->stampCreated(); + } + } + + /** + * Gets the lifetime that the session cookie was set with. + * + * @return integer + */ + public function getLifetime() + { + return $this->meta[self::LIFETIME]; + } + + /** + * Stamps a new session's metadata. + * + * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. + */ + public function stampNew($lifetime = null) + { + $this->stampCreated($lifetime); + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } + + /** + * Gets the created timestamp metadata. + * + * @return integer Unix timestamp + */ + public function getCreated() + { + return $this->meta[self::CREATED]; + } + + /** + * Gets the last used metadata. + * + * @return integer Unix timestamp + */ + public function getLastUsed() + { + return $this->lastUsed; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + // nothing to do + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * Sets name. + * + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + private function stampCreated($lifetime = null) + { + $timeStamp = time(); + $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; + $this->meta[self::LIFETIME] = (null === $lifetime) ? ini_get('session.cookie_lifetime') : $lifetime; + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index 6f1e279..5500a03 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; /** * MockArraySessionStorage mocks the session for unit tests. @@ -53,13 +54,20 @@ class MockArraySessionStorage implements SessionStorageInterface protected $data = array(); /** + * @var MetadataBag + */ + protected $metadataBag; + + /** * Constructor. * - * @param string $name Session name + * @param string $name Session name + * @param MetadataBag $metaBag MetadataBag instance. */ - public function __construct($name = 'MOCKSESSID') + public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->name = $name; + $this->setMetadataBag($metaBag); } /** @@ -90,16 +98,16 @@ class MockArraySessionStorage implements SessionStorageInterface return true; } - /** * {@inheritdoc} */ - public function regenerate($destroy = false) + public function regenerate($destroy = false, $lifetime = null) { if (!$this->started) { $this->start(); } + $this->metadataBag->stampNew($lifetime); $this->id = $this->generateId(); return true; @@ -192,6 +200,30 @@ class MockArraySessionStorage implements SessionStorageInterface } /** + * Sets the MetadataBag. + * + * @param MetadataBag $bag + */ + public function setMetadataBag(MetadataBag $bag = null) + { + if (null === $bag) { + $bag = new MetadataBag(); + } + + $this->metadataBag = $bag; + } + + /** + * Gets the MetadataBag. + * + * @return MetadataBag + */ + public function getMetadataBag() + { + return $this->metadataBag; + } + + /** * Generates a session ID. * * This doesn't need to be particularly cryptographically secure since this is just @@ -206,7 +238,9 @@ class MockArraySessionStorage implements SessionStorageInterface protected function loadSession() { - foreach ($this->bags as $bag) { + $bags = array_merge($this->bags, array($this->metadataBag)); + + foreach ($bags as $bag) { $key = $bag->getStorageKey(); $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array(); $bag->initialize($this->data[$key]); diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php index 2445731..5bf2962 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php @@ -29,6 +29,8 @@ class MockFileSessionStorage extends MockArraySessionStorage */ private $savePath; + private $sessionData; + /** * Constructor. * @@ -73,15 +75,17 @@ class MockFileSessionStorage extends MockArraySessionStorage /** * {@inheritdoc} */ - public function regenerate($destroy = false) + public function regenerate($destroy = false, $lifetime = null) { + if (!$this->started) { + $this->start(); + } + if ($destroy) { $this->destroy(); } - $this->id = $this->generateId(); - - return true; + return parent::regenerate($destroy, $lifetime); } /** diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 5252bf5..215ed26 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; @@ -46,6 +47,11 @@ class NativeSessionStorage implements SessionStorageInterface protected $saveHandler; /** + * @var MetadataBag + */ + protected $metadataBag; + + /** * Constructor. * * Depending on how you want the storage driver to behave you probably @@ -83,10 +89,11 @@ class NativeSessionStorage implements SessionStorageInterface * upload_progress.min-freq, "1" * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" * - * @param array $options Session configuration options. - * @param object $handler SessionHandlerInterface. + * @param array $options Session configuration options. + * @param object $handler SessionHandlerInterface. + * @param MetadataBag $handler MetadataBag. */ - public function __construct(array $options = array(), $handler = null) + public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { // sensible defaults ini_set('session.auto_start', 0); // by default we prefer to explicitly start the session using the class. @@ -99,6 +106,7 @@ class NativeSessionStorage implements SessionStorageInterface register_shutdown_function('session_write_close'); } + $this->setMetadataBag($metaBag); $this->setOptions($options); $this->setSaveHandler($handler); } @@ -187,8 +195,16 @@ class NativeSessionStorage implements SessionStorageInterface /** * {@inheritdoc} */ - public function regenerate($destroy = false) + public function regenerate($destroy = false, $lifetime = null) { + if (null !== $lifetime) { + ini_set('session.cookie_lifetime', $lifetime); + } + + if ($destroy) { + $this->metadataBag->stampNew(); + } + return session_regenerate_id($destroy); } @@ -250,6 +266,30 @@ class NativeSessionStorage implements SessionStorageInterface } /** + * Sets the MetadataBag. + * + * @param MetadataBag $metaBag + */ + public function setMetadataBag(MetadataBag $metaBag = null) + { + if (null === $metaBag) { + $metaBag = new MetadataBag(); + } + + $this->metadataBag = $metaBag; + } + + /** + * Gets the MetadataBag. + * + * @return MetadataBag + */ + public function getMetadataBag() + { + return $this->metadataBag; + } + + /** * Sets session.* ini variables. * * For convenience we omit 'session.' from the beginning of the keys. @@ -261,17 +301,20 @@ class NativeSessionStorage implements SessionStorageInterface */ public function setOptions(array $options) { + $validOptions = array_flip(array( + 'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly', + 'cookie_lifetime', 'cookie_path', 'cookie_secure', + 'entropy_file', 'entropy_length', 'gc_divisor', + 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', + 'hash_function', 'name', 'referer_check', + 'serialize_handler', 'use_cookies', + 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', + 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', + 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', + )); + foreach ($options as $key => $value) { - if (in_array($key, array( - 'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', - 'entropy_file', 'entropy_length', 'gc_divisor', - 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', - 'hash_function', 'name', 'referer_check', - 'serialize_handler', 'use_cookies', - 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', - 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'))) { + if (isset($validOptions[$key])) { ini_set('session.'.$key, $value); } } @@ -335,7 +378,9 @@ class NativeSessionStorage implements SessionStorageInterface $session = &$_SESSION; } - foreach ($this->bags as $bag) { + $bags = array_merge($this->bags, array($this->metadataBag)); + + foreach ($bags as $bag) { $key = $bag->getStorageKey(); $session[$key] = isset($session[$key]) ? $session[$key] : array(); $bag->initialize($session[$key]); diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php index 8bf2e5d..20c533c 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php +++ b/core/vendor/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; /** * StorageInterface. @@ -81,7 +82,11 @@ interface SessionStorageInterface * Note regenerate+destroy should not clear the session data in memory * only delete the session data from persistent storage. * - * @param Boolean $destroy Destroy session when regenerating? + * @param Boolean $destroy Destroy session when regenerating? + * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. * * @return Boolean True if session regenerated, false if error * @@ -89,7 +94,7 @@ interface SessionStorageInterface * * @api */ - function regenerate($destroy = false); + function regenerate($destroy = false, $lifetime = null); /** * Force the session to be saved and closed. @@ -123,4 +128,9 @@ interface SessionStorageInterface * @param SessionBagInterface $bag */ function registerBag(SessionBagInterface $bag); + + /** + * @return MetadataBag + */ + function getMetadataBag(); } diff --git a/core/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php b/core/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php index 1952a84..599170f 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php +++ b/core/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php @@ -82,7 +82,7 @@ class StreamedResponse extends Response $this->headers->set('Cache-Control', 'no-cache'); - parent::prepare($request); + return parent::prepare($request); } /** diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.php new file mode 100644 index 0000000..965a7d2 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\ApacheRequest; + +class ApacheRequestTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider provideServerVars + */ + public function testUriMethods($server, $expectedRequestUri, $expectedBaseUrl, $expectedPathInfo) + { + $request = new ApacheRequest(); + $request->server->replace($server); + + $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct'); + $this->assertEquals($expectedBaseUrl, $request->getBaseUrl(), '->getBaseUrl() is correct'); + $this->assertEquals($expectedPathInfo, $request->getPathInfo(), '->getPathInfo() is correct'); + } + + public function provideServerVars() + { + return array( + array( + array( + 'REQUEST_URI' => '/foo/app_dev.php/bar', + 'SCRIPT_NAME' => '/foo/app_dev.php', + 'PATH_INFO' => '/bar', + ), + '/foo/app_dev.php/bar', + '/foo/app_dev.php', + '/bar' + ), + array( + array( + 'REQUEST_URI' => '/foo/bar', + 'SCRIPT_NAME' => '/foo/app_dev.php', + ), + '/foo/bar', + '/foo', + '/bar', + ), + array( + array( + 'REQUEST_URI' => '/app_dev.php/foo/bar', + 'SCRIPT_NAME' => '/app_dev.php', + 'PATH_INFO' => '/foo/bar', + ), + '/app_dev.php/foo/bar', + '/app_dev.php', + '/foo/bar', + ), + array( + array( + 'REQUEST_URI' => '/foo/bar', + 'SCRIPT_NAME' => '/app_dev.php', + ), + '/foo/bar', + '', + '/foo/bar', + ), + array( + array( + 'REQUEST_URI' => '/app_dev.php', + 'SCRIPT_NAME' => '/app_dev.php', + ), + '/app_dev.php', + '/app_dev.php', + '/', + ), + array( + array( + 'REQUEST_URI' => '/', + 'SCRIPT_NAME' => '/app_dev.php', + ), + '/', + '', + '/', + ), + ); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/CookieTest.php new file mode 100644 index 0000000..6a9948d --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\Cookie; + +/** + * CookieTest + * + * @author John Kary + * @author Hugo Hamon + */ +class CookieTest extends \PHPUnit_Framework_TestCase +{ + public function invalidNames() + { + return array( + array(''), + array(",MyName"), + array(";MyName"), + array(" MyName"), + array("\tMyName"), + array("\rMyName"), + array("\nMyName"), + array("\013MyName"), + array("\014MyName"), + ); + } + + /** + * @dataProvider invalidNames + * @expectedException InvalidArgumentException + * @covers Symfony\Component\HttpFoundation\Cookie::__construct + */ + public function testInstantiationThrowsExceptionIfCookieNameContainsInvalidCharacters($name) + { + new Cookie($name); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidExpiration() + { + $cookie = new Cookie('MyCookie', 'foo','bar'); + } + + /** + * @covers Symfony\Component\HttpFoundation\Cookie::getValue + */ + public function testGetValue() + { + $value = 'MyValue'; + $cookie = new Cookie('MyCookie', $value); + + $this->assertSame($value, $cookie->getValue(), '->getValue() returns the proper value'); + } + + public function testGetPath() + { + $cookie = new Cookie('foo', 'bar'); + + $this->assertSame('/', $cookie->getPath(), '->getPath() returns / as the default path'); + } + + public function testGetExpiresTime() + { + $cookie = new Cookie('foo', 'bar', 3600); + + $this->assertEquals(3600, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); + } + + public function testGetDomain() + { + $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com'); + + $this->assertEquals('.myfoodomain.com', $cookie->getDomain(), '->getDomain() returns the domain name on which the cookie is valid'); + } + + public function testIsSecure() + { + $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', true); + + $this->assertTrue($cookie->isSecure(), '->isSecure() returns whether the cookie is transmitted over HTTPS'); + } + + public function testIsHttpOnly() + { + $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', false, true); + + $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns whether the cookie is only transmitted over HTTP'); + } + + public function testCookieIsNotCleared() + { + $cookie = new Cookie('foo', 'bar', time()+3600*24); + + $this->assertFalse($cookie->isCleared(), '->isCleared() returns false if the cookie did not expire yet'); + } + + public function testCookieIsCleared() + { + $cookie = new Cookie('foo', 'bar', time()-20); + + $this->assertTrue($cookie->isCleared(), '->isCleared() returns true if the cookie has expired'); + } + + public function testToString() + { + $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); + + $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; domain=.myfoodomain.com; secure; httponly', $cookie->__toString(), '->__toString() returns string representation of the cookie'); + + $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com'); + + $this->assertEquals('foo=deleted; expires=' . gmdate("D, d-M-Y H:i:s T", time()-31536001) . '; path=/admin/; domain=.myfoodomain.com; httponly', $cookie->__toString(), '->__toString() returns string representation of a cleared cookie if value is NULL'); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/File/FileTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/FileTest.php new file mode 100644 index 0000000..0744e83 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/FileTest.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\File; + +use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; + +class FileTest extends \PHPUnit_Framework_TestCase +{ + protected $file; + + public function testGetMimeTypeUsesMimeTypeGuessers() + { + $file = new File(__DIR__.'/Fixtures/test.gif'); + $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif'); + + MimeTypeGuesser::getInstance()->register($guesser); + + $this->assertEquals('image/gif', $file->getMimeType()); + } + + public function testGuessExtensionWithoutGuesser() + { + $file = new File(__DIR__.'/Fixtures/directory/.empty'); + + $this->assertNull($file->guessExtension()); + } + + public function testGuessExtensionIsBasedOnMimeType() + { + $file = new File(__DIR__.'/Fixtures/test'); + $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif'); + + MimeTypeGuesser::getInstance()->register($guesser); + + $this->assertEquals('gif', $file->guessExtension()); + } + + public function testConstructWhenFileNotExists() + { + $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + + new File(__DIR__.'/Fixtures/not_here'); + } + + public function testMove() + { + $path = __DIR__.'/Fixtures/test.copy.gif'; + $targetDir = __DIR__.'/Fixtures/directory'; + $targetPath = $targetDir.'/test.copy.gif'; + @unlink($path); + @unlink($targetPath); + copy(__DIR__.'/Fixtures/test.gif', $path); + + $file = new File($path); + $movedFile = $file->move($targetDir); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\File\File', $movedFile); + + $this->assertTrue(file_exists($targetPath)); + $this->assertFalse(file_exists($path)); + $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); + + @unlink($targetPath); + } + + public function testMoveWithNewName() + { + $path = __DIR__.'/Fixtures/test.copy.gif'; + $targetDir = __DIR__.'/Fixtures/directory'; + $targetPath = $targetDir.'/test.newname.gif'; + @unlink($path); + @unlink($targetPath); + copy(__DIR__.'/Fixtures/test.gif', $path); + + $file = new File($path); + $movedFile = $file->move($targetDir, 'test.newname.gif'); + + $this->assertTrue(file_exists($targetPath)); + $this->assertFalse(file_exists($path)); + $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); + + @unlink($targetPath); + } + + public function testMoveToAnUnexistentDirectory() + { + $sourcePath = __DIR__.'/Fixtures/test.copy.gif'; + $targetDir = __DIR__.'/Fixtures/directory/sub'; + $targetPath = $targetDir.'/test.copy.gif'; + @unlink($sourcePath); + @unlink($targetPath); + @rmdir($targetDir); + copy(__DIR__.'/Fixtures/test.gif', $sourcePath); + + $file = new File($sourcePath); + $movedFile = $file->move($targetDir); + + $this->assertFileExists($targetPath); + $this->assertFileNotExists($sourcePath); + $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); + + @unlink($sourcePath); + @unlink($targetPath); + @rmdir($targetDir); + } + + public function testGetExtension() + { + $file = new File(__DIR__.'/Fixtures/test.gif'); + $this->assertEquals('gif', $file->getExtension()); + } + + protected function createMockGuesser($path, $mimeType) + { + $guesser = $this->getMock('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface'); + $guesser + ->expects($this->once()) + ->method('guess') + ->with($this->equalTo($path)) + ->will($this->returnValue($mimeType)) + ; + + return $guesser; + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextension b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextension new file mode 100644 index 0000000..4d1ae35 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextension @@ -0,0 +1 @@ +f \ No newline at end of file diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.empty b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.empty new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test new file mode 100644 index 0000000..b636f4b Binary files /dev/null and b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test differ diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gif b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gif new file mode 100644 index 0000000..b636f4b Binary files /dev/null and b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gif differ diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php new file mode 100644 index 0000000..2990c21 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\File; + +use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; +use Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser; +use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; +use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; + +class MimeTypeTest extends \PHPUnit_Framework_TestCase +{ + protected $path; + + public function testGuessImageWithoutExtension() + { + if (extension_loaded('fileinfo')) { + $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); + } else { + $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); + } + } + + public function testGuessImageWithDirectory() + { + $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + + MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/directory'); + } + + public function testGuessImageWithFileBinaryMimeTypeGuesser() + { + $guesser = MimeTypeGuesser::getInstance(); + $guesser->register(new FileBinaryMimeTypeGuesser()); + if (extension_loaded('fileinfo')) { + $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); + } else { + $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); + } + } + + public function testGuessImageWithKnownExtension() + { + if (extension_loaded('fileinfo')) { + $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif')); + } else { + $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif')); + } + } + + public function testGuessFileWithUnknownExtension() + { + if (extension_loaded('fileinfo')) { + $this->assertEquals('application/octet-stream', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension')); + } else { + $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension')); + } + } + + public function testGuessWithIncorrectPath() + { + $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/not_here'); + } + + public function testGuessWithNonReadablePath() + { + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->markTestSkipped('Can not verify chmod operations on Windows'); + } + + if (in_array(get_current_user(), array('root'))) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + + $path = __DIR__.'/../Fixtures/to_delete'; + touch($path); + chmod($path, 0333); + + if (get_current_user() != 'root' && substr(sprintf('%o', fileperms($path)), -4) == '0333') { + $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException'); + MimeTypeGuesser::getInstance()->guess($path); + } else { + $this->markTestSkipped('Can not verify chmod operations, change of file permissions failed'); + } + } + + public static function tearDownAfterClass() + { + $path = __DIR__.'/../Fixtures/to_delete'; + if (file_exists($path)) { + chmod($path, 0666); + @unlink($path); + } + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.php new file mode 100644 index 0000000..f79096f --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.php @@ -0,0 +1,221 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\File; + +use Symfony\Component\HttpFoundation\File\UploadedFile; + +class UploadedFileTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!ini_get('file_uploads')) { + $this->markTestSkipped('file_uploads is disabled in php.ini'); + } + } + + public function testConstructWhenFileNotExists() + { + $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + + new UploadedFile( + __DIR__.'/Fixtures/not_here', + 'original.gif', + null + ); + } + + public function testFileUploadsWithNoMimeType() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + null, + filesize(__DIR__.'/Fixtures/test.gif'), + UPLOAD_ERR_OK + ); + + $this->assertEquals('application/octet-stream', $file->getClientMimeType()); + + if (extension_loaded('fileinfo')) { + $this->assertEquals('image/gif', $file->getMimeType()); + } + } + + public function testFileUploadsWithUnknownMimeType() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/.unknownextension', + 'original.gif', + null, + filesize(__DIR__.'/Fixtures/.unknownextension'), + UPLOAD_ERR_OK + ); + + $this->assertEquals('application/octet-stream', $file->getClientMimeType()); + } + + public function testErrorIsOkByDefault() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + 'image/gif', + filesize(__DIR__.'/Fixtures/test.gif'), + null + ); + + $this->assertEquals(UPLOAD_ERR_OK, $file->getError()); + } + + public function testGetClientOriginalName() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + 'image/gif', + filesize(__DIR__.'/Fixtures/test.gif'), + null + ); + + $this->assertEquals('original.gif', $file->getClientOriginalName()); + } + + /** + * @expectedException Symfony\Component\HttpFoundation\File\Exception\FileException + */ + public function testMoveLocalFileIsNotAllowed() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + 'image/gif', + filesize(__DIR__.'/Fixtures/test.gif'), + UPLOAD_ERR_OK + ); + + $movedFile = $file->move(__DIR__.'/Fixtures/directory'); + } + + public function testMoveLocalFileIsAllowedInTestMode() + { + $path = __DIR__.'/Fixtures/test.copy.gif'; + $targetDir = __DIR__.'/Fixtures/directory'; + $targetPath = $targetDir.'/test.copy.gif'; + @unlink($path); + @unlink($targetPath); + copy(__DIR__.'/Fixtures/test.gif', $path); + + $file = new UploadedFile( + $path, + 'original.gif', + 'image/gif', + filesize($path), + UPLOAD_ERR_OK, + true + ); + + $movedFile = $file->move(__DIR__.'/Fixtures/directory'); + + $this->assertTrue(file_exists($targetPath)); + $this->assertFalse(file_exists($path)); + $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); + + @unlink($targetPath); + } + + + public function testGetClientOriginalNameSanitizeFilename() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + '../../original.gif', + 'image/gif', + filesize(__DIR__.'/Fixtures/test.gif'), + null + ); + + $this->assertEquals('original.gif', $file->getClientOriginalName()); + } + + public function testGetSize() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + 'image/gif', + filesize(__DIR__.'/Fixtures/test.gif'), + null + ); + + $this->assertEquals(filesize(__DIR__.'/Fixtures/test.gif'), $file->getSize()); + + $file = new UploadedFile( + __DIR__.'/Fixtures/test', + 'original.gif', + 'image/gif' + ); + + $this->assertEquals(filesize(__DIR__.'/Fixtures/test'), $file->getSize()); + } + + public function testGetExtension() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + null + ); + + $this->assertEquals('gif', $file->getExtension()); + } + + public function testIsValid() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + null, + filesize(__DIR__.'/Fixtures/test.gif'), + UPLOAD_ERR_OK + ); + + $this->assertTrue($file->isValid()); + } + + /** + * @dataProvider uploadedFileErrorProvider + */ + public function testIsInvalidOnUploadError($error) + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + null, + filesize(__DIR__.'/Fixtures/test.gif'), + $error + ); + + $this->assertFalse($file->isValid()); + } + + + public function uploadedFileErrorProvider() + { + return array( + array(UPLOAD_ERR_INI_SIZE), + array(UPLOAD_ERR_FORM_SIZE), + array(UPLOAD_ERR_PARTIAL), + array(UPLOAD_ERR_NO_TMP_DIR), + array(UPLOAD_ERR_EXTENSION), + ); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/FileBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/FileBagTest.php new file mode 100644 index 0000000..5042506 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/FileBagTest.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpFoundation\FileBag; + +/** + * FileBagTest. + * + * @author Fabien Potencier + * @author Bulat Shakirzyanov + */ +class FileBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \InvalidArgumentException + */ + public function testFileMustBeAnArrayOrUploadedFile() + { + new FileBag(array('file' => 'foo')); + } + + public function testShouldConvertsUploadedFiles() + { + $tmpFile = $this->createTempFile(); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + + $bag = new FileBag(array('file' => array( + 'name' => basename($tmpFile), + 'type' => 'text/plain', + 'tmp_name' => $tmpFile, + 'error' => 0, + 'size' => 100 + ))); + + $this->assertEquals($file, $bag->get('file')); + } + + public function testShouldSetEmptyUploadedFilesToNull() + { + $bag = new FileBag(array('file' => array( + 'name' => '', + 'type' => '', + 'tmp_name' => '', + 'error' => UPLOAD_ERR_NO_FILE, + 'size' => 0 + ))); + + $this->assertNull($bag->get('file')); + } + + public function testShouldConvertUploadedFilesWithPhpBug() + { + $tmpFile = $this->createTempFile(); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + + $bag = new FileBag(array( + 'child' => array( + 'name' => array( + 'file' => basename($tmpFile), + ), + 'type' => array( + 'file' => 'text/plain', + ), + 'tmp_name' => array( + 'file' => $tmpFile, + ), + 'error' => array( + 'file' => 0, + ), + 'size' => array( + 'file' => 100, + ), + ) + )); + + $files = $bag->all(); + $this->assertEquals($file, $files['child']['file']); + } + + public function testShouldConvertNestedUploadedFilesWithPhpBug() + { + $tmpFile = $this->createTempFile(); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + + $bag = new FileBag(array( + 'child' => array( + 'name' => array( + 'sub' => array('file' => basename($tmpFile)) + ), + 'type' => array( + 'sub' => array('file' => 'text/plain') + ), + 'tmp_name' => array( + 'sub' => array('file' => $tmpFile) + ), + 'error' => array( + 'sub' => array('file' => 0) + ), + 'size' => array( + 'sub' => array('file' => 100) + ), + ) + )); + + $files = $bag->all(); + $this->assertEquals($file, $files['child']['sub']['file']); + } + + public function testShouldNotConvertNestedUploadedFiles() + { + $tmpFile = $this->createTempFile(); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + $bag = new FileBag(array('image' => array('file' => $file))); + + $files = $bag->all(); + $this->assertEquals($file, $files['image']['file']); + } + + protected function createTempFile() + { + return tempnam(sys_get_temp_dir(), 'FormTest'); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.php new file mode 100644 index 0000000..54289f8 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\HeaderBag; + +class HeaderBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\HttpFoundation\HeaderBag::__construct + */ + public function testConstructor() + { + $bag = new HeaderBag(array('foo' => 'bar')); + $this->assertTrue($bag->has('foo')); + } + + /** + * @covers Symfony\Component\HttpFoundation\HeaderBag::all + */ + public function testAll() + { + $bag = new HeaderBag(array('foo' => 'bar')); + $this->assertEquals(array('foo' => array('bar')), $bag->all(), '->all() gets all the input'); + + $bag = new HeaderBag(array('FOO' => 'BAR')); + $this->assertEquals(array('foo' => array('BAR')), $bag->all(), '->all() gets all the input key are lower case'); + } + + /** + * @covers Symfony\Component\HttpFoundation\HeaderBag::replace + */ + public function testReplace() + { + $bag = new HeaderBag(array('foo' => 'bar')); + + $bag->replace(array('NOPE' => 'BAR')); + $this->assertEquals(array('nope' => array('BAR')), $bag->all(), '->replace() replaces the input with the argument'); + $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input'); + } + + /** + * @covers Symfony\Component\HttpFoundation\HeaderBag::get + */ + public function testGet() + { + $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz')); + $this->assertEquals( 'bar', $bag->get('foo'), '->get return current value'); + $this->assertEquals( 'bar', $bag->get('FoO'), '->get key in case insensitive'); + $this->assertEquals( array('bar'), $bag->get('foo', 'nope', false), '->get return the value as array'); + + // defaults + $this->assertNull($bag->get('none'), '->get unknown values returns null'); + $this->assertEquals( 'default', $bag->get('none', 'default'), '->get unknown values returns default'); + $this->assertEquals( array('default'), $bag->get('none', 'default', false), '->get unknown values returns default as array'); + + $bag->set('foo', 'bor', false); + $this->assertEquals( 'bar', $bag->get('foo'), '->get return first value'); + $this->assertEquals( array('bar', 'bor'), $bag->get('foo', 'nope', false), '->get return all values as array'); + } + + /** + * @covers Symfony\Component\HttpFoundation\HeaderBag::contains + */ + public function testContains() + { + $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz')); + $this->assertTrue( $bag->contains('foo', 'bar'), '->contains first value'); + $this->assertTrue( $bag->contains('fuzz', 'bizz'), '->contains second value'); + $this->assertFalse( $bag->contains('nope', 'nope'), '->contains unknown value'); + $this->assertFalse( $bag->contains('foo', 'nope'), '->contains unknown value'); + + // Multiple values + $bag->set('foo', 'bor', false); + $this->assertTrue( $bag->contains('foo', 'bar'), '->contains first value'); + $this->assertTrue( $bag->contains('foo', 'bor'), '->contains second value'); + $this->assertFalse( $bag->contains('foo', 'nope'), '->contains unknown value'); + } + + public function testCacheControlDirectiveAccessors() + { + $bag = new HeaderBag(); + $bag->addCacheControlDirective('public'); + + $this->assertTrue($bag->hasCacheControlDirective('public')); + $this->assertTrue($bag->getCacheControlDirective('public')); + $this->assertEquals('public', $bag->get('cache-control')); + + $bag->addCacheControlDirective('max-age', 10); + $this->assertTrue($bag->hasCacheControlDirective('max-age')); + $this->assertEquals(10, $bag->getCacheControlDirective('max-age')); + $this->assertEquals('max-age=10, public', $bag->get('cache-control')); + + $bag->removeCacheControlDirective('max-age'); + $this->assertFalse($bag->hasCacheControlDirective('max-age')); + } + + public function testCacheControlDirectiveParsing() + { + $bag = new HeaderBag(array('cache-control' => 'public, max-age=10')); + $this->assertTrue($bag->hasCacheControlDirective('public')); + $this->assertTrue($bag->getCacheControlDirective('public')); + + $this->assertTrue($bag->hasCacheControlDirective('max-age')); + $this->assertEquals(10, $bag->getCacheControlDirective('max-age')); + + $bag->addCacheControlDirective('s-maxage', 100); + $this->assertEquals('max-age=10, public, s-maxage=100', $bag->get('cache-control')); + } + + public function testCacheControlDirectiveOverrideWithReplace() + { + $bag = new HeaderBag(array('cache-control' => 'private, max-age=100')); + $bag->replace(array('cache-control' => 'public, max-age=10')); + $this->assertTrue($bag->hasCacheControlDirective('public')); + $this->assertTrue($bag->getCacheControlDirective('public')); + + $this->assertTrue($bag->hasCacheControlDirective('max-age')); + $this->assertEquals(10, $bag->getCacheControlDirective('max-age')); + } + + /** + * @covers Symfony\Component\HttpFoundation\HeaderBag::getIterator + */ + public function testGetIterator() + { + $headers = array('foo' => 'bar', 'hello' => 'world', 'third' => 'charm'); + $headerBag = new HeaderBag($headers); + + $i = 0; + foreach ($headerBag as $key => $val) { + $i++; + $this->assertEquals(array($headers[$key]), $val); + } + + $this->assertEquals(count($headers), $i); + } + + /** + * @covers Symfony\Component\HttpFoundation\HeaderBag::count + */ + public function testCount() + { + $headers = array('foo' => 'bar', 'HELLO' => 'WORLD'); + $headerBag = new HeaderBag($headers); + + $this->assertEquals(count($headers), count($headerBag)); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php new file mode 100644 index 0000000..16ad0d6 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\JsonResponse; + +/** + * @covers Symfony\Component\HttpFoundation\JsonResponse::__construct + * @covers Symfony\Component\HttpFoundation\JsonResponse::setData + * @covers Symfony\Component\HttpFoundation\JsonResponse::setCallback + */ +class JsonResponseTest extends \PHPUnit_Framework_TestCase +{ + public function testConstructorEmptyCreatesJsonObject() + { + $response = new JsonResponse(); + $this->assertSame('{}', $response->getContent()); + } + + public function testConstructorWithArrayCreatesJsonArray() + { + $response = new JsonResponse(array(0, 1, 2, 3)); + $this->assertSame('[0,1,2,3]', $response->getContent()); + } + + public function testConstructorWithAssocArrayCreatesJsonObject() + { + $response = new JsonResponse(array('foo' => 'bar')); + $this->assertSame('{"foo":"bar"}', $response->getContent()); + } + + public function testConstructorWithSimpleTypes() + { + $response = new JsonResponse('foo'); + $this->assertSame('"foo"', $response->getContent()); + + $response = new JsonResponse(0); + $this->assertSame('0', $response->getContent()); + + $response = new JsonResponse(0.1); + $this->assertSame('0.1', $response->getContent()); + + $response = new JsonResponse(true); + $this->assertSame('true', $response->getContent()); + } + + public function testConstructorWithCustomStatus() + { + $response = new JsonResponse(array(), 202); + $this->assertSame(202, $response->getStatusCode()); + } + + public function testConstructorAddsContentTypeHeader() + { + $response = new JsonResponse(); + $this->assertSame('application/json', $response->headers->get('Content-Type')); + } + + public function testConstructorWithCustomHeaders() + { + $response = new JsonResponse(array(), 200, array('ETag' => 'foo')); + $this->assertSame('application/json', $response->headers->get('Content-Type')); + $this->assertSame('foo', $response->headers->get('ETag')); + } + + public function testConstructorWithCustomContentType() + { + $headers = array('Content-Type' => 'application/vnd.acme.blog-v1+json'); + + $response = new JsonResponse(array(), 200, $headers); + $this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type')); + } + + public function testCreate() + { + $response = JsonResponse::create(array('foo' => 'bar'), 204); + + $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); + $this->assertEquals('{"foo":"bar"}', $response->getContent()); + $this->assertEquals(204, $response->getStatusCode()); + } + + public function testSetCallback() + { + $response = JsonResponse::create(array('foo' => 'bar'))->setCallback('callback'); + + $this->assertEquals('callback({"foo":"bar"});', $response->getContent()); + $this->assertEquals('text/javascript', $response->headers->get('Content-Type')); + } + + public function testSetCallbackInvalidIdentifier() + { + $response = new JsonResponse('foo'); + + $this->setExpectedException('InvalidArgumentException'); + $response->setCallback('+invalid'); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php new file mode 100644 index 0000000..d96e00b --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php @@ -0,0 +1,233 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\ParameterBag; + +class ParameterBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::__construct + */ + public function testConstructor() + { + $this->testAll(); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::all + */ + public function testAll() + { + $bag = new ParameterBag(array('foo' => 'bar')); + $this->assertEquals(array('foo' => 'bar'), $bag->all(), '->all() gets all the input'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::replace + */ + public function testReplace() + { + $bag = new ParameterBag(array('foo' => 'bar')); + + $bag->replace(array('FOO' => 'BAR')); + $this->assertEquals(array('FOO' => 'BAR'), $bag->all(), '->replace() replaces the input with the argument'); + $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::get + */ + public function testGet() + { + $bag = new ParameterBag(array('foo' => 'bar', 'null' => null)); + + $this->assertEquals('bar', $bag->get('foo'), '->get() gets the value of a parameter'); + $this->assertEquals('default', $bag->get('unknown', 'default'), '->get() returns second argument as default if a parameter is not defined'); + $this->assertNull($bag->get('null', 'default'), '->get() returns null if null is set'); + } + + public function testGetDoesNotUseDeepByDefault() + { + $bag = new ParameterBag(array('foo' => array('bar' => 'moo'))); + + $this->assertNull($bag->get('foo[bar]')); + } + + /** + * @dataProvider getInvalidPaths + * @expectedException \InvalidArgumentException + */ + public function testGetDeepWithInvalidPaths($path) + { + $bag = new ParameterBag(array('foo' => array('bar' => 'moo'))); + + $bag->get($path, null, true); + } + + public function getInvalidPaths() + { + return array( + array('foo[['), + array('foo[d'), + array('foo[bar]]'), + array('foo[bar]d'), + ); + } + + public function testGetDeep() + { + $bag = new ParameterBag(array('foo' => array('bar' => array('moo' => 'boo')))); + + $this->assertEquals(array('moo' => 'boo'), $bag->get('foo[bar]', null, true)); + $this->assertEquals('boo', $bag->get('foo[bar][moo]', null, true)); + $this->assertEquals('default', $bag->get('foo[bar][foo]', 'default', true)); + $this->assertEquals('default', $bag->get('bar[moo][foo]', 'default', true)); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::set + */ + public function testSet() + { + $bag = new ParameterBag(array()); + + $bag->set('foo', 'bar'); + $this->assertEquals('bar', $bag->get('foo'), '->set() sets the value of parameter'); + + $bag->set('foo', 'baz'); + $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::has + */ + public function testHas() + { + $bag = new ParameterBag(array('foo' => 'bar')); + + $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined'); + $this->assertFalse($bag->has('unknown'), '->has() return false if a parameter is not defined'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::getAlpha + */ + public function testGetAlpha() + { + $bag = new ParameterBag(array('word' => 'foo_BAR_012')); + + $this->assertEquals('fooBAR', $bag->getAlpha('word'), '->getAlpha() gets only alphabetic characters'); + $this->assertEquals('', $bag->getAlpha('unknown'), '->getAlpha() returns empty string if a parameter is not defined'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::getAlnum + */ + public function testGetAlnum() + { + $bag = new ParameterBag(array('word' => 'foo_BAR_012')); + + $this->assertEquals('fooBAR012', $bag->getAlnum('word'), '->getAlnum() gets only alphanumeric characters'); + $this->assertEquals('', $bag->getAlnum('unknown'), '->getAlnum() returns empty string if a parameter is not defined'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::getDigits + */ + public function testGetDigits() + { + $bag = new ParameterBag(array('word' => 'foo_BAR_012')); + + $this->assertEquals('012', $bag->getDigits('word'), '->getDigits() gets only digits as string'); + $this->assertEquals('', $bag->getDigits('unknown'), '->getDigits() returns empty string if a parameter is not defined'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::getInt + */ + public function testGetInt() + { + $bag = new ParameterBag(array('digits' => '0123')); + + $this->assertEquals(123, $bag->getInt('digits'), '->getInt() gets a value of parameter as integer'); + $this->assertEquals(0, $bag->getInt('unknown'), '->getInt() returns zero if a parameter is not defined'); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::filter + */ + public function testFilter() + { + $bag = new ParameterBag(array( + 'digits' => '0123ab', + 'email' => 'example@example.com', + 'url' => 'http://example.com/foo', + 'dec' => '256', + 'hex' => '0x100', + 'array' => array('bang'), + )); + + $this->assertEmpty($bag->filter('nokey'), '->filter() should return empty by default if no key is found'); + + $this->assertEquals('0123', $bag->filter('digits', '', false, FILTER_SANITIZE_NUMBER_INT), '->filter() gets a value of parameter as integer filtering out invalid characters'); + + $this->assertEquals('example@example.com', $bag->filter('email', '', false, FILTER_VALIDATE_EMAIL), '->filter() gets a value of parameter as email'); + + $this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, array('flags' => FILTER_FLAG_PATH_REQUIRED)), '->filter() gets a value of parameter as url with a path'); + + // This test is repeated for code-coverage + $this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED), '->filter() gets a value of parameter as url with a path'); + + $this->assertFalse($bag->filter('dec', '', false, FILTER_VALIDATE_INT, array( + 'flags' => FILTER_FLAG_ALLOW_HEX, + 'options' => array('min_range' => 1, 'max_range' => 0xff)) + ), '->filter() gets a value of parameter as integer between boundaries'); + + $this->assertFalse($bag->filter('hex', '', false, FILTER_VALIDATE_INT, array( + 'flags' => FILTER_FLAG_ALLOW_HEX, + 'options' => array('min_range' => 1, 'max_range' => 0xff)) + ), '->filter() gets a value of parameter as integer between boundaries'); + + $this->assertEquals(array('bang'), $bag->filter('array', '', false), '->filter() gets a value of parameter as an array'); + + + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::getIterator + */ + public function testGetIterator() + { + $parameters = array('foo' => 'bar', 'hello' => 'world'); + $bag = new ParameterBag($parameters); + + $i = 0; + foreach ($bag as $key => $val) { + $i++; + $this->assertEquals($parameters[$key], $val); + } + + $this->assertEquals(count($parameters), $i); + } + + /** + * @covers Symfony\Component\HttpFoundation\ParameterBag::count + */ + public function testCount() + { + $parameters = array('foo' => 'bar', 'hello' => 'world'); + $bag = new ParameterBag($parameters); + + $this->assertEquals(count($parameters), count($bag)); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php new file mode 100644 index 0000000..179ee5a --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use \Symfony\Component\HttpFoundation\RedirectResponse; + +class RedirectResponseTest extends \PHPUnit_Framework_TestCase +{ + public function testGenerateMetaRedirect() + { + $response = new RedirectResponse('foo.bar'); + + $this->assertEquals(1, preg_match( + '##', + preg_replace(array('/\s+/', '/\'/'), array(' ', '"'), $response->getContent()) + )); + } + + public function testGenerateLocationHeader() + { + $response = new RedirectResponse('foo.bar'); + + $this->assertTrue($response->headers->has('Location')); + $this->assertEquals('foo.bar', $response->headers->get('Location')); + } + + public function testGetTargetUrl() + { + $response = new RedirectResponse('foo.bar'); + + $this->assertEquals('foo.bar', $response->getTargetUrl()); + } + + public function testCreate() + { + $response = RedirectResponse::create('foo', 301); + + $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response); + $this->assertEquals(301, $response->getStatusCode()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php new file mode 100644 index 0000000..069d8b4 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php @@ -0,0 +1,180 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + + + +use Symfony\Component\HttpFoundation\RequestMatcher; +use Symfony\Component\HttpFoundation\Request; + +class RequestMatcherTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider testIpv4Provider + */ + public function testIpv4($matches, $remoteAddr, $cidr) + { + $request = Request::create('', 'get', array(), array(), array(), array('REMOTE_ADDR' => $remoteAddr)); + + $matcher = new RequestMatcher(); + $matcher->matchIp($cidr); + + $this->assertEquals($matches, $matcher->matches($request)); + } + + public function testIpv4Provider() + { + return array( + array(true, '192.168.1.1', '192.168.1.1'), + array(true, '192.168.1.1', '192.168.1.1/1'), + array(true, '192.168.1.1', '192.168.1.0/24'), + array(false, '192.168.1.1', '1.2.3.4/1'), + array(false, '192.168.1.1', '192.168.1/33'), + ); + } + + /** + * @dataProvider testIpv6Provider + */ + public function testIpv6($matches, $remoteAddr, $cidr) + { + if (!defined('AF_INET6')) { + $this->markTestSkipped('Only works when PHP is compiled without the option "disable-ipv6".'); + } + + $request = Request::create('', 'get', array(), array(), array(), array('REMOTE_ADDR' => $remoteAddr)); + + $matcher = new RequestMatcher(); + $matcher->matchIp($cidr); + + $this->assertEquals($matches, $matcher->matches($request)); + } + + public function testIpv6Provider() + { + return array( + array(true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), + array(false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), + ); + } + + public function testAnIpv6WithOptionDisabledIpv6() + { + if (defined('AF_INET6')) { + $this->markTestSkipped('Only works when PHP is compiled with the option "disable-ipv6".'); + } + + $request = Request::create('', 'get', array(), array(), array(), array('REMOTE_ADDR' => '2a01:198:603:0:396e:4789:8e99:890f')); + + $matcher = new RequestMatcher(); + $matcher->matchIp('2a01:198:603:0::/65'); + + try { + $matcher->matches($request); + + $this->fail('An expected RuntimeException has not been raised.'); + } catch (\Exception $e) { + $this->assertInstanceOf('\RuntimeException', $e); + } + } + + public function testMethod() + { + $matcher = new RequestMatcher(); + + $matcher->matchMethod('get'); + $request = Request::create('', 'get'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchMethod('post'); + $this->assertFalse($matcher->matches($request)); + + $matcher->matchMethod(array('get', 'post')); + $this->assertTrue($matcher->matches($request)); + } + + public function testHost() + { + $matcher = new RequestMatcher(); + + $request = Request::create('', 'get', array(), array(), array(), array('HTTP_HOST' => 'foo.example.com')); + + $matcher->matchHost('.*\.example\.com'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchHost('\.example\.com$'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchHost('^.*\.example\.com$'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchMethod('.*\.sensio\.com'); + $this->assertFalse($matcher->matches($request)); + } + + public function testPath() + { + $matcher = new RequestMatcher(); + + $request = Request::create('/admin/foo'); + + $matcher->matchPath('/admin/.*'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchPath('/admin'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchPath('^/admin/.*$'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchMethod('/blog/.*'); + $this->assertFalse($matcher->matches($request)); + } + + public function testPathWithLocaleIsNotSupported() + { + $matcher = new RequestMatcher(); + $request = Request::create('/en/login'); + $request->setLocale('en'); + + $matcher->matchPath('^/{_locale}/login$'); + $this->assertFalse($matcher->matches($request)); + } + + public function testPathWithEncodedCharacters() + { + $matcher = new RequestMatcher(); + $request = Request::create('/admin/fo%20o'); + $matcher->matchPath('^/admin/fo o*$'); + $this->assertTrue($matcher->matches($request)); + } + + public function testAttributes() + { + $matcher = new RequestMatcher(); + + $request = Request::create('/admin/foo'); + $request->attributes->set('foo', 'foo_bar'); + + $matcher->matchAttribute('foo', 'foo_.*'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchAttribute('foo', 'foo'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchAttribute('foo', '^foo_bar$'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchAttribute('foo', 'babar'); + $this->assertFalse($matcher->matches($request)); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/RequestTest.php new file mode 100644 index 0000000..84f19a2 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -0,0 +1,1072 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + + +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Request; + +class RequestTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\HttpFoundation\Request::__construct + */ + public function testConstructor() + { + $this->testInitialize(); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::initialize + */ + public function testInitialize() + { + $request = new Request(); + + $request->initialize(array('foo' => 'bar')); + $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument'); + + $request->initialize(array(), array('foo' => 'bar')); + $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument'); + + $request->initialize(array(), array(), array('foo' => 'bar')); + $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument'); + + $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar')); + $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its fourth argument'); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::create + */ + public function testCreate() + { + $request = Request::create('http://test.com/foo?bar=baz'); + $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('bar=baz', $request->getQueryString()); + $this->assertEquals(80, $request->getPort()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://test.com/foo', 'GET', array('bar' => 'baz')); + $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('bar=baz', $request->getQueryString()); + $this->assertEquals(80, $request->getPort()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz')); + $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('bar=baz', $request->getQueryString()); + $this->assertEquals(80, $request->getPort()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('https://test.com/foo?bar=baz'); + $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('bar=baz', $request->getQueryString()); + $this->assertEquals(443, $request->getPort()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertTrue($request->isSecure()); + + $request = Request::create('test.com:90/foo'); + $this->assertEquals('http://test.com:90/foo', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('test.com', $request->getHost()); + $this->assertEquals('test.com:90', $request->getHttpHost()); + $this->assertEquals(90, $request->getPort()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('https://test.com:90/foo'); + $this->assertEquals('https://test.com:90/foo', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('test.com', $request->getHost()); + $this->assertEquals('test.com:90', $request->getHttpHost()); + $this->assertEquals(90, $request->getPort()); + $this->assertTrue($request->isSecure()); + + $request = Request::create('https://127.0.0.1:90/foo'); + $this->assertEquals('https://127.0.0.1:90/foo', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('127.0.0.1', $request->getHost()); + $this->assertEquals('127.0.0.1:90', $request->getHttpHost()); + $this->assertEquals(90, $request->getPort()); + $this->assertTrue($request->isSecure()); + + $request = Request::create('https://[::1]:90/foo'); + $this->assertEquals('https://[::1]:90/foo', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('[::1]', $request->getHost()); + $this->assertEquals('[::1]:90', $request->getHttpHost()); + $this->assertEquals(90, $request->getPort()); + $this->assertTrue($request->isSecure()); + + $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}'; + $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json); + $this->assertEquals($json, $request->getContent()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://test.com'); + $this->assertEquals('http://test.com/', $request->getUri()); + $this->assertEquals('/', $request->getPathInfo()); + $this->assertEquals('', $request->getQueryString()); + $this->assertEquals(80, $request->getPort()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://test.com:90/?test=1'); + $this->assertEquals('http://test.com:90/?test=1', $request->getUri()); + $this->assertEquals('/', $request->getPathInfo()); + $this->assertEquals('test=1', $request->getQueryString()); + $this->assertEquals(90, $request->getPort()); + $this->assertEquals('test.com:90', $request->getHttpHost()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://test:test@test.com'); + $this->assertEquals('http://test:test@test.com/', $request->getUri()); + $this->assertEquals('/', $request->getPathInfo()); + $this->assertEquals('', $request->getQueryString()); + $this->assertEquals(80, $request->getPort()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertEquals('test', $request->getUser()); + $this->assertEquals('test', $request->getPassword()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://testnopass@test.com'); + $this->assertEquals('http://testnopass@test.com/', $request->getUri()); + $this->assertEquals('/', $request->getPathInfo()); + $this->assertEquals('', $request->getQueryString()); + $this->assertEquals(80, $request->getPort()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertEquals('testnopass', $request->getUser()); + $this->assertNull($request->getPassword()); + $this->assertFalse($request->isSecure()); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::duplicate + */ + public function testDuplicate() + { + $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar')); + $dup = $request->duplicate(); + + $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters'); + $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters'); + $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes'); + $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers'); + + $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar')); + + $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided'); + $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided'); + $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided'); + $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided'); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::getFormat + * @covers Symfony\Component\HttpFoundation\Request::setFormat + * @dataProvider getFormatToMimeTypeMapProvider + */ + public function testGetFormatFromMimeType($format, $mimeTypes) + { + $request = new Request(); + foreach ($mimeTypes as $mime) { + $this->assertEquals($format, $request->getFormat($mime)); + } + $request->setFormat($format, $mimeTypes); + foreach ($mimeTypes as $mime) { + $this->assertEquals($format, $request->getFormat($mime)); + } + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::getFormat + */ + public function testGetFormatFromMimeTypeWithParameters() + { + $request = new Request(); + $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8')); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::getMimeType + * @dataProvider getFormatToMimeTypeMapProvider + */ + public function testGetMimeTypeFromFormat($format, $mimeTypes) + { + if (null !== $format) { + $request = new Request(); + $this->assertEquals($mimeTypes[0], $request->getMimeType($format)); + } + } + + public function getFormatToMimeTypeMapProvider() + { + return array( + array(null, array(null, 'unexistent-mime-type')), + array('txt', array('text/plain')), + array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')), + array('css', array('text/css')), + array('json', array('application/json', 'application/x-json')), + array('xml', array('text/xml', 'application/xml', 'application/x-xml')), + array('rdf', array('application/rdf+xml')), + array('atom',array('application/atom+xml')), + ); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::getUri + */ + public function testGetUri() + { + $server = array(); + + // Standard Request on non default PORT + // http://hostname:8080/index.php/path/info?query=string + + $server['HTTP_HOST'] = 'hostname:8080'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '8080'; + + $server['QUERY_STRING'] = 'query=string'; + $server['REQUEST_URI'] = '/index.php/path/info?query=string'; + $server['SCRIPT_NAME'] = '/index.php'; + $server['PATH_INFO'] = '/path/info'; + $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info'; + $server['PHP_SELF'] = '/index_dev.php/path/info'; + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + + $request = new Request(); + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://hostname:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port'); + + // Use std port number + $server['HTTP_HOST'] = 'hostname'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://hostname/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port'); + + // Without HOST HEADER + unset($server['HTTP_HOST']); + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER'); + + // Request with URL REWRITING (hide index.php) + // RewriteCond %{REQUEST_FILENAME} !-f + // RewriteRule ^(.*)$ index.php [QSA,L] + // http://hostname:8080/path/info?query=string + $server = array(); + $server['HTTP_HOST'] = 'hostname:8080'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '8080'; + + $server['REDIRECT_QUERY_STRING'] = 'query=string'; + $server['REDIRECT_URL'] = '/path/info'; + $server['SCRIPT_NAME'] = '/index.php'; + $server['QUERY_STRING'] = 'query=string'; + $server['REQUEST_URI'] = '/path/info?toto=test&1=1'; + $server['SCRIPT_NAME'] = '/index.php'; + $server['PHP_SELF'] = '/index.php'; + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + $this->assertEquals('http://hostname:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite'); + + // Use std port number + // http://hostname/path/info?query=string + $server['HTTP_HOST'] = 'hostname'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://hostname/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port'); + + // Without HOST HEADER + unset($server['HTTP_HOST']); + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER'); + + // With encoded characters + + $server = array( + 'HTTP_HOST' => 'hostname:8080', + 'SERVER_NAME' => 'servername', + 'SERVER_PORT' => '8080', + 'QUERY_STRING' => 'query=string', + 'REQUEST_URI' => '/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', + 'SCRIPT_NAME' => '/ba se/index_dev.php', + 'PATH_TRANSLATED' => 'redirect:/index.php/foo bar/in+fo', + 'PHP_SELF' => '/ba se/index_dev.php/path/info', + 'SCRIPT_FILENAME' => '/some/where/ba se/index_dev.php', + ); + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals( + 'http://hostname:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', + $request->getUri() + ); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::getUriForPath + */ + public function testGetUriForPath() + { + $request = Request::create('http://test.com/foo?bar=baz'); + $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path')); + + $request = Request::create('http://test.com:90/foo?bar=baz'); + $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path')); + + $request = Request::create('https://test.com/foo?bar=baz'); + $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path')); + + $request = Request::create('https://test.com:90/foo?bar=baz'); + $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path')); + + $server = array(); + + // Standard Request on non default PORT + // http://hostname:8080/index.php/path/info?query=string + + $server['HTTP_HOST'] = 'hostname:8080'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '8080'; + + $server['QUERY_STRING'] = 'query=string'; + $server['REQUEST_URI'] = '/index.php/path/info?query=string'; + $server['SCRIPT_NAME'] = '/index.php'; + $server['PATH_INFO'] = '/path/info'; + $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info'; + $server['PHP_SELF'] = '/index_dev.php/path/info'; + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + + $request = new Request(); + + $request->initialize(array(), array(), array(), array(), array(),$server); + + $this->assertEquals('http://hostname:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port'); + + // Use std port number + $server['HTTP_HOST'] = 'hostname'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://hostname/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port'); + + // Without HOST HEADER + unset($server['HTTP_HOST']); + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER'); + + // Request with URL REWRITING (hide index.php) + // RewriteCond %{REQUEST_FILENAME} !-f + // RewriteRule ^(.*)$ index.php [QSA,L] + // http://hostname:8080/path/info?query=string + $server = array(); + $server['HTTP_HOST'] = 'hostname:8080'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '8080'; + + $server['REDIRECT_QUERY_STRING'] = 'query=string'; + $server['REDIRECT_URL'] = '/path/info'; + $server['SCRIPT_NAME'] = '/index.php'; + $server['QUERY_STRING'] = 'query=string'; + $server['REQUEST_URI'] = '/path/info?toto=test&1=1'; + $server['SCRIPT_NAME'] = '/index.php'; + $server['PHP_SELF'] = '/index.php'; + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + $this->assertEquals('http://hostname:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite'); + + // Use std port number + // http://hostname/path/info?query=string + $server['HTTP_HOST'] = 'hostname'; + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://hostname/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port'); + + // Without HOST HEADER + unset($server['HTTP_HOST']); + $server['SERVER_NAME'] = 'servername'; + $server['SERVER_PORT'] = '80'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER'); + $this->assertEquals('servername', $request->getHttpHost()); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::getQueryString + */ + public function testGetQueryString() + { + $request = new Request(); + + $request->server->set('QUERY_STRING', 'foo'); + $this->assertEquals('foo', $request->getQueryString(), '->getQueryString() works with valueless parameters'); + + $request->server->set('QUERY_STRING', 'foo='); + $this->assertEquals('foo=', $request->getQueryString(), '->getQueryString() includes a dangling equal sign'); + + $request->server->set('QUERY_STRING', 'bar=&foo=bar'); + $this->assertEquals('bar=&foo=bar', $request->getQueryString(), '->getQueryString() works when empty parameters'); + + $request->server->set('QUERY_STRING', 'foo=bar&bar='); + $this->assertEquals('bar=&foo=bar', $request->getQueryString(), '->getQueryString() sorts keys alphabetically'); + + $request->server->set('QUERY_STRING', 'him=John%20Doe&her=Jane+Doe'); + $this->assertEquals('her=Jane%2BDoe&him=John%20Doe', $request->getQueryString(), '->getQueryString() normalizes encoding'); + + $request->server->set('QUERY_STRING', 'foo[]=1&foo[]=2'); + $this->assertEquals('foo%5B%5D=1&foo%5B%5D=2', $request->getQueryString(), '->getQueryString() allows array notation'); + + $request->server->set('QUERY_STRING', 'foo=1&foo=2'); + $this->assertEquals('foo=1&foo=2', $request->getQueryString(), '->getQueryString() allows repeated parameters'); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::getHost + */ + public function testGetHost() + { + $request = new Request(); + + $request->initialize(array('foo' => 'bar')); + $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized'); + + $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.exemple.com')); + $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from Host Header'); + + // Host header with port number. + $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.exemple.com:8080')); + $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from Host Header with port number'); + + // Server values. + $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.exemple.com')); + $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from server name'); + + $this->startTrustingProxyData(); + // X_FORWARDED_HOST. + $request->initialize(array(), array(), array(), array(), array(), array('HTTP_X_FORWARDED_HOST' => 'www.exemple.com')); + $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from X_FORWARDED_HOST'); + + // X_FORWARDED_HOST + $request->initialize(array(), array(), array(), array(), array(), array('HTTP_X_FORWARDED_HOST' => 'www.exemple.com, www.second.com')); + $this->assertEquals('www.second.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST use last value'); + + // X_FORWARDED_HOST with port number + $request->initialize(array(), array(), array(), array(), array(), array('HTTP_X_FORWARDED_HOST' => 'www.exemple.com, www.second.com:8080')); + $this->assertEquals('www.second.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST with port number'); + + $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.exemple.com', 'HTTP_X_FORWARDED_HOST' => 'www.forward.com')); + $this->assertEquals('www.forward.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST has priority over Host'); + + $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.exemple.com', 'HTTP_X_FORWARDED_HOST' => 'www.forward.com')); + $this->assertEquals('www.forward.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST has priority over SERVER_NAME '); + + $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.exemple.com', 'HTTP_HOST' => 'www.host.com')); + $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME '); + $this->stopTrustingProxyData(); + } + + /** + * @covers Symfony\Component\HttpFoundation\Request::setMethod + * @covers Symfony\Component\HttpFoundation\Request::getMethod + */ + public function testGetSetMethod() + { + $request = new Request(); + + $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined'); + + $request->setMethod('get'); + $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string'); + + $request->setMethod('PURGE'); + $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one'); + + $request->setMethod('POST'); + $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined'); + + $request->setMethod('POST'); + $request->request->set('_method', 'purge'); + $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST'); + + $request->setMethod('POST'); + $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete'); + $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST'); + + $request = new Request(); + $request->setMethod('POST'); + $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete'); + $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST'); + } + + /** + * @dataProvider testGetClientIpProvider + */ + public function testGetClientIp($expected, $proxy, $remoteAddr, $httpClientIp, $httpForwardedFor) + { + $request = new Request(); + $this->assertEquals('', $request->getClientIp()); + $this->assertEquals('', $request->getClientIp(true)); + + $server = array('REMOTE_ADDR' => $remoteAddr); + if (null !== $httpClientIp) { + $server['HTTP_CLIENT_IP'] = $httpClientIp; + } + if (null !== $httpForwardedFor) { + $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor; + } + + $request->initialize(array(), array(), array(), array(), array(), $server); + if ($proxy) { + $this->startTrustingProxyData(); + } + $this->assertEquals($expected, $request->getClientIp($proxy)); + if ($proxy) { + $this->stopTrustingProxyData(); + } + } + + public function testGetClientIpProvider() + { + return array( + array('88.88.88.88', false, '88.88.88.88', null, null), + array('127.0.0.1', false, '127.0.0.1', '88.88.88.88', null), + array('88.88.88.88', true, '127.0.0.1', '88.88.88.88', null), + array('127.0.0.1', false, '127.0.0.1', null, '88.88.88.88'), + array('88.88.88.88', true, '127.0.0.1', null, '88.88.88.88'), + array('::1', false, '::1', null, null), + array('2620:0:1cfe:face:b00c::3', true, '::1', '2620:0:1cfe:face:b00c::3', null), + array('2620:0:1cfe:face:b00c::3', true, '::1', null, '2620:0:1cfe:face:b00c::3, ::1'), + array('88.88.88.88', true, '123.45.67.89', null, '88.88.88.88, 87.65.43.21, 127.0.0.1'), + ); + } + + public function testGetContentWorksTwiceInDefaultMode() + { + $req = new Request; + $this->assertEquals('', $req->getContent()); + $this->assertEquals('', $req->getContent()); + } + + public function testGetContentReturnsResource() + { + $req = new Request; + $retval = $req->getContent(true); + $this->assertInternalType('resource', $retval); + $this->assertEquals("", fread($retval, 1)); + $this->assertTrue(feof($retval)); + } + + /** + * @expectedException LogicException + * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider + */ + public function testGetContentCantBeCalledTwiceWithResources($first, $second) + { + $req = new Request; + $req->getContent($first); + $req->getContent($second); + } + + public function getContentCantBeCalledTwiceWithResourcesProvider() + { + return array( + 'Resource then fetch' => array(true, false), + 'Resource then resource' => array(true, true), + 'Fetch then resource' => array(false, true), + ); + } + + public function provideOverloadedMethods() + { + return array( + array('PUT'), + array('DELETE'), + array('PATCH'), + ); + } + + /** + * @dataProvider provideOverloadedMethods + */ + public function testCreateFromGlobals($method) + { + $_GET['foo1'] = 'bar1'; + $_POST['foo2'] = 'bar2'; + $_COOKIE['foo3'] = 'bar3'; + $_FILES['foo4'] = array('bar4'); + $_SERVER['foo5'] = 'bar5'; + + $request = Request::createFromGlobals(); + $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET'); + $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST'); + $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE'); + $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES'); + $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER'); + + unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']); + + $_SERVER['REQUEST_METHOD'] = $method; + $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + $request = RequestContentProxy::createFromGlobals(); + $this->assertEquals($method, $request->getMethod()); + $this->assertEquals('mycontent', $request->request->get('content')); + + unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']); + + $_POST['_method'] = $method; + $_POST['foo6'] = 'bar6'; + $_SERVER['REQUEST_METHOD'] = 'POST'; + $request = Request::createFromGlobals(); + $this->assertEquals($method, $request->getMethod()); + $this->assertEquals('bar6', $request->request->get('foo6')); + + unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']); + } + + public function testOverrideGlobals() + { + $request = new Request(); + $request->initialize(array('foo' => 'bar')); + + // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it + $server = $_SERVER; + + $request->overrideGlobals(); + + $this->assertEquals(array('foo' => 'bar'), $_GET); + + $request->initialize(array(), array('foo' => 'bar')); + $request->overrideGlobals(); + + $this->assertEquals(array('foo' => 'bar'), $_POST); + + $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER); + + $this->startTrustingProxyData(); + $request->headers->set('X_FORWARDED_PROTO', 'https'); + + $this->assertTrue($request->isSecure()); + $this->stopTrustingProxyData(); + + $request->overrideGlobals(); + + $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER); + + // restore initial $_SERVER array + $_SERVER = $server; + } + + public function testGetScriptName() + { + $request = new Request(); + $this->assertEquals('', $request->getScriptName()); + + $server = array(); + $server['SCRIPT_NAME'] = '/index.php'; + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/index.php', $request->getScriptName()); + + $server = array(); + $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/frontend.php', $request->getScriptName()); + + $server = array(); + $server['SCRIPT_NAME'] = '/index.php'; + $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/index.php', $request->getScriptName()); + } + + public function testGetBasePath() + { + $request = new Request(); + $this->assertEquals('', $request->getBasePath()); + + $server = array(); + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + $request->initialize(array(), array(), array(), array(), array(), $server); + $this->assertEquals('', $request->getBasePath()); + + $server = array(); + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + $server['SCRIPT_NAME'] = '/index.php'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('', $request->getBasePath()); + + $server = array(); + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + $server['PHP_SELF'] = '/index.php'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('', $request->getBasePath()); + + $server = array(); + $server['SCRIPT_FILENAME'] = '/some/where/index.php'; + $server['ORIG_SCRIPT_NAME'] = '/index.php'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('', $request->getBasePath()); + } + + public function testGetPathInfo() + { + $request = new Request(); + $this->assertEquals('/', $request->getPathInfo()); + + $server = array(); + $server['REQUEST_URI'] = '/path/info'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/path/info', $request->getPathInfo()); + + $server = array(); + $server['REQUEST_URI'] = '/path%20test/info'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/path%20test/info', $request->getPathInfo()); + } + + public function testGetPreferredLanguage() + { + $request = new Request(); + $this->assertNull($request->getPreferredLanguage()); + $this->assertNull($request->getPreferredLanguage(array())); + $this->assertEquals('fr', $request->getPreferredLanguage(array('fr'))); + $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en'))); + $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr'))); + $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr'))); + + $request = new Request(); + $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); + $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us'))); + + $request = new Request(); + $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); + $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); + } + + public function testIsXmlHttpRequest() + { + $request = new Request(); + $this->assertFalse($request->isXmlHttpRequest()); + + $request->headers->set('X-Requested-With', 'XMLHttpRequest'); + $this->assertTrue($request->isXmlHttpRequest()); + + $request->headers->remove('X-Requested-With'); + $this->assertFalse($request->isXmlHttpRequest()); + } + + public function testGetCharsets() + { + $request = new Request(); + $this->assertEquals(array(), $request->getCharsets()); + $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); + $this->assertEquals(array(), $request->getCharsets()); // testing caching + + $request = new Request(); + $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); + $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets()); + + $request = new Request(); + $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'); + $this->assertEquals(array('ISO-8859-1', '*', 'utf-8'), $request->getCharsets()); + } + + public function testGetAcceptableContentTypes() + { + $request = new Request(); + $this->assertEquals(array(), $request->getAcceptableContentTypes()); + $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); + $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching + + $request = new Request(); + $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); + $this->assertEquals(array('multipart/mixed', '*/*', 'text/html', 'application/xhtml+xml', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/vnd.wap.wmlscriptc'), $request->getAcceptableContentTypes()); + } + + public function testGetLanguages() + { + $request = new Request(); + $this->assertEquals(array(), $request->getLanguages()); + + $request = new Request(); + $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); + $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); + $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); + + $request = new Request(); + $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6'); + $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages()); + } + + public function testGetRequestFormat() + { + $request = new Request(); + $this->assertEquals('html', $request->getRequestFormat()); + + $request = new Request(); + $this->assertNull($request->getRequestFormat(null)); + + $request = new Request(); + $this->assertNull($request->setRequestFormat('foo')); + $this->assertEquals('foo', $request->getRequestFormat(null)); + } + + public function testForwardedSecure() + { + $request = new Request(); + $request->headers->set('X-Forwarded-Proto', 'https'); + $request->headers->set('X-Forwarded-Port', 443); + + $this->startTrustingProxyData(); + $this->assertTrue($request->isSecure()); + $this->assertEquals(443, $request->getPort()); + $this->stopTrustingProxyData(); + } + + public function testHasSession() + { + $request = new Request(); + + $this->assertFalse($request->hasSession()); + $request->setSession(new Session(new MockArraySessionStorage())); + $this->assertTrue($request->hasSession()); + } + + public function testHasPreviousSession() + { + $request = new Request(); + + $this->assertFalse($request->hasPreviousSession()); + $request->cookies->set('MOCKSESSID', 'foo'); + $this->assertFalse($request->hasPreviousSession()); + $request->setSession(new Session(new MockArraySessionStorage())); + $this->assertTrue($request->hasPreviousSession()); + } + + public function testToString() + { + $request = new Request(); + + $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); + + $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $request->__toString()); + } + + /** + * @dataProvider splitHttpAcceptHeaderData + */ + public function testSplitHttpAcceptHeader($acceptHeader, $expected) + { + $request = new Request(); + + $this->assertEquals($expected, $request->splitHttpAcceptHeader($acceptHeader)); + } + + public function splitHttpAcceptHeaderData() + { + return array( + array(null, array()), + array('text/html;q=0.8', array('text/html' => 0.8)), + array('text/html;foo=bar;q=0.8 ', array('text/html;foo=bar' => 0.8)), + array('text/html;charset=utf-8; q=0.8', array('text/html;charset=utf-8' => 0.8)), + array('text/html,application/xml;q=0.9,*/*;charset=utf-8; q=0.8', array('text/html' => 1, 'application/xml' => 0.9, '*/*;charset=utf-8' => 0.8)), + array('text/html,application/xhtml+xml;q=0.9,*/*;q=0.8; foo=bar', array('text/html' => 1, 'application/xhtml+xml' => 0.9, '*/*' => 0.8)), + array('text/html,application/xhtml+xml;charset=utf-8;q=0.9; foo=bar,*/*', array('text/html' => 1, '*/*' => 1, 'application/xhtml+xml;charset=utf-8' => 0.9)), + array('text/html,application/xhtml+xml', array('application/xhtml+xml' => 1, 'text/html' => 1)), + ); + } + + public function testIsProxyTrusted() + { + $this->startTrustingProxyData(); + $this->assertTrue(Request::isProxyTrusted()); + $this->stopTrustingProxyData(); + $this->assertFalse(Request::isProxyTrusted()); + } + + public function testIsMethod() + { + $request = new Request(); + $request->setMethod('POST'); + $this->assertTrue($request->isMethod('POST')); + $this->assertTrue($request->isMethod('post')); + $this->assertFalse($request->isMethod('GET')); + $this->assertFalse($request->isMethod('get')); + + $request->setMethod('GET'); + $this->assertTrue($request->isMethod('GET')); + $this->assertTrue($request->isMethod('get')); + $this->assertFalse($request->isMethod('POST')); + $this->assertFalse($request->isMethod('post')); + } + + private function startTrustingProxyData() + { + Request::trustProxyData(); + } + + /** + * @dataProvider getBaseUrlData + */ + public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo) + { + $request = Request::create($uri, 'GET', array(), array(), array(), $server); + + $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl'); + $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo'); + } + + public function getBaseUrlData() + { + return array( + array( + '/foo%20bar', + array( + 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', + 'SCRIPT_NAME' => '/foo bar/app.php', + 'PHP_SELF' => '/foo bar/app.php', + ), + '/foo%20bar', + '/', + ), + array( + '/foo%20bar/home', + array( + 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', + 'SCRIPT_NAME' => '/foo bar/app.php', + 'PHP_SELF' => '/foo bar/app.php', + ), + '/foo%20bar', + '/home', + ), + array( + '/foo%20bar/app.php/home', + array( + 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', + 'SCRIPT_NAME' => '/foo bar/app.php', + 'PHP_SELF' => '/foo bar/app.php', + ), + '/foo%20bar/app.php', + '/home', + ), + array( + '/foo%20bar/app.php/home%3Dbaz', + array( + 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', + 'SCRIPT_NAME' => '/foo bar/app.php', + 'PHP_SELF' => '/foo bar/app.php', + ), + '/foo%20bar/app.php', + '/home%3Dbaz', + ), + array( + '/foo/bar+baz', + array( + 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php', + 'SCRIPT_NAME' => '/foo/app.php', + 'PHP_SELF' => '/foo/app.php', + ), + '/foo', + '/bar+baz', + ), + ); + } + + /** + * @dataProvider urlencodedStringPrefixData + */ + public function testUrlencodedStringPrefix($string, $prefix, $expect) + { + $request = new Request; + + $me = new \ReflectionMethod($request, 'getUrlencodedPrefix'); + $me->setAccessible(true); + + $this->assertSame($expect, $me->invoke($request, $string, $prefix)); + } + + public function urlencodedStringPrefixData() + { + return array( + array('foo', 'foo', 'foo'), + array('fo%6f', 'foo', 'fo%6f'), + array('foo/bar', 'foo', 'foo'), + array('fo%6f/bar', 'foo', 'fo%6f'), + array('f%6f%6f/bar', 'foo', 'f%6f%6f'), + array('%66%6F%6F/bar', 'foo', '%66%6F%6F'), + array('fo+o/bar', 'fo+o', 'fo+o'), + array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'), + ); + } + + private function stopTrustingProxyData() + { + $class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request'); + $property = $class->getProperty('trustProxy'); + $property->setAccessible(true); + $property->setValue(false); + } +} + +class RequestContentProxy extends Request +{ + public function getContent($asResource = false) + { + return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent')); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php new file mode 100644 index 0000000..0e8a67d --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php @@ -0,0 +1,176 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\HttpFoundation\Cookie; + +class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase +{ + public function testCacheControlHeader() + { + $bag = new ResponseHeaderBag(array()); + $this->assertEquals('no-cache', $bag->get('Cache-Control')); + $this->assertTrue($bag->hasCacheControlDirective('no-cache')); + + $bag = new ResponseHeaderBag(array('Cache-Control' => 'public')); + $this->assertEquals('public', $bag->get('Cache-Control')); + $this->assertTrue($bag->hasCacheControlDirective('public')); + + $bag = new ResponseHeaderBag(array('ETag' => 'abcde')); + $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); + $this->assertTrue($bag->hasCacheControlDirective('private')); + $this->assertTrue($bag->hasCacheControlDirective('must-revalidate')); + $this->assertFalse($bag->hasCacheControlDirective('max-age')); + + $bag = new ResponseHeaderBag(array('Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT')); + $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(array( + 'Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT', + 'Cache-Control' => 'max-age=3600' + )); + $this->assertEquals('max-age=3600, private', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(array('Last-Modified' => 'abcde')); + $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(array('Etag' => 'abcde', 'Last-Modified' => 'abcde')); + $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(array('cache-control' => 'max-age=100')); + $this->assertEquals('max-age=100, private', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(array('cache-control' => 's-maxage=100')); + $this->assertEquals('s-maxage=100', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(array('cache-control' => 'private, max-age=100')); + $this->assertEquals('max-age=100, private', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(array('cache-control' => 'public, max-age=100')); + $this->assertEquals('max-age=100, public', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(); + $bag->set('Last-Modified', 'abcde'); + $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); + } + + public function testToStringIncludesCookieHeaders() + { + $bag = new ResponseHeaderBag(array()); + $bag->setCookie(new Cookie('foo', 'bar')); + + $this->assertContains("Set-Cookie: foo=bar; httponly", explode("\r\n", $bag->__toString())); + + $bag->clearCookie('foo'); + + $this->assertContains("Set-Cookie: foo=deleted; expires=".gmdate("D, d-M-Y H:i:s T", time() - 31536001)."; httponly", explode("\r\n", $bag->__toString())); + } + + public function testCookiesWithSameNames() + { + $bag = new ResponseHeaderBag(); + $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar')); + $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'foo.bar')); + $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'bar.foo')); + $bag->setCookie(new Cookie('foo', 'bar')); + + $this->assertCount(4, $bag->getCookies()); + + $headers = explode("\r\n", $bag->__toString()); + $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers); + $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers); + $this->assertContains("Set-Cookie: foo=bar; path=/path/bar; domain=bar.foo; httponly", $headers); + $this->assertContains("Set-Cookie: foo=bar; httponly", $headers); + + $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); + $this->assertTrue(isset($cookies['foo.bar']['/path/foo']['foo'])); + $this->assertTrue(isset($cookies['foo.bar']['/path/bar']['foo'])); + $this->assertTrue(isset($cookies['bar.foo']['/path/bar']['foo'])); + $this->assertTrue(isset($cookies['']['/']['foo'])); + } + + public function testRemoveCookie() + { + $bag = new ResponseHeaderBag(); + $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar')); + $bag->setCookie(new Cookie('bar', 'foo', 0, '/path/bar', 'foo.bar')); + + $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); + $this->assertTrue(isset($cookies['foo.bar']['/path/foo'])); + + $bag->removeCookie('foo', '/path/foo', 'foo.bar'); + + $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); + $this->assertFalse(isset($cookies['foo.bar']['/path/foo'])); + + $bag->removeCookie('bar', '/path/bar', 'foo.bar'); + + $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); + $this->assertFalse(isset($cookies['foo.bar'])); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testMakeDispositionInvalidDisposition() + { + $headers = new ResponseHeaderBag(); + + $headers->makeDisposition('invalid', 'foo.html'); + } + + /** + * @dataProvider provideMakeDisposition + */ + public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected) + { + $headers = new ResponseHeaderBag(); + + $this->assertEquals($expected, $headers->makeDisposition($disposition, $filename, $filenameFallback)); + } + + public function provideMakeDisposition() + { + return array( + array('attachment', 'foo.html', 'foo.html', 'attachment; filename="foo.html"'), + array('attachment', 'foo.html', '', 'attachment; filename="foo.html"'), + array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'), + array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'), + array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'), + array('attachment', 'föö.html', 'foo.html', 'attachment; filename="foo.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html'), + ); + } + + /** + * @dataProvider provideMakeDispositionFail + * @expectedException \InvalidArgumentException + */ + public function testMakeDispositionFail($disposition, $filename) + { + $headers = new ResponseHeaderBag(); + + $headers->makeDisposition($disposition, $filename); + } + + public function provideMakeDispositionFail() + { + return array( + array('attachment', 'foo%20bar.html'), + array('attachment', 'foo/bar.html'), + array('attachment', '/foo.html'), + array('attachment', 'foo\bar.html'), + array('attachment', '\foo.html'), + array('attachment', 'föö.html'), + ); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/ResponseTest.php new file mode 100644 index 0000000..6e76cd2 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/ResponseTest.php @@ -0,0 +1,558 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class ResponseTest extends \PHPUnit_Framework_TestCase +{ + public function testCreate() + { + $response = Response::create('foo', 301, array('Foo' => 'bar')); + + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); + $this->assertEquals(301, $response->getStatusCode()); + $this->assertEquals('bar', $response->headers->get('foo')); + } + + public function testIsValidateable() + { + $response = new Response('', 200, array('Last-Modified' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); + $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if Last-Modified is present'); + + $response = new Response('', 200, array('ETag' => '"12345"')); + $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if ETag is present'); + + $response = new Response(); + $this->assertFalse($response->isValidateable(), '->isValidateable() returns false when no validator is present'); + } + + public function testGetDate() + { + $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); + $this->assertEquals(0, $this->createDateTimeOneHourAgo()->diff($response->getDate())->format('%s'), '->getDate() returns the Date header if present'); + + $response = new Response(); + $date = $response->getDate(); + $this->assertLessThan(1, $date->diff(new \DateTime(), true)->format('%s'), '->getDate() returns the current Date if no Date header present'); + + $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); + $now = $this->createDateTimeNow(); + $response->headers->set('Date', $now->format(DATE_RFC2822)); + $this->assertEquals(0, $now->diff($response->getDate())->format('%s'), '->getDate() returns the date when the header has been modified'); + } + + public function testGetMaxAge() + { + $response = new Response(); + $response->headers->set('Cache-Control', 's-maxage=600, max-age=0'); + $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() uses s-maxage cache control directive when present'); + + $response = new Response(); + $response->headers->set('Cache-Control', 'max-age=600'); + $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() falls back to max-age when no s-maxage directive present'); + + $response = new Response(); + $response->headers->set('Cache-Control', 'must-revalidate'); + $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822)); + $this->assertEquals(3600, $response->getMaxAge(), '->getMaxAge() falls back to Expires when no max-age or s-maxage directive present'); + + $response = new Response(); + $this->assertNull($response->getMaxAge(), '->getMaxAge() returns null if no freshness information available'); + } + + public function testSetSharedMaxAge() + { + $response = new Response(); + $response->setSharedMaxAge(20); + + $cacheControl = $response->headers->get('Cache-Control'); + $this->assertEquals('public, s-maxage=20', $cacheControl); + } + + public function testIsPrivate() + { + $response = new Response(); + $response->headers->set('Cache-Control', 'max-age=100'); + $response->setPrivate(); + $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true'); + $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true'); + + $response = new Response(); + $response->headers->set('Cache-Control', 'public, max-age=100'); + $response->setPrivate(); + $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true'); + $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true'); + $this->assertFalse($response->headers->hasCacheControlDirective('public'), '->isPrivate() removes the public Cache-Control directive'); + } + + public function testExpire() + { + $response = new Response(); + $response->headers->set('Cache-Control', 'max-age=100'); + $response->expire(); + $this->assertEquals(100, $response->headers->get('Age'), '->expire() sets the Age to max-age when present'); + + $response = new Response(); + $response->headers->set('Cache-Control', 'max-age=100, s-maxage=500'); + $response->expire(); + $this->assertEquals(500, $response->headers->get('Age'), '->expire() sets the Age to s-maxage when both max-age and s-maxage are present'); + + $response = new Response(); + $response->headers->set('Cache-Control', 'max-age=5, s-maxage=500'); + $response->headers->set('Age', '1000'); + $response->expire(); + $this->assertEquals(1000, $response->headers->get('Age'), '->expire() does nothing when the response is already stale/expired'); + + $response = new Response(); + $response->expire(); + $this->assertFalse($response->headers->has('Age'), '->expire() does nothing when the response does not include freshness information'); + } + + public function testGetTtl() + { + $response = new Response(); + $this->assertNull($response->getTtl(), '->getTtl() returns null when no Expires or Cache-Control headers are present'); + + $response = new Response(); + $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822)); + $this->assertLessThan(1, 3600 - $response->getTtl(), '->getTtl() uses the Expires header when no max-age is present'); + + $response = new Response(); + $response->headers->set('Expires', $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)); + $this->assertLessThan(0, $response->getTtl(), '->getTtl() returns negative values when Expires is in part'); + + $response = new Response(); + $response->headers->set('Cache-Control', 'max-age=60'); + $this->assertLessThan(1, 60 - $response->getTtl(), '->getTtl() uses Cache-Control max-age when present'); + } + + public function testSetClientTtl() + { + $response = new Response(); + $response->setClientTtl(10); + + $this->assertEquals($response->getMaxAge(), $response->getAge() + 10); + } + + public function testGetSetProtocolVersion() + { + $response = new Response(); + + $this->assertEquals('1.0', $response->getProtocolVersion()); + + $response->setProtocolVersion('1.1'); + + $this->assertEquals('1.1', $response->getProtocolVersion()); + } + + public function testGetVary() + { + $response = new Response(); + $this->assertEquals(array(), $response->getVary(), '->getVary() returns an empty array if no Vary header is present'); + + $response = new Response(); + $response->headers->set('Vary', 'Accept-Language'); + $this->assertEquals(array('Accept-Language'), $response->getVary(), '->getVary() parses a single header name value'); + + $response = new Response(); + $response->headers->set('Vary', 'Accept-Language User-Agent X-Foo'); + $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by spaces'); + + $response = new Response(); + $response->headers->set('Vary', 'Accept-Language,User-Agent, X-Foo'); + $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by commas'); + } + + public function testSetVary() + { + $response = new Response(); + $response->setVary('Accept-Language'); + $this->assertEquals(array('Accept-Language'), $response->getVary()); + + $response->setVary('Accept-Language, User-Agent'); + $this->assertEquals(array('Accept-Language', 'User-Agent'), $response->getVary(), '->setVary() replace the vary header by default'); + + $response->setVary('X-Foo', false); + $this->assertEquals(array('Accept-Language', 'User-Agent'), $response->getVary(), '->setVary() doesn\'t change the Vary header if replace is set to false'); + } + + public function testDefaultContentType() + { + $headerMock = $this->getMock('Symfony\Component\HttpFoundation\ResponseHeaderBag', array('set')); + $headerMock->expects($this->at(0)) + ->method('set') + ->with('Content-Type', 'text/html'); + $headerMock->expects($this->at(1)) + ->method('set') + ->with('Content-Type', 'text/html; charset=UTF-8'); + + $response = new Response('foo'); + $response->headers = $headerMock; + + $response->prepare(new Request()); + } + + public function testContentTypeCharset() + { + $response = new Response(); + $response->headers->set('Content-Type', 'text/css'); + + // force fixContentType() to be called + $response->prepare(new Request()); + + $this->assertEquals('text/css; charset=UTF-8', $response->headers->get('Content-Type')); + } + + public function testPrepareDoesNothingIfContentTypeIsSet() + { + $response = new Response('foo'); + $response->headers->set('Content-Type', 'text/plain'); + + $response->prepare(new Request()); + + $this->assertEquals('text/plain; charset=UTF-8', $response->headers->get('content-type')); + } + + public function testPrepareDoesNothingIfRequestFormatIsNotDefined() + { + $response = new Response('foo'); + + $response->prepare(new Request()); + + $this->assertEquals('text/html; charset=UTF-8', $response->headers->get('content-type')); + } + + public function testPrepareSetContentType() + { + $response = new Response('foo'); + $request = Request::create('/'); + $request->setRequestFormat('json'); + + $response->prepare($request); + + $this->assertEquals('application/json', $response->headers->get('content-type')); + } + + public function testPrepareRemovesContentForHeadRequests() + { + $response = new Response('foo'); + $request = Request::create('/', 'HEAD'); + + $response->prepare($request); + + $this->assertEquals('', $response->getContent()); + } + + public function testSetCache() + { + $response = new Response(); + //array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public') + try { + $response->setCache(array("wrong option" => "value")); + $this->fail('->setCache() throws an InvalidArgumentException if an option is not supported'); + } catch (\Exception $e) { + $this->assertInstanceOf('InvalidArgumentException', $e, '->setCache() throws an InvalidArgumentException if an option is not supported'); + $this->assertContains('"wrong option"', $e->getMessage()); + } + + $options = array('etag' => '"whatever"'); + $response->setCache($options); + $this->assertEquals($response->getEtag(), '"whatever"'); + + $now = new \DateTime(); + $options = array('last_modified' => $now); + $response->setCache($options); + $this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp()); + + $options = array('max_age' => 100); + $response->setCache($options); + $this->assertEquals($response->getMaxAge(), 100); + + $options = array('s_maxage' => 200); + $response->setCache($options); + $this->assertEquals($response->getMaxAge(), 200); + + $this->assertTrue($response->headers->hasCacheControlDirective('public')); + $this->assertFalse($response->headers->hasCacheControlDirective('private')); + + $response->setCache(array('public' => true)); + $this->assertTrue($response->headers->hasCacheControlDirective('public')); + $this->assertFalse($response->headers->hasCacheControlDirective('private')); + + $response->setCache(array('public' => false)); + $this->assertFalse($response->headers->hasCacheControlDirective('public')); + $this->assertTrue($response->headers->hasCacheControlDirective('private')); + + $response->setCache(array('private' => true)); + $this->assertFalse($response->headers->hasCacheControlDirective('public')); + $this->assertTrue($response->headers->hasCacheControlDirective('private')); + + $response->setCache(array('private' => false)); + $this->assertTrue($response->headers->hasCacheControlDirective('public')); + $this->assertFalse($response->headers->hasCacheControlDirective('private')); + } + + public function testSendContent() + { + $response = new Response('test response rendering', 200); + + ob_start(); + $response->sendContent(); + $string = ob_get_clean(); + $this->assertContains('test response rendering', $string); + } + + public function testSetPublic() + { + $response = new Response(); + $response->setPublic(); + + $this->assertTrue($response->headers->hasCacheControlDirective('public')); + $this->assertFalse($response->headers->hasCacheControlDirective('private')); + } + + public function testSetExpires() + { + $response = new Response(); + $response->setExpires(null); + + $this->assertNull($response->getExpires(), '->setExpires() remove the header when passed null'); + + $now = new \DateTime(); + $response->setExpires($now); + + $this->assertEquals($response->getExpires()->getTimestamp(), $now->getTimestamp()); + } + + public function testSetLastModified() + { + $response = new Response(); + $response->setLastModified(new \DateTime()); + $this->assertNotNull($response->getLastModified()); + + $response->setLastModified(null); + $this->assertNull($response->getLastModified()); + } + + public function testIsInvalid() + { + $response = new Response(); + + try { + $response->setStatusCode(99); + $this->fail(); + } catch(\InvalidArgumentException $e) { + $this->assertTrue($response->isInvalid()); + } + + try { + $response->setStatusCode(650); + $this->fail(); + } catch(\InvalidArgumentException $e) { + $this->assertTrue($response->isInvalid()); + } + + $response = new Response('', 200); + $this->assertFalse($response->isInvalid()); + } + + public function testIsInformational() + { + $response = new Response('', 100); + $this->assertTrue($response->isInformational()); + + $response = new Response('', 200); + $this->assertFalse($response->isInformational()); + } + + public function testIsRedirectRedirection() + { + foreach (array(301, 302, 303, 307) as $code) + { + $response = new Response('', $code); + $this->assertTrue($response->isRedirection()); + $this->assertTrue($response->isRedirect()); + } + + $response = new Response('', 304); + $this->assertTrue($response->isRedirection()); + $this->assertFalse($response->isRedirect()); + + $response = new Response('', 200); + $this->assertFalse($response->isRedirection()); + $this->assertFalse($response->isRedirect()); + + $response = new Response('', 404); + $this->assertFalse($response->isRedirection()); + $this->assertFalse($response->isRedirect()); + + $response = new Response('', 301, array('Location' => '/good-uri')); + $this->assertFalse($response->isRedirect('/bad-uri')); + $this->assertTrue($response->isRedirect('/good-uri')); + } + + public function testIsNotFound() + { + $response = new Response('', 404); + $this->assertTrue($response->isNotFound()); + + $response = new Response('', 200); + $this->assertFalse($response->isNotFound()); + } + + public function testIsEmpty() + { + foreach (array(201, 204, 304) as $code) + { + $response = new Response('', $code); + $this->assertTrue($response->isEmpty()); + } + + $response = new Response('', 200); + $this->assertFalse($response->isEmpty()); + } + + public function testIsForbidden() + { + $response = new Response('', 403); + $this->assertTrue($response->isForbidden()); + + $response = new Response('', 200); + $this->assertFalse($response->isForbidden()); + } + + public function testIsOk() + { + $response = new Response('', 200); + $this->assertTrue($response->isOk()); + + $response = new Response('', 404); + $this->assertFalse($response->isOk()); + } + + public function testIsServerOrClientError() + { + $response = new Response('', 404); + $this->assertTrue($response->isClientError()); + $this->assertFalse($response->isServerError()); + + $response = new Response('', 500); + $this->assertFalse($response->isClientError()); + $this->assertTrue($response->isServerError()); + } + + public function testHasVary() + { + $response = new Response(); + $this->assertFalse($response->hasVary()); + + $response->setVary('User-Agent'); + $this->assertTrue($response->hasVary()); + } + + public function testSetEtag() + { + $response = new Response('', 200, array('ETag' => '"12345"')); + $response->setEtag(); + + $this->assertNull($response->headers->get('Etag'), '->setEtag() removes Etags when call with null'); + } + + /** + * @dataProvider validContentProvider + */ + public function testSetContent($content) + { + $response = new Response(); + $response->setContent($content); + $this->assertEquals((string) $content, $response->getContent()); + } + + /** + * @expectedException UnexpectedValueException + * @dataProvider invalidContentProvider + */ + public function testSetContentInvalid($content) + { + $response = new Response(); + $response->setContent($content); + } + + public function testSettersAreChainable() + { + $response = new Response(); + + $setters = array( + 'setProtocolVersion' => '1.0', + 'setCharset' => 'UTF-8', + 'setPublic' => null, + 'setPrivate' => null, + 'setDate' => new \DateTime, + 'expire' => null, + 'setMaxAge' => 1, + 'setSharedMaxAge' => 1, + 'setTtl' => 1, + 'setClientTtl' => 1, + ); + + foreach ($setters as $setter => $arg) { + $this->assertEquals($response, $response->{$setter}($arg)); + } + } + + public function validContentProvider() + { + return array( + 'obj' => array(new StringableObject), + 'string' => array('Foo'), + 'int' => array(2), + ); + } + + public function invalidContentProvider() + { + return array( + 'obj' => array(new \stdClass), + 'array' => array(array()), + 'bool' => array(true, '1'), + ); + } + + protected function createDateTimeOneHourAgo() + { + $date = new \DateTime(); + + return $date->sub(new \DateInterval('PT1H')); + } + + protected function createDateTimeOneHourLater() + { + $date = new \DateTime(); + + return $date->add(new \DateInterval('PT1H')); + } + + protected function createDateTimeNow() + { + return new \DateTime(); + } +} + +class StringableObject +{ + public function __toString() + { + return 'Foo'; + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php new file mode 100644 index 0000000..b99ad1c --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\ServerBag; + +/** + * ServerBagTest + * + * @author Bulat Shakirzyanov + */ +class ServerBagTest extends \PHPUnit_Framework_TestCase +{ + public function testShouldExtractHeadersFromServerArray() + { + $server = array( + 'SOME_SERVER_VARIABLE' => 'value', + 'SOME_SERVER_VARIABLE2' => 'value', + 'ROOT' => 'value', + 'HTTP_CONTENT_TYPE' => 'text/html', + 'HTTP_CONTENT_LENGTH' => '0', + 'HTTP_ETAG' => 'asdf', + 'PHP_AUTH_USER' => 'foo', + 'PHP_AUTH_PW' => 'bar', + ); + + $bag = new ServerBag($server); + + $this->assertEquals(array( + 'CONTENT_TYPE' => 'text/html', + 'CONTENT_LENGTH' => '0', + 'ETAG' => 'asdf', + 'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'), + ), $bag->getHeaders()); + } + + public function testHttpPasswordIsOptional() + { + $bag = new ServerBag(array('PHP_AUTH_USER' => 'foo')); + + $this->assertEquals(array('AUTHORIZATION' => 'Basic '.base64_encode('foo:')), $bag->getHeaders()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.php new file mode 100644 index 0000000..93c634c --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.php @@ -0,0 +1,193 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Attribute; + +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; + +/** + * Tests AttributeBag + * + * @author Drak + */ +class AttributeBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var array + */ + private $array; + + /** + * @var AttributeBag + */ + private $bag; + + protected function setUp() + { + $this->array = array( + 'hello' => 'world', + 'always' => 'be happy', + 'user.login' => 'drak', + 'csrf.token' => array( + 'a' => '1234', + 'b' => '4321', + ), + 'category' => array( + 'fishing' => array( + 'first' => 'cod', + 'second' => 'sole') + ), + ); + $this->bag = new AttributeBag('_sf2'); + $this->bag->initialize($this->array); + } + + protected function tearDown() + { + $this->bag = null; + $this->array = array(); + } + + public function testInitialize() + { + $bag = new AttributeBag(); + $bag->initialize($this->array); + $this->assertEquals($this->array, $bag->all()); + $array = array('should' => 'change'); + $bag->initialize($array); + $this->assertEquals($array, $bag->all()); + } + + public function testGetStorageKey() + { + $this->assertEquals('_sf2', $this->bag->getStorageKey()); + $attributeBag = new AttributeBag('test'); + $this->assertEquals('test', $attributeBag->getStorageKey()); + } + + public function testGetSetName() + { + $this->assertEquals('attributes', $this->bag->getName()); + $this->bag->setName('foo'); + $this->assertEquals('foo', $this->bag->getName()); + } + + /** + * @dataProvider attributesProvider + */ + public function testHas($key, $value, $exists) + { + $this->assertEquals($exists, $this->bag->has($key)); + } + + /** + * @dataProvider attributesProvider + */ + public function testGet($key, $value, $expected) + { + $this->assertEquals($value, $this->bag->get($key)); + } + + public function testGetDefaults() + { + $this->assertNull($this->bag->get('user2.login')); + $this->assertEquals('default', $this->bag->get('user2.login', 'default')); + } + + /** + * @dataProvider attributesProvider + */ + public function testSet($key, $value, $expected) + { + $this->bag->set($key, $value); + $this->assertEquals($value, $this->bag->get($key)); + } + + public function testAll() + { + $this->assertEquals($this->array, $this->bag->all()); + + $this->bag->set('hello', 'fabien'); + $array = $this->array; + $array['hello'] = 'fabien'; + $this->assertEquals($array, $this->bag->all()); + } + + public function testReplace() + { + $array = array(); + $array['name'] = 'jack'; + $array['foo.bar'] = 'beep'; + $this->bag->replace($array); + $this->assertEquals($array, $this->bag->all()); + $this->assertNull($this->bag->get('hello')); + $this->assertNull($this->bag->get('always')); + $this->assertNull($this->bag->get('user.login')); + } + + public function testRemove() + { + $this->assertEquals('world', $this->bag->get('hello')); + $this->bag->remove('hello'); + $this->assertNull($this->bag->get('hello')); + + $this->assertEquals('be happy', $this->bag->get('always')); + $this->bag->remove('always'); + $this->assertNull($this->bag->get('always')); + + $this->assertEquals('drak', $this->bag->get('user.login')); + $this->bag->remove('user.login'); + $this->assertNull($this->bag->get('user.login')); + } + + public function testClear() + { + $this->bag->clear(); + $this->assertEquals(array(), $this->bag->all()); + } + + public function attributesProvider() + { + return array( + array('hello', 'world', true), + array('always', 'be happy', true), + array('user.login', 'drak', true), + array('csrf.token', array('a' => '1234', 'b' => '4321'), true), + array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true), + array('user2.login', null, false), + array('never', null, false), + array('bye', null, false), + array('bye/for/now', null, false), + ); + } + + /** + * @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::getIterator + */ + public function testGetIterator() + { + $i = 0; + foreach ($this->bag as $key => $val) { + $this->assertEquals($this->array[$key], $val); + $i++; + } + + $this->assertEquals(count($this->array), $i); + } + + /** + * @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::count + */ + public function testCount() + { + $this->assertEquals(count($this->array), count($this->bag)); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php new file mode 100644 index 0000000..432499e --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php @@ -0,0 +1,171 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag; + +/** + * Tests NamespacedAttributeBag + * + * @author Drak + */ +class NamespacedAttributeBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var array + */ + private $array; + + /** + * @var NamespacedAttributeBag + */ + private $bag; + + protected function setUp() + { + $this->array = array( + 'hello' => 'world', + 'always' => 'be happy', + 'user.login' => 'drak', + 'csrf.token' => array( + 'a' => '1234', + 'b' => '4321', + ), + 'category' => array( + 'fishing' => array( + 'first' => 'cod', + 'second' => 'sole') + ), + ); + $this->bag = new NamespacedAttributeBag('_sf2', '/'); + $this->bag->initialize($this->array); + } + + protected function tearDown() + { + $this->bag = null; + $this->array = array(); + } + + public function testInitialize() + { + $bag = new NamespacedAttributeBag(); + $bag->initialize($this->array); + $this->assertEquals($this->array, $this->bag->all()); + $array = array('should' => 'not stick'); + $bag->initialize($array); + + // should have remained the same + $this->assertEquals($this->array, $this->bag->all()); + } + + public function testGetStorageKey() + { + $this->assertEquals('_sf2', $this->bag->getStorageKey()); + $attributeBag = new NamespacedAttributeBag('test'); + $this->assertEquals('test', $attributeBag->getStorageKey()); + } + + /** + * @dataProvider attributesProvider + */ + public function testHas($key, $value, $exists) + { + $this->assertEquals($exists, $this->bag->has($key)); + } + + /** + * @dataProvider attributesProvider + */ + public function testGet($key, $value, $expected) + { + $this->assertEquals($value, $this->bag->get($key)); + } + + public function testGetDefaults() + { + $this->assertNull($this->bag->get('user2.login')); + $this->assertEquals('default', $this->bag->get('user2.login', 'default')); + } + + /** + * @dataProvider attributesProvider + */ + public function testSet($key, $value, $expected) + { + $this->bag->set($key, $value); + $this->assertEquals($value, $this->bag->get($key)); + } + + public function testAll() + { + $this->assertEquals($this->array, $this->bag->all()); + + $this->bag->set('hello', 'fabien'); + $array = $this->array; + $array['hello'] = 'fabien'; + $this->assertEquals($array, $this->bag->all()); + } + + public function testReplace() + { + $array = array(); + $array['name'] = 'jack'; + $array['foo.bar'] = 'beep'; + $this->bag->replace($array); + $this->assertEquals($array, $this->bag->all()); + $this->assertNull($this->bag->get('hello')); + $this->assertNull($this->bag->get('always')); + $this->assertNull($this->bag->get('user.login')); + } + + public function testRemove() + { + $this->assertEquals('world', $this->bag->get('hello')); + $this->bag->remove('hello'); + $this->assertNull($this->bag->get('hello')); + + $this->assertEquals('be happy', $this->bag->get('always')); + $this->bag->remove('always'); + $this->assertNull($this->bag->get('always')); + + $this->assertEquals('drak', $this->bag->get('user.login')); + $this->bag->remove('user.login'); + $this->assertNull($this->bag->get('user.login')); + } + + public function testClear() + { + $this->bag->clear(); + $this->assertEquals(array(), $this->bag->all()); + } + + public function attributesProvider() + { + return array( + array('hello', 'world', true), + array('always', 'be happy', true), + array('user.login', 'drak', true), + array('csrf.token', array('a' => '1234', 'b' => '4321'), true), + array('csrf.token/a', '1234', true), + array('csrf.token/b', '4321', true), + array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true), + array('category/fishing', array('first' => 'cod', 'second' => 'sole'), true), + array('category/fishing/first', 'cod', true), + array('category/fishing/second', 'sole', true), + array('user2.login', null, false), + array('never', null, false), + array('bye', null, false), + array('bye/for/now', null, false), + ); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php new file mode 100644 index 0000000..5d44b78 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Flash; + +use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag as FlashBag; + +/** + * AutoExpireFlashBagTest + * + * @author Drak + */ +class AutoExpireFlashBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag + */ + private $bag; + + /** + * @var array + */ + protected $array = array(); + + protected function setUp() + { + parent::setUp(); + $this->bag = new FlashBag(); + $this->array = array('new' => array('notice' => array('A previous flash message'))); + $this->bag->initialize($this->array); + } + + public function tearDown() + { + $this->bag = null; + parent::tearDown(); + } + + public function testInitialize() + { + $bag = new FlashBag(); + $array = array('new' => array('notice' => array('A previous flash message'))); + $bag->initialize($array); + $this->assertEquals(array('A previous flash message'), $bag->peek('notice')); + $array = array('new' => array( + 'notice' => array('Something else'), + 'error' => array('a'), + )); + $bag->initialize($array); + $this->assertEquals(array('Something else'), $bag->peek('notice')); + $this->assertEquals(array('a'), $bag->peek('error')); + } + + public function testGetStorageKey() + { + $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey()); + $attributeBag = new FlashBag('test'); + $this->assertEquals('test', $attributeBag->getStorageKey()); + } + + public function testGetSetName() + { + $this->assertEquals('flashes', $this->bag->getName()); + $this->bag->setName('foo'); + $this->assertEquals('foo', $this->bag->getName()); + } + + public function testPeek() + { + $this->assertEquals(array(), $this->bag->peek('non_existing')); + $this->assertEquals(array('default'), $this->bag->peek('non_existing', array('default'))); + $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + } + + public function testSet() + { + $this->bag->set('notice', 'Foo'); + $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + } + + public function testHas() + { + $this->assertFalse($this->bag->has('nothing')); + $this->assertTrue($this->bag->has('notice')); + } + + public function testKeys() + { + $this->assertEquals(array('notice'), $this->bag->keys()); + } + + public function testPeekAll() + { + $array = array( + 'new' => array( + 'notice' => 'Foo', + 'error' => 'Bar', + ), + ); + + $this->bag->initialize($array); + $this->assertEquals(array( + 'notice' => 'Foo', + 'error' => 'Bar', + ), $this->bag->peekAll() + ); + + $this->assertEquals(array( + 'notice' => 'Foo', + 'error' => 'Bar', + ), $this->bag->peekAll() + ); + } + + public function testGet() + { + $this->assertEquals(array(), $this->bag->get('non_existing')); + $this->assertEquals(array('default'), $this->bag->get('non_existing', array('default'))); + $this->assertEquals(array('A previous flash message'), $this->bag->get('notice')); + $this->assertEquals(array(), $this->bag->get('notice')); + } + + public function testSetAll() + { + $this->bag->setAll(array('a' => 'first', 'b' => 'second')); + $this->assertFalse($this->bag->has('a')); + $this->assertFalse($this->bag->has('b')); + } + + public function testAll() + { + $this->bag->set('notice', 'Foo'); + $this->bag->set('error', 'Bar'); + $this->assertEquals(array( + 'notice' => array('A previous flash message'), + ), $this->bag->all() + ); + + $this->assertEquals(array(), $this->bag->all()); + } + + public function testClear() + { + $this->assertEquals(array('notice' => array('A previous flash message')), $this->bag->clear()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php new file mode 100644 index 0000000..d7d12e5 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php @@ -0,0 +1,168 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Flash; + +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; + +/** + * FlashBagTest + * + * @author Drak + */ +class FlashBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\HttpFoundation\SessionFlash\FlashBagInterface + */ + private $bag; + + /** + * @var array + */ + protected $array = array(); + + protected function setUp() + { + parent::setUp(); + $this->bag = new FlashBag(); + $this->array = array('notice' => array('A previous flash message')); + $this->bag->initialize($this->array); + } + + public function tearDown() + { + $this->bag = null; + parent::tearDown(); + } + + public function testInitialize() + { + $bag = new FlashBag(); + $bag->initialize($this->array); + $this->assertEquals($this->array, $bag->peekAll()); + $array = array('should' => array('change')); + $bag->initialize($array); + $this->assertEquals($array, $bag->peekAll()); + } + + public function testGetStorageKey() + { + $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey()); + $attributeBag = new FlashBag('test'); + $this->assertEquals('test', $attributeBag->getStorageKey()); + } + + public function testGetSetName() + { + $this->assertEquals('flashes', $this->bag->getName()); + $this->bag->setName('foo'); + $this->assertEquals('foo', $this->bag->getName()); + } + + public function testPeek() + { + $this->assertEquals(array(), $this->bag->peek('non_existing')); + $this->assertEquals(array('default'), $this->bag->peek('not_existing', array('default'))); + $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + } + + public function testGet() + { + $this->assertEquals(array(), $this->bag->get('non_existing')); + $this->assertEquals(array('default'), $this->bag->get('not_existing', array('default'))); + $this->assertEquals(array('A previous flash message'), $this->bag->get('notice')); + $this->assertEquals(array(), $this->bag->get('notice')); + } + + public function testAll() + { + $this->bag->set('notice', 'Foo'); + $this->bag->set('error', 'Bar'); + $this->assertEquals(array( + 'notice' => array('Foo'), + 'error' => array('Bar')), $this->bag->all() + ); + + $this->assertEquals(array(), $this->bag->all()); + } + + public function testSet() + { + $this->bag->set('notice', 'Foo'); + $this->bag->set('notice', 'Bar'); + $this->assertEquals(array('Bar'), $this->bag->peek('notice')); + } + + public function testHas() + { + $this->assertFalse($this->bag->has('nothing')); + $this->assertTrue($this->bag->has('notice')); + } + + public function testKeys() + { + $this->assertEquals(array('notice'), $this->bag->keys()); + } + + public function testPeekAll() + { + $this->bag->set('notice', 'Foo'); + $this->bag->set('error', 'Bar'); + $this->assertEquals(array( + 'notice' => array('Foo'), + 'error' => array('Bar'), + ), $this->bag->peekAll() + ); + $this->assertTrue($this->bag->has('notice')); + $this->assertTrue($this->bag->has('error')); + $this->assertEquals(array( + 'notice' => array('Foo'), + 'error' => array('Bar'), + ), $this->bag->peekAll() + ); + } + + /** + * @covers Symfony\Component\HttpFoundation\Session\Flash\FlashBag::count + */ + public function testCount() + { + $flashes = array('hello' => 'world', 'beep' => 'boop', 'notice' => 'nope'); + foreach ($flashes as $key => $val) { + $this->bag->set($key, $val); + } + + $this->assertEquals(count($flashes), count($this->bag)); + } + + /** + * @covers Symfony\Component\HttpFoundation\Session\Flash\FlashBag::getIterator + */ + public function testGetIterator() + { + $flashes = array('hello' => 'world', 'beep' => 'boop', 'notice' => 'nope'); + foreach ($flashes as $key => $val) { + $this->bag->set($key, $val); + } + + $i = 0; + foreach ($this->bag as $key => $val) { + $this->assertEquals(array($flashes[$key]), $val); + $i++; + } + + $this->assertEquals(count($flashes), $i); + $this->assertEquals(0, count($this->bag)); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php new file mode 100644 index 0000000..bd45b2f --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php @@ -0,0 +1,262 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session; + +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\MetadataBag; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; + +/** + * SessionTest + * + * @author Fabien Potencier + * @author Robert Schönthal + * @author Drak + */ +class SessionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface + */ + protected $storage; + + /** + * @var \Symfony\Component\HttpFoundation\Session\SessionInterface + */ + protected $session; + + protected function setUp() + { + $this->storage = new MockArraySessionStorage(); + $this->session = new Session($this->storage, new AttributeBag(), new FlashBag()); + } + + protected function tearDown() + { + $this->storage = null; + $this->session = null; + } + + public function testStart() + { + $this->assertEquals('', $this->session->getId()); + $this->assertTrue($this->session->start()); + $this->assertNotEquals('', $this->session->getId()); + } + + public function testGet() + { + // tests defaults + $this->assertNull($this->session->get('foo')); + $this->assertEquals(1, $this->session->get('foo', 1)); + } + + /** + * @dataProvider setProvider + */ + public function testSet($key, $value) + { + $this->session->set($key, $value); + $this->assertEquals($value, $this->session->get($key)); + } + + /** + * @dataProvider setProvider + */ + public function testHas($key, $value) + { + $this->session->set($key, $value); + $this->assertTrue($this->session->has($key)); + $this->assertFalse($this->session->has($key.'non_value')); + } + + public function testReplace() + { + $this->session->replace(array('happiness' => 'be good', 'symfony' => 'awesome')); + $this->assertEquals(array('happiness' => 'be good', 'symfony' => 'awesome'), $this->session->all()); + $this->session->replace(array()); + $this->assertEquals(array(), $this->session->all()); + } + + /** + * @dataProvider setProvider + */ + public function testAll($key, $value, $result) + { + $this->session->set($key, $value); + $this->assertEquals($result, $this->session->all()); + } + + /** + * @dataProvider setProvider + */ + public function testClear($key, $value) + { + $this->session->set('hi', 'fabien'); + $this->session->set($key, $value); + $this->session->clear(); + $this->assertEquals(array(), $this->session->all()); + } + + public function setProvider() + { + return array( + array('foo', 'bar', array('foo' => 'bar')), + array('foo.bar', 'too much beer', array('foo.bar' => 'too much beer')), + array('great', 'symfony2 is great', array('great' => 'symfony2 is great')), + ); + } + + /** + * @dataProvider setProvider + */ + public function testRemove($key, $value) + { + $this->session->set('hi.world', 'have a nice day'); + $this->session->set($key, $value); + $this->session->remove($key); + $this->assertEquals(array('hi.world' => 'have a nice day'), $this->session->all()); + } + + public function testInvalidate() + { + $this->session->set('invalidate', 123); + $this->session->invalidate(); + $this->assertEquals(array(), $this->session->all()); + } + + public function testMigrate() + { + $this->session->set('migrate', 321); + $this->session->migrate(); + $this->assertEquals(321, $this->session->get('migrate')); + } + + public function testMigrateDestroy() + { + $this->session->set('migrate', 333); + $this->session->migrate(true); + $this->assertEquals(333, $this->session->get('migrate')); + } + + public function testSave() + { + $this->session->save(); + } + + public function testGetId() + { + $this->assertEquals('', $this->session->getId()); + $this->session->start(); + $this->assertNotEquals('', $this->session->getId()); + } + + public function testGetFlashBag() + { + $this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface', $this->session->getFlashBag()); + } + + // deprecated since 2.1, will be removed from 2.3 + + public function testGetSetFlashes() + { + $array = array('notice' => 'hello', 'error' => 'none'); + $this->assertEquals(array(), $this->session->getFlashes()); + $this->session->setFlashes($array); + $this->assertEquals($array, $this->session->getFlashes()); + $this->assertEquals(array(), $this->session->getFlashes()); + $this->session->getFlashBag()->add('notice', 'foo'); + + // test that BC works by only retrieving the first added. + $this->session->getFlashBag()->add('notice', 'foo2'); + $this->assertEquals(array('notice' => 'foo'), $this->session->getFlashes()); + } + + public function testGetSetFlash() + { + $this->assertNull($this->session->getFlash('notice')); + $this->assertEquals('default', $this->session->getFlash('notice', 'default')); + $this->session->getFlashBag()->add('notice', 'foo'); + $this->session->getFlashBag()->add('notice', 'foo2'); + + // test that BC works by only retrieving the first added. + $this->assertEquals('foo', $this->session->getFlash('notice')); + $this->assertNull($this->session->getFlash('notice')); + } + + public function testHasFlash() + { + $this->assertFalse($this->session->hasFlash('notice')); + $this->session->setFlash('notice', 'foo'); + $this->assertTrue($this->session->hasFlash('notice')); + } + + public function testRemoveFlash() + { + $this->session->setFlash('notice', 'foo'); + $this->session->setFlash('error', 'bar'); + $this->assertTrue($this->session->hasFlash('notice')); + $this->session->removeFlash('error'); + $this->assertTrue($this->session->hasFlash('notice')); + $this->assertFalse($this->session->hasFlash('error')); + } + + public function testClearFlashes() + { + $this->assertFalse($this->session->hasFlash('notice')); + $this->assertFalse($this->session->hasFlash('error')); + $this->session->setFlash('notice', 'foo'); + $this->session->setFlash('error', 'bar'); + $this->assertTrue($this->session->hasFlash('notice')); + $this->assertTrue($this->session->hasFlash('error')); + $this->session->clearFlashes(); + $this->assertFalse($this->session->hasFlash('notice')); + $this->assertFalse($this->session->hasFlash('error')); + } + + /** + * @covers Symfony\Component\HttpFoundation\Session\Session::getIterator + */ + public function testGetIterator() + { + $attributes = array('hello' => 'world', 'symfony2' => 'rocks'); + foreach ($attributes as $key => $val) { + $this->session->set($key, $val); + } + + $i = 0; + foreach ($this->session as $key => $val) { + $this->assertEquals($attributes[$key], $val); + $i++; + } + + $this->assertEquals(count($attributes), $i); + } + + /** + * @covers Symfony\Component\HttpFoundation\Session\Session::count + */ + public function testGetCount() + { + $this->session->set('hello', 'world'); + $this->session->set('symfony2', 'rocks'); + + $this->assertEquals(2, count($this->session)); + } + + public function testGetMeta() + { + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\MetadataBag', $this->session->getMetadataBag()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php new file mode 100644 index 0000000..49e1568 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler; + +class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MemcacheSessionHandler + */ + protected $storage; + + protected $memcache; + + protected function setUp() + { + if (!class_exists('Memcache')) { + $this->markTestSkipped('Skipped tests Memcache class is not present'); + } + + $this->memcache = $this->getMock('Memcache'); + $this->storage = new MemcacheSessionHandler($this->memcache); + } + + protected function tearDown() + { + $this->memcache = null; + $this->storage = null; + } + + public function testOpenSession() + { + $this->memcache->expects($this->atLeastOnce()) + ->method('addServer') + ->with('127.0.0.1', 11211, false, 1, 1, 15); + + $this->assertTrue($this->storage->open('', '')); + } + + public function testConstructingWithServerPool() + { + $mock = $this->getMock('Memcache'); + + $storage = new MemcacheSessionHandler($mock, array( + 'serverpool' => array( + array('host' => '127.0.0.2'), + array('host' => '127.0.0.3', + 'port' => 11212, + 'timeout' => 10, + 'persistent' => true, + 'weight' => 5, + 'retry_interval' => 39, + ), + array('host' => '127.0.0.4', + 'port' => 11211, + 'weight' => 2 + ), + ), + )); + + $matcher = $mock + ->expects($this->at(0)) + ->method('addServer') + ->with('127.0.0.2', 11211, false, 1, 1, 15); + $matcher = $mock + ->expects($this->at(1)) + ->method('addServer') + ->with('127.0.0.3', 11212, true, 5, 10, 39); + $matcher = $mock + ->expects($this->at(2)) + ->method('addServer') + ->with('127.0.0.4', 11211, false, 2, 1, 15); + $this->assertTrue($storage->open('', '')); + } + + public function testCloseSession() + { + $this->memcache->expects($this->once()) + ->method('close') + ->will($this->returnValue(true)); + + $this->assertTrue($this->storage->close()); + } + + public function testReadSession() + { + $this->memcache->expects($this->once()) + ->method('get'); + + $this->assertEquals('', $this->storage->read('')); + } + + public function testWriteSession() + { + $this->memcache->expects($this->once()) + ->method('set') + ->will($this->returnValue(true)); + + $this->assertTrue($this->storage->write('', '')); + } + + public function testDestroySession() + { + $this->memcache->expects($this->once()) + ->method('delete') + ->will($this->returnValue(true)); + + $this->assertTrue($this->storage->destroy('')); + } + + public function testGcSession() + { + $this->assertTrue($this->storage->gc(123)); + } + +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php new file mode 100644 index 0000000..5731d92 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler; + +class MemcacheddSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MemcachedSessionHandler + */ + protected $storage; + + protected $memcached; + + protected function setUp() + { + if (!class_exists('Memcached')) { + $this->markTestSkipped('Skipped tests Memcache class is not present'); + } + + $this->memcached = $this->getMock('Memcached'); + $this->storage = new MemcachedSessionHandler($this->memcached); + } + + protected function tearDown() + { + $this->memcached = null; + $this->storage = null; + } + + public function testOpenSession() + { + $this->memcached->expects($this->atLeastOnce()) + ->method('addServers') + ->will($this->returnValue(true)); + + $this->assertTrue($this->storage->open('', '')); + } + + public function testCloseSession() + { + $this->assertTrue($this->storage->close()); + } + + public function testReadSession() + { + $this->memcached->expects($this->once()) + ->method('get'); + + $this->assertEquals('', $this->storage->read('')); + } + + public function testWriteSession() + { + $this->memcached->expects($this->once()) + ->method('set') + ->will($this->returnValue(true)); + + $this->assertTrue($this->storage->write('', '')); + } + + public function testDestroySession() + { + $this->memcached->expects($this->once()) + ->method('delete') + ->will($this->returnValue(true)); + + $this->assertTrue($this->storage->destroy('')); + } + + public function testGcSession() + { + $this->assertTrue($this->storage->gc(123)); + } + + +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php new file mode 100644 index 0000000..7bdf3a1 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +/** + * Test class for NativeFileSessionHandler. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class NativeFileSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testConstruct() + { + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir())); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('files', ini_get('session.save_handler')); + } else { + $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } + + public function testConstructDefault() + { + $path = ini_get('session.save_path'); + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler()); + + $this->assertEquals($path, ini_get('session.save_path')); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeMemcacheSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeMemcacheSessionHandlerTest.php new file mode 100644 index 0000000..b915e59 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeMemcacheSessionHandlerTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeMemcacheSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +/** + * Test class for NativeMemcacheSessionHandler. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class NativeMemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + if (!extension_loaded('memcache')) { + $this->markTestSkipped('Skipped tests memcache extension is not present'); + } + + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeMemcacheSessionHandler('tcp://127.0.0.1:11211?persistent=0')); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('memcache', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('memcache', ini_get('session.save_handler')); + } else { + $this->assertEquals('memcache', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals('tcp://127.0.0.1:11211?persistent=0', ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeMemcachedSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeMemcachedSessionHandlerTest.php new file mode 100644 index 0000000..5f65e9a --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeMemcachedSessionHandlerTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeMemcachedSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +/** + * Test class for NativeMemcachedSessionHandler. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class NativeMemcachedSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + if (!extension_loaded('memcached')) { + $this->markTestSkipped('Skipped tests memcached extension is not present'); + } + + // test takes too long if memcached server is not running + ini_set('memcached.sess_locking', '0'); + + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeMemcachedSessionHandler('127.0.0.1:11211')); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('memcached', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('memcached', ini_get('session.save_handler')); + } else { + $this->assertEquals('memcached', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals('127.0.0.1:11211', ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } +} + diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeRedisSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeRedisSessionHandlerTest.php new file mode 100644 index 0000000..8a57776 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeRedisSessionHandlerTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeRedisSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +/** + * Test class for NativeRedisSessionHandlerTest. + * + * @runTestsInSeparateProcesses + */ +class NativeRedisSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + if (!extension_loaded('redis')) { + $this->markTestSkipped('Skipped tests Redis extension is not present'); + } + + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeRedisSessionHandler('tcp://127.0.0.1:6379?persistent=0')); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('redis', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('redis', ini_get('session.save_handler')); + } else { + $this->assertEquals('redis', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals('tcp://127.0.0.1:6379?persistent=0', ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSqliteSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSqliteSessionHandlerTest.php new file mode 100644 index 0000000..983148e --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSqliteSessionHandlerTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSqliteSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +/** + * Test class for NativeSqliteSessionHandler. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class NativeSqliteSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + if (!extension_loaded('sqlite')) { + $this->markTestSkipped('Skipped tests SQLite extension is not present'); + } + + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeSqliteSessionHandler(sys_get_temp_dir().'/sqlite.db')); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('sqlite', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('sqlite', ini_get('session.save_handler')); + } else { + $this->assertEquals('sqlite', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + + $this->assertEquals(sys_get_temp_dir().'/sqlite.db', ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } +} + diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php new file mode 100644 index 0000000..3bd702e --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpFoundation\Session\Session; + +/** + * Test class for NullSessionHandler. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class NullSessionStorageTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + $storage = $this->getStorage(); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + public function testSession() + { + session_id('nullsessionstorage'); + $storage = $this->getStorage(); + $session = new Session($storage); + $this->assertNull($session->get('something')); + $session->set('something', 'unique'); + $this->assertEquals('unique', $session->get('something')); + } + + public function testNothingIsPersisted() + { + session_id('nullsessionstorage'); + $storage = $this->getStorage(); + $session = new Session($storage); + $session->start(); + $this->assertEquals('nullsessionstorage', $session->getId()); + $this->assertNull($session->get('something')); + } + + public function getStorage() + { + return new NativeSessionStorage(array(), new NullSessionHandler()); + } +} + diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php new file mode 100644 index 0000000..d0938e0 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; + +class PdoSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + private $pdo; + + protected function setUp() + { + if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) { + $this->markTestSkipped('This test requires SQLite support in your environment'); + } + + $this->pdo = new \PDO("sqlite::memory:"); + $sql = "CREATE TABLE sessions (sess_id VARCHAR(255) PRIMARY KEY, sess_data TEXT, sess_time INTEGER)"; + $this->pdo->exec($sql); + } + + public function testMultipleInstances() + { + $storage1 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); + $storage1->write('foo', 'bar'); + + $storage2 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); + $this->assertEquals('bar', $storage2->read('foo'), 'values persist between instances'); + } + + public function testSessionDestroy() + { + $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); + $storage->write('foo', 'bar'); + $this->assertEquals(1, count($this->pdo->query('SELECT * FROM sessions')->fetchAll())); + + $storage->destroy('foo'); + + $this->assertEquals(0, count($this->pdo->query('SELECT * FROM sessions')->fetchAll())); + } + + public function testSessionGC() + { + $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); + + $storage->write('foo', 'bar'); + $storage->write('baz', 'bar'); + + $this->assertEquals(2, count($this->pdo->query('SELECT * FROM sessions')->fetchAll())); + + $storage->gc(-1); + $this->assertEquals(0, count($this->pdo->query('SELECT * FROM sessions')->fetchAll())); + } +} + diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php new file mode 100644 index 0000000..39f268b --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; + +/** + * Test class for MetadataBag. + */ +class MetadataBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MetadataBag + */ + protected $bag; + + /** + * @var array + */ + protected $array = array(); + + protected function setUp() + { + $this->bag = new MetadataBag(); + $this->array = array(MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 0); + $this->bag->initialize($this->array); + } + + protected function tearDown() + { + $this->array = array(); + $this->bag = null; + } + + public function testInitialize() + { + $p = new \ReflectionProperty('Symfony\Component\HttpFoundation\Session\Storage\MetadataBag', 'meta'); + $p->setAccessible(true); + + $bag1 = new MetadataBag(); + $array = array(); + $bag1->initialize($array); + $this->assertGreaterThanOrEqual(time(), $bag1->getCreated()); + $this->assertEquals($bag1->getCreated(), $bag1->getLastUsed()); + + sleep(1); + $bag2 = new MetadataBag(); + $array2 = $p->getValue($bag1); + $bag2->initialize($array2); + $this->assertEquals($bag1->getCreated(), $bag2->getCreated()); + $this->assertEquals($bag1->getLastUsed(), $bag2->getLastUsed()); + $this->assertEquals($bag2->getCreated(), $bag2->getLastUsed()); + + sleep(1); + $bag3 = new MetadataBag(); + $array3 = $p->getValue($bag2); + $bag3->initialize($array3); + $this->assertEquals($bag1->getCreated(), $bag3->getCreated()); + $this->assertGreaterThan($bag2->getLastUsed(), $bag3->getLastUsed()); + $this->assertNotEquals($bag3->getCreated(), $bag3->getLastUsed()); + } + + public function testGetSetName() + { + $this->assertEquals('__metadata', $this->bag->getName()); + $this->bag->setName('foo'); + $this->assertEquals('foo', $this->bag->getName()); + + } + + public function testGetStorageKey() + { + $this->assertEquals('_sf2_meta', $this->bag->getStorageKey()); + } + + public function testGetCreated() + { + $this->assertEquals(1234567, $this->bag->getCreated()); + } + + public function testGetLastUsed() + { + $this->assertLessThanOrEqual(time(), $this->bag->getLastUsed()); + } + + public function testClear() + { + $this->bag->clear(); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php new file mode 100644 index 0000000..0da4805 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; + +/** + * Test class for MockArraySessionStorage. + * + * @author Drak + */ +class MockArraySessionStorageTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MockArraySessionStorage + */ + private $storage; + + /** + * @var array + */ + private $attributes; + + /** + * @var array + */ + private $flashes; + + private $data; + + protected function setUp() + { + $this->attributes = new AttributeBag(); + $this->flashes = new FlashBag(); + + $this->data = array( + $this->attributes->getStorageKey() => array('foo' => 'bar'), + $this->flashes->getStorageKey() => array('notice' => 'hello'), + ); + + $this->storage = new MockArraySessionStorage(); + $this->storage->registerBag($this->flashes); + $this->storage->registerBag($this->attributes); + $this->storage->setSessionData($this->data); + } + + protected function tearDown() + { + $this->data = null; + $this->flashes = null; + $this->attributes = null; + $this->storage = null; + } + + public function testStart() + { + $this->assertEquals('', $this->storage->getId()); + $this->storage->start(); + $id = $this->storage->getId(); + $this->assertNotEquals('', $id); + $this->storage->start(); + $this->assertEquals($id, $this->storage->getId()); + } + + public function testRegenerate() + { + $this->storage->start(); + $id = $this->storage->getId(); + $this->storage->regenerate(); + $this->assertNotEquals($id, $this->storage->getId()); + $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all()); + $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll()); + + $id = $this->storage->getId(); + $this->storage->regenerate(true); + $this->assertNotEquals($id, $this->storage->getId()); + $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all()); + $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll()); + } + + public function testGetId() + { + $this->assertEquals('', $this->storage->getId()); + $this->storage->start(); + $this->assertNotEquals('', $this->storage->getId()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php new file mode 100644 index 0000000..9578ec9 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; + +/** + * Test class for MockFileSessionStorage. + * + * @author Drak + */ +class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var string + */ + private $sessionDir; + + /** + * @var FileMockSessionStorage + */ + protected $storage; + + protected function setUp() + { + $this->sessionDir = sys_get_temp_dir().'/sf2test'; + $this->storage = $this->getStorage(); + } + + protected function tearDown() + { + $this->sessionDir = null; + $this->storage = null; + array_map('unlink', glob($this->sessionDir.'/*.session')); + if (is_dir($this->sessionDir)) { + rmdir($this->sessionDir); + } + } + + public function testStart() + { + $this->assertEquals('', $this->storage->getId()); + $this->assertTrue($this->storage->start()); + $id = $this->storage->getId(); + $this->assertNotEquals('', $this->storage->getId()); + $this->assertTrue($this->storage->start()); + $this->assertEquals($id, $this->storage->getId()); + } + + public function testRegenerate() + { + $this->storage->start(); + $this->storage->getBag('attributes')->set('regenerate', 1234); + $this->storage->regenerate(); + $this->assertEquals(1234, $this->storage->getBag('attributes')->get('regenerate')); + $this->storage->regenerate(true); + $this->assertEquals(1234, $this->storage->getBag('attributes')->get('regenerate')); + } + + public function testGetId() + { + $this->assertEquals('', $this->storage->getId()); + $this->storage->start(); + $this->assertNotEquals('', $this->storage->getId()); + } + + public function testSave() + { + $this->storage->start(); + $id = $this->storage->getId(); + $this->assertNotEquals('108', $this->storage->getBag('attributes')->get('new')); + $this->assertFalse($this->storage->getBag('flashes')->has('newkey')); + $this->storage->getBag('attributes')->set('new', '108'); + $this->storage->getBag('flashes')->set('newkey', 'test'); + $this->storage->save(); + + $storage = $this->getStorage(); + $storage->setId($id); + $storage->start(); + $this->assertEquals('108', $storage->getBag('attributes')->get('new')); + $this->assertTrue($storage->getBag('flashes')->has('newkey')); + $this->assertEquals(array('test'), $storage->getBag('flashes')->peek('newkey')); + } + + public function testMultipleInstances() + { + $storage1 = $this->getStorage(); + $storage1->start(); + $storage1->getBag('attributes')->set('foo', 'bar'); + $storage1->save(); + + $storage2 = $this->getStorage(); + $storage2->setId($storage1->getId()); + $storage2->start(); + $this->assertEquals('bar', $storage2->getBag('attributes')->get('foo'), 'values persist between instances'); + } + + private function getStorage() + { + $storage = new MockFileSessionStorage($this->sessionDir); + $storage->registerBag(new FlashBag); + $storage->registerBag(new AttributeBag); + + return $storage; + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php new file mode 100644 index 0000000..4b88a23 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; + +/** + * Test class for NativeSessionStorage. + * + * @author Drak + * + * These tests require separate processes. + * + * @runTestsInSeparateProcesses + */ +class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase +{ + /** + * @return NativeSessionStorage + */ + protected function getStorage(array $options = array()) + { + $storage = new NativeSessionStorage($options); + $storage->registerBag(new AttributeBag); + + return $storage; + } + + public function testBag() + { + $storage = $this->getStorage(); + $bag = new FlashBag(); + $storage->registerBag($bag); + $this->assertSame($bag, $storage->getBag($bag->getName())); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testRegisterBagException() + { + $storage = $this->getStorage(); + $storage->getBag('non_existing'); + } + + public function testGetId() + { + $storage = $this->getStorage(); + $this->assertEquals('', $storage->getId()); + $storage->start(); + $this->assertNotEquals('', $storage->getId()); + } + + public function testRegenerate() + { + $storage = $this->getStorage(); + $storage->start(); + $id = $storage->getId(); + $storage->getBag('attributes')->set('lucky', 7); + $storage->regenerate(); + $this->assertNotEquals($id, $storage->getId()); + $this->assertEquals(7, $storage->getBag('attributes')->get('lucky')); + + } + + public function testRegenerateDestroy() + { + $storage = $this->getStorage(); + $storage->start(); + $id = $storage->getId(); + $storage->getBag('attributes')->set('legs', 11); + $storage->regenerate(true); + $this->assertNotEquals($id, $storage->getId()); + $this->assertEquals(11, $storage->getBag('attributes')->get('legs')); + } + + public function testDefaultSessionCacheLimiter() + { + ini_set('session.cache_limiter', 'nocache'); + + $storage = new NativeSessionStorage(); + $this->assertEquals('', ini_get('session.cache_limiter')); + } + + public function testExplicitSessionCacheLimiter() + { + ini_set('session.cache_limiter', 'nocache'); + + $storage = new NativeSessionStorage(array('cache_limiter' => 'public')); + $this->assertEquals('public', ini_get('session.cache_limiter')); + } + + public function testCookieOptions() + { + $options = array( + 'cookie_lifetime' => 123456, + 'cookie_path' => '/my/cookie/path', + 'cookie_domain' => 'symfony2.example.com', + 'cookie_secure' => true, + 'cookie_httponly' => false, + ); + + $this->getStorage($options); + $temp = session_get_cookie_params(); + $gco = array(); + + foreach ($temp as $key => $value) { + $gco['cookie_'.$key] = $value; + } + + $this->assertEquals($options, $gco); + } + + public function testSetSaveHandler() + { + $storage = $this->getStorage(); + $storage->setSaveHandler(new \StdClass()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); + } + + public function testSetSaveHandlerPHP53() + { + if (version_compare(phpversion(), '5.4.0', '>=')) { + $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); + } + + $storage = $this->getStorage(); + $storage->setSaveHandler(new NativeFileSessionHandler()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); + } + + public function testSetSaveHandlerPHP54() + { + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->markTestSkipped('Test skipped, for PHP 5.4+ only.'); + } + + $storage = $this->getStorage(); + $storage->setSaveHandler(new NullSessionHandler()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php new file mode 100644 index 0000000..dedbde3 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; + +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; + +// Note until PHPUnit_Mock_Objects 1.2 is released you cannot mock abstracts due to +// https://github.com/sebastianbergmann/phpunit-mock-objects/issues/73 +class ConcreteProxy extends AbstractProxy +{ + +} + +class ConcreteSessionHandlerInterfaceProxy extends AbstractProxy implements \SessionHandlerInterface +{ + public function open($savePath, $sessionName) + { + } + + public function close() + { + } + + public function read($id) + { + } + + public function write($id, $data) + { + } + + public function destroy($id) + { + } + + public function gc($maxlifetime) + { + } +} + +/** + * Test class for AbstractProxy. + * + * @author Drak + */ +class AbstractProxyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var AbstractProxy + */ + protected $proxy; + + protected function setUp() + { + $this->proxy = new ConcreteProxy(); + } + + protected function tearDown() + { + $this->proxy = null; + } + + public function testGetSaveHandlerName() + { + $this->assertNull($this->proxy->getSaveHandlerName()); + } + + public function testIsSessionHandlerInterface() + { + $this->assertFalse($this->proxy->isSessionHandlerInterface()); + $sh = new ConcreteSessionHandlerInterfaceProxy(); + $this->assertTrue($sh->isSessionHandlerInterface()); + } + + public function testIsWrapper() + { + $this->assertFalse($this->proxy->isWrapper()); + } + + public function testIsActive() + { + $this->assertFalse($this->proxy->isActive()); + } + + public function testSetActive() + { + $this->proxy->setActive(true); + $this->assertTrue($this->proxy->isActive()); + $this->proxy->setActive(false); + $this->assertFalse($this->proxy->isActive()); + } + + /** + * @runInSeparateProcess + */ + public function testName() + { + $this->assertEquals(session_name(), $this->proxy->getName()); + $this->proxy->setName('foo'); + $this->assertEquals('foo', $this->proxy->getName()); + $this->assertEquals(session_name(), $this->proxy->getName()); + } + + /** + * @expectedException \LogicException + */ + public function testNameException() + { + $this->proxy->setActive(true); + $this->proxy->setName('foo'); + } + + /** + * @runInSeparateProcess + */ + public function testId() + { + $this->assertEquals(session_id(), $this->proxy->getId()); + $this->proxy->setId('foo'); + $this->assertEquals('foo', $this->proxy->getId()); + $this->assertEquals(session_id(), $this->proxy->getId()); + } + + /** + * @expectedException \LogicException + */ + public function testIdException() + { + $this->proxy->setActive(true); + $this->proxy->setId('foo'); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php new file mode 100644 index 0000000..e9184ce --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; + +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; + +/** + * Test class for NativeProxy. + * + * @author Drak + */ +class NativeProxyTest extends \PHPUnit_Framework_TestCase +{ + public function testIsWrapper() + { + $proxy = new NativeProxy(); + $this->assertFalse($proxy->isWrapper()); + } + + public function testGetSaveHandlerName() + { + $name = ini_get('session.save_handler'); + $proxy = new NativeProxy(); + $this->assertEquals($name, $proxy->getSaveHandlerName()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php new file mode 100644 index 0000000..bae5390 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; + +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; + +/** + * Tests for SessionHandlerProxy class. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class SessionHandlerProxyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var PHPUnit_Framework_MockObject_Matcher + */ + private $mock; + + /** + * @var SessionHandlerProxy + */ + private $proxy; + + protected function setUp() + { + $this->mock = $this->getMock('SessionHandlerInterface'); + $this->proxy = new SessionHandlerProxy($this->mock); + } + + protected function tearDown() + { + $this->mock = null; + $this->proxy = null; + } + + public function testOpen() + { + $this->mock->expects($this->once()) + ->method('open') + ->will($this->returnValue(true)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->open('name', 'id'); + $this->assertTrue($this->proxy->isActive()); + } + + public function testOpenFalse() + { + $this->mock->expects($this->once()) + ->method('open') + ->will($this->returnValue(false)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->open('name', 'id'); + $this->assertFalse($this->proxy->isActive()); + } + + public function testClose() + { + $this->mock->expects($this->once()) + ->method('close') + ->will($this->returnValue(true)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->close(); + $this->assertFalse($this->proxy->isActive()); + } + + public function testCloseFalse() + { + $this->mock->expects($this->once()) + ->method('close') + ->will($this->returnValue(false)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->close(); + $this->assertFalse($this->proxy->isActive()); + } + + public function testRead() + { + $this->mock->expects($this->once()) + ->method('read'); + + $this->proxy->read('id'); + } + + public function testWrite() + { + $this->mock->expects($this->once()) + ->method('write'); + + $this->proxy->write('id', 'data'); + } + + public function testDestroy() + { + $this->mock->expects($this->once()) + ->method('destroy'); + + $this->proxy->destroy('id'); + } + + public function testGc() + { + $this->mock->expects($this->once()) + ->method('gc'); + + $this->proxy->gc(86400); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php new file mode 100644 index 0000000..d95c937 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\StreamedResponse; + +class StreamedResponseTest extends \PHPUnit_Framework_TestCase +{ + public function testConstructor() + { + $response = new StreamedResponse(function () { echo 'foo'; }, 404, array('Content-Type' => 'text/plain')); + + $this->assertEquals(404, $response->getStatusCode()); + $this->assertEquals('text/plain', $response->headers->get('Content-Type')); + } + + public function testPrepareWith11Protocol() + { + $response = new StreamedResponse(function () { echo 'foo'; }); + $request = Request::create('/'); + $request->server->set('SERVER_PROTOCOL', '1.1'); + + $response->prepare($request); + + $this->assertEquals('1.1', $response->getProtocolVersion()); + $this->assertNotEquals('chunked', $response->headers->get('Transfer-Encoding'), 'Apache assumes responses with a Transfer-Encoding header set to chunked to already be encoded.'); + $this->assertEquals('no-cache, private', $response->headers->get('Cache-Control')); + } + + public function testPrepareWith10Protocol() + { + $response = new StreamedResponse(function () { echo 'foo'; }); + $request = Request::create('/'); + $request->server->set('SERVER_PROTOCOL', '1.0'); + + $response->prepare($request); + + $this->assertEquals('1.0', $response->getProtocolVersion()); + $this->assertNull($response->headers->get('Transfer-Encoding')); + $this->assertEquals('no-cache, private', $response->headers->get('Cache-Control')); + } + + public function testSendContent() + { + $called = 0; + + $response = new StreamedResponse(function () use (&$called) { ++$called; }); + + $response->sendContent(); + $this->assertEquals(1, $called); + + $response->sendContent(); + $this->assertEquals(1, $called); + } + + /** + * @expectedException \LogicException + */ + public function testSendContentWithNonCallable() + { + $response = new StreamedResponse('foobar'); + $response->sendContent(); + } + + /** + * @expectedException \LogicException + */ + public function testSetContent() + { + $response = new StreamedResponse(function () { echo 'foo'; }); + $response->setContent('foo'); + } + + public function testGetContent() + { + $response = new StreamedResponse(function () { echo 'foo'; }); + $this->assertFalse($response->getContent()); + } + + public function testCreate() + { + $response = StreamedResponse::create(function () {}, 204); + + $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response); + $this->assertEquals(204, $response->getStatusCode()); + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/Tests/bootstrap.php b/core/vendor/Symfony/Component/HttpFoundation/Tests/bootstrap.php new file mode 100644 index 0000000..f7fc8c9 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/Tests/bootstrap.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + if (ltrim('SessionHandlerInterface', '/') === $class) { + require_once __DIR__.'/../Resources/stubs/SessionHandlerInterface.php'; + } + + if (0 !== strpos(ltrim($class, '/'), 'Symfony\Component\HttpFoundation')) { + return; + } + + require_once __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\HttpFoundation')).'.php'; +}); diff --git a/core/vendor/Symfony/Component/HttpFoundation/phpunit.xml.dist b/core/vendor/Symfony/Component/HttpFoundation/phpunit.xml.dist new file mode 100644 index 0000000..95e0f03 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpFoundation/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + + + + diff --git a/core/vendor/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php b/core/vendor/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php index 758fb1e..2406c65 100644 --- a/core/vendor/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php +++ b/core/vendor/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php @@ -22,7 +22,7 @@ abstract class CacheWarmer implements CacheWarmerInterface { $tmpFile = tempnam(dirname($file), basename($file)); if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { - chmod($file, 0644); + chmod($file, 0666 & ~umask()); return; } diff --git a/core/vendor/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php b/core/vendor/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php index 66f7bf8..406f1df 100644 --- a/core/vendor/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php +++ b/core/vendor/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php @@ -13,7 +13,7 @@ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcherInterface; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** diff --git a/core/vendor/Symfony/Component/HttpKernel/Debug/ContainerAwareTraceableEventDispatcher.php b/core/vendor/Symfony/Component/HttpKernel/Debug/ContainerAwareTraceableEventDispatcher.php new file mode 100644 index 0000000..bba6ea7 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Debug/ContainerAwareTraceableEventDispatcher.php @@ -0,0 +1,318 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Debug; + +use Symfony\Component\HttpKernel\Debug\Stopwatch; +use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Symfony\Component\HttpKernel\Profiler\Profile; +use Symfony\Component\HttpKernel\Profiler\Profiler; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; + +/** + * Extends the ContainerAwareEventDispatcher to add some debugging tools. + * + * @author Fabien Potencier + */ +class ContainerAwareTraceableEventDispatcher extends ContainerAwareEventDispatcher implements TraceableEventDispatcherInterface +{ + private $logger; + private $called; + private $stopwatch; + private $priorities; + private $profiler; + + /** + * Constructor. + * + * @param ContainerInterface $container A ContainerInterface instance + * @param Stopwatch $stopwatch A Stopwatch instance + * @param LoggerInterface $logger A LoggerInterface instance + */ + public function __construct(ContainerInterface $container, Stopwatch $stopwatch, LoggerInterface $logger = null) + { + parent::__construct($container); + + $this->stopwatch = $stopwatch; + $this->logger = $logger; + $this->called = array(); + } + + /** + * {@inheritdoc} + */ + public function dispatch($eventName, Event $event = null) + { + switch ($eventName) { + case 'kernel.request': + $this->stopwatch->openSection(); + break; + case 'kernel.view': + case 'kernel.response': + // stop only if a controller has been executed + try { + $this->stopwatch->stop('controller'); + } catch (\LogicException $e) { + } + break; + case 'kernel.terminate': + $token = $event->getResponse()->headers->get('X-Debug-Token'); + $this->stopwatch->openSection($token); + break; + } + + $e1 = $this->stopwatch->start($eventName, 'section'); + + parent::dispatch($eventName, $event); + + $e1->stop(); + + switch ($eventName) { + case 'kernel.controller': + $this->stopwatch->start('controller', 'section'); + break; + case 'kernel.response': + $token = $event->getResponse()->headers->get('X-Debug-Token'); + $this->stopwatch->stopSection($token); + if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) { + // The profiles can only be updated once they have been created + // that is after the 'kernel.response' event of the main request + $this->updateProfiles($token, true); + } + break; + case 'kernel.terminate': + $this->stopwatch->stopSection($token); + // The children profiles have been updated by the previous 'kernel.response' + // event. Only the root profile need to be updated with the 'kernel.terminate' + // timing informations. + $this->updateProfiles($token, false); + break; + } + + return $event; + } + + /** + * {@inheritDoc} + * + * @throws \RuntimeException if the listener method is not callable + */ + public function addListener($eventName, $listener, $priority = 0) + { + if (!is_callable($listener)) { + throw new \RuntimeException(sprintf('The given callback (%s) for event "%s" is not callable.', $this->getListenerAsString($listener), $eventName)); + } + + $this->priorities[$eventName.'_'.$this->getListenerAsString($listener)] = $priority; + + parent::addListener($eventName, $listener, $priority); + } + + /** + * {@inheritDoc} + */ + protected function doDispatch($listeners, $eventName, Event $event) + { + foreach ($listeners as $listener) { + $info = $this->getListenerInfo($listener, $eventName); + + if (null !== $this->logger) { + $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty'])); + } + + $this->called[$eventName.'.'.$info['pretty']] = $info; + + $e2 = $this->stopwatch->start(isset($info['class']) ? substr($info['class'], strrpos($info['class'], '\\') + 1) : $info['type'], 'event_listener'); + + call_user_func($listener, $event); + + $e2->stop(); + + if ($event->isPropagationStopped()) { + if (null !== $this->logger) { + $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName)); + + $skippedListeners = $this->getListeners($eventName); + $skipped = false; + + foreach ($skippedListeners as $skippedListener) { + if ($skipped) { + $info = $this->getListenerInfo($skippedListener, $eventName); + $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName)); + } + + if ($skippedListener === $listener) { + $skipped = true; + } + } + } + + break; + } + } + } + + /** + * {@inheritDoc} + */ + protected function lazyLoad($eventName) + { + $e = $this->stopwatch->start($eventName.'.loading', 'event_listener_loading'); + + parent::lazyLoad($eventName); + + $e->stop(); + } + + /** + * {@inheritDoc} + */ + public function getCalledListeners() + { + return $this->called; + } + + /** + * {@inheritDoc} + */ + public function getNotCalledListeners() + { + $notCalled = array(); + + foreach ($this->getListeners() as $name => $listeners) { + foreach ($listeners as $listener) { + $info = $this->getListenerInfo($listener, $name); + if (!isset($this->called[$name.'.'.$info['pretty']])) { + $notCalled[$name.'.'.$info['pretty']] = $info; + } + } + } + + return $notCalled; + } + + /** + * Returns information about the listener + * + * @param object $listener The listener + * @param string $eventName The event name + * + * @return array Informations about the listener + */ + private function getListenerInfo($listener, $eventName) + { + $info = array( + 'event' => $eventName, + 'priority' => $this->priorities[$eventName.'_'.$this->getListenerAsString($listener)], + ); + if ($listener instanceof \Closure) { + $info += array( + 'type' => 'Closure', + 'pretty' => 'closure' + ); + } elseif (is_string($listener)) { + try { + $r = new \ReflectionFunction($listener); + $file = $r->getFileName(); + $line = $r->getStartLine(); + } catch (\ReflectionException $e) { + $file = null; + $line = null; + } + $info += array( + 'type' => 'Function', + 'function' => $listener, + 'file' => $file, + 'line' => $line, + 'pretty' => $listener, + ); + } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) { + if (!is_array($listener)) { + $listener = array($listener, '__invoke'); + } + $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; + try { + $r = new \ReflectionMethod($class, $listener[1]); + $file = $r->getFileName(); + $line = $r->getStartLine(); + } catch (\ReflectionException $e) { + $file = null; + $line = null; + } + $info += array( + 'type' => 'Method', + 'class' => $class, + 'method' => $listener[1], + 'file' => $file, + 'line' => $line, + 'pretty' => $class.'::'.$listener[1], + ); + } + + return $info; + } + + /** + * Updates the stopwatch data in the profile hierarchy. + * + * @param string $token Profile token + * @param Boolean $updateChildren Whether to update the children altogether + */ + private function updateProfiles($token, $updateChildren) + { + if (!$this->getContainer()->has('profiler')) { + return; + } + + $this->profiler = $this->getContainer()->get('profiler'); + + if (!$profile = $this->profiler->loadProfile($token)) { + return; + } + + $this->saveStopwatchInfoInProfile($profile, $updateChildren); + } + + /** + * Update the profiles with the timing info and saves them. + * + * @param Profile $profile The root profile + * @param Boolean $updateChildren Whether to update the children altogether + */ + private function saveStopwatchInfoInProfile(Profile $profile, $updateChildren) + { + $profile->getCollector('time')->setEvents($this->stopwatch->getSectionEvents($profile->getToken())); + $this->profiler->saveProfile($profile); + + if ($updateChildren) { + foreach ($profile->getChildren() as $child) { + $this->saveStopwatchInfoInProfile($child, true); + } + } + } + + private function getListenerAsString($listener) + { + if (is_string($listener)) { + return '[string] '.$listener; + } elseif (is_array($listener)) { + return '[array] '.(is_object($listener[0]) ? get_class($listener[0]) : $listener[0]).'::'.$listener[1]; + } elseif (is_object($listener)) { + return '[object] '.get_class($listener); + } + + return '[?] '.var_export($listener, true); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Debug/Stopwatch.php b/core/vendor/Symfony/Component/HttpKernel/Debug/Stopwatch.php index 63e14e2..7f2673d 100644 --- a/core/vendor/Symfony/Component/HttpKernel/Debug/Stopwatch.php +++ b/core/vendor/Symfony/Component/HttpKernel/Debug/Stopwatch.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; diff --git a/core/vendor/Symfony/Component/HttpKernel/Debug/StopwatchEvent.php b/core/vendor/Symfony/Component/HttpKernel/Debug/StopwatchEvent.php index 70b6a5e..36e6541 100644 --- a/core/vendor/Symfony/Component/HttpKernel/Debug/StopwatchEvent.php +++ b/core/vendor/Symfony/Component/HttpKernel/Debug/StopwatchEvent.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; diff --git a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php index d18c72b..7e694eb 100644 --- a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php +++ b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; diff --git a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php index 5a0dbdc..4f6f6a3 100755 --- a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php +++ b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; @@ -42,4 +42,4 @@ abstract class ConfigurableExtension extends Extension * @param ContainerBuilder $container */ abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container); -} \ No newline at end of file +} diff --git a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/Extension.php b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/Extension.php index dcdf032..dacd60a 100644 --- a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/Extension.php +++ b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/Extension.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\Config\Definition\Processor; @@ -9,15 +18,6 @@ use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterf use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Container; -/* - * This file is part of the Symfony framework. - * - * (c) Fabien Potencier - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - /** * Provides useful features shared by many extensions. * diff --git a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php index d7d9c18..dcd7382 100644 --- a/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php +++ b/core/vendor/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php @@ -1,12 +1,12 @@ * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; diff --git a/core/vendor/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php b/core/vendor/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php index dbbb441..83ee82a 100644 --- a/core/vendor/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php +++ b/core/vendor/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Profiler\Profile; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -34,6 +35,7 @@ class ProfilerListener implements EventSubscriberInterface protected $exception; protected $children; protected $requests; + protected $profiles; /** * Constructor. @@ -50,6 +52,7 @@ class ProfilerListener implements EventSubscriberInterface $this->onlyException = (Boolean) $onlyException; $this->onlyMasterRequests = (Boolean) $onlyMasterRequests; $this->children = new \SplObjectStorage(); + $this->profiles = array(); } /** @@ -99,6 +102,16 @@ class ProfilerListener implements EventSubscriberInterface return; } + $this->profiles[] = $profile; + + if (null !== $exception) { + foreach ($this->profiles as $profile) { + $this->profiler->saveProfile($profile); + } + + return; + } + // keep the profile as the child of its parent if (!$master) { array_pop($this->requests); @@ -109,17 +122,16 @@ class ProfilerListener implements EventSubscriberInterface $this->children[$parent] = $profiles; } - // store the profile and its children if (isset($this->children[$request])) { foreach ($this->children[$request] as $child) { - $child->setParent($profile); $profile->addChild($child); - $this->profiler->saveProfile($child); } $this->children[$request] = array(); } - $this->profiler->saveProfile($profile); + if ($master) { + $this->saveProfiles($profile); + } } static public function getSubscribedEvents() @@ -128,9 +140,21 @@ class ProfilerListener implements EventSubscriberInterface // kernel.request must be registered as early as possible to not break // when an exception is thrown in any other kernel.request listener KernelEvents::REQUEST => array('onKernelRequest', 1024), - KernelEvents::RESPONSE => array('onKernelResponse', -100), KernelEvents::EXCEPTION => 'onKernelException', ); } + + /** + * Saves the profile hierarchy. + * + * @param Profile $profile The root profile + */ + private function saveProfiles(Profile $profile) + { + $this->profiler->saveProfile($profile); + foreach ($profile->getChildren() as $profile) { + $this->saveProfiles($profile); + } + } } diff --git a/core/vendor/Symfony/Component/HttpKernel/Exception/FlattenException.php b/core/vendor/Symfony/Component/HttpKernel/Exception/FlattenException.php index c48606e..16f1453 100644 --- a/core/vendor/Symfony/Component/HttpKernel/Exception/FlattenException.php +++ b/core/vendor/Symfony/Component/HttpKernel/Exception/FlattenException.php @@ -27,6 +27,8 @@ class FlattenException private $class; private $statusCode; private $headers; + private $file; + private $line; static public function create(\Exception $exception, $statusCode = null, array $headers = array()) { @@ -42,6 +44,8 @@ class FlattenException $e->setHeaders($headers); $e->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine()); $e->setClass(get_class($exception)); + $e->setFile($exception->getFile()); + $e->setLine($exception->getLine()); if ($exception->getPrevious()) { $e->setPrevious(static::create($exception->getPrevious())); } @@ -93,6 +97,26 @@ class FlattenException $this->class = $class; } + public function getFile() + { + return $this->file; + } + + public function setFile($file) + { + $this->file = $file; + } + + public function getLine() + { + return $this->line; + } + + public function setLine($line) + { + $this->line = $line; + } + public function getMessage() { return $this->message; diff --git a/core/vendor/Symfony/Component/HttpKernel/HttpCache/Store.php b/core/vendor/Symfony/Component/HttpKernel/HttpCache/Store.php index 6818bd3..fe19f3a 100644 --- a/core/vendor/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/core/vendor/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -110,7 +110,7 @@ class Store implements StoreInterface // find a cached entry that matches the request. $match = null; foreach ($entries as $entry) { - if ($this->requestsMatch(isset($entry[1]['vary']) ? $entry[1]['vary'][0] : '', $request->headers->all(), $entry[0])) { + if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? $entry[1]['vary'][0] : '', $request->headers->all(), $entry[0])) { $match = $entry; break; @@ -332,7 +332,7 @@ class Store implements StoreInterface return false; } - chmod($path, 0644); + chmod($path, 0666 & ~umask()); } public function getPath($key) diff --git a/core/vendor/Symfony/Component/HttpKernel/HttpKernel.php b/core/vendor/Symfony/Component/HttpKernel/HttpKernel.php index 3327f4f..9a465d1 100644 --- a/core/vendor/Symfony/Component/HttpKernel/HttpKernel.php +++ b/core/vendor/Symfony/Component/HttpKernel/HttpKernel.php @@ -32,8 +32,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; */ class HttpKernel implements HttpKernelInterface, TerminableInterface { - private $dispatcher; - private $resolver; + protected $dispatcher; + protected $resolver; /** * Constructor diff --git a/core/vendor/Symfony/Component/HttpKernel/Kernel.php b/core/vendor/Symfony/Component/HttpKernel/Kernel.php index d1fb733..7fdb546 100644 --- a/core/vendor/Symfony/Component/HttpKernel/Kernel.php +++ b/core/vendor/Symfony/Component/HttpKernel/Kernel.php @@ -27,14 +27,13 @@ use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass; -use Symfony\Component\HttpKernel\DependencyInjection\Extension as DIExtension; use Symfony\Component\HttpKernel\Debug\ErrorHandler; use Symfony\Component\HttpKernel\Debug\ExceptionHandler; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Loader\DelegatingLoader; use Symfony\Component\Config\ConfigCache; use Symfony\Component\ClassLoader\ClassCollectionLoader; -use Symfony\Component\ClassLoader\DebugUniversalClassLoader; +use Symfony\Component\ClassLoader\DebugClassLoader; /** * The Kernel is the heart of the Symfony system. @@ -91,7 +90,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface ini_set('display_errors', 1); error_reporting(-1); - DebugUniversalClassLoader::enable(); + DebugClassLoader::enable(); ErrorHandler::register($this->errorReportingLevel); if ('cli' !== php_sapi_name()) { ExceptionHandler::register(); @@ -640,7 +639,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface } } - $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters())); + $container = $this->getContainerBuilder(); $extensions = array(); foreach ($this->bundles as $bundle) { if ($extension = $bundle->getContainerExtension()) { @@ -672,6 +671,16 @@ abstract class Kernel implements KernelInterface, TerminableInterface } /** + * Gets a new ContainerBuilder instance used to build the service container. + * + * @return ContainerBuilder + */ + protected function getContainerBuilder() + { + return new ContainerBuilder(new ParameterBag($this->getKernelParameters())); + } + + /** * Dumps the service container to PHP code in the cache. * * @param ConfigCache $cache The config cache diff --git a/core/vendor/Symfony/Component/HttpKernel/README.md b/core/vendor/Symfony/Component/HttpKernel/README.md index 64b1944..1460f0e 100644 --- a/core/vendor/Symfony/Component/HttpKernel/README.md +++ b/core/vendor/Symfony/Component/HttpKernel/README.md @@ -82,6 +82,20 @@ with no efforts. Resources --------- -Unit tests: - -https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/HttpKernel +You can run the unit tests with the following command: + + phpunit -c src/Symfony/Component/HttpKernel/ + +If you also want to run the unit tests that depend on other Symfony +Components, declare the following environment variables before running +PHPUnit: + + export SYMFONY_EVENT_DISPATCHER=../path/to/EventDispatcher + export SYMFONY_HTTP_FOUNDATION=../path/to/HttpFoundation + export SYMFONY_DEPENDENCY_INJECTION=../path/to/DependencyInjection + export SYMFONY_CONSOLE=../path/to/Console + export SYMFONY_BROWSER_KIT=../path/to/BrowserKit + export SYMFONY_FINDER=../path/to/Finder + export SYMFONY_PROCESS=../path/to/Process + export SYMFONY_ROUTING=../path/to/Routing + export SYMFONY_CONFIG=../path/to/Config diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php new file mode 100644 index 0000000..2b8cc79 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Bundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\ExtensionPresentBundle; +use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle\ExtensionAbsentBundle; +use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand; + +class BundleTest extends \PHPUnit_Framework_TestCase +{ + public function testRegisterCommands() + { + if (!class_exists('Symfony\Component\Console\Application')) { + $this->markTestSkipped('The "Console" component is not available'); + } + + if (!class_exists('Symfony\Component\Finder\Finder')) { + $this->markTestSkipped('The "Finder" component is not available'); + } + + $cmd = new FooCommand(); + $app = $this->getMock('Symfony\Component\Console\Application'); + $app->expects($this->once())->method('add')->with($this->equalTo($cmd)); + + $bundle = new ExtensionPresentBundle(); + $bundle->registerCommands($app); + + $bundle2 = new ExtensionAbsentBundle(); + + $this->assertNull($bundle2->registerCommands($app)); + + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php new file mode 100644 index 0000000..c4816ba --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\CacheClearer; + +use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; +use Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer; + +class ChainCacheClearerTest extends \PHPUnit_Framework_TestCase +{ + protected static $cacheDir; + + public static function setUpBeforeClass() + { + self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_clearer_dir'); + } + + public static function tearDownAfterClass() + { + @unlink(self::$cacheDir); + } + + public function testInjectClearersInConstructor() + { + $clearer = $this->getMockClearer(); + $clearer + ->expects($this->once()) + ->method('clear'); + + $chainClearer = new ChainCacheClearer(array($clearer)); + $chainClearer->clear(self::$cacheDir); + } + + public function testInjectClearerUsingAdd() + { + $clearer = $this->getMockClearer(); + $clearer + ->expects($this->once()) + ->method('clear'); + + $chainClearer = new ChainCacheClearer(); + $chainClearer->add($clearer); + $chainClearer->clear(self::$cacheDir); + } + + protected function getMockClearer() + { + return $this->getMock('Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface'); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php new file mode 100644 index 0000000..24e7fd9 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\CacheWarmer; + +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer; + +class CacheWarmerAggregateTest extends \PHPUnit_Framework_TestCase +{ + protected static $cacheDir; + + public static function setUpBeforeClass() + { + self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir'); + } + + public static function tearDownAfterClass() + { + @unlink(self::$cacheDir); + } + + public function testInjectWarmersUsingConstructor() + { + $warmer = $this->getCacheWarmerMock(); + $warmer + ->expects($this->once()) + ->method('warmUp'); + $aggregate = new CacheWarmerAggregate(array($warmer)); + $aggregate->warmUp(self::$cacheDir); + } + + public function testInjectWarmersUsingAdd() + { + $warmer = $this->getCacheWarmerMock(); + $warmer + ->expects($this->once()) + ->method('warmUp'); + $aggregate = new CacheWarmerAggregate(); + $aggregate->add($warmer); + $aggregate->warmUp(self::$cacheDir); + } + + public function testInjectWarmersUsingSetWarmers() + { + $warmer = $this->getCacheWarmerMock(); + $warmer + ->expects($this->once()) + ->method('warmUp'); + $aggregate = new CacheWarmerAggregate(); + $aggregate->setWarmers(array($warmer)); + $aggregate->warmUp(self::$cacheDir); + } + + public function testWarmupDoesCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsEnabled() + { + $warmer = $this->getCacheWarmerMock(); + $warmer + ->expects($this->never()) + ->method('isOptional'); + $warmer + ->expects($this->once()) + ->method('warmUp'); + + $aggregate = new CacheWarmerAggregate(array($warmer)); + $aggregate->enableOptionalWarmers(); + $aggregate->warmUp(self::$cacheDir); + } + + public function testWarmupDoesNotCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsNotEnabled() + { + $warmer = $this->getCacheWarmerMock(); + $warmer + ->expects($this->once()) + ->method('isOptional') + ->will($this->returnValue(true)); + $warmer + ->expects($this->never()) + ->method('warmUp'); + + $aggregate = new CacheWarmerAggregate(array($warmer)); + $aggregate->warmUp(self::$cacheDir); + } + + protected function getCacheWarmerMock() + { + $warmer = $this->getMockBuilder('Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface') + ->disableOriginalConstructor() + ->getMock(); + + return $warmer; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.php new file mode 100644 index 0000000..f0ab05d --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\CacheWarmer; + +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer; + +class CacheWarmerTest extends \PHPUnit_Framework_TestCase +{ + protected static $cacheFile; + + public static function setUpBeforeClass() + { + self::$cacheFile = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir'); + } + + public static function tearDownAfterClass() + { + @unlink(self::$cacheFile); + } + + public function testWriteCacheFileCreatesTheFile() + { + $warmer = new TestCacheWarmer(self::$cacheFile); + $warmer->warmUp(dirname(self::$cacheFile)); + + $this->assertTrue(file_exists(self::$cacheFile)); + } + + /** + * @expectedException \RuntimeException + */ + public function testWriteNonWritableCacheFileThrowsARuntimeException() + { + $nonWritableFile = '/this/file/is/very/probably/not/writable'; + $warmer = new TestCacheWarmer($nonWritableFile); + $warmer->warmUp(dirname($nonWritableFile)); + } +} + +class TestCacheWarmer extends CacheWarmer +{ + protected $file; + + public function __construct($file) + { + $this->file = $file; + } + + public function warmUp($cacheDir) + { + $this->writeCacheFile($this->file, 'content'); + } + + public function isOptional() + { + return false; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/ClientTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/ClientTest.php new file mode 100644 index 0000000..c1fc661 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/ClientTest.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpKernel\Client; +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpKernel\Tests\Fixtures\TestClient; + +class ClientTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\BrowserKit\Client')) { + $this->markTestSkipped('The "BrowserKit" component is not available'); + } + } + + public function testDoRequest() + { + $client = new Client(new TestHttpKernel()); + + $client->request('GET', '/'); + $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request'); + + $client->request('GET', 'http://www.example.com/'); + $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request'); + $this->assertEquals('www.example.com', $client->getRequest()->getHost(), '->doRequest() uses the request handler to make the request'); + + $client->request('GET', 'http://www.example.com/?parameter=http://google.com'); + $this->assertEquals('http://www.example.com/?parameter='.urlencode('http://google.com'), $client->getRequest()->getUri(), '->doRequest() uses the request handler to make the request'); + } + + public function testGetScript() + { + if (!class_exists('Symfony\Component\Process\Process')) { + $this->markTestSkipped('The "Process" component is not available'); + } + + if (!class_exists('Symfony\Component\ClassLoader\UniversalClassLoader')) { + $this->markTestSkipped('The "ClassLoader" component is not available'); + } + + $client = new TestClient(new TestHttpKernel()); + $client->insulate(); + $client->request('GET', '/'); + + $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->getScript() returns a script that uses the request handler to make the request'); + } + + public function testFilterResponseConvertsCookies() + { + $client = new Client(new TestHttpKernel()); + + $r = new \ReflectionObject($client); + $m = $r->getMethod('filterResponse'); + $m->setAccessible(true); + + $expected = array( + 'foo=bar; expires=Sun, 15 Feb 2009 20:00:00 GMT; domain=http://example.com; path=/foo; secure; httponly', + 'foo1=bar1; expires=Sun, 15 Feb 2009 20:00:00 GMT; domain=http://example.com; path=/foo; secure; httponly' + ); + + $response = new Response(); + $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $domResponse = $m->invoke($client, $response); + $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); + + $response = new Response(); + $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $response->headers->setCookie(new Cookie('foo1', 'bar1', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $domResponse = $m->invoke($client, $response); + $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); + $this->assertEquals($expected, $domResponse->getHeader('Set-Cookie', false)); + } + + public function testUploadedFile() + { + $source = tempnam(sys_get_temp_dir(), 'source'); + $target = sys_get_temp_dir().'/sf.moved.file'; + @unlink($target); + + $kernel = new TestHttpKernel(); + $client = new Client($kernel); + + $files = array( + array('tmp_name' => $source, 'name' => 'original', 'type' => 'mime/original', 'size' => 123, 'error' => UPLOAD_ERR_OK), + new UploadedFile($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK), + ); + + foreach ($files as $file) { + $client->request('POST', '/', array(), array('foo' => $file)); + + $files = $client->getRequest()->files->all(); + + $this->assertCount(1, $files); + + $file = $files['foo']; + + $this->assertEquals('original', $file->getClientOriginalName()); + $this->assertEquals('mime/original', $file->getClientMimeType()); + $this->assertEquals('123', $file->getClientSize()); + $this->assertTrue($file->isValid()); + } + + $file->move(dirname($target), basename($target)); + + $this->assertFileExists($target); + unlink($target); + } + + public function testUploadedFileWhenSizeExceedsUploadMaxFileSize() + { + $source = tempnam(sys_get_temp_dir(), 'source'); + + $kernel = new TestHttpKernel(); + $client = new Client($kernel); + + $file = $this + ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') + ->setConstructorArgs(array($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK)) + ->setMethods(array('getSize')) + ->getMock() + ; + + $file->expects($this->once()) + ->method('getSize') + ->will($this->returnValue(INF)) + ; + + $client->request('POST', '/', array(), array($file)); + + $files = $client->getRequest()->files->all(); + + $this->assertCount(1, $files); + + $file = $files[0]; + + $this->assertFalse($file->isValid()); + $this->assertEquals(UPLOAD_ERR_INI_SIZE, $file->getError()); + $this->assertEquals('mime/original', $file->getClientMimeType()); + $this->assertEquals('original', $file->getClientOriginalName()); + $this->assertEquals(0, $file->getClientSize()); + + unlink($source); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php new file mode 100644 index 0000000..e1ede85 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -0,0 +1,176 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpFoundation\Request; + +class ControllerResolverTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testGetController() + { + $logger = new Logger(); + $resolver = new ControllerResolver($logger); + + $request = Request::create('/'); + $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute'); + $this->assertEquals(array('Unable to look for the controller as the "_controller" parameter is missing'), $logger->getLogs('warn')); + + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\ControllerResolverTest::testGetController'); + $controller = $resolver->getController($request); + $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\ControllerResolverTest', $controller[0], '->getController() returns a PHP callable'); + + $request->attributes->set('_controller', $lambda = function () {}); + $controller = $resolver->getController($request); + $this->assertSame($lambda, $controller); + + $request->attributes->set('_controller', $this); + $controller = $resolver->getController($request); + $this->assertSame($this, $controller); + + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\ControllerResolverTest'); + $controller = $resolver->getController($request); + $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\ControllerResolverTest', $controller); + + $request->attributes->set('_controller', array($this, 'controllerMethod1')); + $controller = $resolver->getController($request); + $this->assertSame(array($this, 'controllerMethod1'), $controller); + + $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\ControllerResolverTest', 'controllerMethod4')); + $controller = $resolver->getController($request); + $this->assertSame(array('Symfony\Component\HttpKernel\Tests\ControllerResolverTest', 'controllerMethod4'), $controller); + + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\some_controller_function'); + $controller = $resolver->getController($request); + $this->assertSame('Symfony\Component\HttpKernel\Tests\some_controller_function', $controller); + + $request->attributes->set('_controller', 'foo'); + try { + $resolver->getController($request); + $this->fail('->getController() throws an \InvalidArgumentException if the _controller attribute is not well-formatted'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->getController() throws an \InvalidArgumentException if the _controller attribute is not well-formatted'); + } + + $request->attributes->set('_controller', 'foo::bar'); + try { + $resolver->getController($request); + $this->fail('->getController() throws an \InvalidArgumentException if the _controller attribute contains a non-existent class'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->getController() throws an \InvalidArgumentException if the _controller attribute contains a non-existent class'); + } + + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\ControllerResolverTest::bar'); + try { + $resolver->getController($request); + $this->fail('->getController() throws an \InvalidArgumentException if the _controller attribute contains a non-existent method'); + } catch (\Exception $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e, '->getController() throws an \InvalidArgumentException if the _controller attribute contains a non-existent method'); + } + } + + public function testGetArguments() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $controller = array(new self(), 'testGetArguments'); + $this->assertEquals(array(), $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = array(new self(), 'controllerMethod1'); + $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = array(new self(), 'controllerMethod2'); + $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); + + $request->attributes->set('bar', 'bar'); + $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = function ($foo) {}; + $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = function ($foo, $bar = 'bar') {}; + $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = new self(); + $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller)); + $request->attributes->set('bar', 'bar'); + $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('foobar', 'foobar'); + $controller = 'Symfony\Component\HttpKernel\Tests\some_controller_function'; + $this->assertEquals(array('foo', 'foobar'), $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('foobar', 'foobar'); + $controller = array(new self(), 'controllerMethod3'); + + try { + $resolver->getArguments($request, $controller); + $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); + } catch (\Exception $e) { + $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); + } + + $request = Request::create('/'); + $controller = array(new self(), 'controllerMethod5'); + $this->assertEquals(array($request), $resolver->getArguments($request, $controller), '->getArguments() injects the request'); + } + + public function __invoke($foo, $bar = null) + { + } + + protected function controllerMethod1($foo) + { + } + + protected function controllerMethod2($foo, $bar = null) + { + } + + protected function controllerMethod3($foo, $bar = null, $foobar) + { + } + + static protected function controllerMethod4() + { + } + + protected function controllerMethod5(Request $request) + { + } +} + +function some_controller_function($foo, $foobar) +{ +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.php new file mode 100644 index 0000000..407f18f --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DataCollector; + +use Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class ConfigDataCollectorTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testCollect() + { + $kernel = new KernelForTest('test',true); + $c = new ConfigDataCollector($kernel); + $c->collect(new Request(), new Response()); + + $this->assertSame('test',$c->getEnv()); + $this->assertTrue($c->isDebug()); + $this->assertSame('config',$c->getName()); + $this->assertSame('testkernel',$c->getAppName()); + $this->assertSame(PHP_VERSION,$c->getPhpVersion()); + $this->assertSame(Kernel::VERSION,$c->getSymfonyVersion()); + $this->assertNull($c->getToken()); + + // if else clause because we don't know it + if (extension_loaded('xdebug')) { + $this->assertTrue($c->hasXdebug()); + } else { + $this->assertFalse($c->hasXdebug()); + } + + // if else clause because we don't know it + if (((extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) + || + (extension_loaded('apc') && ini_get('apc.enabled')) + || + (extension_loaded('xcache') && ini_get('xcache.cacher')))) { + $this->assertTrue($c->hasAccelerator()); + } else { + $this->assertFalse($c->hasAccelerator()); + } + } +} + +class KernelForTest extends Kernel +{ + public function getName() + { + return 'testkernel'; + } + + public function registerBundles() + { + } + + public function init() + { + } + + public function getBundles() + { + return array(); + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/EventDataCollectorTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/EventDataCollectorTest.php new file mode 100644 index 0000000..67702c7 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/EventDataCollectorTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DataCollector; + +use Symfony\Component\HttpKernel\DataCollector\EventDataCollector; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\Tests\Fixtures\TestEventDispatcher; + +class EventDataCollectorTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testCollect() + { + $c = new EventDataCollector(); + $c->setEventDispatcher(new TestEventDispatcher()); + + $c->collect(new Request(), new Response()); + + $this->assertSame('events',$c->getName()); + $this->assertSame(array('foo'),$c->getCalledListeners()); + $this->assertSame(array('bar'),$c->getNotCalledListeners()); + } + +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php new file mode 100644 index 0000000..54a8aab --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DataCollector; + +use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector; +use Symfony\Component\HttpKernel\Exception\FlattenException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class ExceptionDataCollectorTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testCollect() + { + $e = new \Exception('foo',500); + $c = new ExceptionDataCollector(); + $flattened = FlattenException::create($e); + $trace = $flattened->getTrace(); + + $this->assertFalse($c->hasException()); + + $c->collect(new Request(), new Response(),$e); + + $this->assertTrue($c->hasException()); + $this->assertEquals($flattened,$c->getException()); + $this->assertSame('foo',$c->getMessage()); + $this->assertSame(500,$c->getCode()); + $this->assertSame('exception',$c->getName()); + $this->assertSame($trace,$c->getTrace()); + } + +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php new file mode 100644 index 0000000..a4b853c --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DataCollector; + +use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class LoggerDataCollectorTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + /** + * @dataProvider getCollectTestData + */ + public function testCollect($nb, $logs, $expected) + { + $logger = $this->getMock('Symfony\Component\HttpKernel\Log\DebugLoggerInterface'); + $logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb)); + $logger->expects($this->once())->method('getLogs')->will($this->returnValue($logs)); + + $c = new LoggerDataCollector($logger); + $c->collect(new Request(), new Response()); + + $this->assertSame('logger', $c->getName()); + $this->assertSame($nb, $c->countErrors()); + $this->assertSame($expected ? $expected : $logs, $c->getLogs()); + } + + public function getCollectTestData() + { + return array( + array( + 1, + array(array('message' => 'foo', 'context' => array())), + null, + ), + array( + 1, + array(array('message' => 'foo', 'context' => array('foo' => fopen(__FILE__, 'r')))), + array(array('message' => 'foo', 'context' => array('foo' => 'Resource(stream)'))), + ), + array( + 1, + array(array('message' => 'foo', 'context' => array('foo' => new \stdClass()))), + array(array('message' => 'foo', 'context' => array('foo' => 'Object(stdClass)'))), + ), + ); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.php new file mode 100644 index 0000000..e028210 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DataCollector; + +use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class MemoryDataCollectorTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testCollect() + { + $c = new MemoryDataCollector(); + + $c->collect(new Request(), new Response()); + + $this->assertInternalType('integer',$c->getMemory()); + $this->assertSame('memory',$c->getName()); + } + +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php new file mode 100644 index 0000000..538d077 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DataCollector; + +use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Cookie; + +class RequestDataCollectorTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + /** + * @dataProvider provider + */ + public function testCollect(Request $request, Response $response) + { + $c = new RequestDataCollector(); + + $c->collect($request, $response); + + $this->assertSame('request',$c->getName()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\HeaderBag',$c->getRequestHeaders()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag',$c->getRequestServer()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag',$c->getRequestCookies()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag',$c->getRequestAttributes()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag',$c->getRequestRequest()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag',$c->getRequestQuery()); + $this->assertEquals('html',$c->getFormat()); + $this->assertEquals(array(),$c->getSessionAttributes()); + + $this->assertInstanceOf('Symfony\Component\HttpFoundation\HeaderBag',$c->getResponseHeaders()); + $this->assertEquals(200,$c->getStatusCode()); + $this->assertEquals('application/json',$c->getContentType()); + } + + public function provider() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + return array(array(null, null)); + } + + $request = Request::create('http://test.com/foo?bar=baz'); + $request->attributes->set('foo', 'bar'); + + $response = new Response(); + $response->setStatusCode(200); + $response->headers->set('Content-Type', 'application/json'); + $response->headers->setCookie(new Cookie('foo','bar',1,'/foo','localhost',true,true)); + $response->headers->setCookie(new Cookie('bar','foo',new \DateTime('@946684800'))); + $response->headers->setCookie(new Cookie('bazz','foo','2000-12-12')); + + return array( + array($request, $response) + ); + } + +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ContainerAwareTraceableEventDispatcherTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ContainerAwareTraceableEventDispatcherTest.php new file mode 100644 index 0000000..b126848 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ContainerAwareTraceableEventDispatcherTest.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Debug; + +use Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher; +use Symfony\Component\HttpKernel\Debug\Stopwatch; + +class ContainerAwareTraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\DependencyInjection\Container')) { + $this->markTestSkipped('The "DependencyInjection" component is not available'); + } + + if (!class_exists('Symfony\Component\HttpKernel\HttpKernel')) { + $this->markTestSkipped('The "HttpKernel" component is not available'); + } + } + + /** + * @expectedException \RuntimeException + */ + public function testThrowsAnExceptionWhenAListenerMethodIsNotCallable() + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $dispatcher = new ContainerAwareTraceableEventDispatcher($container, new Stopwatch()); + $dispatcher->addListener('onFooEvent', new \stdClass()); + } + + public function testClosureDoesNotTriggerErrorNotice() + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $dispatcher = new ContainerAwareTraceableEventDispatcher($container, new StopWatch()); + $triggered = false; + + $dispatcher->addListener('onFooEvent', function() use (&$triggered) { + $triggered = true; + }); + + try { + $dispatcher->dispatch('onFooEvent'); + } catch (\PHPUnit_Framework_Error_Notice $e) { + $this->fail($e->getMessage()); + } + + $this->assertTrue($triggered, 'Closure should have been executed upon dispatch'); + } + + public function testStaticCallable() + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $dispatcher = new ContainerAwareTraceableEventDispatcher($container, new StopWatch()); + + $dispatcher->addListener('onFooEvent', array(__NAMESPACE__.'\StaticClassFixture', 'staticListener')); + + $dispatcher->dispatch('onFooEvent'); + + $this->assertTrue(StaticClassFixture::$called); + } +} + +class StaticClassFixture +{ + static public $called = false; + + static public function staticListener($event) + { + self::$called = true; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ErrorHandlerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ErrorHandlerTest.php new file mode 100644 index 0000000..585efd4 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ErrorHandlerTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Debug; + +use Symfony\Component\HttpKernel\Debug\ErrorHandler; +use Symfony\Component\HttpKernel\Debug\ErrorException; + +/** + * ErrorHandlerTest + * + * @author Robert Schönthal + */ +class ErrorHandlerTest extends \PHPUnit_Framework_TestCase +{ + + public function testConstruct() + { + $handler = ErrorHandler::register(3); + + $level = new \ReflectionProperty($handler, 'level'); + $level->setAccessible(true); + + $this->assertEquals(3, $level->getValue($handler)); + + restore_error_handler(); + } + + public function testHandle() + { + $handler = ErrorHandler::register(0); + $this->assertFalse($handler->handle(0, 'foo', 'foo.php', 12, 'foo')); + + restore_error_handler(); + + $handler = ErrorHandler::register(3); + $this->assertFalse($handler->handle(4, 'foo', 'foo.php', 12, 'foo')); + + restore_error_handler(); + + $handler = ErrorHandler::register(3); + try { + $handler->handle(1, 'foo', 'foo.php', 12, 'foo'); + } catch (\ErrorException $e) { + $this->assertSame('1: foo in foo.php line 12', $e->getMessage()); + } + + restore_error_handler(); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ExceptionHandlerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ExceptionHandlerTest.php new file mode 100644 index 0000000..8c61f5a --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/ExceptionHandlerTest.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Debug; + +use Symfony\Component\HttpKernel\Debug\ExceptionHandler; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; + +class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testDebug() + { + $handler = new ExceptionHandler(false); + $response = $handler->createResponse(new \RuntimeException('Foo')); + + $this->assertContains('

Whoops, looks like something went wrong.

', $response->getContent()); + $this->assertNotContains('
', $response->getContent()); + + $handler = new ExceptionHandler(true); + $response = $handler->createResponse(new \RuntimeException('Foo')); + + $this->assertContains('

Whoops, looks like something went wrong.

', $response->getContent()); + $this->assertContains('
', $response->getContent()); + } + + public function testStatusCode() + { + $handler = new ExceptionHandler(false); + + $response = $handler->createResponse(new \RuntimeException('Foo')); + $this->assertEquals('500', $response->getStatusCode()); + $this->assertContains('Whoops, looks like something went wrong.', $response->getContent()); + + $response = $handler->createResponse(new NotFoundHttpException('Foo')); + $this->assertEquals('404', $response->getStatusCode()); + $this->assertContains('Sorry, the page you are looking for could not be found.', $response->getContent()); + } + + public function testNestedExceptions() + { + $handler = new ExceptionHandler(true); + $response = $handler->createResponse(new \RuntimeException('Foo', null, new \RuntimeException('Bar'))); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/StopwatchEventTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/StopwatchEventTest.php new file mode 100644 index 0000000..a739bc8 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/StopwatchEventTest.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Debug; + +use Symfony\Component\HttpKernel\Debug\StopwatchEvent; + +/** + * StopwatchEventTest + * + * @author Fabien Potencier + */ +class StopwatchEventTest extends \PHPUnit_Framework_TestCase +{ + public function testGetOrigin() + { + $event = new StopwatchEvent(12); + $this->assertEquals(12, $event->getOrigin()); + } + + public function testGetCategory() + { + $event = new StopwatchEvent(microtime(true) * 1000); + $this->assertEquals('default', $event->getCategory()); + + $event = new StopwatchEvent(microtime(true) * 1000, 'cat'); + $this->assertEquals('cat', $event->getCategory()); + } + + public function testGetPeriods() + { + $event = new StopwatchEvent(microtime(true) * 1000); + $this->assertEquals(array(), $event->getPeriods()); + + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + $event->stop(); + $this->assertCount(1, $event->getPeriods()); + + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + $event->stop(); + $event->start(); + $event->stop(); + $this->assertCount(2, $event->getPeriods()); + } + + public function testLap() + { + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + $event->lap(); + $event->stop(); + $this->assertCount(2, $event->getPeriods()); + } + + public function testTotalTime() + { + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + usleep(20000); + $event->stop(); + $total = $event->getTotalTime(); + $this->assertTrue($total >= 11 && $total <= 29, $total.' should be 20 (between 11 and 29)'); + + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + usleep(10000); + $event->stop(); + $event->start(); + usleep(10000); + $event->stop(); + $total = $event->getTotalTime(); + $this->assertTrue($total >= 11 && $total <= 29, $total.' should be 20 (between 11 and 29)'); + } + + /** + * @expectedException \LogicException + */ + public function testStopWithoutStart() + { + $event = new StopwatchEvent(microtime(true) * 1000); + $event->stop(); + } + + public function testEnsureStopped() + { + // this also test overlap between two periods + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + usleep(10000); + $event->start(); + usleep(10000); + $event->ensureStopped(); + $total = $event->getTotalTime(); + $this->assertTrue($total >= 21 && $total <= 39, $total.' should be 30 (between 21 and 39)'); + } + + public function testStartTime() + { + $event = new StopwatchEvent(microtime(true) * 1000); + $this->assertTrue($event->getStartTime() < 0.5); + + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + $event->stop(); + $this->assertTrue($event->getStartTime() < 1); + + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + usleep(10000); + $event->stop(); + $start = $event->getStartTime(); + $this->assertTrue($start >= 0 && $start <= 20); + } + + public function testEndTime() + { + $event = new StopwatchEvent(microtime(true) * 1000); + $this->assertEquals(0, $event->getEndTime()); + + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + $this->assertEquals(0, $event->getEndTime()); + + $event = new StopwatchEvent(microtime(true) * 1000); + $event->start(); + usleep(10000); + $event->stop(); + $event->start(); + usleep(10000); + $event->stop(); + $end = $event->getEndTime(); + $this->assertTrue($end >= 11 && $end <= 29, $end.' should be 20 (between 11 and 29)'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidOriginThrowsAnException() + { + new StopwatchEvent("abc"); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/StopwatchTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/StopwatchTest.php new file mode 100644 index 0000000..76ae556 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Debug/StopwatchTest.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Debug; + +use Symfony\Component\HttpKernel\Debug\Stopwatch; + +/** + * StopwatchTest + * + * @author Fabien Potencier + */ +class StopwatchTest extends \PHPUnit_Framework_TestCase +{ + public function testStart() + { + $stopwatch = new Stopwatch(); + $event = $stopwatch->start('foo', 'cat'); + + $this->assertInstanceof('Symfony\Component\HttpKernel\Debug\StopwatchEvent', $event); + $this->assertEquals('cat', $event->getCategory()); + } + + public function testStop() + { + $stopwatch = new Stopwatch(); + $stopwatch->start('foo', 'cat'); + usleep(20000); + $event = $stopwatch->stop('foo'); + + $this->assertInstanceof('Symfony\Component\HttpKernel\Debug\StopwatchEvent', $event); + $total = $event->getTotalTime(); + $this->assertTrue($total > 10 && $total <= 29, $total.' should be 20 (between 10 and 29)'); + } + + public function testLap() + { + $stopwatch = new Stopwatch(); + $stopwatch->start('foo', 'cat'); + usleep(10000); + $event = $stopwatch->lap('foo'); + usleep(10000); + $stopwatch->stop('foo'); + + $this->assertInstanceof('Symfony\Component\HttpKernel\Debug\StopwatchEvent', $event); + $total = $event->getTotalTime(); + $this->assertTrue($total > 10 && $total <= 29, $total.' should be 20 (between 10 and 29)'); + } + + /** + * @expectedException \LogicException + */ + public function testStopWithoutStart() + { + $stopwatch = new Stopwatch(); + $stopwatch->stop('foo'); + } + + public function testSection() + { + $stopwatch = new Stopwatch(); + + $stopwatch->openSection(); + $stopwatch->start('foo', 'cat'); + $stopwatch->stop('foo'); + $stopwatch->start('bar', 'cat'); + $stopwatch->stop('bar'); + $stopwatch->stopSection('1'); + + $stopwatch->openSection(); + $stopwatch->start('foobar', 'cat'); + $stopwatch->stop('foobar'); + $stopwatch->stopSection('2'); + + $stopwatch->openSection(); + $stopwatch->start('foobar', 'cat'); + $stopwatch->stop('foobar'); + $stopwatch->stopSection('0'); + + + // the section is an event by itself + $this->assertCount(3, $stopwatch->getSectionEvents('1')); + $this->assertCount(2, $stopwatch->getSectionEvents('2')); + $this->assertCount(2, $stopwatch->getSectionEvents('0')); + } + + public function testReopenASection() + { + $stopwatch = new Stopwatch(); + + $stopwatch->openSection(); + $stopwatch->start('foo', 'cat'); + $stopwatch->stopSection('section'); + + $stopwatch->openSection('section'); + $stopwatch->start('bar', 'cat'); + $stopwatch->stopSection('section'); + + $events = $stopwatch->getSectionEvents('section'); + + $this->assertCount(3, $events); + $this->assertCount(2, $events['__section__']->getPeriods()); + } + + /** + * @expectedException \LogicException + */ + public function testReopenANewSectionShouldThrowAnException() + { + $stopwatch = new Stopwatch(); + $stopwatch->openSection('section'); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php new file mode 100644 index 0000000..0800758 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; + +class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\DependencyInjection\Container')) { + $this->markTestSkipped('The "DependencyInjection" component is not available'); + } + + if (!class_exists('Symfony\Component\Config\FileLocator')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + public function testAutoloadMainExtension() + { + $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); + $params = $this->getMock('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag'); + + $container->expects($this->at(0)) + ->method('getExtensionConfig') + ->with('loaded') + ->will($this->returnValue(array(array()))); + $container->expects($this->at(1)) + ->method('getExtensionConfig') + ->with('notloaded') + ->will($this->returnValue(array())); + $container->expects($this->once()) + ->method('loadFromExtension') + ->with('notloaded', array()); + + $container->expects($this->any()) + ->method('getParameterBag') + ->will($this->returnValue($params)); + $params->expects($this->any()) + ->method('all') + ->will($this->returnValue(array())); + $container->expects($this->any()) + ->method('getDefinitions') + ->will($this->returnValue(array())); + $container->expects($this->any()) + ->method('getAliases') + ->will($this->returnValue(array())); + $container->expects($this->any()) + ->method('getExtensions') + ->will($this->returnValue(array())); + + $configPass = new MergeExtensionConfigurationPass(array('loaded', 'notloaded')); + $configPass->process($container); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.php new file mode 100644 index 0000000..2eddc57 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use Symfony\Component\HttpKernel\HttpCache\Esi; +use Symfony\Component\HttpKernel\EventListener\EsiListener; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class EsiListenerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + } + + public function testFilterDoesNothingForSubRequests() + { + $dispatcher = new EventDispatcher(); + $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); + $response = new Response('foo '); + $listener = new EsiListener(new Esi()); + + $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); + $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); + $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control')); + } + + public function testFilterWhenThereIsSomeEsiIncludes() + { + $dispatcher = new EventDispatcher(); + $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); + $response = new Response('foo '); + $listener = new EsiListener(new Esi()); + + $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); + $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); + $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals('content="ESI/1.0"', $event->getResponse()->headers->get('Surrogate-Control')); + } + + public function testFilterWhenThereIsNoEsiIncludes() + { + $dispatcher = new EventDispatcher(); + $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); + $response = new Response('foo'); + $listener = new EsiListener(new Esi()); + + $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); + $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); + $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control')); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php new file mode 100644 index 0000000..f999a35 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\EventListener\ExceptionListener; +use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Tests\Logger; + +/** + * ExceptionListenerTest + * + * @author Robert Schönthal + */ +class ExceptionListenerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testConstruct() + { + $logger = new TestLogger(); + $l = new ExceptionListener('foo', $logger); + + $_logger = new \ReflectionProperty(get_class($l), 'logger'); + $_logger->setAccessible(true); + $_controller = new \ReflectionProperty(get_class($l), 'controller'); + $_controller->setAccessible(true); + + $this->assertSame($logger, $_logger->getValue($l)); + $this->assertSame('foo', $_controller->getValue($l)); + } + + /** + * @dataProvider provider + */ + public function testHandleWithoutLogger($event, $event2) + { + // store the current error_log, and disable it temporarily + $errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); + + $l = new ExceptionListener('foo'); + $l->onKernelException($event); + + $this->assertEquals(new Response('foo'), $event->getResponse()); + + try { + $l->onKernelException($event2); + } catch(\Exception $e) { + $this->assertSame('foo', $e->getMessage()); + } + + // restore the old error_log + ini_set('error_log', $errorLog); + } + + /** + * @dataProvider provider + */ + public function testHandleWithLogger($event, $event2) + { + $logger = new TestLogger(); + + $l = new ExceptionListener('foo', $logger); + $l->onKernelException($event); + + $this->assertEquals(new Response('foo'), $event->getResponse()); + + try { + $l->onKernelException($event2); + } catch(\Exception $e) { + $this->assertSame('foo', $e->getMessage()); + } + + $this->assertEquals(3, $logger->countErrors()); + $this->assertCount(3, $logger->getLogs('crit')); + } + + public function provider() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + return array(array(null, null)); + } + + $request = new Request(); + $exception = new \Exception('foo'); + $event = new GetResponseForExceptionEvent(new TestKernel(), $request, 'foo', $exception); + $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, 'foo', $exception); + + return array( + array($event, $event2) + ); + } + +} + +class TestLogger extends Logger implements DebugLoggerInterface +{ + public function countErrors() + { + return count($this->logs['crit']); + } +} + +class TestKernel implements HttpKernelInterface +{ + public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) + { + return new Response('foo'); + } +} + +class TestKernelThatThrowsException implements HttpKernelInterface +{ + public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) + { + throw new \Exception('bar'); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php new file mode 100644 index 0000000..a13b325 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use Symfony\Component\HttpKernel\EventListener\LocaleListener; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; + +class LocaleListenerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + } + + public function testDefaultLocaleWithoutSession() + { + $listener = new LocaleListener('fr'); + $event = $this->getEvent($request = Request::create('/')); + + $listener->onKernelRequest($event); + $this->assertEquals('fr', $request->getLocale()); + } + + public function testDefaultLocaleWithSession() + { + $request = Request::create('/'); + session_name('foo'); + $request->cookies->set('foo', 'value'); + + $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array('get'), array(), '', true); + $session->expects($this->once())->method('get')->will($this->returnValue('es')); + $request->setSession($session); + + $listener = new LocaleListener('fr'); + $event = $this->getEvent($request); + + $listener->onKernelRequest($event); + $this->assertEquals('es', $request->getLocale()); + } + + public function testLocaleFromRequestAttribute() + { + $request = Request::create('/'); + session_name('foo'); + $request->cookies->set('foo', 'value'); + + $request->attributes->set('_locale', 'es'); + $listener = new LocaleListener('fr'); + $event = $this->getEvent($request); + + // also updates the session _locale value + $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array('set', 'get'), array(), '', true); + $session->expects($this->once())->method('set')->with('_locale', 'es'); + $session->expects($this->once())->method('get')->with('_locale')->will($this->returnValue('es')); + $request->setSession($session); + + $listener->onKernelRequest($event); + $this->assertEquals('es', $request->getLocale()); + } + + public function testLocaleSetForRoutingContext() + { + if (!class_exists('Symfony\Component\Routing\Router')) { + $this->markTestSkipped('The "Routing" component is not available'); + } + + // the request context is updated + $context = $this->getMock('Symfony\Component\Routing\RequestContext'); + $context->expects($this->once())->method('setParameter')->with('_locale', 'es'); + + $router = $this->getMock('Symfony\Component\Routing\Router', array('getContext'), array(), '', false); + $router->expects($this->once())->method('getContext')->will($this->returnValue($context)); + + $request = Request::create('/'); + + $request->attributes->set('_locale', 'es'); + $listener = new LocaleListener('fr', $router); + $listener->onKernelRequest($this->getEvent($request)); + } + + private function getEvent(Request $request) + { + return new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php new file mode 100644 index 0000000..3f8e852 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use Symfony\Component\HttpKernel\EventListener\ResponseListener; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class ResponseListenerTest extends \PHPUnit_Framework_TestCase +{ + private $dispatcher; + + private $kernel; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = new EventDispatcher(); + $listener = new ResponseListener('UTF-8'); + $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); + + $this->kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); + + } + + protected function tearDown() + { + $this->dispatcher = null; + $this->kernel = null; + } + + public function testFilterDoesNothingForSubRequests() + { + $response = new Response('foo'); + + $event = new FilterResponseEvent($this->kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); + $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals('', $event->getResponse()->headers->get('content-type')); + } + + public function testFilterSetsNonDefaultCharsetIfNotOverridden() + { + $listener = new ResponseListener('ISO-8859-15'); + $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); + + $response = new Response('foo'); + + $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals('ISO-8859-15', $response->getCharset()); + } + + public function testFilterDoesNothingIfCharsetIsOverridden() + { + $listener = new ResponseListener('ISO-8859-15'); + $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); + + $response = new Response('foo'); + $response->setCharset('ISO-8859-1'); + + $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals('ISO-8859-1', $response->getCharset()); + } + + public function testFiltersSetsNonDefaultCharsetIfNotOverriddenOnNonTextContentType() + { + $listener = new ResponseListener('ISO-8859-15'); + $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); + + $response = new Response('foo'); + $request = Request::create('/'); + $request->setRequestFormat('application/json'); + + $event = new FilterResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals('ISO-8859-15', $response->getCharset()); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php new file mode 100644 index 0000000..c33b33d --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use Symfony\Component\HttpKernel\EventListener\RouterListener; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\Routing\RequestContext; + +class RouterListenerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + if (!class_exists('Symfony\Component\Routing\Router')) { + $this->markTestSkipped('The "Routing" component is not available'); + } + } + + /** + * @dataProvider getPortData + */ + public function testPort($defaultHttpPort, $defaultHttpsPort, $uri, $expectedHttpPort, $expectedHttpsPort) + { + $urlMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface') + ->disableOriginalConstructor() + ->getMock(); + $context = new RequestContext(); + $context->setHttpPort($defaultHttpPort); + $context->setHttpsPort($defaultHttpsPort); + $urlMatcher->expects($this->any()) + ->method('getContext') + ->will($this->returnValue($context)); + + $listener = new RouterListener($urlMatcher); + $event = $this->createGetResponseEventForUri($uri); + $listener->onKernelRequest($event); + + $this->assertEquals($expectedHttpPort, $context->getHttpPort()); + $this->assertEquals($expectedHttpsPort, $context->getHttpsPort()); + $this->assertEquals(0 === strpos($uri, 'https') ? 'https' : 'http', $context->getScheme()); + } + + public function getPortData() + { + return array( + array(80, 443, 'http://localhost/', 80, 443), + array(80, 443, 'http://localhost:90/', 90, 443), + array(80, 443, 'https://localhost/', 80, 443), + array(80, 443, 'https://localhost:90/', 80, 90), + ); + } + + /** + * @param string $uri + * + * @return GetResponseEvent + */ + private function createGetResponseEventForUri($uri) + { + $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); + $request = Request::create($uri); + $request->attributes->set('_controller', null); // Prevents going in to routing process + + return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Exception/FlattenExceptionTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Exception/FlattenExceptionTest.php new file mode 100644 index 0000000..a1ddda7 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Exception/FlattenExceptionTest.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Exception; + +use Symfony\Component\HttpKernel\Exception\FlattenException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; + +class FlattenExceptionTest extends \PHPUnit_Framework_TestCase +{ + public function testStatusCode() + { + $flattened = FlattenException::create(new \RuntimeException(), 403); + $this->assertEquals('403', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new \RuntimeException()); + $this->assertEquals('500', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new NotFoundHttpException()); + $this->assertEquals('404', $flattened->getStatusCode()); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testFlattenHttpException(\Exception $exception, $statusCode) + { + $flattened = FlattenException::create($exception); + $flattened2 = FlattenException::create($exception); + + $flattened->setPrevious($flattened2); + + $this->assertEquals($exception->getMessage(), $flattened->getMessage(), 'The message is copied from the original exception.'); + $this->assertEquals($exception->getCode(), $flattened->getCode(), 'The code is copied from the original exception.'); + $this->assertEquals(get_class($exception), $flattened->getClass(), 'The class is set to the class of the original exception'); + + } + + /** + * @dataProvider flattenDataProvider + */ + public function testPrevious(\Exception $exception, $statusCode) + { + $flattened = FlattenException::create($exception); + $flattened2 = FlattenException::create($exception); + + $flattened->setPrevious($flattened2); + + $this->assertSame($flattened2,$flattened->getPrevious()); + + $this->assertSame(array($flattened2),$flattened->getAllPrevious()); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testLine(\Exception $exception) + { + $flattened = FlattenException::create($exception); + $this->assertSame($exception->getLine(), $flattened->getLine()); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testFile(\Exception $exception) + { + $flattened = FlattenException::create($exception); + $this->assertSame($exception->getFile(), $flattened->getFile()); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testToArray(\Exception $exception, $statusCode) + { + $flattened = FlattenException::create($exception); + $flattened->setTrace(array(),'foo.php',123); + + $this->assertEquals(array( + array( + 'message'=> 'test', + 'class'=>'Exception', + 'trace'=>array(array( + 'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => '', 'file' => 'foo.php','line' => 123, + 'args' => array() + )), + ) + ),$flattened->toArray()); + } + + public function flattenDataProvider() + { + return array( + array(new \Exception('test', 123), 500), + ); + } + + public function testRecursionInArguments() + { + $a = array('foo', array(2, &$a)); + $exception = $this->createException($a); + + $flattened = FlattenException::create($exception); + $trace = $flattened->getTrace(); + $this->assertContains('*DEEP NESTED ARRAY*', serialize($trace)); + } + + private function createException($foo) + { + return new \Exception(); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php new file mode 100644 index 0000000..c8bfd36 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ExtensionAbsentBundle extends Bundle +{ +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php new file mode 100644 index 0000000..3b31781 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +class ExtensionLoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php new file mode 100644 index 0000000..3af81cb --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ExtensionLoadedBundle extends Bundle +{ +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php new file mode 100644 index 0000000..bfe189b --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command; + +use Symfony\Component\Console\Command\Command; + +class FooCommand extends Command +{ + protected function configure() + { + $this->setName('foo'); + } + +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php new file mode 100644 index 0000000..e42f816 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +class ExtensionPresentExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php new file mode 100644 index 0000000..36a7ad4 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ExtensionPresentBundle extends Bundle +{ +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.php new file mode 100644 index 0000000..f940f83 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class FooBarBundle extends Bundle +{ + // We need a full namespaced bundle instance to test isClassInActiveBundle +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php new file mode 100644 index 0000000..e24daef --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures; + +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Config\Loader\LoaderInterface; + +class KernelForTest extends Kernel +{ + public function getBundleMap() + { + return $this->bundleMap; + } + + public function registerBundles() + { + } + + public function init() + { + } + + public function registerBundleDirs() + { + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + } + + public function initializeBundles() + { + parent::initializeBundles(); + } + + public function isBooted() + { + return $this->booted; + } + + public function setIsBooted($value) + { + $this->booted = (Boolean) $value; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txt b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.php new file mode 100644 index 0000000..ddab206 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures; + +use Symfony\Component\HttpKernel\Client; + +class TestClient extends Client +{ + protected function getScript($request) + { + $script = parent::getScript($request); + + $script = preg_replace('/(\->register\(\);)/', "$0\nrequire_once '".__DIR__."/../TestHttpKernel.php';", $script); + + return $script; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php new file mode 100644 index 0000000..f277378 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures; + +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface +{ + function getCalledListeners() + { + return array('foo'); + } + + function getNotCalledListeners() + { + return array('bar'); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php new file mode 100644 index 0000000..7180da1 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php @@ -0,0 +1,227 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\HttpCache; + +use Symfony\Component\HttpKernel\HttpCache\Esi; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class EsiTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testHasSurrogateEsiCapability() + { + $esi = new Esi(); + + $request = Request::create('/'); + $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); + $this->assertTrue($esi->hasSurrogateEsiCapability($request)); + + $request = Request::create('/'); + $request->headers->set('Surrogate-Capability', 'foobar'); + $this->assertFalse($esi->hasSurrogateEsiCapability($request)); + + $request = Request::create('/'); + $this->assertFalse($esi->hasSurrogateEsiCapability($request)); + } + + public function testAddSurrogateEsiCapability() + { + $esi = new Esi(); + + $request = Request::create('/'); + $esi->addSurrogateEsiCapability($request); + $this->assertEquals('symfony2="ESI/1.0"', $request->headers->get('Surrogate-Capability')); + + $esi->addSurrogateEsiCapability($request); + $this->assertEquals('symfony2="ESI/1.0", symfony2="ESI/1.0"', $request->headers->get('Surrogate-Capability')); + } + + public function testAddSurrogateControl() + { + $esi = new Esi(); + + $response = new Response('foo '); + $esi->addSurrogateControl($response); + $this->assertEquals('content="ESI/1.0"', $response->headers->get('Surrogate-Control')); + + $response = new Response('foo'); + $esi->addSurrogateControl($response); + $this->assertEquals('', $response->headers->get('Surrogate-Control')); + } + + public function testNeedsEsiParsing() + { + $esi = new Esi(); + + $response = new Response(); + $response->headers->set('Surrogate-Control', 'content="ESI/1.0"'); + $this->assertTrue($esi->needsEsiParsing($response)); + + $response = new Response(); + $this->assertFalse($esi->needsEsiParsing($response)); + } + + public function testRenderIncludeTag() + { + $esi = new Esi(); + + $this->assertEquals('', $esi->renderIncludeTag('/', '/alt', true)); + $this->assertEquals('', $esi->renderIncludeTag('/', '/alt', false)); + $this->assertEquals('', $esi->renderIncludeTag('/')); + $this->assertEquals(''."\n".'', $esi->renderIncludeTag('/', '/alt', true, 'some comment')); + } + + public function testProcessDoesNothingIfContentTypeIsNotHtml() + { + $esi = new Esi(); + + $request = Request::create('/'); + $response = new Response(); + $response->headers->set('Content-Type', 'text/plain'); + $esi->process($request, $response); + + $this->assertFalse($response->headers->has('x-body-eval')); + } + + public function testProcess() + { + $esi = new Esi(); + + $request = Request::create('/'); + $response = new Response('foo '); + $esi->process($request, $response); + + $this->assertEquals('foo esi->handle($this, \'...\', \'alt\', true) ?>'."\n", $response->getContent()); + $this->assertEquals('ESI', $response->headers->get('x-body-eval')); + + $response = new Response('foo '); + $esi->process($request, $response); + + $this->assertEquals('foo esi->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent()); + + $response = new Response('foo '); + $esi->process($request, $response); + + $this->assertEquals('foo esi->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent()); + } + + public function testProcessEscapesPhpTags() + { + $esi = new Esi(); + + $request = Request::create('/'); + $response = new Response('foo <%= "lala" %>'); + $esi->process($request, $response); + + $this->assertEquals('foo php die("foo"); ?>= "lala" %>', $response->getContent()); + } + + /** + * @expectedException RuntimeException + */ + public function testProcessWhenNoSrcInAnEsi() + { + $esi = new Esi(); + + $request = Request::create('/'); + $response = new Response('foo '); + $esi->process($request, $response); + } + + public function testProcessRemoveSurrogateControlHeader() + { + $esi = new Esi(); + + $request = Request::create('/'); + $response = new Response('foo '); + $response->headers->set('Surrogate-Control', 'content="ESI/1.0"'); + $esi->process($request, $response); + $this->assertEquals('ESI', $response->headers->get('x-body-eval')); + + $response->headers->set('Surrogate-Control', 'no-store, content="ESI/1.0"'); + $esi->process($request, $response); + $this->assertEquals('ESI', $response->headers->get('x-body-eval')); + $this->assertEquals('no-store', $response->headers->get('surrogate-control')); + + $response->headers->set('Surrogate-Control', 'content="ESI/1.0", no-store'); + $esi->process($request, $response); + $this->assertEquals('ESI', $response->headers->get('x-body-eval')); + $this->assertEquals('no-store', $response->headers->get('surrogate-control')); + } + + public function testHandle() + { + $esi = new Esi(); + $cache = $this->getCache(Request::create('/'), new Response('foo')); + $this->assertEquals('foo', $esi->handle($cache, '/', '/alt', true)); + } + + /** + * @expectedException RuntimeException + */ + public function testHandleWhenResponseIsNot200() + { + $esi = new Esi(); + $response = new Response('foo'); + $response->setStatusCode(404); + $cache = $this->getCache(Request::create('/'), $response); + $esi->handle($cache, '/', '/alt', false); + } + + public function testHandleWhenResponseIsNot200AndErrorsAreIgnored() + { + $esi = new Esi(); + $response = new Response('foo'); + $response->setStatusCode(404); + $cache = $this->getCache(Request::create('/'), $response); + $this->assertEquals('', $esi->handle($cache, '/', '/alt', true)); + } + + public function testHandleWhenResponseIsNot200AndAltIsPresent() + { + $esi = new Esi(); + $response1 = new Response('foo'); + $response1->setStatusCode(404); + $response2 = new Response('bar'); + $cache = $this->getCache(Request::create('/'), array($response1, $response2)); + $this->assertEquals('bar', $esi->handle($cache, '/', '/alt', false)); + } + + protected function getCache($request, $response) + { + $cache = $this->getMock('Symfony\Component\HttpKernel\HttpCache\HttpCache', array('getRequest', 'handle'), array(), '', false); + $cache->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($request)) + ; + if (is_array($response)) { + $cache->expects($this->any()) + ->method('handle') + ->will(call_user_func_array(array($this, 'onConsecutiveCalls'), $response)) + ; + } else { + $cache->expects($this->any()) + ->method('handle') + ->will($this->returnValue($response)) + ; + } + + return $cache; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php new file mode 100644 index 0000000..2ac581d --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -0,0 +1,1052 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\HttpCache; + +use Symfony\Component\HttpKernel\HttpCache\HttpCache; +use Symfony\Component\HttpKernel\HttpCache\StoreInterface; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class HttpCacheTest extends HttpCacheTestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testTerminateDelegatesTerminationOnlyForTerminableInterface() + { + if (!class_exists('Symfony\Component\DependencyInjection\Container')) { + $this->markTestSkipped('The "DependencyInjection" component is not available'); + } + + $storeMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface') + ->disableOriginalConstructor() + ->getMock(); + + // does not implement TerminableInterface + $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpKernelInterface') + ->disableOriginalConstructor() + ->getMock(); + + $kernelMock->expects($this->never()) + ->method('terminate'); + + $kernel = new HttpCache($kernelMock, $storeMock); + $kernel->terminate(Request::create('/'), new Response()); + + // implements TerminableInterface + $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Kernel') + ->disableOriginalConstructor() + ->setMethods(array('terminate', 'registerBundles', 'registerContainerConfiguration')) + ->getMock(); + + $kernelMock->expects($this->once()) + ->method('terminate'); + + $kernel = new HttpCache($kernelMock, $storeMock); + $kernel->terminate(Request::create('/'), new Response()); + } + + public function testPassesOnNonGetHeadRequests() + { + $this->setNextResponse(200); + $this->request('POST', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertResponseOk(); + $this->assertTraceContains('pass'); + $this->assertFalse($this->response->headers->has('Age')); + } + + public function testInvalidatesOnPostPutDeleteRequests() + { + foreach (array('post', 'put', 'delete') as $method) { + $this->setNextResponse(200); + $this->request($method, '/'); + + $this->assertHttpKernelIsCalled(); + $this->assertResponseOk(); + $this->assertTraceContains('invalidate'); + $this->assertTraceContains('pass'); + } + } + + public function testDoesNotCacheWithAuthorizationRequestHeaderAndNonPublicResponse() + { + $this->setNextResponse(200, array('ETag' => '"Foo"')); + $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz')); + + $this->assertHttpKernelIsCalled(); + $this->assertResponseOk(); + $this->assertEquals('private', $this->response->headers->get('Cache-Control')); + + $this->assertTraceContains('miss'); + $this->assertTraceNotContains('store'); + $this->assertFalse($this->response->headers->has('Age')); + } + + public function testDoesCacheWithAuthorizationRequestHeaderAndPublicResponse() + { + $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"Foo"')); + $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz')); + + $this->assertHttpKernelIsCalled(); + $this->assertResponseOk(); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertTrue($this->response->headers->has('Age')); + $this->assertEquals('public', $this->response->headers->get('Cache-Control')); + } + + public function testDoesNotCacheWithCookieHeaderAndNonPublicResponse() + { + $this->setNextResponse(200, array('ETag' => '"Foo"')); + $this->request('GET', '/', array(), array('foo' => 'bar')); + + $this->assertHttpKernelIsCalled(); + $this->assertResponseOk(); + $this->assertEquals('private', $this->response->headers->get('Cache-Control')); + $this->assertTraceContains('miss'); + $this->assertTraceNotContains('store'); + $this->assertFalse($this->response->headers->has('Age')); + } + + public function testDoesNotCacheRequestsWithACookieHeader() + { + $this->setNextResponse(200); + $this->request('GET', '/', array(), array('foo' => 'bar')); + + $this->assertHttpKernelIsCalled(); + $this->assertResponseOk(); + $this->assertEquals('private', $this->response->headers->get('Cache-Control')); + $this->assertTraceContains('miss'); + $this->assertTraceNotContains('store'); + $this->assertFalse($this->response->headers->has('Age')); + } + + public function testRespondsWith304WhenIfModifiedSinceMatchesLastModified() + { + $time = new \DateTime(); + + $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822), 'Content-Type' => 'text/plain'), 'Hello World'); + $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + + $this->assertHttpKernelIsCalled(); + $this->assertEquals(304, $this->response->getStatusCode()); + $this->assertEquals('text/html; charset=UTF-8', $this->response->headers->get('Content-Type')); + $this->assertEmpty($this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + } + + public function testRespondsWith304WhenIfNoneMatchMatchesETag() + { + $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '12345', 'Content-Type' => 'text/plain'), 'Hello World'); + $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345')); + + $this->assertHttpKernelIsCalled(); + $this->assertEquals(304, $this->response->getStatusCode()); + $this->assertEquals('text/html; charset=UTF-8', $this->response->headers->get('Content-Type')); + $this->assertTrue($this->response->headers->has('ETag')); + $this->assertEmpty($this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + } + + public function testRespondsWith304OnlyIfIfNoneMatchAndIfModifiedSinceBothMatch() + { + $time = new \DateTime(); + + $this->setNextResponse(200, array(), '', function ($request, $response) use ($time) + { + $response->setStatusCode(200); + $response->headers->set('ETag', '12345'); + $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); + $response->headers->set('Content-Type', 'text/plain'); + $response->setContent('Hello World'); + }); + + // only ETag matches + $t = \DateTime::createFromFormat('U', time() - 3600); + $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $t->format(DATE_RFC2822))); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + + // only Last-Modified matches + $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '1234', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + + // Both matches + $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(304, $this->response->getStatusCode()); + } + + public function testValidatesPrivateResponsesCachedOnTheClient() + { + $this->setNextResponse(200, array(), '', function ($request, $response) + { + $etags = preg_split('/\s*,\s*/', $request->headers->get('IF_NONE_MATCH')); + if ($request->cookies->has('authenticated')) { + $response->headers->set('Cache-Control', 'private, no-store'); + $response->setETag('"private tag"'); + if (in_array('"private tag"', $etags)) { + $response->setStatusCode(304); + } else { + $response->setStatusCode(200); + $response->headers->set('Content-Type', 'text/plain'); + $response->setContent('private data'); + } + } else { + $response->headers->set('Cache-Control', 'public'); + $response->setETag('"public tag"'); + if (in_array('"public tag"', $etags)) { + $response->setStatusCode(304); + } else { + $response->setStatusCode(200); + $response->headers->set('Content-Type', 'text/plain'); + $response->setContent('public data'); + } + } + }); + + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('"public tag"', $this->response->headers->get('ETag')); + $this->assertEquals('public data', $this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + + $this->request('GET', '/', array(), array('authenticated' => '')); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('"private tag"', $this->response->headers->get('ETag')); + $this->assertEquals('private data', $this->response->getContent()); + $this->assertTraceContains('stale'); + $this->assertTraceContains('invalid'); + $this->assertTraceNotContains('store'); + } + + public function testStoresResponsesWhenNoCacheRequestDirectivePresent() + { + $time = \DateTime::createFromFormat('U', time() + 5); + + $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); + $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + + $this->assertHttpKernelIsCalled(); + $this->assertTraceContains('store'); + $this->assertTrue($this->response->headers->has('Age')); + } + + public function testReloadsResponsesWhenCacheHitsButNoCacheRequestDirectivePresentWhenAllowReloadIsSetTrue() + { + $count = 0; + + $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) + { + ++$count; + $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); + }); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('store'); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('fresh'); + + $this->cacheConfig['allow_reload'] = true; + $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Goodbye World', $this->response->getContent()); + $this->assertTraceContains('reload'); + $this->assertTraceContains('store'); + } + + public function testDoesNotReloadResponsesWhenAllowReloadIsSetFalseDefault() + { + $count = 0; + + $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) + { + ++$count; + $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); + }); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('store'); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('fresh'); + + $this->cacheConfig['allow_reload'] = false; + $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceNotContains('reload'); + + $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceNotContains('reload'); + } + + public function testRevalidatesFreshCacheEntryWhenMaxAgeRequestDirectiveIsExceededWhenAllowRevalidateOptionIsSetTrue() + { + $count = 0; + + $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) + { + ++$count; + $response->headers->set('Cache-Control', 'public, max-age=10000'); + $response->setETag($count); + $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); + }); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('store'); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('fresh'); + + $this->cacheConfig['allow_revalidate'] = true; + $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Goodbye World', $this->response->getContent()); + $this->assertTraceContains('stale'); + $this->assertTraceContains('invalid'); + $this->assertTraceContains('store'); + } + + public function testDoesNotRevalidateFreshCacheEntryWhenEnableRevalidateOptionIsSetFalseDefault() + { + $count = 0; + + $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) + { + ++$count; + $response->headers->set('Cache-Control', 'public, max-age=10000'); + $response->setETag($count); + $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); + }); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('store'); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('fresh'); + + $this->cacheConfig['allow_revalidate'] = false; + $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceNotContains('stale'); + $this->assertTraceNotContains('invalid'); + $this->assertTraceContains('fresh'); + + $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceNotContains('stale'); + $this->assertTraceNotContains('invalid'); + $this->assertTraceContains('fresh'); + } + + public function testFetchesResponseFromBackendWhenCacheMisses() + { + $time = \DateTime::createFromFormat('U', time() + 5); + $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTraceContains('miss'); + $this->assertTrue($this->response->headers->has('Age')); + } + + public function testDoesNotCacheSomeStatusCodeResponses() + { + foreach (array_merge(range(201, 202), range(204, 206), range(303, 305), range(400, 403), range(405, 409), range(411, 417), range(500, 505)) as $code) { + $time = \DateTime::createFromFormat('U', time() + 5); + $this->setNextResponse($code, array('Expires' => $time->format(DATE_RFC2822))); + + $this->request('GET', '/'); + $this->assertEquals($code, $this->response->getStatusCode()); + $this->assertTraceNotContains('store'); + $this->assertFalse($this->response->headers->has('Age')); + } + } + + public function testDoesNotCacheResponsesWithExplicitNoStoreDirective() + { + $time = \DateTime::createFromFormat('U', time() + 5); + $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'no-store')); + + $this->request('GET', '/'); + $this->assertTraceNotContains('store'); + $this->assertFalse($this->response->headers->has('Age')); + } + + public function testDoesNotCacheResponsesWithoutFreshnessInformationOrAValidator() + { + $this->setNextResponse(); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTraceNotContains('store'); + } + + public function testCachesResponsesWithExplicitNoCacheDirective() + { + $time = \DateTime::createFromFormat('U', time() + 5); + $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, no-cache')); + + $this->request('GET', '/'); + $this->assertTraceContains('store'); + $this->assertTrue($this->response->headers->has('Age')); + } + + public function testCachesResponsesWithAnExpirationHeader() + { + $time = \DateTime::createFromFormat('U', time() + 5); + $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertNotNull($this->response->headers->get('Date')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + + $values = $this->getMetaStorageValues(); + $this->assertCount(1, $values); + } + + public function testCachesResponsesWithAMaxAgeDirective() + { + $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=5')); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertNotNull($this->response->headers->get('Date')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + + $values = $this->getMetaStorageValues(); + $this->assertCount(1, $values); + } + + public function testCachesResponsesWithASMaxAgeDirective() + { + $this->setNextResponse(200, array('Cache-Control' => 's-maxage=5')); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertNotNull($this->response->headers->get('Date')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + + $values = $this->getMetaStorageValues(); + $this->assertCount(1, $values); + } + + public function testCachesResponsesWithALastModifiedValidatorButNoFreshnessInformation() + { + $time = \DateTime::createFromFormat('U', time()); + $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822))); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + } + + public function testCachesResponsesWithAnETagValidatorButNoFreshnessInformation() + { + $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"123456"')); + + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + } + + public function testHitsCachedResponsesWithExpiresHeader() + { + $time1 = \DateTime::createFromFormat('U', time() - 5); + $time2 = \DateTime::createFromFormat('U', time() + 5); + $this->setNextResponse(200, array('Cache-Control' => 'public', 'Date' => $time1->format(DATE_RFC2822), 'Expires' => $time2->format(DATE_RFC2822))); + + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('Date')); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + + $this->request('GET', '/'); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2); + $this->assertTrue($this->response->headers->get('Age') > 0); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTraceContains('fresh'); + $this->assertTraceNotContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + } + + public function testHitsCachedResponseWithMaxAgeDirective() + { + $time = \DateTime::createFromFormat('U', time() - 5); + $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, max-age=10')); + + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('Date')); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + + $this->request('GET', '/'); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2); + $this->assertTrue($this->response->headers->get('Age') > 0); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTraceContains('fresh'); + $this->assertTraceNotContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + } + + public function testHitsCachedResponseWithSMaxAgeDirective() + { + $time = \DateTime::createFromFormat('U', time() - 5); + $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 's-maxage=10, max-age=0')); + + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('Date')); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + + $this->request('GET', '/'); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2); + $this->assertTrue($this->response->headers->get('Age') > 0); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTraceContains('fresh'); + $this->assertTraceNotContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + } + + public function testAssignsDefaultTtlWhenResponseHasNoFreshnessInformation() + { + $this->setNextResponse(); + + $this->cacheConfig['default_ttl'] = 10; + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertRegExp('/s-maxage=10/', $this->response->headers->get('Cache-Control')); + + $this->cacheConfig['default_ttl'] = 10; + $this->request('GET', '/'); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTraceContains('fresh'); + $this->assertTraceNotContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + } + + public function testDoesNotAssignDefaultTtlWhenResponseHasMustRevalidateDirective() + { + $this->setNextResponse(200, array('Cache-Control' => 'must-revalidate')); + + $this->cacheConfig['default_ttl'] = 10; + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTraceContains('miss'); + $this->assertTraceNotContains('store'); + $this->assertNotRegExp('/s-maxage/', $this->response->headers->get('Cache-Control')); + $this->assertEquals('Hello World', $this->response->getContent()); + } + + public function testFetchesFullResponseWhenCacheStaleAndNoValidatorsPresent() + { + $time = \DateTime::createFromFormat('U', time() + 5); + $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); + + // build initial request + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('Date')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertNotNull($this->response->headers->get('Age')); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + + # go in and play around with the cached metadata directly ... + $values = $this->getMetaStorageValues(); + $this->assertCount(1, $values); + $tmp = unserialize($values[0]); + $time = \DateTime::createFromFormat('U', time()); + $tmp[0][1]['expires'] = $time->format(DATE_RFC2822); + $r = new \ReflectionObject($this->store); + $m = $r->getMethod('save'); + $m->setAccessible(true); + $m->invoke($this->store, 'md'.sha1('http://localhost/'), serialize($tmp)); + + // build subsequent request; should be found but miss due to freshness + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTrue($this->response->headers->get('Age') <= 1); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTraceContains('stale'); + $this->assertTraceNotContains('fresh'); + $this->assertTraceNotContains('miss'); + $this->assertTraceContains('store'); + $this->assertEquals('Hello World', $this->response->getContent()); + } + + public function testValidatesCachedResponsesWithLastModifiedAndNoFreshnessInformation() + { + $time = \DateTime::createFromFormat('U', time()); + $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time) + { + $response->headers->set('Cache-Control', 'public'); + $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); + if ($time->format(DATE_RFC2822) == $request->headers->get('IF_MODIFIED_SINCE')) { + $response->setStatusCode(304); + $response->setContent(''); + } + }); + + // build initial request + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('Last-Modified')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertTraceNotContains('stale'); + + // build subsequent request; should be found but miss due to freshness + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('Last-Modified')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTrue($this->response->headers->get('Age') <= 1); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('stale'); + $this->assertTraceContains('valid'); + $this->assertTraceContains('store'); + $this->assertTraceNotContains('miss'); + } + + public function testValidatesCachedResponsesWithETagAndNoFreshnessInformation() + { + $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) + { + $response->headers->set('Cache-Control', 'public'); + $response->headers->set('ETag', '"12345"'); + if ($response->getETag() == $request->headers->get('IF_NONE_MATCH')) { + $response->setStatusCode(304); + $response->setContent(''); + } + }); + + // build initial request + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('ETag')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + + // build subsequent request; should be found but miss due to freshness + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertNotNull($this->response->headers->get('ETag')); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $this->assertTrue($this->response->headers->get('Age') <= 1); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('stale'); + $this->assertTraceContains('valid'); + $this->assertTraceContains('store'); + $this->assertTraceNotContains('miss'); + } + + public function testReplacesCachedResponsesWhenValidationResultsInNon304Response() + { + $time = \DateTime::createFromFormat('U', time()); + $count = 0; + $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time, &$count) + { + $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); + $response->headers->set('Cache-Control', 'public'); + switch (++$count) { + case 1: + $response->setContent('first response'); + break; + case 2: + $response->setContent('second response'); + break; + case 3: + $response->setContent(''); + $response->setStatusCode(304); + break; + } + }); + + // first request should fetch from backend and store in cache + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('first response', $this->response->getContent()); + + // second request is validated, is invalid, and replaces cached entry + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('second response', $this->response->getContent()); + + // third response is validated, valid, and returns cached entry + $this->request('GET', '/'); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('second response', $this->response->getContent()); + + $this->assertEquals(3, $count); + } + + public function testPassesHeadRequestsThroughDirectlyOnPass() + { + $that = $this; + $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that) + { + $response->setContent(''); + $response->setStatusCode(200); + $that->assertEquals('HEAD', $request->getMethod()); + }); + + $this->request('HEAD', '/', array('HTTP_EXPECT' => 'something ...')); + $this->assertHttpKernelIsCalled(); + $this->assertEquals('', $this->response->getContent()); + } + + public function testUsesCacheToRespondToHeadRequestsWhenFresh() + { + $that = $this; + $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that) + { + $response->headers->set('Cache-Control', 'public, max-age=10'); + $response->setContent('Hello World'); + $response->setStatusCode(200); + $that->assertNotEquals('HEAD', $request->getMethod()); + }); + + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals('Hello World', $this->response->getContent()); + + $this->request('HEAD', '/'); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('', $this->response->getContent()); + $this->assertEquals(strlen('Hello World'), $this->response->headers->get('Content-Length')); + } + + public function testSendsNoContentWhenFresh() + { + $time = \DateTime::createFromFormat('U', time()); + $that = $this; + $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that, $time) + { + $response->headers->set('Cache-Control', 'public, max-age=10'); + $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); + }); + + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals('Hello World', $this->response->getContent()); + + $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(304, $this->response->getStatusCode()); + $this->assertEquals('', $this->response->getContent()); + } + + public function testInvalidatesCachedResponsesOnPost() + { + $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) + { + if ('GET' == $request->getMethod()) { + $response->setStatusCode(200); + $response->headers->set('Cache-Control', 'public, max-age=500'); + $response->setContent('Hello World'); + } elseif ('POST' == $request->getMethod()) { + $response->setStatusCode(303); + $response->headers->set('Location', '/'); + $response->headers->remove('Cache-Control'); + $response->setContent(''); + } + }); + + // build initial request to enter into the cache + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + + // make sure it is valid + $this->request('GET', '/'); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('fresh'); + + // now POST to same URL + $this->request('POST', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals('/', $this->response->headers->get('Location')); + $this->assertTraceContains('invalidate'); + $this->assertTraceContains('pass'); + $this->assertEquals('', $this->response->getContent()); + + // now make sure it was actually invalidated + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('stale'); + $this->assertTraceContains('invalid'); + $this->assertTraceContains('store'); + } + + public function testServesFromCacheWhenHeadersMatch() + { + $count = 0; + $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) + { + $response->headers->set('Vary', 'Accept User-Agent Foo'); + $response->headers->set('Cache-Control', 'public, max-age=10'); + $response->headers->set('X-Response-Count', ++$count); + $response->setContent($request->headers->get('USER_AGENT')); + }); + + $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Bob/1.0', $this->response->getContent()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + + $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Bob/1.0', $this->response->getContent()); + $this->assertTraceContains('fresh'); + $this->assertTraceNotContains('store'); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + } + + public function testStoresMultipleResponsesWhenHeadersDiffer() + { + $count = 0; + $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) + { + $response->headers->set('Vary', 'Accept User-Agent Foo'); + $response->headers->set('Cache-Control', 'public, max-age=10'); + $response->headers->set('X-Response-Count', ++$count); + $response->setContent($request->headers->get('USER_AGENT')); + }); + + $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Bob/1.0', $this->response->getContent()); + $this->assertEquals(1, $this->response->headers->get('X-Response-Count')); + + $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0')); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertTraceContains('miss'); + $this->assertTraceContains('store'); + $this->assertEquals('Bob/2.0', $this->response->getContent()); + $this->assertEquals(2, $this->response->headers->get('X-Response-Count')); + + $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->assertTraceContains('fresh'); + $this->assertEquals('Bob/1.0', $this->response->getContent()); + $this->assertEquals(1, $this->response->headers->get('X-Response-Count')); + + $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0')); + $this->assertTraceContains('fresh'); + $this->assertEquals('Bob/2.0', $this->response->getContent()); + $this->assertEquals(2, $this->response->headers->get('X-Response-Count')); + + $this->request('GET', '/', array('HTTP_USER_AGENT' => 'Bob/2.0')); + $this->assertTraceContains('miss'); + $this->assertEquals('Bob/2.0', $this->response->getContent()); + $this->assertEquals(3, $this->response->headers->get('X-Response-Count')); + } + + public function testShouldCatchExceptions() + { + $this->catchExceptions(); + + $this->setNextResponse(); + $this->request('GET', '/'); + + $this->assertExceptionsAreCaught(); + } + + public function testShouldNotCatchExceptions() + { + $this->catchExceptions(false); + + $this->setNextResponse(); + $this->request('GET', '/'); + + $this->assertExceptionsAreNotCaught(); + } + + public function testEsiCacheSendsTheLowestTtl() + { + $responses = array( + array( + 'status' => 200, + 'body' => ' ', + 'headers' => array( + 'Cache-Control' => 's-maxage=300', + 'Surrogate-Control' => 'content="ESI/1.0"', + ), + ), + array( + 'status' => 200, + 'body' => 'Hello World!', + 'headers' => array('Cache-Control' => 's-maxage=300'), + ), + array( + 'status' => 200, + 'body' => 'My name is Bobby.', + 'headers' => array('Cache-Control' => 's-maxage=100'), + ), + ); + + $this->setNextResponses($responses); + + $this->request('GET', '/', array(), array(), true); + $this->assertEquals("Hello World! My name is Bobby.", $this->response->getContent()); + + // check for 100 or 99 as the test can be executed after a second change + $this->assertTrue(in_array($this->response->getTtl(), array(99, 100))); + } + + public function testEsiCacheForceValidation() + { + $responses = array( + array( + 'status' => 200, + 'body' => ' ', + 'headers' => array( + 'Cache-Control' => 's-maxage=300', + 'Surrogate-Control' => 'content="ESI/1.0"', + ), + ), + array( + 'status' => 200, + 'body' => 'Hello World!', + 'headers' => array('ETag' => 'foobar'), + ), + array( + 'status' => 200, + 'body' => 'My name is Bobby.', + 'headers' => array('Cache-Control' => 's-maxage=100'), + ), + ); + + $this->setNextResponses($responses); + + $this->request('GET', '/', array(), array(), true); + $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent()); + $this->assertNull($this->response->getTtl()); + $this->assertTrue($this->response->mustRevalidate()); + $this->assertTrue($this->response->headers->hasCacheControlDirective('private')); + $this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache')); + } + + public function testEsiRecalculateContentLengthHeader() + { + $responses = array( + array( + 'status' => 200, + 'body' => '', + 'headers' => array( + 'Content-Length' => 26, + 'Cache-Control' => 's-maxage=300', + 'Surrogate-Control' => 'content="ESI/1.0"', + ), + ), + array( + 'status' => 200, + 'body' => 'Hello World!', + 'headers' => array(), + ), + ); + + $this->setNextResponses($responses); + + $this->request('GET', '/', array(), array(), true); + $this->assertEquals('Hello World!', $this->response->getContent()); + $this->assertEquals(12, $this->response->headers->get('Content-Length')); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php new file mode 100644 index 0000000..6bbcdfb --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php @@ -0,0 +1,180 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpCache\Esi; +use Symfony\Component\HttpKernel\HttpCache\HttpCache; +use Symfony\Component\HttpKernel\HttpCache\Store; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +class HttpCacheTestCase extends \PHPUnit_Framework_TestCase +{ + protected $kernel; + protected $cache; + protected $caches; + protected $cacheConfig; + protected $request; + protected $response; + protected $responses; + protected $catch; + protected $esi; + + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $this->kernel = null; + + $this->cache = null; + $this->esi = null; + $this->caches = array(); + $this->cacheConfig = array(); + + $this->request = null; + $this->response = null; + $this->responses = array(); + + $this->catch = false; + + $this->clearDirectory(sys_get_temp_dir().'/http_cache'); + } + + protected function tearDown() + { + $this->kernel = null; + $this->cache = null; + $this->caches = null; + $this->request = null; + $this->response = null; + $this->responses = null; + $this->cacheConfig = null; + $this->catch = null; + $this->esi = null; + + $this->clearDirectory(sys_get_temp_dir().'/http_cache'); + } + + public function assertHttpKernelIsCalled() + { + $this->assertTrue($this->kernel->hasBeenCalled()); + } + + public function assertHttpKernelIsNotCalled() + { + $this->assertFalse($this->kernel->hasBeenCalled()); + } + + public function assertResponseOk() + { + $this->assertEquals(200, $this->response->getStatusCode()); + } + + public function assertTraceContains($trace) + { + $traces = $this->cache->getTraces(); + $traces = current($traces); + + $this->assertRegExp('/'.$trace.'/', implode(', ', $traces)); + } + + public function assertTraceNotContains($trace) + { + $traces = $this->cache->getTraces(); + $traces = current($traces); + + $this->assertNotRegExp('/'.$trace.'/', implode(', ', $traces)); + } + + public function assertExceptionsAreCaught() + { + $this->assertTrue($this->kernel->isCatchingExceptions()); + } + + public function assertExceptionsAreNotCaught() + { + $this->assertFalse($this->kernel->isCatchingExceptions()); + } + + public function request($method, $uri = '/', $server = array(), $cookies = array(), $esi = false) + { + if (null === $this->kernel) { + throw new \LogicException('You must call setNextResponse() before calling request().'); + } + + $this->kernel->reset(); + + $this->store = new Store(sys_get_temp_dir().'/http_cache'); + + $this->cacheConfig['debug'] = true; + + $this->esi = $esi ? new Esi() : null; + $this->cache = new HttpCache($this->kernel, $this->store, $this->esi, $this->cacheConfig); + $this->request = Request::create($uri, $method, array(), $cookies, array(), $server); + + $this->response = $this->cache->handle($this->request, HttpKernelInterface::MASTER_REQUEST, $this->catch); + + $this->responses[] = $this->response; + } + + public function getMetaStorageValues() + { + $values = array(); + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(sys_get_temp_dir().'/http_cache/md', \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + $values[] = file_get_contents($file); + } + + return $values; + } + + // A basic response with 200 status code and a tiny body. + public function setNextResponse($statusCode = 200, array $headers = array(), $body = 'Hello World', \Closure $customizer = null) + { + $this->kernel = new TestHttpKernel($body, $statusCode, $headers, $customizer); + } + + public function setNextResponses($responses) + { + $this->kernel = new TestMultipleHttpKernel($responses); + } + + public function catchExceptions($catch = true) + { + $this->catch = $catch; + } + + static public function clearDirectory($directory) + { + if (!is_dir($directory)) { + return; + } + + $fp = opendir($directory); + while (false !== $file = readdir($fp)) { + if (!in_array($file, array('.', '..'))) + { + if (is_link($directory.'/'.$file)) { + unlink($directory.'/'.$file); + } elseif (is_dir($directory.'/'.$file)) { + self::clearDirectory($directory.'/'.$file); + rmdir($directory.'/'.$file); + } else { + unlink($directory.'/'.$file); + } + } + } + + closedir($fp); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php new file mode 100644 index 0000000..747d350 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -0,0 +1,232 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpCache\Store; + +class StoreTest extends \PHPUnit_Framework_TestCase +{ + protected $request; + protected $response; + protected $store; + + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $this->request = Request::create('/'); + $this->response = new Response('hello world', 200, array()); + + HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache'); + + $this->store = new Store(sys_get_temp_dir().'/http_cache'); + } + + protected function tearDown() + { + $this->store = null; + $this->request = null; + $this->response = null; + + HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache'); + } + + public function testReadsAnEmptyArrayWithReadWhenNothingCachedAtKey() + { + $this->assertEmpty($this->getStoreMetadata('/nothing')); + } + + public function testRemovesEntriesForKeyWithPurge() + { + $request = Request::create('/foo'); + $this->store->write($request, new Response('foo')); + $this->assertNotEmpty($this->getStoreMetadata($request)); + + $this->assertTrue($this->store->purge('/foo')); + $this->assertEmpty($this->getStoreMetadata($request)); + + $this->assertFalse($this->store->purge('/bar')); + } + + public function testStoresACacheEntry() + { + $cacheKey = $this->storeSimpleEntry(); + + $this->assertNotEmpty($this->getStoreMetadata($cacheKey)); + } + + public function testSetsTheXContentDigestResponseHeaderBeforeStoring() + { + $cacheKey = $this->storeSimpleEntry(); + $entries = $this->getStoreMetadata($cacheKey); + list ($req, $res) = $entries[0]; + + $this->assertEquals('ena94a8fe5ccb19ba61c4c0873d391e987982fbbd3', $res['x-content-digest'][0]); + } + + public function testFindsAStoredEntryWithLookup() + { + $this->storeSimpleEntry(); + $response = $this->store->lookup($this->request); + + $this->assertNotNull($response); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); + } + + public function testDoesNotFindAnEntryWithLookupWhenNoneExists() + { + $request = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + + $this->assertNull($this->store->lookup($request)); + } + + public function testCanonizesUrlsForCacheKeys() + { + $this->storeSimpleEntry($path = '/test?x=y&p=q'); + $hitsReq = Request::create($path); + $missReq = Request::create('/test?p=x'); + + $this->assertNotNull($this->store->lookup($hitsReq)); + $this->assertNull($this->store->lookup($missReq)); + } + + public function testDoesNotFindAnEntryWithLookupWhenTheBodyDoesNotExist() + { + $this->storeSimpleEntry(); + $this->assertNotNull($this->response->headers->get('X-Content-Digest')); + $path = $this->getStorePath($this->response->headers->get('X-Content-Digest')); + @unlink($path); + $this->assertNull($this->store->lookup($this->request)); + } + + public function testRestoresResponseHeadersProperlyWithLookup() + { + $this->storeSimpleEntry(); + $response = $this->store->lookup($this->request); + + $this->assertEquals($response->headers->all(), array_merge(array('content-length' => 4, 'x-body-file' => array($this->getStorePath($response->headers->get('X-Content-Digest')))), $this->response->headers->all())); + } + + public function testRestoresResponseContentFromEntityStoreWithLookup() + { + $this->storeSimpleEntry(); + $response = $this->store->lookup($this->request); + $this->assertEquals($this->getStorePath('en'.sha1('test')), $response->getContent()); + } + + public function testInvalidatesMetaAndEntityStoreEntriesWithInvalidate() + { + $this->storeSimpleEntry(); + $this->store->invalidate($this->request); + $response = $this->store->lookup($this->request); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); + $this->assertFalse($response->isFresh()); + } + + public function testSucceedsQuietlyWhenInvalidateCalledWithNoMatchingEntries() + { + $req = Request::create('/test'); + $this->store->invalidate($req); + $this->assertNull($this->store->lookup($this->request)); + } + + public function testDoesNotReturnEntriesThatVaryWithLookup() + { + $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); + $res = new Response('test', 200, array('Vary' => 'Foo Bar')); + $this->store->write($req1, $res); + + $this->assertNull($this->store->lookup($req2)); + } + + public function testStoresMultipleResponsesForEachVaryCombination() + { + $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar')); + $key = $this->store->write($req1, $res1); + + $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); + $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar')); + $this->store->write($req2, $res2); + + $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Baz', 'HTTP_BAR' => 'Boom')); + $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar')); + $this->store->write($req3, $res3); + + $this->assertEquals($this->getStorePath('en'.sha1('test 3')), $this->store->lookup($req3)->getContent()); + $this->assertEquals($this->getStorePath('en'.sha1('test 2')), $this->store->lookup($req2)->getContent()); + $this->assertEquals($this->getStorePath('en'.sha1('test 1')), $this->store->lookup($req1)->getContent()); + + $this->assertCount(3, $this->getStoreMetadata($key)); + } + + public function testOverwritesNonVaryingResponseWithStore() + { + $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar')); + $key = $this->store->write($req1, $res1); + $this->assertEquals($this->getStorePath('en'.sha1('test 1')), $this->store->lookup($req1)->getContent()); + + $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); + $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar')); + $this->store->write($req2, $res2); + $this->assertEquals($this->getStorePath('en'.sha1('test 2')), $this->store->lookup($req2)->getContent()); + + $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar')); + $key = $this->store->write($req3, $res3); + $this->assertEquals($this->getStorePath('en'.sha1('test 3')), $this->store->lookup($req3)->getContent()); + + $this->assertCount(2, $this->getStoreMetadata($key)); + } + + protected function storeSimpleEntry($path = null, $headers = array()) + { + if (null === $path) { + $path = '/test'; + } + + $this->request = Request::create($path, 'get', array(), array(), array(), $headers); + $this->response = new Response('test', 200, array('Cache-Control' => 'max-age=420')); + + return $this->store->write($this->request, $this->response); + } + + protected function getStoreMetadata($key) + { + $r = new \ReflectionObject($this->store); + $m = $r->getMethod('getMetadata'); + $m->setAccessible(true); + + if ($key instanceof Request) { + $m1 = $r->getMethod('getCacheKey'); + $m1->setAccessible(true); + $key = $m1->invoke($this->store, $key); + } + + return $m->invoke($this->store, $key); + } + + protected function getStorePath($key) + { + $r = new \ReflectionObject($this->store); + $m = $r->getMethod('getPath'); + $m->setAccessible(true); + + return $m->invoke($this->store, $key); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php new file mode 100644 index 0000000..c732c67 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\HttpCache; + +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class TestHttpKernel extends HttpKernel implements ControllerResolverInterface +{ + protected $body; + protected $status; + protected $headers; + protected $called; + protected $customizer; + protected $catch; + + public function __construct($body, $status, $headers, \Closure $customizer = null) + { + $this->body = $body; + $this->status = $status; + $this->headers = $headers; + $this->customizer = $customizer; + $this->called = false; + $this->catch = false; + + parent::__construct(new EventDispatcher(), $this); + } + + public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false) + { + $this->catch = $catch; + + return parent::handle($request, $type, $catch); + } + + public function isCatchingExceptions() + { + return $this->catch; + } + + public function getController(Request $request) + { + return array($this, 'callController'); + } + + public function getArguments(Request $request, $controller) + { + return array($request); + } + + public function callController(Request $request) + { + $this->called = true; + + $response = new Response($this->body, $this->status, $this->headers); + + if (null !== $this->customizer) { + call_user_func($this->customizer, $request, $response); + } + + return $response; + } + + public function hasBeenCalled() + { + return $this->called; + } + + public function reset() + { + $this->called = false; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php new file mode 100644 index 0000000..eeb9bea --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\HttpCache; + +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface +{ + protected $bodies; + protected $statuses; + protected $headers; + protected $catch; + protected $call; + + public function __construct($responses) + { + $this->bodies = array(); + $this->statuses = array(); + $this->headers = array(); + $this->call = false; + + foreach ($responses as $response) { + $this->bodies[] = $response['body']; + $this->statuses[] = $response['status']; + $this->headers[] = $response['headers']; + } + + parent::__construct(new EventDispatcher(), $this); + } + + public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false) + { + return parent::handle($request, $type, $catch); + } + + public function getController(Request $request) + { + return array($this, 'callController'); + } + + public function getArguments(Request $request, $controller) + { + return array($request); + } + + public function callController(Request $request) + { + $this->called = true; + + $response = new Response(array_shift($this->bodies), array_shift($this->statuses), array_shift($this->headers)); + + return $response; + } + + public function hasBeenCalled() + { + return $this->called; + } + + public function reset() + { + $this->call = false; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php new file mode 100644 index 0000000..8a184b4 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -0,0 +1,241 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class HttpKernelTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + /** + * @expectedException RuntimeException + */ + public function testHandleWhenControllerThrowsAnExceptionAndRawIsTrue() + { + $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); + + $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true); + } + + /** + * @expectedException RuntimeException + */ + public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalseAndNoListenerIsRegistered() + { + $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); + + $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false); + } + + public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) + { + $event->setResponse(new Response($event->getException()->getMessage())); + }); + + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); })); + + $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); + } + + public function testHandleWhenAListenerReturnsAResponse() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::REQUEST, function ($event) + { + $event->setResponse(new Response('hello')); + }); + + $kernel = new HttpKernel($dispatcher, $this->getResolver()); + + $this->assertEquals('hello', $kernel->handle(new Request())->getContent()); + } + + /** + * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException + */ + public function testHandleWhenNoControllerIsFound() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(false)); + + $kernel->handle(new Request()); + } + + /** + * @expectedException LogicException + */ + public function testHandleWhenTheControllerIsNotACallable() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver('foobar')); + + $kernel->handle(new Request()); + } + + public function testHandleWhenTheControllerIsAClosure() + { + $response = new Response('foo'); + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () use ($response) { return $response; })); + + $this->assertSame($response, $kernel->handle(new Request())); + } + + public function testHandleWhenTheControllerIsAnObjectWithInvoke() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(new Controller())); + + $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); + } + + public function testHandleWhenTheControllerIsAFunction() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver('Symfony\Component\HttpKernel\Tests\controller_func')); + + $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); + } + + public function testHandleWhenTheControllerIsAnArray() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(array(new Controller(), 'controller'))); + + $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); + } + + public function testHandleWhenTheControllerIsAStaticArray() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(array('Symfony\Component\HttpKernel\Tests\Controller', 'staticcontroller'))); + + $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); + } + + /** + * @expectedException LogicException + */ + public function testHandleWhenTheControllerDoesNotReturnAResponse() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); + + $kernel->handle(new Request()); + } + + public function testHandleWhenTheControllerDoesNotReturnAResponseButAViewIsRegistered() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::VIEW, function ($event) + { + $event->setResponse(new Response($event->getControllerResult())); + }); + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); + + $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); + } + + public function testHandleWithAResponseListener() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::RESPONSE, function ($event) + { + $event->setResponse(new Response('foo')); + }); + $kernel = new HttpKernel($dispatcher, $this->getResolver()); + + $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); + } + + public function testTerminate() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver()); + $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel, &$capturedRequest, &$capturedResponse) { + $called = true; + $capturedKernel = $event->getKernel(); + $capturedRequest = $event->getRequest(); + $capturedResponse = $event->getResponse(); + }); + + $kernel->terminate($request = Request::create('/'), $response = new Response()); + $this->assertTrue($called); + $this->assertEquals($kernel, $capturedKernel); + $this->assertEquals($request, $capturedRequest); + $this->assertEquals($response, $capturedResponse); + } + + protected function getResolver($controller = null) + { + if (null === $controller) { + $controller = function() { return new Response('Hello'); }; + } + + $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface'); + $resolver->expects($this->any()) + ->method('getController') + ->will($this->returnValue($controller)); + $resolver->expects($this->any()) + ->method('getArguments') + ->will($this->returnValue(array())); + + return $resolver; + } + + protected function assertResponseEquals(Response $expected, Response $actual) + { + $expected->setDate($actual->getDate()); + $this->assertEquals($expected, $actual); + } +} + +class Controller +{ + public function __invoke() + { + return new Response('foo'); + } + + public function controller() + { + return new Response('foo'); + } + + static public function staticController() + { + return new Response('foo'); + } +} + +function controller_func() +{ + return new Response('foo'); +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/KernelTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/KernelTest.php new file mode 100644 index 0000000..a26d9d7 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -0,0 +1,782 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\Bundle\BundleInterface; +use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest; +use Symfony\Component\HttpKernel\Tests\Fixtures\FooBarBundle; + +class KernelTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\DependencyInjection\Container')) { + $this->markTestSkipped('The "DependencyInjection" component is not available'); + } + } + + public function testConstructor() + { + $env = 'test_env'; + $debug = true; + $kernel = new KernelForTest($env, $debug); + + $this->assertEquals($env, $kernel->getEnvironment()); + $this->assertEquals($debug, $kernel->isDebug()); + $this->assertFalse($kernel->isBooted()); + $this->assertLessThanOrEqual(microtime(true), $kernel->getStartTime()); + $this->assertNull($kernel->getContainer()); + } + + public function testClone() + { + $env = 'test_env'; + $debug = true; + $kernel = new KernelForTest($env, $debug); + + $clone = clone $kernel; + + $this->assertEquals($env, $clone->getEnvironment()); + $this->assertEquals($debug, $clone->isDebug()); + $this->assertFalse($clone->isBooted()); + $this->assertLessThanOrEqual(microtime(true), $clone->getStartTime()); + $this->assertNull($clone->getContainer()); + } + + public function testBootInitializesBundlesAndContainer() + { + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('initializeBundles', 'initializeContainer', 'getBundles')) + ->getMock(); + $kernel->expects($this->once()) + ->method('initializeBundles'); + $kernel->expects($this->once()) + ->method('initializeContainer'); + $kernel->expects($this->once()) + ->method('getBundles') + ->will($this->returnValue(array())); + + $kernel->boot(); + } + + public function testBootSetsTheContainerToTheBundles() + { + $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\Bundle') + ->disableOriginalConstructor() + ->getMock(); + $bundle->expects($this->once()) + ->method('setContainer'); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('initializeBundles', 'initializeContainer', 'getBundles')) + ->getMock(); + $kernel->expects($this->once()) + ->method('getBundles') + ->will($this->returnValue(array($bundle))); + + $kernel->boot(); + } + + public function testBootSetsTheBootedFlagToTrue() + { + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('initializeBundles', 'initializeContainer', 'getBundles')) + ->getMock(); + $kernel->expects($this->once()) + ->method('getBundles') + ->will($this->returnValue(array())); + + $kernel->boot(); + + $this->assertTrue($kernel->isBooted()); + } + + public function testBootKernelSeveralTimesOnlyInitializesBundlesOnce() + { + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('initializeBundles', 'initializeContainer', 'getBundles')) + ->getMock(); + $kernel->expects($this->once()) + ->method('getBundles') + ->will($this->returnValue(array())); + + $kernel->boot(); + $kernel->boot(); + } + + public function testShutdownCallsShutdownOnAllBundles() + { + $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\Bundle') + ->disableOriginalConstructor() + ->getMock(); + $bundle->expects($this->once()) + ->method('shutdown'); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getBundles')) + ->getMock(); + $kernel->expects($this->once()) + ->method('getBundles') + ->will($this->returnValue(array($bundle))); + + $kernel->shutdown(); + } + + public function testShutdownGivesNullContainerToAllBundles() + { + $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\Bundle') + ->disableOriginalConstructor() + ->getMock(); + $bundle->expects($this->once()) + ->method('setContainer') + ->with(null); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getBundles')) + ->getMock(); + $kernel->expects($this->once()) + ->method('getBundles') + ->will($this->returnValue(array($bundle))); + + $kernel->shutdown(); + } + + public function testHandleCallsHandleOnHttpKernel() + { + $type = HttpKernelInterface::MASTER_REQUEST; + $catch = true; + $request = new Request(); + + $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') + ->disableOriginalConstructor() + ->getMock(); + $httpKernelMock + ->expects($this->once()) + ->method('handle') + ->with($request, $type, $catch); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel')) + ->getMock(); + + $kernel->expects($this->once()) + ->method('getHttpKernel') + ->will($this->returnValue($httpKernelMock)); + + $kernel->handle($request, $type, $catch); + } + + public function testHandleBootsTheKernel() + { + $type = HttpKernelInterface::MASTER_REQUEST; + $catch = true; + $request = new Request(); + + $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') + ->disableOriginalConstructor() + ->getMock(); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel', 'boot')) + ->getMock(); + + $kernel->expects($this->once()) + ->method('getHttpKernel') + ->will($this->returnValue($httpKernelMock)); + + $kernel->expects($this->once()) + ->method('boot'); + + // required as this value is initialized + // in the kernel constructor, which we don't call + $kernel->setIsBooted(false); + + $kernel->handle($request, $type, $catch); + } + + public function testStripComments() + { + if (!function_exists('token_get_all')) { + $this->markTestSkipped('The function token_get_all() is not available.'); + + return; + } + $source = <<assertEquals($expected, Kernel::stripComments($source)); + } + + public function testIsClassInActiveBundleFalse() + { + $kernel = $this->getKernelMockForIsClassInActiveBundleTest(); + + $this->assertFalse($kernel->isClassInActiveBundle('Not\In\Active\Bundle')); + } + + public function testIsClassInActiveBundleFalseNoNamespace() + { + $kernel = $this->getKernelMockForIsClassInActiveBundleTest(); + + $this->assertFalse($kernel->isClassInActiveBundle('NotNamespacedClass')); + } + + public function testIsClassInActiveBundleTrue() + { + $kernel = $this->getKernelMockForIsClassInActiveBundleTest(); + + $this->assertTrue($kernel->isClassInActiveBundle(__NAMESPACE__.'\Fixtures\FooBarBundle\SomeClass')); + } + + protected function getKernelMockForIsClassInActiveBundleTest() + { + $bundle = new FooBarBundle(); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getBundles')) + ->getMock(); + $kernel->expects($this->once()) + ->method('getBundles') + ->will($this->returnValue(array($bundle))); + + return $kernel; + } + + public function testGetRootDir() + { + $kernel = new KernelForTest('test', true); + + $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures', $kernel->getRootDir()); + } + + public function testGetName() + { + $kernel = new KernelForTest('test', true); + + $this->assertEquals('Fixtures', $kernel->getName()); + } + + public function testSerialize() + { + $env = 'test_env'; + $debug = true; + $kernel = new KernelForTest($env, $debug); + + $expected = serialize(array($env, $debug)); + $this->assertEquals($expected, $kernel->serialize()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLocateResourceThrowsExceptionWhenNameIsNotValid() + { + $this->getKernelForInvalidLocateResource()->locateResource('Foo'); + } + + /** + * @expectedException \RuntimeException + */ + public function testLocateResourceThrowsExceptionWhenNameIsUnsafe() + { + $this->getKernelForInvalidLocateResource()->locateResource('@FooBundle/../bar'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLocateResourceThrowsExceptionWhenBundleDoesNotExist() + { + $this->getKernelForInvalidLocateResource()->locateResource('@FooBundle/config/routing.xml'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLocateResourceThrowsExceptionWhenResourceDoesNotExist() + { + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('getBundle') + ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ; + + $kernel->locateResource('@Bundle1Bundle/config/routing.xml'); + } + + public function testLocateResourceReturnsTheFirstThatMatches() + { + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('getBundle') + ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ; + + $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt')); + } + + public function testLocateResourceReturnsTheFirstThatMatchesWithParent() + { + $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); + $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->exactly(2)) + ->method('getBundle') + ->will($this->returnValue(array($child, $parent))) + ; + + $this->assertEquals(__DIR__.'/Fixtures/Bundle2Bundle/foo.txt', $kernel->locateResource('@ParentAABundle/foo.txt')); + $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/bar.txt', $kernel->locateResource('@ParentAABundle/bar.txt')); + } + + public function testLocateResourceReturnsAllMatches() + { + $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); + $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('getBundle') + ->will($this->returnValue(array($child, $parent))) + ; + + $this->assertEquals(array( + __DIR__.'/Fixtures/Bundle2Bundle/foo.txt', + __DIR__.'/Fixtures/Bundle1Bundle/foo.txt'), + $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false)); + } + + public function testLocateResourceReturnsAllMatchesBis() + { + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('getBundle') + ->will($this->returnValue(array( + $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'), + $this->getBundle(__DIR__.'/Foobar') + ))) + ; + + $this->assertEquals( + array(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt'), + $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false) + ); + } + + public function testLocateResourceIgnoresDirOnNonResource() + { + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('getBundle') + ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ; + + $this->assertEquals( + __DIR__.'/Fixtures/Bundle1Bundle/foo.txt', + $kernel->locateResource('@Bundle1Bundle/foo.txt', __DIR__.'/Fixtures') + ); + } + + public function testLocateResourceReturnsTheDirOneForResources() + { + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('getBundle') + ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) + ; + + $this->assertEquals( + __DIR__.'/Fixtures/Resources/FooBundle/foo.txt', + $kernel->locateResource('@FooBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources') + ); + } + + public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes() + { + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('getBundle') + ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) + ; + + $this->assertEquals(array( + __DIR__.'/Fixtures/Resources/Bundle1Bundle/foo.txt', + __DIR__.'/Fixtures/Bundle1Bundle/Resources/foo.txt'), + $kernel->locateResource('@Bundle1Bundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) + ); + } + + public function testLocateResourceOverrideBundleAndResourcesFolders() + { + $parent = $this->getBundle(__DIR__.'/Fixtures/BaseBundle', null, 'BaseBundle', 'BaseBundle'); + $child = $this->getBundle(__DIR__.'/Fixtures/ChildBundle', 'ParentBundle', 'ChildBundle', 'ChildBundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->exactly(4)) + ->method('getBundle') + ->will($this->returnValue(array($child, $parent))) + ; + + $this->assertEquals(array( + __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', + __DIR__.'/Fixtures/ChildBundle/Resources/foo.txt', + __DIR__.'/Fixtures/BaseBundle/Resources/foo.txt', + ), + $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) + ); + + $this->assertEquals( + __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', + $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources') + ); + + try { + $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', false); + $this->fail('Hidden resources should raise an exception when returning an array of matching paths'); + } catch (\RuntimeException $e) { + } + + try { + $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', true); + $this->fail('Hidden resources should raise an exception when returning the first matching path'); + } catch (\RuntimeException $e) { + } + } + + public function testLocateResourceOnDirectories() + { + $kernel = $this->getKernel(); + $kernel + ->expects($this->exactly(2)) + ->method('getBundle') + ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) + ; + + $this->assertEquals( + __DIR__.'/Fixtures/Resources/FooBundle/', + $kernel->locateResource('@FooBundle/Resources/', __DIR__.'/Fixtures/Resources') + ); + $this->assertEquals( + __DIR__.'/Fixtures/Resources/FooBundle', + $kernel->locateResource('@FooBundle/Resources', __DIR__.'/Fixtures/Resources') + ); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->exactly(2)) + ->method('getBundle') + ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) + ; + + $this->assertEquals( + __DIR__.'/Fixtures/Bundle1Bundle/Resources/', + $kernel->locateResource('@Bundle1Bundle/Resources/') + ); + $this->assertEquals( + __DIR__.'/Fixtures/Bundle1Bundle/Resources', + $kernel->locateResource('@Bundle1Bundle/Resources') + ); + } + + public function testInitializeBundles() + { + $parent = $this->getBundle(null, null, 'ParentABundle'); + $child = $this->getBundle(null, 'ParentABundle', 'ChildABundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('registerBundles') + ->will($this->returnValue(array($parent, $child))) + ; + $kernel->initializeBundles(); + + $map = $kernel->getBundleMap(); + $this->assertEquals(array($child, $parent), $map['ParentABundle']); + } + + public function testInitializeBundlesSupportInheritanceCascade() + { + $grandparent = $this->getBundle(null, null, 'GrandParentBBundle'); + $parent = $this->getBundle(null, 'GrandParentBBundle', 'ParentBBundle'); + $child = $this->getBundle(null, 'ParentBBundle', 'ChildBBundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('registerBundles') + ->will($this->returnValue(array($grandparent, $parent, $child))) + ; + + $kernel->initializeBundles(); + + $map = $kernel->getBundleMap(); + $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentBBundle']); + $this->assertEquals(array($child, $parent), $map['ParentBBundle']); + $this->assertEquals(array($child), $map['ChildBBundle']); + } + + /** + * @expectedException \LogicException + */ + public function testInitializeBundlesThrowsExceptionWhenAParentDoesNotExists() + { + $child = $this->getBundle(null, 'FooBar', 'ChildCBundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('registerBundles') + ->will($this->returnValue(array($child))) + ; + $kernel->initializeBundles(); + } + + public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder() + { + $grandparent = $this->getBundle(null, null, 'GrandParentCCundle'); + $parent = $this->getBundle(null, 'GrandParentCCundle', 'ParentCCundle'); + $child = $this->getBundle(null, 'ParentCCundle', 'ChildCCundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('registerBundles') + ->will($this->returnValue(array($parent, $grandparent, $child))) + ; + + $kernel->initializeBundles(); + + $map = $kernel->getBundleMap(); + $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentCCundle']); + $this->assertEquals(array($child, $parent), $map['ParentCCundle']); + $this->assertEquals(array($child), $map['ChildCCundle']); + } + + /** + * @expectedException \LogicException + */ + public function testInitializeBundlesThrowsExceptionWhenABundleIsDirectlyExtendedByTwoBundles() + { + $parent = $this->getBundle(null, null, 'ParentCBundle'); + $child1 = $this->getBundle(null, 'ParentCBundle', 'ChildC1Bundle'); + $child2 = $this->getBundle(null, 'ParentCBundle', 'ChildC2Bundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('registerBundles') + ->will($this->returnValue(array($parent, $child1, $child2))) + ; + $kernel->initializeBundles(); + } + + /** + * @expectedException \LogicException + */ + public function testInitializeBundleThrowsExceptionWhenRegisteringTwoBundlesWithTheSameName() + { + $fooBundle = $this->getBundle(null, null, 'FooBundle', 'DuplicateName'); + $barBundle = $this->getBundle(null, null, 'BarBundle', 'DuplicateName'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('registerBundles') + ->will($this->returnValue(array($fooBundle, $barBundle))) + ; + $kernel->initializeBundles(); + } + + /** + * @expectedException \LogicException + */ + public function testInitializeBundleThrowsExceptionWhenABundleExtendsItself() + { + $circularRef = $this->getBundle(null, 'CircularRefBundle', 'CircularRefBundle'); + + $kernel = $this->getKernel(); + $kernel + ->expects($this->once()) + ->method('registerBundles') + ->will($this->returnValue(array($circularRef))) + ; + $kernel->initializeBundles(); + } + + public function testTerminateReturnsSilentlyIfKernelIsNotBooted() + { + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel')) + ->getMock(); + + $kernel->expects($this->never()) + ->method('getHttpKernel'); + + $kernel->setIsBooted(false); + $kernel->terminate(Request::create('/'), new Response()); + } + + public function testTerminateDelegatesTerminationOnlyForTerminableInterface() + { + // does not implement TerminableInterface + $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface') + ->disableOriginalConstructor() + ->getMock(); + + $httpKernelMock + ->expects($this->never()) + ->method('terminate'); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel')) + ->getMock(); + + $kernel->expects($this->once()) + ->method('getHttpKernel') + ->will($this->returnValue($httpKernelMock)); + + $kernel->setIsBooted(true); + $kernel->terminate(Request::create('/'), new Response()); + + // implements TerminableInterface + $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') + ->disableOriginalConstructor() + ->setMethods(array('terminate')) + ->getMock(); + + $httpKernelMock + ->expects($this->once()) + ->method('terminate'); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel')) + ->getMock(); + + $kernel->expects($this->exactly(2)) + ->method('getHttpKernel') + ->will($this->returnValue($httpKernelMock)); + + $kernel->setIsBooted(true); + $kernel->terminate(Request::create('/'), new Response()); + } + + protected function getBundle($dir = null, $parent = null, $className = null, $bundleName = null) + { + $bundle = $this + ->getMockBuilder('Symfony\Component\HttpKernel\Tests\BundleForTest') + ->setMethods(array('getPath', 'getParent', 'getName')) + ->disableOriginalConstructor() + ; + + if ($className) { + $bundle->setMockClassName($className); + } + + $bundle = $bundle->getMockForAbstractClass(); + + $bundle + ->expects($this->any()) + ->method('getName') + ->will($this->returnValue(null === $bundleName ? get_class($bundle) : $bundleName)) + ; + + $bundle + ->expects($this->any()) + ->method('getPath') + ->will($this->returnValue($dir)) + ; + + $bundle + ->expects($this->any()) + ->method('getParent') + ->will($this->returnValue($parent)) + ; + + return $bundle; + } + + protected function getKernel() + { + return $this + ->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') + ->setMethods(array('getBundle', 'registerBundles')) + ->disableOriginalConstructor() + ->getMock() + ; + } + + protected function getKernelForInvalidLocateResource() + { + return $this + ->getMockBuilder('Symfony\Component\HttpKernel\Kernel') + ->disableOriginalConstructor() + ->getMockForAbstractClass() + ; + } +} + +abstract class BundleForTest implements BundleInterface +{ + // We can not extend Symfony\Component\HttpKernel\Bundle\Bundle as we want to mock getName() which is final +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Logger.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Logger.php new file mode 100644 index 0000000..88babf3 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Logger.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpKernel\Log\LoggerInterface; + +class Logger implements LoggerInterface +{ + protected $logs; + + public function __construct() + { + $this->clear(); + } + + public function getLogs($priority = false) + { + return false === $priority ? $this->logs : $this->logs[$priority]; + } + + public function clear() + { + $this->logs = array( + 'emerg' => array(), + 'alert' => array(), + 'crit' => array(), + 'err' => array(), + 'warn' => array(), + 'notice' => array(), + 'info' => array(), + 'debug' => array(), + ); + } + + public function log($message, $priority) + { + $this->logs[$priority][] = $message; + } + + public function emerg($message, array $context = array()) + { + $this->log($message, 'emerg'); + } + + public function alert($message, array $context = array()) + { + $this->log($message, 'alert'); + } + + public function crit($message, array $context = array()) + { + $this->log($message, 'crit'); + } + + public function err($message, array $context = array()) + { + $this->log($message, 'err'); + } + + public function warn($message, array $context = array()) + { + $this->log($message, 'warn'); + } + + public function notice($message, array $context = array()) + { + $this->log($message, 'notice'); + } + + public function info($message, array $context = array()) + { + $this->log($message, 'info'); + } + + public function debug($message, array $context = array()) + { + $this->log($message, 'debug'); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.php new file mode 100644 index 0000000..15bcc39 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.php @@ -0,0 +1,216 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\Profiler\Profile; + +abstract class AbstractProfilerStorageTest extends \PHPUnit_Framework_TestCase +{ + public function testStore() + { + for ($i = 0; $i < 10; $i ++) { + $profile = new Profile('token_'.$i); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo.bar'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + } + $this->assertCount(10, $this->getStorage()->find('127.0.0.1', 'http://foo.bar', 20, 'GET'), '->write() stores data in the storage'); + } + + public function testChildren() + { + $parentProfile = new Profile('token_parent'); + $parentProfile->setIp('127.0.0.1'); + $parentProfile->setUrl('http://foo.bar/parent'); + + $childProfile = new Profile('token_child'); + $childProfile->setIp('127.0.0.1'); + $childProfile->setUrl('http://foo.bar/child'); + + $parentProfile->addChild($childProfile); + + $this->getStorage()->write($parentProfile); + $this->getStorage()->write($childProfile); + + // Load them from storage + $parentProfile = $this->getStorage()->read('token_parent'); + $childProfile = $this->getStorage()->read('token_child'); + + // Check child has link to parent + $this->assertNotNull($childProfile->getParent()); + $this->assertEquals($parentProfile->getToken(), $childProfile->getParentToken()); + + // Check parent has child + $children = $parentProfile->getChildren(); + $this->assertCount(1, $children); + $this->assertEquals($childProfile->getToken(), $children[0]->getToken()); + } + + public function testStoreSpecialCharsInUrl() + { + // The storage accepts special characters in URLs (Even though URLs are not + // supposed to contain them) + $profile = new Profile('simple_quote'); + $profile->setUrl('http://foo.bar/\''); + $this->getStorage()->write($profile); + $this->assertTrue(false !== $this->getStorage()->read('simple_quote'), '->write() accepts single quotes in URL'); + + $profile = new Profile('double_quote'); + $profile->setUrl('http://foo.bar/"'); + $this->getStorage()->write($profile); + $this->assertTrue(false !== $this->getStorage()->read('double_quote'), '->write() accepts double quotes in URL'); + + $profile = new Profile('backslash'); + $profile->setUrl('http://foo.bar/\\'); + $this->getStorage()->write($profile); + $this->assertTrue(false !== $this->getStorage()->read('backslash'), '->write() accepts backslash in URL'); + + $profile = new Profile('comma'); + $profile->setUrl('http://foo.bar/,'); + $this->getStorage()->write($profile); + $this->assertTrue(false !== $this->getStorage()->read('comma'), '->write() accepts comma in URL'); + } + + public function testStoreDuplicateToken() + { + $profile = new Profile('token'); + $profile->setUrl('http://example.com/'); + + $this->assertTrue($this->getStorage()->write($profile), '->write() returns true when the token is unique'); + + $profile->setUrl('http://example.net/'); + + $this->assertTrue($this->getStorage()->write($profile), '->write() returns true when the token is already present in the storage'); + $this->assertEquals('http://example.net/', $this->getStorage()->read('token')->getUrl(), '->write() overwrites the current profile data'); + + $this->assertCount(1, $this->getStorage()->find('', '', 1000, ''), '->find() does not return the same profile twice'); + } + + public function testRetrieveByIp() + { + $profile = new Profile('token'); + $profile->setIp('127.0.0.1'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'), '->find() retrieve a record by IP'); + $this->assertCount(0, $this->getStorage()->find('127.0.%.1', '', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the IP'); + $this->assertCount(0, $this->getStorage()->find('127.0._.1', '', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the IP'); + } + + public function testRetrieveByUrl() + { + $profile = new Profile('simple_quote'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo.bar/\''); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $profile = new Profile('double_quote'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo.bar/"'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $profile = new Profile('backslash'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo\\bar/'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $profile = new Profile('percent'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo.bar/%'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $profile = new Profile('underscore'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo.bar/_'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $profile = new Profile('semicolon'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo.bar/;'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/\'', 10, 'GET'), '->find() accepts single quotes in URLs'); + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/"', 10, 'GET'), '->find() accepts double quotes in URLs'); + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo\\bar/', 10, 'GET'), '->find() accepts backslash in URLs'); + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/;', 10, 'GET'), '->find() accepts semicolon in URLs'); + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/%', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the URL'); + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/_', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the URL'); + } + + public function testStoreTime() + { + $dt = new \DateTime('now'); + for ($i = 0; $i < 3; $i++) { + $dt->modify('+1 minute'); + $profile = new Profile('time_'.$i); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://foo.bar'); + $profile->setTime($dt->getTimestamp()); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + } + $records = $this->getStorage()->find('', '', 3, 'GET'); + $this->assertCount(3, $records, '->find() returns all previously added records'); + $this->assertEquals($records[0]['token'], 'time_2', '->find() returns records ordered by time in descendant order'); + $this->assertEquals($records[1]['token'], 'time_1', '->find() returns records ordered by time in descendant order'); + $this->assertEquals($records[2]['token'], 'time_0', '->find() returns records ordered by time in descendant order'); + } + + public function testRetrieveByEmptyUrlAndIp() + { + for ($i = 0; $i < 5; $i++) { + $profile = new Profile('token_'.$i); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + } + $this->assertCount(5, $this->getStorage()->find('', '', 10, 'GET'), '->find() returns all previously added records'); + $this->getStorage()->purge(); + } + + public function testPurge() + { + $profile = new Profile('token1'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://example.com/'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $this->assertTrue(false !== $this->getStorage()->read('token1')); + $this->assertCount(1, $this->getStorage()->find('127.0.0.1', '', 10, 'GET')); + + $profile = new Profile('token2'); + $profile->setIp('127.0.0.1'); + $profile->setUrl('http://example.net/'); + $profile->setMethod('GET'); + $this->getStorage()->write($profile); + + $this->assertTrue(false !== $this->getStorage()->read('token2')); + $this->assertCount(2, $this->getStorage()->find('127.0.0.1', '', 10, 'GET')); + + $this->getStorage()->purge(); + + $this->assertEmpty($this->getStorage()->read('token'), '->purge() removes all data stored by profiler'); + $this->assertCount(0, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'), '->purge() removes all items from index'); + } + + /** + * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface + */ + abstract protected function getStorage(); +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php new file mode 100644 index 0000000..16c615a --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage; + +class FileProfilerStorageTest extends AbstractProfilerStorageTest +{ + protected static $tmpDir; + protected static $storage; + + protected static function cleanDir() + { + $flags = \FilesystemIterator::SKIP_DOTS; + $iterator = new \RecursiveDirectoryIterator(self::$tmpDir, $flags); + $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); + + foreach ($iterator as $file) { + if (is_file($file)) { + unlink($file); + } + } + } + + public static function setUpBeforeClass() + { + self::$tmpDir = sys_get_temp_dir() . '/sf2_profiler_file_storage'; + if (is_dir(self::$tmpDir)) { + self::cleanDir(); + } + self::$storage = new FileProfilerStorage('file:'.self::$tmpDir); + } + + public static function tearDownAfterClass() + { + self::cleanDir(); + } + + protected function setUp() + { + self::$storage->purge(); + } + + /** + * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface + */ + protected function getStorage() + { + return self::$storage; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.php new file mode 100644 index 0000000..fb55026 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\Profiler\MemcacheProfilerStorage; + +class DummyMemcacheProfilerStorage extends MemcacheProfilerStorage +{ + public function getMemcache() + { + return parent::getMemcache(); + } +} + +/** + * @group memcached + */ +class MemcacheProfilerStorageTest extends AbstractProfilerStorageTest +{ + protected static $storage; + + public static function tearDownAfterClass() + { + if (self::$storage) { + self::$storage->purge(); + } + } + + protected function setUp() + { + if (!extension_loaded('memcache')) { + $this->markTestSkipped('MemcacheProfilerStorageTest requires that the extension memcache is loaded'); + } + + self::$storage = new DummyMemcacheProfilerStorage('memcache://127.0.0.1:11211', '', '', 86400); + try { + self::$storage->getMemcache(); + $stats = self::$storage->getMemcache()->getExtendedStats(); + if (!isset($stats['127.0.0.1:11211']) || $stats['127.0.0.1:11211'] === false) { + throw new \Exception(); + } + } catch (\Exception $e) { + $this->markTestSkipped('MemcacheProfilerStorageTest requires that there is a Memcache server present on localhost'); + } + + if (self::$storage) { + self::$storage->purge(); + } + } + + /** + * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface + */ + protected function getStorage() + { + return self::$storage; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.php new file mode 100644 index 0000000..5f2f5c3 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\Profiler\MemcachedProfilerStorage; + +class DummyMemcachedProfilerStorage extends MemcachedProfilerStorage +{ + public function getMemcached() + { + return parent::getMemcached(); + } +} + +/** + * @group memcached + */ +class MemcachedProfilerStorageTest extends AbstractProfilerStorageTest +{ + protected static $storage; + + public static function tearDownAfterClass() + { + if (self::$storage) { + self::$storage->purge(); + } + } + + protected function setUp() + { + if (!extension_loaded('memcached')) { + $this->markTestSkipped('MemcachedProfilerStorageTest requires that the extension memcached is loaded'); + } + + self::$storage = new DummyMemcachedProfilerStorage('memcached://127.0.0.1:11211', '', '', 86400); + try { + self::$storage->getMemcached(); + } catch (\Exception $e) { + $this->markTestSkipped('MemcachedProfilerStorageTest requires that there is a Memcache server present on localhost'); + } + + if (self::$storage) { + self::$storage->purge(); + } + } + + /** + * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface + */ + protected function getStorage() + { + return self::$storage; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.php new file mode 100644 index 0000000..310320c --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\Profiler\MongoDbProfilerStorage; +use Symfony\Component\HttpKernel\Profiler\Profile; + +class DummyMongoDbProfilerStorage extends MongoDbProfilerStorage +{ + public function getMongo() + { + return parent::getMongo(); + } +} + +class MongoDbProfilerStorageTest extends AbstractProfilerStorageTest +{ + protected static $storage; + + static public function setUpBeforeClass() + { + if (extension_loaded('mongo')) { + self::$storage = new DummyMongoDbProfilerStorage('mongodb://localhost/symfony_tests/profiler_data', '', '', 86400); + try { + self::$storage->getMongo(); + } catch (\MongoConnectionException $e) { + self::$storage = null; + } + } + } + + static public function tearDownAfterClass() + { + if (self::$storage) { + self::$storage->purge(); + self::$storage = null; + } + } + + public function testCleanup() + { + $dt = new \DateTime('-2 day'); + for ($i = 0; $i < 3; $i++) { + $dt->modify('-1 day'); + $profile = new Profile('time_'.$i); + $profile->setTime($dt->getTimestamp()); + $profile->setMethod('GET'); + self::$storage->write($profile); + } + $records = self::$storage->find('', '', 3, 'GET'); + $this->assertCount(1, $records, '->find() returns only one record'); + $this->assertEquals($records[0]['token'], 'time_2', '->find() returns the latest added record'); + self::$storage->purge(); + } + + /** + * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface + */ + protected function getStorage() + { + return self::$storage; + } + + protected function setUp() + { + if (self::$storage) { + self::$storage->purge(); + } else { + $this->markTestSkipped('MongoDbProfilerStorageTest requires then mongo PHP extennsion and a MongoDB server on localhost'); + } + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php new file mode 100644 index 0000000..2a41531 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; +use Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage; +use Symfony\Component\HttpKernel\Profiler\Profiler; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class ProfilerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + } + + public function testCollect() + { + if (!class_exists('SQLite3') && (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers()))) { + $this->markTestSkipped('This test requires SQLite support in your environment'); + } + + $request = new Request(); + $request->query->set('foo', 'bar'); + $response = new Response(); + $collector = new RequestDataCollector(); + + $tmp = tempnam(sys_get_temp_dir(), 'sf2_profiler'); + if (file_exists($tmp)) { + @unlink($tmp); + } + $storage = new SqliteProfilerStorage('sqlite:'.$tmp); + $storage->purge(); + + $profiler = new Profiler($storage); + $profiler->add($collector); + $profile = $profiler->collect($request, $response); + + $profile = $profiler->loadProfile($profile->getToken()); + $this->assertEquals(array('foo' => 'bar'), $profiler->get('request')->getRequestQuery()->all()); + + @unlink($tmp); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.php new file mode 100644 index 0000000..88779bc --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\Profiler\RedisProfilerStorage; + +class DummyRedisProfilerStorage extends RedisProfilerStorage +{ + public function getRedis() + { + return parent::getRedis(); + } +} + +class RedisProfilerStorageTest extends AbstractProfilerStorageTest +{ + protected static $storage; + + protected function setUp() + { + if (!extension_loaded('redis')) { + $this->markTestSkipped('RedisProfilerStorageTest requires redis extension to be loaded'); + } + + self::$storage = new DummyRedisProfilerStorage('redis://127.0.0.1:6379', '', '', 86400); + try { + self::$storage->getRedis(); + + self::$storage->purge(); + + } catch (\Exception $e) { + self::$storage = false; + $this->markTestSkipped('RedisProfilerStorageTest requires that there is a Redis server present on localhost'); + } + } + + protected function tearDown() + { + if (self::$storage) { + self::$storage->purge(); + self::$storage->getRedis()->close(); + self::$storage = false; + } + } + + /** + * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface + */ + protected function getStorage() + { + return self::$storage; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.php b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.php new file mode 100644 index 0000000..43546c1 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Profiler; + +use Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage; + +class SqliteProfilerStorageTest extends AbstractProfilerStorageTest +{ + protected static $dbFile; + protected static $storage; + + public static function setUpBeforeClass() + { + self::$dbFile = tempnam(sys_get_temp_dir(), 'sf2_sqlite_storage'); + if (file_exists(self::$dbFile)) { + @unlink(self::$dbFile); + } + self::$storage = new SqliteProfilerStorage('sqlite:'.self::$dbFile); + } + + public static function tearDownAfterClass() + { + @unlink(self::$dbFile); + } + + protected function setUp() + { + if (!class_exists('SQLite3') && (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers()))) { + $this->markTestSkipped('This test requires SQLite support in your environment'); + } + self::$storage->purge(); + } + + /** + * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface + */ + protected function getStorage() + { + return self::$storage; + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php b/core/vendor/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php new file mode 100644 index 0000000..d526c4d --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class TestHttpKernel extends HttpKernel implements ControllerResolverInterface +{ + public function __construct() + { + parent::__construct(new EventDispatcher(), $this); + } + + public function getController(Request $request) + { + return array($this, 'callController'); + } + + public function getArguments(Request $request, $controller) + { + return array($request); + } + + public function callController(Request $request) + { + return new Response('Request: '.$request->getRequestUri()); + } +} diff --git a/core/vendor/Symfony/Component/HttpKernel/Tests/bootstrap.php b/core/vendor/Symfony/Component/HttpKernel/Tests/bootstrap.php new file mode 100644 index 0000000..2386a26 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/Tests/bootstrap.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + foreach (array( + 'SYMFONY_EVENT_DISPATCHER' => 'EventDispatcher', + 'SYMFONY_HTTP_FOUNDATION' => 'HttpFoundation', + 'SYMFONY_DEPENDENCY_INJECTION' => 'DependencyInjection', + 'SYMFONY_CONSOLE' => 'Console', + 'SYMFONY_BROWSER_KIT' => 'BrowserKit', + 'SYMFONY_FINDER' => 'Finder', + 'SYMFONY_CLASS_LOADER' => 'ClassLoader', + 'SYMFONY_PROCESS' => 'Process', + 'SYMFONY_ROUTING' => 'Routing', + 'SYMFONY_CONFIG' => 'Config', + ) as $env => $name) { + if (isset($_SERVER[$env]) && 0 === strpos(ltrim($class, '/'), 'Symfony\Component\\'.$name)) { + if (file_exists($file = $_SERVER[$env].'/'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\\'.$name)).'.php')) { + require_once $file; + } + } + } + + if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\HttpKernel')) { + if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\HttpKernel')).'.php')) { + require_once $file; + } + } +}); diff --git a/core/vendor/Symfony/Component/HttpKernel/phpunit.xml.dist b/core/vendor/Symfony/Component/HttpKernel/phpunit.xml.dist new file mode 100644 index 0000000..0d881e1 --- /dev/null +++ b/core/vendor/Symfony/Component/HttpKernel/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + + + + diff --git a/core/vendor/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php b/core/vendor/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php index 0725ca6..0edd6e9 100644 --- a/core/vendor/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php +++ b/core/vendor/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php @@ -17,6 +17,7 @@ use Symfony\Component\Routing\Route; * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. * * @author Fabien Potencier + * @author Tobias Schultze * * @api */ @@ -43,92 +44,22 @@ class PhpGeneratorDumper extends GeneratorDumper 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', ), $options); - return - $this->startClass($options['class'], $options['base_class']). - $this->addConstructor(). - $this->addGenerator(). - $this->endClass() - ; - } - - private function addGenerator() - { - $methods = array(); - foreach ($this->getRoutes()->all() as $name => $route) { - $compiledRoute = $route->compile(); - - $variables = str_replace("\n", '', var_export($compiledRoute->getVariables(), true)); - $defaults = str_replace("\n", '', var_export($compiledRoute->getDefaults(), true)); - $requirements = str_replace("\n", '', var_export($compiledRoute->getRequirements(), true)); - $tokens = str_replace("\n", '', var_export($compiledRoute->getTokens(), true)); - - $escapedName = str_replace('.', '__', $name); - - $methods[] = <<{'get'.\$escapedName.'RouteInfo'}(); - - return \$this->doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$absolute); - } - -$methods -EOF; - } - - private function startClass($class, $baseClass) - { - $routes = array(); - foreach ($this->getRoutes()->all() as $name => $route) { - $routes[] = " '$name' => true,"; - } - $routes = implode("\n", $routes); - return <<generateDeclaredRoutes()}; - private function addConstructor() - { - return <<context = \$context; } +{$this->generateGenerateMethod()} +} + EOF; } - private function endClass() + /** + * Generates PHP code representing an array of defined routes + * together with the routes properties (e.g. requirements). + * + * @return string PHP code + */ + private function generateDeclaredRoutes() + { + $routes = "array(\n"; + foreach ($this->getRoutes()->all() as $name => $route) { + $compiledRoute = $route->compile(); + + $properties = array(); + $properties[] = $compiledRoute->getVariables(); + $properties[] = $compiledRoute->getDefaults(); + $properties[] = $compiledRoute->getRequirements(); + $properties[] = $compiledRoute->getTokens(); + + $routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true))); + } + $routes .= ' )'; + + return $routes; + } + + /** + * Generates PHP code representing the `generate` method that implements the UrlGeneratorInterface. + * + * @return string PHP code + */ + private function generateGenerateMethod() { return <<doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$absolute); + } EOF; } } diff --git a/core/vendor/Symfony/Component/Routing/Generator/UrlGenerator.php b/core/vendor/Symfony/Component/Routing/Generator/UrlGenerator.php index 535f7bb..f47f3e5 100644 --- a/core/vendor/Symfony/Component/Routing/Generator/UrlGenerator.php +++ b/core/vendor/Symfony/Component/Routing/Generator/UrlGenerator.php @@ -19,7 +19,7 @@ use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; /** - * UrlGenerator generates URL based on a set of routes. + * UrlGenerator generates a URL based on a set of routes. * * @author Fabien Potencier * @@ -34,7 +34,6 @@ class UrlGenerator implements UrlGeneratorInterface ); protected $routes; - protected $cache; /** * Constructor. @@ -48,7 +47,6 @@ class UrlGenerator implements UrlGeneratorInterface { $this->routes = $routes; $this->context = $context; - $this->cache = array(); } /** @@ -84,11 +82,10 @@ class UrlGenerator implements UrlGeneratorInterface throw new RouteNotFoundException(sprintf('Route "%s" does not exist.', $name)); } - if (!isset($this->cache[$name])) { - $this->cache[$name] = $route->compile(); - } + // the Route has a cache of its own and is not recompiled as long as it does not get modified + $compiledRoute = $route->compile(); - return $this->doGenerate($this->cache[$name]->getVariables(), $route->getDefaults(), $route->getRequirements(), $this->cache[$name]->getTokens(), $parameters, $name, $absolute); + return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $absolute); } /** diff --git a/core/vendor/Symfony/Component/Routing/Loader/XmlFileLoader.php b/core/vendor/Symfony/Component/Routing/Loader/XmlFileLoader.php index 913deab..8f27b03 100644 --- a/core/vendor/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/core/vendor/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -79,6 +79,7 @@ class XmlFileLoader extends FileLoader $defaults = array(); $requirements = array(); + $options = array(); foreach ($node->childNodes as $n) { if (!$n instanceof \DOMElement) { @@ -92,13 +93,16 @@ class XmlFileLoader extends FileLoader case 'requirement': $requirements[(string) $n->getAttribute('key')] = trim((string) $n->nodeValue); break; + case 'option': + $options[(string) $n->getAttribute('key')] = trim((string) $n->nodeValue); + break; default: throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $n->tagName)); } } $this->setCurrentDir(dirname($path)); - $collection->addCollection($this->import($resource, ('' !== $type ? $type : null), false, $file), $prefix, $defaults, $requirements); + $collection->addCollection($this->import($resource, ('' !== $type ? $type : null), false, $file), $prefix, $defaults, $requirements, $options); break; default: throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName)); diff --git a/core/vendor/Symfony/Component/Routing/Loader/YamlFileLoader.php b/core/vendor/Symfony/Component/Routing/Loader/YamlFileLoader.php index 5d8f02a..1f9d711 100644 --- a/core/vendor/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/core/vendor/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -69,9 +69,10 @@ class YamlFileLoader extends FileLoader $prefix = isset($config['prefix']) ? $config['prefix'] : null; $defaults = isset($config['defaults']) ? $config['defaults'] : array(); $requirements = isset($config['requirements']) ? $config['requirements'] : array(); + $options = isset($config['options']) ? $config['options'] : array(); $this->setCurrentDir(dirname($path)); - $collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix, $defaults, $requirements); + $collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix, $defaults, $requirements, $options); } else { $this->parseRoute($collection, $name, $config, $path); } diff --git a/core/vendor/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/core/vendor/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd index 3b8fa3d..b8571e6 100644 --- a/core/vendor/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd +++ b/core/vendor/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd @@ -29,6 +29,7 @@ + diff --git a/core/vendor/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php b/core/vendor/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php index 344abe2..7499bdd 100644 --- a/core/vendor/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php +++ b/core/vendor/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php @@ -31,6 +31,8 @@ class ApacheMatcherDumper extends MatcherDumper * @param array $options An array of options * * @return string A string to be used as Apache rewrite rules + * + * @throws \LogicException When the route regex is invalid */ public function dump(array $options = array()) { @@ -39,6 +41,8 @@ class ApacheMatcherDumper extends MatcherDumper 'base_uri' => '', ), $options); + $options['script_name'] = self::escape($options['script_name'], ' ', '\\'); + $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]"); $methodVars = array(); @@ -46,8 +50,14 @@ class ApacheMatcherDumper extends MatcherDumper $compiledRoute = $route->compile(); // prepare the apache regex - $regex = preg_replace('/\?P<.+?>/', '', substr(str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), 1, -3)); - $regex = '^'.preg_quote($options['base_uri']).substr($regex, 1); + $regex = $compiledRoute->getRegex(); + $delimiter = $regex[0]; + $regexPatternEnd = strrpos($regex, $delimiter); + if (strlen($regex) < 2 || 0 === $regexPatternEnd) { + throw new \LogicException('The "%s" route regex "%s" is invalid', $name, $regex); + } + $regex = preg_replace('/\?<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1)); + $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\'); $methods = array(); if ($req = $route->getRequirement('_method')) { @@ -58,14 +68,13 @@ class ApacheMatcherDumper extends MatcherDumper } } - $hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' == substr($regex, -2) && '^/$' != $regex; + $hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex; $variables = array('E=_ROUTING__route:'.$name); foreach ($compiledRoute->getVariables() as $i => $variable) { $variables[] = 'E=_ROUTING_'.$variable.':%'.($i + 1); } foreach ($route->getDefaults() as $key => $value) { - // todo: a more legit way to escape the value? $variables[] = 'E=_ROUTING_'.$key.':'.strtr($value, array( ':' => '\\:', '=' => '\\=', @@ -121,4 +130,36 @@ class ApacheMatcherDumper extends MatcherDumper return implode("\n\n", $rules)."\n"; } + + /** + * Escapes a string. + * + * @param string $string The string to be escaped + * @param string $char The character to be escaped + * @param string $with The character to be used for escaping + * + * @return string The escaped string + */ + static private function escape($string, $char, $with) + { + $escaped = false; + $output = ''; + foreach(str_split($string) as $symbol) { + if ($escaped) { + $output .= $symbol; + $escaped = false; + continue; + } + if ($symbol === $char) { + $output .= $with.$char; + continue; + } + if ($symbol === $with) { + $escaped = true; + } + $output .= $symbol; + } + + return $output; + } } diff --git a/core/vendor/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/core/vendor/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 5c2fcb4..bc26c0c 100644 --- a/core/vendor/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/core/vendor/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -18,6 +18,7 @@ use Symfony\Component\Routing\RouteCollection; * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. * * @author Fabien Potencier + * @author Tobias Schultze */ class PhpMatcherDumper extends MatcherDumper { @@ -42,113 +43,144 @@ class PhpMatcherDumper extends MatcherDumper // trailing slash support is only enabled if we know how to redirect the user $interfaces = class_implements($options['base_class']); - $supportsRedirections = isset($interfaces['Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface']); - - return - $this->startClass($options['class'], $options['base_class']). - $this->addConstructor(). - $this->addMatcher($supportsRedirections). - $this->endClass() - ; + $supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']); + + return <<context = \$context; } - private function addMatcher($supportsRedirections) +{$this->generateMatchMethod($supportsRedirections)} +} + +EOF; + } + + /** + * Generates the code for the match method implementing UrlMatcherInterface. + * + * @param Boolean $supportsRedirections Whether redirections are supported by the base class + * + * @return string Match method as PHP code + */ + private function generateMatchMethod($supportsRedirections) { - // we need to deep clone the routes as we will modify the structure to optimize the dump - $code = implode("\n", $this->compileRoutes(clone $this->getRoutes(), $supportsRedirections)); + $code = rtrim($this->compileRoutes($this->getRoutes(), $supportsRedirections), "\n"); return <<getIterator(); - $keys = array_keys($routeIterator->getArrayCopy()); - $keysCount = count($keys); - - $i = 0; - foreach ($routeIterator as $name => $route) { - $i++; - - if ($route instanceof RouteCollection) { - $prefix = $route->getPrefix(); - $optimizable = $prefix && count($route->all()) > 1 && false === strpos($route->getPrefix(), '{'); - $indent = ''; - if ($optimizable) { - for ($j = $i; $j < $keysCount; $j++) { - if ($keys[$j] === null) { - continue; - } - - $testRoute = $routeIterator->offsetGet($keys[$j]); - $isCollection = ($testRoute instanceof RouteCollection); - - $testPrefix = $isCollection ? $testRoute->getPrefix() : $testRoute->getPattern(); - - if (0 === strpos($testPrefix, $prefix)) { - $routeIterator->offsetUnset($keys[$j]); - - if ($isCollection) { - $route->addCollection($testRoute); - } else { - $route->add($keys[$j], $testRoute); - } - - $i++; - $keys[$j] = null; - } - } - - if ($prefix !== $parentPrefix) { - $code[] = sprintf(" if (0 === strpos(\$pathinfo, %s)) {", var_export($prefix, true)); - $indent = ' '; - } - } - - foreach ($this->compileRoutes($route, $supportsRedirections, $prefix) as $line) { - foreach (explode("\n", $line) as $l) { - if ($l) { - $code[] = $indent.$l; - } else { - $code[] = $l; - } - } - } - - if ($optimizable && $prefix !== $parentPrefix) { - $code[] = " }\n"; - } - } else { - foreach ($this->compileRoute($route, $name, $supportsRedirections, $parentPrefix) as $line) { - $code[] = $line; - } + $code = ''; + + $prefix = $routes->getPrefix(); + $countDirectChildRoutes = $this->countDirectChildRoutes($routes); + $countAllChildRoutes = count($routes->all()); + // Can the matching be optimized by wrapping it with the prefix condition + // - no need to optimize if current prefix is the same as the parent prefix + // - if $countDirectChildRoutes === 0, the sub-collections can do their own optimizations (in case there are any) + // - it's not worth wrapping a single child route + // - prefixes with variables cannot be optimized because routes within the collection might have different requirements for the same variable + $optimizable = '' !== $prefix && $prefix !== $parentPrefix && $countDirectChildRoutes > 0 && $countAllChildRoutes > 1 && false === strpos($prefix, '{'); + if ($optimizable) { + $code .= sprintf(" if (0 === strpos(\$pathinfo, %s)) {\n", var_export($prefix, true)); + } + + foreach ($routes as $name => $route) { + if ($route instanceof Route) { + // a single route in a sub-collection is not wrapped so it should do its own optimization in ->compileRoute with $parentPrefix = null + $code .= $this->compileRoute($route, $name, $supportsRedirections, 1 === $countAllChildRoutes ? null : $prefix)."\n"; + } elseif ($countAllChildRoutes - $countDirectChildRoutes > 0) { // we can stop iterating recursively if we already know there are no more routes + $code .= $this->compileRoutes($route, $supportsRedirections, $prefix); } } + if ($optimizable) { + $code .= " }\n\n"; + // apply extra indention at each line (except empty ones) + $code = preg_replace('/^.{2,}$/m', ' $0', $code); + } + return $code; } + + /** + * Compiles a single Route to PHP code used to match it against the path info. + * + * @param Route $routes A Route instance + * @param string $name The name of the Route + * @param Boolean $supportsRedirections Whether redirections are supported by the base class + * @param string|null $parentPrefix The prefix of the parent collection used to optimize the code + * + * @return string PHP code + */ private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) { - $code = array(); + $code = ''; $compiledRoute = $route->compile(); $conditions = array(); $hasTrailingSlash = false; $matches = false; $methods = array(); + if ($req = $route->getRequirement('_method')) { $methods = explode('|', strtoupper($req)); // GET and HEAD are equivalent @@ -156,9 +188,10 @@ EOF; $methods[] = 'HEAD'; } } + $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods)); - if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), $m)) { + if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?.*?)\$\1#', $compiledRoute->getRegex(), $m)) { if ($supportsTrailingSlash && substr($m['url'], -1) === '/') { $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); $hasTrailingSlash = true; @@ -166,11 +199,11 @@ EOF; $conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true)); } } else { - if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() != $parentPrefix) { + if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) { $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true)); } - $regex = str_replace(array("\n", ' '), '', $compiledRoute->getRegex()); + $regex = $compiledRoute->getRegex(); if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) { $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); $hasTrailingSlash = true; @@ -182,39 +215,42 @@ EOF; $conditions = implode(' && ', $conditions); - $gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name); - - $code[] = <<context->getMethod() != '$methods[0]') { \$allow[] = '$methods[0]'; goto $gotoname; } + EOF; } else { - $methods = implode('\', \'', $methods); - $code[] = <<context->getMethod(), array('$methods'))) { \$allow = array_merge(\$allow, array('$methods')); goto $gotoname; } + EOF; } } if ($hasTrailingSlash) { - $code[] = sprintf(<<redirect(\$pathinfo.'/', '%s'); + return \$this->redirect(\$pathinfo.'/', '$name'); } -EOF - , $name); + +EOF; } if ($scheme = $route->getRequirement('_scheme')) { @@ -222,77 +258,32 @@ EOF throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.'); } - $code[] = sprintf(<<context->getScheme() !== '$scheme') { - return \$this->redirect(\$pathinfo, '%s', '$scheme'); + return \$this->redirect(\$pathinfo, '$name', '$scheme'); } -EOF - , $name); + +EOF; } // optimize parameters array if (true === $matches && $compiledRoute->getDefaults()) { - $code[] = sprintf(" return array_merge(\$this->mergeDefaults(\$matches, %s), array('_route' => '%s'));" + $code .= sprintf(" return array_merge(\$this->mergeDefaults(\$matches, %s), array('_route' => '%s'));\n" , str_replace("\n", '', var_export($compiledRoute->getDefaults(), true)), $name); } elseif (true === $matches) { - $code[] = sprintf(" \$matches['_route'] = '%s';", $name); - $code[] = sprintf(" return \$matches;", $name); + $code .= sprintf(" \$matches['_route'] = '%s';\n", $name); + $code .= " return \$matches;\n"; } elseif ($compiledRoute->getDefaults()) { - $code[] = sprintf(' return %s;', str_replace("\n", '', var_export(array_merge($compiledRoute->getDefaults(), array('_route' => $name)), true))); + $code .= sprintf(" return %s;\n", str_replace("\n", '', var_export(array_merge($compiledRoute->getDefaults(), array('_route' => $name)), true))); } else { - $code[] = sprintf(" return array('_route' => '%s');", $name); + $code .= sprintf(" return array('_route' => '%s');\n", $name); } - $code[] = " }"; + $code .= " }\n"; if ($methods) { - $code[] = " $gotoname:"; + $code .= " $gotoname:\n"; } - $code[] = ''; - return $code; } - - private function startClass($class, $baseClass) - { - return <<context = \$context; - } - -EOF; - } - - private function endClass() - { - return << $route) { if ($route instanceof RouteCollection) { if (!$ret = $this->matchCollection($pathinfo, $route)) { diff --git a/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcher.php b/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcher.php index eaae027..ded89e6 100644 --- a/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -72,7 +72,14 @@ class UrlMatcher implements UrlMatcherInterface } /** - * {@inheritDoc} + * Tries to match a URL with a set of routes. + * + * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) + * + * @return array An array of parameters + * + * @throws ResourceNotFoundException If the resource could not be found + * @throws MethodNotAllowedException If the resource was found but the request method is not allowed * * @api */ @@ -80,7 +87,7 @@ class UrlMatcher implements UrlMatcherInterface { $this->allow = array(); - if ($ret = $this->matchCollection(urldecode($pathinfo), $this->routes)) { + if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) { return $ret; } @@ -177,7 +184,7 @@ class UrlMatcher implements UrlMatcherInterface $parameters = $defaults; foreach ($params as $key => $value) { if (!is_int($key)) { - $parameters[$key] = rawurldecode($value); + $parameters[$key] = $value; } } diff --git a/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php b/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php index ce998ea..58c5688 100644 --- a/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php +++ b/core/vendor/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php @@ -30,7 +30,7 @@ interface UrlMatcherInterface extends RequestContextAwareInterface * If the matcher can not find information, it must throw one of the exceptions documented * below. * - * @param string $pathinfo The path info to be parsed + * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) * * @return array An array of parameters * diff --git a/core/vendor/Symfony/Component/Routing/README.md b/core/vendor/Symfony/Component/Routing/README.md index eb72334..63c398c 100644 --- a/core/vendor/Symfony/Component/Routing/README.md +++ b/core/vendor/Symfony/Component/Routing/README.md @@ -27,6 +27,14 @@ system: Resources --------- -Unit tests: +You can run the unit tests with the following command: -https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/Routing + phpunit -c src/Symfony/Component/Routing/ + +If you also want to run the unit tests that depend on other Symfony +Components, declare the following environment variables before running +PHPUnit: + + export SYMFONY_CONFIG=../path/to/Config + export SYMFONY_YAML=../path/to/Yaml + export DOCTRINE_COMMON=../path/to/doctrine-common diff --git a/core/vendor/Symfony/Component/Routing/Route.php b/core/vendor/Symfony/Component/Routing/Route.php index 02131f4..05d8a74 100644 --- a/core/vendor/Symfony/Component/Routing/Route.php +++ b/core/vendor/Symfony/Component/Routing/Route.php @@ -79,10 +79,12 @@ class Route $this->pattern = trim($pattern); // a route must start with a slash - if (empty($this->pattern) || '/' !== $this->pattern[0]) { + if ('' === $this->pattern || '/' !== $this->pattern[0]) { $this->pattern = '/'.$this->pattern; } + $this->compiled = null; + return $this; } @@ -107,9 +109,28 @@ class Route */ public function setOptions(array $options) { - $this->options = array_merge(array( + $this->options = array( 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', - ), $options); + ); + + return $this->addOptions($options); + } + + /** + * Adds options. + * + * This method implements a fluent interface. + * + * @param array $options The options + * + * @return Route The current Route instance + */ + public function addOptions(array $options) + { + foreach ($options as $name => $option) { + $this->options[(string) $name] = $option; + } + $this->compiled = null; return $this; } @@ -129,6 +150,7 @@ class Route public function setOption($name, $value) { $this->options[$name] = $value; + $this->compiled = null; return $this; } @@ -185,6 +207,7 @@ class Route foreach ($defaults as $name => $default) { $this->defaults[(string) $name] = $default; } + $this->compiled = null; return $this; } @@ -226,6 +249,7 @@ class Route public function setDefault($name, $default) { $this->defaults[(string) $name] = $default; + $this->compiled = null; return $this; } @@ -270,6 +294,7 @@ class Route foreach ($requirements as $key => $regex) { $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); } + $this->compiled = null; return $this; } @@ -299,6 +324,7 @@ class Route public function setRequirement($key, $regex) { $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); + $this->compiled = null; return $this; } @@ -325,15 +351,19 @@ class Route private function sanitizeRequirement($key, $regex) { - if (is_array($regex)) { - throw new \InvalidArgumentException(sprintf('Routing requirements must be a string, array given for "%s"', $key)); + if (!is_string($regex)) { + throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" must be a string', $key)); + } + + if ('' === $regex) { + throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty', $key)); } - if ('^' == $regex[0]) { + if ('^' === $regex[0]) { $regex = substr($regex, 1); } - if ('$' == substr($regex, -1)) { + if ('$' === substr($regex, -1)) { $regex = substr($regex, 0, -1); } diff --git a/core/vendor/Symfony/Component/Routing/RouteCollection.php b/core/vendor/Symfony/Component/Routing/RouteCollection.php index cc8fdc9..85acf33 100644 --- a/core/vendor/Symfony/Component/Routing/RouteCollection.php +++ b/core/vendor/Symfony/Component/Routing/RouteCollection.php @@ -14,12 +14,13 @@ namespace Symfony\Component\Routing; use Symfony\Component\Config\Resource\ResourceInterface; /** - * A RouteCollection represents a set of Route instances. + * A RouteCollection represents a set of Route instances as a tree structure. * * When adding a route, it overrides existing routes with the - * same name defined in theinstance or its children and parents. + * same name defined in the instance or its children and parents. * * @author Fabien Potencier + * @author Tobias Schultze * * @api */ @@ -55,7 +56,7 @@ class RouteCollection implements \IteratorAggregate /** * Gets the parent RouteCollection. * - * @return RouteCollection The parent RouteCollection + * @return RouteCollection|null The parent RouteCollection or null when it's the root */ public function getParent() { @@ -63,17 +64,22 @@ class RouteCollection implements \IteratorAggregate } /** - * Sets the parent RouteCollection. + * Gets the root RouteCollection of the tree. * - * @param RouteCollection $parent The parent RouteCollection + * @return RouteCollection The root RouteCollection */ - public function setParent(RouteCollection $parent) + public function getRoot() { - $this->parent = $parent; + $parent = $this; + while ($parent->getParent()) { + $parent = $parent->getParent(); + } + + return $parent; } /** - * Gets the current RouteCollection as an Iterator. + * Gets the current RouteCollection as an Iterator that includes all routes and child route collections. * * @return \ArrayIterator An \ArrayIterator interface */ @@ -95,23 +101,16 @@ class RouteCollection implements \IteratorAggregate public function add($name, Route $route) { if (!preg_match('/^[a-z0-9A-Z_.]+$/', $name)) { - throw new \InvalidArgumentException(sprintf('Name "%s" contains non valid characters for a route name.', $name)); + throw new \InvalidArgumentException(sprintf('The provided route name "%s" contains non valid characters. A route name must only contain digits (0-9), letters (a-z and A-Z), underscores (_) and dots (.).', $name)); } - $parent = $this; - while ($parent->getParent()) { - $parent = $parent->getParent(); - } - - if ($parent) { - $parent->remove($name); - } + $this->remove($name); $this->routes[$name] = $route; } /** - * Returns the array of routes. + * Returns all routes in this collection and its children. * * @return array An array of routes */ @@ -130,45 +129,39 @@ class RouteCollection implements \IteratorAggregate } /** - * Gets a route by name. + * Gets a route by name defined in this collection or its children. * - * @param string $name The route name + * @param string $name The route name * - * @return Route $route A Route instance + * @return Route|null A Route instance or null when not found */ public function get($name) { - // get the latest defined route - foreach (array_reverse($this->routes) as $routes) { - if (!$routes instanceof RouteCollection) { - continue; - } + if (isset($this->routes[$name])) { + return $this->routes[$name] instanceof RouteCollection ? null : $this->routes[$name]; + } - if (null !== $route = $routes->get($name)) { + foreach ($this->routes as $routes) { + if ($routes instanceof RouteCollection && null !== $route = $routes->get($name)) { return $route; } } - if (isset($this->routes[$name])) { - return $this->routes[$name]; - } + return null; } /** - * Removes a route by name. + * Removes a route or an array of routes by name from all connected + * collections (this instance and all parents and children). * - * @param string $name The route name + * @param string|array $name The route name or an array of route names */ public function remove($name) { - if (isset($this->routes[$name])) { - unset($this->routes[$name]); - } + $root = $this->getRoot(); - foreach ($this->routes as $routes) { - if ($routes instanceof RouteCollection) { - $routes->remove($name); - } + foreach ((array) $name as $n) { + $root->removeRecursively($n); } } @@ -179,19 +172,27 @@ class RouteCollection implements \IteratorAggregate * @param string $prefix An optional prefix to add before each pattern of the route collection * @param array $defaults An array of default values * @param array $requirements An array of requirements + * @param array $options An array of options + * + * @throws \InvalidArgumentException When the RouteCollection already exists in the tree * * @api */ - public function addCollection(RouteCollection $collection, $prefix = '', $defaults = array(), $requirements = array()) + public function addCollection(RouteCollection $collection, $prefix = '', $defaults = array(), $requirements = array(), $options = array()) { - $collection->setParent($this); - $collection->addPrefix($prefix, $defaults, $requirements); - - // remove all routes with the same name in all existing collections - foreach (array_keys($collection->all()) as $name) { - $this->remove($name); + // prevent infinite loops by recursive referencing + $root = $this->getRoot(); + if ($root === $collection || $root->hasCollection($collection)) { + throw new \InvalidArgumentException('The RouteCollection already exists in the tree.'); } + // remove all routes with the same names in all existing collections + $this->remove(array_keys($collection->all())); + + $collection->setParent($this); + // the sub-collection must have the prefix of the parent (current instance) prepended because it does not + // necessarily already have it applied (depending on the order RouteCollections are added to each other) + $collection->addPrefix($this->getPrefix() . $prefix, $defaults, $requirements, $options); $this->routes[] = $collection; } @@ -201,32 +202,43 @@ class RouteCollection implements \IteratorAggregate * @param string $prefix An optional prefix to add before each pattern of the route collection * @param array $defaults An array of default values * @param array $requirements An array of requirements + * @param array $options An array of options * * @api */ - public function addPrefix($prefix, $defaults = array(), $requirements = array()) + public function addPrefix($prefix, $defaults = array(), $requirements = array(), $options = array()) { // a prefix must not end with a slash $prefix = rtrim($prefix, '/'); + if ('' === $prefix && empty($defaults) && empty($requirements) && empty($options)) { + return; + } + // a prefix must start with a slash - if ($prefix && '/' !== $prefix[0]) { + if ('' !== $prefix && '/' !== $prefix[0]) { $prefix = '/'.$prefix; } $this->prefix = $prefix.$this->prefix; - foreach ($this->routes as $name => $route) { + foreach ($this->routes as $route) { if ($route instanceof RouteCollection) { - $route->addPrefix($prefix, $defaults, $requirements); + $route->addPrefix($prefix, $defaults, $requirements, $options); } else { $route->setPattern($prefix.$route->getPattern()); $route->addDefaults($defaults); $route->addRequirements($requirements); + $route->addOptions($options); } } } + /** + * Returns the prefix that may contain placeholders. + * + * @return string The prefix + */ public function getPrefix() { return $this->prefix; @@ -258,4 +270,60 @@ class RouteCollection implements \IteratorAggregate { $this->resources[] = $resource; } + + /** + * Sets the parent RouteCollection. It's only used internally from one RouteCollection + * to another. It makes no sense to be available as part of the public API. + * + * @param RouteCollection $parent The parent RouteCollection + */ + private function setParent(RouteCollection $parent) + { + $this->parent = $parent; + } + + /** + * Removes a route by name from this collection and its children recursively. + * + * @param string $name The route name + * + * @return Boolean true when found + */ + private function removeRecursively($name) + { + // It is ensured by the adders (->add and ->addCollection) that there can + // only be one route per name in all connected collections. So we can stop + // interating recursively on the first hit. + if (isset($this->routes[$name])) { + unset($this->routes[$name]); + + return true; + } + + foreach ($this->routes as $routes) { + if ($routes instanceof RouteCollection && $routes->removeRecursively($name)) { + return true; + } + } + + return false; + } + + /** + * Checks whether the given RouteCollection is already set in any child of the current instance. + * + * @param RouteCollection $collection A RouteCollection instance + * + * @return Boolean + */ + private function hasCollection(RouteCollection $collection) + { + foreach ($this->routes as $routes) { + if ($routes === $collection || $routes instanceof RouteCollection && $routes->hasCollection($collection)) { + return true; + } + } + + return false; + } } diff --git a/core/vendor/Symfony/Component/Routing/RouteCompiler.php b/core/vendor/Symfony/Component/Routing/RouteCompiler.php index 5cebd22..dc5e5e6 100644 --- a/core/vendor/Symfony/Component/Routing/RouteCompiler.php +++ b/core/vendor/Symfony/Component/Routing/RouteCompiler.php @@ -18,6 +18,8 @@ namespace Symfony\Component\Routing; */ class RouteCompiler implements RouteCompilerInterface { + const REGEX_DELIMITER = '#'; + /** * Compiles the current route instance. * @@ -47,7 +49,7 @@ class RouteCompiler implements RouteCompilerInterface if ($pos !== $len) { $seps[] = $pattern[$pos]; } - $regexp = sprintf('[^%s]+?', preg_quote(implode('', array_unique($seps)), '#')); + $regexp = sprintf('[^%s]+?', preg_quote(implode('', array_unique($seps)), self::REGEX_DELIMITER)); } $tokens[] = array('variable', $match[0][0][0], $regexp, $var); @@ -66,7 +68,8 @@ class RouteCompiler implements RouteCompilerInterface // find the first optional token $firstOptional = INF; for ($i = count($tokens) - 1; $i >= 0; $i--) { - if ('variable' === $tokens[$i][0] && $route->hasDefault($tokens[$i][3])) { + $token = $tokens[$i]; + if ('variable' === $token[0] && $route->hasDefault($token[3])) { $firstOptional = $i; } else { break; @@ -74,36 +77,56 @@ class RouteCompiler implements RouteCompilerInterface } // compute the matching regexp - $regex = ''; - $indent = 1; - if (1 === count($tokens) && 0 === $firstOptional) { - $token = $tokens[0]; - ++$indent; - $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?:\n", preg_quote($token[1], '#')); - $regex .= str_repeat(' ', $indent * 4).sprintf("(?P<%s>%s)\n", $token[3], $token[2]); - } else { - foreach ($tokens as $i => $token) { - if ('text' === $token[0]) { - $regex .= str_repeat(' ', $indent * 4).preg_quote($token[1], '#')."\n"; - } else { - if ($i >= $firstOptional) { - $regex .= str_repeat(' ', $indent * 4)."(?:\n"; - ++$indent; - } - $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?P<%s>%s)\n", preg_quote($token[1], '#'), $token[3], $token[2]); - } - } - } - while (--$indent) { - $regex .= str_repeat(' ', $indent * 4).")?\n"; + $regexp = ''; + for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) { + $regexp .= $this->computeRegexp($tokens, $i, $firstOptional); } return new CompiledRoute( $route, 'text' === $tokens[0][0] ? $tokens[0][1] : '', - sprintf("#^\n%s$#xs", $regex), + self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s', array_reverse($tokens), $variables ); } + + /** + * Computes the regexp used to match a specific token. It can be static text or a subpattern. + * + * @param array $tokens The route tokens + * @param integer $index The index of the current token + * @param integer $firstOptional The index of the first optional token + * + * @return string The regexp pattern for a single token + */ + private function computeRegexp(array $tokens, $index, $firstOptional) + { + $token = $tokens[$index]; + if('text' === $token[0]) { + // Text tokens + return preg_quote($token[1], self::REGEX_DELIMITER); + } else { + // Variable tokens + if (0 === $index && 0 === $firstOptional && 1 == count($tokens)) { + // When the only token is an optional variable token, the separator is required + return sprintf('%s(?<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); + } else { + $regexp = sprintf('%s(?<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); + if ($index >= $firstOptional) { + // Enclose each optional token in a subpattern to make it optional. + // "?:" means it is non-capturing, i.e. the portion of the subject string that + // matched the optional subpattern is not passed back. + $regexp = "(?:$regexp"; + $nbTokens = count($tokens); + if ($nbTokens - 1 == $index) { + // Close the optional subpatterns + $regexp .= str_repeat(")?", $nbTokens - $firstOptional); + } + } + + return $regexp; + } + } + } } diff --git a/core/vendor/Symfony/Component/Routing/RouteCompilerInterface.php b/core/vendor/Symfony/Component/Routing/RouteCompilerInterface.php index e0ad86b..5193665 100644 --- a/core/vendor/Symfony/Component/Routing/RouteCompilerInterface.php +++ b/core/vendor/Symfony/Component/Routing/RouteCompilerInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Routing; /** - * RouteCompilerInterface is the interface that all RouteCompiler classes must implements. + * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. * * @author Fabien Potencier */ diff --git a/core/vendor/Symfony/Component/Routing/Tests/Annotation/RouteTest.php b/core/vendor/Symfony/Component/Routing/Tests/Annotation/RouteTest.php new file mode 100644 index 0000000..dc080db --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Annotation/RouteTest.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Annotation; + +use Symfony\Component\Routing\Annotation\Route; + +class RouteTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \BadMethodCallException + */ + public function testInvalidRouteParameter() + { + $route = new Route(array('foo' => 'bar')); + } + + /** + * @dataProvider getValidParameters + */ + public function testRouteParameters($parameter, $value, $getter) + { + $route = new Route(array($parameter => $value)); + $this->assertEquals($route->$getter(), $value); + } + + public function getValidParameters() + { + return array( + array('value', '/Blog', 'getPattern'), + array('requirements', array('_method' => 'GET'), 'getRequirements'), + array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'), + array('name', 'blog_index', 'getName'), + array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults') + ); + } +} + diff --git a/core/vendor/Symfony/Component/Routing/Tests/CompiledRouteTest.php b/core/vendor/Symfony/Component/Routing/Tests/CompiledRouteTest.php new file mode 100644 index 0000000..d0e6186 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/CompiledRouteTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests; + +use Symfony\Component\Routing\CompiledRoute; +use Symfony\Component\Routing\Route; + +class CompiledRouteTest extends \PHPUnit_Framework_TestCase +{ + public function testAccessors() + { + $route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar')); + + $compiled = new CompiledRoute($route, 'prefix', 'regex', array('tokens'), array('variables')); + $this->assertEquals($route, $compiled->getRoute(), '__construct() takes a route as its first argument'); + $this->assertEquals('prefix', $compiled->getStaticPrefix(), '__construct() takes a static prefix as its second argument'); + $this->assertEquals('regex', $compiled->getRegex(), '__construct() takes a regexp as its third argument'); + $this->assertEquals(array('tokens'), $compiled->getTokens(), '__construct() takes an array of tokens as its fourth argument'); + $this->assertEquals(array('variables'), $compiled->getVariables(), '__construct() takes an array of variables as its fifth argument'); + } + + public function testgetPatterngetDefaultsgetOptionsgetRequirements() + { + $route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar')); + + $compiled = new CompiledRoute($route, 'prefix', 'regex', array('tokens'), array('variables')); + $this->assertEquals('/{foo}', $compiled->getPattern(), '->getPattern() returns the route pattern'); + $this->assertEquals(array('foo' => 'bar'), $compiled->getDefaults(), '->getDefaults() returns the route defaults'); + $this->assertEquals(array('foo' => '\d+'), $compiled->getRequirements(), '->getRequirements() returns the route requirements'); + $this->assertEquals(array_merge(array( + 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', + ), array('foo' => 'bar')), $compiled->getOptions(), '->getOptions() returns the route options'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php new file mode 100644 index 0000000..56bcab2 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses; + +abstract class AbstractClass +{ +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php new file mode 100644 index 0000000..320dc35 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses; + +class FooClass +{ +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php new file mode 100644 index 0000000..c2601d4 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures; + +use Symfony\Component\Routing\Loader\XmlFileLoader; + +/** + * XmlFileLoader with schema validation turned off + */ +class CustomXmlFileLoader extends XmlFileLoader +{ + protected function validate(\DOMDocument $dom) + { + return true; + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php new file mode 100644 index 0000000..e95c1f2 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures; + +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; + +/** + * @author Fabien Potencier + */ +class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface +{ + public function redirect($path, $route, $scheme = null) + { + return array( + '_controller' => 'Some controller reference...', + 'path' => $path, + 'scheme' => $scheme, + ); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/annotated.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/annotated.php new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache new file mode 100644 index 0000000..a937998 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache @@ -0,0 +1,71 @@ +# skip "real" requests +RewriteCond %{REQUEST_FILENAME} -f +RewriteRule .* - [QSA,L] + +# foo +RewriteCond %{REQUEST_URI} ^/foo/(baz|symfony)$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:foo,E=_ROUTING_bar:%1,E=_ROUTING_def:test] + +# bar +RewriteCond %{REQUEST_URI} ^/bar/([^/]+?)$ +RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC] +RewriteRule .* - [S=1,E=_ROUTING__allow_GET:1,E=_ROUTING__allow_HEAD:1] +RewriteCond %{REQUEST_URI} ^/bar/([^/]+?)$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:bar,E=_ROUTING_foo:%1] + +# baragain +RewriteCond %{REQUEST_URI} ^/baragain/([^/]+?)$ +RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$ [NC] +RewriteRule .* - [S=1,E=_ROUTING__allow_GET:1,E=_ROUTING__allow_POST:1,E=_ROUTING__allow_HEAD:1] +RewriteCond %{REQUEST_URI} ^/baragain/([^/]+?)$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baragain,E=_ROUTING_foo:%1] + +# baz +RewriteCond %{REQUEST_URI} ^/test/baz$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz] + +# baz2 +RewriteCond %{REQUEST_URI} ^/test/baz\.html$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz2] + +# baz3 +RewriteCond %{REQUEST_URI} ^/test/baz3$ +RewriteRule .* $0/ [QSA,L,R=301] +RewriteCond %{REQUEST_URI} ^/test/baz3/$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz3] + +# baz4 +RewriteCond %{REQUEST_URI} ^/test/([^/]+?)$ +RewriteRule .* $0/ [QSA,L,R=301] +RewriteCond %{REQUEST_URI} ^/test/([^/]+?)/$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz4,E=_ROUTING_foo:%1] + +# baz5 +RewriteCond %{REQUEST_URI} ^/test/([^/]+?)/$ +RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC] +RewriteRule .* - [S=2,E=_ROUTING__allow_GET:1,E=_ROUTING__allow_HEAD:1] +RewriteCond %{REQUEST_URI} ^/test/([^/]+?)$ +RewriteRule .* $0/ [QSA,L,R=301] +RewriteCond %{REQUEST_URI} ^/test/([^/]+?)/$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz5,E=_ROUTING_foo:%1] + +# baz5unsafe +RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]+?)/$ +RewriteCond %{REQUEST_METHOD} !^(POST)$ [NC] +RewriteRule .* - [S=1,E=_ROUTING__allow_POST:1] +RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]+?)/$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz5unsafe,E=_ROUTING_foo:%1] + +# baz6 +RewriteCond %{REQUEST_URI} ^/test/baz$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz6,E=_ROUTING_foo:bar\ baz] + +# baz7 +RewriteCond %{REQUEST_URI} ^/te\ st/baz$ +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz7] + +# 405 Method Not Allowed +RewriteCond %{_ROUTING__allow_GET} !-z [OR] +RewriteCond %{_ROUTING__allow_HEAD} !-z [OR] +RewriteCond %{_ROUTING__allow_POST} !-z +RewriteRule .* app.php [QSA,L] diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php new file mode 100644 index 0000000..2c764d0 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -0,0 +1,219 @@ +context = $context; + } + + public function match($pathinfo) + { + $allow = array(); + $pathinfo = rawurldecode($pathinfo); + + // foo + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?baz|symfony)$#s', $pathinfo, $matches)) { + return array_merge($this->mergeDefaults($matches, array ( 'def' => 'test',)), array('_route' => 'foo')); + } + + // bar + if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?[^/]+?)$#s', $pathinfo, $matches)) { + if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { + $allow = array_merge($allow, array('GET', 'HEAD')); + goto not_bar; + } + $matches['_route'] = 'bar'; + return $matches; + } + not_bar: + + // barhead + if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?[^/]+?)$#s', $pathinfo, $matches)) { + if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { + $allow = array_merge($allow, array('GET', 'HEAD')); + goto not_barhead; + } + $matches['_route'] = 'barhead'; + return $matches; + } + not_barhead: + + // baz + if ($pathinfo === '/test/baz') { + return array('_route' => 'baz'); + } + + // baz2 + if ($pathinfo === '/test/baz.html') { + return array('_route' => 'baz2'); + } + + // baz3 + if ($pathinfo === '/test/baz3/') { + return array('_route' => 'baz3'); + } + + // baz4 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?[^/]+?)/$#s', $pathinfo, $matches)) { + $matches['_route'] = 'baz4'; + return $matches; + } + + // baz5 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?[^/]+?)/$#s', $pathinfo, $matches)) { + if ($this->context->getMethod() != 'POST') { + $allow[] = 'POST'; + goto not_baz5; + } + $matches['_route'] = 'baz5'; + return $matches; + } + not_baz5: + + // baz.baz6 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?[^/]+?)/$#s', $pathinfo, $matches)) { + if ($this->context->getMethod() != 'PUT') { + $allow[] = 'PUT'; + goto not_bazbaz6; + } + $matches['_route'] = 'baz.baz6'; + return $matches; + } + not_bazbaz6: + + // foofoo + if ($pathinfo === '/foofoo') { + return array ( 'def' => 'test', '_route' => 'foofoo',); + } + + // quoter + if (preg_match('#^/(?[\']+)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'quoter'; + return $matches; + } + + // space + if ($pathinfo === '/spa ce') { + return array('_route' => 'space'); + } + + if (0 === strpos($pathinfo, '/a')) { + if (0 === strpos($pathinfo, '/a/b\'b')) { + // foo1 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo1'; + return $matches; + } + + // bar1 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'bar1'; + return $matches; + } + + } + + // overriden + if (preg_match('#^/a/(?.*)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'overriden'; + return $matches; + } + + if (0 === strpos($pathinfo, '/a/b\'b')) { + // foo2 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo2'; + return $matches; + } + + // bar2 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'bar2'; + return $matches; + } + + } + + } + + if (0 === strpos($pathinfo, '/multi')) { + // helloWorld + if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?[^/]+?))?$#s', $pathinfo, $matches)) { + return array_merge($this->mergeDefaults($matches, array ( 'who' => 'World!',)), array('_route' => 'helloWorld')); + } + + // overriden2 + if ($pathinfo === '/multi/new') { + return array('_route' => 'overriden2'); + } + + // hey + if ($pathinfo === '/multi/hey/') { + return array('_route' => 'hey'); + } + + } + + // foo3 + if (preg_match('#^/(?<_locale>[^/]+?)/b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo3'; + return $matches; + } + + // bar3 + if (preg_match('#^/(?<_locale>[^/]+?)/b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'bar3'; + return $matches; + } + + // ababa + if ($pathinfo === '/ababa') { + return array('_route' => 'ababa'); + } + + // foo4 + if (0 === strpos($pathinfo, '/aba') && preg_match('#^/aba/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo4'; + return $matches; + } + + if (0 === strpos($pathinfo, '/a')) { + // a + if ($pathinfo === '/a/a...') { + return array('_route' => 'a'); + } + + if (0 === strpos($pathinfo, '/a/b')) { + // b + if (preg_match('#^/a/b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'b'; + return $matches; + } + + // c + if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'c'; + return $matches; + } + + } + + } + + throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache new file mode 100644 index 0000000..d16ab97 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache @@ -0,0 +1,7 @@ +# skip "real" requests +RewriteCond %{REQUEST_FILENAME} -f +RewriteRule .* - [QSA,L] + +# foo +RewriteCond %{REQUEST_URI} ^/foo$ +RewriteRule .* ap\ p_d\ ev.php [QSA,L,E=_ROUTING__route:foo] diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php new file mode 100644 index 0000000..4b9af5c --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -0,0 +1,244 @@ +context = $context; + } + + public function match($pathinfo) + { + $allow = array(); + $pathinfo = rawurldecode($pathinfo); + + // foo + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?baz|symfony)$#s', $pathinfo, $matches)) { + return array_merge($this->mergeDefaults($matches, array ( 'def' => 'test',)), array('_route' => 'foo')); + } + + // bar + if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?[^/]+?)$#s', $pathinfo, $matches)) { + if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { + $allow = array_merge($allow, array('GET', 'HEAD')); + goto not_bar; + } + $matches['_route'] = 'bar'; + return $matches; + } + not_bar: + + // barhead + if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?[^/]+?)$#s', $pathinfo, $matches)) { + if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { + $allow = array_merge($allow, array('GET', 'HEAD')); + goto not_barhead; + } + $matches['_route'] = 'barhead'; + return $matches; + } + not_barhead: + + // baz + if ($pathinfo === '/test/baz') { + return array('_route' => 'baz'); + } + + // baz2 + if ($pathinfo === '/test/baz.html') { + return array('_route' => 'baz2'); + } + + // baz3 + if (rtrim($pathinfo, '/') === '/test/baz3') { + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'baz3'); + } + return array('_route' => 'baz3'); + } + + // baz4 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?[^/]+?)/?$#s', $pathinfo, $matches)) { + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'baz4'); + } + $matches['_route'] = 'baz4'; + return $matches; + } + + // baz5 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?[^/]+?)/$#s', $pathinfo, $matches)) { + if ($this->context->getMethod() != 'POST') { + $allow[] = 'POST'; + goto not_baz5; + } + $matches['_route'] = 'baz5'; + return $matches; + } + not_baz5: + + // baz.baz6 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?[^/]+?)/$#s', $pathinfo, $matches)) { + if ($this->context->getMethod() != 'PUT') { + $allow[] = 'PUT'; + goto not_bazbaz6; + } + $matches['_route'] = 'baz.baz6'; + return $matches; + } + not_bazbaz6: + + // foofoo + if ($pathinfo === '/foofoo') { + return array ( 'def' => 'test', '_route' => 'foofoo',); + } + + // quoter + if (preg_match('#^/(?[\']+)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'quoter'; + return $matches; + } + + // space + if ($pathinfo === '/spa ce') { + return array('_route' => 'space'); + } + + if (0 === strpos($pathinfo, '/a')) { + if (0 === strpos($pathinfo, '/a/b\'b')) { + // foo1 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo1'; + return $matches; + } + + // bar1 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'bar1'; + return $matches; + } + + } + + // overriden + if (preg_match('#^/a/(?.*)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'overriden'; + return $matches; + } + + if (0 === strpos($pathinfo, '/a/b\'b')) { + // foo2 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo2'; + return $matches; + } + + // bar2 + if (preg_match('#^/a/b\'b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'bar2'; + return $matches; + } + + } + + } + + if (0 === strpos($pathinfo, '/multi')) { + // helloWorld + if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?[^/]+?))?$#s', $pathinfo, $matches)) { + return array_merge($this->mergeDefaults($matches, array ( 'who' => 'World!',)), array('_route' => 'helloWorld')); + } + + // overriden2 + if ($pathinfo === '/multi/new') { + return array('_route' => 'overriden2'); + } + + // hey + if (rtrim($pathinfo, '/') === '/multi/hey') { + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'hey'); + } + return array('_route' => 'hey'); + } + + } + + // foo3 + if (preg_match('#^/(?<_locale>[^/]+?)/b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo3'; + return $matches; + } + + // bar3 + if (preg_match('#^/(?<_locale>[^/]+?)/b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'bar3'; + return $matches; + } + + // ababa + if ($pathinfo === '/ababa') { + return array('_route' => 'ababa'); + } + + // foo4 + if (0 === strpos($pathinfo, '/aba') && preg_match('#^/aba/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'foo4'; + return $matches; + } + + if (0 === strpos($pathinfo, '/a')) { + // a + if ($pathinfo === '/a/a...') { + return array('_route' => 'a'); + } + + if (0 === strpos($pathinfo, '/a/b')) { + // b + if (preg_match('#^/a/b/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'b'; + return $matches; + } + + // c + if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'c'; + return $matches; + } + + } + + } + + // secure + if ($pathinfo === '/secure') { + if ($this->context->getScheme() !== 'https') { + return $this->redirect($pathinfo, 'secure', 'https'); + } + return array('_route' => 'secure'); + } + + // nonsecure + if ($pathinfo === '/nonsecure') { + if ($this->context->getScheme() !== 'http') { + return $this->redirect($pathinfo, 'nonsecure', 'http'); + } + return array('_route' => 'nonsecure'); + } + + throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php new file mode 100644 index 0000000..3373931 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php @@ -0,0 +1,44 @@ +context = $context; + } + + public function match($pathinfo) + { + $allow = array(); + $pathinfo = rawurldecode($pathinfo); + + if (0 === strpos($pathinfo, '/rootprefix')) { + // static + if ($pathinfo === '/rootprefix/test') { + return array('_route' => 'static'); + } + + // dynamic + if (preg_match('#^/rootprefix/(?[^/]+?)$#s', $pathinfo, $matches)) { + $matches['_route'] = 'dynamic'; + return $matches; + } + + } + + throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/empty.yml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/empty.yml new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/foo.xml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/foo.xml new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/foo1.xml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/foo1.xml new file mode 100644 index 0000000..e69de29 diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/incomplete.yml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/incomplete.yml new file mode 100644 index 0000000..df64d32 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/incomplete.yml @@ -0,0 +1,2 @@ +blog_show: + defaults: { _controller: MyBlogBundle:Blog:show } diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml new file mode 100644 index 0000000..a9b72f3 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml @@ -0,0 +1,12 @@ + + + + + + MyBundle:Blog:show + GET + + + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml @@ -0,0 +1 @@ +foo diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml new file mode 100644 index 0000000..015e270 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml @@ -0,0 +1,3 @@ +someroute: + resource: path/to/some.yml + name_prefix: test_ diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml new file mode 100644 index 0000000..863ef03 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml @@ -0,0 +1,8 @@ + + + + + bar + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml new file mode 100644 index 0000000..cba82f3 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml @@ -0,0 +1,13 @@ + + + + + + MyBundle:Blog:show + GET + + baz + + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.php b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.php new file mode 100644 index 0000000..0d1d3a7 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.php @@ -0,0 +1,13 @@ +add('blog_show', new Route( + '/blog/{slug}', + array('_controller' => 'MyBlogBundle:Blog:show'), + array(), + array('compiler_class' => 'RouteCompiler') +)); + +return $collection; diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml new file mode 100644 index 0000000..fdb3807 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml @@ -0,0 +1,12 @@ + + + + + + MyBundle:Blog:show + GET + + + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.yml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.yml new file mode 100644 index 0000000..e645d9b --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validpattern.yml @@ -0,0 +1,6 @@ +blog_show: + pattern: /blog/{slug} + defaults: { _controller: MyBlogBundle:Blog:show } + options: + compiler_class: RouteCompiler + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validresource.xml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validresource.xml new file mode 100644 index 0000000..14ac0fc --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validresource.xml @@ -0,0 +1,12 @@ + + + + + + foo + \d+ + + + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validresource.yml b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validresource.yml new file mode 100644 index 0000000..e66f376 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Fixtures/validresource.yml @@ -0,0 +1,6 @@ +blog_show: + resource: validpattern.yml + prefix: /{foo} + defaults: { 'foo': 'foo' } + requirements: { 'foo': '\d+' } + options: { 'foo': 'bar' } diff --git a/core/vendor/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php b/core/vendor/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php new file mode 100644 index 0000000..7a3dabe --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Generator\Dumper\PhpGeneratorDumper; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; +use Symfony\Component\Routing\RequestContext; + +class PhpGeneratorDumperTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var RouteCollection + */ + private $routeCollection; + + /** + * @var PhpGeneratorDumper + */ + private $generatorDumper; + + /** + * @var string + */ + private $testTmpFilepath; + + protected function setUp() + { + parent::setUp(); + + $this->routeCollection = new RouteCollection(); + $this->generatorDumper = new PhpGeneratorDumper($this->routeCollection, new RequestContext()); + $this->testTmpFilepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.'php_generator.php'; + @unlink($this->testTmpFilepath); + } + + protected function tearDown() + { + parent::tearDown(); + + @unlink($this->testTmpFilepath); + + $this->routeCollection = null; + $this->generatorDumper = null; + $this->testTmpFilepath = null; + } + + public function testDumpWithRoutes() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}')); + $this->routeCollection->add('Test2', new Route('/testing2')); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + include ($this->testTmpFilepath); + + $projectUrlGenerator = new \ProjectUrlGenerator(new RequestContext('/app.php')); + + $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), true); + $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), true); + $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), false); + $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), false); + + $this->assertEquals($absoluteUrlWithParameter, 'http://localhost/app.php/testing/bar'); + $this->assertEquals($absoluteUrlWithoutParameter, 'http://localhost/app.php/testing2'); + $this->assertEquals($relativeUrlWithParameter, '/app.php/testing/bar'); + $this->assertEquals($relativeUrlWithoutParameter, '/app.php/testing2'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testDumpWithoutRoutes() + { + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'WithoutRoutesUrlGenerator'))); + include ($this->testTmpFilepath); + + $projectUrlGenerator = new \WithoutRoutesUrlGenerator(new RequestContext('/app.php')); + + $projectUrlGenerator->generate('Test', array()); + } + + /** + * @expectedException Symfony\Component\Routing\Exception\RouteNotFoundException + */ + public function testGenerateNonExistingRoute() + { + $this->routeCollection->add('Test', new Route('/test')); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'NonExistingRoutesUrlGenerator'))); + include ($this->testTmpFilepath); + + $projectUrlGenerator = new \NonExistingRoutesUrlGenerator(new RequestContext()); + $url = $projectUrlGenerator->generate('NonExisting', array()); + } + + public function testDumpForRouteWithDefaults() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}', array('foo' => 'bar'))); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'DefaultRoutesUrlGenerator'))); + include ($this->testTmpFilepath); + + $projectUrlGenerator = new \DefaultRoutesUrlGenerator(new RequestContext()); + $url = $projectUrlGenerator->generate('Test', array()); + + $this->assertEquals($url, '/testing'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php b/core/vendor/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php new file mode 100644 index 0000000..e4834e5 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php @@ -0,0 +1,228 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Generator; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\Generator\UrlGenerator; +use Symfony\Component\Routing\RequestContext; + +class UrlGeneratorTest extends \PHPUnit_Framework_TestCase +{ + public function testAbsoluteUrlWithPort80() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes)->generate('test', array(), true); + + $this->assertEquals('http://localhost/app.php/testing', $url); + } + + public function testAbsoluteSecureUrlWithPort443() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes, array('scheme' => 'https'))->generate('test', array(), true); + + $this->assertEquals('https://localhost/app.php/testing', $url); + } + + public function testAbsoluteUrlWithNonStandardPort() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes, array('httpPort' => 8080))->generate('test', array(), true); + + $this->assertEquals('http://localhost:8080/app.php/testing', $url); + } + + public function testAbsoluteSecureUrlWithNonStandardPort() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes, array('httpsPort' => 8080, 'scheme' => 'https'))->generate('test', array(), true); + + $this->assertEquals('https://localhost:8080/app.php/testing', $url); + } + + public function testRelativeUrlWithoutParameters() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes)->generate('test', array(), false); + + $this->assertEquals('/app.php/testing', $url); + } + + public function testRelativeUrlWithParameter() + { + $routes = $this->getRoutes('test', new Route('/testing/{foo}')); + $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), false); + + $this->assertEquals('/app.php/testing/bar', $url); + } + + public function testRelativeUrlWithNullParameter() + { + $routes = $this->getRoutes('test', new Route('/testing.{format}', array('format' => null))); + $url = $this->getGenerator($routes)->generate('test', array(), false); + + $this->assertEquals('/app.php/testing', $url); + } + + public function testRelativeUrlWithNullParameterButNotOptional() + { + $routes = $this->getRoutes('test', new Route('/testing/{foo}/bar', array('foo' => null))); + $url = $this->getGenerator($routes)->generate('test', array(), false); + + $this->assertEquals('/app.php/testing//bar', $url); + } + + public function testRelativeUrlWithOptionalZeroParameter() + { + $routes = $this->getRoutes('test', new Route('/testing/{page}')); + $url = $this->getGenerator($routes)->generate('test', array('page' => 0), false); + + $this->assertEquals('/app.php/testing/0', $url); + } + + public function testRelativeUrlWithExtraParameters() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), false); + + $this->assertEquals('/app.php/testing?foo=bar', $url); + } + + public function testAbsoluteUrlWithExtraParameters() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true); + + $this->assertEquals('http://localhost/app.php/testing?foo=bar', $url); + } + + public function testUrlWithNullExtraParameters() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $url = $this->getGenerator($routes)->generate('test', array('foo' => null), true); + + $this->assertEquals('http://localhost/app.php/testing', $url); + } + + public function testUrlWithExtraParametersFromGlobals() + { + $routes = $this->getRoutes('test', new Route('/testing')); + $generator = $this->getGenerator($routes); + $context = new RequestContext('/app.php'); + $context->setParameter('bar', 'bar'); + $generator->setContext($context); + $url = $generator->generate('test', array('foo' => 'bar')); + + $this->assertEquals('/app.php/testing?foo=bar', $url); + } + + public function testUrlWithGlobalParameter() + { + $routes = $this->getRoutes('test', new Route('/testing/{foo}')); + $generator = $this->getGenerator($routes); + $context = new RequestContext('/app.php'); + $context->setParameter('foo', 'bar'); + $generator->setContext($context); + $url = $generator->generate('test', array()); + + $this->assertEquals('/app.php/testing/bar', $url); + } + + /** + * @expectedException Symfony\Component\Routing\Exception\RouteNotFoundException + */ + public function testGenerateWithoutRoutes() + { + $routes = $this->getRoutes('foo', new Route('/testing/{foo}')); + $this->getGenerator($routes)->generate('test', array(), true); + } + + /** + * @expectedException Symfony\Component\Routing\Exception\MissingMandatoryParametersException + */ + public function testGenerateForRouteWithoutMandatoryParameter() + { + $routes = $this->getRoutes('test', new Route('/testing/{foo}')); + $this->getGenerator($routes)->generate('test', array(), true); + } + + /** + * @expectedException Symfony\Component\Routing\Exception\InvalidParameterException + */ + public function testGenerateForRouteWithInvalidOptionalParameter() + { + $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); + $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true); + } + + /** + * @expectedException Symfony\Component\Routing\Exception\InvalidParameterException + */ + public function testGenerateForRouteWithInvalidManditoryParameter() + { + $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => 'd+'))); + $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true); + } + + public function testSchemeRequirementDoesNothingIfSameCurrentScheme() + { + $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http'))); + $this->assertEquals('/app.php/', $this->getGenerator($routes)->generate('test')); + + $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'https'))); + $this->assertEquals('/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test')); + } + + public function testSchemeRequirementForcesAbsoluteUrl() + { + $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'https'))); + $this->assertEquals('https://localhost/app.php/', $this->getGenerator($routes)->generate('test')); + + $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http'))); + $this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test')); + } + + public function testNoTrailingSlashForMultipleOptionalParameters() + { + $routes = $this->getRoutes('test', new Route('/category/{slug1}/{slug2}/{slug3}', array('slug2' => null, 'slug3' => null))); + + $this->assertEquals('/app.php/category/foo', $this->getGenerator($routes)->generate('test', array('slug1' => 'foo'))); + } + + public function testWithAnIntegerAsADefaultValue() + { + $routes = $this->getRoutes('test', new Route('/{default}', array('default' => 0))); + + $this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', array('default' => 'foo'))); + } + + protected function getGenerator(RouteCollection $routes, array $parameters = array()) + { + $context = new RequestContext('/app.php'); + foreach ($parameters as $key => $value) { + $method = 'set'.$key; + $context->$method($value); + } + $generator = new UrlGenerator($routes, $context); + + return $generator; + } + + protected function getRoutes($name, Route $route) + { + $routes = new RouteCollection(); + $routes->add($name, $route); + + return $routes; + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php new file mode 100644 index 0000000..a30555b --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + + +abstract class AbstractAnnotationLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Doctrine\\Common\\Version')) { + $this->markTestSkipped('Doctrine is not available.'); + } + } + + public function getReader() + { + return $this->getMockBuilder('Doctrine\Common\Annotations\Reader') + ->disableOriginalConstructor() + ->getMock() + ; + } + + public function getClassLoader($reader) + { + return $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader') + ->setConstructorArgs(array($reader)) + ->getMockForAbstractClass() + ; + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php new file mode 100644 index 0000000..faeacfb --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Routing\Loader\AnnotationClassLoader; + +class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest +{ + protected $loader; + + protected function setUp() + { + parent::setUp(); + + $this->loader = $this->getClassLoader($this->getReader()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLoadMissingClass() + { + $this->loader->load('MissingClass'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLoadAbstractClass() + { + $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\AbstractClass'); + } + + /** + * @covers Symfony\Component\Routing\Loader\AnnotationClassLoader::supports + * @dataProvider provideTestSupportsChecksResource + */ + public function testSupportsChecksResource($resource, $expectedSupports) + { + $this->assertSame($expectedSupports, $this->loader->supports($resource), '->supports() returns true if the resource is loadable'); + } + + public function provideTestSupportsChecksResource() + { + return array( + array('class', true), + array('\fully\qualified\class\name', true), + array('namespaced\class\without\leading\slash', true), + array('ÿClassWithLegalSpecialCharacters', true), + array('5', false), + array('foo.foo', false), + array(null, false), + ); + } + + /** + * @covers Symfony\Component\Routing\Loader\AnnotationClassLoader::supports + */ + public function testSupportsChecksTypeIfSpecified() + { + $this->assertTrue($this->loader->supports('class', 'annotation'), '->supports() checks the resource type if specified'); + $this->assertFalse($this->loader->supports('class', 'foo'), '->supports() checks the resource type if specified'); + } + +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php new file mode 100644 index 0000000..3877eec --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; +use Symfony\Component\Config\FileLocator; + +class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest +{ + protected $loader; + protected $reader; + + protected function setUp() + { + parent::setUp(); + + $this->reader = $this->getReader(); + $this->loader = new AnnotationDirectoryLoader(new FileLocator(), $this->getClassLoader($this->reader)); + } + + public function testLoad() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses'); + } + + /** + * @covers Symfony\Component\Routing\Loader\AnnotationDirectoryLoader::supports + */ + public function testSupports() + { + $fixturesDir = __DIR__.'/../Fixtures'; + + $this->assertTrue($this->loader->supports($fixturesDir), '->supports() returns true if the resource is loadable'); + $this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + + $this->assertTrue($this->loader->supports($fixturesDir, 'annotation'), '->supports() checks the resource type if specified'); + $this->assertFalse($this->loader->supports($fixturesDir, 'foo'), '->supports() checks the resource type if specified'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php new file mode 100644 index 0000000..02d0576 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Routing\Loader\AnnotationFileLoader; +use Symfony\Component\Config\FileLocator; + +class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest +{ + protected $loader; + protected $reader; + + protected function setUp() + { + parent::setUp(); + + $this->reader = $this->getReader(); + $this->loader = new AnnotationFileLoader(new FileLocator(), $this->getClassLoader($this->reader)); + } + + public function testLoad() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php'); + } + + /** + * @covers Symfony\Component\Routing\Loader\AnnotationFileLoader::supports + */ + public function testSupports() + { + $fixture = __DIR__.'/../Fixtures/annotated.php'; + + $this->assertTrue($this->loader->supports($fixture), '->supports() returns true if the resource is loadable'); + $this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + + $this->assertTrue($this->loader->supports($fixture, 'annotation'), '->supports() checks the resource type if specified'); + $this->assertFalse($this->loader->supports($fixture, 'foo'), '->supports() checks the resource type if specified'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php new file mode 100644 index 0000000..6c34fe4 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Routing\Loader\ClosureLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +class ClosureLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\FileLocator')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + /** + * @covers Symfony\Component\Routing\Loader\ClosureLoader::supports + */ + public function testSupports() + { + $loader = new ClosureLoader(); + + $closure = function () {}; + + $this->assertTrue($loader->supports($closure), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + + $this->assertTrue($loader->supports($closure, 'closure'), '->supports() checks the resource type if specified'); + $this->assertFalse($loader->supports($closure, 'foo'), '->supports() checks the resource type if specified'); + } + + /** + * @covers Symfony\Component\Routing\Loader\ClosureLoader::load + */ + public function testLoad() + { + $loader = new ClosureLoader(); + + $route = new Route('/'); + $routes = $loader->load(function () use ($route) + { + $routes = new RouteCollection(); + + $routes->add('foo', $route); + + return $routes; + }); + + $this->assertEquals($route, $routes->get('foo'), '->load() loads a \Closure resource'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php new file mode 100644 index 0000000..f4b30e3 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Routing\Loader\PhpFileLoader; +use Symfony\Component\Routing\Route; + +class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\FileLocator')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + /** + * @covers Symfony\Component\Routing\Loader\PhpFileLoader::supports + */ + public function testSupports() + { + $loader = new PhpFileLoader($this->getMock('Symfony\Component\Config\FileLocator')); + + $this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + + $this->assertTrue($loader->supports('foo.php', 'php'), '->supports() checks the resource type if specified'); + $this->assertFalse($loader->supports('foo.php', 'foo'), '->supports() checks the resource type if specified'); + } + + public function testLoadWithRoute() + { + $loader = new PhpFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $routeCollection = $loader->load('validpattern.php'); + $routes = $routeCollection->all(); + + $this->assertEquals(1, count($routes), 'One route is loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + $route = $routes['blog_show']; + $this->assertEquals('RouteCompiler', $route->getOption('compiler_class')); + } +} + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php new file mode 100644 index 0000000..554ee1a --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Routing\Loader\XmlFileLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\Tests\Fixtures\CustomXmlFileLoader; + +class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\FileLocator')) { + $this->markTestSkipped('The "Config" component is not available'); + } + } + + /** + * @covers Symfony\Component\Routing\Loader\XmlFileLoader::supports + */ + public function testSupports() + { + $loader = new XmlFileLoader($this->getMock('Symfony\Component\Config\FileLocator')); + + $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + + $this->assertTrue($loader->supports('foo.xml', 'xml'), '->supports() checks the resource type if specified'); + $this->assertFalse($loader->supports('foo.xml', 'foo'), '->supports() checks the resource type if specified'); + } + + public function testLoadWithRoute() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $routeCollection = $loader->load('validpattern.xml'); + $routes = $routeCollection->all(); + + $this->assertEquals(1, count($routes), 'One route is loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + $route = $routes['blog_show']; + $this->assertEquals('RouteCompiler', $route->getOption('compiler_class')); + } + + public function testLoadWithImport() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $routeCollection = $loader->load('validresource.xml'); + $routes = $routeCollection->all(); + + $this->assertEquals(1, count($routes), 'One route is loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + $this->assertEquals('foo', $routes['blog_show']->getDefault('foo')); + $this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo')); + $this->assertEquals('bar', $routes['blog_show']->getOption('foo')); + } + + /** + * @expectedException \InvalidArgumentException + * @dataProvider getPathsToInvalidFiles + */ + public function testLoadThrowsExceptionWithInvalidFile($filePath) + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader->load($filePath); + } + + /** + * @expectedException \InvalidArgumentException + * @dataProvider getPathsToInvalidFiles + */ + public function testLoadThrowsExceptionWithInvalidFileEvenWithoutSchemaValidation($filePath) + { + $loader = new CustomXmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader->load($filePath); + } + + public function getPathsToInvalidFiles() + { + return array(array('nonvalidnode.xml'), array('nonvalidroute.xml'), array('nonvalid.xml')); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/core/vendor/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php new file mode 100644 index 0000000..0c870e6 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Routing\Loader\YamlFileLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Config\Resource\FileResource; + +class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\Config\FileLocator')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + if (!class_exists('Symfony\Component\Yaml\Yaml')) { + $this->markTestSkipped('The "Yaml" component is not available'); + } + } + + /** + * @covers Symfony\Component\Routing\Loader\YamlFileLoader::supports + */ + public function testSupports() + { + $loader = new YamlFileLoader($this->getMock('Symfony\Component\Config\FileLocator')); + + $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable'); + $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); + + $this->assertTrue($loader->supports('foo.yml', 'yaml'), '->supports() checks the resource type if specified'); + $this->assertFalse($loader->supports('foo.yml', 'foo'), '->supports() checks the resource type if specified'); + } + + public function testLoadDoesNothingIfEmpty() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $collection = $loader->load('empty.yml'); + + $this->assertEquals(array(), $collection->all()); + $this->assertEquals(array(new FileResource(realpath(__DIR__.'/../Fixtures/empty.yml'))), $collection->getResources()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLoadThrowsExceptionIfNotAnArray() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader->load('nonvalid.yml'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLoadThrowsExceptionIfArrayHasUnsupportedKeys() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader->load('nonvalidkeys.yml'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testLoadThrowsExceptionWhenIncomplete() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader->load('incomplete.yml'); + } + + public function testLoadWithPattern() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $routeCollection = $loader->load('validpattern.yml'); + $routes = $routeCollection->all(); + + $this->assertEquals(1, count($routes), 'One route is loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + $route = $routes['blog_show']; + $this->assertEquals('RouteCompiler', $route->getOption('compiler_class')); + } + + public function testLoadWithResource() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $routeCollection = $loader->load('validresource.yml'); + $routes = $routeCollection->all(); + + $this->assertEquals(1, count($routes), 'One route is loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + $this->assertEquals('foo', $routes['blog_show']->getDefault('foo')); + $this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo')); + $this->assertEquals('bar', $routes['blog_show']->getOption('foo')); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testParseRouteThrowsExceptionWithMissingPattern() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader->load('incomplete.yml'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php b/core/vendor/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php new file mode 100644 index 0000000..9cae8b8 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Matcher\ApacheUrlMatcher; + +class ApacheUrlMatcherTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getMatchData + */ + public function testMatch($name, $pathinfo, $server, $expect) + { + $collection = new RouteCollection; + $context = new RequestContext; + $matcher = new ApacheUrlMatcher($collection, $context); + + $_SERVER = $server; + + $result = $matcher->match($pathinfo, $server); + $this->assertSame(var_export($expect, true), var_export($result, true)); + } + + public function getMatchData() + { + return array( + array( + 'Simple route', + '/hello/world', + array( + '_ROUTING__route' => 'hello', + '_ROUTING__controller' => 'AcmeBundle:Default:index', + '_ROUTING_name' => 'world', + ), + array( + '_route' => 'hello', + '_controller' => 'AcmeBundle:Default:index', + 'name' => 'world', + ), + ), + array( + 'REDIRECT_ envs', + '/hello/world', + array( + 'REDIRECT__ROUTING__route' => 'hello', + 'REDIRECT__ROUTING__controller' => 'AcmeBundle:Default:index', + 'REDIRECT__ROUTING_name' => 'world', + ), + array( + '_route' => 'hello', + '_controller' => 'AcmeBundle:Default:index', + 'name' => 'world', + ), + ), + ); + } +} + diff --git a/core/vendor/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php b/core/vendor/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php new file mode 100644 index 0000000..65cb454 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher\Dumper; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Matcher\Dumper\ApacheMatcherDumper; + +class ApacheMatcherDumperTest extends \PHPUnit_Framework_TestCase +{ + static protected $fixturesPath; + + static public function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/../../Fixtures/'); + } + + public function testDump() + { + $dumper = new ApacheMatcherDumper($this->getRouteCollection()); + + $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher1.apache', $dumper->dump(), '->dump() dumps basic routes to the correct apache format.'); + } + + /** + * @dataProvider provideEscapeFixtures + */ + public function testEscapePattern($src, $dest, $char, $with, $message) + { + $r = new \ReflectionMethod(new ApacheMatcherDumper($this->getRouteCollection()), 'escape'); + $r->setAccessible(true); + $this->assertEquals($dest, $r->invoke(null, $src, $char, $with), $message); + } + + public function provideEscapeFixtures() + { + return array( + array('foo', 'foo', ' ', '-', 'Preserve string that should not be escaped'), + array('fo-o', 'fo-o', ' ', '-', 'Preserve string that should not be escaped'), + array('fo o', 'fo- o', ' ', '-', 'Escape special characters'), + array('fo-- o', 'fo--- o', ' ', '-', 'Escape special characters'), + array('fo- o', 'fo- o', ' ', '-', 'Do not escape already escaped string'), + ); + } + + public function testEscapeScriptName() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + $dumper = new ApacheMatcherDumper($collection); + $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher2.apache', $dumper->dump(array('script_name' => 'ap p_d\ ev.php'))); + } + + private function getRouteCollection() + { + $collection = new RouteCollection(); + + // defaults and requirements + $collection->add('foo', new Route( + '/foo/{bar}', + array('def' => 'test'), + array('bar' => 'baz|symfony') + )); + // method requirement + $collection->add('bar', new Route( + '/bar/{foo}', + array(), + array('_method' => 'GET|head') + )); + // method requirement (again) + $collection->add('baragain', new Route( + '/baragain/{foo}', + array(), + array('_method' => 'get|post') + )); + // simple + $collection->add('baz', new Route( + '/test/baz' + )); + // simple with extension + $collection->add('baz2', new Route( + '/test/baz.html' + )); + // trailing slash + $collection->add('baz3', new Route( + '/test/baz3/' + )); + // trailing slash with variable + $collection->add('baz4', new Route( + '/test/{foo}/' + )); + // trailing slash and safe method + $collection->add('baz5', new Route( + '/test/{foo}/', + array(), + array('_method' => 'get') + )); + // trailing slash and unsafe method + $collection->add('baz5unsafe', new Route( + '/testunsafe/{foo}/', + array(), + array('_method' => 'post') + )); + // complex + $collection->add('baz6', new Route( + '/test/baz', + array('foo' => 'bar baz') + )); + // space in path + $collection->add('baz7', new Route( + '/te st/baz' + )); + + return $collection; + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/core/vendor/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php new file mode 100644 index 0000000..0aea039 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -0,0 +1,203 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher\Dumper; + +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \LogicException + */ + public function testDumpWhenSchemeIsUsedWithoutAProperDumper() + { + $collection = new RouteCollection(); + $collection->add('secure', new Route( + '/secure', + array(), + array('_scheme' => 'https') + )); + $dumper = new PhpMatcherDumper($collection, new RequestContext()); + $dumper->dump(); + } + + /** + * @dataProvider getRouteCollections + */ + public function testDump(RouteCollection $collection, $fixture, $options = array()) + { + $basePath = __DIR__.'/../../Fixtures/dumper/'; + + $dumper = new PhpMatcherDumper($collection, new RequestContext()); + + $this->assertStringEqualsFile($basePath.$fixture, $dumper->dump($options), '->dump() correctly dumps routes as optimized PHP code.'); + } + + public function getRouteCollections() + { + /* test case 1 */ + + $collection = new RouteCollection(); + + $collection->add('overriden', new Route('/overriden')); + + // defaults and requirements + $collection->add('foo', new Route( + '/foo/{bar}', + array('def' => 'test'), + array('bar' => 'baz|symfony') + )); + // method requirement + $collection->add('bar', new Route( + '/bar/{foo}', + array(), + array('_method' => 'GET|head') + )); + // GET method requirement automatically adds HEAD as valid + $collection->add('barhead', new Route( + '/barhead/{foo}', + array(), + array('_method' => 'GET') + )); + // simple + $collection->add('baz', new Route( + '/test/baz' + )); + // simple with extension + $collection->add('baz2', new Route( + '/test/baz.html' + )); + // trailing slash + $collection->add('baz3', new Route( + '/test/baz3/' + )); + // trailing slash with variable + $collection->add('baz4', new Route( + '/test/{foo}/' + )); + // trailing slash and method + $collection->add('baz5', new Route( + '/test/{foo}/', + array(), + array('_method' => 'post') + )); + // complex name + $collection->add('baz.baz6', new Route( + '/test/{foo}/', + array(), + array('_method' => 'put') + )); + // defaults without variable + $collection->add('foofoo', new Route( + '/foofoo', + array('def' => 'test') + )); + // pattern with quotes + $collection->add('quoter', new Route( + '/{quoter}', + array(), + array('quoter' => '[\']+') + )); + // space in pattern + $collection->add('space', new Route( + '/spa ce' + )); + + // prefixes + $collection1 = new RouteCollection(); + $collection1->add('overriden', new Route('/overriden1')); + $collection1->add('foo1', new Route('/{foo}')); + $collection1->add('bar1', new Route('/{bar}')); + $collection2 = new RouteCollection(); + $collection2->addCollection($collection1, '/b\'b'); + $collection2->add('overriden', new Route('/{var}', array(), array('var' => '.*'))); + $collection1 = new RouteCollection(); + $collection1->add('foo2', new Route('/{foo1}')); + $collection1->add('bar2', new Route('/{bar1}')); + $collection2->addCollection($collection1, '/b\'b'); + $collection->addCollection($collection2, '/a'); + + // overriden through addCollection() and multiple sub-collections with no own prefix + $collection1 = new RouteCollection(); + $collection1->add('overriden2', new Route('/old')); + $collection1->add('helloWorld', new Route('/hello/{who}', array('who' => 'World!'))); + $collection2 = new RouteCollection(); + $collection3 = new RouteCollection(); + $collection3->add('overriden2', new Route('/new')); + $collection3->add('hey', new Route('/hey/')); + $collection1->addCollection($collection2); + $collection2->addCollection($collection3); + $collection->addCollection($collection1, '/multi'); + + // "dynamic" prefix + $collection1 = new RouteCollection(); + $collection1->add('foo3', new Route('/{foo}')); + $collection1->add('bar3', new Route('/{bar}')); + $collection2 = new RouteCollection(); + $collection2->addCollection($collection1, '/b'); + $collection->addCollection($collection2, '/{_locale}'); + + // route between collections + $collection->add('ababa', new Route('/ababa')); + + // collection with static prefix but only one route + $collection1 = new RouteCollection(); + $collection1->add('foo4', new Route('/{foo}')); + $collection->addCollection($collection1, '/aba'); + + // multiple sub-collections with a single route and a prefix each + $collection1 = new RouteCollection(); + $collection1->add('a', new Route('/a...')); + $collection2 = new RouteCollection(); + $collection2->add('b', new Route('/{var}')); + $collection3 = new RouteCollection(); + $collection3->add('c', new Route('/{var}')); + + $collection1->addCollection($collection2, '/b'); + $collection2->addCollection($collection3, '/c'); + $collection->addCollection($collection1, '/a'); + + /* test case 2 */ + + $redirectCollection = clone $collection; + + // force HTTPS redirection + $redirectCollection->add('secure', new Route( + '/secure', + array(), + array('_scheme' => 'https') + )); + + // force HTTP redirection + $redirectCollection->add('nonsecure', new Route( + '/nonsecure', + array(), + array('_scheme' => 'http') + )); + + /* test case 3 */ + + $rootprefixCollection = new RouteCollection(); + $rootprefixCollection->add('static', new Route('/test')); + $rootprefixCollection->add('dynamic', new Route('/{var}')); + $rootprefixCollection->addPrefix('rootprefix'); + + return array( + array($collection, 'url_matcher1.php', array()), + array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), + array($rootprefixCollection, 'url_matcher3.php', array()) + ); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php b/core/vendor/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php new file mode 100644 index 0000000..43c958b --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +class RedirectableUrlMatcherTest extends \PHPUnit_Framework_TestCase +{ + public function testRedirectWhenNoSlash() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/')); + + $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher->expects($this->once())->method('redirect'); + $matcher->match('/foo'); + } + + public function testSchemeRedirect() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https'))); + + $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher + ->expects($this->once()) + ->method('redirect') + ->with('/foo', 'foo', 'https') + ->will($this->returnValue(array('_route' => 'foo'))) + ; + $matcher->match('/foo'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php b/core/vendor/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php new file mode 100644 index 0000000..7f8725c --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; + +class TraceableUrlMatcherTest extends \PHPUnit_Framework_TestCase +{ + public function test() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', array(), array('_method' => 'POST'))); + $coll->add('bar', new Route('/bar/{id}', array(), array('id' => '\d+'))); + $coll->add('bar1', new Route('/bar/{name}', array(), array('id' => '\w+', '_method' => 'POST'))); + + $context = new RequestContext(); + + $matcher = new TraceableUrlMatcher($coll, $context); + $traces = $matcher->getTraces('/babar'); + $this->assertEquals(array(0, 0, 0), $this->getLevels($traces)); + + $traces = $matcher->getTraces('/foo'); + $this->assertEquals(array(1, 0, 0), $this->getLevels($traces)); + + $traces = $matcher->getTraces('/bar/12'); + $this->assertEquals(array(0, 2), $this->getLevels($traces)); + + $traces = $matcher->getTraces('/bar/dd'); + $this->assertEquals(array(0, 1, 1), $this->getLevels($traces)); + + $context->setMethod('POST'); + $traces = $matcher->getTraces('/foo'); + $this->assertEquals(array(2), $this->getLevels($traces)); + + $traces = $matcher->getTraces('/bar/dd'); + $this->assertEquals(array(0, 1, 2), $this->getLevels($traces)); + } + + public function getLevels($traces) + { + $levels = array(); + foreach ($traces as $trace) { + $levels[] = $trace['level']; + } + + return $levels; + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/core/vendor/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php new file mode 100644 index 0000000..e38c75a --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -0,0 +1,228 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +class UrlMatcherTest extends \PHPUnit_Framework_TestCase +{ + public function testNoMethodSoAllowed() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo')); + + $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher->match('/foo'); + } + + public function testMethodNotAllowed() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', array(), array('_method' => 'post'))); + + $matcher = new UrlMatcher($coll, new RequestContext()); + + try { + $matcher->match('/foo'); + $this->fail(); + } catch (MethodNotAllowedException $e) { + $this->assertEquals(array('POST'), $e->getAllowedMethods()); + } + } + + public function testHeadAllowedWhenRequirementContainsGet() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', array(), array('_method' => 'get'))); + + $matcher = new UrlMatcher($coll, new RequestContext('', 'head')); + $matcher->match('/foo'); + } + + public function testMethodNotAllowedAggregatesAllowedMethods() + { + $coll = new RouteCollection(); + $coll->add('foo1', new Route('/foo', array(), array('_method' => 'post'))); + $coll->add('foo2', new Route('/foo', array(), array('_method' => 'put|delete'))); + + $matcher = new UrlMatcher($coll, new RequestContext()); + + try { + $matcher->match('/foo'); + $this->fail(); + } catch (MethodNotAllowedException $e) { + $this->assertEquals(array('POST', 'PUT', 'DELETE'), $e->getAllowedMethods()); + } + } + + public function testMatch() + { + // test the patterns are matched and parameters are returned + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo/{bar}')); + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + try { + $matcher->match('/no-match'); + $this->fail(); + } catch (ResourceNotFoundException $e) {} + $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz'), $matcher->match('/foo/baz')); + + // test that defaults are merged + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo/{bar}', array('def' => 'test'))); + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'def' => 'test'), $matcher->match('/foo/baz')); + + // test that route "method" is ignored if no method is given in the context + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo', array(), array('_method' => 'GET|head'))); + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertInternalType('array', $matcher->match('/foo')); + + // route does not match with POST method context + $matcher = new UrlMatcher($collection, new RequestContext('', 'post'), array()); + try { + $matcher->match('/foo'); + $this->fail(); + } catch (MethodNotAllowedException $e) {} + + // route does match with GET or HEAD method context + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertInternalType('array', $matcher->match('/foo')); + $matcher = new UrlMatcher($collection, new RequestContext('', 'head'), array()); + $this->assertInternalType('array', $matcher->match('/foo')); + + // route with an optional variable as the first segment + $collection = new RouteCollection(); + $collection->add('bar', new Route('/{bar}/foo', array('bar' => 'bar'), array('bar' => 'foo|bar'))); + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/bar/foo')); + $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo/foo')); + + $collection = new RouteCollection(); + $collection->add('bar', new Route('/{bar}', array('bar' => 'bar'), array('bar' => 'foo|bar'))); + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo')); + $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/')); + } + + public function testMatchWithPrefixes() + { + $collection1 = new RouteCollection(); + $collection1->add('foo', new Route('/{foo}')); + + $collection2 = new RouteCollection(); + $collection2->addCollection($collection1, '/b'); + + $collection = new RouteCollection(); + $collection->addCollection($collection2, '/a'); + + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertEquals(array('_route' => 'foo', 'foo' => 'foo'), $matcher->match('/a/b/foo')); + } + + public function testMatchWithDynamicPrefix() + { + $collection1 = new RouteCollection(); + $collection1->add('foo', new Route('/{foo}')); + + $collection2 = new RouteCollection(); + $collection2->addCollection($collection1, '/b'); + + $collection = new RouteCollection(); + $collection->addCollection($collection2, '/{_locale}'); + + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertEquals(array('_locale' => 'fr', '_route' => 'foo', 'foo' => 'foo'), $matcher->match('/fr/b/foo')); + } + + public function testMatchNonAlpha() + { + $collection = new RouteCollection(); + $chars = '!"$%éà &\'()*+,./:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\[]^_`abcdefghijklmnopqrstuvwxyz{|}~-'; + $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '['.preg_quote($chars).']+'))); + + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.rawurlencode($chars).'/bar')); + $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.strtr($chars, array('%' => '%25')).'/bar')); + } + + public function testMatchWithDotMetacharacterInRequirements() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '.+'))); + + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + $this->assertEquals(array('_route' => 'foo', 'foo' => "\n"), $matcher->match('/'.urlencode("\n").'/bar'), 'linefeed character is matched'); + } + + public function testMatchOverridenRoute() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + + $collection1 = new RouteCollection(); + $collection1->add('foo', new Route('/foo1')); + + $collection->addCollection($collection1); + + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + + $this->assertEquals(array('_route' => 'foo'), $matcher->match('/foo1')); + $this->setExpectedException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $this->assertEquals(array(), $matcher->match('/foo')); + } + + public function testMatchRegression() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/{foo}')); + $coll->add('bar', new Route('/foo/bar/{foo}')); + + $matcher = new UrlMatcher($coll, new RequestContext()); + $this->assertEquals(array('foo' => 'bar', '_route' => 'bar'), $matcher->match('/foo/bar/bar')); + + $collection = new RouteCollection(); + $collection->add('foo', new Route('/{bar}')); + $matcher = new UrlMatcher($collection, new RequestContext(), array()); + try { + $matcher->match('/'); + $this->fail(); + } catch (ResourceNotFoundException $e) { + } + } + + /** + * @expectedException Symfony\Component\Routing\Exception\ResourceNotFoundException + */ + public function testSchemeRequirement() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https'))); + $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher->match('/foo'); + } + + public function testDecodeOnce() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/{foo}')); + + $matcher = new UrlMatcher($coll, new RequestContext()); + $this->assertEquals(array('foo' => 'bar%23', '_route' => 'foo'), $matcher->match('/foo/bar%2523')); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/RouteCollectionTest.php b/core/vendor/Symfony/Component/Routing/Tests/RouteCollectionTest.php new file mode 100644 index 0000000..aee0f9d --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/RouteCollectionTest.php @@ -0,0 +1,279 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Route; +use Symfony\Component\Config\Resource\FileResource; + +class RouteCollectionTest extends \PHPUnit_Framework_TestCase +{ + public function testRoute() + { + $collection = new RouteCollection(); + $route = new Route('/foo'); + $collection->add('foo', $route); + $this->assertEquals(array('foo' => $route), $collection->all(), '->add() adds a route'); + $this->assertEquals($route, $collection->get('foo'), '->get() returns a route by name'); + $this->assertNull($collection->get('bar'), '->get() returns null if a route does not exist'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testAddInvalidRoute() + { + $collection = new RouteCollection(); + $route = new Route('/foo'); + $collection->add('f o o', $route); + } + + public function testOverridenRoute() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + $collection->add('foo', new Route('/foo1')); + + $this->assertEquals('/foo1', $collection->get('foo')->getPattern()); + } + + public function testDeepOverridenRoute() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + + $collection1 = new RouteCollection(); + $collection1->add('foo', new Route('/foo1')); + + $collection2 = new RouteCollection(); + $collection2->add('foo', new Route('/foo2')); + + $collection1->addCollection($collection2); + $collection->addCollection($collection1); + + $this->assertEquals('/foo2', $collection1->get('foo')->getPattern()); + $this->assertEquals('/foo2', $collection->get('foo')->getPattern()); + } + + public function testIteratorWithOverridenRoutes() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + + $collection1 = new RouteCollection(); + $collection->addCollection($collection1); + $collection1->add('foo', new Route('/foo1')); + + $this->assertEquals('/foo1', $this->getFirstNamedRoute($collection, 'foo')->getPattern()); + } + + protected function getFirstNamedRoute(RouteCollection $routeCollection, $name) + { + foreach ($routeCollection as $key => $route) { + if ($route instanceof RouteCollection) { + return $this->getFirstNamedRoute($route, $name); + } + + if ($name === $key) { + return $route; + } + } + } + + public function testAddCollection() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $collection = new RouteCollection(); + $collection->add('foo', $foo = new Route('/foo')); + $collection1 = new RouteCollection(); + $collection1->add('foo', $foo1 = new Route('/foo1')); + $collection1->add('bar', $bar1 = new Route('/bar1')); + $collection->addCollection($collection1); + $this->assertEquals(array('foo' => $foo1, 'bar' => $bar1), $collection->all(), '->addCollection() adds routes from another collection'); + + $collection = new RouteCollection(); + $collection->add('foo', $foo = new Route('/foo')); + $collection1 = new RouteCollection(); + $collection1->add('foo', $foo1 = new Route('/foo1')); + $collection->addCollection($collection1, '/{foo}', array('foo' => 'foo'), array('foo' => '\d+'), array('foo' => 'bar')); + $this->assertEquals('/{foo}/foo1', $collection->get('foo')->getPattern(), '->addCollection() can add a prefix to all merged routes'); + $this->assertEquals(array('foo' => 'foo'), $collection->get('foo')->getDefaults(), '->addCollection() can add a prefix to all merged routes'); + $this->assertEquals(array('foo' => '\d+'), $collection->get('foo')->getRequirements(), '->addCollection() can add a prefix to all merged routes'); + $this->assertEquals( + array('foo' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), + $collection->get('foo')->getOptions(), '->addCollection() can add an option to all merged routes' + ); + + $collection = new RouteCollection(); + $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml')); + $collection1 = new RouteCollection(); + $collection1->addResource($foo1 = new FileResource(__DIR__.'/Fixtures/foo1.xml')); + $collection->addCollection($collection1); + $this->assertEquals(array($foo, $foo1), $collection->getResources(), '->addCollection() merges resources'); + } + + public function testAddPrefix() + { + $collection = new RouteCollection(); + $collection->add('foo', $foo = new Route('/foo')); + $collection->add('bar', $bar = new Route('/bar')); + $collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+'), array('foo' => 'bar')); + $this->assertEquals('/{admin}/foo', $collection->get('foo')->getPattern(), '->addPrefix() adds a prefix to all routes'); + $this->assertEquals('/{admin}/bar', $collection->get('bar')->getPattern(), '->addPrefix() adds a prefix to all routes'); + $this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds a prefix to all routes'); + $this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds a prefix to all routes'); + $this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds a prefix to all routes'); + $this->assertEquals(array('admin' => '\d+'), $collection->get('bar')->getRequirements(), '->addPrefix() adds a prefix to all routes'); + $this->assertEquals( + array('foo' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), + $collection->get('foo')->getOptions(), '->addPrefix() adds an option to all routes' + ); + $this->assertEquals( + array('foo' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), + $collection->get('bar')->getOptions(), '->addPrefix() adds an option to all routes' + ); + $collection->addPrefix('0'); + $this->assertEquals('/0/{admin}', $collection->getPrefix(), '->addPrefix() ensures a prefix must start with a slash and must not end with a slash'); + } + + public function testAddPrefixOverridesDefaultsAndRequirements() + { + $collection = new RouteCollection(); + $collection->add('foo', $foo = new Route('/foo')); + $collection->add('bar', $bar = new Route('/bar', array(), array('_scheme' => 'http'))); + $collection->addPrefix('/admin', array(), array('_scheme' => 'https')); + + $this->assertEquals('https', $collection->get('foo')->getRequirement('_scheme'), '->addPrefix() overrides existing requirements'); + $this->assertEquals('https', $collection->get('bar')->getRequirement('_scheme'), '->addPrefix() overrides existing requirements'); + } + + public function testAddCollectionOverridesDefaultsAndRequirements() + { + $imported = new RouteCollection(); + $imported->add('foo', $foo = new Route('/foo')); + $imported->add('bar', $bar = new Route('/bar', array(), array('_scheme' => 'http'))); + + $collection = new RouteCollection(); + $collection->addCollection($imported, null, array(), array('_scheme' => 'https')); + + $this->assertEquals('https', $collection->get('foo')->getRequirement('_scheme'), '->addCollection() overrides existing requirements'); + $this->assertEquals('https', $collection->get('bar')->getRequirement('_scheme'), '->addCollection() overrides existing requirements'); + } + + public function testResource() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $collection = new RouteCollection(); + $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml')); + $this->assertEquals(array($foo), $collection->getResources(), '->addResources() adds a resource'); + } + + public function testUniqueRouteWithGivenName() + { + $collection1 = new RouteCollection(); + $collection1->add('foo', new Route('/old')); + $collection2 = new RouteCollection(); + $collection3 = new RouteCollection(); + $collection3->add('foo', $new = new Route('/new')); + + $collection1->addCollection($collection2); + $collection2->addCollection($collection3); + + $collection1->add('stay', new Route('/stay')); + + $iterator = $collection1->getIterator(); + + $this->assertSame($new, $collection1->get('foo'), '->get() returns new route that overrode previous one'); + // size of 2 because collection1 contains collection2 and /stay but not /old anymore + $this->assertCount(2, $iterator, '->addCollection() removes previous routes when adding new routes with the same name'); + $this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $iterator->current(), '->getIterator returns both Routes and RouteCollections'); + $iterator->next(); + $this->assertInstanceOf('Symfony\Component\Routing\Route', $iterator->current(), '->getIterator returns both Routes and RouteCollections'); + } + + public function testGet() + { + $collection1 = new RouteCollection(); + $collection1->add('a', $a = new Route('/a')); + $collection2 = new RouteCollection(); + $collection2->add('b', $b = new Route('/b')); + $collection1->addCollection($collection2); + + $this->assertSame($b, $collection1->get('b'), '->get() returns correct route in child collection'); + $this->assertNull($collection2->get('a'), '->get() does not return the route defined in parent collection'); + $this->assertNull($collection1->get('non-existent'), '->get() returns null when route does not exist'); + $this->assertNull($collection1->get(0), '->get() does not disclose internal child RouteCollection'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testCannotSelfJoinCollection() + { + $collection = new RouteCollection(); + + $collection->addCollection($collection); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testCannotAddExistingCollectionToTree() + { + $collection1 = new RouteCollection(); + $collection2 = new RouteCollection(); + $collection3 = new RouteCollection(); + + $collection1->addCollection($collection2); + $collection1->addCollection($collection3); + $collection2->addCollection($collection3); + } + + public function testPatternDoesNotChangeWhenDefinitionOrderChanges() + { + $collection1 = new RouteCollection(); + $collection1->add('a', new Route('/a...')); + $collection2 = new RouteCollection(); + $collection2->add('b', new Route('/b...')); + $collection3 = new RouteCollection(); + $collection3->add('c', new Route('/c...')); + + $rootCollection_A = new RouteCollection(); + $collection2->addCollection($collection3, '/c'); + $collection1->addCollection($collection2, '/b'); + $rootCollection_A->addCollection($collection1, '/a'); + + // above should mean the same as below + + $collection1 = new RouteCollection(); + $collection1->add('a', new Route('/a...')); + $collection2 = new RouteCollection(); + $collection2->add('b', new Route('/b...')); + $collection3 = new RouteCollection(); + $collection3->add('c', new Route('/c...')); + + $rootCollection_B = new RouteCollection(); + $collection1->addCollection($collection2, '/b'); + $collection2->addCollection($collection3, '/c'); + $rootCollection_B->addCollection($collection1, '/a'); + + // test it now + + $this->assertEquals($rootCollection_A, $rootCollection_B); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/RouteCompilerTest.php b/core/vendor/Symfony/Component/Routing/Tests/RouteCompilerTest.php new file mode 100644 index 0000000..7245e79 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/RouteCompilerTest.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests; + +use Symfony\Component\Routing\Route; + +class RouteCompilerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider provideCompileData + */ + public function testCompile($name, $arguments, $prefix, $regex, $variables, $tokens) + { + $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route'); + $route = $r->newInstanceArgs($arguments); + + $compiled = $route->compile(); + $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)'); + $this->assertEquals($regex, $compiled->getRegex(), $name.' (regex)'); + $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)'); + $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)'); + } + + public function provideCompileData() + { + return array( + array( + 'Static route', + array('/foo'), + '/foo', '#^/foo$#s', array(), array( + array('text', '/foo'), + )), + + array( + 'Route with a variable', + array('/foo/{bar}'), + '/foo', '#^/foo/(?[^/]+?)$#s', array('bar'), array( + array('variable', '/', '[^/]+?', 'bar'), + array('text', '/foo'), + )), + + array( + 'Route with a variable that has a default value', + array('/foo/{bar}', array('bar' => 'bar')), + '/foo', '#^/foo(?:/(?[^/]+?))?$#s', array('bar'), array( + array('variable', '/', '[^/]+?', 'bar'), + array('text', '/foo'), + )), + + array( + 'Route with several variables', + array('/foo/{bar}/{foobar}'), + '/foo', '#^/foo/(?[^/]+?)/(?[^/]+?)$#s', array('bar', 'foobar'), array( + array('variable', '/', '[^/]+?', 'foobar'), + array('variable', '/', '[^/]+?', 'bar'), + array('text', '/foo'), + )), + + array( + 'Route with several variables that have default values', + array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')), + '/foo', '#^/foo(?:/(?[^/]+?)(?:/(?[^/]+?))?)?$#s', array('bar', 'foobar'), array( + array('variable', '/', '[^/]+?', 'foobar'), + array('variable', '/', '[^/]+?', 'bar'), + array('text', '/foo'), + )), + + array( + 'Route with several variables but some of them have no default values', + array('/foo/{bar}/{foobar}', array('bar' => 'bar')), + '/foo', '#^/foo/(?[^/]+?)/(?[^/]+?)$#s', array('bar', 'foobar'), array( + array('variable', '/', '[^/]+?', 'foobar'), + array('variable', '/', '[^/]+?', 'bar'), + array('text', '/foo'), + )), + + array( + 'Route with an optional variable as the first segment', + array('/{bar}', array('bar' => 'bar')), + '', '#^/(?[^/]+?)?$#s', array('bar'), array( + array('variable', '/', '[^/]+?', 'bar'), + )), + + array( + 'Route with an optional variable as the first segment with requirements', + array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')), + '', '#^/(?(foo|bar))?$#s', array('bar'), array( + array('variable', '/', '(foo|bar)', 'bar'), + )), + ); + } + + /** + * @expectedException \LogicException + */ + public function testRouteWithSameVariableTwice() + { + $route = new Route('/{name}/{name}'); + + $compiled = $route->compile(); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/RouteTest.php b/core/vendor/Symfony/Component/Routing/Tests/RouteTest.php new file mode 100644 index 0000000..8e46682 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/RouteTest.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests; + +use Symfony\Component\Routing\Route; + +class RouteTest extends \PHPUnit_Framework_TestCase +{ + public function testConstructor() + { + $route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar')); + $this->assertEquals('/{foo}', $route->getPattern(), '__construct() takes a pattern as its first argument'); + $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '__construct() takes defaults as its second argument'); + $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '__construct() takes requirements as its third argument'); + $this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument'); + } + + public function testPattern() + { + $route = new Route('/{foo}'); + $route->setPattern('/{bar}'); + $this->assertEquals('/{bar}', $route->getPattern(), '->setPattern() sets the pattern'); + $route->setPattern(''); + $this->assertEquals('/', $route->getPattern(), '->setPattern() adds a / at the beginning of the pattern if needed'); + $route->setPattern('bar'); + $this->assertEquals('/bar', $route->getPattern(), '->setPattern() adds a / at the beginning of the pattern if needed'); + $this->assertEquals($route, $route->setPattern(''), '->setPattern() implements a fluent interface'); + } + + public function testOptions() + { + $route = new Route('/{foo}'); + $route->setOptions(array('foo' => 'bar')); + $this->assertEquals(array_merge(array( + 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', + ), array('foo' => 'bar')), $route->getOptions(), '->setOptions() sets the options'); + $this->assertEquals($route, $route->setOptions(array()), '->setOptions() implements a fluent interface'); + + $route->setOptions(array('foo' => 'foo')); + $route->addOptions(array('bar' => 'bar')); + $this->assertEquals($route, $route->addOptions(array()), '->addOptions() implements a fluent interface'); + $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), $route->getOptions(), '->addDefaults() keep previous defaults'); + } + + public function testDefaults() + { + $route = new Route('/{foo}'); + $route->setDefaults(array('foo' => 'bar')); + $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '->setDefaults() sets the defaults'); + $this->assertEquals($route, $route->setDefaults(array()), '->setDefaults() implements a fluent interface'); + + $route->setDefault('foo', 'bar'); + $this->assertEquals('bar', $route->getDefault('foo'), '->setDefault() sets a default value'); + + $route->setDefault('foo2', 'bar2'); + $this->assertEquals('bar2', $route->getDefault('foo2'), '->getDefault() return the default value'); + $this->assertNull($route->getDefault('not_defined'), '->getDefault() return null if default value is not setted'); + + $route->setDefault('_controller', $closure = function () { return 'Hello'; }); + $this->assertEquals($closure, $route->getDefault('_controller'), '->setDefault() sets a default value'); + + $route->setDefaults(array('foo' => 'foo')); + $route->addDefaults(array('bar' => 'bar')); + $this->assertEquals($route, $route->addDefaults(array()), '->addDefaults() implements a fluent interface'); + $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar'), $route->getDefaults(), '->addDefaults() keep previous defaults'); + } + + public function testRequirements() + { + $route = new Route('/{foo}'); + $route->setRequirements(array('foo' => '\d+')); + $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '->setRequirements() sets the requirements'); + $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() returns a requirement'); + $this->assertNull($route->getRequirement('bar'), '->getRequirement() returns null if a requirement is not defined'); + $route->setRequirements(array('foo' => '^\d+$')); + $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() removes ^ and $ from the pattern'); + $this->assertEquals($route, $route->setRequirements(array()), '->setRequirements() implements a fluent interface'); + + $route->setRequirements(array('foo' => '\d+')); + $route->addRequirements(array('bar' => '\d+')); + $this->assertEquals($route, $route->addRequirements(array()), '->addRequirements() implements a fluent interface'); + $this->assertEquals(array('foo' => '\d+', 'bar' => '\d+'), $route->getRequirements(), '->addRequirement() keep previous requirements'); + } + + public function testRequirement() + { + $route = new Route('/{foo}'); + $route->setRequirement('foo', '^\d+$'); + $this->assertEquals('\d+', $route->getRequirement('foo'), '->setRequirement() removes ^ and $ from the pattern'); + } + + /** + * @dataProvider getInvalidRequirements + * @expectedException \InvalidArgumentException + */ + public function testSetInvalidRequirement($req) + { + $route = new Route('/{foo}'); + $route->setRequirement('foo', $req); + } + + public function getInvalidRequirements() + { + return array( + array(''), + array(array()) + ); + } + + public function testCompile() + { + $route = new Route('/{foo}'); + $this->assertInstanceOf('Symfony\Component\Routing\CompiledRoute', $compiled = $route->compile(), '->compile() returns a compiled route'); + $this->assertSame($compiled, $route->compile(), '->compile() only compiled the route once if unchanged'); + $route->setRequirement('foo', '.*'); + $this->assertNotSame($compiled, $route->compile(), '->compile() recompiles if the route was modified'); + } +} diff --git a/core/vendor/Symfony/Component/Routing/Tests/bootstrap.php b/core/vendor/Symfony/Component/Routing/Tests/bootstrap.php new file mode 100644 index 0000000..8565b33 --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/Tests/bootstrap.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + foreach (array( + 'SYMFONY_CONFIG' => 'Config', + 'SYMFONY_YAML' => 'Yaml', + ) as $env => $name) { + if (isset($_SERVER[$env]) && 0 === strpos(ltrim($class, '/'), 'Symfony\Component\\'.$name)) { + if (file_exists($file = $_SERVER[$env].'/'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\\'.$name)).'.php')) { + require_once $file; + } + } + } + + if (isset($_SERVER['DOCTRINE_COMMON']) && 0 === strpos(ltrim($class, '/'), 'Doctrine\Common')) { + if (file_exists($file = $_SERVER['DOCTRINE_COMMON'].'/lib/'.str_replace('\\', '/', $class).'.php')) { + require_once $file; + } + } + + if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\Routing')) { + if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\Routing')).'.php')) { + require_once $file; + } + } +}); diff --git a/core/vendor/Symfony/Component/Routing/phpunit.xml.dist b/core/vendor/Symfony/Component/Routing/phpunit.xml.dist new file mode 100644 index 0000000..f6d9ede --- /dev/null +++ b/core/vendor/Symfony/Component/Routing/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + + + +