[TASK] Update php-cs-fixer to 2.5.0
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / Rendering / RendererRegistry.php
1 <?php
2 namespace TYPO3\CMS\Core\Resource\Rendering;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Resource\FileInterface;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Class RendererRegistry
22 */
23 class RendererRegistry implements \TYPO3\CMS\Core\SingletonInterface
24 {
25 /**
26 * Registered class names
27 *
28 * @var array
29 */
30 protected $classNames = [];
31
32 /**
33 * Instance cache for renderer classes
34 *
35 * @var FileRendererInterface[]
36 */
37 protected $instances = null;
38
39 /**
40 * Returns an instance of this class
41 *
42 * @return RendererRegistry
43 */
44 public static function getInstance()
45 {
46 return GeneralUtility::makeInstance(self::class);
47 }
48
49 /**
50 * Allows to register a Renderer class
51 *
52 * @param string $className
53 * @throws \InvalidArgumentException
54 */
55 public function registerRendererClass($className)
56 {
57 if (!class_exists($className)) {
58 throw new \InvalidArgumentException('The class "' . $className . '" you are trying to register is not available', 1411840171);
59 }
60 if (!in_array(FileRendererInterface::class, class_implements($className), true)) {
61 throw new \InvalidArgumentException('The renderer needs to implement the FileRendererInterface', 1411840172);
62 }
63 $this->classNames[] = $className;
64 }
65
66 /**
67 * Get all registered renderer instances
68 *
69 * @return FileRendererInterface[]
70 */
71 public function getRendererInstances()
72 {
73 if ($this->instances === null) {
74 $this->instances = [];
75
76 // As the result is in reverse order we need to reverse
77 // the array before processing to keep the items with same
78 // priority in the same order as they were added to the registry.
79 $classNames = array_reverse($this->classNames);
80 foreach ($classNames as $className) {
81 /** @var FileRendererInterface $object */
82 $object = $this->createRendererInstance($className);
83 $this->instances[] = $object;
84 }
85
86 if (count($this->instances) > 1) {
87 usort($this->instances, [$this, 'compareRendererPriority']);
88 }
89 }
90 return $this->instances;
91 }
92
93 /**
94 * Create an instance of a certain renderer class
95 *
96 * @param string $className
97 * @return FileRendererInterface
98 */
99 protected function createRendererInstance($className)
100 {
101 return GeneralUtility::makeInstance($className);
102 }
103
104 /**
105 * Compare the priority of two renderer classes
106 * Is used for sorting array of Renderer instances by priority
107 * We want the result to be ordered from high to low so a higher
108 * priority comes before a lower.
109 *
110 * @param FileRendererInterface $rendererA
111 * @param FileRendererInterface $rendererB
112 * @return int -1 a > b, 0 a == b, 1 a < b
113 */
114 protected function compareRendererPriority(FileRendererInterface $rendererA, FileRendererInterface $rendererB)
115 {
116 return $rendererB->getPriority() - $rendererA->getPriority();
117 }
118
119 /**
120 * Get matching renderer with highest priority
121 *
122 * @param FileInterface $file
123 * @return NULL|FileRendererInterface
124 */
125 public function getRenderer(FileInterface $file)
126 {
127 $matchingFileRenderer = null;
128
129 /** @var FileRendererInterface $fileRenderer */
130 foreach ($this->getRendererInstances() as $fileRenderer) {
131 if ($fileRenderer->canRender($file)) {
132 $matchingFileRenderer = $fileRenderer;
133 break;
134 }
135 }
136 return $matchingFileRenderer;
137 }
138 }