[TASK] Use file_get_contents instead of getUrl()
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / Extension / MicroDataSchema.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea\Extension;
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\Utility\GeneralUtility;
18 use TYPO3\CMS\Rtehtmlarea\RteHtmlAreaApi;
19
20 /**
21 * Microdata Schema extension for htmlArea RTE
22 */
23 class MicroDataSchema extends RteHtmlAreaApi
24 {
25 /**
26 * The name of the plugin registered by the extension
27 *
28 * @var string
29 */
30 protected $pluginName = 'MicrodataSchema';
31
32 /**
33 * The comma-separated list of button names that the registered plugin is adding to the htmlArea RTE toolbar
34 *
35 * @var string
36 */
37 protected $pluginButtons = 'showmicrodata';
38
39 /**
40 * The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
41 *
42 * @var array
43 */
44 protected $convertToolbarForHtmlAreaArray = array(
45 'showmicrodata' => 'ShowMicrodata'
46 );
47
48 /**
49 * Return JS configuration of the htmlArea plugins registered by the extension
50 *
51 * @return string JS configuration for registered plugins
52 */
53 public function buildJavascriptConfiguration()
54 {
55 $schema = array(
56 'types' => array(),
57 'properties' => array()
58 );
59 // Parse configured schemas
60 if (is_array($this->configuration['thisConfig']['schema.']) && is_array($this->configuration['thisConfig']['schema.']['sources.'])) {
61 foreach ($this->configuration['thisConfig']['schema.']['sources.'] as $source) {
62 $fileName = trim($source);
63 $absolutePath = GeneralUtility::getFileAbsFileName($fileName);
64 // Fallback to default schema file if configured file does not exists or is of zero size
65 if (!$fileName || !file_exists($absolutePath) || !filesize($absolutePath)) {
66 $fileName = 'EXT:' . $this->extensionKey . '/Resources/Public/Rdf/MicrodataSchema/SchemaOrgAll.rdf';
67 }
68 $fileName = $this->getFullFileName($fileName);
69 $rdf = file_get_contents($fileName);
70 if ($rdf) {
71 $this->parseSchema($rdf, $schema);
72 }
73 }
74 }
75 uasort($schema['types'], array($this, 'compareLabels'));
76 uasort($schema['properties'], array($this, 'compareLabels'));
77 // Insert no type and no property entries
78 $languageService = $this->getLanguageService();
79 $noSchema = $languageService->sL('LLL:EXT:rtehtmlarea/Resources/Private/Language/Plugins/MicrodataSchema/locallang.xlf:No type');
80 $noProperty = $languageService->sL('LLL:EXT:rtehtmlarea/Resources/Private/Language/Plugins/MicrodataSchema/locallang.xlf:No property');
81 array_unshift($schema['types'], array('name' => 'none', 'label' => $noSchema));
82 array_unshift($schema['properties'], array('name' => 'none', 'label' => $noProperty));
83 // Store json encoded array in temporary file
84 return 'RTEarea[editornumber].schemaUrl = "' . $this->writeTemporaryFile('schema_' . $this->configuration['language'], 'js', json_encode($schema)) . '";';
85 }
86
87 /**
88 * Compare the labels of two schema types or properties for localized sort purposes
89 *
90 * @param array $a: first type/property definition array
91 * @param array $b: second type/property definition array
92 * @return int
93 */
94 protected function compareLabels($a, $b)
95 {
96 return strcoll($a['label'], $b['label']);
97 }
98
99 /**
100 * Convert the xml rdf schema into an array
101 *
102 * @param string $string XML rdf schema to convert into an array
103 * @param array $schema: reference to the array to be filled
104 * @return void
105 */
106 protected function parseSchema($string, &$schema)
107 {
108 $types = array();
109 $properties = array();
110 // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
111 $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
112 // Load the document
113 $document = new \DOMDocument();
114 $document->loadXML($string);
115 libxml_disable_entity_loader($previousValueOfEntityLoader);
116 if ($document) {
117 // Scan resource descriptions
118 $items = $document->getElementsByTagName('Description');
119 foreach ($items as $item) {
120 $name = $item->getAttribute('rdf:about');
121 $type = $item->getElementsByTagName('type');
122 if ($name && $type->length) {
123 $type = $type->item(0)->getAttribute('rdf:resource');
124 $resource = array();
125 $resource['name'] = $name;
126 $labels = $item->getElementsByTagName('label');
127 if ($labels->length) {
128 foreach ($labels as $label) {
129 $language = $label->getAttribute('xml:lang');
130 if ($language === $this->language) {
131 $resource['label'] = $label->nodeValue;
132 } elseif ($language === 'en') {
133 $defaultLabel = $label->nodeValue;
134 }
135 }
136 if (!$resource['label']) {
137 $resource['label'] = $defaultLabel;
138 }
139 }
140 $comments = $item->getElementsByTagName('comment');
141 if ($comments->length) {
142 foreach ($comments as $comment) {
143 $language = $comment->getAttribute('xml:lang');
144 if ($language === $this->language) {
145 $resource['comment'] = $comment->nodeValue;
146 } elseif ($language === 'en') {
147 $defaultComment = $comment->nodeValue;
148 }
149 }
150 if (!$resource['comment']) {
151 $resource['comment'] = $defaultComment;
152 }
153 }
154 switch ($type) {
155 case 'http://www.w3.org/2000/01/rdf-schema#Class':
156 $subClassOfs = $item->getElementsByTagName('subClassOf');
157 if ($subClassOfs->length) {
158 foreach ($subClassOfs as $subClassOf) {
159 $resource['subClassOf'] = $subClassOf->getAttribute('rdf:resource');
160 }
161 }
162 // schema.rdfs.org/all.rdf may contain duplicates!!
163 if (!in_array($resource['name'], $types)) {
164 $schema['types'][] = $resource;
165 $types[] = $resource['name'];
166 }
167 break;
168 case 'http://www.w3.org/1999/02/22-rdf-syntax-ns#Property':
169 // Keep only the last level of the name
170 // This is the value we want in the itemprop attribute
171 $pos = strrpos($resource['name'], '/');
172 if ($pos) {
173 $resource['name'] = substr($resource['name'], $pos + 1);
174 }
175 $domains = $item->getElementsByTagName('domain');
176 if ($domains->length) {
177 foreach ($domains as $domain) {
178 $resource['domain'] = $domain->getAttribute('rdf:resource');
179 }
180 }
181 $ranges = $item->getElementsByTagName('range');
182 if ($ranges->length) {
183 foreach ($ranges as $range) {
184 $resource['range'] = $range->getAttribute('rdf:resource');
185 }
186 }
187 // schema.rdfs.org/all.rdf may contain duplicates!!
188 if (!in_array($resource['name'], $properties)) {
189 $schema['properties'][] = $resource;
190 $properties[] = $resource['name'];
191 }
192 break;
193 default:
194 // Do nothing
195 }
196 }
197 }
198 }
199 }
200 }