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