0ad17e68c0cadbd8268542924ffe31bfe24d4ad9
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Property / PropertyMappingConfiguration.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Property;
3
4 /* *
5 * This script belongs to the Extbase framework *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License as published by the *
9 * Free Software Foundation, either version 3 of the License, or (at your *
10 * option) any later version. *
11 * *
12 * This script is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
14 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
15 * General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with the script. *
19 * If not, see http://www.gnu.org/licenses/lgpl.html *
20 * *
21 * The TYPO3 project - inspiring people to share! *
22 * */
23
24 /**
25 * Concrete configuration object for the PropertyMapper.
26 *
27 * @api
28 */
29 use TYPO3\CMS\Core\Core\ClassLoader;
30
31 class PropertyMappingConfiguration implements \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface {
32
33 /**
34 * Placeholder in property paths for multi-valued types
35 */
36 const PROPERTY_PATH_PLACEHOLDER = '*';
37
38 /**
39 * multi-dimensional array which stores type-converter specific configuration:
40 * 1. Dimension: Fully qualified class name of the type converter
41 * 2. Dimension: Configuration Key
42 * Value: Configuration Value
43 *
44 * @var array
45 */
46 protected $configuration;
47
48 /**
49 * Stores the configuration for specific child properties.
50 *
51 * @var array<\TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface>
52 */
53 protected $subConfigurationForProperty = array();
54
55 /**
56 * The parent PropertyMappingConfiguration. If a configuration value for the current entry is not found, we propagate the question to the parent.
57 *
58 * @var \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface
59 */
60 protected $parentConfiguration;
61
62 /**
63 * Keys which should be renamed
64 *
65 * @var array
66 */
67 protected $mapping = array();
68
69 /**
70 * @var \TYPO3\CMS\Extbase\Property\TypeConverterInterface
71 */
72 protected $typeConverter = NULL;
73
74 /**
75 * List of allowed property names to be converted
76 *
77 * @var array
78 */
79 protected $propertiesToBeMapped = array();
80
81 /**
82 * List of disallowed property names which will be ignored while property mapping
83 *
84 * @var array
85 */
86 protected $propertiesNotToBeMapped = array();
87
88 /**
89 * If TRUE, unknown properties will be mapped.
90 *
91 * @var boolean
92 */
93 protected $mapUnknownProperties = FALSE;
94
95 /**
96 * Set the parent PropertyMappingConfiguration. Only used internally!
97 *
98 * @param \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $parentConfiguration
99 *
100 * @return void
101 */
102 protected function setParent(\TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $parentConfiguration) {
103 $this->parentConfiguration = $parentConfiguration;
104 }
105
106 /**
107 * The behavior is as follows:
108 *
109 * - if a property has been explicitly forbidden using allowAllPropertiesExcept(...), it is directly rejected
110 * - if a property has been allowed using allowProperties(...), it is directly allowed.
111 * - if allowAllProperties* has been called, we allow unknown properties
112 * - else, return FALSE.
113 *
114 * @param string $propertyName
115 * @return boolean TRUE if the given propertyName should be mapped, FALSE otherwise.
116 * @api
117 */
118 public function shouldMap($propertyName) {
119 if (isset($this->propertiesNotToBeMapped[$propertyName])) {
120 return FALSE;
121 }
122 if (isset($this->propertiesToBeMapped[$propertyName])) {
123 return TRUE;
124 }
125 if (isset($this->subConfigurationForProperty[self::PROPERTY_PATH_PLACEHOLDER])) {
126 return TRUE;
127 }
128 return $this->mapUnknownProperties;
129 }
130
131 /**
132 * Allow all properties in property mapping, even unknown ones.
133 *
134 * @return void
135 * @api
136 */
137 public function allowAllProperties() {
138 $this->mapUnknownProperties = TRUE;
139 }
140
141 /**
142 * Allow a list of specific properties. All arguments of
143 * allowProperties are used here (varargs).
144 *
145 * Example: allowProperties('title', 'content', 'author')
146 *
147 * @return void
148 * @api
149 */
150 public function allowProperties() {
151 foreach (func_get_args() as $propertyName) {
152 $this->propertiesToBeMapped[$propertyName] = $propertyName;
153 }
154 }
155
156 /**
157 * Allow all properties during property mapping, but reject a few
158 * selected ones (blacklist).
159 *
160 * Example: allowAllPropertiesExcept('password', 'userGroup')
161 *
162 * @return void
163 * @api
164 */
165 public function allowAllPropertiesExcept() {
166 $this->mapUnknownProperties = TRUE;
167 foreach (func_get_args() as $propertyName) {
168 $this->propertiesNotToBeMapped[$propertyName] = $propertyName;
169 }
170 }
171
172 /**
173 * Returns the sub-configuration for the passed $propertyName. Must ALWAYS return a valid configuration object!
174 *
175 * @param string $propertyName
176 *
177 * @return \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface the property mapping configuration for the given $propertyName.
178 * @api
179 */
180 public function getConfigurationFor($propertyName) {
181 if (isset($this->subConfigurationForProperty[$propertyName])) {
182 return $this->subConfigurationForProperty[$propertyName];
183 }
184 return new \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration();
185 }
186
187 /**
188 * Maps the given $sourcePropertyName to a target property name.
189 *
190 * @param string $sourcePropertyName
191 *
192 * @return string property name of target
193 * @api
194 */
195 public function getTargetPropertyName($sourcePropertyName) {
196 if (isset($this->mapping[$sourcePropertyName])) {
197 return $this->mapping[$sourcePropertyName];
198 }
199 return $sourcePropertyName;
200 }
201
202 /**
203 * @param string $typeConverterClassName
204 * @param string $key
205 *
206 * @return mixed configuration value for the specific $typeConverterClassName. Can be used by Type Converters to fetch converter-specific configuration.
207 * @api
208 */
209 public function getConfigurationValue($typeConverterClassName, $key) {
210 if (!isset($this->configuration[$typeConverterClassName][$key])) {
211 return NULL;
212 }
213 return $this->configuration[$typeConverterClassName][$key];
214 }
215
216 /**
217 * Define renaming from Source to Target property.
218 *
219 * @param string $sourcePropertyName
220 * @param string $targetPropertyName
221 *
222 * @return void
223 * @api
224 */
225 public function setMapping($sourcePropertyName, $targetPropertyName) {
226 $this->mapping[$sourcePropertyName] = $targetPropertyName;
227 }
228
229 /**
230 * Set all options for the given $typeConverter.
231 *
232 * @param string $typeConverter class name of type converter
233 * @param array $options
234 *
235 * @return void
236 * @api
237 */
238 public function setTypeConverterOptions($typeConverter, array $options) {
239 if (strpos($typeConverter, '_') !== FALSE) {
240 $typeConverter = ClassLoader::getClassNameForAlias($typeConverter);
241 }
242 $this->configuration[$typeConverter] = $options;
243 }
244
245 /**
246 * Set a single option (denoted by $optionKey) for the given $typeConverter.
247 *
248 * @param string $typeConverter class name of type converter
249 * @param string $optionKey
250 * @param mixed $optionValue
251 *
252 * @return void
253 * @api
254 */
255 public function setTypeConverterOption($typeConverter, $optionKey, $optionValue) {
256 if (strpos($typeConverter, '_') !== FALSE) {
257 $typeConverter = ClassLoader::getClassNameForAlias($typeConverter);
258 }
259 $this->configuration[$typeConverter][$optionKey] = $optionValue;
260 }
261
262 /**
263 * Returns the configuration for the specific property path, ready to be modified. Should be used
264 * inside a fluent interface like:
265 * $configuration->forProperty('foo.bar')->setTypeConverterOption(....)
266 *
267 * @param string $propertyPath
268 *
269 * @return \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration (or a subclass thereof)
270 * @api
271 */
272 public function forProperty($propertyPath) {
273 $splittedPropertyPath = explode('.', $propertyPath);
274 return $this->traverseProperties($splittedPropertyPath);
275 }
276
277 /**
278 * Traverse the property configuration. Only used by forProperty().
279 *
280 * @param array $splittedPropertyPath
281 *
282 * @return \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration (or a subclass thereof)
283 */
284 public function traverseProperties(array $splittedPropertyPath) {
285 if (count($splittedPropertyPath) === 0) {
286 return $this;
287 }
288 $currentProperty = array_shift($splittedPropertyPath);
289 if (!isset($this->subConfigurationForProperty[$currentProperty])) {
290 $type = get_class($this);
291 $this->subConfigurationForProperty[$currentProperty] = new $type();
292 $this->subConfigurationForProperty[$currentProperty]->setParent($this);
293 }
294 return $this->subConfigurationForProperty[$currentProperty]->traverseProperties($splittedPropertyPath);
295 }
296
297 /**
298 * Return the type converter set for this configuration.
299 *
300 * @return \TYPO3\CMS\Extbase\Property\TypeConverterInterface
301 * @api
302 */
303 public function getTypeConverter() {
304 return $this->typeConverter;
305 }
306
307 /**
308 * Set a type converter which should be used for this specific conversion.
309 *
310 * @param \TYPO3\CMS\Extbase\Property\TypeConverterInterface $typeConverter
311 *
312 * @return void
313 * @api
314 */
315 public function setTypeConverter(\TYPO3\CMS\Extbase\Property\TypeConverterInterface $typeConverter) {
316 $this->typeConverter = $typeConverter;
317 }
318 }
319
320 ?>