diff --git a/UPDATE.ja.md b/UPDATE.ja.md index 286250835a..b7e82da154 100644 --- a/UPDATE.ja.md +++ b/UPDATE.ja.md @@ -115,6 +115,20 @@ beta1 から beta2 'allow_delete' => true, )); +* Request::hasSession() メソッドの名前は Request::hasPreviousSession() に変更されました。hasSession() メソッドはまだ存在しますが、 + セッションが以前のリクエストから開始されたかどうかではなく、リクエストがセッションオブジェクトを含んでいるかチェックするのみです。 + +* Serializer: NormalizerInterface の `supports()` メソッドは `supportsNormalization` と `supportsDenormalization` の 2 つのメソッドに分割されました。 + +* ParameterBag::getDeep() メソッドは削除され、ParameterBag::get() メソッドの真偽値の引数に置き換えられました。 + +* Serializer: `AbstractEncoder` と `AbstractNormalizer` はそれぞれ `SerializerAwareEncoder` と `SerializerAwareNormalizer` に名前が変更されました。 + +* Serializer: すべてのインターフェイスから `$properties` という引数が除かれました。 + +* Form: オプションの値である "date" タイプの "widget" の "text" は "single-text" に名前が変更されました。 + "text" は現在は個々のテキストボックスを示します ("time" タイプのように) 。 + PR12 から beta1 --------------- @@ -133,6 +147,9 @@ PR12 から beta1 * `File::getWebPath()` メソッドと `File::rename()` メソッドは削除されました。同様に `framework.document_root` コンフィギュレーションも削除されました。 +* `File::getDefaultExtension()` メソッドの名前は `File::guessExtension()` に変更されました。 + また、拡張子を推測できなかった場合は null を返すように変更されました。 + * `session` のコンフィギュレーションがリファクタリングされました * `class` オプションが削除されました(代わりに `session.class` パラメータを使ってください) @@ -141,7 +158,7 @@ PR12 から beta1 * `storage_id` オプションには、サービスIDの一部ではなく、サービスIDそのものを指定するように変更されました。 -* `DoctrineMigrationsBundle` と `DoctrineFixturesBundle` の 2 つのバンドルは、symfony コアから独立し、個別のリポジトリで管理されるようになりました。 +* `DoctrineMigrationsBundle` と `DoctrineFixturesBundle` の 2 つのバンドルは、Symfony コアから独立し、個別のリポジトリで管理されるようになりました。 * フォームフレームワークの大きなリファクタリングが行われました(詳細はドキュメントを参照してください) diff --git a/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php b/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php index 6ffb865bce..bd0b6a7fb1 100644 --- a/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php +++ b/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php @@ -15,6 +15,7 @@ use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\AssetFactoryPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\AssetManagerPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\CheckYuiFilterPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\FilterManagerPass; +use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\CheckCssEmbedFilterPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\CheckClosureFilterPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -32,6 +33,7 @@ class AsseticBundle extends Bundle parent::build($container); $container->addCompilerPass(new CheckClosureFilterPass()); + $container->addCompilerPass(new CheckCssEmbedFilterPass()); $container->addCompilerPass(new CheckYuiFilterPass()); $container->addCompilerPass(new TemplatingPass()); $container->addCompilerPass(new AssetFactoryPass()); diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php index 97dee17d61..5af36bd21c 100644 --- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php @@ -15,6 +15,7 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -79,6 +80,23 @@ class AsseticExtension extends Extension unset($filter['file']); } + if (isset($filter['apply_to'])) { + if (!is_array($filter['apply_to'])) { + $filter['apply_to'] = array($filter['apply_to']); + } + + foreach ($filter['apply_to'] as $i => $pattern) { + $worker = new DefinitionDecorator('assetic.worker.ensure_filter'); + $worker->replaceArgument(0, '/'.$pattern.'/'); + $worker->replaceArgument(1, new Reference('assetic.filter.'.$name)); + $worker->addTag('assetic.factory_worker'); + + $container->setDefinition('assetic.filter.'.$name.'.worker'.$i, $worker); + } + + unset($filter['apply_to']); + } + foreach ($filter as $key => $value) { $container->setParameter('assetic.filter.'.$name.'.'.$key, $value); } diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckClosureFilterPass.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckClosureFilterPass.php index e54ca51eb6..e2beaca776 100644 --- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckClosureFilterPass.php +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckClosureFilterPass.php @@ -23,8 +23,9 @@ class CheckClosureFilterPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { - if ($container->hasDefinition('assetic.filter.closure.jar') && - $container->getParameterBag()->resolveValue($container->getParameter('assetic.filter.closure.jar'))) { + if ($container->hasDefinition('assetic.filter.closure.jar') + && $container->hasParameter('assetic.filter.closure.jar') + && $container->getParameterBag()->resolveValue($container->getParameter('assetic.filter.closure.jar'))) { $container->removeDefinition('assetic.filter.closure.api'); } elseif ($container->hasDefinition('assetic.filter.closure.api')) { $container->removeDefinition('assetic.filter.closure.jar'); diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckCssEmbedFilterPass.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckCssEmbedFilterPass.php new file mode 100644 index 0000000000..e9c660c71e --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckCssEmbedFilterPass.php @@ -0,0 +1,31 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +/** + * Checks that the location of the CssEmbed JAR has been configured. + * + * @author Kris Wallsmith + */ +class CheckCssEmbedFilterPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if ($container->hasDefinition('assetic.filter.cssembed') && + !$container->getParameterBag()->resolveValue($container->getParameter('assetic.filter.cssembed.jar'))) { + throw new \RuntimeException('The "assetic.filters.cssembed" configuration requires a "jar" value.'); + } + } +} diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml index 8d0c56671c..c51ac1795b 100644 --- a/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml @@ -15,6 +15,7 @@ Assetic\Factory\Resource\CoalescingDirectoryResource Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource Symfony\Bundle\AsseticBundle\FilterManager + Assetic\Factory\Worker\EnsureFilterWorker %kernel.cache_dir%/assetic @@ -54,5 +55,10 @@ + + + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/cssembed.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/cssembed.xml new file mode 100644 index 0000000000..0a9c171541 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/cssembed.xml @@ -0,0 +1,20 @@ + + + + + + Assetic\Filter\CssEmbedFilter + %assetic.java.bin% + + + + + + + %assetic.filter.cssembed.jar% + %assetic.filter.cssembed.java% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml b/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml index c992dbb401..0df8dfcf0c 100644 --- a/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml +++ b/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml @@ -32,7 +32,8 @@ assetic: inputs: css/widget.sass filters: sass filters: - sass: ~ + sass: + apply_to: "\.sass$" yui_css: jar: %kernel.root_dir/java/yui-compressor-2.4.6.jar twig: diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/CreateSchemaDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/CreateSchemaDoctrineCommand.php index e2fe33f4cd..6988d98d97 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/CreateSchemaDoctrineCommand.php +++ b/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/CreateSchemaDoctrineCommand.php @@ -19,7 +19,8 @@ use Symfony\Component\Console\Output\Output; use Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand; /** - * Command to create the database schema for a set of classes based on their mappings. + * Command to execute the SQL needed to generate the database schema for + * a given entity manager. * * @author Fabien Potencier * @author Jonathan H. Wage @@ -32,17 +33,21 @@ class CreateSchemaDoctrineCommand extends CreateCommand $this ->setName('doctrine:schema:create') + ->setDescription('Executes (or dumps) the SQL needed to generate the database schema.') ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command') ->setHelp(<<doctrine:schema:create command creates the default entity -managers schema: +The doctrine:schema:create command executes the SQL needed to +generate the database schema for the default entity manager: ./app/console doctrine:schema:create -You can also optionally specify the name of a entity manager to create the -schema for: +You can also generate the database schema for a specific entity manager: ./app/console doctrine:schema:create --em=default + +Finally, instead of executing the SQL, you can output the SQL: + +./app/console doctrine:schema:create --dump-sql EOT ); } diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/DropSchemaDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/DropSchemaDoctrineCommand.php index 34d89a1299..ab3eef6de6 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/DropSchemaDoctrineCommand.php +++ b/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/DropSchemaDoctrineCommand.php @@ -32,12 +32,17 @@ class DropSchemaDoctrineCommand extends DropCommand $this ->setName('doctrine:schema:drop') + ->setDescription('Executes (or dumps) the SQL needed to drop the current database schema.') ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command') ->setHelp(<<doctrine:schema:drop command drops the default entity -managers schema: +The doctrine:schema:drop command generates the SQL needed to +drop the database schema of the default entity manager: -./app/console doctrine:schema:drop +./app/console doctrine:schema:drop --dump-sql + +Alternatively, you can execute the generated queries: + +./app/console doctrine:schema:drop --force You can also optionally specify the name of a entity manager to drop the schema for: diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/UpdateSchemaDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/UpdateSchemaDoctrineCommand.php index 3cea447dc9..e316806fd6 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/UpdateSchemaDoctrineCommand.php +++ b/src/Symfony/Bundle/DoctrineBundle/Command/Proxy/UpdateSchemaDoctrineCommand.php @@ -19,7 +19,8 @@ use Symfony\Component\Console\Output\Output; use Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand; /** - * Command to update the database schema for a set of classes based on their mappings. + * Command to generate the SQL needed to update the database schema to match + * the current mapping information. * * @author Fabien Potencier * @author Jonathan H. Wage @@ -32,15 +33,23 @@ class UpdateSchemaDoctrineCommand extends UpdateCommand $this ->setName('doctrine:schema:update') + ->setDescription('Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata.') ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command') ->setHelp(<<doctrine:schema:update command updates the default entity -managers schema: +The doctrine:schema:update command generates the SQL needed to +synchronize the database schema with the current mapping metadata of the +default entity manager. -./app/console doctrine:schema:update +For example, if you add metadata for a new column to an entity, this command +would generate and output the SQL needed to add the new column to the database: -You can also optionally specify the name of a entity manager to update the -schema for: +./app/console doctrine:schema:update --dump-sql + +Alternatively, you can execute the generated queries: + +./app/console doctrine:schema:update --force + +You can also update the database schema for a specific entity manager: ./app/console doctrine:schema:update --em=default EOT diff --git a/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php index 6bd973be1b..46bdc632ae 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php +++ b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php @@ -24,7 +24,7 @@ class ContainerTest extends TestCase $this->assertInstanceOf('Doctrine\DBAL\Configuration', $container->get('doctrine.dbal.default_connection.configuration')); $this->assertInstanceOf('Doctrine\Common\EventManager', $container->get('doctrine.dbal.default_connection.event_manager')); $this->assertInstanceOf('Doctrine\DBAL\Connection', $container->get('doctrine.dbal.default_connection')); - $this->assertInstanceOf('Doctrine\Common\Annotations\AnnotationReader', $container->get('doctrine.orm.metadata.annotation_reader')); + $this->assertInstanceOf('Doctrine\Common\Annotations\ReaderInterface', $container->get('doctrine.orm.metadata.annotation_reader')); $this->assertInstanceOf('Doctrine\ORM\Configuration', $container->get('doctrine.orm.default_configuration')); $this->assertInstanceOf('Doctrine\ORM\Mapping\Driver\DriverChain', $container->get('doctrine.orm.default_metadata_driver')); $this->assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.orm.default_metadata_cache')); diff --git a/src/Symfony/Bundle/DoctrineBundle/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php b/src/Symfony/Bundle/DoctrineBundle/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php index 14a6b23827..5dc4f2ce2a 100755 --- a/src/Symfony/Bundle/DoctrineBundle/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php +++ b/src/Symfony/Bundle/DoctrineBundle/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php @@ -35,7 +35,7 @@ abstract class AbstractDoctrineExtensionTest extends TestCase // doctrine.dbal.default_connection $this->assertEquals('%doctrine.default_connection%', $container->getDefinition('doctrine')->getArgument(3), '->load() overrides existing configuration options'); $this->assertEquals('foo', $container->getParameter('doctrine.default_connection'), '->load() overrides existing configuration options'); - + } public function testDbalLoad() @@ -124,9 +124,6 @@ abstract class AbstractDoctrineExtensionTest extends TestCase $this->assertEquals('Symfony\Bundle\DoctrineBundle\Mapping\Driver\XmlDriver', $container->getParameter('doctrine.orm.metadata.xml.class')); $this->assertEquals('Symfony\Bundle\DoctrineBundle\Mapping\Driver\YamlDriver', $container->getParameter('doctrine.orm.metadata.yml.class')); - $class = new \ReflectionClass($container->getParameter('doctrine.orm.metadata.annotation_reader.class')); - $this->assertTrue($class->getName() === 'Doctrine\Common\Annotations\AnnotationReader' || $class->isSubClassOf('Doctrine\Common\Annotations\AnnotationReader')); - $config = array( 'proxy_namespace' => 'MyProxies', 'auto_generate_proxy_classes' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php index 40f9a729b2..5045326af6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php @@ -86,7 +86,7 @@ class RedirectController extends ContainerAware $port = ':'.$httpsPort; } - $url = $scheme.'://'.$request->getHttpHost().$port.$request->getBaseUrl().$path.$qs; + $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs; return new RedirectResponse($url, $permanent ? 301 : 302); } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 75371e2acd..34ffc7185e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -457,6 +457,8 @@ class FrameworkExtension extends Extension $arguments = $loaderChain->getArguments(); array_unshift($arguments[0], new Reference('validator.mapping.loader.annotation_loader')); $loaderChain->setArguments($arguments); + } else { + $container->setParameter('validator.mapping.loader.annotation_loader.namespaces', array()); } if (isset($config['cache'])) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml index 68d2f1de3e..cc9746c05a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml @@ -5,10 +5,10 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - Annotations\Cache\FileCache + Doctrine\Common\Annotations\Cache\FileCache - Annotations\Reader - Annotations\CachedReader + Doctrine\Common\Annotations\Reader + Doctrine\Common\Annotations\CachedReader diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml index 492da8cb3a..203684e5b0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml @@ -15,6 +15,9 @@ Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory + + + @@ -52,11 +55,11 @@ - %validator.mapping.loader.xml_files_loader.mapping_files% + %validator.mapping.loader.xml_files_loader.mapping_files% - %validator.mapping.loader.yaml_files_loader.mapping_files% + %validator.mapping.loader.yaml_files_loader.mapping_files% diff --git a/src/Symfony/Component/Form/AbstractExtension.php b/src/Symfony/Component/Form/AbstractExtension.php index b164d7b0d7..9897948109 100644 --- a/src/Symfony/Component/Form/AbstractExtension.php +++ b/src/Symfony/Component/Form/AbstractExtension.php @@ -20,25 +20,38 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; abstract class AbstractExtension implements FormExtensionInterface { /** - * @var array + * The types provided by this extension + * @var array An array of FormTypeInterface */ private $types; /** - * @var array + * The type extensions provided by this extension + * @var array An array of FormTypeExtensionInterface */ private $typeExtensions; /** + * The type guesser provided by this extension * @var FormTypeGuesserInterface */ private $typeGuesser; /** + * Whether the type guesser has been loaded * @var Boolean */ private $typeGuesserLoaded = false; + /** + * Returns a type by name. + * + * @param string $name The name of the type + * + * @return FormTypeInterface The type + * + * @throws FormException if the given type is not supported by this extension + */ public function getType($name) { if (null === $this->types) { @@ -52,6 +65,13 @@ abstract class AbstractExtension implements FormExtensionInterface return $this->types[$name]; } + /** + * Returns whether the given type is supported. + * + * @param string $name The name of the type + * + * @return Boolean Whether the type is supported by this extension + */ public function hasType($name) { if (null === $this->types) { @@ -61,6 +81,13 @@ abstract class AbstractExtension implements FormExtensionInterface return isset($this->types[$name]); } + /** + * Returns the extensions for the given type. + * + * @param string $name The name of the type + * + * @return array An array of extensions as FormTypeExtensionInterface instances + */ public function getTypeExtensions($name) { if (null === $this->typeExtensions) { @@ -72,6 +99,13 @@ abstract class AbstractExtension implements FormExtensionInterface : array(); } + /** + * Returns whether this extension provides type extensions for the given type. + * + * @param string $name The name of the type + * + * @return Boolean Whether the given type has extensions + */ public function hasTypeExtensions($name) { if (null === $this->typeExtensions) { @@ -81,6 +115,11 @@ abstract class AbstractExtension implements FormExtensionInterface return isset($this->typeExtensions[$name]) && count($this->typeExtensions[$name]) > 0; } + /** + * Returns the type guesser provided by this extension. + * + * @return FormTypeGuesserInterface|null The type guesser + */ public function getTypeGuesser() { if (!$this->typeGuesserLoaded) { @@ -90,69 +129,92 @@ abstract class AbstractExtension implements FormExtensionInterface return $this->typeGuesser; } + /** + * Registers the types. + * + * @return array An array of FormTypeInterface instances + */ protected function loadTypes() { return array(); } + /** + * Registers the type extensions. + * + * @return array An array of FormTypeExtensionInterface instances + */ protected function loadTypeExtensions() { return array(); } + /** + * Registers the type guesser. + * + * @return FormTypeGuesserInterface|null A type guesser + */ protected function loadTypeGuesser() { return null; } + /** + * Initializes the types. + * + * @throws UnexpectedTypeException if any registered type is not an instance of FormTypeInterface + */ private function initTypes() { - $types = $this->loadTypes(); - $typesByName = array(); + $this->types = array(); - foreach ($types as $type) { + foreach ($this->loadTypes() as $type) { if (!$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'Symfony\Component\Form\FormTypeInterface'); } - $typesByName[$type->getName()] = $type; + $this->types[$type->getName()] = $type; } - - $this->types = $typesByName; } + /** + * Initializes the type extensions. + * + * @throws UnexpectedTypeException if any registered type extension is not + * an instance of FormTypeExtensionInterface + */ private function initTypeExtensions() { - $extensions = $this->loadTypeExtensions(); - $extensionsByType = array(); + $this->typeExtensions = array(); - foreach ($extensions as $extension) { + foreach ($this->loadTypeExtensions() as $extension) { if (!$extension instanceof FormTypeExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface'); } $type = $extension->getExtendedType(); - if (!isset($extensionsByType[$type])) { - $extensionsByType[$type] = array(); + if (!isset($this->typeExtensions[$type])) { + $this->typeExtensions[$type] = array(); } - $extensionsByType[$type][] = $extension; + $this->typeExtensions[$type][] = $extension; } - - $this->typeExtensions = $extensionsByType; } + /** + * Initializes the type guesser. + * + * @throws UnexpectedTypeException if the type guesser is not an instance of FormTypeGuesserInterface + */ private function initTypeGuesser() { $this->typeGuesserLoaded = true; - $guesser = $this->loadTypeGuesser(); + $this->guesser = $this->loadTypeGuesser(); - if (!$guesser instanceof FormTypeGuesserInterface) { - throw new UnexpectedTypeException($guesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); + if (!$this->guesser instanceof FormTypeGuesserInterface) { + throw new UnexpectedTypeException($this->guesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); } - - $this->guesser = $guesser; } -} +} \ No newline at end of file diff --git a/src/Symfony/Component/Form/AbstractType.php b/src/Symfony/Component/Form/AbstractType.php index dd66a03773..311c340f65 100644 --- a/src/Symfony/Component/Form/AbstractType.php +++ b/src/Symfony/Component/Form/AbstractType.php @@ -15,20 +15,75 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; abstract class AbstractType implements FormTypeInterface { + /** + * The extensions for this type + * @var array An array of FormTypeExtensionInterface instances + */ private $extensions = array(); + /** + * Builds the form. + * + * This method gets called for each type in the hierarchy starting form the + * top most type. + * Type extensions can further modify the form. + * + * @see FormTypeExtensionInterface::buildForm() + * + * @param FormBuilder $builder The form builder + * @param array $options The options + */ public function buildForm(FormBuilder $builder, array $options) { } + /** + * Builds the form view. + * + * This method gets called for each type in the hierarchy starting form the + * top most type. + * Type extensions can further modify the view. + * + * @see FormTypeExtensionInterface::buildView() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ public function buildView(FormView $view, FormInterface $form) { } + /** + * Builds the form view. + * + * This method gets called for each type in the hierarchy starting form the + * top most type. + * Type extensions can further modify the view. + * + * Children views have been built while this method gets called so you get + * a chance to modify them. + * + * @see FormTypeExtensionInterface::buildViewBottomUp() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ public function buildViewBottomUp(FormView $view, FormInterface $form) { } + /** + * Returns a builder for the current type. + * + * The builder is retrieved by going up in the type hierarchy when a type does + * not provide one. + * + * @param string $name The name of the builder + * @param FormFactoryInterface $factory The form factory + * @param array $options The options + * + * @return FormBuilder|null A form builder or null when the type does not have a builder + */ public function createBuilder($name, FormFactoryInterface $factory, array $options) { return null; @@ -63,7 +118,7 @@ abstract class AbstractType implements FormTypeInterface * * @param array $options * - * @return string The name of the parent type + * @return string|null The name of the parent type if any otherwise null */ public function getParent(array $options) { @@ -73,6 +128,8 @@ abstract class AbstractType implements FormTypeInterface /** * Returns the name of this type. * + * The default name type is the class name without the Form nor Type suffix + * * @return string The name of this type */ public function getName() diff --git a/src/Symfony/Component/Form/AbstractTypeExtension.php b/src/Symfony/Component/Form/AbstractTypeExtension.php index 9b0a5caa2b..afaeb18a2c 100644 --- a/src/Symfony/Component/Form/AbstractTypeExtension.php +++ b/src/Symfony/Component/Form/AbstractTypeExtension.php @@ -13,18 +13,58 @@ namespace Symfony\Component\Form; abstract class AbstractTypeExtension implements FormTypeExtensionInterface { + /** + * Builds the form. + * + * This method gets called after the extended type has built the form to + * further modify it. + * + * @see FormTypeInterface::buildForm() + * + * @param FormBuilder $builder The form builder + * @param array $options The options + */ public function buildForm(FormBuilder $builder, array $options) { } + /** + * Builds the view. + * + * This method gets called after the extended type has built the view to + * further modify it. + * + * @see FormTypeInterface::buildView() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ public function buildView(FormView $view, FormInterface $form) { } + /** + * Builds the view. + * + * This method gets called after the extended type has built the view to + * further modify it. + * + * @see FormTypeInterface::buildViewBottomUp() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ public function buildViewBottomUp(FormView $view, FormInterface $form) { } + /** + * Overrides the default options form the extended type. + * + * @param array $options + * + * @return array + */ public function getDefaultOptions(array $options) { return array(); diff --git a/src/Symfony/Component/Form/CallbackTransformer.php b/src/Symfony/Component/Form/CallbackTransformer.php index 2519d34d06..9abf617293 100644 --- a/src/Symfony/Component/Form/CallbackTransformer.php +++ b/src/Symfony/Component/Form/CallbackTransformer.php @@ -13,21 +13,56 @@ namespace Symfony\Component\Form; class CallbackTransformer implements DataTransformerInterface { + /** + * The callback used for forward transform + * @var \Closure + */ private $transform; + /** + * The callback used for reverse transform + * @var \Closure + */ private $reverseTransform; + /** + * Constructor. + * + * @param \Closure $transform The forward transform callback + * @param \Closure $reverseTransform The reverse transform callback + */ public function __construct(\Closure $transform, \Closure $reverseTransform) { $this->transform = $transform; $this->reverseTransform = $reverseTransform; } + /** + * Transforms a value from the original representation to a transformed representation. + * + * @param mixed $value The value in the original representation + * + * @return mixed The value in the transformed representation + * + * @throws UnexpectedTypeException when the argument is not a string + * @throws DataTransformerException when the transformation fails + */ public function transform($data) { return call_user_func($this->transform, $data); } + /** + * Transforms a value from the transformed representation to its original + * representation. + * + * @param mixed $value The value in the transformed representation + * + * @return mixed The value in the original representation + * + * @throws UnexpectedTypeException when the argument is not of the expected type + * @throws DataTransformerException when the transformation fails + */ public function reverseTransform($data) { return call_user_func($this->reverseTransform, $data); diff --git a/src/Symfony/Component/Form/DataTransformerInterface.php b/src/Symfony/Component/Form/DataTransformerInterface.php index dc4950a19b..633297d48c 100644 --- a/src/Symfony/Component/Form/DataTransformerInterface.php +++ b/src/Symfony/Component/Form/DataTransformerInterface.php @@ -40,8 +40,10 @@ interface DataTransformerInterface * passed. * * @param mixed $value The value in the original representation + * * @return mixed The value in the transformed representation - * @throws UnexpectedTypeException when the argument is no string + * + * @throws UnexpectedTypeException when the argument is not a string * @throws DataTransformerException when the transformation fails */ function transform($value); @@ -65,8 +67,10 @@ interface DataTransformerInterface * is passed. * * @param mixed $value The value in the transformed representation - * @throws UnexpectedTypeException when the argument is not of the - * expected type + * + * @return mixed The value in the original representation + * + * @throws UnexpectedTypeException when the argument is not of the expected type * @throws DataTransformerException when the transformation fails */ function reverseTransform($value); diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index fcd71e5eae..dd728dd4d0 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -77,7 +77,7 @@ class Form implements \IteratorAggregate, FormInterface /** * The children of this form - * @var array + * @var array An array of FormInterface instances */ private $children = array(); @@ -89,7 +89,7 @@ class Form implements \IteratorAggregate, FormInterface /** * The errors of this form - * @var array + * @var array An array of FromError instances */ private $errors = array(); @@ -165,7 +165,7 @@ class Form implements \IteratorAggregate, FormInterface /** * The validators attached to this form - * @var array + * @var array An array of FormValidatorInterface instances */ private $validators; @@ -252,7 +252,7 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Returns the supported types. + * Returns the types used by this form. * * @return array An array of FormTypeInterface */ diff --git a/src/Symfony/Component/Form/FormExtensionInterface.php b/src/Symfony/Component/Form/FormExtensionInterface.php index 770e714ae7..f20b681333 100644 --- a/src/Symfony/Component/Form/FormExtensionInterface.php +++ b/src/Symfony/Component/Form/FormExtensionInterface.php @@ -11,15 +11,51 @@ namespace Symfony\Component\Form; +/** + * Interface for extensions which provide types, type extensions and a guesser. + */ interface FormExtensionInterface { + /** + * Returns a type by name. + * + * @param string $name The name of the type + * + * @return FormTypeInterface The type + */ function getType($name); + /** + * Returns whether the given type is supported. + * + * @param string $name The name of the type + * + * @return Boolean Whether the type is supported by this extension + */ function hasType($name); + /** + * Returns the extensions for the given type. + * + * @param string $name The name of the type + * + * @return array An array of extensions as FormTypeExtensionInterface instances + */ function getTypeExtensions($name); + /** + * Returns whether this extension provides type extensions for the given type. + * + * @param string $name The name of the type + * + * @return Boolean Whether the given type has extensions + */ function hasTypeExtensions($name); + /** + * Returns the type guesser provided by this extension. + * + * @return FormTypeGuesserInterface|null The type guesser + */ function getTypeGuesser(); } diff --git a/src/Symfony/Component/Form/FormFactory.php b/src/Symfony/Component/Form/FormFactory.php index e24c7aaebb..6aca9ce50c 100644 --- a/src/Symfony/Component/Form/FormFactory.php +++ b/src/Symfony/Component/Form/FormFactory.php @@ -24,10 +24,22 @@ class FormFactory implements FormFactoryInterface 'max_length', ); + /** + * Extensions + * @var array An array of FormExtensionInterface + */ private $extensions = array(); + /** + * All known types (cache) + * @var array An array of FormTypeInterface + */ private $types = array(); + /** + * The guesser chain + * @var FormTypeGuesserChain + */ private $guesser; /** @@ -48,6 +60,13 @@ class FormFactory implements FormFactoryInterface $this->extensions = $extensions; } + /** + * Returns whether the given type is supported. + * + * @param string $name The name of the type + * + * @return Boolean Whether the type is supported + */ public function hasType($name) { if (isset($this->types[$name])) { @@ -63,6 +82,11 @@ class FormFactory implements FormFactoryInterface return true; } + /** + * Add a type. + * + * @param FormTypeInterface $type The type + */ public function addType(FormTypeInterface $type) { $this->loadTypeExtensions($type); @@ -70,6 +94,17 @@ class FormFactory implements FormFactoryInterface $this->types[$type->getName()] = $type; } + /** + * Returns a type by name. + * + * This methods registers the type extensions from the form extensions. + * + * @param string|FormTypeInterface $name The name of the type or a type instance + * + * @return FormTypeInterface The type + * + * @throws FormException if the type can not be retrieved from any extension + */ public function getType($name) { if (!is_string($name)) { @@ -83,24 +118,74 @@ class FormFactory implements FormFactoryInterface return $this->types[$name]; } + /** + * Returns a form. + * + * @see createBuilder() + * + * @param string|FormTypeInterface $type The type of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return Form The form named after the type + * + * @throws FormException if any given option is not applicable to the given type + */ public function create($type, $data = null, array $options = array()) { return $this->createBuilder($type, $data, $options)->getForm(); } + /** + * Returns a form. + * + * @see createNamedBuilder() + * + * @param string|FormTypeInterface $type The type of the form + * @param string $name The name of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return Form The form + * + * @throws FormException if any given option is not applicable to the given type + */ public function createNamed($type, $name, $data = null, array $options = array()) { return $this->createNamedBuilder($type, $name, $data, $options)->getForm(); } /** - * @inheritDoc + * Returns a form for a property of a class. + * + * @see createBuilderForProperty() + * + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * @param mixed $data The initial data + * @param array $options The options for the builder + * + * @return Form The form named after the property + * + * @throws FormException if any given option is not applicable to the form type */ public function createForProperty($class, $property, $data = null, array $options = array()) { return $this->createBuilderForProperty($class, $property, $data, $options)->getForm(); } + /** + * Returns a form builder + * + * @param string|FormTypeInterface $type The type of the form + * @param string $name The name of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return FormBuilder The form builder + * + * @throws FormException if any given option is not applicable to the given type + */ public function createBuilder($type, $data = null, array $options = array()) { $name = is_object($type) ? $type->getName() : $type; @@ -108,6 +193,18 @@ class FormFactory implements FormFactoryInterface return $this->createNamedBuilder($type, $name, $data, $options); } + /** + * Returns a form builder. + * + * @param string|FormTypeInterface $type The type of the form + * @param string $name The name of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return FormBuilder The form builder + * + * @throws FormException if any given option is not applicable to the given type + */ public function createNamedBuilder($type, $name, $data = null, array $options = array()) { $builder = null; @@ -185,6 +282,21 @@ class FormFactory implements FormFactoryInterface return $builder; } + /** + * Returns a form builder for a property of a class. + * + * If any of the 'max_length', 'required' and type options can be guessed, + * and are not provided in the options argument, the guessed value is used. + * + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * @param mixed $data The initial data + * @param array $options The options for the builder + * + * @return FormBuilder The form builder named after the property + * + * @throws FormException if any given option is not applicable to the form type + */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()) { if (!$this->guesser) { @@ -213,6 +325,9 @@ class FormFactory implements FormFactoryInterface return $this->createNamedBuilder($type, $property, $data, $options); } + /** + * Initializes the guesser chain. + */ private function loadGuesser() { $guessers = array(); @@ -228,6 +343,13 @@ class FormFactory implements FormFactoryInterface $this->guesser = new FormTypeGuesserChain($guessers); } + /** + * Loads a type. + * + * @param string $name The type name + * + * @throws FormException if the type is not provided by any registered extension + */ private function loadType($name) { $type = null; @@ -248,6 +370,11 @@ class FormFactory implements FormFactoryInterface $this->types[$name] = $type; } + /** + * Loads the extensions for a given type. + * + * @param FormTypeInterface $type The type + */ private function loadTypeExtensions(FormTypeInterface $type) { $typeExtensions = array(); diff --git a/src/Symfony/Component/Form/FormFactoryInterface.php b/src/Symfony/Component/Form/FormFactoryInterface.php index 6206737cc0..42f201f07d 100644 --- a/src/Symfony/Component/Form/FormFactoryInterface.php +++ b/src/Symfony/Component/Form/FormFactoryInterface.php @@ -13,16 +13,92 @@ namespace Symfony\Component\Form; interface FormFactoryInterface { + /** + * Returns a form. + * + * @see createBuilder() + * + * @param string|FormTypeInterface $type The type of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return Form The form named after the type + * + * @throws FormException if any given option is not applicable to the given type + */ function create($type, $data = null, array $options = array()); + /** + * Returns a form. + * + * @param string|FormTypeInterface $type The type of the form + * @param string $name The name of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return Form The form + * + * @throws FormException if any given option is not applicable to the given type + */ function createNamed($type, $name, $data = null, array $options = array()); + /** + * Returns a form for a property of a class. + * + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * @param mixed $data The initial data + * @param array $options The options for the builder + * + * @return Form The form named after the property + * + * @throws FormException if any given option is not applicable to the form type + */ function createForProperty($class, $property, $data = null, array $options = array()); + /** + * Returns a form builder + * + * @param string|FormTypeInterface $type The type of the form + * @param string $name The name of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return FormBuilder The form builder + * + * @throws FormException if any given option is not applicable to the given type + */ function createBuilder($type, $data = null, array $options = array()); + /** + * Returns a form builder. + * + * @param string|FormTypeInterface $type The type of the form + * @param string $name The name of the form + * @param mixed $data The initial data + * @param array $options The options + * + * @return FormBuilder The form builder + * + * @throws FormException if any given option is not applicable to the given type + */ function createNamedBuilder($type, $name, $data = null, array $options = array()); + /** + * Returns a form builder for a property of a class. + * + * If any of the 'max_length', 'required' and type options can be guessed, + * and are not provided in the options argument, the guessed value is used. + * + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * @param mixed $data The initial data + * @param array $options The options for the builder + * + * @return FormBuilder The form builder named after the property + * + * @throws FormException if any given option is not applicable to the form type + */ function createBuilderForProperty($class, $property, $data = null, array $options = array()); function getType($name); diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index e432c007f3..7e15d78945 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -21,14 +21,14 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable /** * Sets the parent form. * - * @param FormInterface $parent The parent form + * @param FormInterface $parent The parent form */ function setParent(FormInterface $parent = null); /** * Returns the parent form. * - * @return FormInterface The parent form + * @return FormInterface The parent form */ function getParent(); @@ -49,7 +49,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable /** * Returns whether a child with the given name exists. * - * @param string $name + * @param string $name * * @return Boolean */ @@ -65,7 +65,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable /** * Returns all children in this group. * - * @return array + * @return array An array of FormInterface instances */ function getChildren(); @@ -79,7 +79,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable /** * Returns all errors. * - * @return array An array of FormError instances that occurred during binding + * @return array An array of FormError instances that occurred during binding */ function getErrors(); diff --git a/src/Symfony/Component/Form/FormTypeExtensionInterface.php b/src/Symfony/Component/Form/FormTypeExtensionInterface.php index 8837b5f858..a12cb0f608 100644 --- a/src/Symfony/Component/Form/FormTypeExtensionInterface.php +++ b/src/Symfony/Component/Form/FormTypeExtensionInterface.php @@ -13,12 +13,52 @@ namespace Symfony\Component\Form; interface FormTypeExtensionInterface { + /** + * Builds the form. + * + * This method gets called after the extended type has built the form to + * further modify it. + * + * @see FormTypeInterface::buildForm() + * + * @param FormBuilder $builder The form builder + * @param array $options The options + */ function buildForm(FormBuilder $builder, array $options); + /** + * Builds the view. + * + * This method gets called after the extended type has built the view to + * further modify it. + * + * @see FormTypeInterface::buildView() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ function buildView(FormView $view, FormInterface $form); + /** + * Builds the view. + * + * This method gets called after the extended type has built the view to + * further modify it. + * + * @see FormTypeInterface::buildViewBottomUp() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ function buildViewBottomUp(FormView $view, FormInterface $form); + /** + * Overrides the default options form the extended type. + * + * @param array $options + * + * @return array + */ function getDefaultOptions(array $options); /** @@ -30,5 +70,11 @@ interface FormTypeExtensionInterface */ function getAllowedOptionValues(array $options); + + /** + * Returns the name of the type being extended + * + * @return string The name of the type being extended + */ function getExtendedType(); } \ No newline at end of file diff --git a/src/Symfony/Component/Form/FormTypeGuesserChain.php b/src/Symfony/Component/Form/FormTypeGuesserChain.php index 5877670433..261ffbc7d6 100644 --- a/src/Symfony/Component/Form/FormTypeGuesserChain.php +++ b/src/Symfony/Component/Form/FormTypeGuesserChain.php @@ -67,6 +67,7 @@ class FormTypeGuesserChain implements FormTypeGuesserInterface * * @param \Closure $closure The closure to execute. Accepts a guesser * as argument and should return a Guess instance + * * @return FieldFactoryGuess The guess with the highest confidence */ private function guess(\Closure $closure) diff --git a/src/Symfony/Component/Form/FormTypeGuesserInterface.php b/src/Symfony/Component/Form/FormTypeGuesserInterface.php index 0afb830693..d6dd8dd1ab 100644 --- a/src/Symfony/Component/Form/FormTypeGuesserInterface.php +++ b/src/Symfony/Component/Form/FormTypeGuesserInterface.php @@ -16,17 +16,19 @@ interface FormTypeGuesserInterface /** * Returns a field guess for a property name of a class * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for - * @return TypeGuess A guess for the field's type and options + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * + * @return TypeGuess A guess for the field's type and options */ function guessType($class, $property); /** * Returns a guess whether a property of a class is required * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * * @return Guess A guess for the field's required setting */ function guessRequired($class, $property); @@ -34,8 +36,9 @@ interface FormTypeGuesserInterface /** * Returns a guess about the field's maximum length * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * * @return Guess A guess for the field's maximum length */ function guessMaxLength($class, $property); diff --git a/src/Symfony/Component/Form/FormTypeInterface.php b/src/Symfony/Component/Form/FormTypeInterface.php index a4d7d5f3f5..18e5587a64 100644 --- a/src/Symfony/Component/Form/FormTypeInterface.php +++ b/src/Symfony/Component/Form/FormTypeInterface.php @@ -13,10 +13,49 @@ namespace Symfony\Component\Form; interface FormTypeInterface { + /** + * Builds the form. + * + * This method gets called for each type in the hierarchy starting form the + * top most type. + * Type extensions can further modify the form. + * + * @see FormTypeExtensionInterface::buildForm() + * + * @param FormBuilder $builder The form builder + * @param array $options The options + */ function buildForm(FormBuilder $builder, array $options); + /** + * Builds the form view. + * + * This method gets called for each type in the hierarchy starting form the + * top most type. + * Type extensions can further modify the view. + * + * @see FormTypeExtensionInterface::buildView() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ function buildView(FormView $view, FormInterface $form); + /** + * Builds the form view. + * + * This method gets called for each type in the hierarchy starting form the + * top most type. + * Type extensions can further modify the view. + * + * Children views have been built when this method gets called so you get + * a chance to modify them. + * + * @see FormTypeExtensionInterface::buildViewBottomUp() + * + * @param FormView $view The view + * @param FormInterface $form The form + */ function buildViewBottomUp(FormView $view, FormInterface $form); function createBuilder($name, FormFactoryInterface $factory, array $options); @@ -44,7 +83,7 @@ interface FormTypeInterface * * @param array $options * - * @return string The name of the parent type + * @return string|null The name of the parent type if any otherwise null */ function getParent(array $options); diff --git a/src/Symfony/Component/Form/Guess/TypeGuess.php b/src/Symfony/Component/Form/Guess/TypeGuess.php index 73c028b838..80b2593426 100644 --- a/src/Symfony/Component/Form/Guess/TypeGuess.php +++ b/src/Symfony/Component/Form/Guess/TypeGuess.php @@ -34,7 +34,7 @@ class TypeGuess extends Guess /** * Constructor * - * @param string $type The guessed field type + * @param string $type The guessed field type * @param array $options The options for creating instances of the * guessed class * @param integer $confidence The confidence that the guessed class name diff --git a/src/Symfony/Component/HttpFoundation/HeaderBag.php b/src/Symfony/Component/HttpFoundation/HeaderBag.php index 2e8d8346ae..4682808eff 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/HeaderBag.php @@ -44,14 +44,20 @@ class HeaderBag */ public function __toString() { + if (!$this->headers) { + return ''; + } + $beautifier = function ($name) { return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", ucfirst($name)); }; + $max = max(array_map('strlen', array_keys($this->headers))) + 1; $content = ''; + ksort($this->headers); foreach ($this->headers as $name => $values) { foreach ($values as $value) { - $content .= sprintf("%s: %s\r\n", $beautifier($name), $value); + $content .= sprintf("%-{$max}s %s\r\n", $beautifier($name).':', $value); } } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 43c9a88627..1dc6ca408d 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -468,11 +468,7 @@ class Request */ public function getHttpHost() { - $host = $this->headers->get('HOST'); - if (!empty($host)) { - return $host; - } - + $host = $this->getHost(); $scheme = $this->getScheme(); $name = $this->server->get('SERVER_NAME'); $port = $this->getPort(); diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 76f066da50..17da15cec6 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -82,10 +82,13 @@ class Response */ public function __construct($content = '', $status = 200, $headers = array()) { + $this->headers = new ResponseHeaderBag($headers); $this->setContent($content); $this->setStatusCode($status); $this->setProtocolVersion('1.0'); - $this->headers = new ResponseHeaderBag($headers); + if (!$this->headers->has('Date')) { + $this->setDate(new \DateTime(null, new \DateTimeZone('UTC'))); + } $this->charset = 'UTF-8'; } @@ -329,20 +332,24 @@ class Response /** * Returns the Date header as a DateTime instance. * - * When no Date header is present, the current time is returned. - * * @return \DateTime A \DateTime instance * * @throws \RuntimeException when the header is not parseable */ public function getDate() { - if (null === $date = $this->headers->getDate('Date')) { - $date = new \DateTime(null, new \DateTimeZone('UTC')); - $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); - } + return $this->headers->getDate('Date'); + } - return $date; + /** + * Sets the Date header. + * + * @param \DateTime $date A \DateTime instance + */ + public function setDate(\DateTime $date) + { + $date->setTimezone(new \DateTimeZone('UTC')); + $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); } /** diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index f0dc5dcb8b..9466eb3774 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -182,6 +182,8 @@ class HttpCache implements HttpKernelInterface $this->restoreResponseBody($request, $response); + $response->setDate(new \DateTime(null, new \DateTimeZone('UTC'))); + if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) { $response->headers->set('X-Symfony-Cache', $this->getLog()); } @@ -340,9 +342,8 @@ class HttpCache implements HttpKernelInterface } $entry = clone $entry; - $entry->headers->remove('Date'); - foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { + foreach (array('Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { if ($response->headers->has($name)) { $entry->headers->set($name, $response->headers->get($name)); } diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php index a15444be51..1e2c282b7e 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Routing\Loader; -use Annotations\ReaderInterface; +use Doctrine\Common\Annotations\ReaderInterface; use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Route; diff --git a/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php index e21f02831c..39b1ecca5d 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Mapping\Loader; -use Annotations\ReaderInterface; +use Doctrine\Common\Annotations\ReaderInterface; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\GroupSequence; diff --git a/tests/Symfony/Tests/Component/Validator/Mapping/Loader/AnnotationLoaderTest.php b/tests/Symfony/Tests/Component/Validator/Mapping/Loader/AnnotationLoaderTest.php index 1f1c5d08a6..c63ccbeca5 100644 --- a/tests/Symfony/Tests/Component/Validator/Mapping/Loader/AnnotationLoaderTest.php +++ b/tests/Symfony/Tests/Component/Validator/Mapping/Loader/AnnotationLoaderTest.php @@ -14,7 +14,7 @@ namespace Symfony\Tests\Component\Validator\Mapping\Loader; require_once __DIR__.'/../../Fixtures/Entity.php'; require_once __DIR__.'/../../Fixtures/ConstraintA.php'; -use Annotations\Reader; +use Doctrine\Common\Annotations\Reader; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\NotNull; @@ -28,7 +28,7 @@ class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase { protected function setUp() { - if (!class_exists('Annotations\Reader')) { + if (!class_exists('Doctrine\Common\Annotations\Reader')) { $this->markTestSkipped('Unmet dependency: Annotations is required for this test'); } } diff --git a/tests/Symfony/Tests/Component/Validator/ValidatorFactoryTest.php b/tests/Symfony/Tests/Component/Validator/ValidatorFactoryTest.php index a3ed8990da..cb5fc1c74e 100644 --- a/tests/Symfony/Tests/Component/Validator/ValidatorFactoryTest.php +++ b/tests/Symfony/Tests/Component/Validator/ValidatorFactoryTest.php @@ -11,7 +11,7 @@ namespace Symfony\Tests\Component\Validator; -use Annotations\Reader; +use Doctrine\Common\Annotations\Reader; use Symfony\Component\Validator\Validator; use Symfony\Component\Validator\ValidatorContext; use Symfony\Component\Validator\ValidatorFactory; @@ -76,7 +76,7 @@ class ValidatorFactoryTest extends \PHPUnit_Framework_TestCase public function testBuildDefaultFromAnnotations() { - if (!class_exists('Annotations\Reader')) { + if (!class_exists('Doctrine\Common\Annotations\Reader')) { $this->markTestSkipped('Annotations is required for this test'); } $factory = ValidatorFactory::buildDefault(); @@ -91,7 +91,7 @@ class ValidatorFactoryTest extends \PHPUnit_Framework_TestCase public function testBuildDefaultFromAnnotationsWithCustomNamespaces() { - if (!class_exists('Annotations\Reader')) { + if (!class_exists('Doctrine\Common\Annotations\Reader')) { $this->markTestSkipped('Annotations is required for this test'); } $factory = ValidatorFactory::buildDefault(array(), true); @@ -145,7 +145,7 @@ class ValidatorFactoryTest extends \PHPUnit_Framework_TestCase public function testBuildDefaultFromMultipleLoaders() { - if (!class_exists('Annotations\Reader')) { + if (!class_exists('Doctrine\Common\Annotations\Reader')) { $this->markTestSkipped('Annotations is required for this test'); } $xmlPath = __DIR__.'/Mapping/Loader/constraint-mapping.xml'; diff --git a/vendors.sh b/vendors.sh index 7caab2d554..f5259528f6 100755 --- a/vendors.sh +++ b/vendors.sh @@ -44,7 +44,7 @@ install_git doctrine git://github.com/doctrine/doctrine2.git 2.0.4 install_git doctrine-dbal git://github.com/doctrine/dbal.git 2.0.4 # Doctrine Common -install_git doctrine-common git://github.com/doctrine/common.git 2.0.2 +install_git doctrine-common git://github.com/doctrine/common.git origin/3.0.x # Doctrine migrations install_git doctrine-migrations git://github.com/doctrine/migrations.git