Minor dependency updates
[yaffs-website] / vendor / easyrdf / easyrdf / lib / EasyRdf / Format.php
1 <?php
2
3 /**
4  * EasyRdf
5  *
6  * LICENSE
7  *
8  * Copyright (c) 2009-2013 Nicholas J Humfrey.  All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  *    this list of conditions and the following disclaimer in the documentation
16  *    and/or other materials provided with the distribution.
17  * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
18  *    promote products derived from this software without specific prior
19  *    written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * @package    EasyRdf
34  * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
35  * @license    http://www.opensource.org/licenses/bsd-license.php
36  */
37
38 /**
39  * Class the represents an RDF file format.
40  *
41  * For each format, the name, label, URIs and associated MIME Types are
42  * stored. A single parser and serialiser can also be registered to each
43  * format.
44  *
45  * @package    EasyRdf
46  * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
47  * @license    http://www.opensource.org/licenses/bsd-license.php
48  */
49 class EasyRdf_Format
50 {
51     private static $formats = array();
52
53     private $name = array();
54     private $label = null;
55     private $uri = null;
56     private $mimeTypes = array();
57     private $extensions = array();
58     private $parserClass = null;
59     private $serialiserClass = null;
60
61     /** Get a list of format names
62      *
63      * @return array          An array of formats name
64      */
65     public static function getNames()
66     {
67         return array_keys(self::$formats);
68     }
69
70     /** Get a list of all the registered formats
71      *
72      * @return array          An array of format objects
73      */
74     public static function getFormats()
75     {
76         return self::$formats;
77     }
78
79     /** Generates an HTTP Accept header string
80      *
81      * The string will contain all of the MIME Types that we
82      * are able to parse.
83      *
84      * It is also possible to specify additional MIME types
85      * in the form array('text/plain' => 0.5) where 0.5 is the
86      * q value for that type. The types are sorted by q value
87      * before constructing the string.
88      *
89      * @param array $extraTypes    extra MIME types to add
90      * @return string              list of supported MIME types
91      */
92     public static function getHttpAcceptHeader($extraTypes = array())
93     {
94         $accept = $extraTypes;
95         foreach (self::$formats as $format) {
96             if ($format->parserClass and count($format->mimeTypes) > 0) {
97                 $accept = array_merge($accept, $format->mimeTypes);
98             }
99         }
100         arsort($accept, SORT_NUMERIC);
101
102         $acceptStr='';
103         foreach ($accept as $type => $q) {
104             if ($acceptStr) {
105                 $acceptStr .= ',';
106             }
107             if ($q == 1.0) {
108                 $acceptStr .= $type;
109             } else {
110                 $acceptStr .= sprintf("%s;q=%1.1F", $type, $q);
111             }
112         }
113         return $acceptStr;
114     }
115
116     /** Check if a named graph exists
117      *
118      * @param string $name    the name of the format
119      * @return boolean        true if the format exists
120      */
121     public static function formatExists($name)
122     {
123         return array_key_exists($name, self::$formats);
124     }
125
126     /** Get a EasyRdf_Format from a name, uri or mime type
127      *
128      * @param string $query   a query string to search for
129      * @return object         the first EasyRdf_Format that matches the query
130      * @throws EasyRdf_Exception  if no format is found
131      */
132     public static function getFormat($query)
133     {
134         if (!is_string($query) or $query == null or $query == '') {
135             throw new InvalidArgumentException(
136                 "\$query should be a string and cannot be null or empty"
137             );
138         }
139
140         foreach (self::$formats as $format) {
141             if ($query == $format->name or
142                 $query == $format->uri or
143                 array_key_exists($query, $format->mimeTypes) or
144                 in_array($query, $format->extensions)) {
145                 return $format;
146             }
147         }
148
149         # No match
150         throw new EasyRdf_Exception(
151             "Format is not recognised: $query"
152         );
153     }
154
155     /** Register a new format
156      *
157      * @param  string  $name       The name of the format (e.g. ntriples)
158      * @param  string  $label      The label for the format (e.g. N-Triples)
159      * @param  string  $uri        The URI for the format
160      * @param  string  $mimeTypes  One or more mime types for the format
161      * @param  string  $extensions One or more extensions (file suffix)
162      * @return object              The new EasyRdf_Format object
163      */
164     public static function register(
165         $name,
166         $label = null,
167         $uri = null,
168         $mimeTypes = array(),
169         $extensions = array()
170     ) {
171         if (!is_string($name) or $name == null or $name == '') {
172             throw new InvalidArgumentException(
173                 "\$name should be a string and cannot be null or empty"
174             );
175         }
176
177         if (!array_key_exists($name, self::$formats)) {
178             self::$formats[$name] = new EasyRdf_Format($name);
179         }
180
181         self::$formats[$name]->setLabel($label);
182         self::$formats[$name]->setUri($uri);
183         self::$formats[$name]->setMimeTypes($mimeTypes);
184         self::$formats[$name]->setExtensions($extensions);
185         return self::$formats[$name];
186     }
187
188     /** Remove a format from the registry
189      *
190      * @param  string  $name      The name of the format (e.g. ntriples)
191      */
192     public static function unregister($name)
193     {
194         unset(self::$formats[$name]);
195     }
196
197     /** Class method to register a parser class to a format name
198      *
199      * @param  string  $name   The name of the format (e.g. ntriples)
200      * @param  string  $class  The name of the class (e.g. EasyRdf_Parser_Ntriples)
201      */
202     public static function registerParser($name, $class)
203     {
204         if (!self::formatExists($name)) {
205             self::register($name);
206         }
207         self::getFormat($name)->setParserClass($class);
208     }
209
210     /** Class method to register a serialiser class to a format name
211      *
212      * @param  string  $name   The name of the format (e.g. ntriples)
213      * @param  string  $class  The name of the class (e.g. EasyRdf_Serialiser_Ntriples)
214      */
215     public static function registerSerialiser($name, $class)
216     {
217         if (!self::formatExists($name)) {
218             self::register($name);
219         }
220         self::getFormat($name)->setSerialiserClass($class);
221     }
222
223     /** Attempt to guess the document format from some content.
224      *
225      * If $filename is given, then the suffix is first used to guess the format.
226      *
227      * If the document format is not recognised, null is returned.
228      *
229      * @param  string $data     The document data
230      * @param  string $filename Optional filename
231      * @return object EasyRdf_Format The format object
232      */
233     public static function guessFormat($data, $filename = null)
234     {
235         if (is_array($data)) {
236             # Data has already been parsed into RDF/PHP
237             return self::getFormat('php');
238         }
239
240         // First try and identify by the filename
241         if ($filename and preg_match('/\.(\w+)$/', $filename, $matches)) {
242             foreach (self::$formats as $format) {
243                 if (in_array($matches[1], $format->extensions)) {
244                     return $format;
245                 }
246             }
247         }
248
249         // Then try and guess by the first 1024 bytes of content
250         $short = substr($data, 0, 1024);
251         if (preg_match('/^\s*\{/', $short)) {
252             return self::getFormat('json');
253         } elseif (preg_match('/<rdf:/i', $short)) {
254             return self::getFormat('rdfxml');
255         } elseif (preg_match('|http://www.w3.org/2005/sparql-results|', $short)) {
256             return self::getFormat('sparql-xml');
257         } elseif (preg_match('/\WRDFa\W/i', $short)) {
258             return self::getFormat('rdfa');
259         } elseif (preg_match('/<!DOCTYPE html|<html/i', $short)) {
260             # We don't support any other microformats embedded in HTML
261             return self::getFormat('rdfa');
262         } elseif (preg_match('/@prefix\s|@base\s/', $short)) {
263             return self::getFormat('turtle');
264         } elseif (preg_match('/^\s*<.+> <.+>/m', $short)) {
265             return self::getFormat('ntriples');
266         } else {
267             return null;
268         }
269     }
270
271     /**
272      * This constructor is for internal use only.
273      * To create a new format, use the register method.
274      *
275      * @param  string  $name    The name of the format
276      * @see    EasyRdf_Format::register()
277      * @ignore
278      */
279     public function __construct($name)
280     {
281         $this->name = $name;
282         $this->label = $name;  # Only a default
283     }
284
285     /** Get the name of a format object
286      *
287      * @return string The name of the format (e.g. rdfxml)
288      */
289     public function getName()
290     {
291         return $this->name;
292     }
293
294     /** Get the label for a format object
295      *
296      * @return string The format label (e.g. RDF/XML)
297      */
298     public function getLabel()
299     {
300         return $this->label;
301     }
302
303     /** Set the label for a format object
304      *
305      * @param  string $label  The new label for the format
306      */
307     public function setLabel($label)
308     {
309         if ($label) {
310             if (!is_string($label)) {
311                 throw new InvalidArgumentException(
312                     "\$label should be a string"
313                 );
314             }
315             return $this->label = $label;
316         } else {
317             return $this->label = null;
318         }
319     }
320
321     /** Get the URI for a format object
322      *
323      * @return string The format URI
324      */
325     public function getUri()
326     {
327         return $this->uri;
328     }
329
330     /** Set the URI for a format object
331      *
332      * @param string $uri  The new URI for the format
333      */
334     public function setUri($uri)
335     {
336         if ($uri) {
337             if (!is_string($uri)) {
338                 throw new InvalidArgumentException(
339                     "\$uri should be a string"
340                 );
341             }
342             return $this->uri = $uri;
343         } else {
344             return $this->uri = null;
345         }
346     }
347
348     /** Get the default registered mime type for a format object
349      *
350      * @return string The default mime type as a string.
351      */
352     public function getDefaultMimeType()
353     {
354         $types = array_keys($this->mimeTypes);
355         if (isset($types[0])) {
356             return $types[0];
357         }
358     }
359
360     /** Get all the registered mime types for a format object
361      *
362      * @return array One or more MIME types in an array with
363      *               the mime type as the key and q value as the value
364      */
365     public function getMimeTypes()
366     {
367         return $this->mimeTypes;
368     }
369
370     /** Set the MIME Types for a format object
371      *
372      * @param array $mimeTypes  One or more mime types
373      */
374     public function setMimeTypes($mimeTypes)
375     {
376         if ($mimeTypes) {
377             if (!is_array($mimeTypes)) {
378                 $mimeTypes = array($mimeTypes);
379             }
380             $this->mimeTypes = $mimeTypes;
381         } else {
382             $this->mimeTypes = array();
383         }
384     }
385
386     /** Get the default registered file extension (filename suffix) for a format object
387      *
388      * @return string The default extension as a string.
389      */
390     public function getDefaultExtension()
391     {
392         if (isset($this->extensions[0])) {
393             return $this->extensions[0];
394         }
395     }
396
397     /** Get all the registered file extensions (filename suffix) for a format object
398      *
399      * @return array One or more extensions as an array
400      */
401     public function getExtensions()
402     {
403         return $this->extensions;
404     }
405
406     /** Set the file format extensions (filename suffix) for a format object
407      *
408      * @param mixed $extensions  One or more file extensions
409      */
410     public function setExtensions($extensions)
411     {
412         if ($extensions) {
413             if (!is_array($extensions)) {
414                 $extensions = array($extensions);
415             }
416             $this->extensions = $extensions;
417         } else {
418             $this->extensions = array();
419         }
420     }
421
422     /** Set the parser to use for a format
423      *
424      * @param string $class  The name of the class
425      */
426     public function setParserClass($class)
427     {
428         if ($class) {
429             if (!is_string($class)) {
430                 throw new InvalidArgumentException(
431                     "\$class should be a string"
432                 );
433             }
434             $this->parserClass = $class;
435         } else {
436             $this->parserClass = null;
437         }
438     }
439
440     /** Get the name of the class to use to parse the format
441      *
442      * @return string The name of the class
443      */
444     public function getParserClass()
445     {
446         return $this->parserClass;
447     }
448
449     /** Create a new parser to parse this format
450      *
451      * @return object The new parser object
452      */
453     public function newParser()
454     {
455         $parserClass = $this->parserClass;
456         if (!$parserClass) {
457             throw new EasyRdf_Exception(
458                 "No parser class available for format: ".$this->getName()
459             );
460         }
461         return (new $parserClass());
462     }
463
464     /** Set the serialiser to use for a format
465      *
466      * @param string $class  The name of the class
467      */
468     public function setSerialiserClass($class)
469     {
470         if ($class) {
471             if (!is_string($class)) {
472                 throw new InvalidArgumentException(
473                     "\$class should be a string"
474                 );
475             }
476             $this->serialiserClass = $class;
477         } else {
478             $this->serialiserClass = null;
479         }
480     }
481
482     /** Get the name of the class to use to serialise the format
483      *
484      * @return string The name of the class
485      */
486     public function getSerialiserClass()
487     {
488         return $this->serialiserClass;
489     }
490
491     /** Create a new serialiser to parse this format
492      *
493      * @return object The new serialiser object
494      */
495     public function newSerialiser()
496     {
497         $serialiserClass = $this->serialiserClass;
498         if (!$serialiserClass) {
499             throw new EasyRdf_Exception(
500                 "No serialiser class available for format: ".$this->getName()
501             );
502         }
503         return (new $serialiserClass());
504     }
505
506     /** Magic method to return the name of the format when casted to string
507      *
508      * @return string The name of the format
509      */
510     public function __toString()
511     {
512         return $this->name;
513     }
514 }
515
516
517 /*
518    Register default set of supported formats
519    NOTE: they are ordered by preference
520 */
521
522 EasyRdf_Format::register(
523     'php',
524     'RDF/PHP',
525     'http://n2.talis.com/wiki/RDF_PHP_Specification',
526     array(
527         'application/x-httpd-php-source' => 1.0
528     ),
529     array('phps')
530 );
531
532 EasyRdf_Format::register(
533     'json',
534     'RDF/JSON Resource-Centric',
535     'http://n2.talis.com/wiki/RDF_JSON_Specification',
536     array(
537         'application/json' => 1.0,
538         'text/json' => 0.9,
539         'application/rdf+json' => 0.9
540     ),
541     array('json')
542 );
543
544 EasyRdf_Format::register(
545     'jsonld',
546     'JSON-LD',
547     'http://www.w3.org/TR/json-ld/',
548     array(
549         'application/ld+json' => 1.0
550     ),
551     array('jsonld')
552 );
553
554 EasyRdf_Format::register(
555     'ntriples',
556     'N-Triples',
557     'http://www.w3.org/TR/n-triples/',
558     array(
559         'application/n-triples' => 1.0,
560         'text/plain' => 0.9,
561         'text/ntriples' => 0.9,
562         'application/ntriples' => 0.9,
563         'application/x-ntriples' => 0.9
564     ),
565     array('nt')
566 );
567
568 EasyRdf_Format::register(
569     'turtle',
570     'Turtle Terse RDF Triple Language',
571     'http://www.dajobe.org/2004/01/turtle',
572     array(
573         'text/turtle' => 0.8,
574         'application/turtle' => 0.7,
575         'application/x-turtle' => 0.7
576     ),
577     array('ttl')
578 );
579
580 EasyRdf_Format::register(
581     'rdfxml',
582     'RDF/XML',
583     'http://www.w3.org/TR/rdf-syntax-grammar',
584     array(
585         'application/rdf+xml' => 0.8
586     ),
587     array('rdf', 'xrdf')
588 );
589
590 EasyRdf_Format::register(
591     'dot',
592     'Graphviz',
593     'http://www.graphviz.org/doc/info/lang.html',
594     array(
595         'text/vnd.graphviz' => 0.8
596     ),
597     array('gv', 'dot')
598 );
599
600 EasyRdf_Format::register(
601     'json-triples',
602     'RDF/JSON Triples'
603 );
604
605 EasyRdf_Format::register(
606     'n3',
607     'Notation3',
608     'http://www.w3.org/2000/10/swap/grammar/n3#',
609     array(
610         'text/n3' => 0.5,
611         'text/rdf+n3' => 0.5
612     ),
613     array('n3')
614 );
615
616 EasyRdf_Format::register(
617     'rdfa',
618     'RDFa',
619     'http://www.w3.org/TR/rdfa-core/',
620     array(
621         'text/html' => 0.4,
622         'application/xhtml+xml' => 0.4
623     ),
624     array('html')
625 );
626
627 EasyRdf_Format::register(
628     'sparql-xml',
629     'SPARQL XML Query Results',
630     'http://www.w3.org/TR/rdf-sparql-XMLres/',
631     array(
632         'application/sparql-results+xml' => 1.0
633     )
634 );
635
636 EasyRdf_Format::register(
637     'sparql-json',
638     'SPARQL JSON Query Results',
639     'http://www.w3.org/TR/rdf-sparql-json-res/',
640     array(
641         'application/sparql-results+json' => 1.0
642     )
643 );
644
645 EasyRdf_Format::register(
646     'png',
647     'Portable Network Graphics (PNG)',
648     'http://www.w3.org/TR/PNG/',
649     array(
650         'image/png' => 0.3
651     ),
652     array('png')
653 );
654
655 EasyRdf_Format::register(
656     'gif',
657     'Graphics Interchange Format (GIF)',
658     'http://www.w3.org/Graphics/GIF/spec-gif89a.txt',
659     array(
660         'image/gif' => 0.2
661     ),
662     array('gif')
663 );
664
665 EasyRdf_Format::register(
666     'svg',
667     'Scalable Vector Graphics (SVG)',
668     'http://www.w3.org/TR/SVG/',
669     array(
670         'image/svg+xml' => 0.3
671     ),
672     array('svg')
673 );
674
675
676 /*
677    Register default set of parsers and serialisers
678 */
679
680 EasyRdf_Format::registerParser('json', 'EasyRdf_Parser_Json');
681 EasyRdf_Format::registerParser('jsonld', 'EasyRdf_Parser_JsonLd');
682 EasyRdf_Format::registerParser('ntriples', 'EasyRdf_Parser_Ntriples');
683 EasyRdf_Format::registerParser('php', 'EasyRdf_Parser_RdfPhp');
684 EasyRdf_Format::registerParser('rdfxml', 'EasyRdf_Parser_RdfXml');
685 EasyRdf_Format::registerParser('turtle', 'EasyRdf_Parser_Turtle');
686 EasyRdf_Format::registerParser('rdfa', 'EasyRdf_Parser_Rdfa');
687
688 EasyRdf_Format::registerSerialiser('json', 'EasyRdf_Serialiser_Json');
689 EasyRdf_Format::registerSerialiser('jsonld', 'EasyRdf_Serialiser_JsonLd');
690 EasyRdf_Format::registerSerialiser('n3', 'EasyRdf_Serialiser_Turtle');
691 EasyRdf_Format::registerSerialiser('ntriples', 'EasyRdf_Serialiser_Ntriples');
692 EasyRdf_Format::registerSerialiser('php', 'EasyRdf_Serialiser_RdfPhp');
693 EasyRdf_Format::registerSerialiser('rdfxml', 'EasyRdf_Serialiser_RdfXml');
694 EasyRdf_Format::registerSerialiser('turtle', 'EasyRdf_Serialiser_Turtle');
695
696 EasyRdf_Format::registerSerialiser('dot', 'EasyRdf_Serialiser_GraphViz');
697 EasyRdf_Format::registerSerialiser('gif', 'EasyRdf_Serialiser_GraphViz');
698 EasyRdf_Format::registerSerialiser('png', 'EasyRdf_Serialiser_GraphViz');
699 EasyRdf_Format::registerSerialiser('svg', 'EasyRdf_Serialiser_GraphViz');