AnnotationBuilderFactory.php 5.13 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
<?php
/**
 * @link      http://github.com/zendframework/zend-form for the canonical source repository
 * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Form\Annotation;

use Interop\Container\ContainerInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use Zend\Form\Factory;
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class AnnotationBuilderFactory implements FactoryInterface
{
    /**
     * @param  ContainerInterface $container
     * @param  string $name
     * @param  null|array $options
     * @return AnnotationBuilder
     * @throws ServiceNotCreatedException for invalid listener configuration.
     */
    public function __invoke(ContainerInterface $container, $name, array $options = null)
    {
        //setup a form factory which can use custom form elements
        $annotationBuilder = new AnnotationBuilder();
        $eventManager      = $container->get('EventManager');
        $annotationBuilder->setEventManager($eventManager);

        $this->injectFactory($annotationBuilder->getFormFactory(), $container);

        $config = $this->marshalConfig($container);
        if (isset($config['preserve_defined_order'])) {
            $annotationBuilder->setPreserveDefinedOrder($config['preserve_defined_order']);
        }

        $this->injectAnnotations($config, $annotationBuilder);
        $this->injectListeners($config, $eventManager, $container);

        return $annotationBuilder;
    }

    /**
     * Create and return AnnotationBuilder instance
     *
     * For use with zend-servicemanager v2; proxies to __invoke().
     *
     * @param ServiceLocatorInterface $container
     * @return AnnotationBuilder
     */
    public function createService(ServiceLocatorInterface $container)
    {
        return $this($container, AnnotationBuilder::class);
    }

    /**
     * Marshal annotation builder configuration, if any.
     *
     * Looks for the `config` service in the container, returning an empty array
     * if not found.
     *
     * If found, checks for a `form_annotation_builder` entry, returning an empty
     * array if not found or not an array.
     *
     * Otherwise, returns the `form_annotation_builder` array.
     *
     * @param ContainerInterface $container
     * @return array
     */
    private function marshalConfig(ContainerInterface $container)
    {
        if (! $container->has('config')) {
            return [];
        }

        $config = $container->get('config');
        $config = isset($config['form_annotation_builder'])
            ? $config['form_annotation_builder']
            : [];

        return is_array($config) ? $config : [];
    }

    /**
     * Inject annotations from configuration, if any.
     *
     * @param array $config
     * @param AnnotationBuilder $builder
     * @return void
     */
    private function injectAnnotations(array $config, AnnotationBuilder $builder)
    {
        if (! isset($config['annotations'])) {
            return;
        }

        $parser = $builder->getAnnotationParser();
        foreach ($config['annotations'] as $fullyQualifiedClassName) {
            $parser->registerAnnotation($fullyQualifiedClassName);
        }
    }

    /**
     * Inject event listeners from configuration, if any.
     *
     * Loops through the 'listeners' array, and:
     *
     * - attempts to fetch it from the container
     * - if the fetched instance is not a `ListenerAggregate`, raises an exception
     * - otherwise attaches it to the event manager
     *
     * @param array $config
     * @param EventManagerInterface $events
     * @param ContainerInterface $container
     * @return void
     * @throws ServiceNotCreatedException if any listener is not an event listener
     *     aggregate.
     */
    private function injectListeners(array $config, EventManagerInterface $events, ContainerInterface $container)
    {
        if (! isset($config['listeners'])) {
            return;
        }

        foreach ($config['listeners'] as $listenerName) {
            $listener = $container->get($listenerName);

            if (! $listener instanceof ListenerAggregateInterface) {
                throw new ServiceNotCreatedException(sprintf('Invalid event listener (%s) provided', $listenerName));
            }

            $listener->attach($events);
        }
    }

    /**
     * Inject the annotation builder's factory instance with the FormElementManager.
     *
     * Also injects the factory with the InputFilterManager if present.
     *
     * @param Factory $factory
     * @param ContainerInterface $container
     */
    private function injectFactory(Factory $factory, ContainerInterface $container)
    {
        $factory->setFormElementManager($container->get('FormElementManager'));

        if ($container->has('InputFilterManager')) {
            $inputFilters = $container->get('InputFilterManager');
            $factory->getInputFilterFactory()->setInputFilterManager($inputFilters);
        }
    }
}