FieldFactory.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. namespace Symfony\Component\Form\FieldFactory;
  3. /*
  4. * This file is part of the Symfony framework.
  5. *
  6. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  12. /**
  13. * Default implementation of FieldFactoryInterface
  14. *
  15. * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  16. * @see FieldFactoryInterface
  17. */
  18. class FieldFactory implements FieldFactoryInterface
  19. {
  20. /**
  21. * A list of guessers for guessing field classes and options
  22. * @var array
  23. */
  24. protected $guessers;
  25. /**
  26. * Constructor
  27. *
  28. * @param array $guessers A list of instances implementing
  29. * FieldFactoryGuesserInterface
  30. */
  31. public function __construct(array $guessers)
  32. {
  33. foreach ($guessers as $guesser) {
  34. if (!$guesser instanceof FieldFactoryGuesserInterface) {
  35. throw new UnexpectedTypeException($guesser, 'FieldFactoryGuesserInterface');
  36. }
  37. }
  38. $this->guessers = $guessers;
  39. }
  40. /**
  41. * @inheritDoc
  42. */
  43. public function getInstance($object, $property, array $options = array())
  44. {
  45. $guess = $this->guess(function ($guesser) use ($object, $property) {
  46. return $guesser->guessMaxLength($object, $property);
  47. });
  48. $maxLength = $guess ? $guess->getValue() : null;
  49. $guess = $this->guess(function ($guesser) use ($object, $property) {
  50. return $guesser->guessClass($object, $property);
  51. });
  52. if (!$guess) {
  53. throw new \RuntimeException(sprintf('No field could be guessed for property "%s" of class %s', $property, get_class($object)));
  54. }
  55. $class = $guess->getClass();
  56. $textField = 'Symfony\Component\Form\TextField';
  57. if (null !== $maxLength && ($class == $textField || is_subclass_of($class, $textField))) {
  58. $options = array_merge(array('max_length' => $maxLength), $options);
  59. }
  60. $options = array_merge($guess->getOptions(), $options);
  61. $field = new $class($property, $options);
  62. $guess = $this->guess(function ($guesser) use ($object, $property) {
  63. return $guesser->guessRequired($object, $property);
  64. });
  65. if ($guess) {
  66. $field->setRequired($guess->getValue());
  67. }
  68. return $field;
  69. }
  70. /**
  71. * Executes a closure for each guesser and returns the best guess from the
  72. * return values
  73. *
  74. * @param \Closure $closure The closure to execute. Accepts a guesser as
  75. * argument and should return a FieldFactoryGuess
  76. * instance
  77. * @return FieldFactoryGuess The guess with the highest confidence
  78. */
  79. protected function guess(\Closure $closure)
  80. {
  81. $guesses = array();
  82. foreach ($this->guessers as $guesser) {
  83. if ($guess = $closure($guesser)) {
  84. $guesses[] = $guess;
  85. }
  86. }
  87. return FieldFactoryGuess::getBestGuess($guesses);
  88. }
  89. }