MailViewRendererFactory::__invoke()   B
last analyzed

Complexity

Conditions 6
Paths 10

Size

Total Lines 42
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 42
c 0
b 0
f 0
rs 8.439
cc 6
eloc 19
nc 10
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace AcMailer\View;
5
6
use Interop\Container\ContainerInterface as InteropContainer;
7
use Psr\Container\ContainerExceptionInterface;
8
use Psr\Container\ContainerInterface;
9
use Psr\Container\NotFoundExceptionInterface;
10
use Zend\Expressive\Template\TemplateRendererInterface;
11
use Zend\Mvc\Service\ViewHelperManagerFactory;
12
use Zend\ServiceManager\Config;
13
use Zend\View\Exception\InvalidArgumentException;
14
use Zend\View\HelperPluginManager;
15
use Zend\View\Renderer\PhpRenderer;
16
use Zend\View\Renderer\RendererInterface;
17
use Zend\View\Resolver\AggregateResolver;
18
use Zend\View\Resolver\ResolverInterface;
19
use Zend\View\Resolver\TemplateMapResolver;
20
use Zend\View\Resolver\TemplatePathStack;
21
22
class MailViewRendererFactory
23
{
24
    const SERVICE_NAME = 'AcMailer\MailViewRenderer';
25
26
    /**
27
     * @param ContainerInterface $container
28
     * @return TemplateRendererInterface
29
     * @throws NotFoundExceptionInterface
30
     * @throws InvalidArgumentException
31
     * @throws ContainerExceptionInterface
32
     */
33
    public function __invoke(ContainerInterface $container): TemplateRendererInterface
34
    {
35
        // First, if the TemplateRendererInterface is registered as a service, use that service.
36
        // This should be true in expressive applications
37
        if ($container->has(TemplateRendererInterface::class)) {
38
            return $container->get(TemplateRendererInterface::class);
39
        }
40
41
        // If the mailviewrenderer is registered, wrap it into a ZendViewRenderer
42
        // This should be true in Zend/MVC apps, run in a HTTP context
43
        if ($container->has('mailviewrenderer')) {
44
            return $this->wrapZendView($container->get('mailviewrenderer'));
45
        }
46
47
        // Finally, create a zend/view PhpRenderer and wrap it into a ZendViewRenderer
48
        // This should be reached only in Zend/MVC apps run in a CLI context
49
        $vmConfig = $this->getSpecificConfig($container, 'view_manager');
50
        $renderer = new PhpRenderer();
51
52
        // Check what kind of view_manager configuration has been defined
53
        $resolversStack = [];
54
        if (isset($vmConfig['template_map'])) {
55
            // Create a TemplateMapResolver in case only the template_map has been defined
56
            $resolversStack[] = new TemplateMapResolver($vmConfig['template_map']);
57
        }
58
        if (isset($vmConfig['template_path_stack'])) {
59
            // Create a TemplatePathStack resolver in case only the template_path_stack has been defined
60
            $pathStackResolver = new TemplatePathStack();
61
            $pathStackResolver->setPaths($vmConfig['template_path_stack']);
62
            $resolversStack[] = $pathStackResolver;
63
        }
64
65
        // Create the template resolver for the PhpRenderer
66
        $resolver = $this->buildTemplateResolverFromStack($resolversStack);
67
        if ($resolver !== null) {
68
            $renderer->setResolver($resolver);
69
        }
70
71
        // Create a HelperPluginManager with default view helpers and user defined view helpers
72
        $renderer->setHelperPluginManager($this->createHelperPluginManager($container));
73
        return $this->wrapZendView($renderer);
74
    }
75
76
    private function wrapZendView(RendererInterface $renderer): TemplateRendererInterface
77
    {
78
        return new SimpleZendViewRenderer($renderer);
79
    }
80
81
    /**
82
     * Creates a view helper manager
83
     * @param ContainerInterface|InteropContainer $container
84
     * @return HelperPluginManager
85
     * @throws ContainerExceptionInterface
86
     */
87
    private function createHelperPluginManager(ContainerInterface $container): HelperPluginManager
88
    {
89
        $factory = new ViewHelperManagerFactory();
90
        /** @var HelperPluginManager $helperManager */
91
        $helperManager = $factory($container, ViewHelperManagerFactory::PLUGIN_MANAGER_CLASS);
92
        $config = new Config($this->getSpecificConfig($container, 'view_helpers'));
93
        $config->configureServiceManager($helperManager);
94
        return $helperManager;
95
    }
96
97
    /**
98
     * Returns a specific configuration defined by provided key
99
     * @param ContainerInterface $container
100
     * @param string $configKey
101
     * @return array
102
     * @throws ContainerExceptionInterface
103
     */
104
    private function getSpecificConfig(ContainerInterface $container, string $configKey): array
105
    {
106
        return $container->get('config')[$configKey] ?? [];
107
    }
108
109
    /**
110
     * @param array $resolversStack
111
     * @return ResolverInterface|null
112
     */
113
    private function buildTemplateResolverFromStack(array $resolversStack)
114
    {
115
        if (empty($resolversStack)) {
116
            return null;
117
        }
118
119
        if (\count($resolversStack) === 1) {
120
            return \array_shift($resolversStack);
121
        }
122
123
        // Attach all resolvers to the aggregate, if there's more than one
124
        $aggregateResolver = new AggregateResolver();
125
        foreach ($resolversStack as $resolver) {
126
            $aggregateResolver->attach($resolver);
127
        }
128
        return $aggregateResolver;
129
    }
130
}
131