FieldFactory.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Form\FieldFactory;
  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($class, $property, array $options = array())
  44. {
  45. // guess field class and options
  46. $classGuess = $this->guess(function ($guesser) use ($class, $property) {
  47. return $guesser->guessClass($class, $property);
  48. });
  49. if (!$classGuess) {
  50. throw new \RuntimeException(sprintf('No field could be guessed for property "%s" of class %s', $property, $class));
  51. }
  52. // guess maximum length
  53. $maxLengthGuess = $this->guess(function ($guesser) use ($class, $property) {
  54. return $guesser->guessMaxLength($class, $property);
  55. });
  56. // guess whether field is required
  57. $requiredGuess = $this->guess(function ($guesser) use ($class, $property) {
  58. return $guesser->guessRequired($class, $property);
  59. });
  60. // construct field
  61. $fieldClass = $classGuess->getClass();
  62. $textField = 'Symfony\Component\Form\TextField';
  63. if ($maxLengthGuess && ($fieldClass == $textField || is_subclass_of($fieldClass, $textField))) {
  64. // TODO enable me again later
  65. // $options = array_merge(array('max_length' => $maxLengthGuess->getValue()), $options);
  66. }
  67. if ($requiredGuess) {
  68. $options = array_merge(array('required' => $requiredGuess->getValue()), $options);
  69. }
  70. // user options may override guessed options
  71. $options = array_merge($classGuess->getOptions(), $options);
  72. return new $fieldClass($property, $options);
  73. }
  74. /**
  75. * Executes a closure for each guesser and returns the best guess from the
  76. * return values
  77. *
  78. * @param \Closure $closure The closure to execute. Accepts a guesser as
  79. * argument and should return a FieldFactoryGuess
  80. * instance
  81. * @return FieldFactoryGuess The guess with the highest confidence
  82. */
  83. protected function guess(\Closure $closure)
  84. {
  85. $guesses = array();
  86. foreach ($this->guessers as $guesser) {
  87. if ($guess = $closure($guesser)) {
  88. $guesses[] = $guess;
  89. }
  90. }
  91. return FieldFactoryGuess::getBestGuess($guesses);
  92. }
  93. }