Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fix supports formtype parser #81

Merged
merged 5 commits into from

4 participants

@docteurklein

If you give class names which require constructor arguments, the FormTypeParser fails with fatal error when calling supports.

@Seldaek
Owner

Congrats on the insane hack ;) Looks alright to me but I'll let @willdurand check it out and merge because I'm not very familiar with that part of the code.

@stof

If your class as some required constructor arguments, you should be using the type name instead.
your hack will indeed allow to build the object, but will still break stuff as the type will not have its dependencies and so will break when using it.

Parser/FormTypeParser.php
@@ -65,7 +65,7 @@ public function supports($item)
public function parse($type)
{
if (is_string($type) && class_exists($type)) {
- $type = new $type();
+ $item = unserialize(sprintf('O:%d:"%s":0:{}', strlen($item), $item));
@stof
stof added a note

$item ? There is no such variable

oops. fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@docteurklein

@stof I agree about the fact that when parsing the form, we should have a valid object instance.

Maybe should we just keep the hack for the supports method ?

This way, the fatal error would be triggered only when it's actually a real form type.

@stof

@docteurklein supports should check if the class is implementing FormTypeInterface in case it is a class name or an object instead (and call the form factory only when passing a string considered as type name).

And to have a real check, it could even check if the constructor can be called in case a class name is passed (i.e. does not have mandatory arguments).

@docteurklein

@stof there is another problem when creating the form: required options.

Parser/FormTypeParser.php
((8 lines not shown))
}
-
- $form = $this->formFactory->create($item);
- } catch (FormException $e) {
+ }
+ catch (FormException $e) {
@stof
stof added a note

Wrong CS here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Parser/FormTypeParser.php
@@ -11,6 +11,10 @@
namespace Nelmio\ApiDocBundle\Parser;
+use Symfony\Component\OptionsResolver\Exception\MissingOptionsException;
+
+use Symfony\Component\Form\FormRegistry;
+
@stof
stof added a note

please remove the empty lines here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@docteurklein

any news ?

@willdurand willdurand merged commit bd625ae into from
@willdurand
Collaborator

Thank you, and sorry for the delay.

@docteurklein

no problem! thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 40 additions and 9 deletions.
  1. +39 −9 Parser/FormTypeParser.php
  2. +1 −0  Resources/config/formatters.xml
View
48 Parser/FormTypeParser.php
@@ -11,6 +11,8 @@
namespace Nelmio\ApiDocBundle\Parser;
+use Symfony\Component\OptionsResolver\Exception\MissingOptionsException;
+use Symfony\Component\Form\FormRegistry;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\Exception\FormException;
@@ -36,9 +38,10 @@ class FormTypeParser implements ParserInterface
'country' => 'string',
);
- public function __construct(FormFactoryInterface $formFactory)
+ public function __construct(FormFactoryInterface $formFactory, FormRegistry $formRegistry)
{
- $this->formFactory = $formFactory;
+ $this->formFactory = $formFactory;
+ $this->formRegistry = $formRegistry;
}
/**
@@ -47,16 +50,16 @@ public function __construct(FormFactoryInterface $formFactory)
public function supports($item)
{
try {
- if (is_string($item) && class_exists($item)) {
- $item = new $item();
+ if ($this->createForm($item)) {
+ return true;
}
-
- $form = $this->formFactory->create($item);
} catch (FormException $e) {
return false;
+ } catch (MissingOptionsException $e) {
+ return false;
}
- return true;
+ return false;
}
/**
@@ -64,8 +67,8 @@ public function supports($item)
*/
public function parse($type)
{
- if (is_string($type) && class_exists($type)) {
- $type = new $type();
+ if ($this->implementsType($type)) {
+ $type = $this->getTypeInstance($type);
}
$form = $this->formFactory->create($type);
@@ -111,4 +114,31 @@ private function parseForm($form, $prefix = null)
return $parameters;
}
+
+ private function implementsType($item)
+ {
+ if (!class_exists($item)) {
+ return false;
+ }
+ $refl = new \ReflectionClass($item);
+
+ return $refl->implementsInterface('Symfony\Component\Form\FormTypeInterface');
+ }
+
+ private function getTypeInstance($type)
+ {
+ return unserialize(sprintf('O:%d:"%s":0:{}', strlen($type), $type));
+ }
+
+ private function createForm($item)
+ {
+ if ($this->implementsType($item)) {
+ $type = $this->getTypeInstance($item);
+
+ return $this->formFactory->create($type);
+ }
+ if ($this->formRegistry->hasType($item)) {
+ return $this->formFactory->create($item);
+ }
+ }
}
View
1  Resources/config/formatters.xml
@@ -15,6 +15,7 @@
<services>
<service id="nelmio_api_doc.parser.form_type_parser" class="%nelmio_api_doc.parser.form_type_parser.class%">
<argument type="service" id="form.factory" />
+ <argument type="service" id="form.registry" />
<tag name="nelmio_api_doc.extractor.parser" />
</service>
<service id="nelmio_api_doc.formatter.abstract_formatter" class="%nelmio_api_doc.formatter.abstract_formatter.class%" />
Something went wrong with that request. Please try again.