Upgraded to Symfony 2.1-beta2
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (!@include __DIR__ . '/../vendor/.composer/autoload.php') {
|
||||
die("You must set up the project dependencies, run the following commands:
|
||||
wget http://getcomposer.org/composer.phar
|
||||
php composer.phar install
|
||||
");
|
||||
}
|
||||
|
||||
spl_autoload_register(function($class) {
|
||||
if (0 === strpos($class, 'Symfony\\Bundle\\MonologBundle')) {
|
||||
$path = __DIR__.'/../'.implode('/', array_slice(explode('\\', $class), 3)).'.php';
|
||||
if (!stream_resolve_include_path($path)) {
|
||||
return false;
|
||||
}
|
||||
require_once $path;
|
||||
return true;
|
||||
}
|
||||
});
|
@@ -23,7 +23,8 @@
|
||||
"monolog/monolog": "1.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/yaml": "2.1.*"
|
||||
"symfony/yaml": "2.1.*",
|
||||
"symfony/config": "2.1.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Symfony\\Bundle\\MonologBundle": "" }
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit colors="true" bootstrap="Tests/bootstrap.php">
|
||||
<phpunit colors="true" bootstrap="vendor/autoload.php">
|
||||
<testsuites>
|
||||
<testsuite name="MonologBundle for the Symfony Framework">
|
||||
<directory>./Tests</directory>
|
||||
|
@@ -53,6 +53,8 @@ class Configuration implements ConfigurationInterface
|
||||
->scalarNode('password')->defaultNull()->end()
|
||||
->scalarNode('host')->defaultValue('localhost')->end()
|
||||
->scalarNode('port')->defaultFalse()->end()
|
||||
->scalarNode('timeout')->defaultValue(30)->end()
|
||||
->scalarNode('source_ip')->defaultNull()->end()
|
||||
->scalarNode('encryption')
|
||||
->defaultNull()
|
||||
->validate()
|
||||
|
@@ -76,7 +76,7 @@ class SwiftmailerExtension extends Extension
|
||||
$config['port'] = 'ssl' === $config['encryption'] ? 465 : 25;
|
||||
}
|
||||
|
||||
foreach (array('encryption', 'port', 'host', 'username', 'password', 'auth_mode') as $key) {
|
||||
foreach (array('encryption', 'port', 'host', 'username', 'password', 'auth_mode', 'timeout', 'source_ip') as $key) {
|
||||
$container->setParameter('swiftmailer.transport.smtp.'.$key, $config[$key]);
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,8 @@
|
||||
<xsd:attribute name="port" type="xsd:string" />
|
||||
<xsd:attribute name="encryption" type="encryption" />
|
||||
<xsd:attribute name="auth-mode" type="auth_mode" />
|
||||
<xsd:attribute name="timeout" type="xsd:string"/>
|
||||
<xsd:attribute name="source-ip" type="xsd:string"/>
|
||||
<xsd:attribute name="transport" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="delivery-address" type="xsd:string" />
|
||||
|
@@ -22,6 +22,8 @@
|
||||
<call method="setUsername"><argument>%swiftmailer.transport.smtp.username%</argument></call>
|
||||
<call method="setPassword"><argument>%swiftmailer.transport.smtp.password%</argument></call>
|
||||
<call method="setAuthMode"><argument>%swiftmailer.transport.smtp.auth_mode%</argument></call>
|
||||
<call method="setTimeout"><argument>%swiftmailer.transport.smtp.timeout%</argument></call>
|
||||
<call method="setSourceIp"><argument>%swiftmailer.transport.smtp.source_ip%</argument></call>
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
@@ -18,8 +18,13 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"swiftmailer/swiftmailer": ">=4.1.8,<4.2-dev",
|
||||
"symfony/swiftmailer-bridge": "self.version"
|
||||
"swiftmailer/swiftmailer": ">=4.2.0,<4.3-dev",
|
||||
"symfony/swiftmailer-bridge": "2.1.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dependency-injection": "2.1.*",
|
||||
"symfony/http-kernel": "2.1.*",
|
||||
"symfony/config": "2.1.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Symfony\\Bundle\\SwiftmailerBundle": "" }
|
||||
@@ -27,7 +32,7 @@
|
||||
"target-dir": "Symfony/Bundle/SwiftmailerBundle",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1.x-dev"
|
||||
"dev-master": "2.1-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
20
vendor/symfony/swiftmailer-bundle/Symfony/Bundle/SwiftmailerBundle/phpunit.xml.dist
vendored
Normal file
20
vendor/symfony/swiftmailer-bundle/Symfony/Bundle/SwiftmailerBundle/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit colors="true" bootstrap="vendor/autoload.php">
|
||||
<testsuites>
|
||||
<testsuite name="SwiftmailerBundle for the Symfony Framework">
|
||||
<directory>./Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>.</directory>
|
||||
<exclude>
|
||||
<directory>./Resources</directory>
|
||||
<directory>./Tests</directory>
|
||||
<directory>./vendor</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
98
vendor/symfony/symfony/UPGRADE-2.1.md
vendored
98
vendor/symfony/symfony/UPGRADE-2.1.md
vendored
@@ -65,6 +65,52 @@
|
||||
|
||||
After: `$request->getLocale()`
|
||||
|
||||
### HttpFoundation
|
||||
|
||||
* [BC BREAK] The current locale for the user is not stored anymore in the session
|
||||
|
||||
You can simulate the old behavior by registering a listener that looks like the following, if the paramater which handle locale value in the request is `_locale`:
|
||||
|
||||
```
|
||||
namespace XXX;
|
||||
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class LocaleListener implements EventSubscriberInterface
|
||||
{
|
||||
private $defaultLocale;
|
||||
|
||||
public function __construct($defaultLocale = 'en')
|
||||
{
|
||||
$this->defaultLocale = $defaultLocale;
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
if (!$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($locale = $request->attributes->get('_locale')) {
|
||||
$request->getSession()->set('_locale', $locale);
|
||||
} else {
|
||||
$request->setDefaultLocale($request->getSession()->get('_locale', $this->defaultLocale));
|
||||
}
|
||||
}
|
||||
|
||||
static public function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
// must be registered before the default Locale listener
|
||||
KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
* `Symfony\Component\Security\Core\User\UserInterface::equals()` has moved to
|
||||
@@ -193,6 +239,40 @@
|
||||
public function finishView(FormViewInterface $view, FormInterface $form, array $options)
|
||||
```
|
||||
|
||||
* If you previously inherited from `FieldType`, you should now inherit from
|
||||
`FormType`. You should also set the option `compound` to `false` if your field
|
||||
is not supposed to contain child fields.
|
||||
|
||||
`FieldType` was deprecated and will be removed in Symfony 2.3.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return 'field';
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
public function getParent()
|
||||
{
|
||||
return 'form';
|
||||
}
|
||||
|
||||
public function setDefaultOptions(OptionsResolverInterface $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'compound' => false,
|
||||
));
|
||||
}
|
||||
```
|
||||
|
||||
The changed signature of `getParent()` is explained in the next step.
|
||||
The new method `setDefaultOptions` is described in the section "Deprecations".
|
||||
|
||||
* No options are passed to `getParent()` of `FormTypeInterface` anymore. If
|
||||
you previously dynamically inherited from `FormType` or `FieldType`, you can now
|
||||
dynamically set the "compound" option instead.
|
||||
@@ -460,6 +540,22 @@
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
* Creation of default labels has been moved to the view layer. You will need
|
||||
to incorporate this logic into any custom `form_label` templates to
|
||||
accommodate those cases when the `label` option has not been explicitly
|
||||
set.
|
||||
|
||||
```
|
||||
{% block form_label %}
|
||||
{% if label is empty %}
|
||||
{% set label = name|humanize %}
|
||||
{% endif %}
|
||||
|
||||
{# ... #}
|
||||
|
||||
{% endblock %}
|
||||
````
|
||||
|
||||
#### Other BC Breaks
|
||||
|
||||
* The order of the first two arguments of the methods `createNamed` and
|
||||
@@ -1008,7 +1104,7 @@
|
||||
### Serializer
|
||||
|
||||
* The key names created by the `GetSetMethodNormalizer` have changed from
|
||||
from all lowercased to camelCased (e.g. `mypropertyvalue` to `myPropertyValue`).
|
||||
all lowercased to camelCased (e.g. `mypropertyvalue` to `myPropertyValue`).
|
||||
|
||||
* The `item` element is now converted to an array when deserializing XML.
|
||||
|
||||
|
5
vendor/symfony/symfony/autoload.php.dist
vendored
5
vendor/symfony/symfony/autoload.php.dist
vendored
@@ -15,8 +15,3 @@ if (!function_exists('intl_get_error_code')) {
|
||||
|
||||
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
|
||||
AnnotationRegistry::registerFile(__DIR__.'/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
|
||||
|
||||
if (is_file(__DIR__.'/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php')) {
|
||||
require_once __DIR__.'/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php';
|
||||
Swift::registerAutoload(__DIR__.'/vendor/swiftmailer/swiftmailer/lib/swift_init.php');
|
||||
}
|
||||
|
1
vendor/symfony/symfony/composer.json
vendored
1
vendor/symfony/symfony/composer.json
vendored
@@ -67,6 +67,7 @@
|
||||
"SessionHandlerInterface": "src/Symfony/Component/HttpFoundation/Resources/stubs"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1-dev"
|
||||
|
@@ -17,7 +17,7 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"swiftmailer/swiftmailer": ">=4.1.2,<4.2-dev"
|
||||
"swiftmailer/swiftmailer": ">=4.2.0,<4.3-dev"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/http-kernel": "self.version"
|
||||
|
@@ -91,6 +91,13 @@ class FormExtension extends \Twig_Extension
|
||||
);
|
||||
}
|
||||
|
||||
public function getFilters()
|
||||
{
|
||||
return array(
|
||||
'humanize' => new \Twig_Filter_Function(__NAMESPACE__.'\humanize'),
|
||||
);
|
||||
}
|
||||
|
||||
public function isChoiceGroup($label)
|
||||
{
|
||||
return FormUtil::isChoiceGroup($label);
|
||||
@@ -364,3 +371,8 @@ class FormExtension extends \Twig_Extension
|
||||
return $blocks;
|
||||
}
|
||||
}
|
||||
|
||||
function humanize($text)
|
||||
{
|
||||
return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text))));
|
||||
}
|
||||
|
@@ -225,6 +225,9 @@
|
||||
{% if required %}
|
||||
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
|
||||
{% endif %}
|
||||
{% if label is empty %}
|
||||
{% set label = name|humanize %}
|
||||
{% endif %}
|
||||
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}</label>
|
||||
{% endspaceless %}
|
||||
{% endblock form_label %}
|
||||
|
@@ -32,3 +32,9 @@ CHANGELOG
|
||||
`gc_probability`/`gc_divisor` chance of being run. The `gc_maxlifetime` defines
|
||||
how long a session can idle for. It is different from cookie lifetime which
|
||||
declares how long a cookie can be stored on the remote client.
|
||||
* Removed 'auto_start' configuration parameter from session config. The session will
|
||||
start on demand.
|
||||
* [BC BREAK] TemplateNameParser::parseFromFilename() has been moved to a dedicated
|
||||
parser: TemplateFilenameParser::parse().
|
||||
* [BC BREAK] Kernel parameters are replaced by their value whereever they appear
|
||||
in Route patterns, requirements and defaults. Use '%%' as the escaped value for '%'.
|
||||
|
@@ -13,7 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
|
||||
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;
|
||||
use Symfony\Component\Templating\TemplateNameParserInterface;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
|
||||
/**
|
||||
@@ -31,11 +31,11 @@ class TemplateFinder implements TemplateFinderInterface
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param KernelInterface $kernel A KernelInterface instance
|
||||
* @param TemplateNameParser $parser A TemplateNameParser instance
|
||||
* @param string $rootDir The directory where global templates can be stored
|
||||
* @param KernelInterface $kernel A KernelInterface instance
|
||||
* @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance
|
||||
* @param string $rootDir The directory where global templates can be stored
|
||||
*/
|
||||
public function __construct(KernelInterface $kernel, TemplateNameParser $parser, $rootDir)
|
||||
public function __construct(KernelInterface $kernel, TemplateNameParserInterface $parser, $rootDir)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
$this->parser = $parser;
|
||||
@@ -78,7 +78,7 @@ class TemplateFinder implements TemplateFinderInterface
|
||||
if (is_dir($dir)) {
|
||||
$finder = new Finder();
|
||||
foreach ($finder->files()->followLinks()->in($dir) as $file) {
|
||||
$template = $this->parser->parseFromFilename($file->getRelativePathname());
|
||||
$template = $this->parser->parse($file->getRelativePathname());
|
||||
if (false !== $template) {
|
||||
$templates[] = $template;
|
||||
}
|
||||
|
@@ -84,6 +84,11 @@ class Client extends BaseClient
|
||||
/**
|
||||
* Returns the script to execute when the request must be insulated.
|
||||
*
|
||||
* It assumes that the autoloader is named 'autoload.php' and that it is
|
||||
* stored in the same directory as the kernel (this is the case for the
|
||||
* Symfony Standard Edition). If this is not your case, create your own
|
||||
* client and override this method.
|
||||
*
|
||||
* @param Request $request A Request instance
|
||||
*
|
||||
* @return string The script content
|
||||
@@ -94,11 +99,22 @@ class Client extends BaseClient
|
||||
$request = str_replace("'", "\\'", serialize($request));
|
||||
|
||||
$r = new \ReflectionObject($this->kernel);
|
||||
|
||||
$autoloader = dirname($r->getFileName()).'/autoload.php';
|
||||
if (is_file($autoloader)) {
|
||||
$autoloader = str_replace("'", "\\'", $autoloader);
|
||||
} else {
|
||||
$autoloader = '';
|
||||
}
|
||||
|
||||
$path = str_replace("'", "\\'", $r->getFileName());
|
||||
|
||||
return <<<EOF
|
||||
<?php
|
||||
|
||||
if ('$autoloader') {
|
||||
require_once '$autoloader';
|
||||
}
|
||||
require_once '$path';
|
||||
|
||||
\$kernel = unserialize('$kernel');
|
||||
|
@@ -37,6 +37,11 @@ class CacheWarmupCommand extends ContainerAwareCommand
|
||||
The <info>%command.name%</info> command warms up the cache.
|
||||
|
||||
Before running this command, the cache must be empty.
|
||||
|
||||
This command does not generate the classes cache (as when executing this
|
||||
command, too many classes that should be part of the cache are already loaded
|
||||
in memory). Use <comment>curl</comment> or any other similar tool to warm up
|
||||
the classes cache if you want.
|
||||
EOF
|
||||
)
|
||||
;
|
||||
|
@@ -17,6 +17,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Config\Definition\NodeInterface;
|
||||
use Symfony\Component\Config\Definition\ArrayNode;
|
||||
use Symfony\Component\Config\Definition\PrototypedArrayNode;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* A console command for dumping available configuration reference
|
||||
@@ -102,6 +103,12 @@ EOF
|
||||
'" does not have it\'s getConfiguration() method setup');
|
||||
}
|
||||
|
||||
if (!$configuration instanceof ConfigurationInterface) {
|
||||
throw new \LogicException(
|
||||
'Configuration class "'.get_class($configuration).
|
||||
'" should implement ConfigurationInterface in order to be dumpable');
|
||||
}
|
||||
|
||||
$rootNode = $configuration->getConfigTreeBuilder()->buildTree();
|
||||
|
||||
$output->writeln($message);
|
||||
|
@@ -32,7 +32,7 @@ class ContainerDebugCommand extends ContainerAwareCommand
|
||||
/**
|
||||
* @var ContainerBuilder
|
||||
*/
|
||||
private $containerBuilder;
|
||||
protected $containerBuilder;
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
@@ -209,7 +209,7 @@ EOF
|
||||
*
|
||||
* @return \Symfony\Component\DependencyInjection\Definition|\Symfony\Component\DependencyInjection\Alias
|
||||
*/
|
||||
private function resolveServiceDefinition($serviceId)
|
||||
protected function resolveServiceDefinition($serviceId)
|
||||
{
|
||||
if ($this->containerBuilder->hasDefinition($serviceId)) {
|
||||
return $this->containerBuilder->getDefinition($serviceId);
|
||||
|
@@ -74,11 +74,13 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
protected function outputRoutes(OutputInterface $output)
|
||||
protected function outputRoutes(OutputInterface $output, $routes = null)
|
||||
{
|
||||
$routes = array();
|
||||
foreach ($this->getContainer()->get('router')->getRouteCollection()->all() as $name => $route) {
|
||||
$routes[$name] = $route->compile();
|
||||
if (null === $routes) {
|
||||
$routes = array();
|
||||
foreach ($this->getContainer()->get('router')->getRouteCollection()->all() as $name => $route) {
|
||||
$routes[$name] = $route->compile();
|
||||
}
|
||||
}
|
||||
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('router', 'Current routes'));
|
||||
|
@@ -46,7 +46,21 @@ class Configuration implements ConfigurationInterface
|
||||
|
||||
$rootNode
|
||||
->children()
|
||||
->scalarNode('charset')->info('general configuration')->end()
|
||||
->scalarNode('charset')
|
||||
->defaultNull()
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v) { return null !== $v; })
|
||||
->then(function($v) {
|
||||
$message = 'The charset setting is deprecated. Just remove it from your configuration file.';
|
||||
|
||||
if ('UTF-8' !== $v) {
|
||||
$message .= sprintf(' You need to define a getCharset() method in your Application Kernel class that returns "%s".', $v);
|
||||
}
|
||||
|
||||
throw new \RuntimeException($message);
|
||||
})
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('trust_proxy_headers')->defaultFalse()->end()
|
||||
->scalarNode('secret')->isRequired()->end()
|
||||
->scalarNode('ide')->defaultNull()->end()
|
||||
@@ -176,7 +190,16 @@ class Configuration implements ConfigurationInterface
|
||||
->info('session configuration')
|
||||
->canBeUnset()
|
||||
->children()
|
||||
->booleanNode('auto_start')->defaultFalse()->end()
|
||||
->booleanNode('auto_start')
|
||||
->info('DEPRECATED! Session starts on demand')
|
||||
->defaultNull()
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v) { return null !== $v; })
|
||||
->then(function($v) {
|
||||
throw new \RuntimeException('The auto_start setting is deprecated. Just remove it from your configuration file.');
|
||||
})
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('storage_id')->defaultValue('session.storage.native')->end()
|
||||
->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end()
|
||||
->scalarNode('name')->end()
|
||||
|
@@ -60,9 +60,6 @@ class FrameworkExtension extends Extension
|
||||
$configuration = $this->getConfiguration($configs, $container);
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
$container->setParameter('kernel.charset', $config['charset']);
|
||||
}
|
||||
$container->setParameter('kernel.secret', $config['secret']);
|
||||
|
||||
$container->setParameter('kernel.trust_proxy_headers', $config['trust_proxy_headers']);
|
||||
@@ -119,17 +116,12 @@ class FrameworkExtension extends Extension
|
||||
|
||||
'Symfony\\Component\\Config\\FileLocator',
|
||||
|
||||
'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface',
|
||||
'Symfony\\Component\\EventDispatcher\\EventDispatcher',
|
||||
'Symfony\\Component\\EventDispatcher\\Event',
|
||||
'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface',
|
||||
'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher',
|
||||
|
||||
'Symfony\\Component\\HttpKernel\\HttpKernel',
|
||||
'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener',
|
||||
'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener',
|
||||
'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
|
||||
'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface',
|
||||
'Symfony\\Component\\HttpKernel\\Event\\KernelEvent',
|
||||
'Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent',
|
||||
'Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent',
|
||||
@@ -143,7 +135,6 @@ class FrameworkExtension extends Extension
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
|
||||
// Cannot be included because annotations will parse the big compiled class file
|
||||
// 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
|
||||
'Symfony\\Bundle\\FrameworkBundle\\HttpKernel',
|
||||
));
|
||||
}
|
||||
|
||||
@@ -266,13 +257,8 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('request_listener.https_port', $config['https_port']);
|
||||
|
||||
$this->addClassesToCompile(array(
|
||||
'Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface',
|
||||
'Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface',
|
||||
'Symfony\\Component\\Routing\\RouterInterface',
|
||||
'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
|
||||
'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
|
||||
'Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface',
|
||||
'Symfony\\Component\\Routing\\RequestContextAwareInterface',
|
||||
'Symfony\\Component\\Routing\\RequestContext',
|
||||
'Symfony\\Component\\Routing\\Router',
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableUrlMatcher',
|
||||
@@ -291,13 +277,10 @@ class FrameworkExtension extends Extension
|
||||
{
|
||||
$loader->load('session.xml');
|
||||
|
||||
// session
|
||||
$container->getDefinition('session_listener')->addArgument($config['auto_start']);
|
||||
|
||||
// session storage
|
||||
$container->setAlias('session.storage', $config['storage_id']);
|
||||
$options = array();
|
||||
foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'auto_start', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) {
|
||||
foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) {
|
||||
if (isset($config[$key])) {
|
||||
$options[$key] = $config[$key];
|
||||
}
|
||||
@@ -319,7 +302,6 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$this->addClassesToCompile(array(
|
||||
'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
|
||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface',
|
||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
|
||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\FileSessionHandler',
|
||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy',
|
||||
@@ -411,14 +393,6 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$this->addClassesToCompile(array(
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables',
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Templating\\EngineInterface',
|
||||
'Symfony\\Component\\Templating\\StreamingEngineInterface',
|
||||
'Symfony\\Component\\Templating\\TemplateNameParserInterface',
|
||||
'Symfony\\Component\\Templating\\TemplateNameParser',
|
||||
'Symfony\\Component\\Templating\\EngineInterface',
|
||||
'Symfony\\Component\\Config\\FileLocatorInterface',
|
||||
'Symfony\\Component\\Templating\\TemplateReferenceInterface',
|
||||
'Symfony\\Component\\Templating\\TemplateReference',
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference',
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser',
|
||||
$container->findDefinition('templating.locator')->getClass(),
|
||||
@@ -426,9 +400,6 @@ class FrameworkExtension extends Extension
|
||||
|
||||
if (in_array('php', $config['engines'], true)) {
|
||||
$this->addClassesToCompile(array(
|
||||
'Symfony\\Component\\Templating\\PhpEngine',
|
||||
'Symfony\\Component\\Templating\\Loader\\LoaderInterface',
|
||||
'Symfony\\Component\\Templating\\Storage\\Storage',
|
||||
'Symfony\\Component\\Templating\\Storage\\FileStorage',
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Templating\\PhpEngine',
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Templating\\Loader\\FilesystemLoader',
|
||||
|
@@ -33,15 +33,9 @@ class SessionListener implements EventSubscriberInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $autoStart;
|
||||
|
||||
public function __construct(ContainerInterface $container, $autoStart = false)
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->autoStart = $autoStart;
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
@@ -50,20 +44,12 @@ class SessionListener implements EventSubscriberInterface
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->container->has('session')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
if ($request->hasSession()) {
|
||||
if (!$this->container->has('session') || $request->hasSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request->setSession($session = $this->container->get('session'));
|
||||
|
||||
if ($this->autoStart || $request->hasPreviousSession()) {
|
||||
$session->start();
|
||||
}
|
||||
$request->setSession($this->container->get('session'));
|
||||
}
|
||||
|
||||
static public function getSubscribedEvents()
|
||||
|
@@ -32,7 +32,7 @@ abstract class HttpCache extends BaseHttpCache
|
||||
* Constructor.
|
||||
*
|
||||
* @param HttpKernelInterface $kernel An HttpKernelInterface instance
|
||||
* @param String $cacheDir The cache directory (default used if null)
|
||||
* @param string $cacheDir The cache directory (default used if null)
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $kernel, $cacheDir = null)
|
||||
{
|
||||
|
@@ -21,7 +21,7 @@
|
||||
* @author: Albert Jessurum <ajessu@gmail.com>
|
||||
*/
|
||||
|
||||
if (is_file($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $_SERVER['REQUEST_URI'])) {
|
||||
if (is_file($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $_SERVER['SCRIPT_NAME'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -89,6 +89,7 @@
|
||||
<tag name="kernel.event_subscriber" />
|
||||
<tag name="monolog.logger" channel="request" />
|
||||
<argument type="service" id="router" />
|
||||
<argument type="service" id="router.request_context" on-invalid="ignore" />
|
||||
<argument type="service" id="logger" on-invalid="ignore" />
|
||||
</service>
|
||||
</services>
|
||||
|
@@ -21,6 +21,7 @@
|
||||
<xsd:element name="annotations" type="annotations" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:all>
|
||||
|
||||
<!-- charset is deprecated and will be removed in 2.2 -->
|
||||
<xsd:attribute name="charset" type="xsd:string" />
|
||||
<xsd:attribute name="trust-proxy-headers" type="xsd:string" />
|
||||
<xsd:attribute name="ide" type="xsd:string" />
|
||||
@@ -84,9 +85,9 @@
|
||||
<xsd:attribute name="domain" type="xsd:string" />
|
||||
<xsd:attribute name="secure" type="xsd:boolean" />
|
||||
<xsd:attribute name="httponly" type="xsd:boolean" />
|
||||
<xsd:attribute name="auto-start" type="xsd:boolean" />
|
||||
<!-- end of deprecated attributes -->
|
||||
<xsd:attribute name="cache-limiter" type="xsd:string" />
|
||||
<xsd:attribute name="auto-start" type="xsd:boolean" />
|
||||
<xsd:attribute name="gc-maxlifetime" type="xsd:string" />
|
||||
<xsd:attribute name="gc-divisor" type="xsd:string" />
|
||||
<xsd:attribute name="gc-probability" type="xsd:string" />
|
||||
|
@@ -7,6 +7,7 @@
|
||||
<parameters>
|
||||
<parameter key="templating.engine.delegating.class">Symfony\Bundle\FrameworkBundle\Templating\DelegatingEngine</parameter>
|
||||
<parameter key="templating.name_parser.class">Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser</parameter>
|
||||
<parameter key="templating.filename_parser.class">Symfony\Bundle\FrameworkBundle\Templating\TemplateFilenameParser</parameter>
|
||||
<parameter key="templating.cache_warmer.template_paths.class">Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplatePathsCacheWarmer</parameter>
|
||||
<parameter key="templating.locator.class">Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator</parameter>
|
||||
<parameter key="templating.loader.filesystem.class">Symfony\Bundle\FrameworkBundle\Templating\Loader\FilesystemLoader</parameter>
|
||||
@@ -25,6 +26,8 @@
|
||||
<argument type="service" id="kernel" />
|
||||
</service>
|
||||
|
||||
<service id="templating.filename_parser" class="%templating.filename_parser.class%" />
|
||||
|
||||
<service id="templating.locator" class="%templating.locator.class%" public="false">
|
||||
<argument type="service" id="file_locator" />
|
||||
<argument>%kernel.cache_dir%</argument>
|
||||
@@ -32,7 +35,7 @@
|
||||
|
||||
<service id="templating.finder" class="%templating.finder.class%" public="false">
|
||||
<argument type="service" id="kernel" />
|
||||
<argument type="service" id="templating.name_parser" />
|
||||
<argument type="service" id="templating.filename_parser" />
|
||||
<argument>%kernel.root_dir%/Resources</argument>
|
||||
</service>
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
<?php if ($required) { $label_attr['class'] = trim((isset($label_attr['class']) ? $label_attr['class'] : '').' required'); } ?>
|
||||
<?php if (!$compound) { $label_attr['for'] = $id; } ?>
|
||||
<?php if (!$label) { $label = $view['form']->humanize($name); } ?>
|
||||
<label <?php foreach ($label_attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>><?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>
|
||||
|
@@ -16,6 +16,8 @@ use Symfony\Component\Routing\RequestContext;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* This Router only creates the Loader only when the cache is empty.
|
||||
@@ -72,9 +74,12 @@ class Router extends BaseRouter implements WarmableInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces placeholders with service container parameter values in route defaults and requirements.
|
||||
* Replaces placeholders with service container parameter values in:
|
||||
* - the route defaults,
|
||||
* - the route requirements,
|
||||
* - the route pattern.
|
||||
*
|
||||
* @param $collection
|
||||
* @param RouteCollection $collection
|
||||
*/
|
||||
private function resolveParameters(RouteCollection $collection)
|
||||
{
|
||||
@@ -83,27 +88,60 @@ class Router extends BaseRouter implements WarmableInterface
|
||||
$this->resolveParameters($route);
|
||||
} else {
|
||||
foreach ($route->getDefaults() as $name => $value) {
|
||||
if (!$value || '%' !== $value[0] || '%' !== substr($value, -1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = substr($value, 1, -1);
|
||||
if ($this->container->hasParameter($key)) {
|
||||
$route->setDefault($name, $this->container->getParameter($key));
|
||||
}
|
||||
$route->setDefault($name, $this->resolveString($value));
|
||||
}
|
||||
|
||||
foreach ($route->getRequirements() as $name => $value) {
|
||||
if (!$value || '%' !== $value[0] || '%' !== substr($value, -1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = substr($value, 1, -1);
|
||||
if ($this->container->hasParameter($key)) {
|
||||
$route->setRequirement($name, $this->container->getParameter($key));
|
||||
}
|
||||
$route->setRequirement($name, $this->resolveString($value));
|
||||
}
|
||||
|
||||
$route->setPattern($this->resolveString($route->getPattern()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces placeholders with the service container parameters in the given string.
|
||||
*
|
||||
* @param string $value The source string which might contain %placeholders%
|
||||
*
|
||||
* @return string A string where the placeholders have been replaced.
|
||||
*
|
||||
* @throws ParameterNotFoundException When a placeholder does not exist as a container parameter
|
||||
* @throws RuntimeException When a container value is not a string or a numeric value
|
||||
*/
|
||||
private function resolveString($value)
|
||||
{
|
||||
$container = $this->container;
|
||||
|
||||
$escapedValue = preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($container, $value) {
|
||||
// skip %%
|
||||
if (!isset($match[1])) {
|
||||
return '%%';
|
||||
}
|
||||
|
||||
$key = strtolower($match[1]);
|
||||
|
||||
if (!$container->hasParameter($key)) {
|
||||
throw new ParameterNotFoundException($key);
|
||||
}
|
||||
|
||||
$resolved = $container->getParameter($key);
|
||||
|
||||
if (is_string($resolved) || is_numeric($resolved)) {
|
||||
return (string) $resolved;
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf(
|
||||
'A string value must be composed of strings and/or numbers,' .
|
||||
'but found parameter "%s" of type %s inside string value "%s".',
|
||||
$key,
|
||||
gettype($resolved),
|
||||
$value)
|
||||
);
|
||||
|
||||
}, $value);
|
||||
|
||||
return str_replace('%%', '%', $escapedValue);
|
||||
}
|
||||
}
|
||||
|
@@ -314,6 +314,11 @@ class FormHelper extends Helper
|
||||
return trim($this->engine->render($template, $variables));
|
||||
}
|
||||
|
||||
public function humanize($text)
|
||||
{
|
||||
return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text))));
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'form';
|
||||
|
40
vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateFilenameParser.php
vendored
Normal file
40
vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateFilenameParser.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Templating;
|
||||
|
||||
use Symfony\Component\Templating\TemplateNameParserInterface;
|
||||
|
||||
/**
|
||||
* TemplateFilenameParser converts template filenames to
|
||||
* TemplateReferenceInterface instances.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TemplateFilenameParser implements TemplateNameParserInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($file)
|
||||
{
|
||||
$parts = explode('/', strtr($file, '\\', '/'));
|
||||
|
||||
$elements = explode('.', array_pop($parts));
|
||||
if (3 > count($elements)) {
|
||||
return false;
|
||||
}
|
||||
$engine = array_pop($elements);
|
||||
$format = array_pop($elements);
|
||||
|
||||
return new TemplateReference('', implode('/', $parts), implode('.', $elements), $format, $engine);
|
||||
}
|
||||
}
|
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Templating;
|
||||
|
||||
use Symfony\Component\Templating\TemplateNameParser as BaseTemplateNameParser;
|
||||
use Symfony\Component\Templating\TemplateNameParserInterface;
|
||||
use Symfony\Component\Templating\TemplateReferenceInterface;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
|
||||
@@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\KernelInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TemplateNameParser extends BaseTemplateNameParser
|
||||
class TemplateNameParser implements TemplateNameParserInterface
|
||||
{
|
||||
protected $kernel;
|
||||
protected $cache;
|
||||
@@ -80,26 +80,4 @@ class TemplateNameParser extends BaseTemplateNameParser
|
||||
|
||||
return $this->cache[$name] = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a filename to a template.
|
||||
*
|
||||
* @param string $file The filename
|
||||
*
|
||||
* @return TemplateReferenceInterface A template
|
||||
*/
|
||||
public function parseFromFilename($file)
|
||||
{
|
||||
$parts = explode('/', strtr($file, '\\', '/'));
|
||||
|
||||
$elements = explode('.', array_pop($parts));
|
||||
if (3 > count($elements)) {
|
||||
return false;
|
||||
}
|
||||
$engine = array_pop($elements);
|
||||
$format = array_pop($elements);
|
||||
|
||||
return new TemplateReference('', implode('/', $parts), implode('.', $elements), $format, $engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;
|
||||
use Symfony\Bundle\FrameworkBundle\Templating\TemplateFilenameParser;
|
||||
use Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplateFinder;
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\BaseBundle\BaseBundle;
|
||||
|
||||
@@ -38,7 +38,7 @@ class TemplateFinderTest extends TestCase
|
||||
->will($this->returnValue(array('BaseBundle' => new BaseBundle())))
|
||||
;
|
||||
|
||||
$parser = new TemplateNameParser($kernel);
|
||||
$parser = new TemplateFilenameParser($kernel);
|
||||
|
||||
$finder = new TemplateFinder($kernel, $parser, __DIR__.'/../Fixtures/Resources');
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
$container->loadFromExtension('framework', array(
|
||||
'secret' => 's3cr3t',
|
||||
'session' => array(
|
||||
'auto_start' => true,
|
||||
'storage_id' => 'session.storage.native',
|
||||
'handler_id' => 'session.handler.native_file',
|
||||
'name' => '_SYMFONY',
|
||||
|
@@ -3,7 +3,6 @@
|
||||
$container->loadFromExtension('framework', array(
|
||||
'secret' => 's3cr3t',
|
||||
'session' => array(
|
||||
'auto_start' => true,
|
||||
'storage_id' => 'session.storage.native',
|
||||
'handler_id' => 'session.handler.native_file',
|
||||
'name' => '_SYMFONY',
|
||||
|
@@ -19,7 +19,6 @@ $container->loadFromExtension('framework', array(
|
||||
'type' => 'xml',
|
||||
),
|
||||
'session' => array(
|
||||
'auto_start' => true,
|
||||
'storage_id' => 'session.storage.native',
|
||||
'handler_id' => 'session.handler.native_file',
|
||||
'name' => '_SYMFONY',
|
||||
|
@@ -7,6 +7,6 @@
|
||||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config secret="s3cr3t">
|
||||
<framework:session auto-start="true" storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" lifetime="2012" path="/sf2" domain="sf2.example.com" secure="false" httponly="false" cookie-lifetime="86400" cookie-path="/" cookie-domain="example.com" cookie-secure="true" cookie-httponly="true" />
|
||||
<framework:session storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" lifetime="2012" path="/sf2" domain="sf2.example.com" secure="false" httponly="false" cookie-lifetime="86400" cookie-path="/" cookie-domain="example.com" cookie-secure="true" cookie-httponly="true" />
|
||||
</framework:config>
|
||||
</container>
|
||||
|
@@ -7,6 +7,6 @@
|
||||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config secret="s3cr3t">
|
||||
<framework:session auto-start="true" storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" lifetime="2012" path="/sf2" domain="sf2.example.com" secure="false" httponly="false" cookie-lifetime="86400" cookie-path="/" cookie-httponly="true" />
|
||||
<framework:session storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" lifetime="2012" path="/sf2" domain="sf2.example.com" secure="false" httponly="false" cookie-lifetime="86400" cookie-path="/" cookie-httponly="true" />
|
||||
</framework:config>
|
||||
</container>
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<framework:esi enabled="true" />
|
||||
<framework:profiler only-exceptions="true" />
|
||||
<framework:router resource="%kernel.root_dir%/config/routing.xml" type="xml" />
|
||||
<framework:session auto-start="true" gc-maxlifetime="90000" gc-probability="1" gc-divisor="108" storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" cookie-lifetime="86400" cookie-path="/" cookie-domain="example.com" cookie-secure="true" cookie-httponly="true" save-path="/path/to/sessions" />
|
||||
<framework:session gc-maxlifetime="90000" gc-probability="1" gc-divisor="108" storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" cookie-lifetime="86400" cookie-path="/" cookie-domain="example.com" cookie-secure="true" cookie-httponly="true" save-path="/path/to/sessions" />
|
||||
<framework:templating assets-version="SomeVersionScheme" cache="/path/to/cache" >
|
||||
<framework:loader>loader.foo</framework:loader>
|
||||
<framework:loader>loader.bar</framework:loader>
|
||||
|
@@ -1,7 +1,6 @@
|
||||
framework:
|
||||
secret: s3cr3t
|
||||
session:
|
||||
auto_start: true
|
||||
storage_id: session.storage.native
|
||||
handler_id: session.handler.native_file
|
||||
name: _SYMFONY
|
||||
|
@@ -1,7 +1,6 @@
|
||||
framework:
|
||||
secret: s3cr3t
|
||||
session:
|
||||
auto_start: true
|
||||
storage_id: session.storage.native
|
||||
handler_id: session.handler.native_file
|
||||
name: _SYMFONY
|
||||
|
@@ -13,7 +13,6 @@ framework:
|
||||
resource: %kernel.root_dir%/config/routing.xml
|
||||
type: xml
|
||||
session:
|
||||
auto_start: true
|
||||
storage_id: session.storage.native
|
||||
handler_id: session.handler.native_file
|
||||
name: _SYMFONY
|
||||
|
@@ -77,7 +77,6 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
|
||||
$this->assertTrue($container->hasDefinition('session'), '->registerSessionConfiguration() loads session.xml');
|
||||
$this->assertEquals('fr', $container->getParameter('kernel.default_locale'));
|
||||
$this->assertTrue($container->getDefinition('session_listener')->getArgument(1));
|
||||
$this->assertEquals('session.storage.native', (string) $container->getAlias('session.storage'));
|
||||
$this->assertEquals('session.handler.native_file', (string) $container->getAlias('session.handler'));
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
framework:
|
||||
charset: UTF-8
|
||||
secret: test
|
||||
csrf_protection:
|
||||
enabled: true
|
||||
@@ -9,7 +8,6 @@ framework:
|
||||
test: ~
|
||||
default_locale: en
|
||||
session:
|
||||
auto_start: true
|
||||
storage_id: session.storage.mock_file
|
||||
|
||||
services:
|
||||
|
@@ -17,72 +17,151 @@ use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
class RoutingTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testPlaceholders()
|
||||
public function testDefaultsPlaceholders()
|
||||
{
|
||||
$routes = new RouteCollection();
|
||||
$routes->add('foo', new Route('/foo', array(
|
||||
'foo' => '%foo%',
|
||||
'bar' => '%bar%',
|
||||
'foobar' => 'foobar',
|
||||
'foo1' => '%foo',
|
||||
'foo2' => 'foo%',
|
||||
'foo3' => 'f%o%o',
|
||||
), array(
|
||||
'foo' => '%foo%',
|
||||
'bar' => '%bar%',
|
||||
'foobar' => 'foobar',
|
||||
'foo1' => '%foo',
|
||||
'foo2' => 'foo%',
|
||||
'foo3' => 'f%o%o',
|
||||
)));
|
||||
|
||||
$routes->add('foo', new Route(
|
||||
'/foo',
|
||||
array(
|
||||
'foo' => 'before_%parameter.foo%',
|
||||
'bar' => '%parameter.bar%_after',
|
||||
'baz' => '%%unescaped%%',
|
||||
),
|
||||
array(
|
||||
)
|
||||
));
|
||||
|
||||
$sc = $this->getServiceContainer($routes);
|
||||
$sc->expects($this->at(1))->method('hasParameter')->will($this->returnValue(false));
|
||||
$sc->expects($this->at(2))->method('hasParameter')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(3))->method('getParameter')->will($this->returnValue('bar'));
|
||||
$sc->expects($this->at(4))->method('hasParameter')->will($this->returnValue(false));
|
||||
$sc->expects($this->at(5))->method('hasParameter')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(6))->method('getParameter')->will($this->returnValue('bar'));
|
||||
|
||||
$sc->expects($this->at(1))->method('hasParameter')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(2))->method('getParameter')->will($this->returnValue('foo'));
|
||||
$sc->expects($this->at(3))->method('hasParameter')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(4))->method('getParameter')->will($this->returnValue('bar'));
|
||||
|
||||
$router = new Router($sc, 'foo');
|
||||
$route = $router->getRouteCollection()->get('foo');
|
||||
|
||||
$this->assertEquals('%foo%', $route->getDefault('foo'));
|
||||
$this->assertEquals('bar', $route->getDefault('bar'));
|
||||
$this->assertEquals('foobar', $route->getDefault('foobar'));
|
||||
$this->assertEquals('%foo', $route->getDefault('foo1'));
|
||||
$this->assertEquals('foo%', $route->getDefault('foo2'));
|
||||
$this->assertEquals('f%o%o', $route->getDefault('foo3'));
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'foo' => 'before_foo',
|
||||
'bar' => 'bar_after',
|
||||
'baz' => '%unescaped%',
|
||||
),
|
||||
$route->getDefaults()
|
||||
);
|
||||
}
|
||||
|
||||
$this->assertEquals('%foo%', $route->getRequirement('foo'));
|
||||
$this->assertEquals('bar', $route->getRequirement('bar'));
|
||||
$this->assertEquals('foobar', $route->getRequirement('foobar'));
|
||||
$this->assertEquals('%foo', $route->getRequirement('foo1'));
|
||||
$this->assertEquals('foo%', $route->getRequirement('foo2'));
|
||||
$this->assertEquals('f%o%o', $route->getRequirement('foo3'));
|
||||
public function testRequirementsPlaceholders()
|
||||
{
|
||||
$routes = new RouteCollection();
|
||||
|
||||
$routes->add('foo', new Route(
|
||||
'/foo',
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'foo' => 'before_%parameter.foo%',
|
||||
'bar' => '%parameter.bar%_after',
|
||||
'baz' => '%%unescaped%%',
|
||||
)
|
||||
));
|
||||
|
||||
$sc = $this->getServiceContainer($routes);
|
||||
|
||||
$sc->expects($this->at(1))->method('hasParameter')->with('parameter.foo')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(2))->method('getParameter')->with('parameter.foo')->will($this->returnValue('foo'));
|
||||
$sc->expects($this->at(3))->method('hasParameter')->with('parameter.bar')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(4))->method('getParameter')->with('parameter.bar')->will($this->returnValue('bar'));
|
||||
|
||||
$router = new Router($sc, 'foo');
|
||||
$route = $router->getRouteCollection()->get('foo');
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'foo' => 'before_foo',
|
||||
'bar' => 'bar_after',
|
||||
'baz' => '%unescaped%',
|
||||
),
|
||||
$route->getRequirements()
|
||||
);
|
||||
}
|
||||
|
||||
public function testPatternPlaceholders()
|
||||
{
|
||||
$routes = new RouteCollection();
|
||||
|
||||
$routes->add('foo', new Route('/before/%parameter.foo%/after/%%unescaped%%'));
|
||||
|
||||
$sc = $this->getServiceContainer($routes);
|
||||
|
||||
$sc->expects($this->at(1))->method('hasParameter')->with('parameter.foo')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(2))->method('getParameter')->with('parameter.foo')->will($this->returnValue('foo'));
|
||||
|
||||
$router = new Router($sc, 'foo');
|
||||
$route = $router->getRouteCollection()->get('foo');
|
||||
|
||||
$this->assertEquals(
|
||||
'/before/foo/after/%unescaped%',
|
||||
$route->getPattern()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException
|
||||
* @expectedExceptionMessage You have requested a non-existent parameter "nope".
|
||||
*/
|
||||
public function testExceptionOnNonExistentParameter()
|
||||
{
|
||||
$routes = new RouteCollection();
|
||||
|
||||
$routes->add('foo', new Route('/%nope%'));
|
||||
|
||||
$sc = $this->getServiceContainer($routes);
|
||||
|
||||
$sc->expects($this->at(1))->method('hasParameter')->with('nope')->will($this->returnValue(false));
|
||||
|
||||
$router = new Router($sc, 'foo');
|
||||
$router->getRouteCollection()->get('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
* @expectedExceptionMessage A string value must be composed of strings and/or numbers,but found parameter "object" of type object inside string value "/%object%".
|
||||
*/
|
||||
public function testExceptionOnNonStringParameter()
|
||||
{
|
||||
$routes = new RouteCollection();
|
||||
|
||||
$routes->add('foo', new Route('/%object%'));
|
||||
|
||||
$sc = $this->getServiceContainer($routes);
|
||||
|
||||
$sc->expects($this->at(1))->method('hasParameter')->with('object')->will($this->returnValue(true));
|
||||
$sc->expects($this->at(2))->method('getParameter')->with('object')->will($this->returnValue(new \stdClass()));
|
||||
|
||||
$router = new Router($sc, 'foo');
|
||||
$router->getRouteCollection()->get('foo');
|
||||
}
|
||||
|
||||
private function getServiceContainer(RouteCollection $routes)
|
||||
{
|
||||
$sc = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
||||
$sc
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->will($this->returnValue($this->getLoader($routes)))
|
||||
;
|
||||
|
||||
return $sc;
|
||||
}
|
||||
|
||||
private function getLoader(RouteCollection $routes)
|
||||
{
|
||||
$loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
|
||||
|
||||
$loader
|
||||
->expects($this->any())
|
||||
->method('load')
|
||||
->will($this->returnValue($routes))
|
||||
;
|
||||
|
||||
return $loader;
|
||||
$sc = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface');
|
||||
|
||||
$sc
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->will($this->returnValue($loader))
|
||||
;
|
||||
|
||||
return $sc;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\Templating;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\Templating\TemplateFilenameParser;
|
||||
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
|
||||
|
||||
class TemplateFilenameParserTest extends TestCase
|
||||
{
|
||||
protected $parser;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->parser = new TemplateFilenameParser();
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->parser = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilenameToTemplateProvider
|
||||
*/
|
||||
public function testParseFromFilename($file, $ref)
|
||||
{
|
||||
$template = $this->parser->parse($file);
|
||||
|
||||
if ($ref === false) {
|
||||
$this->assertFalse($template);
|
||||
} else {
|
||||
$this->assertEquals($template->getLogicalName(), $ref->getLogicalName());
|
||||
}
|
||||
}
|
||||
|
||||
public function getFilenameToTemplateProvider()
|
||||
{
|
||||
return array(
|
||||
array('/path/to/section/name.format.engine', new TemplateReference('', '/path/to/section', 'name', 'format', 'engine')),
|
||||
array('\\path\\to\\section\\name.format.engine', new TemplateReference('', '/path/to/section', 'name', 'format', 'engine')),
|
||||
array('name.format.engine', new TemplateReference('', '', 'name', 'format', 'engine')),
|
||||
array('name.format', false),
|
||||
array('name', false),
|
||||
);
|
||||
}
|
||||
}
|
@@ -84,30 +84,4 @@ class TemplateNameParserTest extends TestCase
|
||||
array('FooBundle:Post:foo:bar'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilenameToTemplateProvider
|
||||
*/
|
||||
public function testParseFromFilename($file, $ref)
|
||||
{
|
||||
$template = $this->parser->parseFromFilename($file);
|
||||
|
||||
if ($ref === false) {
|
||||
$this->assertFalse($template);
|
||||
} else {
|
||||
$this->assertEquals($template->getLogicalName(), $ref->getLogicalName());
|
||||
}
|
||||
}
|
||||
|
||||
public function getFilenameToTemplateProvider()
|
||||
{
|
||||
return array(
|
||||
array('/path/to/section/name.format.engine', new TemplateReference('', '/path/to/section', 'name', 'format', 'engine')),
|
||||
array('\\path\\to\\section\\name.format.engine', new TemplateReference('', '/path/to/section', 'name', 'format', 'engine')),
|
||||
array('name.format.engine', new TemplateReference('', '', 'name', 'format', 'engine')),
|
||||
array('name.format', false),
|
||||
array('name', false),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -80,6 +80,45 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('no translation', $translator->trans('no translation'));
|
||||
}
|
||||
|
||||
public function testGetLocale()
|
||||
{
|
||||
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
|
||||
|
||||
$request
|
||||
->expects($this->once())
|
||||
->method('getLocale')
|
||||
->will($this->returnValue('en'))
|
||||
;
|
||||
|
||||
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
||||
|
||||
$container
|
||||
->expects($this->exactly(2))
|
||||
->method('isScopeActive')
|
||||
->with('request')
|
||||
->will($this->onConsecutiveCalls(false, true))
|
||||
;
|
||||
|
||||
$container
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with('request')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
|
||||
$container
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('request')
|
||||
->will($this->returnValue($request))
|
||||
;
|
||||
|
||||
$translator = new Translator($container, new MessageSelector());
|
||||
|
||||
$this->assertNull($translator->getLocale());
|
||||
$this->assertSame('en', $translator->getLocale());
|
||||
}
|
||||
|
||||
protected function getCatalogue($locale, $messages)
|
||||
{
|
||||
$catalogue = new MessageCatalogue($locale);
|
||||
|
@@ -65,7 +65,7 @@ class Translator extends BaseTranslator
|
||||
*/
|
||||
public function getLocale()
|
||||
{
|
||||
if (null === $this->locale && $this->container->has('request')) {
|
||||
if (null === $this->locale && $this->container->isScopeActive('request') && $this->container->has('request')) {
|
||||
$this->locale = $this->container->get('request')->getLocale();
|
||||
}
|
||||
|
||||
|
@@ -303,9 +303,11 @@ class MainConfiguration implements ConfigurationInterface
|
||||
->example(array(
|
||||
'memory' => array(
|
||||
'name' => 'memory',
|
||||
'users' => array(
|
||||
'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'),
|
||||
'bar' => array('password' => 'bar', 'roles' => '[ROLE_USER, ROLE_ADMIN]')
|
||||
'memory' => array(
|
||||
'users' => array(
|
||||
'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'),
|
||||
'bar' => array('password' => 'bar', 'roles' => '[ROLE_USER, ROLE_ADMIN]')
|
||||
),
|
||||
)
|
||||
),
|
||||
'entity' => array('entity' => array('class' => 'SecurityBundle:User', 'property' => 'username'))
|
||||
|
@@ -91,21 +91,14 @@ class SecurityExtension extends Extension
|
||||
// add some required classes for compilation
|
||||
$this->addClassesToCompile(array(
|
||||
'Symfony\\Component\\Security\\Http\\Firewall',
|
||||
'Symfony\\Component\\Security\\Http\\FirewallMapInterface',
|
||||
'Symfony\\Component\\Security\\Core\\SecurityContext',
|
||||
'Symfony\\Component\\Security\\Core\\SecurityContextInterface',
|
||||
'Symfony\\Component\\Security\\Core\\User\\UserProviderInterface',
|
||||
'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationProviderManager',
|
||||
'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationManagerInterface',
|
||||
'Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager',
|
||||
'Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface',
|
||||
'Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface',
|
||||
|
||||
'Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap',
|
||||
'Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext',
|
||||
|
||||
'Symfony\\Component\\HttpFoundation\\RequestMatcher',
|
||||
'Symfony\\Component\\HttpFoundation\\RequestMatcherInterface',
|
||||
));
|
||||
}
|
||||
|
||||
@@ -181,7 +174,6 @@ class SecurityExtension extends Extension
|
||||
}
|
||||
|
||||
$this->addClassesToCompile(array(
|
||||
'Symfony\\Component\\Security\\Http\\AccessMapInterface',
|
||||
'Symfony\\Component\\Security\\Http\\AccessMap',
|
||||
));
|
||||
|
||||
@@ -551,13 +543,14 @@ class SecurityExtension extends Extension
|
||||
{
|
||||
$exceptionListenerId = 'security.exception_listener.'.$id;
|
||||
$listener = $container->setDefinition($exceptionListenerId, new DefinitionDecorator('security.exception_listener'));
|
||||
$listener->replaceArgument(3, null === $defaultEntryPoint ? null : new Reference($defaultEntryPoint));
|
||||
$listener->replaceArgument(3, $id);
|
||||
$listener->replaceArgument(4, null === $defaultEntryPoint ? null : new Reference($defaultEntryPoint));
|
||||
|
||||
// access denied handler setup
|
||||
if (isset($config['access_denied_handler'])) {
|
||||
$listener->replaceArgument(5, new Reference($config['access_denied_handler']));
|
||||
$listener->replaceArgument(6, new Reference($config['access_denied_handler']));
|
||||
} elseif (isset($config['access_denied_url'])) {
|
||||
$listener->replaceArgument(4, $config['access_denied_url']);
|
||||
$listener->replaceArgument(5, $config['access_denied_url']);
|
||||
}
|
||||
|
||||
return $exceptionListenerId;
|
||||
|
@@ -128,6 +128,7 @@
|
||||
|
||||
<service id="security.http_utils" class="%security.http_utils.class%" public="false">
|
||||
<argument type="service" id="router" on-invalid="null" />
|
||||
<argument type="service" id="router" on-invalid="null" />
|
||||
</service>
|
||||
|
||||
<!-- Validator -->
|
||||
|
@@ -158,6 +158,7 @@
|
||||
<argument type="service" id="security.context" />
|
||||
<argument type="service" id="security.authentication.trust_resolver" />
|
||||
<argument type="service" id="security.http_utils" />
|
||||
<argument />
|
||||
<argument type="service" id="security.authentication.entry_point" on-invalid="null" />
|
||||
<argument>%security.access.denied_url%</argument>
|
||||
<argument type="service" id="security.access.denied_handler" on-invalid="null" />
|
||||
|
@@ -1,5 +1,4 @@
|
||||
framework:
|
||||
charset: UTF-8
|
||||
secret: test
|
||||
csrf_protection:
|
||||
enabled: true
|
||||
@@ -9,7 +8,6 @@ framework:
|
||||
test: ~
|
||||
default_locale: en
|
||||
session:
|
||||
auto_start: true
|
||||
storage_id: session.storage.mock_file
|
||||
profiler: { only_exceptions: false }
|
||||
|
||||
|
@@ -92,14 +92,12 @@ class TwigExtension extends Extension
|
||||
|
||||
$this->addClassesToCompile(array(
|
||||
'Twig_Environment',
|
||||
'Twig_ExtensionInterface',
|
||||
'Twig_Extension',
|
||||
'Twig_Extension_Core',
|
||||
'Twig_Extension_Escaper',
|
||||
'Twig_Extension_Optimizer',
|
||||
'Twig_LoaderInterface',
|
||||
'Twig_Markup',
|
||||
'Twig_TemplateInterface',
|
||||
'Twig_Template',
|
||||
));
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager;
|
||||
|
||||
/**
|
||||
* ProfilerController.
|
||||
@@ -25,6 +26,8 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*/
|
||||
class ProfilerController extends ContainerAware
|
||||
{
|
||||
protected $templateManager;
|
||||
|
||||
/**
|
||||
* Renders a profiler panel for the given token.
|
||||
*
|
||||
@@ -49,13 +52,13 @@ class ProfilerController extends ContainerAware
|
||||
throw new NotFoundHttpException(sprintf('Panel "%s" is not available for token "%s".', $panel, $token));
|
||||
}
|
||||
|
||||
return $this->container->get('templating')->renderResponse($this->getTemplateName($profiler, $panel), array(
|
||||
return $this->container->get('templating')->renderResponse($this->getTemplateManager()->getName($profile, $panel), array(
|
||||
'token' => $token,
|
||||
'profile' => $profile,
|
||||
'collector' => $profile->getCollector($panel),
|
||||
'panel' => $panel,
|
||||
'page' => $page,
|
||||
'templates' => $this->getTemplates($profiler),
|
||||
'templates' => $this->getTemplateManager()->getTemplates($profile),
|
||||
'is_ajax' => $request->isXmlHttpRequest(),
|
||||
));
|
||||
}
|
||||
@@ -181,7 +184,7 @@ class ProfilerController extends ContainerAware
|
||||
return $this->container->get('templating')->renderResponse('WebProfilerBundle:Profiler:toolbar.html.twig', array(
|
||||
'position' => $position,
|
||||
'profile' => $profile,
|
||||
'templates' => $this->getTemplates($profiler),
|
||||
'templates' => $this->getTemplateManager()->getTemplates($profile),
|
||||
'profiler_url' => $url,
|
||||
));
|
||||
}
|
||||
@@ -308,51 +311,17 @@ class ProfilerController extends ContainerAware
|
||||
return new Response($phpinfo);
|
||||
}
|
||||
|
||||
protected function getTemplateNames($profiler)
|
||||
protected function getTemplateManager()
|
||||
{
|
||||
$templates = array();
|
||||
foreach ($this->container->getParameter('data_collector.templates') as $arguments) {
|
||||
if (null === $arguments) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($name, $template) = $arguments;
|
||||
if (!$profiler->has($name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('.html.twig' === substr($template, -10)) {
|
||||
$template = substr($template, 0, -10);
|
||||
}
|
||||
|
||||
if (!$this->container->get('templating')->exists($template.'.html.twig')) {
|
||||
throw new \UnexpectedValueException(sprintf('The profiler template "%s.html.twig" for data collector "%s" does not exist.', $template, $name));
|
||||
}
|
||||
|
||||
$templates[$name] = $template.'.html.twig';
|
||||
if (null === $this->templateManager) {
|
||||
$this->templateManager = new TemplateManager(
|
||||
$this->container->get('profiler'),
|
||||
$this->container->get('templating'),
|
||||
$this->container->get('twig'),
|
||||
$this->container->getParameter('data_collector.templates')
|
||||
);
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
protected function getTemplateName($profiler, $panel)
|
||||
{
|
||||
$templates = $this->getTemplateNames($profiler);
|
||||
|
||||
if (!isset($templates[$panel])) {
|
||||
throw new NotFoundHttpException(sprintf('Panel "%s" is not registered.', $panel));
|
||||
}
|
||||
|
||||
return $templates[$panel];
|
||||
}
|
||||
|
||||
protected function getTemplates($profiler)
|
||||
{
|
||||
$templates = $this->getTemplateNames($profiler);
|
||||
foreach ($templates as $name => $template) {
|
||||
$templates[$name] = $this->container->get('twig')->loadTemplate($template);
|
||||
}
|
||||
|
||||
return $templates;
|
||||
return $this->templateManager;
|
||||
}
|
||||
}
|
||||
|
123
vendor/symfony/symfony/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php
vendored
Normal file
123
vendor/symfony/symfony/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\WebProfilerBundle\Profiler;
|
||||
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||
use Symfony\Component\HttpKernel\Profiler\Profile;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
/**
|
||||
* Profiler Templates Manager
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Artur Wielogórski <wodor@wodor.net>
|
||||
*/
|
||||
class TemplateManager
|
||||
{
|
||||
protected $templating;
|
||||
protected $twig;
|
||||
protected $templates;
|
||||
protected $profiler;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Profiler $profiler
|
||||
* @param TwigEngine $templating
|
||||
* @param \Twig_Environment $twig
|
||||
* @param array $templates
|
||||
*/
|
||||
public function __construct(Profiler $profiler, EngineInterface $templating, \Twig_Environment $twig, array $templates)
|
||||
{
|
||||
$this->profiler = $profiler;
|
||||
$this->templating = $templating;
|
||||
$this->twig = $twig;
|
||||
$this->templates = $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the template name for a given panel.
|
||||
*
|
||||
* @param Profile $profile
|
||||
* @param string $panel
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
public function getName(Profile $profile, $panel)
|
||||
{
|
||||
$templates = $this->getNames($profile);
|
||||
|
||||
if (!isset($templates[$panel])) {
|
||||
throw new NotFoundHttpException(sprintf('Panel "%s" is not registered in profiler or is not present in viewed profile.', $panel));
|
||||
}
|
||||
|
||||
return $templates[$panel];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the templates for a given profile.
|
||||
*
|
||||
* @param Profile $profile
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplates(Profile $profile)
|
||||
{
|
||||
$templates = $this->getNames($profile);
|
||||
foreach ($templates as $name => $template) {
|
||||
$templates[$name] = $this->twig->loadTemplate($template);
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets template names of templates that are present in the viewed profile.
|
||||
*
|
||||
* @param Profile $profile
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
protected function getNames(Profile $profile)
|
||||
{
|
||||
$templates = array();
|
||||
|
||||
foreach ($this->templates as $arguments) {
|
||||
if (null === $arguments) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($name, $template) = $arguments;
|
||||
|
||||
if (!$this->profiler->has($name) || !$profile->hasCollector($name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('.html.twig' === substr($template, -10)) {
|
||||
$template = substr($template, 0, -10);
|
||||
}
|
||||
|
||||
if (!$this->templating->exists($template.'.html.twig')) {
|
||||
throw new \UnexpectedValueException(sprintf('The profiler template "%s.html.twig" for data collector "%s" does not exist.', $template, $name));
|
||||
}
|
||||
|
||||
$templates[$name] = $template.'.html.twig';
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
}
|
@@ -67,7 +67,7 @@
|
||||
<b>Token</b>
|
||||
<span>
|
||||
{% if profiler_url %}
|
||||
<a style="color: #2f2f2f" href="{{ profiler_url }}">{{ collector.token }}</a>
|
||||
<a href="{{ profiler_url }}">{{ collector.token }}</a>
|
||||
{% else %}
|
||||
{{ collector.token }}
|
||||
{% endif %}
|
||||
|
@@ -10,6 +10,17 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
{% if collector.calledlisteners|length %}
|
||||
{{ block('panelContent') }}
|
||||
{% else %}
|
||||
<h2>Events</h2>
|
||||
<p>
|
||||
<em>No events have been recorded. Are you sure that debugging is enabled in the kernel ?</em>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block panelContent %}
|
||||
<h2>Called Listeners</h2>
|
||||
|
||||
<table>
|
||||
|
@@ -14,14 +14,15 @@
|
||||
{% endif %}
|
||||
|
||||
{% block toolbar %}
|
||||
{% set total_time = collector.events|length ? '%.0f ms'|format(collector.totaltime) : 'n/a' %}
|
||||
{% set icon %}
|
||||
<img width="16" height="28" alt="Time" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAcCAYAAABoMT8aAAABqUlEQVR42t2Vv0sCYRyHX9OmEhsMx/YKGlwLQ69DTEUSBJEQEy5J3FRc/BsuiFqEIIcQIRo6ysUhoaBBWhoaGoJwiMJLglRKrs8bXgienmkQdPDAwX2f57j3fhFJkkbiPwTK5bIiFoul3kmPud8MqKMewDXpwuGww+12n9hsNhFnlijYf/Z4PDmO45Yxo+10ZFGTyWRMEItU6AdCx7lczkgd6n7J2Wx2xm63P6jJMk6n80YQBBN1aUDv9XqvlAbbm2LE7/cLODRB0un0VveAeoDC8/waCQQC18MGQqHQOcEKvw8bcLlcL6TfYnVtCrGRAlartUUYhmn1jKg/E3USjUYfhw3E4/F7ks/nz4YNFIvFQ/ogbUYikdefyqlU6gnuOg2YK5XKvs/n+xhUDgaDTVEUt+HO04ABOBA5isViDTU5kUi81Wq1AzhWMEkDGmAEq2C3UCjcYXGauDvfEsuyUjKZbJRKpVvM8IABU9SVX+cxYABmwIE9cFqtVi9xtgvsC2AHbIAFoKey0gdlHEyDObAEWLACFsEsMALdIJ80+dK0bTS95v7+v/AJnis0eO906QwAAAAASUVORK5CYII="/>
|
||||
<span>{{ '%.0f'|format(collector.totaltime) }} ms</span>
|
||||
<span>{{ total_time }}</span>
|
||||
{% endset %}
|
||||
{% set text %}
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Total time</b>
|
||||
<span>{{ '%.0f'|format(collector.totaltime) }} ms</span>
|
||||
<span>{{ total_time }}</span>
|
||||
</div>
|
||||
{% endset %}
|
||||
{% include 'WebProfilerBundle:Profiler:toolbar_item.html.twig' with { 'link': profiler_url } %}
|
||||
@@ -36,7 +37,16 @@
|
||||
|
||||
{% block panel %}
|
||||
<h2>Timeline</h2>
|
||||
{% if collector.events|length %}
|
||||
{{ block('panelContent') }}
|
||||
{% else %}
|
||||
<p>
|
||||
<em>No timing events have been recorded. Are you sure that debugging is enabled in the kernel ?</em>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block panelContent %}
|
||||
<form id="timeline-control" action="" method="get">
|
||||
<input type="hidden" name="panel" value="time" />
|
||||
<table>
|
||||
@@ -413,7 +423,6 @@
|
||||
elementThresholdControl.onclick = canvasAutoUpdateOnThresholdChange;
|
||||
elementThresholdControl.onchange = canvasAutoUpdateOnThresholdChange;
|
||||
elementThresholdControl.onkeyup = canvasAutoUpdateOnThresholdChange;
|
||||
|
||||
//]]></script>
|
||||
{% endblock %}
|
||||
|
||||
|
@@ -55,6 +55,11 @@
|
||||
.sf-toolbar-block .sf-toolbar-info-piece:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.sf-toolbar-block .sf-toolbar-info-piece a,
|
||||
.sf-toolbar-block .sf-toolbar-info-piece abbr {
|
||||
color: #2f2f2f;
|
||||
}
|
||||
|
||||
.sf-toolbar-block .sf-toolbar-info-piece b {
|
||||
display: inline-block;
|
||||
|
@@ -64,6 +64,9 @@ class WebProfilerExtensionTest extends TestCase
|
||||
$this->container->setParameter('kernel.cache_dir', __DIR__);
|
||||
$this->container->setParameter('kernel.debug', false);
|
||||
$this->container->setParameter('kernel.root_dir', __DIR__);
|
||||
$this->container->register('profiler', $this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\Profiler'))
|
||||
->addArgument(new Definition($this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface')));
|
||||
$this->container->setParameter('data_collector.templates', array());
|
||||
$this->container->set('kernel', $this->kernel);
|
||||
}
|
||||
|
||||
|
178
vendor/symfony/symfony/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php
vendored
Normal file
178
vendor/symfony/symfony/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\WebProfilerBundle\Tests\Profiler;
|
||||
|
||||
use Symfony\Bundle\WebProfilerBundle\Tests\TestCase;
|
||||
use Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager;
|
||||
|
||||
/**
|
||||
* Test for TemplateManager class.
|
||||
*
|
||||
* @author Artur Wielogórski <wodor@wodor.net>
|
||||
*/
|
||||
class TemplateManagerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Bundle\TwigBundle\TwigEngine
|
||||
*/
|
||||
protected $twigEngine;
|
||||
|
||||
/**
|
||||
* @var \Twig_Environment
|
||||
*/
|
||||
protected $twigEnvironment;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\HttpKernel\Profiler\Profiler
|
||||
*/
|
||||
protected $profiler;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $profile;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager
|
||||
*/
|
||||
protected $templateManager;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$profiler = $this->mockProfiler();
|
||||
$twigEngine = $this->mockTwigEngine();
|
||||
$twigEnvironment = $this->mockTwigEnvironment();
|
||||
$templates = array(
|
||||
'data_collector.foo'=>array('foo','FooBundle:Collector:foo'),
|
||||
'data_collector.bar'=>array('bar','FooBundle:Collector:bar'),
|
||||
'data_collector.baz'=>array('baz','FooBundle:Collector:baz')
|
||||
);
|
||||
|
||||
$this->templateManager = new TemplateManager($profiler, $twigEngine, $twigEnvironment, $templates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function testGetNameOfInvalidTemplate()
|
||||
{
|
||||
$profile = $this->mockProfile();
|
||||
$this->templateManager->getName($profile, 'notexistingpanel');
|
||||
}
|
||||
|
||||
/**
|
||||
* if template exists in both profile and profiler then its name should be returned
|
||||
*/
|
||||
public function testGetNameValidTemplate()
|
||||
{
|
||||
$this->profiler->expects($this->any())
|
||||
->method('has')
|
||||
->withAnyParameters()
|
||||
->will($this->returnCallback(array($this, 'profilerHasCallback')));
|
||||
|
||||
$profile = $this->mockProfile();
|
||||
$profile->expects($this->any())
|
||||
->method('hasCollector')
|
||||
->will($this->returnCallback(array($this, 'profileHasCollectorCallback')));
|
||||
|
||||
$this->assertEquals('FooBundle:Collector:foo.html.twig', $this->templateManager->getName($profile, 'foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* template should be loaded for 'foo' because other collectors are
|
||||
* missing in profile or in profiler
|
||||
*/
|
||||
public function testGetTemplates()
|
||||
{
|
||||
|
||||
$profile = $this->mockProfile();
|
||||
$profile->expects($this->any())
|
||||
->method('hasCollector')
|
||||
->will($this->returnCallback(array($this, 'profilerHasCallback')));
|
||||
|
||||
$this->profiler->expects($this->any())
|
||||
->method('has')
|
||||
->withAnyParameters()
|
||||
->will($this->returnCallback(array($this, 'profileHasCollectorCallback')));
|
||||
|
||||
$result = $this->templateManager->getTemplates($profile);
|
||||
$this->assertArrayHasKey('foo',$result);
|
||||
$this->assertArrayNotHasKey('bar',$result);
|
||||
$this->assertArrayNotHasKey('baz',$result);
|
||||
}
|
||||
|
||||
public function profilerHasCallback($panel)
|
||||
{
|
||||
switch ($panel) {
|
||||
case 'foo':
|
||||
case 'bar':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function profileHasCollectorCallback($panel)
|
||||
{
|
||||
switch ($panel) {
|
||||
case 'foo':
|
||||
case 'baz':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function mockProfile()
|
||||
{
|
||||
$this->profile = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profile')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
protected function mockTwigEnvironment()
|
||||
{
|
||||
$this->twigEnvironment = $this->getMockBuilder('Twig_Environment')->getMock();
|
||||
|
||||
$this->twigEnvironment->expects($this->any())
|
||||
->method('loadTemplate')
|
||||
->will($this->returnValue('loadedTemplate'));
|
||||
|
||||
return $this->twigEnvironment;
|
||||
}
|
||||
|
||||
protected function mockTwigEngine()
|
||||
{
|
||||
$this->twigEngine = $this->getMockBuilder('Symfony\Bundle\TwigBundle\TwigEngine')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->twigEngine->expects($this->any())
|
||||
->method('exists')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
return $this->twigEngine;
|
||||
}
|
||||
|
||||
protected function mockProfiler()
|
||||
{
|
||||
$this->profiler = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
return $this->profiler;
|
||||
}
|
||||
}
|
@@ -55,7 +55,7 @@ class ApcClassLoader
|
||||
public function __construct($prefix, $classFinder)
|
||||
{
|
||||
if (!extension_loaded('apc')) {
|
||||
throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.');
|
||||
throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.');
|
||||
}
|
||||
|
||||
if (!method_exists($classFinder, 'findFile')) {
|
||||
|
@@ -19,6 +19,7 @@ namespace Symfony\Component\ClassLoader;
|
||||
class ClassCollectionLoader
|
||||
{
|
||||
static private $loaded;
|
||||
static private $seen;
|
||||
|
||||
/**
|
||||
* Loads a list of classes and caches them in one big file.
|
||||
@@ -41,14 +42,21 @@ class ClassCollectionLoader
|
||||
|
||||
self::$loaded[$name] = true;
|
||||
|
||||
$declared = array_merge(get_declared_classes(), get_declared_interfaces());
|
||||
if (function_exists('get_declared_traits')) {
|
||||
$declared = array_merge($declared, get_declared_traits());
|
||||
}
|
||||
|
||||
if ($adaptive) {
|
||||
// don't include already declared classes
|
||||
$classes = array_diff($classes, get_declared_classes(), get_declared_interfaces());
|
||||
$classes = array_diff($classes, $declared);
|
||||
|
||||
// the cache is different depending on which classes are already declared
|
||||
$name = $name.'-'.substr(md5(implode('|', $classes)), 0, 5);
|
||||
}
|
||||
|
||||
$classes = array_unique($classes);
|
||||
|
||||
$cache = $cacheDir.'/'.$name.$extension;
|
||||
|
||||
// auto-reload
|
||||
@@ -61,6 +69,9 @@ class ClassCollectionLoader
|
||||
$time = filemtime($cache);
|
||||
$meta = unserialize(file_get_contents($metadata));
|
||||
|
||||
sort($meta[1]);
|
||||
sort($classes);
|
||||
|
||||
if ($meta[1] != $classes) {
|
||||
$reload = true;
|
||||
} else {
|
||||
@@ -83,18 +94,17 @@ class ClassCollectionLoader
|
||||
|
||||
$files = array();
|
||||
$content = '';
|
||||
foreach ($classes as $class) {
|
||||
if (!class_exists($class) && !interface_exists($class) && (!function_exists('trait_exists') || !trait_exists($class))) {
|
||||
throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class));
|
||||
foreach (self::getOrderedClasses($classes) as $class) {
|
||||
if (in_array($class->getName(), $declared)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$r = new \ReflectionClass($class);
|
||||
$files[] = $r->getFileName();
|
||||
$files[] = $class->getFileName();
|
||||
|
||||
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
|
||||
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName()));
|
||||
|
||||
// add namespace declaration for global code
|
||||
if (!$r->inNamespace()) {
|
||||
if (!$class->inNamespace()) {
|
||||
$c = "\nnamespace\n{\n".self::stripComments($c)."\n}\n";
|
||||
} else {
|
||||
$c = self::fixNamespaceDeclarations('<?php '.$c);
|
||||
@@ -220,4 +230,82 @@ class ClassCollectionLoader
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an ordered array of passed classes including all their dependencies.
|
||||
*
|
||||
* @param array $classes
|
||||
*
|
||||
* @return array An array of sorted \ReflectionClass instances (dependencies added if needed)
|
||||
*
|
||||
* @throws \InvalidArgumentException When a class can't be loaded
|
||||
*/
|
||||
static private function getOrderedClasses(array $classes)
|
||||
{
|
||||
$map = array();
|
||||
self::$seen = array();
|
||||
foreach ($classes as $class) {
|
||||
try {
|
||||
$reflectionClass = new \ReflectionClass($class);
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class));
|
||||
}
|
||||
|
||||
$map = array_merge($map, self::getClassHierarchy($reflectionClass));
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
static private function getClassHierarchy(\ReflectionClass $class)
|
||||
{
|
||||
if (isset(self::$seen[$class->getName()])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
self::$seen[$class->getName()] = true;
|
||||
|
||||
$classes = array($class);
|
||||
$parent = $class;
|
||||
while (($parent = $parent->getParentClass()) && $parent->isUserDefined() && !isset(self::$seen[$parent->getName()])) {
|
||||
self::$seen[$parent->getName()] = true;
|
||||
|
||||
array_unshift($classes, $parent);
|
||||
}
|
||||
|
||||
if (function_exists('get_declared_traits')) {
|
||||
foreach ($classes as $c) {
|
||||
foreach (self::getTraits($c) as $trait) {
|
||||
self::$seen[$trait->getName()] = true;
|
||||
|
||||
array_unshift($classes, $trait);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($class->getInterfaces() as $interface) {
|
||||
if ($interface->isUserDefined() && !isset(self::$seen[$interface->getName()])) {
|
||||
self::$seen[$interface->getName()] = true;
|
||||
|
||||
array_unshift($classes, $interface);
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
static private function getTraits(\ReflectionClass $class)
|
||||
{
|
||||
$traits = $class->getTraits();
|
||||
$classes = array();
|
||||
while ($trait = array_pop($traits)) {
|
||||
if ($trait->isUserDefined() && !isset(self::$seen[$trait->getName()])) {
|
||||
$classes[] = $trait;
|
||||
|
||||
$traits = array_merge($traits, $trait->getTraits());
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
||||
|
@@ -13,8 +13,106 @@ namespace Symfony\Component\ClassLoader\Tests;
|
||||
|
||||
use Symfony\Component\ClassLoader\ClassCollectionLoader;
|
||||
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/CInterface.php';
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/B.php';
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/A.php';
|
||||
|
||||
class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getDifferentOrders
|
||||
*/
|
||||
public function testClassReordering(array $classes)
|
||||
{
|
||||
$expected = array(
|
||||
'ClassesWithParents\\CInterface',
|
||||
'ClassesWithParents\\B',
|
||||
'ClassesWithParents\\A',
|
||||
);
|
||||
|
||||
$r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
|
||||
$m = $r->getMethod('getOrderedClasses');
|
||||
$m->setAccessible(true);
|
||||
|
||||
$ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', $classes);
|
||||
|
||||
$this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
|
||||
}
|
||||
|
||||
public function getDifferentOrders()
|
||||
{
|
||||
return array(
|
||||
array(array(
|
||||
'ClassesWithParents\\A',
|
||||
'ClassesWithParents\\CInterface',
|
||||
'ClassesWithParents\\B',
|
||||
)),
|
||||
array(array(
|
||||
'ClassesWithParents\\B',
|
||||
'ClassesWithParents\\A',
|
||||
'ClassesWithParents\\CInterface',
|
||||
)),
|
||||
array(array(
|
||||
'ClassesWithParents\\CInterface',
|
||||
'ClassesWithParents\\B',
|
||||
'ClassesWithParents\\A',
|
||||
)),
|
||||
array(array(
|
||||
'ClassesWithParents\\A',
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getDifferentOrdersForTraits
|
||||
*/
|
||||
public function testClassWithTraitsReordering(array $classes)
|
||||
{
|
||||
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||
$this->markTestSkipped('Requires PHP > 5.4.0.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/ATrait.php';
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/BTrait.php';
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/D.php';
|
||||
require_once __DIR__.'/Fixtures/ClassesWithParents/E.php';
|
||||
|
||||
$expected = array(
|
||||
'ClassesWithParents\\CInterface',
|
||||
'ClassesWithParents\\CTrait',
|
||||
'ClassesWithParents\\ATrait',
|
||||
'ClassesWithParents\\BTrait',
|
||||
'ClassesWithParents\\B',
|
||||
'ClassesWithParents\\A',
|
||||
'ClassesWithParents\\D',
|
||||
'ClassesWithParents\\E',
|
||||
);
|
||||
|
||||
$r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
|
||||
$m = $r->getMethod('getOrderedClasses');
|
||||
$m->setAccessible(true);
|
||||
|
||||
$ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', $classes);
|
||||
|
||||
$this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
|
||||
}
|
||||
|
||||
public function getDifferentOrdersForTraits()
|
||||
{
|
||||
return array(
|
||||
array(array(
|
||||
'ClassesWithParents\\E',
|
||||
'ClassesWithParents\\ATrait',
|
||||
)),
|
||||
array(array(
|
||||
'ClassesWithParents\\E',
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
public function testFixNamespaceDeclarations()
|
||||
{
|
||||
$source = <<<EOF
|
||||
|
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
class A extends B {}
|
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
trait ATrait
|
||||
{
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
class B implements CInterface {}
|
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
trait BTrait
|
||||
{
|
||||
use ATrait;
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
interface CInterface {}
|
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
trait CTrait
|
||||
{
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
class D extends A
|
||||
{
|
||||
use BTrait;
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
class E extends D
|
||||
{
|
||||
use CTrait;
|
||||
}
|
@@ -344,7 +344,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the confifuration of a concrete node.
|
||||
* Validate the configuration of a concrete node.
|
||||
*
|
||||
* @param NodeInterface $node The related node
|
||||
*
|
||||
|
210
vendor/symfony/symfony/src/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php
vendored
Normal file
210
vendor/symfony/symfony/src/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Config\Tests\Definition\Builder;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
|
||||
|
||||
class ExprBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function testAlwaysExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->always($this->returnClosure('new_value'))
|
||||
->end();
|
||||
|
||||
$this->assertFinalizedValueIs('new_value', $test);
|
||||
}
|
||||
|
||||
public function testIfTrueExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifTrue()
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test, array('key'=>true));
|
||||
|
||||
$test = $this->getTestBuilder()
|
||||
->ifTrue( function($v){ return true; })
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test);
|
||||
|
||||
$test = $this->getTestBuilder()
|
||||
->ifTrue( function($v){ return false; })
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('value',$test);
|
||||
}
|
||||
|
||||
public function testIfStringExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifString()
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test);
|
||||
|
||||
$test = $this->getTestBuilder()
|
||||
->ifString()
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs(45, $test, array('key'=>45));
|
||||
|
||||
}
|
||||
|
||||
public function testIfNullExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifNull()
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test, array('key'=>null));
|
||||
|
||||
$test = $this->getTestBuilder()
|
||||
->ifNull()
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('value', $test);
|
||||
}
|
||||
|
||||
public function testIfArrayExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifArray()
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test, array('key'=>array()));
|
||||
|
||||
$test = $this->getTestBuilder()
|
||||
->ifArray()
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('value', $test);
|
||||
}
|
||||
|
||||
public function testIfInArrayExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifInArray(array('foo', 'bar', 'value'))
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test);
|
||||
|
||||
$test = $this->getTestBuilder()
|
||||
->ifInArray(array('foo', 'bar'))
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('value', $test);
|
||||
}
|
||||
|
||||
public function testIfNotInArrayExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifNotInArray(array('foo', 'bar'))
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test);
|
||||
|
||||
$test = $this->getTestBuilder()
|
||||
->ifNotInArray(array('foo', 'bar', 'value_from_config' ))
|
||||
->then($this->returnClosure('new_value'))
|
||||
->end();
|
||||
$this->assertFinalizedValueIs('new_value', $test);
|
||||
}
|
||||
|
||||
public function testThenEmptyArrayExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifString()
|
||||
->thenEmptyArray()
|
||||
->end();
|
||||
$this->assertFinalizedValueIs(array(), $test);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
*/
|
||||
public function testThenInvalid()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifString()
|
||||
->thenInvalid('Invalid value')
|
||||
->end();
|
||||
$this->finalizeTestBuilder($test);
|
||||
}
|
||||
|
||||
public function testThenUnsetExpression()
|
||||
{
|
||||
$test = $this->getTestBuilder()
|
||||
->ifString()
|
||||
->thenUnset()
|
||||
->end();
|
||||
$this->assertEquals(array(), $this->finalizeTestBuilder($test));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a test treebuilder with a variable node, and init the validation
|
||||
* @return TreeBuilder
|
||||
*/
|
||||
protected function getTestBuilder()
|
||||
{
|
||||
$builder = new TreeBuilder();
|
||||
return $builder
|
||||
->root('test')
|
||||
->children()
|
||||
->variableNode('key')
|
||||
->validate()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the validation process and finalize with the given config
|
||||
* @param TreeBuilder $testBuilder The tree builder to finalize
|
||||
* @param array $config The config you want to use for the finalization, if nothing provided
|
||||
* a simple array('key'=>'value') will be used
|
||||
* @return array The finalized config values
|
||||
*/
|
||||
protected function finalizeTestBuilder($testBuilder, $config=null)
|
||||
{
|
||||
return $testBuilder
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->buildTree()
|
||||
->finalize($config === null ? array('key'=>'value') : $config)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a closure that will return the given value
|
||||
* @param $val The value that the closure must return
|
||||
* @return Closure
|
||||
*/
|
||||
protected function returnClosure($val) {
|
||||
return function($v) use ($val) {
|
||||
return $val;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given test builder, will return the given value
|
||||
* @param mixed $value The value to test
|
||||
* @param TreeBuilder $test The tree builder to finalize
|
||||
* @param mixed $config The config values that new to be finalized
|
||||
*/
|
||||
protected function assertFinalizedValueIs($value, $treeBuilder, $config=null)
|
||||
{
|
||||
$this->assertEquals(array('key'=>$value), $this->finalizeTestBuilder($treeBuilder, $config));
|
||||
}
|
||||
}
|
@@ -882,7 +882,7 @@ class Application
|
||||
*/
|
||||
protected function getCommandName(InputInterface $input)
|
||||
{
|
||||
return $input->getFirstArgument('command');
|
||||
return $input->getFirstArgument();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -10,3 +10,6 @@ CHANGELOG
|
||||
* added Definition::clearTag()
|
||||
* component exceptions that inherit base SPL classes are now used exclusively
|
||||
(this includes dumped containers)
|
||||
* [BC BREAK] fixed unescaping of class arguments, method
|
||||
ParameterBag::unescapeValue() was made public
|
||||
|
||||
|
@@ -220,8 +220,8 @@ class Container implements IntrospectableContainerInterface
|
||||
/**
|
||||
* Gets a service.
|
||||
*
|
||||
* If a service is both defined through a set() method and
|
||||
* with a set*Service() method, the former has always precedence.
|
||||
* If a service is defined both through a set() method and
|
||||
* with a get{$id}Service() method, the former has always precedence.
|
||||
*
|
||||
* @param string $id The service identifier
|
||||
* @param integer $invalidBehavior The behavior when the service does not exist
|
||||
|
@@ -728,24 +728,28 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*/
|
||||
private function createService(Definition $definition, $id)
|
||||
{
|
||||
$parameterBag = $this->getParameterBag();
|
||||
|
||||
if (null !== $definition->getFile()) {
|
||||
require_once $this->getParameterBag()->resolveValue($definition->getFile());
|
||||
require_once $parameterBag->resolveValue($definition->getFile());
|
||||
}
|
||||
|
||||
$arguments = $this->resolveServices($this->getParameterBag()->resolveValue($definition->getArguments()));
|
||||
$arguments = $this->resolveServices(
|
||||
$parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments()))
|
||||
);
|
||||
|
||||
if (null !== $definition->getFactoryMethod()) {
|
||||
if (null !== $definition->getFactoryClass()) {
|
||||
$factory = $this->getParameterBag()->resolveValue($definition->getFactoryClass());
|
||||
$factory = $parameterBag->resolveValue($definition->getFactoryClass());
|
||||
} elseif (null !== $definition->getFactoryService()) {
|
||||
$factory = $this->get($this->getParameterBag()->resolveValue($definition->getFactoryService()));
|
||||
$factory = $this->get($parameterBag->resolveValue($definition->getFactoryService()));
|
||||
} else {
|
||||
throw new RuntimeException('Cannot create service from factory method without a factory service or factory class.');
|
||||
}
|
||||
|
||||
$service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments);
|
||||
} else {
|
||||
$r = new \ReflectionClass($this->getParameterBag()->resolveValue($definition->getClass()));
|
||||
$r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
|
||||
|
||||
$service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
|
||||
}
|
||||
@@ -774,11 +778,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
}
|
||||
|
||||
if ($ok) {
|
||||
call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
|
||||
call_user_func_array(array($service, $call[0]), $this->resolveServices($parameterBag->resolveValue($call[1])));
|
||||
}
|
||||
}
|
||||
|
||||
$properties = $this->resolveServices($this->getParameterBag()->resolveValue($definition->getProperties()));
|
||||
$properties = $this->resolveServices($parameterBag->resolveValue($definition->getProperties()));
|
||||
foreach ($properties as $name => $value) {
|
||||
$service->$name = $value;
|
||||
}
|
||||
@@ -787,7 +791,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
if (is_array($callable) && is_object($callable[0]) && $callable[0] instanceof Reference) {
|
||||
$callable[0] = $this->get((string) $callable[0]);
|
||||
} elseif (is_array($callable)) {
|
||||
$callable[0] = $this->getParameterBag()->resolveValue($callable[0]);
|
||||
$callable[0] = $parameterBag->resolveValue($callable[0]);
|
||||
}
|
||||
|
||||
if (!is_callable($callable)) {
|
||||
|
@@ -345,7 +345,7 @@ EOF
|
||||
;
|
||||
|
||||
$current = libxml_use_internal_errors(true);
|
||||
$valid = $dom->schemaValidateSource($source);
|
||||
$valid = @$dom->schemaValidateSource($source);
|
||||
foreach ($tmpfiles as $tmpfile) {
|
||||
@unlink($tmpfile);
|
||||
}
|
||||
|
@@ -253,7 +253,28 @@ class ParameterBag implements ParameterBagInterface
|
||||
return $this->resolved;
|
||||
}
|
||||
|
||||
private function unescapeValue($value)
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function escapeValue($value)
|
||||
{
|
||||
if (is_string($value)) {
|
||||
return str_replace('%', '%%', $value);
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$result = array();
|
||||
foreach ($value as $k => $v) {
|
||||
$result[$k] = $this->escapeValue($v);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function unescapeValue($value)
|
||||
{
|
||||
if (is_string($value)) {
|
||||
return str_replace('%%', '%', $value);
|
||||
|
@@ -94,4 +94,22 @@ interface ParameterBagInterface
|
||||
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
|
||||
*/
|
||||
function resolveValue($value);
|
||||
|
||||
/**
|
||||
* Escape parameter placeholders %
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function escapeValue($value);
|
||||
|
||||
/**
|
||||
* Unescape parameter placeholders %
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function unescapeValue($value);
|
||||
}
|
||||
|
@@ -251,9 +251,9 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$builder = new ContainerBuilder();
|
||||
$builder->register('bar', 'stdClass');
|
||||
$builder->register('foo1', 'FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar')));
|
||||
$builder->register('foo1', 'FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'), '%%unescape_it%%'));
|
||||
$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');
|
||||
$this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->arguments, '->createService() replaces parameters and service references in the arguments provided by the service definition');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -201,6 +201,22 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$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::escapeValue
|
||||
*/
|
||||
public function testEscapeValue()
|
||||
{
|
||||
$bag = new ParameterBag();
|
||||
|
||||
$bag->add(array(
|
||||
'foo' => $bag->escapeValue(array('bar' => array('ding' => 'I\'m a bar %foo %bar', 'zero' => null))),
|
||||
'bar' => $bag->escapeValue('I\'m a %foo%'),
|
||||
));
|
||||
|
||||
$this->assertEquals('I\'m a %%foo%%', $bag->get('bar'), '->escapeValue() escapes % by doubling it');
|
||||
$this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %%foo %%bar', 'zero' => null)), $bag->get('foo'), '->escapeValue() escapes % by doubling it');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve
|
||||
* @dataProvider stringsWithSpacesProvider
|
||||
|
@@ -12,3 +12,5 @@ CHANGELOG
|
||||
* added searching based on the file content via Finder::contains() and
|
||||
Finder::notContains()
|
||||
* added support for the != operator in the Comparator
|
||||
* [BC BREAK] filter expressions (used for file name and content) are no more
|
||||
considered as regexps but glob patterns when they are enclosed in '*' or '?'
|
||||
|
@@ -58,7 +58,7 @@ abstract class MultiplePcreFilterIterator extends \FilterIterator
|
||||
$end = substr($m[1], -1);
|
||||
|
||||
if ($start === $end) {
|
||||
return !preg_match('/[[:alnum:] \\\\]/', $start);
|
||||
return !preg_match('/[*?[:alnum:] \\\\]/', $start);
|
||||
}
|
||||
|
||||
if ($start === '{' && $end === '}') {
|
||||
|
@@ -38,6 +38,8 @@ class MultiplePcreFilterIteratorTest extends \PHPUnit_Framework_TestCase
|
||||
array('/foo/imsxu', true, 'valid regex with multiple modifiers'),
|
||||
array('#foo#', true, '"#" is a valid delimiter'),
|
||||
array('{foo}', true, '"{,}" is a valid delimiter pair'),
|
||||
array('*foo.*', false, '"*" is not considered as a valid delimiter'),
|
||||
array('?foo.?', false, '"?" is not considered as a valid delimiter'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -139,3 +139,5 @@ CHANGELOG
|
||||
* deprecated `getChildren` in Form and FormBuilder in favor of `all`
|
||||
* deprecated `hasChildren` in Form and FormBuilder in favor of `count`
|
||||
* FormBuilder now implements \IteratorAggregate
|
||||
* [BC BREAK] compound forms now always need a data mapper
|
||||
* FormBuilder now maintains the order when explicitely adding form builders as children
|
||||
|
@@ -23,22 +23,24 @@ class PropertyPathMapper implements DataMapperInterface
|
||||
*/
|
||||
public function mapDataToForms($data, array $forms)
|
||||
{
|
||||
if (!empty($data) && !is_array($data) && !is_object($data)) {
|
||||
throw new UnexpectedTypeException($data, 'Object, array or empty');
|
||||
if (null === $data || array() === $data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
$iterator = new VirtualFormAwareIterator($forms);
|
||||
$iterator = new \RecursiveIteratorIterator($iterator);
|
||||
if (!is_array($data) && !is_object($data)) {
|
||||
throw new UnexpectedTypeException($data, 'object, array or empty');
|
||||
}
|
||||
|
||||
foreach ($iterator as $form) {
|
||||
/* @var FormInterface $form */
|
||||
$propertyPath = $form->getPropertyPath();
|
||||
$config = $form->getConfig();
|
||||
$iterator = new VirtualFormAwareIterator($forms);
|
||||
$iterator = new \RecursiveIteratorIterator($iterator);
|
||||
|
||||
if (null !== $propertyPath && $config->getMapped()) {
|
||||
$form->setData($propertyPath->getValue($data));
|
||||
}
|
||||
foreach ($iterator as $form) {
|
||||
/* @var FormInterface $form */
|
||||
$propertyPath = $form->getPropertyPath();
|
||||
$config = $form->getConfig();
|
||||
|
||||
if (null !== $propertyPath && $config->getMapped()) {
|
||||
$form->setData($propertyPath->getValue($data));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,6 +50,14 @@ class PropertyPathMapper implements DataMapperInterface
|
||||
*/
|
||||
public function mapFormsToData(array $forms, &$data)
|
||||
{
|
||||
if (null === $data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_array($data) && !is_object($data)) {
|
||||
throw new UnexpectedTypeException($data, 'object, array or empty');
|
||||
}
|
||||
|
||||
$iterator = new VirtualFormAwareIterator($forms);
|
||||
$iterator = new \RecursiveIteratorIterator($iterator);
|
||||
|
||||
|
@@ -42,8 +42,9 @@ class FormType extends AbstractType
|
||||
->setMapped($options['mapped'])
|
||||
->setByReference($options['by_reference'])
|
||||
->setVirtual($options['virtual'])
|
||||
->setCompound($options['compound'])
|
||||
->setData($options['data'])
|
||||
->setDataMapper(new PropertyPathMapper())
|
||||
->setDataMapper($options['compound'] ? new PropertyPathMapper() : null)
|
||||
;
|
||||
|
||||
if ($options['trim']) {
|
||||
@@ -112,11 +113,11 @@ class FormType extends AbstractType
|
||||
'max_length' => $options['max_length'],
|
||||
'pattern' => $options['pattern'],
|
||||
'size' => null,
|
||||
'label' => $options['label'] ?: $this->humanize($form->getName()),
|
||||
'label' => $options['label'],
|
||||
'multipart' => false,
|
||||
'attr' => $options['attr'],
|
||||
'label_attr' => $options['label_attr'],
|
||||
'compound' => $options['compound'],
|
||||
'compound' => $form->getConfig()->getCompound(),
|
||||
'types' => $types,
|
||||
'translation_domain' => $translationDomain,
|
||||
));
|
||||
@@ -160,7 +161,7 @@ class FormType extends AbstractType
|
||||
}
|
||||
|
||||
return function (FormInterface $form) {
|
||||
return count($form) > 0 ? array() : '';
|
||||
return $form->getConfig()->getCompound() ? array() : '';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -226,9 +227,4 @@ class FormType extends AbstractType
|
||||
{
|
||||
return 'form';
|
||||
}
|
||||
|
||||
private function humanize($text)
|
||||
{
|
||||
return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text))));
|
||||
}
|
||||
}
|
||||
|
@@ -261,7 +261,12 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
return new ValueGuess(sprintf('.{%s,%s}', (string) $constraint->min, (string) $constraint->max), Guess::LOW_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Regex':
|
||||
return new ValueGuess($constraint->pattern, Guess::HIGH_CONFIDENCE );
|
||||
$htmlPattern = $constraint->getHtmlPattern();
|
||||
|
||||
if (null !== $htmlPattern) {
|
||||
return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Min':
|
||||
return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE);
|
||||
|
@@ -15,6 +15,7 @@ use Symfony\Component\Form\Exception\FormException;
|
||||
use Symfony\Component\Form\Exception\AlreadyBoundException;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Util\FormUtil;
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
@@ -130,6 +131,13 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$config = new UnmodifiableFormConfig($config);
|
||||
}
|
||||
|
||||
// Compound forms always need a data mapper, otherwise calls to
|
||||
// `setData` and `add` will not lead to the correct population of
|
||||
// the child forms.
|
||||
if ($config->getCompound() && !$config->getDataMapper()) {
|
||||
throw new FormException('Compound forms need a data mapper');
|
||||
}
|
||||
|
||||
$this->config = $config;
|
||||
|
||||
$this->setData($config->getData());
|
||||
@@ -345,7 +353,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$viewData = $this->normToView($normData);
|
||||
|
||||
// Validate if view data matches data class (unless empty)
|
||||
if (!empty($viewData)) {
|
||||
if (!FormUtil::isEmpty($viewData)) {
|
||||
$dataClass = $this->config->getDataClass();
|
||||
|
||||
$actualType = is_object($viewData) ? 'an instance of class ' . get_class($viewData) : ' a(n) ' . gettype($viewData);
|
||||
@@ -378,7 +386,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$this->viewData = $viewData;
|
||||
$this->synchronized = true;
|
||||
|
||||
if (count($this->children) > 0 && $this->config->getDataMapper()) {
|
||||
if ($this->config->getCompound()) {
|
||||
// Update child forms from the data
|
||||
$this->config->getDataMapper()->mapDataToForms($viewData, $this->children);
|
||||
}
|
||||
@@ -477,25 +485,29 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$this->config->getEventDispatcher()->dispatch(FormEvents::BIND_CLIENT_DATA, $event);
|
||||
$submittedData = $event->getData();
|
||||
|
||||
// Build the data in the view format
|
||||
// By default, the submitted data is also the data in view format
|
||||
$viewData = $submittedData;
|
||||
|
||||
if (count($this->children) > 0) {
|
||||
if (null === $viewData || '' === $viewData) {
|
||||
$viewData = array();
|
||||
}
|
||||
// Check whether the form is compound.
|
||||
// This check is preferrable over checking the number of children,
|
||||
// since forms without children may also be compound.
|
||||
// (think of empty collection forms)
|
||||
if ($this->config->getCompound()) {
|
||||
if (!is_array($submittedData)) {
|
||||
if (!FormUtil::isEmpty($submittedData)) {
|
||||
throw new UnexpectedTypeException($submittedData, 'array');
|
||||
}
|
||||
|
||||
if (!is_array($viewData)) {
|
||||
throw new UnexpectedTypeException($viewData, 'array');
|
||||
$submittedData = array();
|
||||
}
|
||||
|
||||
foreach ($this->children as $name => $child) {
|
||||
if (!isset($viewData[$name])) {
|
||||
$viewData[$name] = null;
|
||||
if (!isset($submittedData[$name])) {
|
||||
$submittedData[$name] = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($viewData as $name => $value) {
|
||||
foreach ($submittedData as $name => $value) {
|
||||
if ($this->has($name)) {
|
||||
$this->children[$name]->bind($value);
|
||||
} else {
|
||||
@@ -503,14 +515,13 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a data mapper, use old view data and merge
|
||||
// data from the children into it later
|
||||
if ($this->config->getDataMapper()) {
|
||||
$viewData = $this->getViewData();
|
||||
}
|
||||
// If the form is compound, the default data in view format
|
||||
// is reused. The data of the children is merged into this
|
||||
// default data using the data mapper.
|
||||
$viewData = $this->getViewData();
|
||||
}
|
||||
|
||||
if (null === $viewData || '' === $viewData) {
|
||||
if (FormUtil::isEmpty($viewData)) {
|
||||
$emptyData = $this->config->getEmptyData();
|
||||
|
||||
if ($emptyData instanceof \Closure) {
|
||||
@@ -522,7 +533,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
}
|
||||
|
||||
// Merge form data from children into existing view data
|
||||
if (count($this->children) > 0 && $this->config->getDataMapper() && null !== $viewData) {
|
||||
if ($this->config->getCompound()) {
|
||||
$this->config->getDataMapper()->mapFormsToData($this->children, $viewData);
|
||||
}
|
||||
|
||||
@@ -542,7 +553,6 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$this->config->getEventDispatcher()->dispatch(FormEvents::BIND_NORM_DATA, $event);
|
||||
$normData = $event->getData();
|
||||
|
||||
|
||||
// Synchronize representations - must not change the content!
|
||||
$modelData = $this->normToModel($normData);
|
||||
$viewData = $this->normToView($normData);
|
||||
@@ -591,7 +601,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
// Form bound without name
|
||||
$params = $request->request->all();
|
||||
$files = $request->files->all();
|
||||
} elseif (count($this->children) > 0) {
|
||||
} elseif ($this->config->getCompound()) {
|
||||
// Form bound with name and children
|
||||
$params = $request->request->get($name, array());
|
||||
$files = $request->files->get($name, array());
|
||||
@@ -692,7 +702,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
}
|
||||
}
|
||||
|
||||
return array() === $this->modelData || null === $this->modelData || '' === $this->modelData;
|
||||
return FormUtil::isEmpty($this->modelData) || array() === $this->modelData;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -841,13 +851,15 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
throw new AlreadyBoundException('You cannot add children to a bound form');
|
||||
}
|
||||
|
||||
if (!$this->config->getCompound()) {
|
||||
throw new FormException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?');
|
||||
}
|
||||
|
||||
$this->children[$child->getName()] = $child;
|
||||
|
||||
$child->setParent($this);
|
||||
|
||||
if ($this->config->getDataMapper()) {
|
||||
$this->config->getDataMapper()->mapDataToForms($this->getViewData(), array($child));
|
||||
}
|
||||
$this->config->getDataMapper()->mapDataToForms($this->getViewData(), array($child));
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -1037,9 +1049,12 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
*/
|
||||
private function normToView($value)
|
||||
{
|
||||
if (!$this->config->getViewTransformers()) {
|
||||
// Scalar values should always be converted to strings to
|
||||
// facilitate differentiation between empty ("") and zero (0).
|
||||
// Scalar values should be converted to strings to
|
||||
// facilitate differentiation between empty ("") and zero (0).
|
||||
// Only do this for simple forms, as the resulting value in
|
||||
// compound forms is passed to the data mapper and thus should
|
||||
// not be converted to a string before.
|
||||
if (!$this->config->getViewTransformers() && !$this->config->getCompound()) {
|
||||
return null === $value || is_scalar($value) ? (string) $value : $value;
|
||||
}
|
||||
|
||||
|
@@ -103,6 +103,8 @@ class FormBuilder extends FormConfig implements \IteratorAggregate, FormBuilderI
|
||||
throw new CircularReferenceException(is_string($type) ? $this->getFormFactory()->getType($type) : $type);
|
||||
}
|
||||
|
||||
// Add to "children" to maintain order
|
||||
$this->children[$child] = null;
|
||||
$this->unresolvedChildren[$child] = array(
|
||||
'type' => $type,
|
||||
'options' => $options,
|
||||
|
@@ -53,6 +53,11 @@ class FormConfig implements FormConfigEditorInterface
|
||||
*/
|
||||
private $virtual = false;
|
||||
|
||||
/**
|
||||
* @var Boolean
|
||||
*/
|
||||
private $compound = false;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@@ -356,6 +361,14 @@ class FormConfig implements FormConfigEditorInterface
|
||||
return $this->virtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCompound()
|
||||
{
|
||||
return $this->compound;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -632,6 +645,16 @@ class FormConfig implements FormConfigEditorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setCompound($compound)
|
||||
{
|
||||
$this->compound = $compound;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@@ -199,6 +199,17 @@ interface FormConfigEditorInterface extends FormConfigInterface
|
||||
*/
|
||||
function setVirtual($virtual);
|
||||
|
||||
/**
|
||||
* Sets whether the form should be compound.
|
||||
*
|
||||
* @param Boolean $compound Whether the form should be compound.
|
||||
*
|
||||
* @return self The configuration object.
|
||||
*
|
||||
* @see FormConfigInterface::getCompound()
|
||||
*/
|
||||
function setCompound($compound);
|
||||
|
||||
/**
|
||||
* Set the types.
|
||||
*
|
||||
|
@@ -65,6 +65,17 @@ interface FormConfigInterface
|
||||
*/
|
||||
function getVirtual();
|
||||
|
||||
/**
|
||||
* Returns whether the form is compound.
|
||||
*
|
||||
* This property is independent of whether the form actually has
|
||||
* children. A form can be compound and have no children at all, like
|
||||
* for example an empty collection form.
|
||||
*
|
||||
* @return Boolean Whether the form is compound.
|
||||
*/
|
||||
function getCompound();
|
||||
|
||||
/**
|
||||
* Returns the form types used to construct the form.
|
||||
*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user