From 8fbf19694f253e8bacdd677362ee58967506bbb3 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Wage" Date: Sat, 2 Oct 2010 16:43:30 -0500 Subject: [PATCH 01/10] Adding orm: and mongodb: annotation aliases to avoid conflicts. Recommended is to use the aliases instead of relying on the default namespace for annotations. /** @orm:Entity */ /** @mongodb:Document */ --- src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml | 5 +++++ .../DoctrineMongoDBBundle/Resources/config/mongodb.xml | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml b/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml index f86804b4901b2..a8227fd750ffc 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml +++ b/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml @@ -45,6 +45,11 @@ %doctrine.orm.metadata_driver.entity_dirs% + %doctrine.orm.metadata.annotation_default_namespace% + + Doctrine\ORM\Mapping\ + orm + diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml b/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml index fa41a2ce50756..c2f718b54e5ba 100755 --- a/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml @@ -57,6 +57,10 @@ %doctrine.odm.mongodb.metadata.annotation_default_namespace% + + Doctrine\ODM\MongoDB\Mapping\ + mongodb + %doctrine.odm.mongodb.xml_mapping_dirs% %doctrine.odm.mongodb.yml_mapping_dirs% From e88c0b7fc5a20bb768ca22552959e0b96490044a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 3 Oct 2010 07:34:56 +0200 Subject: [PATCH 02/10] [DoctrineBundle] fixed previous commit --- src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml b/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml index a8227fd750ffc..e4e43730dbc4a 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml +++ b/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml @@ -45,6 +45,9 @@ %doctrine.orm.metadata_driver.entity_dirs% + + + %doctrine.orm.metadata.annotation_default_namespace% Doctrine\ORM\Mapping\ @@ -52,10 +55,6 @@ - - Doctrine\ORM\Mapping\ - - %doctrine.orm.metadata_driver.mapping_dirs% From c2f856f074352cbcc6534a137c5d4bb754f1a8f3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 4 Oct 2010 14:01:33 +0200 Subject: [PATCH 03/10] [FrameworkBundle] fixed comment --- src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php index ded9f577c80ee..63707a3abf169 100755 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php @@ -137,7 +137,7 @@ protected function escapeParameters(array $parameters) } // parses template names following the following pattern: - // bundle:section:template(.format)(.renderer) + // bundle:section:template(.format).renderer public function splitTemplateName($name, array $defaults = array()) { $parts = explode(':', $name); From a38069288ce2f5d37237196531200d7a7cd291cf Mon Sep 17 00:00:00 2001 From: ornicar Date: Mon, 4 Oct 2010 12:09:20 +0200 Subject: [PATCH 04/10] Fix namespace collision --- src/Symfony/Bundle/FrameworkBundle/Client.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Client.php b/src/Symfony/Bundle/FrameworkBundle/Client.php index 27c68b2e6a7d8..d86217acdf91a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Client.php +++ b/src/Symfony/Bundle/FrameworkBundle/Client.php @@ -7,7 +7,7 @@ use Symfony\Component\HttpKernel\Client as BaseClient; use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\CookieJar; -use Symfony\Component\HttpKernel\Profiler\Profiler; +use Symfony\Component\HttpKernel\Profiler\Profiler as HttpProfiler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -67,7 +67,7 @@ public function getKernel() /** * Gets a profiler for the current Response. * - * @return Profiler A Profiler instance + * @return HttpProfiler A Profiler instance */ public function getProfiler() { From 2525998f6e47299438ccf07e6c5c92b4755f66a5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 9 Sep 2010 12:14:06 +0200 Subject: [PATCH 05/10] replaced form field rendering with plain templates Documentation available here: http://docs.symfony-reloaded.org/master/guides/form/ --- .../Resources/config/templating.xml | 9 + .../Resources/views/Form/errors.php | 7 + .../views/Form/group/div/field_group.php | 9 + .../Resources/views/Form/group/div/row.php | 5 + .../views/Form/group/table/field_group.php | 9 + .../Resources/views/Form/group/table/row.php | 9 + .../Resources/views/Form/hidden.php | 3 + .../Resources/views/Form/label.php | 1 + .../views/Form/widget/choice_field.php | 9 + .../views/Form/widget/date_field.php | 9 + .../views/Form/widget/date_time_field.php | 2 + .../views/Form/widget/input_field.php | 1 + .../views/Form/widget/money_field.php | 6 + .../views/Form/widget/percent_field.php | 6 + .../views/Form/widget/textarea_field.php | 1 + .../views/Form/widget/time_field.php | 9 + .../views/Form/widget/toggle_field.php | 11 + .../Templating/Form/BaseField.php | 132 +++++++++ .../FrameworkBundle/Templating/Form/Field.php | 104 +++++++ .../Templating/Form/FieldGroup.php | 75 +++++ .../Templating/Form/FieldInterface.php | 22 ++ .../FrameworkBundle/Templating/Form/Form.php | 44 +++ .../Templating}/HtmlGenerator.php | 48 ++- .../Templating}/HtmlGeneratorInterface.php | 2 +- .../DependencyInjection/TwigExtension.php | 11 + .../TwigBundle/Extension/FormExtension.php | 240 +++++++++++++++ .../TwigBundle/Extension/HtmlExtension.php | 62 ++++ .../Bundle/TwigBundle/Node/FormThemeNode.php | 49 +++ .../Bundle/TwigBundle/Node/HelperNode.php | 8 +- .../Bundle/TwigBundle/Node/TagNode.php | 62 ++++ .../Resources/config/schema/twig-1.0.xsd | 28 +- .../TwigBundle/Resources/config/twig.xml | 12 + .../TwigBundle/Resources/views/form.twig | 41 +++ .../TwigBundle/Resources/views/widgets.twig | 57 ++++ .../TokenParser/ContentTagTokenParser.php | 66 +++++ .../TokenParser/FormThemeTokenParser.php | 55 ++++ .../TwigBundle/TokenParser/TagTokenParser.php | 57 ++++ src/Symfony/Component/Form/CheckboxField.php | 6 +- src/Symfony/Component/Form/ChoiceField.php | 135 +++------ src/Symfony/Component/Form/Configurable.php | 5 + src/Symfony/Component/Form/DateField.php | 62 ++-- src/Symfony/Component/Form/DateTimeField.php | 11 - src/Symfony/Component/Form/Field.php | 93 +----- src/Symfony/Component/Form/FieldGroup.php | 119 +------- src/Symfony/Component/Form/FieldInterface.php | 30 +- src/Symfony/Component/Form/FileField.php | 6 +- src/Symfony/Component/Form/Form.php | 84 +----- src/Symfony/Component/Form/HiddenField.php | 8 +- src/Symfony/Component/Form/HybridField.php | 15 + src/Symfony/Component/Form/InputField.php | 14 +- src/Symfony/Component/Form/MoneyField.php | 44 +-- src/Symfony/Component/Form/NumberField.php | 6 +- src/Symfony/Component/Form/PasswordField.php | 6 +- src/Symfony/Component/Form/PercentField.php | 8 - src/Symfony/Component/Form/RadioField.php | 6 +- .../Component/Form/Renderer/Renderer.php | 88 ------ .../Form/Renderer/RendererInterface.php | 45 --- .../Component/Form/Renderer/TableRenderer.php | 52 ---- src/Symfony/Component/Form/TextField.php | 6 +- src/Symfony/Component/Form/TextareaField.php | 8 +- src/Symfony/Component/Form/TimeField.php | 22 +- src/Symfony/Component/Form/ToggleField.php | 23 +- src/Symfony/Component/Form/Translatable.php | 20 -- .../Component/I18N/TranslatorInterface.php | 22 -- .../Component/Form/CheckboxFieldTest.php | 20 -- .../Tests/Component/Form/ChoiceFieldTest.php | 278 ------------------ .../Tests/Component/Form/DateFieldTest.php | 115 -------- .../Component/Form/DateTimeFieldTest.php | 46 --- .../Tests/Component/Form/FieldGroupTest.php | 179 +---------- .../Symfony/Tests/Component/Form/FormTest.php | 42 --- .../Tests/Component/Form/HiddenFieldTest.php | 11 - .../Component/Form/HtmlGeneratorTest.php | 91 ------ .../Tests/Component/Form/InputFieldTest.php | 33 --- .../Tests/Component/Form/MoneyFieldTest.php | 46 --- .../Tests/Component/Form/NumberFieldTest.php | 46 --- .../Component/Form/PasswordFieldTest.php | 49 --- .../Tests/Component/Form/PercentFieldTest.php | 46 --- .../Tests/Component/Form/RadioFieldTest.php | 33 --- .../Form/Renderer/RendererTestCase.php | 23 -- .../Tests/Component/Form/TextFieldTest.php | 28 -- .../Component/Form/TextareaFieldTest.php | 28 -- .../Tests/Component/Form/TimeFieldTest.php | 124 -------- .../Tests/Component/Form/ToggleFieldTest.php | 67 ----- 83 files changed, 1456 insertions(+), 2074 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/errors.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/field_group.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/row.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/field_group.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/row.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/label.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/choice_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_time_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/input_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/money_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/percent_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/textarea_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/time_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/toggle_field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Templating/Form/BaseField.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Templating/Form/Field.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldGroup.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldInterface.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Templating/Form/Form.php rename src/Symfony/{Component/Form => Bundle/FrameworkBundle/Templating}/HtmlGenerator.php (67%) rename src/Symfony/{Component/Form => Bundle/FrameworkBundle/Templating}/HtmlGeneratorInterface.php (97%) create mode 100644 src/Symfony/Bundle/TwigBundle/Extension/FormExtension.php create mode 100644 src/Symfony/Bundle/TwigBundle/Extension/HtmlExtension.php create mode 100644 src/Symfony/Bundle/TwigBundle/Node/FormThemeNode.php create mode 100644 src/Symfony/Bundle/TwigBundle/Node/TagNode.php create mode 100644 src/Symfony/Bundle/TwigBundle/Resources/views/form.twig create mode 100644 src/Symfony/Bundle/TwigBundle/Resources/views/widgets.twig create mode 100644 src/Symfony/Bundle/TwigBundle/TokenParser/ContentTagTokenParser.php create mode 100644 src/Symfony/Bundle/TwigBundle/TokenParser/FormThemeTokenParser.php create mode 100644 src/Symfony/Bundle/TwigBundle/TokenParser/TagTokenParser.php delete mode 100644 src/Symfony/Component/Form/Renderer/Renderer.php delete mode 100644 src/Symfony/Component/Form/Renderer/RendererInterface.php delete mode 100644 src/Symfony/Component/Form/Renderer/TableRenderer.php delete mode 100644 src/Symfony/Component/Form/Translatable.php delete mode 100644 src/Symfony/Component/I18N/TranslatorInterface.php delete mode 100644 tests/Symfony/Tests/Component/Form/CheckboxFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/HtmlGeneratorTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/InputFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/MoneyFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/NumberFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/PasswordFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/PercentFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/RadioFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/Renderer/RendererTestCase.php delete mode 100644 tests/Symfony/Tests/Component/Form/TextFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/TextareaFieldTest.php delete mode 100644 tests/Symfony/Tests/Component/Form/ToggleFieldTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml index 87bd3b3b5fca9..aefa0065ab1fc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml @@ -19,6 +19,8 @@ Symfony\Bundle\FrameworkBundle\Templating\Helper\SessionHelper Symfony\Bundle\FrameworkBundle\Templating\Helper\CodeHelper Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper + Symfony\Bundle\FrameworkBundle\Templating\Form\Form + Symfony\Bundle\FrameworkBundle\Templating\HtmlGenerator false null @@ -26,6 +28,8 @@ + + @@ -101,6 +105,11 @@ + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/errors.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/errors.php new file mode 100644 index 0000000000000..9ade44ed9f029 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/errors.php @@ -0,0 +1,7 @@ + +
    + +
  • trans($error[0], $error[1], 'validators') ?>
  • + +
+ diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/field_group.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/field_group.php new file mode 100644 index 0000000000000..fce7c0c2605b8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/field_group.php @@ -0,0 +1,9 @@ +errors() ?> + +
+ + render() ?> + +
+ +hidden() ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/row.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/row.php new file mode 100644 index 0000000000000..2960ecec7f2b0 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/div/row.php @@ -0,0 +1,5 @@ +
+ label() ?> + errors() ?> + field() ?> +
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/field_group.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/field_group.php new file mode 100644 index 0000000000000..f4eeba6ce8850 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/field_group.php @@ -0,0 +1,9 @@ +errors() ?> + + + + render() ?> + +
+ +hidden() ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/row.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/row.php new file mode 100644 index 0000000000000..8d42093f86b82 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/group/table/row.php @@ -0,0 +1,9 @@ + + + label() ?> + + + errors() ?> + widget() ?> + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden.php new file mode 100644 index 0000000000000..8d53c09b7b8c8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden.php @@ -0,0 +1,3 @@ + + widget() ?> + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/label.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/label.php new file mode 100644 index 0000000000000..d975823806b65 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/label.php @@ -0,0 +1 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/choice_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/choice_field.php new file mode 100644 index 0000000000000..dd7cb72c56046 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/choice_field.php @@ -0,0 +1,9 @@ +getOption('expanded')): ?> + + widget() ?> + + + contentTag('select', + $generator->choices($origin->getPreferredChoices(), $origin->getOtherChoices(), $origin->getEmptyValue(), $origin->getSelected()), + $attributes) ?> + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_field.php new file mode 100644 index 0000000000000..4787cc8af7611 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_field.php @@ -0,0 +1,9 @@ +isField()): ?> + tag('input', $attributes) ?> + + widget($attributes), + $field['month']->widget($attributes), + $field['day']->widget($attributes), + ), $origin->getPattern()) ?> + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_time_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_time_field.php new file mode 100644 index 0000000000000..bc349b78fac5a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/date_time_field.php @@ -0,0 +1,2 @@ +widget($attributes) ?> +widget($attributes) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/input_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/input_field.php new file mode 100644 index 0000000000000..c425fcfa9f79c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/input_field.php @@ -0,0 +1 @@ +tag('input', $attributes) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/money_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/money_field.php new file mode 100644 index 0000000000000..9e55562f38e84 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/money_field.php @@ -0,0 +1,6 @@ +render('FrameworkBundle:Form:widget/input_field.php', array( + 'field' => $field, + 'origin' => $origin, + 'attributes' => $attributes, + 'generator' => $generator, +)), $origin->getPattern()) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/percent_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/percent_field.php new file mode 100644 index 0000000000000..ecef83aa61677 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/percent_field.php @@ -0,0 +1,6 @@ +render('FrameworkBundle:Form:widget/input_field.php', array( + 'field' => $field, + 'origin' => $origin, + 'attributes' => $attributes, + 'generator' => $generator, +)) ?> % diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/textarea_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/textarea_field.php new file mode 100644 index 0000000000000..ed5a9237c8669 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/textarea_field.php @@ -0,0 +1 @@ +contentTag('textarea', $view->escape($field->getDisplayedData()), $attributes) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/time_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/time_field.php new file mode 100644 index 0000000000000..76cb2c2bb179d --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/time_field.php @@ -0,0 +1,9 @@ +isField()): ?> + tag('input', $attributes) ?> + + widget($attributes).':'.$field['minute']->widget($attributes) ?> + + getOption('with_seconds')): ?> + widget($attributes) ?> + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/toggle_field.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/toggle_field.php new file mode 100644 index 0000000000000..373cd28cf47db --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget/toggle_field.php @@ -0,0 +1,11 @@ +render('FrameworkBundle:Form:widget/input_field.php', array( + 'field' => $field, + 'origin' => $origin, + 'attributes' => $attributes, + 'generator' => $generator, + )) +?> + +getOption('label')): ?> + contentTag('label', $view['translator']->trans($label), array('for' => $origin->getId())) ?> + diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Form/BaseField.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/BaseField.php new file mode 100644 index 0000000000000..076ea555c6780 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/BaseField.php @@ -0,0 +1,132 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * + * + * @author Fabien Potencier + */ +abstract class BaseField implements FieldInterface, SafeDecoratorInterface +{ + protected $engine; + protected $field; + protected $generator; + protected $theme; + protected $doctype; + + public function __construct(FormFieldInterface $field, Engine $engine, HtmlGeneratorInterface $generator, $theme, $doctype) + { + $this->field = $field; + $this->engine = $engine; + $this->generator = $generator; + $this->theme = $theme; + } + + public function getIterator() + { + if (!$this->field instanceof FieldGroupInterface) { + throw new \LogicException(sprintf('Cannot iterate a non group field (%s)', $this->field->getKey())); + } + + $fields = array(); + foreach ($this->field->getFields() as $field) { + if (!$field->isHidden()) { + $fields[] = $field; + } + } + + return new \ArrayIterator($this->wrapFields($fields)); + } + + /** + * Returns true if the bound field exists (implements the \ArrayAccess interface). + * + * @param string $key The key of the bound field + * + * @return Boolean true if the widget exists, false otherwise + */ + public function offsetExists($key) + { + if (!$this->field instanceof FieldGroupInterface) { + throw new \LogicException(sprintf('Cannot access a non group field as an array (%s)', $this->field->getKey())); + } + + return $this->field->has($key); + } + + /** + * Returns the form field associated with the name (implements the \ArrayAccess interface). + * + * @param string $key The offset of the value to get + * + * @return Field A form field instance + */ + public function offsetGet($key) + { + if (!$this->field instanceof FieldGroupInterface) { + throw new \LogicException(sprintf('Cannot access a non group field as an array (%s)', $this->field->getKey())); + } + + return $this->createField($this->field->get($key)); + } + + /** + * Throws an exception saying that values cannot be set (implements the \ArrayAccess interface). + * + * @param string $offset (ignored) + * @param string $value (ignored) + * + * @throws \LogicException + */ + public function offsetSet($key, $field) + { + throw new \LogicException('This helper is read-only'); + } + + /** + * Throws an exception saying that values cannot be unset (implements the \ArrayAccess interface). + * + * @param string $key + * + * @throws \LogicException + */ + public function offsetUnset($key) + { + throw new \LogicException('This helper is read-only'); + } + + protected function wrapFields($fields) + { + foreach ($fields as $id => $field) { + $fields[$id] = $this->createField($field); + } + + return $fields; + } + + protected function createField(FormFieldInterface $field) + { + if ($field instanceof Form || get_class($field) === 'Symfony\Component\Form\FieldGroup') { + return new FieldGroup($field, $this->engine, $this->generator, $this->theme, $this->doctype); + } + + return new Field($field, $this->engine, $this->generator, $this->theme, $this->doctype); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Form/Field.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/Field.php new file mode 100644 index 0000000000000..052ddce0b5224 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/Field.php @@ -0,0 +1,104 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Field wraps a Form\FieldInterface instance. + * + * @author Fabien Potencier + */ +class Field extends BaseField +{ + static protected $cache = array(); + + public function render($template = null) + { + if ($this->field instanceof Form || get_class($this->field) === 'Symfony\Component\Form\FieldGroup') { + throw new \LogicException(sprintf('Cannot render a group field as a row (%s)', $this->field->getKey())); + } + + if (null === $template) { + $template = sprintf('FrameworkBundle:Form:group/%s/row.php', $this->theme); + } + + return $this->engine->render($template, array('field' => $this)); + } + + public function data() + { + return $this->field->getData(); + } + + public function widget(array $attributes = array(), $template = null) + { + if ($this->field instanceof Form || get_class($this->field) === 'Symfony\Component\Form\FieldGroup') { + throw new \LogicException(sprintf('Cannot render a group field (%s)', $this->field->getKey())); + } + + if (null === $template) { + $template = $this->getTemplate(); + } + + return $this->engine->render($template, array( + 'field' => $this, + 'origin' => $this->field, + 'attributes' => array_merge($this->field->getAttributes(), $attributes), + 'generator' => $this->generator, + )); + } + + public function label($label, $template = null) + { + if (null === $template) { + $template = 'FrameworkBundle:Form:label.php'; + } + + return $this->engine->render($template, array( + 'field' => $this, + 'id' => $this->field->getId(), + 'key' => $this->field->getKey(), + 'label' => $label ? $label : ucfirst(strtolower(str_replace('_', ' ', $this->field->getKey()))) + )); + } + + public function errors($template = null) + { + if (null === $template) { + $template = 'FrameworkBundle:Form:errors.php'; + } + + return $this->engine->render($template, array('field' => $this, 'errors' => $this->field->getErrors())); + } + + protected function getTemplate() + { + $class = get_class($this->field); + + if (isset(self::$cache[$class])) { + return self::$cache[$class]; + } + + // find a template for the given class or one of its parents + do { + $parts = explode('\\', $class); + $c = array_pop($parts); + + $underscore = strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($c, '_', '.'))); + + if ($this->engine->exists($template = 'FrameworkBundle:Form:widget/'.$underscore.'.php')) { + return self::$cache[$class] = $template; + } + } while (false !== $class = get_parent_class($class)); + + throw new \RuntimeException(sprintf('Unable to find a template to render the "%s" widget.', $this->field->getKey())); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldGroup.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldGroup.php new file mode 100644 index 0000000000000..791270416c16f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldGroup.php @@ -0,0 +1,75 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * FieldGroup wraps a Form\FieldGroupInterface instance. + * + * @author Fabien Potencier + */ +class FieldGroup extends BaseField +{ + /** + * Renders the form tag. + * + * This method only renders the opening form tag. + * You need to close it after the form rendering. + * + * This method takes into account the multipart widgets. + * + * @param string $url The URL for the action + * @param array $attributes An array of HTML attributes + * + * @return string An HTML representation of the opening form tag + */ + public function form($url, array $attributes = array()) + { + return sprintf('', $this->generator->attributes(array_merge(array( + 'action' => $url, + 'method' => isset($attributes['method']) ? strtolower($attributes['method']) : 'post', + 'enctype' => $this->field->isMultipart() ? 'multipart/form-data' : null, + ), $attributes))); + } + + public function render($template = null) + { + if (null === $template) { + $template = sprintf('FrameworkBundle:Form:group/%s/field_group.php', $this->theme); + } + + return $this->engine->render($template, array('group' => $this)); + } + + public function hidden($template = null) + { + if (null === $template) { + $template = 'FrameworkBundle:Form:hidden.php'; + } + + return $this->engine->render($template, array( + 'group' => $this, + 'hidden' => $this->wrapFields($this->field->getHiddenFields(true)) + )); + } + + public function errors($template = null) + { + if (null === $template) { + $template = 'FrameworkBundle:Form:errors.php'; + } + + return $this->engine->render($template, array( + 'group' => $this, + 'errors' => $this->field->getErrors() + )); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldInterface.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldInterface.php new file mode 100644 index 0000000000000..bafcd4d444596 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/FieldInterface.php @@ -0,0 +1,22 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * + * + * @author Fabien Potencier + */ +interface FieldInterface extends \IteratorAggregate, \ArrayAccess +{ + function render($template = null); +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Form/Form.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/Form.php new file mode 100644 index 0000000000000..89d3a64db3bac --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Form/Form.php @@ -0,0 +1,44 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Form is a factory that wraps Form instances. + * + * @author Fabien Potencier + */ +class Form +{ + public $generator; + + protected $engine; + protected $theme; + protected $doctype; + + public function __construct(Engine $engine, HtmlGeneratorInterface $generator, $theme = 'table', $doctype = 'xhtml') + { + $this->engine = $engine; + $this->generator = $generator; + $this->theme = $theme; + $this->doctype = $doctype; + } + + public function get(FieldGroupInterface $group, $theme = null, $doctype = null) + { + return new FieldGroup($group, $this->engine, $this->generator, null === $theme ? $this->theme : $theme, null === $doctype ? $this->doctype : $doctype); + } +} diff --git a/src/Symfony/Component/Form/HtmlGenerator.php b/src/Symfony/Bundle/FrameworkBundle/Templating/HtmlGenerator.php similarity index 67% rename from src/Symfony/Component/Form/HtmlGenerator.php rename to src/Symfony/Bundle/FrameworkBundle/Templating/HtmlGenerator.php index 2030ea341f455..ebd40a9fbc720 100644 --- a/src/Symfony/Component/Form/HtmlGenerator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/HtmlGenerator.php @@ -1,6 +1,6 @@ doChoices(array('' => $empty), $selected)."\n"; + } + + if (count($preferredChoices) > 0) { + $html .= $this->doChoices($preferredChoices, $selected)."\n"; + $html .= $this->contentTag('option', $origin->getOption('separator'), array('disabled' => true))."\n"; + } + + $html .= $this->doChoices($choices, $selected)."\n"; + + return $html; + } + + protected function doChoices(array $choices, array $selected) + { + $options = array(); + foreach ($choices as $key => $option) { + if (is_array($option)) { + $options[] = $this->contentTag( + 'optgroup', + "\n".renderChoices($option, $selected)."\n", + array('label' => $this->escape($key)) + ); + } else { + $attributes = array('value' => $this->escape($key)); + + if (isset($selected[strval($key)])) { + $attributes['selected'] = true; + } + + $options[] = $this->contentTag( + 'option', + $this->escape($option), + $attributes + ); + } + } + + return implode("\n", $options); + } + /** * Prepares an attribute key and value for HTML representation. * diff --git a/src/Symfony/Component/Form/HtmlGeneratorInterface.php b/src/Symfony/Bundle/FrameworkBundle/Templating/HtmlGeneratorInterface.php similarity index 97% rename from src/Symfony/Component/Form/HtmlGeneratorInterface.php rename to src/Symfony/Bundle/FrameworkBundle/Templating/HtmlGeneratorInterface.php index 266b1c06029b9..d216b482166c6 100644 --- a/src/Symfony/Component/Form/HtmlGeneratorInterface.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/HtmlGeneratorInterface.php @@ -1,6 +1,6 @@ setParameter('twig.options', array_replace($container->getParameter('twig.options'), $config)); + + // form resources + foreach (array('resources', 'resource') as $key) { + if (isset($config['form'][$key])) { + $resources = $config['form'][$key]; + if (!is_array($resources)) { + $resources = array($resources); + } + $container->setParameter('twig.form.resources', array_merge($container->getParameter('twig.form.resources'), $resources)); + } + } } /** diff --git a/src/Symfony/Bundle/TwigBundle/Extension/FormExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/FormExtension.php new file mode 100644 index 0000000000000..39933e13264bf --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Extension/FormExtension.php @@ -0,0 +1,240 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * + * @author Fabien Potencier + */ +class FormExtension extends \Twig_Extension +{ + static protected $cache = array(); + + protected $resources; + protected $templates; + protected $environment; + protected $themes; + protected $generator; + + public function __construct(HtmlGeneratorInterface $generator, array $resources = array()) + { + $this->generator = $generator; + $this->themes = new \SplObjectStorage(); + $this->resources = array_merge(array( + 'TwigBundle::form.twig', + 'TwigBundle::widgets.twig', + ), $resources); + } + + /** + * {@inheritdoc} + */ + public function initRuntime(\Twig_Environment $environment) + { + $this->environment = $environment; + + $this->templates = $this->resolveResources($this->resources); + } + + public function setTheme(FieldGroupInterface $group, array $resources) + { + $this->themes->attach($group, $resources); + } + + /** + * Returns the token parser instance to add to the existing list. + * + * @return array An array of Twig_TokenParser instances + */ + public function getTokenParsers() + { + return array( + // {% form_theme form "SomeBungle::widgets.twig" %} + new FormThemeTokenParser(), + ); + } + + /** + * {@inheritdoc} + */ + public function getFilters() + { + return array( + 'render_enctype' => new \Twig_Filter_Method($this, 'renderEnctype', array('is_escaper' => true)), + 'render' => new \Twig_Filter_Method($this, 'render', array('is_escaper' => true)), + 'render_hidden' => new \Twig_Filter_Method($this, 'renderHidden', array('is_escaper' => true)), + 'render_errors' => new \Twig_Filter_Method($this, 'renderErrors', array('is_escaper' => true)), + 'render_widget' => new \Twig_Filter_Method($this, 'renderWidget', array('is_escaper' => true)), + 'render_label' => new \Twig_Filter_Method($this, 'renderLabel', array('is_escaper' => true)), + 'render_data' => new \Twig_Filter_Method($this, 'renderData', array('is_escaper' => true)), + 'render_choices' => new \Twig_Filter_Method($this, 'renderChoices', array('is_escaper' => true)), + ); + } + + public function renderEnctype(Form $form) + { + return $form->isMultipart() ? 'enctype="multipart/form-data"' : ''; + } + + public function render(FieldInterface $field, array $attributes = array()) + { + if ($field instanceof Form || get_class($field) === 'Symfony\Component\Form\FieldGroup') { + return $this->templates['group']->getBlock('group', array( + 'group' => $field, + 'attributes' => $attributes, + )); + } + + return $this->templates['field']->getBlock('field', array( + 'field' => $field, + 'attributes' => $attributes, + )); + } + + public function renderHidden(FieldGroupInterface $form) + { + return $this->templates['hidden']->getBlock('hidden', array( + 'fields' => $form->getHiddenFields() + )); + } + + public function renderErrors($formOrField) + { + return $this->templates['errors']->getBlock('errors', array( + 'errors' => $formOrField->getErrors() + )); + } + + public function renderLabel(FieldInterface $field, $label = null, array $attributes = array()) + { + return $this->templates['label']->getBlock('label', array( + 'id' => $field->getId(), + 'key' => $field->getKey(), + 'label' => null !== $label ? $label : ucfirst(strtolower(str_replace('_', ' ', $field->getKey()))), + 'attributes' => $attributes, + )); + } + + public function renderWidget(FieldInterface $field, array $attributes = array(), $resources = null) + { + if (null === $resources) { + $parent = $field; + $resources = array(); + while ($parent = $parent->getParent()) { + if (isset($this->themes[$parent])) { + $resources = $this->themes[$parent]; + } + } + } else { + $resources = array($resources); + } + + list($widget, $template) = $this->getWidget($field, $resources); + + return $template->getBlock($widget, array( + 'field' => $field, + 'attributes' => array_merge($field->getAttributes(), $attributes), + )); + } + + public function renderData(FieldInterface $field) + { + return $field->getData(); + } + + public function renderChoices(FieldInterface $field) + { + return $this->generator->choices( + $field->getPreferredChoices(), + $field->getOtherChoices(), + $field->getEmptyValue(), + $field->getSelected() + ); + } + + protected function getWidget(FieldInterface $field, array $resources = array()) + { + $cacheable = true; + $templates = array(); + if ($resources) { + $templates = $this->resolveResources($resources); + $cacheable = false; + } + + // add "global" templates as fallback + $templates = array_merge($this->templates, $templates); + + $class = get_class($field); + + if (true === $cacheable && isset(self::$cache[$class])) { + return self::$cache[$class]; + } + + // find a template for the given class or one of its parents + do { + $parts = explode('\\', $class); + $c = array_pop($parts); + + $underscore = strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($c, '_', '.'))); + + if (isset($templates[$underscore])) { + if (true === $cacheable) { + self::$cache[$class] = array($underscore, $templates[$underscore]); + } + + return array($underscore, $templates[$underscore]); + } + } while (false !== $class = get_parent_class($class)); + + throw new \RuntimeException(sprintf('Unable to render the "%s" field.', $field->getKey())); + } + + protected function resolveResources(array $resources) + { + $templates = array(); + foreach ($resources as $resource) + { + $blocks = $this->resolveTemplate($this->environment->loadTemplate($resource)); + + $templates = array_replace($templates, $blocks); + } + + return $templates; + } + + protected function resolveTemplate($template) + { + // an array of blockName => template + $blocks = array(); + foreach ($template->getBlockNames() as $name) { + $blocks[$name] = $template; + } + + return $blocks; + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'form'; + } +} diff --git a/src/Symfony/Bundle/TwigBundle/Extension/HtmlExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/HtmlExtension.php new file mode 100644 index 0000000000000..32633aa7c5a64 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Extension/HtmlExtension.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * + * @author Fabien Potencier + */ +class HtmlExtension extends \Twig_Extension +{ + protected $generator; + + public function __construct(HtmlGeneratorInterface $generator) + { + $this->generator = $generator; + } + + public function getGenerator() + { + return $this->generator; + } + + /** + * Returns the token parser instance to add to the existing list. + * + * @return array An array of Twig_TokenParser instances + */ + public function getTokenParsers() + { + return array( + // {% tag "input" with attributes %} + new TagTokenParser(), + + // {% contenttag "textarea" with attributes %}content{% endcontenttag %} + new ContentTagTokenParser(), + ); + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'html'; + } +} diff --git a/src/Symfony/Bundle/TwigBundle/Node/FormThemeNode.php b/src/Symfony/Bundle/TwigBundle/Node/FormThemeNode.php new file mode 100644 index 0000000000000..d697bd620d460 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Node/FormThemeNode.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * + * + * @author Fabien Potencier + */ +class FormThemeNode extends \Twig_Node +{ + public function __construct(\Twig_NodeInterface $form, \Twig_NodeInterface $resources, $lineno, $tag = null) + { + parent::__construct(array('form' => $form, 'resources' => $resources), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param \Twig_Compiler A Twig_Compiler instance + */ + public function compile($compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo $this->env->getExtension(\'form\')->setTheme(') + ->subcompile($this->getNode('form')) + ->raw(', array(') + ; + + foreach ($this->getNode('resources') as $resource) { + $compiler + ->subcompile($resource) + ->raw(', ') + ; + } + + $compiler->raw('));'); + } +} diff --git a/src/Symfony/Bundle/TwigBundle/Node/HelperNode.php b/src/Symfony/Bundle/TwigBundle/Node/HelperNode.php index a4d8d4eb0c380..eba6b5ca66ca5 100644 --- a/src/Symfony/Bundle/TwigBundle/Node/HelperNode.php +++ b/src/Symfony/Bundle/TwigBundle/Node/HelperNode.php @@ -35,15 +35,15 @@ public function compile($compiler) ->raw("\$this->env->getExtension(") ->string('symfony.helpers') ->raw(")->getContainer()->get(") - ->string($this['helper']) + ->string($this->getAttribute('helper')) ->raw(")->") - ->raw($this['method']) + ->raw($this->getAttribute('method')) ->raw("(") ; - foreach ($this->values as $i => $value) { + foreach ($this->getNode('values') as $i => $value) { $compiler->subcompile($value); - if ($i !== count($this->values) - 1) { + if ($i !== count($this->getNode('values')) - 1) { $compiler->raw(', '); } } diff --git a/src/Symfony/Bundle/TwigBundle/Node/TagNode.php b/src/Symfony/Bundle/TwigBundle/Node/TagNode.php new file mode 100644 index 0000000000000..8bad2b95f382a --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Node/TagNode.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * + * + * @author Fabien Potencier + */ +class TagNode extends \Twig_Node +{ + public function __construct(\Twig_NodeInterface $htmlTag, \Twig_NodeInterface $content = null, \Twig_Node_Expression $attributes = null, $lineno, $tag = null) + { + parent::__construct(array('html_tag' => $htmlTag, 'content' => $content, 'html_attributes' => $attributes), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param \Twig_Compiler A Twig_Compiler instance + */ + public function compile($compiler) + { + $compiler->addDebugInfo($this); + + $method = null === $this->getNode('content') ? 'tag' : 'contentTag'; + + if (null !== $this->getNode('content')) { + $compiler + ->write("ob_start();\n") + ->subcompile($this->getNode('content')) + ->write('$content = ob_get_clean();') + ; + } + + $compiler + ->write('echo $this->env->getExtension(\'html\')->getGenerator()->'.$method.'(') + ->subcompile($this->getNode('html_tag')) + ->raw(', ') + ; + + if (null !== $this->getNode('content')) { + $compiler + ->raw('$content, ') + ; + } + + $compiler + ->subcompile($this->getNode('html_attributes')) + ->raw(');') + ; + } +} diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd index 68fe823855b4a..024d2580d5532 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd @@ -5,14 +5,24 @@ targetNamespace="http://www.symfony-project.org/schema/dic/twig" elementFormDefault="qualified"> - + - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index 1ca4e88e66825..8c8368e8a2552 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -13,6 +13,7 @@ Symfony\Bundle\TwigBundle\Loader\Loader Symfony\Bundle\TwigBundle\Renderer\Renderer + @@ -42,9 +43,20 @@
+ + + + + + + + + + %twig.form.resources% +
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/form.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/form.twig new file mode 100644 index 0000000000000..ba3b2c732e5ac --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/form.twig @@ -0,0 +1,41 @@ +{% block group %} + {{ group|render_errors }} + + {% for field in group %} + {% if not field.ishidden %} + {{ field|render }} + {% endif %} + {% endfor %} +
+ {{ group|render_hidden }} +{% endblock group %} + +{% block field %} + + {{ field|render_label }} + + {{ field|render_errors }} + {{ field|render_widget }} + + +{% endblock field %} + +{% block errors %} + {% if errors %} +
    + {% for error in errors %} +
  • {% trans error.0 with error.1 from validators %}
  • + {% endfor %} +
+ {% endif %} +{% endblock errors %} + +{% block hidden %} + {% for field in fields %} + {{ field|render_widget }} + {% endfor %} +{% endblock hidden %} + +{% block label %} + +{% endblock label %} diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/widgets.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/widgets.twig new file mode 100644 index 0000000000000..f7d104f2bc3ba --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/widgets.twig @@ -0,0 +1,57 @@ +{% block input_field %} + {% tag "input" with attributes %} +{% endblock input_field %} + +{% block textarea_field %} + {% contenttag "textarea" with attributes %}{{ field.displayedData }}{% endcontenttag %} +{% endblock textarea_field %} + +{% block choice_field %} + {% if field.options.expanded %} + {% for child in field %} + {{ child|render_widget }} + {% endfor %} + {% else %} + {% contenttag "select" with attributes %} + {{ field|render_choices }} + {% endcontenttag %} + {% endif %} +{% endblock choice_field %} + +{% block toggle_field %} + {% display input_field %} + {% if field.options.label %} + {% contenttag "label" with ['for': field.id] %}{% trans field.options.label %}{% endcontenttag %} + {% endif %} +{% endblock toggle_field %} + +{% block date_time_field %} + {{ field.date|render_widget }} + {{ field.time|render_widget }} +{% endblock date_time_field %} + +{% block date_field %} + {% if field.field %} + {% display input_field %} + {% else %} + {{ field.pattern|replace(['{{ year }}': field.year|render_widget, '{{ month }}': field.month|render_widget, '{{ day }}': field.day|render_widget,]) }} + {% endif %} +{% endblock date_field %} + +{% block time_field %} + {% if field.isfield %} + {% display input_field %} + {% else %} + {{ field.hour|render_widget }}:{{ field.minute|render_widget }} + {% if field.options.with_seconds %}:{{ field.second|render_widget }}{% endif %} + {% endif %} +{% endblock time_field %} + +{% block money_field %} + {% set widget %}{% display input_field %}{% endset %} + {{ field.pattern|replace(['{{ widget }}': widget]) }} +{% endblock money_field %} + +{% block percent_field %} + {% display input_field %} % +{% endblock percent_field %} diff --git a/src/Symfony/Bundle/TwigBundle/TokenParser/ContentTagTokenParser.php b/src/Symfony/Bundle/TwigBundle/TokenParser/ContentTagTokenParser.php new file mode 100644 index 0000000000000..d4ba0eecaf64f --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/TokenParser/ContentTagTokenParser.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * + * + * @author Fabien Potencier + */ +class ContentTagTokenParser extends \Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param \Twig_Token $token A Twig_Token instance + * + * @return \Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(\Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + + $tag = $this->parser->getExpressionParser()->parseExpression(); + + $attributes = null; + if ($stream->test('with')) { + $stream->next(); + $attributes = $this->parser->getExpressionParser()->parseExpression(); + } + + $stream->expect(\Twig_Token::BLOCK_END_TYPE); + + $content = $this->parser->subparse(array($this, 'decideContentTagFork'), true); + + $stream->expect(\Twig_Token::BLOCK_END_TYPE); + + return new TagNode($tag, $content, $attributes, $lineno, $this->getTag()); + } + + public function decideContentTagFork($token) + { + return $token->test(array('endcontenttag')); + } + + /** + * Gets the tag name associated with this token parser. + * + * @param string The tag name + */ + public function getTag() + { + return 'contenttag'; + } +} diff --git a/src/Symfony/Bundle/TwigBundle/TokenParser/FormThemeTokenParser.php b/src/Symfony/Bundle/TwigBundle/TokenParser/FormThemeTokenParser.php new file mode 100644 index 0000000000000..7fd3974bc6b14 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/TokenParser/FormThemeTokenParser.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * + * + * @author Fabien Potencier + */ +class FormThemeTokenParser extends \Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param \Twig_Token $token A Twig_Token instance + * + * @return \Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(\Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + + $form = $this->parser->getExpressionParser()->parseExpression(); + $resources = array(); + do { + $resources[] = $this->parser->getExpressionParser()->parseExpression(); + } while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)); + + $stream->expect(\Twig_Token::BLOCK_END_TYPE); + + return new FormThemeNode($form, new \Twig_Node($resources), $lineno, $this->getTag()); + } + + /** + * Gets the tag name associated with this token parser. + * + * @param string The tag name + */ + public function getTag() + { + return 'form_theme'; + } +} diff --git a/src/Symfony/Bundle/TwigBundle/TokenParser/TagTokenParser.php b/src/Symfony/Bundle/TwigBundle/TokenParser/TagTokenParser.php new file mode 100644 index 0000000000000..43222c3346ac9 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/TokenParser/TagTokenParser.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * + * + * @author Fabien Potencier + */ +class TagTokenParser extends \Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param \Twig_Token $token A Twig_Token instance + * + * @return \Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(\Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + + $tag = $this->parser->getExpressionParser()->parseExpression(); + + $attributes = null; + if ($stream->test('with')) { + $stream->next(); + $attributes = $this->parser->getExpressionParser()->parseExpression(); + } + + $stream->expect(\Twig_Token::BLOCK_END_TYPE); + + return new TagNode($tag, null, $attributes, $lineno, $this->getTag()); + } + + /** + * Gets the tag name associated with this token parser. + * + * @param string The tag name + */ + public function getTag() + { + return 'tag'; + } +} diff --git a/src/Symfony/Component/Form/CheckboxField.php b/src/Symfony/Component/Form/CheckboxField.php index 6fd3971725062..6fed502f4f745 100644 --- a/src/Symfony/Component/Form/CheckboxField.php +++ b/src/Symfony/Component/Form/CheckboxField.php @@ -21,10 +21,10 @@ class CheckboxField extends ToggleField /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - return parent::render(array_merge(array( + return array_merge(parent::getAttributes(), array( 'type' => 'checkbox', - ), $attributes)); + )); } } \ No newline at end of file diff --git a/src/Symfony/Component/Form/ChoiceField.php b/src/Symfony/Component/Form/ChoiceField.php index e05bbcd7d8969..adc309cfa1058 100644 --- a/src/Symfony/Component/Form/ChoiceField.php +++ b/src/Symfony/Component/Form/ChoiceField.php @@ -37,7 +37,6 @@ protected function configure() $this->addOption('multiple', false); $this->addOption('expanded', false); $this->addOption('empty_value', ''); - $this->addOption('translate_choices', false); if (!is_array($this->getOption('choices'))) { throw new UnexpectedTypeException('The choices option must be an array'); @@ -70,6 +69,51 @@ protected function configure() } } + /** + * {@inheritDoc} + */ + public function getAttributes() + { + $attributes = array( + 'id' => $this->getId(), + 'name' => $this->getName(), + 'disabled' => $this->isDisabled(), + ); + + // Add "[]" to the name in case a select tag with multiple options is + // displayed. Otherwise only one of the selected options is sent in the + // POST request. + if ($this->getOption('multiple') && !$this->getOption('expanded')) { + $attributes['name'] .= '[]'; + } + + if ($this->getOption('multiple')) { + $attributes['multiple'] = 'multiple'; + } + + return array_merge(parent::getAttributes(), $attributes); + } + + public function getSelected() + { + return array_flip(array_map('strval', (array) $this->getDisplayedData())); + } + + public function getPreferredChoices() + { + return array_intersect_key($this->getOption('choices'), $this->preferredChoices); + } + + public function getOtherChoices() + { + return array_diff_key($this->getOption('choices'), $this->preferredChoices); + } + + public function getEmptyValue() + { + return $this->isRequired() ? false : $this->getOption('empty_value'); + } + /** * Returns a new field of type radio button or checkbox. * @@ -82,13 +126,11 @@ protected function newChoiceField($choice, $label) return new CheckboxField($choice, array( 'value' => $choice, 'label' => $label, - 'translate_label' => $this->getOption('translate_choices'), )); } else { return new RadioField($choice, array( 'value' => $choice, 'label' => $label, - 'translate_label' => $this->getOption('translate_choices'), )); } } @@ -171,91 +213,4 @@ protected function reverseTransform($value) return parent::reverseTransform($value); } } - - /** - * {@inheritDoc} - */ - public function render(array $attributes = array()) - { - if ($this->getOption('expanded')) { - $html = ""; - - foreach ($this as $field) { - $html .= $field->render()."\n"; - } - - return $html; - } else { - $attrs['id'] = $this->getId(); - $attrs['name'] = $this->getName(); - $attrs['disabled'] = $this->isDisabled(); - - // Add "[]" to the name in case a select tag with multiple options is - // displayed. Otherwise only one of the selected options is sent in the - // POST request. - if ($this->getOption('multiple') && !$this->getOption('expanded')) { - $attrs['name'] .= '[]'; - } - - if ($this->getOption('multiple')) { - $attrs['multiple'] = 'multiple'; - } - - $selected = array_flip(array_map('strval', (array)$this->getDisplayedData())); - $html = "\n"; - - if (!$this->isRequired()) { - $html .= $this->renderChoices(array('' => $this->getOption('empty_value')), $selected)."\n"; - } - - $choices = $this->getOption('choices'); - - if (count($this->preferredChoices) > 0) { - $html .= $this->renderChoices(array_intersect_key($choices, $this->preferredChoices), $selected)."\n"; - $html .= $this->generator->contentTag('option', $this->getOption('separator'), array('disabled' => true))."\n"; - } - - $html .= $this->renderChoices(array_diff_key($choices, $this->preferredChoices), $selected)."\n"; - - return $this->generator->contentTag('select', $html, array_merge($attrs, $attributes)); - } - } - - /** - * Returns an array of option tags for the choice field - * - * @return array An array of option tags - */ - protected function renderChoices(array $choices, array $selected) - { - $options = array(); - - foreach ($choices as $key => $option) { - if (is_array($option)) { - $options[] = $this->generator->contentTag( - 'optgroup', - "\n".$this->renderChoices($option, $selected)."\n", - array('label' => $this->generator->escape($key)) - ); - } else { - $attributes = array('value' => $this->generator->escape($key)); - - if (isset($selected[strval($key)])) { - $attributes['selected'] = true; - } - - if ($this->getOption('translate_choices')) { - $option = $this->translate($option); - } - - $options[] = $this->generator->contentTag( - 'option', - $this->generator->escape($option), - $attributes - ); - } - } - - return implode("\n", $options); - } } diff --git a/src/Symfony/Component/Form/Configurable.php b/src/Symfony/Component/Form/Configurable.php index 455286d7dbe86..e956b3354c635 100644 --- a/src/Symfony/Component/Form/Configurable.php +++ b/src/Symfony/Component/Form/Configurable.php @@ -143,4 +143,9 @@ public function hasOption($name) { return isset($this->options[$name]); } + + public function getOptions() + { + return $this->options; + } } diff --git a/src/Symfony/Component/Form/DateField.php b/src/Symfony/Component/Form/DateField.php index 399986f56243a..688c6e41566a2 100644 --- a/src/Symfony/Component/Form/DateField.php +++ b/src/Symfony/Component/Form/DateField.php @@ -79,7 +79,7 @@ class DateField extends HybridField * * data_timezone: The timezone of the data * * user_timezone: The timezone of the user entering a new value * * pattern: The pattern for the select boxes when "widget" is "select". - * You can use the placeholders "%year%", "%month%" and "%day%". + * You can use the placeholders "{{ year }}", "{{ month }}" and "{{ day }}". * Default: locale dependent * * @param array $options Options for this field @@ -145,6 +145,23 @@ protected function configure() } } + /** + * {@inheritDoc} + */ + public function getAttributes() + { + if ($this->isField()) { + return array_merge(parent::getAttributes(), array( + 'id' => $this->getId(), + 'name' => $this->getName(), + 'value' => $this->getDisplayedData(), + 'type' => 'text', + )); + } + + return parent::getAttributes(); + } + /** * Generates an array of choices for the given values * @@ -194,41 +211,22 @@ protected function generateMonthChoices(array $months) return $choices; } - /** - * {@inheritDoc} - */ - public function render(array $attributes = array()) + public function getPattern() { - if ($this->getOption('widget') === self::INPUT) { - return $this->generator->tag('input', array_merge(array( - 'id' => $this->getId(), - 'name' => $this->getName(), - 'value' => $this->getDisplayedData(), - 'type' => 'text', - ), $attributes)); - } else { - // set order as specified in the pattern - if ($this->getOption('pattern')) { - $pattern = $this->getOption('pattern'); - } - // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) - // lookup various formats at http://userguide.icu-project.org/formatparse/datetime - else if (preg_match('/^([yMd]+).+([yMd]+).+([yMd]+)$/', $this->formatter->getPattern())) { - $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('%year%', '%month%', '%day%'), $this->formatter->getPattern()); - } - // default fallback - else { - $pattern = '%year%-%month%-%day%'; - } + // set order as specified in the pattern + if ($this->getOption('pattern')) { + return $this->getOption('pattern'); + } - return str_replace(array('%year%', '%month%', '%day%'), array( - $this->get('year')->render($attributes), - $this->get('month')->render($attributes), - $this->get('day')->render($attributes), - ), $pattern); + // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) + // lookup various formats at http://userguide.icu-project.org/formatparse/datetime + if (preg_match('/^([yMd]+).+([yMd]+).+([yMd]+)$/', $this->formatter->getPattern())) { + return preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $this->formatter->getPattern()); } - } + // default fallback + return '{{ year }}-{{ month }}-{{ day }}'; + } /** * Sets the locale of this field. diff --git a/src/Symfony/Component/Form/DateTimeField.php b/src/Symfony/Component/Form/DateTimeField.php index 1bc373cac8967..7b9c63188dbe5 100644 --- a/src/Symfony/Component/Form/DateTimeField.php +++ b/src/Symfony/Component/Form/DateTimeField.php @@ -120,15 +120,4 @@ protected function reverseTransform($value) { return parent::reverseTransform(array_merge($value['date'], $value['time'])); } - - /** - * {@inheritDoc} - */ - public function render(array $attributes = array()) - { - $html = $this->get('date')->render($attributes)."\n"; - $html .= $this->get('time')->render($attributes); - - return $html; - } } diff --git a/src/Symfony/Component/Form/Field.php b/src/Symfony/Component/Form/Field.php index fc0aca3b2c0e1..8b2734b58e54c 100644 --- a/src/Symfony/Component/Form/Field.php +++ b/src/Symfony/Component/Form/Field.php @@ -15,24 +15,15 @@ use Symfony\Component\Form\Exception\PropertyAccessDeniedException; use Symfony\Component\Form\ValueTransformer\ValueTransformerInterface; use Symfony\Component\Form\ValueTransformer\TransformationFailedException; -use Symfony\Component\I18N\TranslatorInterface; abstract class Field extends Configurable implements FieldInterface { - /** - * The object used for generating HTML code - * @var HtmlGeneratorInterface - */ - protected $generator = null; - protected $taintedData = null; protected $locale = null; - protected $translator = null; private $errors = array(); private $key = ''; private $parent = null; - private $renderer = null; private $bound = false; private $required = null; private $data = null; @@ -48,7 +39,6 @@ public function __construct($key, array $options = array()) $this->addOption('property_path', (string)$key); $this->key = (string)$key; - $this->generator = new HtmlGenerator(); if ($this->locale === null) { $this->locale = class_exists('\Locale', false) ? \Locale::getDefault() : 'en'; @@ -70,6 +60,11 @@ public function __clone() // TODO } + public function getAttributes() + { + return array(); + } + /** * Returns the data of the field as it is displayed to the user. * @@ -172,14 +167,6 @@ public function isDisabled() } } - /** - * {@inheritDoc} - */ - public function setGenerator(HtmlGeneratorInterface $generator) - { - $this->generator = $generator; - } - /** * {@inheritDoc} */ @@ -287,9 +274,9 @@ public function getData() * * @see FieldInterface */ - public function addError($message, PropertyPath $path = null, $type = null) + public function addError($messageTemplate, array $messageParameters = array(), PropertyPath $path = null, $type = null) { - $this->errors[] = $message; + $this->errors[] = array($messageTemplate, $messageParameters); } /** @@ -347,55 +334,17 @@ public function setLocale($locale) } /** - * Sets the translator of this field. + * Injects the locale into the given object, if set. * - * @see Translatable - */ - public function setTranslator(TranslatorInterface $translator) - { - $this->translator = $translator; - - if ($this->valueTransformer !== null && $this->valueTransformer instanceof Translatable) { - $this->valueTransformer->setTranslator($translator); - } - } - - /** - * Translates the text using the associated translator, if available - * - * If no translator is available, the original text is returned without - * modification. - * - * @param string $text The text to translate - * @param array $parameters The parameters to insert in the text - * @return string The translated text - */ - protected function translate($text, array $parameters = array()) - { - if ($this->translator !== null) { - $text = $this->translator->translate($text, $parameters); - } - - return $text; - } - - /** - * Injects the locale and the translator into the given object, if set. - * - * The locale is injected only if the object implements Localizable. The - * translator is injected only if the object implements Translatable. + * The locale is injected only if the object implements Localizable. * * @param object $object */ - protected function injectLocaleAndTranslator($object) + protected function injectLocale($object) { if ($object instanceof Localizable) { $object->setLocale($this->locale); } - - if (!is_null($this->translator) && $object instanceof Translatable) { - $object->setTranslator($this->translator); - } } /** @@ -405,7 +354,7 @@ protected function injectLocaleAndTranslator($object) */ public function setValueTransformer(ValueTransformerInterface $valueTransformer) { - $this->injectLocaleAndTranslator($valueTransformer); + $this->injectLocale($valueTransformer); $this->valueTransformer = $valueTransformer; } @@ -630,24 +579,4 @@ protected function updateProperty(&$objectOrArray, PropertyPath $propertyPath) $objectOrArray[$propertyPath->getCurrent()] = $this->getData(); } } - - /** - * {@inheritDoc} - */ - public function renderErrors() - { - $html = ''; - - if ($this->hasErrors()) { - $html .= "
    \n"; - - foreach ($this->getErrors() as $error) { - $html .= "
  • " . $error . "
  • \n"; - } - - $html .= "
\n"; - } - - return $html; - } } diff --git a/src/Symfony/Component/Form/FieldGroup.php b/src/Symfony/Component/Form/FieldGroup.php index 97cf3f90f2f4b..156028cdc6193 100644 --- a/src/Symfony/Component/Form/FieldGroup.php +++ b/src/Symfony/Component/Form/FieldGroup.php @@ -13,10 +13,7 @@ use Symfony\Component\Form\Exception\AlreadyBoundException; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Renderer\RendererInterface; -use Symfony\Component\Form\Renderer\TableRenderer; use Symfony\Component\Form\Iterator\RecursiveFieldsWithPropertyPathIterator; -use Symfony\Component\I18N\TranslatorInterface; /** * FieldGroup represents an array of widgets bind to names and values. @@ -37,19 +34,6 @@ class FieldGroup extends Field implements \IteratorAggregate, FieldGroupInterfac */ protected $extraFields = array(); - /** - * Constructor - * - * @see FieldInterface::__construct() - */ - public function __construct($key, array $options = array()) - { - // set the default renderer before calling the configure() method - $this->setRenderer(new TableRenderer()); - - parent::__construct($key, $options); - } - /** * Clones this group */ @@ -109,11 +93,6 @@ public function add(FieldInterface $field) $field->setParent($this); $field->setLocale($this->locale); - $field->setGenerator($this->generator); - - if ($this->translator !== null) { - $field->setTranslator($this->translator); - } $data = $this->getTransformedData(); @@ -367,7 +346,7 @@ public function isValid() /** * {@inheritDoc} */ - public function addError($message, PropertyPath $path = null, $type = null) + public function addError($messageTemplate, array $messageParameters = array(), PropertyPath $path = null, $type = null) { if ($path !== null) { if ($type === self::FIELD_ERROR && $path->hasNext()) { @@ -378,7 +357,7 @@ public function addError($message, PropertyPath $path = null, $type = null) } if ($this->has($path->getCurrent()) && !$this->get($path->getCurrent())->isHidden()) { - $this->get($path->getCurrent())->addError($message, $path, $type); + $this->get($path->getCurrent())->addError($messageTemplate, $messageParameters, $path, $type); return; } @@ -395,7 +374,7 @@ public function addError($message, PropertyPath $path = null, $type = null) $path->next(); } - $field->addError($message, $path, $type); + $field->addError($messageTemplate, $messageParameters, $path, $type); return; } @@ -404,7 +383,7 @@ public function addError($message, PropertyPath $path = null, $type = null) } } - parent::addError($message); + parent::addError($messageTemplate, $messageParameters); } /** @@ -423,67 +402,6 @@ public function isMultipart() return false; } - /** - * Sets the renderer. - * - * @param RendererInterface $renderer - */ - public function setRenderer(RendererInterface $renderer) - { - $this->renderer = $renderer; - } - - /** - * Returns the current renderer. - * - * @return RendererInterface - */ - public function getRenderer() - { - return $this->renderer; - } - - /** - * Delegates the rendering of the field to the renderer set. - * - * @return string The rendered widget - */ - public function render(array $attributes = array()) - { - $this->injectLocaleAndTranslator($this->renderer); - - return $this->renderer->render($this, $attributes); - } - - /** - * Delegates the rendering of the field to the renderer set. - * - * @return string The rendered widget - */ - public function renderErrors() - { - $this->injectLocaleAndTranslator($this->renderer); - - return $this->renderer->renderErrors($this); - } - /** - * Renders hidden form fields. - * - * @param boolean $recursive False will prevent hidden fields from embedded forms from rendering - * - * @return string - */ - public function renderHiddenFields($recursive = true) - { - $output = ''; - - foreach ($this->getHiddenFields($recursive) as $field) { - $output .= $field->render(); - } - - return $output; - } - /** * Returns true if the bound field exists (implements the \ArrayAccess interface). * @@ -566,33 +484,4 @@ public function setLocale($locale) $field->setLocale($locale); } } - - /** - * Sets the translator of this field. - * - * @see Translatable - */ - public function setTranslator(TranslatorInterface $translator) - { - parent::setTranslator($translator); - - foreach ($this->fields as $field) { - $field->setTranslator($translator); - } - } - - /** - * Distributes the generator among all nested fields - * - * @param HtmlGeneratorInterface $generator - */ - public function setGenerator(HtmlGeneratorInterface $generator) - { - parent::setGenerator($generator); - - // TESTME - foreach ($this->fields as $field) { - $field->setGenerator($generator); - } - } } diff --git a/src/Symfony/Component/Form/FieldInterface.php b/src/Symfony/Component/Form/FieldInterface.php index b076209a078df..e6c3ed4e614bb 100644 --- a/src/Symfony/Component/Form/FieldInterface.php +++ b/src/Symfony/Component/Form/FieldInterface.php @@ -18,7 +18,7 @@ * * @author Bernhard Schussek */ -interface FieldInterface extends Localizable, Translatable +interface FieldInterface extends Localizable { /** * Marks a constraint violation in a form field @@ -185,23 +185,7 @@ public function bind($taintedData); * @param PropertyPath $path * @param ConstraintViolation$violation */ - public function addError($message, PropertyPath $path = null, $type = null); - - /** - * Renders this field. - * - * @param array $attributes The attributes to include in the rendered - * output - * @return string The rendered output of this field - */ - public function render(array $attributes = array()); - - /** - * Renders the errors of this field. - * - * @return string The rendered output of the field errors - */ - public function renderErrors(); + function addError($messageTemplate, array $messageParameters = array(), PropertyPath $path = null, $type = null); /** * Returns whether the field is bound. @@ -261,14 +245,4 @@ public function isHidden(); * @param boolean $required */ public function setRequired($required); - - /** - * Sets the generator used for rendering HTML. - * - * Usually there is one generator instance shared between all fields of a - * form. - * - * @param string $charset - */ - public function setGenerator(HtmlGeneratorInterface $generator); } diff --git a/src/Symfony/Component/Form/FileField.php b/src/Symfony/Component/Form/FileField.php index e712f4a14f356..27f50553d5a6e 100644 --- a/src/Symfony/Component/Form/FileField.php +++ b/src/Symfony/Component/Form/FileField.php @@ -19,11 +19,11 @@ class FileField extends InputField /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - return parent::render(array_merge(array( + return array_merge(parent::getAttributes(), array( 'type' => 'file', - ), $attributes)); + )); } /** diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index b8809f5779a05..9994325dc7de0 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -12,7 +12,6 @@ */ use Symfony\Component\Validator\ValidatorInterface; -use Symfony\Component\I18N\TranslatorInterface; /** * Form represents a form. @@ -34,7 +33,6 @@ class Form extends FieldGroup protected static $defaultCsrfProtection = false; protected static $defaultCsrfFieldName = '_token'; protected static $defaultLocale = null; - protected static $defaultTranslator = null; protected $validator = null; protected $validationGroups = null; @@ -51,7 +49,6 @@ class Form extends FieldGroup */ public function __construct($name, $object, ValidatorInterface $validator, array $options = array()) { - $this->generator = new HtmlGenerator(); $this->validator = $validator; $this->setData($object); @@ -71,26 +68,9 @@ public function __construct($name, $object, ValidatorInterface $validator, array $this->setLocale(self::$defaultLocale); } - if (self::$defaultTranslator !== null) { - $this->setTranslator(self::$defaultTranslator); - } - parent::__construct($name, $options); } - /** - * Sets the charset used for rendering HTML - * - * This method overrides the internal HTML generator! If you want to use - * your own generator, use setGenerator() instead. - * - * @param string $charset - */ - public function setCharset($charset) - { - $this->setGenerator(new HtmlGenerator($charset)); - } - /** * Sets the validation groups for this form. * @@ -131,26 +111,6 @@ static public function getDefaultLocale() return self::$defaultLocale; } - /** - * Sets the default translator for newly created forms. - * - * @param TranslatorInterface $defaultTranslator - */ - static public function setDefaultTranslator(TranslatorInterface $defaultTranslator) - { - self::$defaultTranslator = $defaultTranslator; - } - - /** - * Returns the default translator for newly created forms. - * - * @return TranslatorInterface - */ - static public function getDefaultTranslator() - { - return self::$defaultTranslator; - } - /** * Binds the form with values and files. * @@ -191,7 +151,7 @@ final public function bind($taintedValues, array $taintedFiles = null) $type = self::FIELD_ERROR; } - $this->addError($violation->getMessage(), $propertyPath, $type); + $this->addError($violation->getMessageTemplate(), $violation->getMessageParameters(), $propertyPath, $type); } } } @@ -208,26 +168,6 @@ protected function doBind(array $taintedData) parent::bind($taintedData); } - /** - * Gets the stylesheet paths associated with the form. - * - * @return array An array of stylesheet paths - */ - public function getStylesheets() - { - return $this->getWidget()->getStylesheets(); - } - - /** - * Gets the JavaScript paths associated with the form. - * - * @return array An array of JavaScript paths - */ - public function getJavaScripts() - { - return $this->getWidget()->getJavaScripts(); - } - /** * Returns a CSRF token for the set CSRF secret * @@ -385,28 +325,6 @@ static public function getDefaultCsrfSecret() return self::$defaultCsrfSecret; } - /** - * Renders the form tag. - * - * This method only renders the opening form tag. - * You need to close it after the form rendering. - * - * This method takes into account the multipart widgets. - * - * @param string $url The URL for the action - * @param array $attributes An array of HTML attributes - * - * @return string An HTML representation of the opening form tag - */ - public function renderFormTag($url, array $attributes = array()) - { - return sprintf('', $this->generator->attributes(array_merge(array( - 'action' => $url, - 'method' => isset($attributes['method']) ? strtolower($attributes['method']) : 'post', - 'enctype' => $this->isMultipart() ? 'multipart/form-data' : null, - ), $attributes))); - } - /** * Returns whether the maximum POST size was reached in this request. * diff --git a/src/Symfony/Component/Form/HiddenField.php b/src/Symfony/Component/Form/HiddenField.php index 0cff38a16e34e..4e68b51c56a1b 100644 --- a/src/Symfony/Component/Form/HiddenField.php +++ b/src/Symfony/Component/Form/HiddenField.php @@ -21,11 +21,11 @@ class HiddenField extends InputField /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - return parent::render(array_merge(array( - 'type' => 'hidden', - ), $attributes)); + return array_merge(parent::getAttributes(), array( + 'type' => 'hidden', + )); } /** diff --git a/src/Symfony/Component/Form/HybridField.php b/src/Symfony/Component/Form/HybridField.php index 616320905c4a6..4214dfa6ed4f3 100644 --- a/src/Symfony/Component/Form/HybridField.php +++ b/src/Symfony/Component/Form/HybridField.php @@ -48,6 +48,21 @@ public function setFieldMode($mode) $this->mode = $mode; } + public function isField() + { + return self::FIELD === $this->mode; + } + + public function isGroup() + { + return self::GROUP === $this->mode; + } + + public function getFieldMode() + { + return $this->mode; + } + /** * {@inheritDoc} * diff --git a/src/Symfony/Component/Form/InputField.php b/src/Symfony/Component/Form/InputField.php index b98e73b68ab4d..96e217c4f1517 100644 --- a/src/Symfony/Component/Form/InputField.php +++ b/src/Symfony/Component/Form/InputField.php @@ -21,13 +21,13 @@ abstract class InputField extends Field /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - return $this->generator->tag('input', array_merge(array( - 'id' => $this->getId(), - 'name' => $this->getName(), - 'value' => $this->getDisplayedData(), - 'disabled' => $this->isDisabled(), - ), $attributes)); + return array_merge(parent::getAttributes(), array( + 'id' => $this->getId(), + 'name' => $this->getName(), + 'value' => $this->getDisplayedData(), + 'disabled' => $this->isDisabled(), + )); } } diff --git a/src/Symfony/Component/Form/MoneyField.php b/src/Symfony/Component/Form/MoneyField.php index 06c50547f89ac..f603bf143af89 100644 --- a/src/Symfony/Component/Form/MoneyField.php +++ b/src/Symfony/Component/Form/MoneyField.php @@ -47,37 +47,25 @@ protected function configure() ))); } - /** - * {@inheritDoc} - */ - public function render(array $attributes = array()) - { - $input = parent::render($attributes); - - if ($this->getOption('currency')) { - return str_replace('%widget%', $input, $this->getPattern($this->locale, $this->getOption('currency'))); - } else { - return $input; - } - } - /** * Returns the pattern for this locale * - * The pattern contains the placeholder "%widget%" where the HTML tag should + * The pattern contains the placeholder "{{ widget }}" where the HTML tag should * be inserted - * - * @param string $locale */ - protected static function getPattern($locale, $currency) + protected function getPattern() { - if (!isset(self::$patterns[$locale])) { - self::$patterns[$locale] = array(); + if (!$this->getOption('currency')) { + return '{{ widget }}'; + } + + if (!isset(self::$patterns[$this->locale])) { + self::$patterns[$this->locale] = array(); } - if (!isset(self::$patterns[$locale][$currency])) { - $format = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); - $pattern = $format->formatCurrency('123', $currency); + if (!isset(self::$patterns[$this->locale][$this->getOption('currency')])) { + $format = new \NumberFormatter($this->locale, \NumberFormatter::CURRENCY); + $pattern = $format->formatCurrency('123', $this->getOption('currency')); // the spacings between currency symbol and number are ignored, because // a single space leads to better readability in combination with input @@ -88,14 +76,14 @@ protected static function getPattern($locale, $currency) preg_match('/^([^\s\xc2\xa0]*)[\s\xc2\xa0]*123[,.]00[\s\xc2\xa0]*([^\s\xc2\xa0]*)$/', $pattern, $matches); if (!empty($matches[1])) { - self::$patterns[$locale] = $matches[1].' %widget%'; + self::$patterns[$this->locale] = $matches[1].' {{ widget }}'; } else if (!empty($matches[2])) { - self::$patterns[$locale] = '%widget% '.$matches[2]; + self::$patterns[$this->locale] = '{{ widget }} '.$matches[2]; } else { - self::$patterns[$locale] = '%widget%'; + self::$patterns[$this->locale] = '{{ widget }}'; } } - return self::$patterns[$locale]; + return self::$patterns[$this->locale]; } -} \ No newline at end of file +} diff --git a/src/Symfony/Component/Form/NumberField.php b/src/Symfony/Component/Form/NumberField.php index 46169bf33945b..24a45b25a773a 100644 --- a/src/Symfony/Component/Form/NumberField.php +++ b/src/Symfony/Component/Form/NumberField.php @@ -40,10 +40,10 @@ protected function configure() /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes(array $attributes = array()) { - return parent::render(array_merge(array( + return array_merge(parent::getAttributes(), array( 'type' => 'text', - ), $attributes)); + )); } } diff --git a/src/Symfony/Component/Form/PasswordField.php b/src/Symfony/Component/Form/PasswordField.php index 01817deabb834..83698c66d2077 100644 --- a/src/Symfony/Component/Form/PasswordField.php +++ b/src/Symfony/Component/Form/PasswordField.php @@ -31,11 +31,11 @@ protected function configure() /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - return parent::render(array_merge(array( + return array_merge(parent::getAttributes(), array( 'value' => $this->getOption('always_empty') && !$this->isBound() ? '' : $this->getDisplayedData(), 'type' => 'password', - ), $attributes)); + )); } } \ No newline at end of file diff --git a/src/Symfony/Component/Form/PercentField.php b/src/Symfony/Component/Form/PercentField.php index 88075f8132f3a..4d3467a568d69 100644 --- a/src/Symfony/Component/Form/PercentField.php +++ b/src/Symfony/Component/Form/PercentField.php @@ -36,12 +36,4 @@ protected function configure() 'type' => $this->getOption('type'), ))); } - - /** - * {@inheritDoc} - */ - public function render(array $attributes = array()) - { - return parent::render($attributes).' %'; - } } diff --git a/src/Symfony/Component/Form/RadioField.php b/src/Symfony/Component/Form/RadioField.php index 56c5617f8bde7..e2546a5c27c22 100644 --- a/src/Symfony/Component/Form/RadioField.php +++ b/src/Symfony/Component/Form/RadioField.php @@ -21,11 +21,11 @@ class RadioField extends ToggleField /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - return parent::render(array_merge(array( + return array_merge(parent::getAttributes(), array( 'type' => 'radio', 'name' => $this->getParent() ? $this->getParent()->getName() : $this->getName(), - ), $attributes)); + )); } } diff --git a/src/Symfony/Component/Form/Renderer/Renderer.php b/src/Symfony/Component/Form/Renderer/Renderer.php deleted file mode 100644 index 76705334f7fef..0000000000000 --- a/src/Symfony/Component/Form/Renderer/Renderer.php +++ /dev/null @@ -1,88 +0,0 @@ - 'all', '/another/file.css' => 'screen,print') - * - * @return array An array of stylesheet paths - */ - public function getStylesheets() - { - return array(); - } - - /** - * Gets the JavaScript paths associated with the renderer. - * - * @return array An array of JavaScript paths - */ - public function getJavaScripts() - { - return array(); - } - - /** - * {@inheritDoc} - */ - public function renderErrors(FieldInterface $field) - { - $html = ''; - - if ($field->hasErrors()) { - $html .= "
    \n"; - - foreach ($field->getErrors() as $error) { - $html .= "
  • " . $error . "
  • \n"; - } - - $html .= "
\n"; - } - - return $html; - } - - /** - * {@inheritDoc} - */ - public function setTranslator(TranslatorInterface $translator) - { - // TODO - } - - /** - * {@inheritDoc} - */ - public function setLocale($locale) - { - // TODO - } - - /** - * {@inheritDoc} - */ - public function setGenerator(HtmlGeneratorInterface $generator) - { - $this->generator = $generator; - } -} diff --git a/src/Symfony/Component/Form/Renderer/RendererInterface.php b/src/Symfony/Component/Form/Renderer/RendererInterface.php deleted file mode 100644 index e7186259c805e..0000000000000 --- a/src/Symfony/Component/Form/Renderer/RendererInterface.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -interface RendererInterface extends Localizable, Translatable -{ - /** - * Sets the generator used for rendering the HTML - * - * @param HtmlGeneratorInterface $generator - */ - public function setGenerator(HtmlGeneratorInterface $generator); - - /** - * Returns the textual representation of the given field. - * - * @param FieldInterface $field The form field - * @param array $attributes The attributes to include in the - * rendered output - * @return string The rendered output - * @throws InvalidArgumentException If the $field is not instance of the - * expected class - */ - public function render(FieldInterface $field, array $attributes = array()); - - /** - * Returns the textual representation of the errors of the given field. - * - * @param FieldInterface $field The form field - * @return string The rendered output - * @throws InvalidArgumentException If the $field is not instance of the - * expected class - */ - public function renderErrors(FieldInterface $field); -} \ No newline at end of file diff --git a/src/Symfony/Component/Form/Renderer/TableRenderer.php b/src/Symfony/Component/Form/Renderer/TableRenderer.php deleted file mode 100644 index 23adfe9235ea0..0000000000000 --- a/src/Symfony/Component/Form/Renderer/TableRenderer.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Renders a field group as HTML table - * - * @author Bernhard Schussek - */ -class TableRenderer extends Renderer -{ - /** - * {@inheritDoc} - */ - public function render(FieldInterface $group, array $attributes = array()) - { - $html = "\n"; - - foreach ($group as $field) { - $label = self::humanize($field->getKey()); - - $html .= "\n"; - $html .= "\n"; - $html .= ""; - $html .= "\n"; - } - - $html .= "
\n"; - if ($field->hasErrors()) { - $html .= $field->renderErrors()."\n"; - } - $html .= $field->render()."\n"; - $html .= "
\n"; - - return $html; - } - - protected static function humanize($text) - { - return ucfirst(strtolower(str_replace('_', ' ', $text))); - } -} diff --git a/src/Symfony/Component/Form/TextField.php b/src/Symfony/Component/Form/TextField.php index 973be1e24d16c..7f994124db8cd 100644 --- a/src/Symfony/Component/Form/TextField.php +++ b/src/Symfony/Component/Form/TextField.php @@ -31,11 +31,11 @@ protected function configure() /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - return parent::render(array_merge(array( + return array_merge(parent::getAttributes(), array( 'type' => 'text', 'maxlength' => $this->getOption('max_length'), - ), $attributes)); + )); } } diff --git a/src/Symfony/Component/Form/TextareaField.php b/src/Symfony/Component/Form/TextareaField.php index e553da54a9a9a..369b7cfc7de6d 100644 --- a/src/Symfony/Component/Form/TextareaField.php +++ b/src/Symfony/Component/Form/TextareaField.php @@ -21,15 +21,13 @@ class TextareaField extends Field /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - $content = $this->generator->escape($this->getDisplayedData()); - - return $this->generator->contentTag('textarea', $content, array_merge(array( + return array_merge(parent::getAttributes(), array( 'id' => $this->getId(), 'name' => $this->getName(), 'rows' => 4, 'cols' => 30, - ), $attributes)); + )); } } diff --git a/src/Symfony/Component/Form/TimeField.php b/src/Symfony/Component/Form/TimeField.php index 2a2bf56cdb06a..63bcae43fd564 100644 --- a/src/Symfony/Component/Form/TimeField.php +++ b/src/Symfony/Component/Form/TimeField.php @@ -107,25 +107,23 @@ protected function configure() $this->setValueTransformer(new ValueTransformerChain($transformers)); } + public function isField() + { + return self::INPUT === $this->getOption('widget'); + } + /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - if ($this->getOption('widget') == self::INPUT) { - $attributes = array_merge(array( + if ($this->isField()) { + return array_merge(parent::getAttributes(), array( 'size' => '1', - ), $attributes); - } - - $html = $this->get('hour')->render($attributes); - $html .= ':' . $this->get('minute')->render($attributes); - - if ($this->getOption('with_seconds')) { - $html .= ':' . $this->get('second')->render($attributes); + )); } - return $html; + return parent::getAttributes(); } /** diff --git a/src/Symfony/Component/Form/ToggleField.php b/src/Symfony/Component/Form/ToggleField.php index 4c7064bd96059..ff6e89d369f04 100644 --- a/src/Symfony/Component/Form/ToggleField.php +++ b/src/Symfony/Component/Form/ToggleField.php @@ -27,7 +27,6 @@ protected function configure() { $this->addOption('value'); $this->addOption('label'); - $this->addOption('translate_label', false); $this->setValueTransformer(new BooleanToStringTransformer()); } @@ -35,23 +34,11 @@ protected function configure() /** * {@inheritDoc} */ - public function render(array $attributes = array()) + public function getAttributes() { - $html = parent::render(array_merge(array( - 'value' => $this->getOption('value'), - 'checked' => ((string)$this->getDisplayedData() !== '' && $this->getDisplayedData() !== 0), - ), $attributes)); - - if ($label = $this->getOption('label')) { - if ($this->getOption('translate_label')) { - $label = $this->translate($label); - } - - $html .= ' '.$this->generator->contentTag('label', $label, array( - 'for' => $this->getId(), - )); - } - - return $html; + return array_merge(parent::getAttributes(), array( + 'value' => $this->getOption('value'), + 'checked' => (string) $this->getDisplayedData() !== '' && $this->getDisplayedData() !== 0, + )); } } diff --git a/src/Symfony/Component/Form/Translatable.php b/src/Symfony/Component/Form/Translatable.php deleted file mode 100644 index 275d801564362..0000000000000 --- a/src/Symfony/Component/Form/Translatable.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -interface Translatable -{ - /** - * Sets the translator unit of the class. - * - * @param TranslatorInterface $translator - */ - public function setTranslator(TranslatorInterface $translator); -} diff --git a/src/Symfony/Component/I18N/TranslatorInterface.php b/src/Symfony/Component/I18N/TranslatorInterface.php deleted file mode 100644 index d94954abc33ad..0000000000000 --- a/src/Symfony/Component/I18N/TranslatorInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -interface TranslatorInterface -{ - /** - * Translates a given text string. - * - * @param string $text The text to translate - * @param array $parameters The parameters to inject into the text - * @param string $locale The locale of the translated text. If null, - * the preconfigured locale of the translator - * or the system's default culture is used. - */ - public function translate($text, array $parameters = array(), $locale = null); -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/CheckboxFieldTest.php b/tests/Symfony/Tests/Component/Form/CheckboxFieldTest.php deleted file mode 100644 index 9147cff5ee181..0000000000000 --- a/tests/Symfony/Tests/Component/Form/CheckboxFieldTest.php +++ /dev/null @@ -1,20 +0,0 @@ -setData(true); - - $html = ''; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/ChoiceFieldTest.php b/tests/Symfony/Tests/Component/Form/ChoiceFieldTest.php index 1d5405107652c..00450df19c9ae 100644 --- a/tests/Symfony/Tests/Component/Form/ChoiceFieldTest.php +++ b/tests/Symfony/Tests/Component/Form/ChoiceFieldTest.php @@ -72,165 +72,6 @@ public function testBindSingleNonExpanded() $this->assertEquals('b', $field->getDisplayedData()); } - public function testRenderSingleNonExpanded() - { - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => false, - 'choices' => $this->choices, - )); - - $field->setData('b'); - - $html = << - - - - - - -EOF; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } - - public function testRenderSingleNonExpanded_translateChoices() - { - $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface'); - $translator->expects($this->any()) - ->method('translate') - ->will($this->returnCallback(function($text) { - return 'translated['.$text.']'; - })); - - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => false, - 'choices' => $this->choices, - 'translate_choices' => true, - )); - - $field->setTranslator($translator); - $field->setData('b'); - - $html = << - - - - - - -EOF; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } - - public function testRenderSingleNonExpanded_disabled() - { - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => false, - 'choices' => $this->choices, - 'disabled' => true, - )); - - - $html = << - - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderSingleNonExpandedWithPreferred() - { - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => false, - 'choices' => $this->choices, - 'preferred_choices' => $this->preferredChoices, - 'separator' => '---', - )); - - $field->setData('d'); - - $html = << - - - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderSingleNonExpandedWithGroups() - { - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => false, - 'choices' => $this->groupedChoices, - )); - - $html = << - - - - - - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderSingleNonExpandedNonRequired() - { - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => false, - 'choices' => $this->choices, - 'empty_value' => 'empty', - )); - - $field->setData(null); - $field->setRequired(false); - - $html = << - - - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - public function testBindMultipleNonExpanded() { $field = new ChoiceField('name', array( @@ -245,29 +86,6 @@ public function testBindMultipleNonExpanded() $this->assertEquals(array('a', 'b'), $field->getDisplayedData()); } - public function testRenderMultipleNonExpanded() - { - $field = new ChoiceField('name', array( - 'multiple' => true, - 'expanded' => false, - 'choices' => $this->choices, - )); - - $field->setData(array('a', 'b')); - - $html = << - - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - public function testBindSingleExpanded() { $field = new ChoiceField('name', array( @@ -316,80 +134,6 @@ public function testBindSingleExpandedNumericChoices() $this->assertSame(array(0 => '', 1 => '1', 2 => '', 3 => '', 4 => ''), $field->getDisplayedData()); } - public function testRenderSingleExpanded() - { - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => true, - 'choices' => $this->choices, - )); - - $field->setData('b'); - - $html = << - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderSingleExpanded_translateChoices() - { - $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface'); - $translator->expects($this->any()) - ->method('translate') - ->will($this->returnCallback(function($text) { - return 'translated['.$text.']'; - })); - - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => true, - 'choices' => $this->choices, - 'translate_choices' => true, - )); - - $field->setTranslator($translator); - $field->setData('b'); - - $html = << - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderSingleExpandedWithPreferred() - { - $field = new ChoiceField('name', array( - 'multiple' => false, - 'expanded' => true, - 'choices' => $this->choices, - 'preferred_choices' => $this->preferredChoices, - )); - - $html = << - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } - public function testBindMultipleExpanded() { $field = new ChoiceField('name', array( @@ -437,26 +181,4 @@ public function testBindMultipleExpandedNumericChoices() $this->assertSame('', $field[4]->getDisplayedData()); $this->assertSame(array(0 => '', 1 => '1', 2 => '1', 3 => '', 4 => ''), $field->getDisplayedData()); } - - public function testRenderMultipleExpanded() - { - $field = new ChoiceField('name', array( - 'multiple' => true, - 'expanded' => true, - 'choices' => $this->choices, - )); - - $field->setData(array('a', 'b')); - - $html = << - - - - - -EOF; - - $this->assertEquals($html, $field->render()); - } } \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/DateFieldTest.php b/tests/Symfony/Tests/Component/Form/DateFieldTest.php index c313e5c41f1e1..10c1cf221a339 100644 --- a/tests/Symfony/Tests/Component/Form/DateFieldTest.php +++ b/tests/Symfony/Tests/Component/Form/DateFieldTest.php @@ -99,119 +99,4 @@ public function testSetData_differentTimezones() $this->assertEquals('01.06.2010', $field->getDisplayedData()); } - - public function testRenderAsInput() - { - $field = new DateField('name', array('widget' => 'input')); - - $field->setLocale('de_AT'); - $field->setData(new \DateTime('2010-06-02 UTC')); - - $html = ''; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } - - public function testRenderAsInputWithFormat() - { - $field = new DateField('name', array('widget' => 'input', 'format' => 'short')); - - $field->setLocale('de_AT'); - $field->setData(new \DateTime('2010-06-02 UTC')); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderAsChoice() - { - $field = new DateField('name', array( - 'years' => array(2010, 2011), - 'months' => array(6, 7), - 'days' => array(1, 2), - 'widget' => DateField::CHOICE, - )); - - $field->setLocale('de_AT'); - $field->setData(new \DateTime('2010-06-02 UTC')); - - $html = << - - -.. -EOF; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } - - public function testRenderAsChoiceNonRequired() - { - $field = new DateField('name', array( - 'years' => array(2010, 2011), - 'months' => array(6, 7), - 'days' => array(1, 2), - 'widget' => DateField::CHOICE, - )); - - $field->setLocale('de_AT'); - $field->setRequired(false); - - $html = << - - - -.. -EOF; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderAsChoiceWithPattern() - { - $field = new DateField('name', array( - 'years' => array(2010, 2011), - 'months' => array(6, 7), - 'days' => array(1, 2), - 'widget' => DateField::CHOICE, - 'pattern' => '%day%---%month%---%year%', - )); - - $field->setLocale('de_AT'); - - $html = << - - ------- -EOF; - - $this->assertEquals($html, $field->render()); - } } \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/DateTimeFieldTest.php b/tests/Symfony/Tests/Component/Form/DateTimeFieldTest.php index 270dd0db9cef9..f25cd7fc924d5 100644 --- a/tests/Symfony/Tests/Component/Form/DateTimeFieldTest.php +++ b/tests/Symfony/Tests/Component/Form/DateTimeFieldTest.php @@ -151,50 +151,4 @@ public function testBind_differentTimezones() $this->assertEquals($dateTime->format('Y-m-d H:i:s'), $field->getData()); } - - public function testRender() - { - $field = new DateTimeField('name', array( - 'years' => array(2010, 2011), - 'months' => array(6, 7), - 'days' => array(1, 2), - 'hours' => array(3, 4), - 'minutes' => array(5, 6), - 'seconds' => array(7, 8), - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', - 'date_widget' => DateField::CHOICE, - 'time_widget' => TimeField::CHOICE, - 'type' => DateTimeField::DATETIME, - 'with_seconds' => true, - )); - - $field->setLocale('de_AT'); - $field->setData(new \DateTime('2010-06-02 03:04:05 UTC')); - - $html = << - - -.. -:: -EOF; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } } \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/FieldGroupTest.php b/tests/Symfony/Tests/Component/Form/FieldGroupTest.php index af0c3c4dc8659..79d2e4a723c32 100644 --- a/tests/Symfony/Tests/Component/Form/FieldGroupTest.php +++ b/tests/Symfony/Tests/Component/Form/FieldGroupTest.php @@ -153,7 +153,7 @@ public function testAddErrorMapsFieldValidationErrorsOntoFields() $group = new FieldGroup('author'); $group->add($field); - $group->addError('Message', new PropertyPath('fields[firstName].data'), FieldGroup::FIELD_ERROR); + $group->addError('Message', array(), new PropertyPath('fields[firstName].data'), FieldGroup::FIELD_ERROR); } public function testAddErrorMapsFieldValidationErrorsOntoFieldsWithinNestedFieldGroups() @@ -168,7 +168,7 @@ public function testAddErrorMapsFieldValidationErrorsOntoFieldsWithinNestedField $innerGroup->add($field); $group->add($innerGroup); - $group->addError('Message', new PropertyPath('fields[names].fields[firstName].data'), FieldGroup::FIELD_ERROR); + $group->addError('Message', array(), new PropertyPath('fields[names].fields[firstName].data'), FieldGroup::FIELD_ERROR); } public function testAddErrorKeepsFieldValidationErrorsIfFieldNotFound() @@ -180,9 +180,9 @@ public function testAddErrorKeepsFieldValidationErrorsIfFieldNotFound() $group = new FieldGroup('author'); $group->add($field); - $group->addError('Message', new PropertyPath('fields[bar].data'), FieldGroup::FIELD_ERROR); + $group->addError('Message', array(), new PropertyPath('fields[bar].data'), FieldGroup::FIELD_ERROR); - $this->assertEquals(array('Message'), $group->getErrors()); + $this->assertEquals(array(array('Message', array())), $group->getErrors()); } public function testAddErrorKeepsFieldValidationErrorsIfFieldIsHidden() @@ -197,9 +197,9 @@ public function testAddErrorKeepsFieldValidationErrorsIfFieldIsHidden() $group = new FieldGroup('author'); $group->add($field); - $group->addError('Message', new PropertyPath('fields[firstName].data'), FieldGroup::FIELD_ERROR); + $group->addError('Message', array(), new PropertyPath('fields[firstName].data'), FieldGroup::FIELD_ERROR); - $this->assertEquals(array('Message'), $group->getErrors()); + $this->assertEquals(array(array('Message', array())), $group->getErrors()); } public function testAddErrorMapsDataValidationErrorsOntoFields() @@ -213,12 +213,12 @@ public function testAddErrorMapsDataValidationErrorsOntoFields() ->will($this->returnValue(new PropertyPath('firstName'))); $field->expects($this->once()) ->method('addError') - ->with($this->equalTo('Message'), $this->equalTo($expectedPath), $this->equalTo(FieldGroup::DATA_ERROR)); + ->with($this->equalTo('Message'), array(), $this->equalTo($expectedPath), $this->equalTo(FieldGroup::DATA_ERROR)); $group = new FieldGroup('author'); $group->add($field); - $group->addError('Message', new PropertyPath('firstName'), FieldGroup::DATA_ERROR); + $group->addError('Message', array(), new PropertyPath('firstName'), FieldGroup::DATA_ERROR); } public function testAddErrorKeepsDataValidationErrorsIfFieldNotFound() @@ -233,7 +233,7 @@ public function testAddErrorKeepsDataValidationErrorsIfFieldNotFound() $group = new FieldGroup('author'); $group->add($field); - $group->addError('Message', new PropertyPath('bar'), FieldGroup::DATA_ERROR); + $group->addError('Message', array(), new PropertyPath('bar'), FieldGroup::DATA_ERROR); } public function testAddErrorKeepsDataValidationErrorsIfFieldIsHidden() @@ -251,7 +251,7 @@ public function testAddErrorKeepsDataValidationErrorsIfFieldIsHidden() $group = new FieldGroup('author'); $group->add($field); - $group->addError('Message', new PropertyPath('firstName'), FieldGroup::DATA_ERROR); + $group->addError('Message', array(), new PropertyPath('firstName'), FieldGroup::DATA_ERROR); } public function testAddErrorMapsDataValidationErrorsOntoNestedFields() @@ -266,12 +266,12 @@ public function testAddErrorMapsDataValidationErrorsOntoNestedFields() ->will($this->returnValue(new PropertyPath('address'))); $field->expects($this->once()) ->method('addError') - ->with($this->equalTo('Message'), $this->equalTo($expectedPath), $this->equalTo(FieldGroup::DATA_ERROR)); + ->with($this->equalTo('Message'), array(), $this->equalTo($expectedPath), $this->equalTo(FieldGroup::DATA_ERROR)); $group = new FieldGroup('author'); $group->add($field); - $group->addError('Message', new PropertyPath('address.street'), FieldGroup::DATA_ERROR); + $group->addError('Message', array(), new PropertyPath('address.street'), FieldGroup::DATA_ERROR); } public function testAddErrorMapsErrorsOntoFieldsInAnonymousGroups() @@ -285,14 +285,14 @@ public function testAddErrorMapsErrorsOntoFieldsInAnonymousGroups() ->will($this->returnValue(new PropertyPath('address'))); $field->expects($this->once()) ->method('addError') - ->with($this->equalTo('Message'), $this->equalTo($expectedPath), $this->equalTo(FieldGroup::DATA_ERROR)); + ->with($this->equalTo('Message'), array(), $this->equalTo($expectedPath), $this->equalTo(FieldGroup::DATA_ERROR)); $group = new FieldGroup('author'); $group2 = new FieldGroup('anonymous', array('property_path' => null)); $group2->add($field); $group->add($group2); - $group->addError('Message', new PropertyPath('address'), FieldGroup::DATA_ERROR); + $group->addError('Message', array(), new PropertyPath('address'), FieldGroup::DATA_ERROR); } public function testAddThrowsExceptionIfAlreadyBound() @@ -540,80 +540,6 @@ public function testIsNotMultipartIfNoFieldIsMultipart() $this->assertFalse($group->isMultipart()); } - public function testRenderForwardsToRenderer() - { - $group = new FieldGroup('author'); - - $renderer = $this->createMockRenderer(); - $renderer->expects($this->once()) - ->method('render') - ->with($this->equalTo($group), $this->equalTo(array('foo' => 'bar'))) - ->will($this->returnValue('HTML')); - - $group->setRenderer($renderer); - - // test - $output = $group->render(array('foo' => 'bar')); - - $this->assertEquals('HTML', $output); - } - - public function testRenderErrorsForwardsToRenderer() - { - $group = new FieldGroup('author'); - - $renderer = $this->createMockRenderer(); - $renderer->expects($this->once()) - ->method('renderErrors') - ->with($this->equalTo($group)) - ->will($this->returnValue('HTML')); - - $group->setRenderer($renderer); - - // test - $output = $group->renderErrors(); - - $this->assertEquals('HTML', $output); - } - - public function testLocaleIsPassedToRenderer() - { - $renderer = $this->getMock('Symfony\Component\Form\Renderer\RendererInterface'); - $renderer->expects($this->once()) - ->method('setLocale') - ->with($this->equalTo('de_DE')); - - $group = new FieldGroup('author'); - $group->setRenderer($renderer); - $group->setLocale('de_DE'); - $group->render(); - } - - public function testTranslatorIsPassedToRenderer() - { - $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface'); - $renderer = $this->getMock('Symfony\Component\Form\Renderer\RendererInterface'); - $renderer->expects($this->once()) - ->method('setTranslator') - ->with($this->equalTo($translator)); - - $group = new FieldGroup('author'); - $group->setRenderer($renderer); - $group->setTranslator($translator); - $group->render(); - } - - public function testTranslatorIsNotPassedToRendererIfNotSet() - { - $renderer = $this->getMock('Symfony\Component\Form\Renderer\RendererInterface'); - $renderer->expects($this->never()) - ->method('setTranslator'); - - $group = new FieldGroup('author'); - $group->setRenderer($renderer); - $group->render(); - } - public function testLocaleIsPassedToField_SetBeforeAddingTheField() { $field = $this->getMock('Symfony\Component\Form\Field', array(), array(), '', false, false); @@ -651,51 +577,6 @@ public function testLocaleIsPassedToField_SetAfterAddingTheField() $this->assertEquals(array(class_exists('\Locale', false) ? \Locale::getDefault() : 'en', 'de_DE'), $field->locales); } - public function testTranslatorIsPassedToField_SetBeforeAddingTheField() - { - $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface'); - $field = $this->getMock('Symfony\Component\Form\Field', array(), array(), '', false, false); - $field->expects($this->any()) - ->method('getKey') - ->will($this->returnValue('firstName')); - $field->expects($this->once()) - ->method('setTranslator') - ->with($this->equalTo($translator)); - - $group = new FieldGroup('author'); - $group->setTranslator($translator); - $group->add($field); - } - - public function testTranslatorIsPassedToField_SetAfterAddingTheField() - { - $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface'); - $field = $this->getMock('Symfony\Component\Form\Field', array(), array(), '', false, false); - $field->expects($this->any()) - ->method('getKey') - ->will($this->returnValue('firstName')); - $field->expects($this->once()) - ->method('setTranslator') - ->with($this->equalTo($translator)); - - $group = new FieldGroup('author'); - $group->add($field); - $group->setTranslator($translator); - } - - public function testTranslatorIsNotPassedToFieldIfNotSet() - { - $field = $this->getMock('Symfony\Component\Form\Field', array(), array(), '', false, false); - $field->expects($this->any()) - ->method('getKey') - ->will($this->returnValue('firstName')); - $field->expects($this->never()) - ->method('setTranslator'); - - $group = new FieldGroup('author'); - $group->add($field); - } - public function testSupportsClone() { $group = new FieldGroup('author'); @@ -722,33 +603,6 @@ public function testBindWithoutPriorSetData() $this->assertEquals(array('firstName' => 'Bernhard'), $group->getData()); } - public function testSetGenerator_calledBeforeAdding() - { - $generator = $this->getMock('Symfony\Component\Form\HtmlGeneratorInterface'); - - $field = $this->createMockField('firstName'); - $field->expects($this->once()) - ->method('setGenerator') - ->with($this->equalTo($generator)); - - $group = new FieldGroup('author'); - $group->setGenerator($generator); - $group->add($field); - } - - public function testSetGenerator_calledAfterAdding() - { - $generator = $this->getMock('Symfony\Component\Form\HtmlGeneratorInterface'); - - $field = $this->createMockField('firstName'); - $field->expects($this->exactly(2)) // cannot test different arguments :( - ->method('setGenerator'); - - $group = new FieldGroup('author'); - $group->add($field); - $group->setGenerator($generator); - } - protected function createMockField($key) { $field = $this->getMock( @@ -807,11 +661,6 @@ protected function createMultipartMockField($key) return $field; } - protected function createMockRenderer() - { - return $this->getMock('Symfony\Component\Form\Renderer\RendererInterface'); - } - protected function createMockTransformer() { return $this->getMock('Symfony\Component\Form\ValueTransformer\ValueTransformerInterface', array(), array(), '', false, false); diff --git a/tests/Symfony/Tests/Component/Form/FormTest.php b/tests/Symfony/Tests/Component/Form/FormTest.php index f5829c8fd7acc..31831e3ef2d75 100644 --- a/tests/Symfony/Tests/Component/Form/FormTest.php +++ b/tests/Symfony/Tests/Component/Form/FormTest.php @@ -9,7 +9,6 @@ use Symfony\Component\Form\Field; use Symfony\Component\Form\HiddenField; use Symfony\Component\Form\FieldGroup; -use Symfony\Component\Form\HtmlGenerator; use Symfony\Component\Form\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; @@ -175,23 +174,6 @@ public function testDefaultLocaleCanBeSet() $form->add($field); } - public function testDefaultTranslatorCanBeSet() - { - $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface'); - Form::setDefaultTranslator($translator); - $form = new Form('author', new Author(), $this->validator); - - $field = $this->getMock('Symfony\Component\Form\Field', array(), array(), '', false, false); - $field->expects($this->any()) - ->method('getKey') - ->will($this->returnValue('firstName')); - $field->expects($this->once()) - ->method('setTranslator') - ->with($this->equalTo($translator)); - - $form->add($field); - } - public function testValidationGroupsCanBeSet() { $form = new Form('author', new Author(), $this->validator); @@ -241,30 +223,6 @@ public function testMultipartFormsWithParentsRequireNoFiles() $form->bind(array('file' => 'test.txt')); } - public function testRenderFormTagProducesValidXhtml() - { - $form = new Form('author', new Author(), $this->validator); - - $this->assertEquals('
', $form->renderFormTag('url')); - } - - public function testSetCharsetAdjustsGenerator() - { - $form = $this->getMock( - 'Symfony\Component\Form\Form', - array('setGenerator'), - array(), - '', - false // don't call original constructor - ); - - $form->expects($this->once()) - ->method('setGenerator') - ->with($this->equalTo(new HtmlGenerator('iso-8859-1'))); - - $form->setCharset('iso-8859-1'); - } - protected function createMockField($key) { $field = $this->getMock( diff --git a/tests/Symfony/Tests/Component/Form/HiddenFieldTest.php b/tests/Symfony/Tests/Component/Form/HiddenFieldTest.php index 2b5ba1a297947..de8ec74aaeee7 100644 --- a/tests/Symfony/Tests/Component/Form/HiddenFieldTest.php +++ b/tests/Symfony/Tests/Component/Form/HiddenFieldTest.php @@ -13,17 +13,6 @@ public function setUp() $this->field = new HiddenField('name'); } - public function testRender() - { - $this->field->setData('foobar'); - - $html = ''; - - $this->assertEquals($html, $this->field->render(array( - 'class' => 'foobar', - ))); - } - public function testIsHidden() { $this->assertTrue($this->field->isHidden()); diff --git a/tests/Symfony/Tests/Component/Form/HtmlGeneratorTest.php b/tests/Symfony/Tests/Component/Form/HtmlGeneratorTest.php deleted file mode 100644 index 087a76c374bdb..0000000000000 --- a/tests/Symfony/Tests/Component/Form/HtmlGeneratorTest.php +++ /dev/null @@ -1,91 +0,0 @@ -generator = new HtmlGenerator(); - } - - public function testEscape() - { - $this->assertEquals('<&abcd', $this->generator->escape('<&abcd')); - } - - public function testEscapeOnlyOnce() - { - $this->assertEquals('<&abcd', $this->generator->escape('<&abcd')); - } - - public function testAttribute() - { - $this->assertEquals('foo="bar"', $this->generator->attribute('foo', 'bar')); - } - - public function testEscapeAttribute() - { - $this->assertEquals('foo="<>"', $this->generator->attribute('foo', '<>')); - } - - public function testXhtmlAttribute() - { - HtmlGenerator::setXhtml(true); - $this->assertEquals('foo="foo"', $this->generator->attribute('foo', true)); - } - - public function testNonXhtmlAttribute() - { - HtmlGenerator::setXhtml(false); - $this->assertEquals('foo', $this->generator->attribute('foo', true)); - } - - public function testAttributes() - { - $html = $this->generator->attributes(array( - 'foo' => 'bar', - 'bar' => 'baz', - )); - $this->assertEquals(' foo="bar" bar="baz"', $html); - } - - public function testXhtmlTag() - { - HtmlGenerator::setXhtml(true); - $html = $this->generator->tag('input', array( - 'type' => 'text', - )); - $this->assertEquals('', $html); - } - - public function testNonXhtmlTag() - { - HtmlGenerator::setXhtml(false); - $html = $this->generator->tag('input', array( - 'type' => 'text', - )); - $this->assertEquals('', $html); - } - - public function testContentTag() - { - $html = $this->generator->contentTag('p', 'asdf', array( - 'class' => 'foo', - )); - $this->assertEquals('

asdf

', $html); - } - - // it should be possible to pass the output of the tag() method as body - // of the content tag - public function testDontEscapeContentTag() - { - $this->assertEquals('

<&

', $this->generator->contentTag('p', '<&')); - } - -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/InputFieldTest.php b/tests/Symfony/Tests/Component/Form/InputFieldTest.php deleted file mode 100644 index 79a27497586e0..0000000000000 --- a/tests/Symfony/Tests/Component/Form/InputFieldTest.php +++ /dev/null @@ -1,33 +0,0 @@ -setData('foobar'); - - $html = ''; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } - - public function testRender_disabled() - { - $field = new TestInputField('name', array('disabled' => true)); - $field->setData('foobar'); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/MoneyFieldTest.php b/tests/Symfony/Tests/Component/Form/MoneyFieldTest.php deleted file mode 100644 index 1208f65bff29e..0000000000000 --- a/tests/Symfony/Tests/Component/Form/MoneyFieldTest.php +++ /dev/null @@ -1,46 +0,0 @@ -setLocale('de_AT'); - $field->setData(1234); - - $html = ''; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } - - public function testRenderWithCurrency_afterWidget() - { - $field = new MoneyField('name', array('currency' => 'EUR')); - - $field->setLocale('de_DE'); - $field->setData(1234); - - $html = ' €'; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderWithCurrency_beforeWidget() - { - $field = new MoneyField('name', array('currency' => 'EUR')); - - $field->setLocale('en_US'); - $field->setData(1234); - - $html = '€ '; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/NumberFieldTest.php b/tests/Symfony/Tests/Component/Form/NumberFieldTest.php deleted file mode 100644 index d9986c3b93a1c..0000000000000 --- a/tests/Symfony/Tests/Component/Form/NumberFieldTest.php +++ /dev/null @@ -1,46 +0,0 @@ -setLocale('de_AT'); - $field->setData(1234.5678); - - $html = ''; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } - - public function testRenderWithPrecision() - { - $field = new NumberField('name', array('precision' => 4)); - - $field->setLocale('de_AT'); - $field->setData(1234.5678); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderWithGrouping() - { - $field = new NumberField('name', array('grouping' => true)); - - $field->setLocale('de_AT'); - $field->setData(1234.5678); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/PasswordFieldTest.php b/tests/Symfony/Tests/Component/Form/PasswordFieldTest.php deleted file mode 100644 index fd4099b5ea12a..0000000000000 --- a/tests/Symfony/Tests/Component/Form/PasswordFieldTest.php +++ /dev/null @@ -1,49 +0,0 @@ -setData('asdf'); - - $html = ''; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } - - // when the user made an error in the form, display the value in the field - public function testRenderAfterBinding() - { - $field = new PasswordField('name'); - $field->bind('asdf'); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderNotAlwaysEmpty() - { - $field = new PasswordField('name', array('always_empty' => false)); - $field->setData('asdf'); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderNotAlwaysEmptyAfterBinding() - { - $field = new PasswordField('name', array('always_empty' => false)); - $field->bind('asdf'); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/PercentFieldTest.php b/tests/Symfony/Tests/Component/Form/PercentFieldTest.php deleted file mode 100644 index b7303760b808a..0000000000000 --- a/tests/Symfony/Tests/Component/Form/PercentFieldTest.php +++ /dev/null @@ -1,46 +0,0 @@ -setLocale('de_DE'); - $field->setData(0.12); - - $html = ' %'; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderWithPrecision() - { - $field = new PercentField('name', array('precision' => 2)); - - $field->setLocale('de_DE'); - $field->setData(0.1234); - - $html = ' %'; - - $this->assertEquals($html, $field->render()); - } - - public function testRenderWithInteger() - { - $field = new PercentField('name', array('type' => 'integer')); - - $field->setLocale('de_DE'); - $field->setData(123); - - $html = ' %'; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/RadioFieldTest.php b/tests/Symfony/Tests/Component/Form/RadioFieldTest.php deleted file mode 100644 index 69674c92b1fa7..0000000000000 --- a/tests/Symfony/Tests/Component/Form/RadioFieldTest.php +++ /dev/null @@ -1,33 +0,0 @@ -setData(true); - - $html = ''; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } - - // when a radio button is in a field group, all radio buttons in that group - // should have the same name - public function testRenderParentName() - { - $field = new RadioField('name'); - $field->setParent(new FieldGroup('parent')); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/Renderer/RendererTestCase.php b/tests/Symfony/Tests/Component/Form/Renderer/RendererTestCase.php deleted file mode 100644 index 0d68b7cd47d36..0000000000000 --- a/tests/Symfony/Tests/Component/Form/Renderer/RendererTestCase.php +++ /dev/null @@ -1,23 +0,0 @@ -getMock('Symfony\Component\Form\FieldInterface'); - - $field->expects($this->any()) - ->method('getDisplayedData') - ->will($this->returnValue($displayedData)); - $field->expects($this->any()) - ->method('getName') - ->will($this->returnValue($name)); - $field->expects($this->any()) - ->method('getId') - ->will($this->returnValue($id)); - - return $field; - } -} diff --git a/tests/Symfony/Tests/Component/Form/TextFieldTest.php b/tests/Symfony/Tests/Component/Form/TextFieldTest.php deleted file mode 100644 index 2f7a00c13eeab..0000000000000 --- a/tests/Symfony/Tests/Component/Form/TextFieldTest.php +++ /dev/null @@ -1,28 +0,0 @@ -setData('asdf'); - - $html = ''; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } - - public function testRenderWithMaxLength() - { - $field = new TextField('name', array('max_length' => 10)); - $field->setData('asdf'); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/TextareaFieldTest.php b/tests/Symfony/Tests/Component/Form/TextareaFieldTest.php deleted file mode 100644 index 15d822537d651..0000000000000 --- a/tests/Symfony/Tests/Component/Form/TextareaFieldTest.php +++ /dev/null @@ -1,28 +0,0 @@ -setData('asdf'); - - $html = ''; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } - - public function testRenderEscapesValue() - { - $field = new TextareaField('name'); - $field->setData('<&&'); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/TimeFieldTest.php b/tests/Symfony/Tests/Component/Form/TimeFieldTest.php index c4a3d82476d05..00aaa29663638 100644 --- a/tests/Symfony/Tests/Component/Form/TimeFieldTest.php +++ b/tests/Symfony/Tests/Component/Form/TimeFieldTest.php @@ -133,128 +133,4 @@ public function testSetData_differentTimezones() $this->assertEquals($displayedData, $field->getDisplayedData()); } - - public function testRenderAsInputs() - { - $field = new TimeField('name', array( - 'widget' => TimeField::INPUT, - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', - )); - - $field->setData(new \DateTime('04:05 UTC')); - - $html = << -: - -EOF; - - $this->assertEquals(str_replace("\n", '', $html), $field->render(array('class' => 'foobar'))); - } - - public function testRenderAsInputs_withSeconds() - { - $field = new TimeField('name', array( - 'widget' => TimeField::INPUT, - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', - 'with_seconds' => true, - )); - - $field->setData(new \DateTime('04:05:06 UTC')); - - $html = << -: - -: - -EOF; - - $this->assertEquals(str_replace("\n", '', $html), $field->render(array('class' => 'foobar'))); - } - - public function testRenderAsChoices() - { - $field = new TimeField('name', array( - 'hours' => array(3, 4), - 'minutes' => array(5, 6), - 'widget' => TimeField::CHOICE, - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', - )); - - $field->setData(new \DateTime('04:05 UTC')); - - $html = << - - -: -EOF; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } - - public function testRenderAsChoices_withSeconds() - { - $field = new TimeField('name', array( - 'hours' => array(3, 4), - 'minutes' => array(5, 6), - 'seconds' => array(7, 8), - 'widget' => TimeField::CHOICE, - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', - 'with_seconds' => true, - )); - - $field->setData(new \DateTime('04:05:07 UTC')); - - $html = << - - -:: -EOF; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } - - public function testRenderAsChoices_nonRequired() - { - $field = new TimeField('name', array( - 'hours' => array(3, 4), - 'minutes' => array(5, 6), - 'widget' => TimeField::CHOICE, - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', - )); - - $field->setRequired(false); - $field->setData(new \DateTime('04:05 UTC')); - - $html = << - - - -: -EOF; - - $this->assertEquals($html, $field->render(array('class' => 'foobar'))); - } } \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Form/ToggleFieldTest.php b/tests/Symfony/Tests/Component/Form/ToggleFieldTest.php deleted file mode 100644 index 7d8ef8f266ced..0000000000000 --- a/tests/Symfony/Tests/Component/Form/ToggleFieldTest.php +++ /dev/null @@ -1,67 +0,0 @@ -setData(true); - - $html = ''; - - $this->assertEquals($html, $field->render(array( - 'class' => 'foobar', - ))); - } - - public function testRender_deselected() - { - $field = new TestToggleField('name'); - $field->setData(false); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } - - public function testRender_withValue() - { - $field = new TestToggleField('name', array('value' => 'foobar')); - - $html = ''; - - $this->assertEquals($html, $field->render()); - } - - public function testRender_withLabel() - { - $field = new TestToggleField('name', array('label' => 'foobar')); - - $html = ' '; - - $this->assertEquals($html, $field->render()); - } - - public function testRender_withTranslatedLabel() - { - $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface'); - $translator->expects($this->any()) - ->method('translate') - ->will($this->returnCallback(function($text) { - return 'translated['.$text.']'; - })); - - $field = new TestToggleField('name', array('label' => 'foobar', 'translate_label' => true)); - $field->setTranslator($translator); - - $html = ' '; - - $this->assertEquals($html, $field->render()); - } -} \ No newline at end of file From ff683a694e37ecf779e1a16b5058666d6443ce85 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Wage" Date: Mon, 4 Oct 2010 22:23:45 -0500 Subject: [PATCH 06/10] Integrating new data fixtures code. --- autoload.php.dist | 17 ++- install_vendors.sh | 3 + .../LoadDataFixturesDoctrineCommand.php | 142 ++---------------- .../DoctrineBundle/Resources/config/dbal.xml | 9 +- .../DoctrineBundle/Resources/config/orm.xml | 9 +- .../DoctrineBundle/Tests/ContainerTest.php | 62 ++++++++ .../CreateSchemaDoctrineODMCommand.php | 8 +- .../Command/DropSchemaDoctrineODMCommand.php | 8 +- .../LoadDataFixturesDoctrineODMCommand.php | 91 +++++++++++ .../Resources/config/mongodb.xml | 3 +- .../Tests/ContainerTest.php | 58 +++++++ update_vendors.sh | 3 + 12 files changed, 257 insertions(+), 156 deletions(-) create mode 100644 src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php create mode 100644 src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php create mode 100644 src/Symfony/Bundle/DoctrineMongoDBBundle/Tests/ContainerTest.php diff --git a/autoload.php.dist b/autoload.php.dist index 81ee7573a143a..902a1735ba33b 100644 --- a/autoload.php.dist +++ b/autoload.php.dist @@ -6,13 +6,14 @@ use Symfony\Component\HttpFoundation\UniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespaces(array( - 'Symfony' => __DIR__.'/src', - 'Doctrine\\ODM\\MongoDB' => __DIR__.'/vendor/doctrine-mongodb/lib', - 'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib', - 'Doctrine\\DBAL\\Migrations' => __DIR__.'/vendor/doctrine-migrations/lib', - 'Doctrine\\DBAL' => __DIR__.'/vendor/doctrine-dbal/lib', - 'Doctrine' => __DIR__.'/vendor/doctrine/lib', - 'Zend' => __DIR__.'/vendor/zend/library', + 'Symfony' => __DIR__.'/src', + 'Doctrine\\ODM\\MongoDB' => __DIR__.'/vendor/doctrine-mongodb/lib', + 'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib', + 'Doctrine\\DBAL\\Migrations' => __DIR__.'/vendor/doctrine-migrations/lib', + 'Doctrine\\DBAL' => __DIR__.'/vendor/doctrine-dbal/lib', + 'Doctrine\\ORM\\DataFixtures' => __DIR__.'/vendor/doctrine-orm-data-fixtures', + 'Doctrine' => __DIR__.'/vendor/doctrine/lib', + 'Zend' => __DIR__.'/vendor/zend/library', )); $loader->registerPrefixes(array( 'Swift_' => __DIR__.'/vendor/swiftmailer/lib/classes', @@ -26,4 +27,4 @@ set_include_path( __DIR__.'/vendor/phing/classes'.PATH_SEPARATOR. __DIR__.'/vendor/propel/runtime/lib'.PATH_SEPARATOR. get_include_path() -); +); \ No newline at end of file diff --git a/install_vendors.sh b/install_vendors.sh index f61a8d0170e1f..d0a6f1ceb1fd7 100755 --- a/install_vendors.sh +++ b/install_vendors.sh @@ -12,6 +12,9 @@ cd vendor # Doctrine ORM git clone git://github.com/doctrine/doctrine2.git doctrine +# Doctrine ORM Data Fixtures Extension +git clone git://github.com/doctrine/orm-data-fixtures doctrine-orm-data-fixtures + # Doctrine DBAL git clone git://github.com/doctrine/dbal.git doctrine-dbal diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php index 532ab90b21652..c07dac0045165 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php +++ b/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php @@ -39,6 +39,7 @@ protected function configure() ->setDescription('Load data fixtures to your database.') ->addOption('fixtures', null, InputOption::PARAMETER_OPTIONAL | InputOption::PARAMETER_IS_ARRAY, 'The directory or file to load data fixtures from.') ->addOption('append', null, InputOption::PARAMETER_OPTIONAL, 'Whether or not to append the data fixtures.', false) + ->addOption('em', null, InputOption::PARAMETER_REQUIRED, 'The entity manager to use for this command.') ->setHelp(<<doctrine:data:load command loads data fixtures from your bundles: @@ -57,7 +58,10 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { - $defaultEm = $this->container->getDoctrine_ORM_EntityManagerService(); + $emName = $input->getOption('em'); + $emName = $emName ? $emName : 'default'; + $emServiceName = sprintf('doctrine.orm.%s_entity_manager', $emName); + $em = $this->container->get($emServiceName); $dirOrFile = $input->getOption('fixtures'); if ($dirOrFile) { $paths = is_array($dirOrFile) ? $dirOrFile : array($dirOrFile); @@ -69,139 +73,19 @@ protected function execute(InputInterface $input, OutputInterface $output) $namespace = str_replace('/', '\\', dirname($tmp)); $class = basename($tmp); - if (isset($bundleDirs[$namespace]) && is_dir($dir = $bundleDirs[$namespace].'/'.$class.'/Resources/data/fixtures/doctrine/orm')) { + if (isset($bundleDirs[$namespace]) && is_dir($dir = $bundleDirs[$namespace].'/'.$class.'/DataFixtures/ORM')) { $paths[] = $dir; } } } - $files = array(); + $loader = new \Doctrine\Common\DataFixtures\Loader(); foreach ($paths as $path) { - if (is_dir($path)) { - $finder = new Finder(); - $found = iterator_to_array($finder - ->files() - ->name('*.php') - ->in($path)); - } else { - $found = array($path); - } - $files = array_merge($files, $found); - } - - $ems = array(); - $emEntities = array(); - $files = array_unique($files); - foreach ($files as $file) { - $em = $defaultEm; - $output->writeln(sprintf('Loading data fixtures from "%s"', $file)); - - $before = array_keys(get_defined_vars()); - include($file); - $after = array_keys(get_defined_vars()); - $new = array_diff($after, $before); - $params = $em->getConnection()->getParams(); - $emName = isset($params['path']) ? $params['path']:$params['dbname']; - - $ems[$emName] = $em; - $emEntities[$emName] = array(); - $variables = array_values($new); - - foreach ($variables as $variable) { - $value = $$variable; - if (!is_object($value) || $value instanceof \Doctrine\ORM\EntityManager) { - continue; - } - $emEntities[$emName][] = $value; - } - foreach ($ems as $emName => $em) { - if (!$input->getOption('append')) { - $output->writeln(sprintf('Purging data from entity manager named "%s"', $emName)); - $this->purgeEntityManager($em); - } - - $entities = $emEntities[$emName]; - $numEntities = count($entities); - $output->writeln(sprintf('Persisting "%s" '.($numEntities > 1 ? 'entities' : 'entity').'', count($entities))); - - foreach ($entities as $entity) { - $em->persist($entity); - } - $output->writeln('Flushing entity manager'); - $em->flush(); - } - } - } - - protected function purgeEntityManager(EntityManager $em) - { - $classes = array(); - $metadatas = $em->getMetadataFactory()->getAllMetadata(); - - foreach ($metadatas as $metadata) { - if (!$metadata->isMappedSuperclass) { - $classes[] = $metadata; - } + $loader->loadFromDirectory($path); } - - $commitOrder = $this->getCommitOrder($em, $classes); - - // Drop association tables first - $orderedTables = $this->getAssociationTables($commitOrder); - - // Drop tables in reverse commit order - for ($i = count($commitOrder) - 1; $i >= 0; --$i) { - $class = $commitOrder[$i]; - - if (($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName) - || $class->isMappedSuperclass) { - continue; - } - - $orderedTables[] = $class->getTableName(); - } - - foreach($orderedTables as $tbl) { - $em->getConnection()->executeUpdate("DELETE FROM $tbl"); - } - } - - protected function getCommitOrder(EntityManager $em, array $classes) - { - $calc = new CommitOrderCalculator; - - foreach ($classes as $class) { - $calc->addClass($class); - - foreach ($class->associationMappings as $assoc) { - if ($assoc['isOwningSide']) { - $targetClass = $em->getClassMetadata($assoc['targetEntity']); - - if ( ! $calc->hasClass($targetClass->name)) { - $calc->addClass($targetClass); - } - - // add dependency ($targetClass before $class) - $calc->addDependency($targetClass, $class); - } - } - } - - return $calc->getCommitOrder(); - } - - protected function getAssociationTables(array $classes) - { - $associationTables = array(); - - foreach ($classes as $class) { - foreach ($class->associationMappings as $assoc) { - if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) { - $associationTables[] = $assoc['joinTable']['name']; - } - } - } - - return $associationTables; + $fixtures = $loader->getFixtures(); + $purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger($em); + $executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($em, $purger); + $executor->execute($fixtures, $input->getOption('append')); } -} +} \ No newline at end of file diff --git a/src/Symfony/Bundle/DoctrineBundle/Resources/config/dbal.xml b/src/Symfony/Bundle/DoctrineBundle/Resources/config/dbal.xml index fd7cbe7ba0bfe..33479e3f07e3e 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Resources/config/dbal.xml +++ b/src/Symfony/Bundle/DoctrineBundle/Resources/config/dbal.xml @@ -7,15 +7,16 @@ default Doctrine\DBAL\Connection - + Doctrine\DBAL\Logging\DebugStack + Symfony\Bundle\DoctrineBundle\Logger\DbalLogger Symfony\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector default - + - + @@ -24,4 +25,4 @@ - + \ No newline at end of file diff --git a/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml b/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml index e4e43730dbc4a..2a01ae14d0f60 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml +++ b/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml @@ -42,13 +42,12 @@ - + %doctrine.orm.metadata_driver.entity_dirs% - - %doctrine.orm.metadata.annotation_default_namespace% + Doctrine\ORM\Mapping\ orm @@ -56,12 +55,12 @@ - + %doctrine.orm.metadata_driver.mapping_dirs% - + %doctrine.orm.metadata_driver.mapping_dirs% diff --git a/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php new file mode 100644 index 0000000000000..5276ee797781a --- /dev/null +++ b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DoctrineBundle\Tests; + +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +class ContainerTest extends TestCase +{ + public function getContainer() + { + $container = new ContainerBuilder(new ParameterBag(array( + 'kernel.bundle_dirs' => array(), + 'kernel.bundles' => array(), + 'kernel.cache_dir' => sys_get_temp_dir(), + ))); + $loader = new DoctrineExtension(); + $container->registerExtension($loader); + $loader->dbalLoad(array(), $container); + $loader->ormLoad(array(), $container); + + $dumper = new PhpDumper($container); + $code = $dumper->dump(); + eval(str_replace('getContainer(); + $this->assertInstanceOf('Doctrine\DBAL\Logging\DebugStack', $container->get('doctrine.dbal.logger.debug')); + $this->assertInstanceOf('Doctrine\DBAL\Logging\DebugStack', $container->get('doctrine.dbal.logger')); + $this->assertInstanceOf('Symfony\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector', $container->get('doctrine.data_collector')); + $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\ORM\Mapping\Driver\AnnotationDriver', $container->get('doctrine.orm.metadata_driver.annotation')); + $this->assertInstanceOf('Doctrine\Common\Annotations\AnnotationReader', $container->get('doctrine.orm.metadata_driver.annotation.reader')); + $this->assertInstanceOf('Doctrine\ORM\Mapping\Driver\XmlDriver', $container->get('doctrine.orm.metadata_driver.xml')); + $this->assertInstanceOf('Doctrine\ORM\Mapping\Driver\YamlDriver', $container->get('doctrine.orm.metadata_driver.yml')); + $this->assertInstanceOf('Doctrine\ORM\Configuration', $container->get('doctrine.orm.default_configuration')); + $this->assertInstanceOf('Doctrine\ORM\Mapping\Driver\DriverChain', $container->get('doctrine.orm.metadata_driver')); + $this->assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.orm.default_metadata_cache')); + $this->assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.orm.default_query_cache')); + $this->assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.orm.default_result_cache')); + $this->assertInstanceOf('Doctrine\ORM\EntityManager', $container->get('doctrine.orm.default_entity_manager')); + $this->assertInstanceOf('Doctrine\DBAL\Connection', $container->get('database_connection')); + $this->assertInstanceOf('Doctrine\ORM\EntityManager', $container->get('doctrine.orm.entity_manager')); + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/CreateSchemaDoctrineODMCommand.php b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/CreateSchemaDoctrineODMCommand.php index 52cd8d91b0278..25e87e2428879 100644 --- a/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/CreateSchemaDoctrineODMCommand.php +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/CreateSchemaDoctrineODMCommand.php @@ -21,16 +21,16 @@ protected function configure() parent::configure(); $this - ->setName('doctrine:odm:schema:create') + ->setName('doctrine:mongodb:schema:create') ->addOption('dm', null, InputOption::PARAMETER_REQUIRED, 'The document manager to use for this command.') ->setHelp(<<doctrine:odm:schema:create command creates the default document manager's schema: +The doctrine:mongodb:schema:create command creates the default document manager's schema: - ./symfony doctrine:odm:schema:create + ./symfony doctrine:mongodb:schema:create You can also optionally specify the name of a document manager to create the schema for: - ./symfony doctrine:odm:schema:create --dm=default + ./symfony doctrine:mongodb:schema:create --dm=default EOT ); } diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/DropSchemaDoctrineODMCommand.php b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/DropSchemaDoctrineODMCommand.php index 37f7005b67fc1..3c49e0f8af9ac 100644 --- a/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/DropSchemaDoctrineODMCommand.php +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/DropSchemaDoctrineODMCommand.php @@ -21,16 +21,16 @@ protected function configure() parent::configure(); $this - ->setName('doctrine:odm:schema:drop') + ->setName('doctrine:mongodb:schema:drop') ->addOption('dm', null, InputOption::PARAMETER_REQUIRED, 'The document manager to use for this command.') ->setHelp(<<doctrine:odm:schema:drop command drops the default document manager's schema: +The doctrine:mongodb:schema:drop command drops the default document manager's schema: - ./symfony doctrine:odm:schema:drop + ./symfony doctrine:mongodb:schema:drop You can also optionally specify the name of a document manager to drop the schema for: - ./symfony doctrine:odm:schema:drop --dm=default + ./symfony doctrine:mongodb:schema:drop --dm=default EOT ); } diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php new file mode 100644 index 0000000000000..abafc25f8e2e1 --- /dev/null +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php @@ -0,0 +1,91 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Load data fixtures from bundles. + * + * @author Fabien Potencier + * @author Jonathan H. Wage + */ +class LoadDataFixturesDoctrineODMCommand extends DoctrineODMCommand +{ + protected function configure() + { + $this + ->setName('doctrine:mongodb:data:load') + ->setDescription('Load data fixtures to your database.') + ->addOption('fixtures', null, InputOption::PARAMETER_OPTIONAL | InputOption::PARAMETER_IS_ARRAY, 'The directory or file to load data fixtures from.') + ->addOption('append', null, InputOption::PARAMETER_OPTIONAL, 'Whether or not to append the data fixtures.', false) + ->addOption('dm', null, InputOption::PARAMETER_REQUIRED, 'The document manager to use for this command.') + ->setHelp(<<doctrine:mongodb:data:load command loads data fixtures from your bundles: + + ./symfony doctrine:mongodb:data:load + +You can also optionally specify the path to fixtures with the --fixtures option: + + ./symfony doctrine:mongodb:data:load --fixtures=/path/to/fixtures1 --fixtures=/path/to/fixtures2 + +If you want to append the fixtures instead of flushing the database first you can use the --append option: + + ./symfony doctrine:mongodb:data:load --append +EOT + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $dmName = $input->getOption('dm'); + $dmName = $dmName ? $dmName : 'default'; + $dmServiceName = sprintf('doctrine.odm.mongodb.%s_document_manager', $dmName); + $dm = $this->container->get($dmServiceName); + $dirOrFile = $input->getOption('fixtures'); + if ($dirOrFile) { + $paths = is_array($dirOrFile) ? $dirOrFile : array($dirOrFile); + } else { + $paths = array(); + $bundleDirs = $this->container->getKernelService()->getBundleDirs(); + foreach ($this->container->getKernelService()->getBundles() as $bundle) { + $tmp = dirname(str_replace('\\', '/', get_class($bundle))); + $namespace = str_replace('/', '\\', dirname($tmp)); + $class = basename($tmp); + + if (isset($bundleDirs[$namespace]) && is_dir($dir = $bundleDirs[$namespace].'/'.$class.'/DataFixtures/MongoDB')) { + $paths[] = $dir; + } + } + } + + $loader = new \Doctrine\Common\DataFixtures\Loader(); + foreach ($paths as $path) { + $loader->loadFromDirectory($path); + } + $fixtures = $loader->getFixtures(); + $purger = new \Doctrine\Common\DataFixtures\Purger\MongoDBPurger($dm); + $executor = new \Doctrine\Common\DataFixtures\Executor\MongoDBExecutor($dm, $purger); + $executor->execute($fixtures, $input->getOption('append')); + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml b/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml index c2f718b54e5ba..71835fd7e78f8 100755 --- a/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/Resources/config/mongodb.xml @@ -56,7 +56,6 @@ - %doctrine.odm.mongodb.metadata.annotation_default_namespace% Doctrine\ODM\MongoDB\Mapping\ mongodb @@ -77,4 +76,4 @@ - + \ No newline at end of file diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/Tests/ContainerTest.php b/src/Symfony/Bundle/DoctrineMongoDBBundle/Tests/ContainerTest.php new file mode 100644 index 0000000000000..6d03d6db7fae6 --- /dev/null +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/Tests/ContainerTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DoctrineBundle\Tests; + +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Bundle\DoctrineMongoDBBundle\DependencyInjection\DoctrineMongoDBExtension; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +class ContainerTest extends TestCase +{ + public function getContainer() + { + $container = new ContainerBuilder(new ParameterBag(array( + 'kernel.bundle_dirs' => array(), + 'kernel.bundles' => array(), + 'kernel.cache_dir' => sys_get_temp_dir(), + ))); + $loader = new DoctrineMongoDBExtension(); + $container->registerExtension($loader); + $loader->mongodbLoad(array(), $container); + + $dumper = new PhpDumper($container); + $code = $dumper->dump(); + eval(str_replace('getContainer(); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Mapping\Driver\DriverChain', $container->get('doctrine.odm.mongodb.metadata.chain')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver', $container->get('doctrine.odm.mongodb.metadata.annotation')); + $this->assertInstanceOf('Doctrine\Common\Annotations\AnnotationReader', $container->get('doctrine.odm.mongodb.metadata.annotation_reader')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Mapping\Driver\XmlDriver', $container->get('doctrine.odm.mongodb.metadata.xml')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Mapping\Driver\YamlDriver', $container->get('doctrine.odm.mongodb.metadata.yml')); + $this->assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.odm.mongodb.cache.array')); + $this->assertInstanceOf('Symfony\Bundle\DoctrineMongoDBBundle\Logger\DoctrineMongoDBLogger', $container->get('doctrine.odm.mongodb.logger')); + $this->assertInstanceOf('Symfony\Bundle\DoctrineMongoDBBundle\DataCollector\DoctrineMongoDBDataCollector', $container->get('doctrine.odm.mongodb.data_collector')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Mongo', $container->get('doctrine.odm.mongodb.default_connection')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Configuration', $container->get('doctrine.odm.mongodb.default_configuration')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Mapping\Driver\DriverChain', $container->get('doctrine.odm.mongodb.metadata')); + $this->assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.odm.mongodb.default_metadata_cache')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\DocumentManager', $container->get('doctrine.odm.mongodb.default_document_manager')); + $this->assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.odm.mongodb.cache')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\DocumentManager', $container->get('doctrine.odm.mongodb.document_manager')); + } +} \ No newline at end of file diff --git a/update_vendors.sh b/update_vendors.sh index 1de72e87f3dc8..446b486071597 100755 --- a/update_vendors.sh +++ b/update_vendors.sh @@ -5,6 +5,9 @@ CURRENT=`pwd`/vendor # Doctrine ORM cd $CURRENT/doctrine && git pull +# Doctrine ORM Data Fixtures Extension +cd $CURRENT/doctrine-orm-data-fixtures && git pull + # Doctrine DBAL cd $CURRENT/doctrine-dbal && git pull From 3bc3115d8c784c5be201d0156a51d6626135a246 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Wage" Date: Tue, 5 Oct 2010 01:51:23 -0500 Subject: [PATCH 07/10] Adding setLogger for data fixtures. --- .../DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php | 3 +++ .../Command/LoadDataFixturesDoctrineODMCommand.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php index c07dac0045165..9b02dd4b6c7be 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php +++ b/src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php @@ -86,6 +86,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $fixtures = $loader->getFixtures(); $purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger($em); $executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($em, $purger); + $executor->setLogger(function($message) use ($output) { + $output->writeln(sprintf(' > %s', $message)); + }); $executor->execute($fixtures, $input->getOption('append')); } } \ No newline at end of file diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php index abafc25f8e2e1..c5e8997603966 100644 --- a/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php @@ -86,6 +86,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $fixtures = $loader->getFixtures(); $purger = new \Doctrine\Common\DataFixtures\Purger\MongoDBPurger($dm); $executor = new \Doctrine\Common\DataFixtures\Executor\MongoDBExecutor($dm, $purger); + $executor->setLogger(function($message) use ($output) { + $output->writeln(sprintf(' > %s', $message)); + }); $executor->execute($fixtures, $input->getOption('append')); } } \ No newline at end of file From c6ed5930229780a7bcf11a45c64918a7c13897ae Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 5 Oct 2010 09:05:29 +0200 Subject: [PATCH 08/10] fixed unit tests --- src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php | 2 +- .../Bundle/DoctrineMongoDBBundle/Tests/ContainerTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php index 5276ee797781a..ba7d46bbae003 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php +++ b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php @@ -32,7 +32,7 @@ public function getContainer() $loader->ormLoad(array(), $container); $dumper = new PhpDumper($container); - $code = $dumper->dump(); + $code = $dumper->dump(array('class' => 'DoctrineBundleTestsProjectServiceContainer')); eval(str_replace('mongodbLoad(array(), $container); $dumper = new PhpDumper($container); - $code = $dumper->dump(); + $code = $dumper->dump(array('class' => 'DoctrineMongoDBBundleTestsProjectServiceContainer')); eval(str_replace('assertInstanceOf('Doctrine\Common\Cache\ArrayCache', $container->get('doctrine.odm.mongodb.cache')); $this->assertInstanceOf('Doctrine\ODM\MongoDB\DocumentManager', $container->get('doctrine.odm.mongodb.document_manager')); } -} \ No newline at end of file +} From 36a31eceb86755db9773758a2f29499e0eceea8d Mon Sep 17 00:00:00 2001 From: "Jonathan H. Wage" Date: Tue, 5 Oct 2010 02:14:07 -0500 Subject: [PATCH 09/10] Fixing container test. --- src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php | 2 +- .../Bundle/DoctrineMongoDBBundle/Tests/ContainerTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php index ba7d46bbae003..45480c7347c56 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php +++ b/src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php @@ -34,7 +34,7 @@ public function getContainer() $dumper = new PhpDumper($container); $code = $dumper->dump(array('class' => 'DoctrineBundleTestsProjectServiceContainer')); eval(str_replace('dump(array('class' => 'DoctrineMongoDBBundleTestsProjectServiceContainer')); eval(str_replace(' Date: Tue, 5 Oct 2010 02:29:00 -0500 Subject: [PATCH 10/10] Fixing old path to new one. --- autoload.php.dist | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/autoload.php.dist b/autoload.php.dist index 902a1735ba33b..ecaec83f53c96 100644 --- a/autoload.php.dist +++ b/autoload.php.dist @@ -6,14 +6,14 @@ use Symfony\Component\HttpFoundation\UniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespaces(array( - 'Symfony' => __DIR__.'/src', - 'Doctrine\\ODM\\MongoDB' => __DIR__.'/vendor/doctrine-mongodb/lib', - 'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib', - 'Doctrine\\DBAL\\Migrations' => __DIR__.'/vendor/doctrine-migrations/lib', - 'Doctrine\\DBAL' => __DIR__.'/vendor/doctrine-dbal/lib', - 'Doctrine\\ORM\\DataFixtures' => __DIR__.'/vendor/doctrine-orm-data-fixtures', - 'Doctrine' => __DIR__.'/vendor/doctrine/lib', - 'Zend' => __DIR__.'/vendor/zend/library', + 'Symfony' => __DIR__.'/src', + 'Doctrine\\ODM\\MongoDB' => __DIR__.'/vendor/doctrine-mongodb/lib', + 'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib', + 'Doctrine\\DBAL\\Migrations' => __DIR__.'/vendor/doctrine-migrations/lib', + 'Doctrine\\DBAL' => __DIR__.'/vendor/doctrine-dbal/lib', + 'Doctrine\\Common\\DataFixtures' => __DIR__.'/vendor/doctrine-data-fixtures/lib', + 'Doctrine' => __DIR__.'/vendor/doctrine/lib', + 'Zend' => __DIR__.'/vendor/zend/library', )); $loader->registerPrefixes(array( 'Swift_' => __DIR__.'/vendor/swiftmailer/lib/classes',