Minor dependency updates
[yaffs-website] / vendor / easyrdf / easyrdf / lib / EasyRdf / Serialiser / GraphViz.php
1 <?php
2
3 /**
4  * EasyRdf
5  *
6  * LICENSE
7  *
8  * Copyright (c) 2012-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 to serialise an EasyRdf_Graph to GraphViz
40  *
41  * Depends upon the GraphViz 'dot' command line tools to render images.
42  *
43  * See http://www.graphviz.org/ for more information.
44  *
45  * @package    EasyRdf
46  * @copyright  Copyright (c) 2012-2013 Nicholas J Humfrey
47  * @license    http://www.opensource.org/licenses/bsd-license.php
48  */
49 class EasyRdf_Serialiser_GraphViz extends EasyRdf_Serialiser
50 {
51     private $dotCommand = 'dot';
52     private $useLabels = false;
53     private $onlyLabelled = false;
54     private $attributes = array('charset' => 'utf-8');
55
56     /**
57      * Constructor
58      *
59      * @return object EasyRdf_Serialiser_GraphViz
60      */
61     public function __construct()
62     {
63     }
64
65     /**
66      * Set the path to the GraphViz 'dot' command
67      *
68      * Default is to search PATH for the command 'dot'.
69      *
70      * @param string $cmd   The path to the 'dot' command.
71      * @return object EasyRdf_Serialiser_GraphViz
72      */
73     public function setDotCommand($cmd)
74     {
75         $this->dotCommand = $cmd;
76         return $this;
77     }
78
79     /**
80      * Get the path to the GraphViz 'dot' command
81      *
82      * The default value is simply 'dot'
83      *
84      * @return string The path to the 'dot' command.
85      */
86     public function getDotCommand()
87     {
88         return $this->dotCommand;
89     }
90
91     /**
92      * Turn on/off the option to display labels instead of URIs.
93      *
94      * When this option is turned on, then labels for resources will
95      * be displayed instead of the full URI of a resource. This makes
96      * it simpler to create friendly diagrams that non-technical people
97      * can understand.
98      *
99      * This option is turned off by default.
100      *
101      * @param bool $useLabels   A boolean value to turn labels on and off
102      * @return object EasyRdf_Serialiser_GraphViz
103      */
104     public function setUseLabels($useLabels)
105     {
106         $this->useLabels = $useLabels;
107         return $this;
108     }
109
110     /**
111      * Get the state of the use labels option
112      *
113      * @return bool The current state of the use labels option
114      */
115     public function getUseLabels()
116     {
117         return $this->useLabels;
118     }
119
120     /**
121      * Turn on/off the option to only display nodes and edges with labels
122      *
123      * When this option is turned on, then only nodes (resources and literals)
124      * and edges (properties) will only be displayed if they have a label. You
125      * can use this option, to create concise, diagrams of your data, rather than
126      * the RDF.
127      *
128      * This option is turned off by default.
129      *
130      * @param bool $onlyLabelled   A boolean value to enable/display only labelled items
131      * @return object EasyRdf_Serialiser_GraphViz
132      */
133     public function setOnlyLabelled($onlyLabelled)
134     {
135         $this->onlyLabelled = $onlyLabelled;
136         return $this;
137     }
138
139     /**
140      * Get the state of the only Only Labelled option
141      *
142      * @return bool The current state of the Only Labelled option
143      */
144     public function getOnlyLabelled()
145     {
146         return $this->onlyLabelled;
147     }
148
149     /**
150      * Set an attribute on the GraphViz graph
151      *
152      * Example:
153      *     $serialiser->setAttribute('rotate', 90);
154      *
155      * See the GraphViz tool documentation for information about the
156      * available attributes.
157      *
158      * @param string $name    The name of the attribute
159      * @param string $value   The value for the attribute
160      * @return object EasyRdf_Serialiser_GraphViz
161      */
162     public function setAttribute($name, $value)
163     {
164         $this->attributes[$name] = $value;
165         return $this;
166     }
167
168     /**
169      * Get an attribute of the GraphViz graph
170      *
171      * @param string $name    Attribute name
172      * @return string The value of the graph attribute
173      */
174     public function getAttribute($name)
175     {
176         return $this->attributes[$name];
177     }
178
179     /**
180      * Convert an EasyRdf object into a GraphViz node identifier
181      *
182      * @ignore
183      */
184     protected function nodeName($entity)
185     {
186         if ($entity instanceof EasyRdf_Resource) {
187             if ($entity->isBNode()) {
188                 return "B".$entity->getUri();
189             } else {
190                 return "R".$entity->getUri();
191             }
192         } else {
193             return "L".$entity;
194         }
195     }
196
197     /**
198      * Internal function to escape a string into DOT safe syntax
199      *
200      * @ignore
201      */
202     protected function escape($input)
203     {
204         if (preg_match('/^([a-z_][a-z_0-9]*|-?(\.[0-9]+|[0-9]+(\.[0-9]*)?))$/i', $input)) {
205             return $input;
206         } else {
207             return '"'.str_replace(
208                 array("\r\n", "\n", "\r", '"'),
209                 array('\n',   '\n', '\n', '\"'),
210                 $input
211             ).'"';
212         }
213     }
214
215     /**
216      * Internal function to escape an associate array of attributes and
217      * turns it into a DOT notation string
218      *
219      * @ignore
220      */
221     protected function escapeAttributes($array)
222     {
223         $items = '';
224         foreach ($array as $k => $v) {
225             $items[] = $this->escape($k).'='.$this->escape($v);
226         }
227         return '['.implode(',', $items).']';
228     }
229
230     /**
231      * Internal function to create dot syntax line for either a node or an edge
232      *
233      * @ignore
234      */
235     protected function serialiseRow($node1, $node2 = null, $attributes = array())
236     {
237         $result = '  '.$this->escape($node1);
238         if ($node2) {
239             $result .= ' -> '.$this->escape($node2);
240         }
241         if (count($attributes)) {
242             $result .= ' '.$this->escapeAttributes($attributes);
243         }
244         return $result.";\n";
245     }
246
247     /**
248      * Internal function to serialise an EasyRdf_Graph into a DOT formatted string
249      *
250      * @ignore
251      */
252     protected function serialiseDot($graph)
253     {
254         $result = "digraph {\n";
255
256         // Write the graph attributes
257         foreach ($this->attributes as $k => $v) {
258             $result .= '  '.$this->escape($k).'='.$this->escape($v).";\n";
259         }
260
261         // Go through each of the properties and write the edges
262         $nodes = array();
263         $result .= "\n  // Edges\n";
264         foreach ($graph->resources() as $resource) {
265             $name1 = $this->nodeName($resource);
266             foreach ($resource->propertyUris() as $property) {
267                 $label = null;
268                 if ($this->useLabels) {
269                     $label = $graph->resource($property)->label();
270                 }
271                 if ($label === null) {
272                     if ($this->onlyLabelled == true) {
273                         continue;
274                     } else {
275                         $label = EasyRdf_Namespace::shorten($property);
276                     }
277                 }
278                 foreach ($resource->all("<$property>") as $value) {
279                     $name2 = $this->nodeName($value);
280                     $nodes[$name1] = $resource;
281                     $nodes[$name2] = $value;
282                     $result .= $this->serialiseRow(
283                         $name1,
284                         $name2,
285                         array('label' => $label)
286                     );
287                 }
288             }
289         }
290
291         ksort($nodes);
292
293         $result .= "\n  // Nodes\n";
294         foreach ($nodes as $name => $node) {
295             $type = substr($name, 0, 1);
296             $label = '';
297             if ($type == 'R') {
298                 if ($this->useLabels) {
299                     $label = $node->label();
300                 }
301                 if (!$label) {
302                     $label = $node->shorten();
303                 }
304                 if (!$label) {
305                     $label = $node->getURI();
306                 }
307                 $result .= $this->serialiseRow(
308                     $name,
309                     null,
310                     array(
311                         'URL'   => $node->getURI(),
312                         'label' => $label,
313                         'shape' => 'ellipse',
314                         'color' => 'blue'
315                     )
316                 );
317             } elseif ($type == 'B') {
318                 if ($this->useLabels) {
319                     $label = $node->label();
320                 }
321                 $result .= $this->serialiseRow(
322                     $name,
323                     null,
324                     array(
325                         'label' => $label,
326                         'shape' => 'circle',
327                         'color' => 'green'
328                     )
329                 );
330             } else {
331                 $result .= $this->serialiseRow(
332                     $name,
333                     null,
334                     array(
335                         'label' => strval($node),
336                         'shape' => 'record',
337                     )
338                 );
339             }
340
341         }
342
343         $result .= "}\n";
344
345         return $result;
346     }
347
348     /**
349      * Internal function to render a graph into an image
350      *
351      * @ignore
352      */
353     public function renderImage($graph, $format = 'png')
354     {
355         $dot = $this->serialiseDot($graph);
356
357         return EasyRdf_Utils::execCommandPipe(
358             $this->dotCommand,
359             array("-T$format"),
360             $dot
361         );
362     }
363
364     /**
365      * Serialise an EasyRdf_Graph into a GraphViz dot document.
366      *
367      * Supported output format names: dot, gif, png, svg
368      *
369      * @param EasyRdf_Graph $graph  An EasyRdf_Graph object.
370      * @param string        $format The name of the format to convert to.
371      * @param array         $options
372      * @throws EasyRdf_Exception
373      * @return string The RDF in the new desired format.
374      */
375     public function serialise($graph, $format, array $options = array())
376     {
377         parent::checkSerialiseParams($graph, $format);
378
379         switch($format) {
380             case 'dot':
381                 return $this->serialiseDot($graph);
382             case 'png':
383             case 'gif':
384             case 'svg':
385                 return $this->renderImage($graph, $format);
386             default:
387                 throw new EasyRdf_Exception(
388                     "EasyRdf_Serialiser_GraphViz does not support: $format"
389                 );
390         }
391     }
392 }