2 declare(strict_types
= 1);
4 namespace TYPO3\CMS\Core\MetaTag
;
7 * This file is part of the TYPO3 CMS project.
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
16 * The TYPO3 project - inspiring people to share!
19 use TYPO3\CMS\Core\SingletonInterface
;
21 abstract class AbstractMetaTagManager
implements MetaTagManagerInterface
, SingletonInterface
24 * The default attribute that defines the name of the property
26 * This creates tags like <meta name="" /> by default
30 protected $defaultNameAttribute = 'name';
33 * The default attribute that defines the content
35 * This creates tags like <meta content="" /> by default
39 protected $defaultContentAttribute = 'content';
42 * Set if by default it is possible to have multiple occurrences of properties of this manager
46 protected $defaultAllowMultipleOccurrences = false;
49 * The separator to define subproperties like og:image:width
53 protected $subPropertySeparator = ':';
56 * Array of properties that can be handled by this manager
60 * $handledProperties = [
63 * 'allowMultipleOccurrences' => true,
64 * 'allowedSubProperties' => [
74 * 'allowedSubProperties' => [
76 * 'allowMultipleOccurrences' => true
84 protected $handledProperties = [];
87 * Array of properties that are set by the manager
91 protected $properties = [];
96 * @param string $property Name of the property
97 * @param string $content Content of the property
98 * @param array $subProperties Optional subproperties
99 * @param bool $replace Replace the currently set value
100 * @param string $type Optional type of property (name, property, http-equiv)
102 * @throws \UnexpectedValueException
104 public function addProperty(string $property, string $content, array $subProperties = [], bool $replace = false, string $type = '')
106 $property = strtolower($property);
108 if (isset($this->handledProperties
[$property])) {
109 $subPropertiesArray = [];
110 foreach ($subProperties as $subPropertyKey => $subPropertyValue) {
111 if (isset($this->handledProperties
[$property]['allowedSubProperties'][$subPropertyKey])) {
112 $subPropertiesArray[$subPropertyKey] = is_array($subPropertyValue) ?
$subPropertyValue : [$subPropertyValue];
115 if (!isset($this->properties
[$property]) ||
empty($this->properties
[$property])) {
116 $this->properties
[$property][] = ['content' => $content, 'subProperties' => $subPropertiesArray];
118 if ($replace === true) {
119 $this->removeProperty($property, $type);
120 $this->properties
[$property][] = ['content' => $content, 'subProperties' => $subPropertiesArray];
124 if (isset($this->handledProperties
[$property]['allowMultipleOccurrences']) &&
125 (bool)$this->handledProperties
[$property]['allowMultipleOccurrences']
127 $this->properties
[$property][] = ['content' => $content, 'subProperties' => $subPropertiesArray];
131 // Check if there is an allowed subproperty that can handle the given property
132 foreach ($this->handledProperties
as $handledProperty => $handledPropertyConfig) {
133 if (!isset($handledPropertyConfig['allowedSubProperties'])) {
136 foreach ((array)$handledPropertyConfig['allowedSubProperties'] as $allowedSubProperty => $allowedSubPropertyConfig) {
137 $propertyKey = is_array($allowedSubPropertyConfig) ?
$allowedSubProperty : $allowedSubPropertyConfig;
139 if ($property !== $handledProperty . $this->subPropertySeparator
. $propertyKey ||
140 !isset($this->properties
[$handledProperty])
145 $propertyArrayKeys = array_keys($this->properties
[$handledProperty]);
146 $lastIndex = end($propertyArrayKeys);
148 if (!isset($this->properties
[$handledProperty][$lastIndex]['subProperties'][$propertyKey])) {
149 $this->properties
[$handledProperty][$lastIndex]['subProperties'][$propertyKey][] = $content;
151 if ($replace === true) {
152 unset($this->properties
[$handledProperty][$lastIndex]['subProperties'][$propertyKey]);
153 $this->properties
[$handledProperty][$lastIndex]['subProperties'][$propertyKey][] = $content;
157 if (is_array($allowedSubPropertyConfig) &&
158 isset($allowedSubPropertyConfig['allowMultipleOccurrences']) &&
159 (bool)$allowedSubPropertyConfig['allowMultipleOccurrences']
161 $this->properties
[$handledProperty][$lastIndex]['subProperties'][$propertyKey][] = $content;
169 throw new \
UnexpectedValueException(
170 sprintf('This MetaTagManager can\'t handle property "%s"', $property),
177 * Returns an array with all properties that can be handled by this manager
181 public function getAllHandledProperties(): array
183 return $this->handledProperties
;
187 * Get a specific property that is set before
189 * @param string $property Name of the property
190 * @param string $type Optional type of property (name, property, http-equiv)
193 public function getProperty(string $property, string $type = ''): array
195 $property = strtolower($property);
197 if (isset($this->properties
[$property])) {
198 return $this->properties
[$property];
205 * Render a meta tag for a specific property
207 * @param string $property Name of the property
210 public function renderProperty(string $property): string
212 $property = strtolower($property);
215 $nameAttribute = $this->defaultNameAttribute
;
216 if (isset($this->handledProperties
[$property]['nameAttribute'])
217 && !empty((string)$this->handledProperties
[$property]['nameAttribute'])) {
218 $nameAttribute = (string)$this->handledProperties
[$property]['nameAttribute'];
221 $contentAttribute = $this->defaultContentAttribute
;
222 if (isset($this->handledProperties
[$property]['contentAttribute'])
223 && !empty((string)$this->handledProperties
[$property]['contentAttribute'])) {
224 $contentAttribute = (string)$this->handledProperties
[$property]['contentAttribute'];
227 if ($nameAttribute && $contentAttribute) {
228 foreach ($this->getProperty($property) as $propertyItem) {
229 $metaTags[] = '<meta ' .
230 htmlspecialchars($nameAttribute) . '="' . htmlspecialchars($property) . '" ' .
231 htmlspecialchars($contentAttribute) . '="' . htmlspecialchars($propertyItem['content']) . '" />';
233 if (!count($propertyItem['subProperties'])) {
236 foreach ($propertyItem['subProperties'] as $subProperty => $subPropertyItems) {
237 foreach ($subPropertyItems as $subPropertyItem) {
238 $metaTags[] = '<meta ' .
239 htmlspecialchars($nameAttribute) . '="' . htmlspecialchars($property . $this->subPropertySeparator
. $subProperty) . '" ' .
240 htmlspecialchars($contentAttribute) . '="' . htmlspecialchars((string)$subPropertyItem) . '" />';
246 return implode(PHP_EOL
, $metaTags);
250 * Render all registered properties of this manager
254 public function renderAllProperties(): string
257 foreach (array_keys($this->properties
) as $property) {
258 $metatags[] = $this->renderProperty($property);
261 return implode(PHP_EOL
, $metatags);
265 * Remove one property from the MetaTagManager
266 * If there are multiple occurrences of a property, they all will be removed
268 * @param string $property
269 * @param string $type
271 public function removeProperty(string $property, string $type = '')
273 $property = strtolower($property);
275 unset($this->properties
[$property]);
279 * Unset all properties of this MetaTagManager
281 public function removeAllProperties()
283 $this->properties
= [];
287 * Check if this manager can handle the given property
289 * @param string $property Name of property to check (eg. og:title)
292 public function canHandleProperty(string $property): bool
294 if (isset($this->handledProperties
[$property])) {
298 foreach ($this->handledProperties
as $handledProperty => $handledPropertyConfig) {
299 foreach ((array)$handledPropertyConfig['allowedSubProperties'] as $allowedSubProperty => $allowedSubPropertyConfig) {
300 $propertyKey = is_array($allowedSubPropertyConfig) ?
$allowedSubProperty : $allowedSubPropertyConfig;
301 if ($property === $handledProperty . $this->subPropertySeparator
. $propertyKey) {