1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Document
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE.txt
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * OpenSearch class, provides an easy interface to display an OpenSearch document
14 *
15 * @link http://www.opensearch.org/
16 * @since 11.1
17 */
18 class JDocumentOpensearch extends JDocument
19 {
20 /**
21 * ShortName element
22 *
23 * required
24 *
25 * @var string
26 * @since 11.1
27 */
28 private $_shortName = '';
29
30 /**
31 * Images collection
32 *
33 * optional
34 *
35 * @var object
36 * @since 11.1
37 */
38 private $_images = array();
39
40 /**
41 * The url collection
42 *
43 * @var array
44 * @since 11.1
45 */
46 private $_urls = array();
47
48 /**
49 * Class constructor
50 *
51 * @param array $options Associative array of options
52 *
53 * @since 11.1
54 */
55 public function __construct($options = array())
56 {
57 parent::__construct($options);
58
59 // Set document type
60 $this->_type = 'opensearch';
61
62 // Set mime type
63 $this->_mime = 'application/opensearchdescription+xml';
64
65 // Add the URL for self updating
66 $update = new JOpenSearchUrl;
67 $update->type = 'application/opensearchdescription+xml';
68 $update->rel = 'self';
69 $update->template = JRoute::_(JUri::getInstance());
70 $this->addUrl($update);
71
72 // Add the favicon as the default image
73 // Try to find a favicon by checking the template and root folder
74 $app = JFactory::getApplication();
75 $dirs = array(JPATH_THEMES . '/' . $app->getTemplate(), JPATH_BASE);
76
77 foreach ($dirs as $dir)
78 {
79 if (file_exists($dir . '/favicon.ico'))
80 {
81 $path = str_replace(JPATH_BASE, '', $dir);
82 $path = str_replace('\\', '/', $path);
83 $favicon = new JOpenSearchImage;
84
85 if ($path == '')
86 {
87 $favicon->data = JUri::base() . 'favicon.ico';
88 }
89 else
90 {
91 if ($path[0] == '/')
92 {
93 $path = substr($path, 1);
94 }
95
96 $favicon->data = JUri::base() . $path . '/favicon.ico';
97 }
98
99 $favicon->height = '16';
100 $favicon->width = '16';
101 $favicon->type = 'image/vnd.microsoft.icon';
102
103 $this->addImage($favicon);
104
105 break;
106 }
107 }
108 }
109
110 /**
111 * Render the document
112 *
113 * @param boolean $cache If true, cache the output
114 * @param array $params Associative array of attributes
115 *
116 * @return The rendered data
117 *
118 * @since 11.1
119 */
120 public function render($cache = false, $params = array())
121 {
122 $xml = new DOMDocument('1.0', 'utf-8');
123
124 if (defined('JDEBUG') && JDEBUG)
125 {
126 $xml->formatOutput = true;
127 }
128
129 // The OpenSearch Namespace
130 $osns = 'http://a9.com/-/spec/opensearch/1.1/';
131
132 // Create the root element
133 $elOs = $xml->createElementNs($osns, 'OpenSearchDescription');
134
135 $elShortName = $xml->createElementNs($osns, 'ShortName');
136 $elShortName->appendChild($xml->createTextNode(htmlspecialchars($this->_shortName)));
137 $elOs->appendChild($elShortName);
138
139 $elDescription = $xml->createElementNs($osns, 'Description');
140 $elDescription->appendChild($xml->createTextNode(htmlspecialchars($this->description)));
141 $elOs->appendChild($elDescription);
142
143 // Always set the accepted input encoding to UTF-8
144 $elInputEncoding = $xml->createElementNs($osns, 'InputEncoding');
145 $elInputEncoding->appendChild($xml->createTextNode('UTF-8'));
146 $elOs->appendChild($elInputEncoding);
147
148 foreach ($this->_images as $image)
149 {
150 $elImage = $xml->createElementNs($osns, 'Image');
151 $elImage->setAttribute('type', $image->type);
152 $elImage->setAttribute('width', $image->width);
153 $elImage->setAttribute('height', $image->height);
154 $elImage->appendChild($xml->createTextNode(htmlspecialchars($image->data)));
155 $elOs->appendChild($elImage);
156 }
157
158 foreach ($this->_urls as $url)
159 {
160 $elUrl = $xml->createElementNs($osns, 'Url');
161 $elUrl->setAttribute('type', $url->type);
162
163 // Results is the default value so we don't need to add it
164 if ($url->rel != 'results')
165 {
166 $elUrl->setAttribute('rel', $url->rel);
167 }
168
169 $elUrl->setAttribute('template', $url->template);
170 $elOs->appendChild($elUrl);
171 }
172
173 $xml->appendChild($elOs);
174 parent::render();
175
176 return $xml->saveXml();
177 }
178
179 /**
180 * Sets the short name
181 *
182 * @param string $name The name.
183 *
184 * @return JDocumentOpensearch instance of $this to allow chaining
185 *
186 * @since 11.1
187 */
188 public function setShortName($name)
189 {
190 $this->_shortName = $name;
191
192 return $this;
193 }
194
195 /**
196 * Adds a URL to the OpenSearch description.
197 *
198 * @param JOpenSearchUrl $url The url to add to the description.
199 *
200 * @return JDocumentOpensearch instance of $this to allow chaining
201 *
202 * @since 11.1
203 */
204 public function addUrl(JOpenSearchUrl $url)
205 {
206 $this->_urls[] = $url;
207
208 return $this;
209 }
210
211 /**
212 * Adds an image to the OpenSearch description.
213 *
214 * @param JOpenSearchImage $image The image to add to the description.
215 *
216 * @return JDocumentOpensearch instance of $this to allow chaining
217 *
218 * @since 11.1
219 */
220 public function addImage(JOpenSearchImage $image)
221 {
222 $this->_images[] = $image;
223
224 return $this;
225 }
226 }
227
228 /**
229 * JOpenSearchUrl is an internal class that stores the search URLs for the OpenSearch description
230 *
231 * @since 11.1
232 */
233 class JOpenSearchUrl
234 {
235 /**
236 * Type item element
237 *
238 * required
239 *
240 * @var string
241 * @since 11.1
242 */
243 public $type = 'text/html';
244
245 /**
246 * Rel item element
247 *
248 * required
249 *
250 * @var string
251 * @since 11.1
252 */
253 public $rel = 'results';
254
255 /**
256 * Template item element. Has to contain the {searchTerms} parameter to work.
257 *
258 * required
259 *
260 * @var string
261 * @since 11.1
262 */
263 public $template;
264 }
265
266 /**
267 * JOpenSearchImage is an internal class that stores Images for the OpenSearch Description
268 *
269 * @since 11.1
270 */
271 class JOpenSearchImage
272 {
273 /**
274 * The images MIME type
275 *
276 * required
277 *
278 * @var string
279 * @since 11.1
280 */
281 public $type = '';
282
283 /**
284 * URL of the image or the image as base64 encoded value
285 *
286 * required
287 *
288 * @var string
289 * @since 11.1
290 */
291 public $data = '';
292
293 /**
294 * The image's width
295 *
296 * required
297 *
298 * @var string
299 * @since 11.1
300 */
301 public $width;
302
303 /**
304 * The image's height
305 *
306 * required
307 *
308 * @var string
309 * @since 11.1
310 */
311 public $height;
312 }
313