Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Form / Factory.php
blob9afd8abacc084cf466ce976eff9177913bee689f
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Form;
12 use ArrayAccess;
13 use Traversable;
14 use Zend\InputFilter\Factory as InputFilterFactory;
15 use Zend\InputFilter\InputFilterInterface;
16 use Zend\Stdlib\ArrayUtils;
17 use Zend\Stdlib\Hydrator;
19 class Factory
21 /**
22 * @var InputFilterFactory
24 protected $inputFilterFactory;
26 /**
27 * @var FormElementManager
29 protected $formElementManager;
31 /**
32 * @param FormElementManager $formElementManager
34 public function __construct(FormElementManager $formElementManager = null)
36 if ($formElementManager) {
37 $this->setFormElementManager($formElementManager);
41 /**
42 * Set input filter factory to use when creating forms
44 * @param InputFilterFactory $inputFilterFactory
45 * @return Factory
47 public function setInputFilterFactory(InputFilterFactory $inputFilterFactory)
49 $this->inputFilterFactory = $inputFilterFactory;
50 return $this;
53 /**
54 * Get current input filter factory
56 * If none provided, uses an unconfigured instance.
58 * @return InputFilterFactory
60 public function getInputFilterFactory()
62 if (null === $this->inputFilterFactory) {
63 $this->setInputFilterFactory(new InputFilterFactory());
65 return $this->inputFilterFactory;
68 /**
69 * Set the form element manager
71 * @param FormElementManager $formElementManager
72 * @return Factory
74 public function setFormElementManager(FormElementManager $formElementManager)
76 $this->formElementManager = $formElementManager;
77 return $this;
80 /**
81 * Get form element manager
83 * @return FormElementManager
85 public function getFormElementManager()
87 if ($this->formElementManager === null) {
88 $this->setFormElementManager(new FormElementManager());
91 return $this->formElementManager;
94 /**
95 * Create an element, fieldset, or form
97 * Introspects the 'type' key of the provided $spec, and determines what
98 * type is being requested; if none is provided, assumes the spec
99 * represents simply an element.
101 * @param array|Traversable $spec
102 * @return ElementInterface
103 * @throws Exception\DomainException
105 public function create($spec)
107 $spec = $this->validateSpecification($spec, __METHOD__);
108 $type = isset($spec['type']) ? $spec['type'] : 'Zend\Form\Element';
110 $element = $this->getFormElementManager()->get($type);
112 if ($element instanceof FormInterface) {
113 return $this->configureForm($element, $spec);
116 if ($element instanceof FieldsetInterface) {
117 return $this->configureFieldset($element, $spec);
120 if ($element instanceof ElementInterface) {
121 return $this->configureElement($element, $spec);
124 throw new Exception\DomainException(sprintf(
125 '%s expects the $spec["type"] to implement one of %s, %s, or %s; received %s',
126 __METHOD__,
127 'Zend\Form\ElementInterface',
128 'Zend\Form\FieldsetInterface',
129 'Zend\Form\FormInterface',
130 $type
135 * Create an element
137 * @param array $spec
138 * @return ElementInterface
140 public function createElement($spec)
142 if (!isset($spec['type'])) {
143 $spec['type'] = 'Zend\Form\Element';
146 return $this->create($spec);
150 * Create a fieldset
152 * @param array $spec
153 * @return ElementInterface
155 public function createFieldset($spec)
157 if (!isset($spec['type'])) {
158 $spec['type'] = 'Zend\Form\Fieldset';
161 return $this->create($spec);
165 * Create a form
167 * @param array $spec
168 * @return ElementInterface
170 public function createForm($spec)
172 if (!isset($spec['type'])) {
173 $spec['type'] = 'Zend\Form\Form';
176 return $this->create($spec);
180 * Configure an element based on the provided specification
182 * Specification can contain any of the following:
183 * - type: the Element class to use; defaults to \Zend\Form\Element
184 * - name: what name to provide the element, if any
185 * - options: an array, Traversable, or ArrayAccess object of element options
186 * - attributes: an array, Traversable, or ArrayAccess object of element
187 * attributes to assign
189 * @param ElementInterface $element
190 * @param array|Traversable|ArrayAccess $spec
191 * @throws Exception\DomainException
192 * @return ElementInterface
194 public function configureElement(ElementInterface $element, $spec)
196 $spec = $this->validateSpecification($spec, __METHOD__);
198 $name = isset($spec['name']) ? $spec['name'] : null;
199 $options = isset($spec['options']) ? $spec['options'] : null;
200 $attributes = isset($spec['attributes']) ? $spec['attributes'] : null;
202 if ($name !== null && $name !== '') {
203 $element->setName($name);
206 if (is_array($options) || $options instanceof Traversable || $options instanceof ArrayAccess) {
207 $element->setOptions($options);
210 if (is_array($attributes) || $attributes instanceof Traversable || $attributes instanceof ArrayAccess) {
211 $element->setAttributes($attributes);
214 return $element;
218 * Configure a fieldset based on the provided specification
220 * Specification can contain any of the following:
221 * - type: the Fieldset class to use; defaults to \Zend\Form\Fieldset
222 * - name: what name to provide the fieldset, if any
223 * - options: an array, Traversable, or ArrayAccess object of element options
224 * - attributes: an array, Traversable, or ArrayAccess object of element
225 * attributes to assign
226 * - elements: an array or Traversable object where each entry is an array
227 * or ArrayAccess object containing the keys:
228 * - flags: (optional) array of flags to pass to FieldsetInterface::add()
229 * - spec: the actual element specification, per {@link configureElement()}
231 * @param FieldsetInterface $fieldset
232 * @param array|Traversable|ArrayAccess $spec
233 * @throws Exception\DomainException
234 * @return FieldsetInterface
236 public function configureFieldset(FieldsetInterface $fieldset, $spec)
238 $spec = $this->validateSpecification($spec, __METHOD__);
239 $fieldset = $this->configureElement($fieldset, $spec);
241 if (isset($spec['object'])) {
242 $this->prepareAndInjectObject($spec['object'], $fieldset, __METHOD__);
245 if (isset($spec['hydrator'])) {
246 $this->prepareAndInjectHydrator($spec['hydrator'], $fieldset, __METHOD__);
249 if (isset($spec['elements'])) {
250 $this->prepareAndInjectElements($spec['elements'], $fieldset, __METHOD__);
253 if (isset($spec['fieldsets'])) {
254 $this->prepareAndInjectFieldsets($spec['fieldsets'], $fieldset, __METHOD__);
257 $factory = (isset($spec['factory']) ? $spec['factory'] : $this);
258 $this->prepareAndInjectFactory($factory, $fieldset, __METHOD__);
260 return $fieldset;
264 * Configure a form based on the provided specification
266 * Specification follows that of {@link configureFieldset()}, and adds the
267 * following keys:
269 * - input_filter: input filter instance, named input filter class, or
270 * array specification for the input filter factory
271 * - hydrator: hydrator instance or named hydrator class
273 * @param FormInterface $form
274 * @param array|Traversable|ArrayAccess $spec
275 * @return FormInterface
277 public function configureForm(FormInterface $form, $spec)
279 $spec = $this->validateSpecification($spec, __METHOD__);
280 $form = $this->configureFieldset($form, $spec);
282 if (isset($spec['input_filter'])) {
283 $this->prepareAndInjectInputFilter($spec['input_filter'], $form, __METHOD__);
286 if (isset($spec['validation_group'])) {
287 $this->prepareAndInjectValidationGroup($spec['validation_group'], $form, __METHOD__);
290 return $form;
294 * Validate a provided specification
296 * Ensures we have an array, Traversable, or ArrayAccess object, and returns it.
298 * @param array|Traversable|ArrayAccess $spec
299 * @param string $method Method invoking the validator
300 * @return array|ArrayAccess
301 * @throws Exception\InvalidArgumentException for invalid $spec
303 protected function validateSpecification($spec, $method)
305 if (is_array($spec)) {
306 return $spec;
309 if ($spec instanceof Traversable) {
310 $spec = ArrayUtils::iteratorToArray($spec);
311 return $spec;
314 if (!$spec instanceof ArrayAccess) {
315 throw new Exception\InvalidArgumentException(sprintf(
316 '%s expects an array, or object implementing Traversable or ArrayAccess; received "%s"',
317 $method,
318 (is_object($spec) ? get_class($spec) : gettype($spec))
322 return $spec;
326 * Takes a list of element specifications, creates the elements, and injects them into the provided fieldset
328 * @param array|Traversable|ArrayAccess $elements
329 * @param FieldsetInterface $fieldset
330 * @param string $method Method invoking this one (for exception messages)
331 * @return void
333 protected function prepareAndInjectElements($elements, FieldsetInterface $fieldset, $method)
335 $elements = $this->validateSpecification($elements, $method);
337 foreach ($elements as $elementSpecification) {
338 $flags = isset($elementSpecification['flags']) ? $elementSpecification['flags'] : array();
339 $spec = isset($elementSpecification['spec']) ? $elementSpecification['spec'] : array();
341 if (!isset($spec['type'])) {
342 $spec['type'] = 'Zend\Form\Element';
345 $element = $this->create($spec);
346 $fieldset->add($element, $flags);
351 * Takes a list of fieldset specifications, creates the fieldsets, and injects them into the master fieldset
353 * @param array|Traversable|ArrayAccess $fieldsets
354 * @param FieldsetInterface $masterFieldset
355 * @param string $method Method invoking this one (for exception messages)
356 * @return void
358 public function prepareAndInjectFieldsets($fieldsets, FieldsetInterface $masterFieldset, $method)
360 $fieldsets = $this->validateSpecification($fieldsets, $method);
362 foreach ($fieldsets as $fieldsetSpecification) {
363 $flags = isset($fieldsetSpecification['flags']) ? $fieldsetSpecification['flags'] : array();
364 $spec = isset($fieldsetSpecification['spec']) ? $fieldsetSpecification['spec'] : array();
366 $fieldset = $this->createFieldset($spec);
367 $masterFieldset->add($fieldset, $flags);
372 * Prepare and inject an object
374 * Takes a string indicating a class name, instantiates the class
375 * by that name, and injects the class instance as the bound object.
377 * @param string $objectName
378 * @param FieldsetInterface $fieldset
379 * @param string $method
380 * @throws Exception\DomainException
381 * @return void
383 protected function prepareAndInjectObject($objectName, FieldsetInterface $fieldset, $method)
385 if (!is_string($objectName)) {
386 throw new Exception\DomainException(sprintf(
387 '%s expects string class name; received "%s"',
388 $method,
389 (is_object($objectName) ? get_class($objectName) : gettype($objectName))
393 if (!class_exists($objectName)) {
394 throw new Exception\DomainException(sprintf(
395 '%s expects string class name to be a valid class name; received "%s"',
396 $method,
397 $objectName
401 $fieldset->setObject(new $objectName);
405 * Prepare and inject a named hydrator
407 * Takes a string indicating a hydrator class name (or a concrete instance), try first to instantiates the class
408 * by pulling it from service manager, and injects the hydrator instance into the form.
410 * @param string|array|Hydrator\HydratorInterface $hydratorOrName
411 * @param FieldsetInterface $fieldset
412 * @param string $method
413 * @return void
414 * @throws Exception\DomainException If $hydratorOrName is not a string, does not resolve to a known class, or
415 * the class does not implement Hydrator\HydratorInterface
417 protected function prepareAndInjectHydrator($hydratorOrName, FieldsetInterface $fieldset, $method)
419 if ($hydratorOrName instanceof Hydrator\HydratorInterface) {
420 $fieldset->setHydrator($hydratorOrName);
421 return;
424 if (is_array($hydratorOrName)) {
425 if (!isset($hydratorOrName['type'])) {
426 throw new Exception\DomainException(sprintf(
427 '%s expects array specification to have a type value',
428 $method
431 $hydratorOptions = (isset($hydratorOrName['options'])) ? $hydratorOrName['options'] : array();
432 $hydratorOrName = $hydratorOrName['type'];
433 } else {
434 $hydratorOptions = array();
437 if (is_string($hydratorOrName)) {
438 $hydrator = $this->getHydratorFromName($hydratorOrName);
441 if (!$hydrator instanceof Hydrator\HydratorInterface) {
442 throw new Exception\DomainException(sprintf(
443 '%s expects a valid implementation of Zend\Form\Hydrator\HydratorInterface; received "%s"',
444 $method,
445 $hydratorOrName
449 if (!empty($hydratorOptions) && $hydrator instanceof Hydrator\HydratorOptionsInterface) {
450 $hydrator->setOptions($hydratorOptions);
453 $fieldset->setHydrator($hydrator);
457 * Prepare and inject a named factory
459 * Takes a string indicating a factory class name (or a concrete instance), try first to instantiates the class
460 * by pulling it from service manager, and injects the factory instance into the fieldset.
462 * @param string|array|Factory $factoryOrName
463 * @param FieldsetInterface $fieldset
464 * @param string $method
465 * @return void
466 * @throws Exception\DomainException If $factoryOrName is not a string, does not resolve to a known class, or
467 * the class does not extend Form\Factory
469 protected function prepareAndInjectFactory($factoryOrName, FieldsetInterface $fieldset, $method)
471 if (is_array($factoryOrName)) {
472 if (!isset($factoryOrName['type'])) {
473 throw new Exception\DomainException(sprintf(
474 '%s expects array specification to have a type value',
475 $method
478 $factoryOrName = $factoryOrName['type'];
481 if (is_string($factoryOrName)) {
482 $factoryOrName = $this->getFactoryFromName($factoryOrName);
485 if (!$factoryOrName instanceof Factory) {
486 throw new Exception\DomainException(sprintf(
487 '%s expects a valid extention of Zend\Form\Factory; received "%s"',
488 $method,
489 $factoryOrName
493 $fieldset->setFormFactory($factoryOrName);
497 * Prepare an input filter instance and inject in the provided form
499 * If the input filter specified is a string, assumes it is a class name,
500 * and attempts to instantiate it. If the class does not exist, or does
501 * not extend InputFilterInterface, an exception is raised.
503 * Otherwise, $spec is passed on to the attached InputFilter Factory
504 * instance in order to create the input filter.
506 * @param string|array|Traversable $spec
507 * @param FormInterface $form
508 * @param string $method
509 * @return void
510 * @throws Exception\DomainException for unknown InputFilter class or invalid InputFilter instance
512 protected function prepareAndInjectInputFilter($spec, FormInterface $form, $method)
514 if ($spec instanceof InputFilterInterface) {
515 $form->setInputFilter($spec);
516 return;
519 if (is_string($spec)) {
520 if (!class_exists($spec)) {
521 throw new Exception\DomainException(sprintf(
522 '%s expects string input filter names to be valid class names; received "%s"',
523 $method,
524 $spec
527 $filter = new $spec;
528 if (!$filter instanceof InputFilterInterface) {
529 throw new Exception\DomainException(sprintf(
530 '%s expects a valid implementation of Zend\InputFilter\InputFilterInterface; received "%s"',
531 $method,
532 $spec
535 $form->setInputFilter($filter);
536 return;
539 $factory = $this->getInputFilterFactory();
540 $filter = $factory->createInputFilter($spec);
541 if (method_exists($filter, 'setFactory')) {
542 $filter->setFactory($factory);
544 $form->setInputFilter($filter);
548 * Prepare a validation group and inject in the provided form
550 * Takes an array of elements names
552 * @param string|array|Traversable $spec
553 * @param FormInterface $form
554 * @param string $method
555 * @return void
556 * @throws Exception\DomainException if validation group given is not an array
558 protected function prepareAndInjectValidationGroup($spec, FormInterface $form, $method)
560 if (!is_array($spec)) {
561 if (!class_exists($spec)) {
562 throw new Exception\DomainException(sprintf(
563 '%s expects an array for validation group; received "%s"',
564 $method,
565 $spec
570 $form->setValidationGroup($spec);
574 * Try to pull hydrator from service manager, or instantiates it from its name
576 * @param string $hydratorName
577 * @return mixed
578 * @throws Exception\DomainException
580 protected function getHydratorFromName($hydratorName)
582 $services = $this->getFormElementManager()->getServiceLocator();
584 if ($services && $services->has('HydratorManager')) {
585 $hydrators = $services->get('HydratorManager');
586 if ($hydrators->has($hydratorName)) {
587 return $hydrators->get($hydratorName);
591 if ($services && $services->has($hydratorName)) {
592 return $services->get($hydratorName);
595 if (!class_exists($hydratorName)) {
596 throw new Exception\DomainException(sprintf(
597 'Expects string hydrator name to be a valid class name; received "%s"',
598 $hydratorName
602 $hydrator = new $hydratorName;
603 return $hydrator;
607 * Try to pull factory from service manager, or instantiates it from its name
609 * @param string $factoryName
610 * @return mixed
611 * @throws Exception\DomainException
613 protected function getFactoryFromName($factoryName)
615 $services = $this->getFormElementManager()->getServiceLocator();
617 if ($services && $services->has($factoryName)) {
618 return $services->get($factoryName);
621 if (!class_exists($factoryName)) {
622 throw new Exception\DomainException(sprintf(
623 'Expects string factory name to be a valid class name; received "%s"',
624 $factoryName
628 $factory = new $factoryName;
629 return $factory;