[FEATURE] htmlArea RTE: Edit HTML5 microdata items
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / extensions / MicrodataSchema / class.tx_rtehtmlarea_microdataschema.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2012 Stanislas Rolland <typo3(arobas)sjbr.ca>
6 * All rights reserved
7 *
8 * This script is part of the Typo3 project. The Typo3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24 /**
25 * Microdata Schema extension for htmlArea RTE
26 *
27 * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
28 *
29 */
30 class tx_rtehtmlarea_microdataschema extends tx_rtehtmlarea_api {
31 // The key of the TYPO3 extension that is extending htmlArea RTE
32 protected $extensionKey = 'rtehtmlarea';
33 // The name of the plugin registered by the extension
34 protected $pluginName = 'MicrodataSchema';
35 // Path to this main locallang file of the extension relative to the extension dir.
36 protected $relativePathToLocallangFile = 'extensions/MicrodataSchema/locallang.xlf';
37 // Path to the skin (css) file relative to the extension dir
38 protected $relativePathToSkin = 'extensions/MicrodataSchema/skin/htmlarea.css';
39 protected $htmlAreaRTE; // Reference to the invoking object
40 protected $thisConfig; // Reference to RTE PageTSConfig
41 protected $toolbar; // Reference to RTE toolbar array
42 protected $LOCAL_LANG; // Frontend language array
43
44 protected $pluginButtons = 'showmicrodata';
45 protected $convertToolbarForHtmlAreaArray = array (
46 'showmicrodata' => 'ShowMicrodata',
47 );
48
49 /**
50 * Return JS configuration of the htmlArea plugins registered by the extension
51 *
52 * @param integer Relative id of the RTE editing area in the form
53 *
54 * @return string JS configuration for registered plugins
55 *
56 * The returned string will be a set of JS instructions defining the configuration that will be provided to the plugin(s)
57 * Each of the instructions should be of the form:
58 * RTEarea['.$RTEcounter.']["buttons"]["button-id"]["property"] = "value";
59 */
60 public function buildJavascriptConfiguration($RTEcounter) {
61 $registerRTEinJavascriptString = '';
62 $schema = array(
63 'types' => array(),
64 'properties' => array(),
65 );
66 // Parse configured schemas
67 if (is_array($this->thisConfig['schema.']) && is_array($this->thisConfig['schema.']['sources.'])) {
68 foreach ($this->thisConfig['schema.']['sources.'] as $source) {
69 $fileName = $this->htmlAreaRTE->getFullFileName($source);
70 $absolutePath = $fileName
71 ? t3lib_div::resolveBackPath(PATH_site . (($this->htmlAreaRTE->is_FE() || $this->htmlAreaRTE->isFrontendEditActive()) ? '' : TYPO3_mainDir) . $fileName)
72 : '';
73 // Fallback to default schema file if configured file does not exists or is of zero size
74 if (!$fileName || !file_exists($absolutePath) || !filesize($absolutePath)) {
75 $fileName = $this->htmlAreaRTE->getFullFileName('EXT:' . $this->ID . '/extensions/MicrodataSchema/res/schemaOrgAll.rdf');
76 }
77 $rdf = t3lib_div::getUrl($fileName);
78 if ($rdf) {
79 $this->parseSchema($rdf, $schema);
80 }
81 }
82 }
83 // Sort the types and properties
84 function compareLabel($a, $b) {
85 return strcoll($a['label'], $b['label']);
86 }
87 uasort($schema['types'], 'compareLabel');
88 uasort($schema['properties'], 'compareLabel');
89 // Insert no type and no property entries
90 if ($this->htmlAreaRTE->is_FE()) {
91 $noSchema = $GLOBALS['TSFE']->getLLL('No type', $this->LOCAL_LANG);
92 $noProperty = $GLOBALS['TSFE']->getLLL('No property', $this->LOCAL_LANG);
93 } else {
94 $noSchema = $GLOBALS['LANG']->getLL('No type');
95 $noProperty = $GLOBALS['LANG']->getLL('No property');
96 }
97 array_unshift($schema['types'], array('name' => 'none', 'label' => $noSchema));
98 array_unshift($schema['properties'], array('name' => 'none', 'label' => $noProperty));
99 // Convert character set
100 if ($this->htmlAreaRTE->is_FE()) {
101 $GLOBALS['TSFE']->csConvObj->convArray($schema, $this->htmlAreaRTE->outputCharset, 'utf-8');
102 } else {
103 $GLOBALS['LANG']->csConvObj->convArray($schema, $GLOBALS['LANG']->charSet, 'utf-8');
104 }
105 // Store json encoded array in temporary file
106 $registerRTEinJavascriptString = LF. TAB . 'RTEarea[editornumber].schemaUrl = "' . (($this->htmlAreaRTE->is_FE() && $GLOBALS['TSFE']->absRefPrefix) ? $GLOBALS['TSFE']->absRefPrefix : '') . $this->htmlAreaRTE->writeTemporaryFile('', 'schema_' . $this->htmlAreaRTE->language, 'js', json_encode($schema), TRUE) . '";';
107 return $registerRTEinJavascriptString;
108 }
109 /**
110 * Convert the xml rdf schema into an array
111 *
112 * @param string $string XML rdf schema to convert into an array
113 * @param array $schema: reference to the array to be filled
114 * @return void
115 */
116 protected function parseSchema($string, &$schema) {
117 $resources = array();
118 $types = array();
119 $properties = array();
120 // Load the document
121 $document = new DOMDocument();
122 $document->loadXML($string);
123 if ($document) {
124 // Scan resource descriptions
125 $items = $document->getElementsByTagName('Description');
126 $itemsCount = $items->length;
127 foreach ($items as $item) {
128 $name = $item->getAttribute('rdf:about');
129 $type = $item->getElementsByTagName('type');
130 if ($name && $type->length) {
131 $type = $type->item(0)->getAttribute('rdf:resource');
132 $resource = array();
133 $resource['name'] = $name;
134 $labels = $item->getElementsByTagName('label');
135 if ($labels->length) {
136 foreach ($labels as $label) {
137 $language = $label->getAttribute('xml:lang');
138 if ($language === $this->language) {
139 $resource['label'] = $label->nodeValue;
140 } elseif ($language === 'en') {
141 $defaultLabel = $label->nodeValue;
142 }
143 }
144 if (!$resource['label']) {
145 $resource['label'] = $defaultLabel;
146 }
147 }
148 $comments = $item->getElementsByTagName('comment');
149 if ($comments->length) {
150 foreach ($comments as $comment) {
151 $language = $comment->getAttribute('xml:lang');
152 if ($language === $this->language) {
153 $resource['comment'] = $comment->nodeValue;
154 } elseif ($language === 'en') {
155 $defaultComment = $comment->nodeValue;
156 }
157 }
158 if (!$resource['comment']) {
159 $resource['comment'] = $defaultComment;
160 }
161 }
162 switch ($type) {
163 case 'http://www.w3.org/2000/01/rdf-schema#Class':
164 $subClassOfs = $item->getElementsByTagName('subClassOf');
165 if ($subClassOfs->length) {
166 foreach ($subClassOfs as $subClassOf) {
167 $resource['subClassOf'] = $subClassOf->getAttribute('rdf:resource');
168 }
169 }
170 // schema.rdfs.org/all.rdf may contain duplicates!!
171 if (!in_array($resource['name'], $types)) {
172 $schema['types'][] = $resource;
173 $types[] = $resource['name'];
174 }
175 break;
176 case 'http://www.w3.org/1999/02/22-rdf-syntax-ns#Property':
177 // Keep only the last level of the name
178 // This is the value we want in the itemprop attribute
179 $pos = strrpos($resource['name'], '/');
180 if ($pos) {
181 $resource['name'] = substr($resource['name'], $pos+1);
182 }
183 $domains = $item->getElementsByTagName('domain');
184 if ($domains->length) {
185 foreach ($domains as $domain) {
186 $resource['domain'] = $domain->getAttribute('rdf:resource');
187 }
188 }
189 $ranges = $item->getElementsByTagName('range');
190 if ($ranges->length) {
191 foreach ($ranges as $range) {
192 $resource['range'] = $range->getAttribute('rdf:resource');
193 }
194 }
195 // schema.rdfs.org/all.rdf may contain duplicates!!
196 if (!in_array($resource['name'], $properties)) {
197 $schema['properties'][] = $resource;
198 $properties[] = $resource['name'];
199 }
200 $break;
201 }
202 }
203 }
204 }
205 }
206 }
207 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/MicrodataSchema/class.tx_rtehtmlarea_microdataschema.php'])) {
208 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/MicrodataSchema/class.tx_rtehtmlarea_microdataschema.php']);
209 }
210 ?>