-
-
Notifications
You must be signed in to change notification settings - Fork 188
/
ViewHelperResolver.php
160 lines (145 loc) · 5.4 KB
/
ViewHelperResolver.php
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
158
159
160
<?php
namespace Neos\FluidAdaptor\Core\ViewHelper;
/*
* This file is part of the Neos.FluidAdaptor package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/
use Neos\Flow\Annotations as Flow;
use Neos\Flow\ObjectManagement\ObjectManagerInterface;
use Neos\Flow\Package\Package;
use Neos\Flow\Package\PackageManager;
/**
* Class ViewHelperResolver
*
* Class whose purpose is dedicated to resolving classes which
* can be used as ViewHelpers and ExpressionNodes in Fluid.
*
* In addition to modifying the behavior or the parser when
* legacy mode is requested, this ViewHelperResolver is also
* made capable of "mixing" two different ViewHelper namespaces
* to effectively create aliases for the Fluid core ViewHelpers
* to be loaded in the (TYPO3|Neos) scope as well.
*
* @Flow\Scope("singleton")
*/
class ViewHelperResolver extends \TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperResolver
{
/**
* @Flow\Inject
* @var ObjectManagerInterface
*/
protected $objectManager;
/**
* @Flow\Inject
* @var PackageManager
*/
protected $packageManager;
/**
* Custom merged namespace for Neos Fluid adapter;
* will look for classes in both namespaces starting
* from the bottom.
*
* @var array
*/
protected $namespaces = [];
/**
* @Flow\InjectConfiguration(path="namespaces")
* @var array
*/
protected $namespacesFromConfiguration;
public function initializeObject($reason)
{
if ($reason === ObjectManagerInterface::INITIALIZATIONCAUSE_RECREATED) {
return;
}
/** @var Package $package */
foreach ($this->packageManager->getAvailablePackages() as $package) {
foreach ($package->getNamespaces() as $namespace) {
$viewHelperNamespace = $namespace;
if (strpos(strrev($namespace), '\\') !== 0) {
$viewHelperNamespace .= '\\';
}
$viewHelperNamespace .= 'ViewHelpers';
$this->addNamespace(strtolower($package->getPackageKey()), $viewHelperNamespace);
}
}
foreach ($this->namespacesFromConfiguration as $identifier => $namespace) {
$this->addNamespace($identifier, $namespace);
}
}
/**
* @param string $viewHelperClassName
* @return \TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperInterface
*/
public function createViewHelperInstanceFromClassName($viewHelperClassName)
{
return $this->objectManager->get($viewHelperClassName);
}
/**
* Add a PHP namespace where ViewHelpers can be found and give
* it an alias/identifier.
*
* The provided namespace can be either a single namespace or
* an array of namespaces, as strings. The identifier/alias is
* always a single, alpha-numeric ASCII string.
*
* Calling this method multiple times with different PHP namespaces
* for the same alias causes that namespace to be *extended*,
* meaning that the PHP namespace you provide second, third etc.
* are also used in lookups and are used *first*, so that if any
* of the namespaces you add contains a class placed and named the
* same way as one that exists in an earlier namespace, then your
* class gets used instead of the earlier one.
*
* Example:
*
* $resolver->addNamespace('my', 'My\Package\ViewHelpers');
* // Any ViewHelpers under this namespace can now be accessed using for example {my:example()}
* // Now, assuming you also have an ExampleViewHelper class in a different
* // namespace and wish to make that ExampleViewHelper override the other:
* $resolver->addNamespace('my', 'My\OtherPackage\ViewHelpers');
* // Now, since ExampleViewHelper exists in both places but the
* // My\OtherPackage\ViewHelpers namespace was added *last*, Fluid
* // will find and use My\OtherPackage\ViewHelpers\ExampleViewHelper.
*
* Alternatively, setNamespaces() can be used to reset and redefine
* all previously added namespaces - which is great for cases where
* you need to remove or replace previously added namespaces. Be aware
* that setNamespaces() also removes the default "f" namespace, so
* when you use this method you should always include the "f" namespace.
*
* @param string $identifier
* @param string|array $phpNamespace
* @return void
*/
public function addNamespace($identifier, $phpNamespace)
{
if ($phpNamespace === null) {
$this->namespaces[$identifier] = null;
return;
}
if (!is_array($phpNamespace)) {
$this->addNamespaceInternal($identifier, $phpNamespace);
return;
}
foreach ($phpNamespace as $namespace) {
$this->addNamespaceInternal($identifier, $namespace);
}
}
/**
* @param string $identifier
* @param string $phpNamespace
*/
protected function addNamespaceInternal($identifier, $phpNamespace)
{
if (!isset($this->namespaces[$identifier])) {
$this->namespaces[$identifier] = [];
}
$this->namespaces[$identifier] = array_unique(array_merge($this->namespaces[$identifier], [$phpNamespace]));
}
}