some updates

This commit is contained in:
Johannes Schmitt 2011-05-16 21:35:23 +02:00
commit 796d9af0c4
41 changed files with 752 additions and 99 deletions

View File

@ -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 コアから独立し、個別のリポジトリで管理されるようになりました。
* フォームフレームワークの大きなリファクタリングが行われました(詳細はドキュメントを参照してください)

View File

@ -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());

View File

@ -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);
}

View File

@ -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');

View File

@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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 <kris@symfony.com>
*/
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.');
}
}
}

View File

@ -15,6 +15,7 @@
<parameter key="assetic.coalescing_directory_resource.class">Assetic\Factory\Resource\CoalescingDirectoryResource</parameter>
<parameter key="assetic.directory_resource.class">Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource</parameter>
<parameter key="assetic.filter_manager.class">Symfony\Bundle\AsseticBundle\FilterManager</parameter>
<parameter key="assetic.worker.ensure_filter.class">Assetic\Factory\Worker\EnsureFilterWorker</parameter>
<parameter key="assetic.node.paths" type="collection"></parameter>
<parameter key="assetic.cache_dir">%kernel.cache_dir%/assetic</parameter>
@ -54,5 +55,10 @@
<tag name="kernel.cache_warmer" priority="10" />
<argument type="service" id="service_container" />
</service>
<service id="assetic.worker.ensure_filter" class="%assetic.worker.ensure_filter.class%" abstract="true" public="false">
<argument /> <!-- pattern -->
<argument /> <!-- filter -->
</service>
</services>
</container>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="assetic.filter.cssembed.class">Assetic\Filter\CssEmbedFilter</parameter>
<parameter key="assetic.filter.cssembed.java">%assetic.java.bin%</parameter>
<parameter key="assetic.filter.cssembed.jar" />
</parameters>
<services>
<service id="assetic.filter.cssembed" class="%assetic.filter.cssembed.class%">
<tag name="assetic.filter" alias="cssembed" />
<argument>%assetic.filter.cssembed.jar%</argument>
<argument>%assetic.filter.cssembed.java%</argument>
</service>
</services>
</container>

View File

@ -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:

View File

@ -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 <fabien@symfony.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
@ -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(<<<EOT
The <info>doctrine:schema:create</info> command creates the default entity
managers schema:
The <info>doctrine:schema:create</info> command executes the SQL needed to
generate the database schema for the default entity manager:
<info>./app/console doctrine:schema:create</info>
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:
<info>./app/console doctrine:schema:create --em=default</info>
Finally, instead of executing the SQL, you can output the SQL:
<info>./app/console doctrine:schema:create --dump-sql</info>
EOT
);
}

View File

@ -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(<<<EOT
The <info>doctrine:schema:drop</info> command drops the default entity
managers schema:
The <info>doctrine:schema:drop</info> command generates the SQL needed to
drop the database schema of the default entity manager:
<info>./app/console doctrine:schema:drop</info>
<info>./app/console doctrine:schema:drop --dump-sql</info>
Alternatively, you can execute the generated queries:
<info>./app/console doctrine:schema:drop --force</info>
You can also optionally specify the name of a entity manager to drop the
schema for:

View File

@ -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 <fabien@symfony.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
@ -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(<<<EOT
The <info>doctrine:schema:update</info> command updates the default entity
managers schema:
The <info>doctrine:schema:update</info> command generates the SQL needed to
synchronize the database schema with the current mapping metadata of the
default entity manager.
<info>./app/console doctrine:schema:update</info>
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:
<info>./app/console doctrine:schema:update --dump-sql</info>
Alternatively, you can execute the generated queries:
<info>./app/console doctrine:schema:update --force</info>
You can also update the database schema for a specific entity manager:
<info>./app/console doctrine:schema:update --em=default</info>
EOT

View File

@ -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'));

View File

@ -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,

View File

@ -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);
}

View File

@ -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'])) {

View File

@ -5,10 +5,10 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="annotations.cache.file_cache.class">Annotations\Cache\FileCache</parameter>
<parameter key="annotations.cache.file_cache.class">Doctrine\Common\Annotations\Cache\FileCache</parameter>
<parameter key="annotations.reader.class">Annotations\Reader</parameter>
<parameter key="annotations.cached_reader.class">Annotations\CachedReader</parameter>
<parameter key="annotations.reader.class">Doctrine\Common\Annotations\Reader</parameter>
<parameter key="annotations.cached_reader.class">Doctrine\Common\Annotations\CachedReader</parameter>
</parameters>
<services>

View File

@ -15,6 +15,9 @@
<parameter key="validator.mapping.loader.xml_files_loader.class">Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader</parameter>
<parameter key="validator.mapping.loader.yaml_files_loader.class">Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader</parameter>
<parameter key="validator.validator_factory.class">Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory</parameter>
<parameter key="validator.mapping.loader.annotation_loader.namespaces" type="collection" />
<parameter key="validator.mapping.loader.xml_files_loader.mapping_files" type="collection" />
<parameter key="validator.mapping.loader.yaml_files_loader.mapping_files" type="collection" />
</parameters>
<services>
@ -52,11 +55,11 @@
</service>
<service id="validator.mapping.loader.xml_files_loader" class="%validator.mapping.loader.xml_files_loader.class%" public="false">
<argument type="collection">%validator.mapping.loader.xml_files_loader.mapping_files%</argument>
<argument>%validator.mapping.loader.xml_files_loader.mapping_files%</argument>
</service>
<service id="validator.mapping.loader.yaml_files_loader" class="%validator.mapping.loader.yaml_files_loader.class%" public="false">
<argument type="collection">%validator.mapping.loader.yaml_files_loader.mapping_files%</argument>
<argument>%validator.mapping.loader.yaml_files_loader.mapping_files%</argument>
</service>
</services>
</container>

View File

@ -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;
}
}
}

View File

@ -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()

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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
*/

View File

@ -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();
}

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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();
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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');
}
/**

View File

@ -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));
}

View File

@ -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;

View File

@ -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;

View File

@ -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');
}
}

View File

@ -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';

View File

@ -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