TYPO3 CMS  TYPO3_7-6
MicroDataSchema.php
Go to the documentation of this file.
1 <?php
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 
19 
24 {
30  protected $pluginName = 'MicrodataSchema';
31 
37  protected $pluginButtons = 'showmicrodata';
38 
45  'showmicrodata' => 'ShowMicrodata'
46  ];
47 
53  public function buildJavascriptConfiguration()
54  {
55  $schema = [
56  'types' => [],
57  'properties' => []
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 = GeneralUtility::getUrl($fileName);
70  if ($rdf) {
71  $this->parseSchema($rdf, $schema);
72  }
73  }
74  }
75  uasort($schema['types'], [$this, 'compareLabels']);
76  uasort($schema['properties'], [$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'], ['name' => 'none', 'label' => $noSchema]);
82  array_unshift($schema['properties'], ['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 
94  protected function compareLabels($a, $b)
95  {
96  return strcoll($a['label'], $b['label']);
97  }
98 
106  protected function parseSchema($string, &$schema)
107  {
108  $types = [];
109  $properties = [];
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 = [];
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 }
writeTemporaryFile($label, $fileExtension='js', $contents='')
static getUrl($url, $includeHeader=0, $requestHeaders=false, &$report=null)
static getFileAbsFileName($filename, $onlyRelative=true, $relToTYPO3_mainDir=false)