b6e5a71c1f8345eea0e73c3902818bdc91704658
[yaffs-website] / vendor / easyrdf / easyrdf / lib / EasyRdf / Literal.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 that represents an RDF Literal
40  *
41  * @package    EasyRdf
42  * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
43  * @license    http://www.opensource.org/licenses/bsd-license.php
44  */
45 class EasyRdf_Literal
46 {
47     /** @ignore a mapping from datatype uri to class name */
48     private static $datatypeMap = array();
49
50     /** @ignore A mapping from class name to datatype URI */
51     private static $classMap = array();
52
53     /** @ignore The string value for this literal */
54     protected $value = null;
55
56     /** @ignore The language of the literal (e.g. 'en') */
57     protected $lang = null;
58
59     /** @ignore The datatype URI of the literal */
60     protected $datatype = null;
61
62
63     /** Create a new literal object
64      *
65      * PHP values of type bool, int or float, will automatically be converted
66      * to the corresponding datatype and PHP sub-class.
67      *
68      * If a registered datatype is given, then the registered subclass of EasyRdf_Literal
69      * will instantiated.
70      *
71      * Note that literals are not required to have a language or datatype.
72      * Literals cannot have both a language and a datatype.
73      *
74      * @param  mixed  $value     The value of the literal or an associative array
75      * @param  string $lang      The natural language of the literal or null (e.g. 'en')
76      * @param  string $datatype  The datatype of the literal or null (e.g. 'xsd:integer')
77      * @return object EasyRdf_Literal (or subclass of EasyRdf_Literal)
78      */
79     public static function create($value, $lang = null, $datatype = null)
80     {
81         if (EasyRdf_Utils::isAssociativeArray($value)) {
82             if (isset($value['xml:lang'])) {
83                 $lang = $value['xml:lang'];
84             } elseif (isset($value['lang'])) {
85                 $lang = $value['lang'];
86             }
87             if (isset($value['datatype'])) {
88                 $datatype = $value['datatype'];
89             }
90             $value = isset($value['value']) ? $value['value'] : null;
91         }
92
93         if (is_null($datatype) or $datatype === '') {
94             if (is_null($lang) or $lang === '') {
95                 // Automatic datatype selection
96                 $datatype = self::getDatatypeForValue($value);
97             }
98         } elseif (is_object($datatype)) {
99             $datatype = strval($datatype);
100         } else {
101             // Expand shortened URIs (qnames)
102             $datatype = EasyRdf_Namespace::expand($datatype);
103         }
104
105         // Work out what class to use for this datatype
106         if (isset(self::$datatypeMap[$datatype])) {
107             $class = self::$datatypeMap[$datatype];
108         } else {
109             $class = 'EasyRdf_Literal';
110         }
111         return new $class($value, $lang, $datatype);
112     }
113
114     /** Register an RDF datatype with a PHP class name
115      *
116      * When parsing registered class will be used whenever the datatype
117      * is seen.
118      *
119      * When serialising a registered class, the mapping will be used to
120      * set the datatype in the RDF.
121      *
122      * Example:
123      * EasyRdf_Literal::registerDatatype('xsd:dateTime', 'My_DateTime_Class');
124      *
125      * @param  string  $datatype   The RDF datatype (e.g. xsd:dateTime)
126      * @param  string  $class      The PHP class name (e.g. My_DateTime_Class)
127      */
128     public static function setDatatypeMapping($datatype, $class)
129     {
130         if (!is_string($datatype) or $datatype == null or $datatype == '') {
131             throw new InvalidArgumentException(
132                 "\$datatype should be a string and cannot be null or empty"
133             );
134         }
135
136         if (!is_string($class) or $class == null or $class == '') {
137             throw new InvalidArgumentException(
138                 "\$class should be a string and cannot be null or empty"
139             );
140         }
141
142         $datatype = EasyRdf_Namespace::expand($datatype);
143         self::$datatypeMap[$datatype] = $class;
144         self::$classMap[$class] = $datatype;
145     }
146
147     /** Remove the mapping between an RDF datatype and a PHP class name
148      *
149      * @param  string  $datatype   The RDF datatype (e.g. xsd:dateTime)
150      */
151     public static function deleteDatatypeMapping($datatype)
152     {
153         if (!is_string($datatype) or $datatype == null or $datatype == '') {
154             throw new InvalidArgumentException(
155                 "\$datatype should be a string and cannot be null or empty"
156             );
157         }
158
159         $datatype = EasyRdf_Namespace::expand($datatype);
160         if (isset(self::$datatypeMap[$datatype])) {
161             $class = self::$datatypeMap[$datatype];
162             unset(self::$datatypeMap[$datatype]);
163             unset(self::$classMap[$class]);
164         }
165     }
166
167     /** Get datatype URI for a PHP value.
168      *
169      * This static function is intended for internal use.
170      * Given a PHP value, it will return an XSD datatype
171      * URI for that value, for example:
172      * http://www.w3.org/2001/XMLSchema#integer
173      *
174      * @return string  A URI for the datatype of $value.
175      */
176     public static function getDatatypeForValue($value)
177     {
178         if (is_float($value)) {
179             return 'http://www.w3.org/2001/XMLSchema#double';
180         } elseif (is_int($value)) {
181             return 'http://www.w3.org/2001/XMLSchema#integer';
182         } elseif (is_bool($value)) {
183             return 'http://www.w3.org/2001/XMLSchema#boolean';
184         } elseif (is_object($value) and $value instanceof DateTime) {
185             return 'http://www.w3.org/2001/XMLSchema#dateTime';
186         } else {
187             return null;
188         }
189     }
190
191
192
193     /** Constructor for creating a new literal
194      *
195      * @param  string $value     The value of the literal
196      * @param  string $lang      The natural language of the literal or null (e.g. 'en')
197      * @param  string $datatype  The datatype of the literal or null (e.g. 'xsd:string')
198      * @return object EasyRdf_Literal
199      */
200     public function __construct($value, $lang = null, $datatype = null)
201     {
202         $this->value = $value;
203         $this->lang = $lang ? $lang : null;
204         $this->datatype = $datatype ? $datatype : null;
205
206         if ($this->datatype) {
207             if (is_object($this->datatype)) {
208                 // Convert objects to strings
209                 $this->datatype = strval($this->datatype);
210             } else {
211                 // Expand shortened URIs (CURIEs)
212                 $this->datatype = EasyRdf_Namespace::expand($this->datatype);
213             }
214
215             // Literals can not have both a language and a datatype
216             $this->lang = null;
217         } else {
218             // Set the datatype based on the subclass
219             $class = get_class($this);
220             if (isset(self::$classMap[$class])) {
221                 $this->datatype = self::$classMap[$class];
222                 $this->lang = null;
223             }
224         }
225
226         if (is_float($this->value)) {
227             // special handling of floats, as they suffer from locale [mis]configuration
228             $this->value = rtrim(sprintf('%F', $this->value), '0');
229         } else {
230             // Cast value to string
231             settype($this->value, 'string');
232         }
233     }
234
235     /** Returns the value of the literal.
236      *
237      * @return string  Value of this literal.
238      */
239     public function getValue()
240     {
241         return $this->value;
242     }
243
244     /** Returns the full datatype URI of the literal.
245      *
246      * @return string  Datatype URI of this literal.
247      */
248     public function getDatatypeUri()
249     {
250         return $this->datatype;
251     }
252
253     /** Returns the shortened datatype URI of the literal.
254      *
255      * @return string  Datatype of this literal (e.g. xsd:integer).
256      */
257     public function getDatatype()
258     {
259         if ($this->datatype) {
260             return EasyRdf_Namespace::shorten($this->datatype);
261         } else {
262             return null;
263         }
264     }
265
266     /** Returns the language of the literal.
267      *
268      * @return string  Language of this literal.
269      */
270     public function getLang()
271     {
272         return $this->lang;
273     }
274
275     /** Returns the properties of the literal as an associative array
276      *
277      * For example:
278      * array('type' => 'literal', 'value' => 'string value')
279      *
280      * @return array  The properties of the literal
281      */
282     public function toRdfPhp()
283     {
284         $array = array(
285             'type' => 'literal',
286             'value' => $this->value
287         );
288
289         if ($this->datatype) {
290             $array['datatype'] = $this->datatype;
291         }
292
293         if ($this->lang) {
294             $array['lang'] = $this->lang;
295         }
296
297         return $array;
298     }
299
300     /** Magic method to return the value of a literal as a string
301      *
302      * @return string The value of the literal
303      */
304     public function __toString()
305     {
306         return isset($this->value) ? $this->value : '';
307     }
308
309     /** Return pretty-print view of the literal
310      *
311      * @param  string $format Either 'html' or 'text'
312      * @param  string $color  The colour of the text
313      * @return string
314      */
315     public function dumpValue($format = 'html', $color = 'black')
316     {
317         return EasyRdf_Utils::dumpLiteralValue($this, $format, $color);
318     }
319 }
320
321 /*
322    Register default set of datatype classes
323 */
324
325 EasyRdf_Literal::setDatatypeMapping('xsd:boolean', 'EasyRdf_Literal_Boolean');
326 EasyRdf_Literal::setDatatypeMapping('xsd:date', 'EasyRdf_Literal_Date');
327 EasyRdf_Literal::setDatatypeMapping('xsd:dateTime', 'EasyRdf_Literal_DateTime');
328 EasyRdf_Literal::setDatatypeMapping('xsd:decimal', 'EasyRdf_Literal_Decimal');
329 EasyRdf_Literal::setDatatypeMapping('xsd:hexBinary', 'EasyRdf_Literal_HexBinary');
330 EasyRdf_Literal::setDatatypeMapping('rdf:HTML', 'EasyRdf_Literal_HTML');
331 EasyRdf_Literal::setDatatypeMapping('xsd:integer', 'EasyRdf_Literal_Integer');
332 EasyRdf_Literal::setDatatypeMapping('rdf:XMLLiteral', 'EasyRdf_Literal_XML');