-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathphpGraphviz.php
More file actions
206 lines (168 loc) · 4.7 KB
/
phpGraphviz.php
File metadata and controls
206 lines (168 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<?php
/**
* @author Julian Bogdani <jbogdani@gmail.com>
* @copyright BraDypUS 2007-2013
* @license All rights reserved
* @since Apr 23, 2013
*
* Makes directed Graphs using Graphviz from remote DOT files.
* If required DOT files will be cleaned from redundant edges and a simple cycles controle will be performed.
*/
namespace graphviz;
class phpGraphviz
{
private
/**
* Path on server to dot file (inside tmp_dir) or to cleaned dot file
*/
$dot_file,
/**
* Absolute path to dot program
*/
$graphviz_path;
/**
*
* @param string $graphviz_path Absolute path to graphviz executables
* @throws \Exception on errors
*
* Sets main settings and performs basics checks on server settings.
*/
public function __construct($graphviz_path)
{
$this->graphviz_path = $graphviz_path;
}
/**
* Gets content of remote DOT file and saves it to server's temporary folder
* @param string $remotePath Path, URL, to remote DOT file
* @throws \Exception on errors
*/
private function makeDotFile($remotePath)
{
$this->dot_file = sys_get_temp_dir() . '/' . uniqid('dot') . '.dot';
$dot_content = file_get_contents($remotePath);
if (!$dot_content)
{
throw new \Exception('Can not get content of file ' . $remotePath);
}
if (!@file_put_contents($this->dot_file, $dot_content))
{
throw new \Exception('Can not write content in ' . $this->dot_file);
}
}
/**
* Cleans DOT file using TRED (transitive reduction filter for directed graphs)
* and saves file to server's temporary folder.
* @throws \Exception on errors
*/
private function cleanDotFile()
{
$command = $this->graphviz_path . 'tred ' . escapeshellarg($this->dot_file);
exec($command, $msg, $return_val);
if(is_array($msg))
{
if($msg[(count($msg)-2)] == "warning: G has cycle(s), transitive reduction not unique")
{
throw new \Exception('Cicles problem found! ' . var_export($msg, true));
}
}
$text = implode("\n", $msg);
$this->dot_file = str_replace('.dot', '-cleaned.dot', $this->dot_file);
if (!file_put_contents($this->dot_file, $text))
{
throw new \Exception('Error in writing cleaned dot code in ' . $this->dot_file);
}
}
/**
* Checks if image output format is valid
* @param string $format
* @return boolean
*/
private function isValidFormat($format)
{
$allowed_formats = array('png', 'gif', 'jpeg', 'svg');
return in_array($format, $allowed_formats);
}
/**
*
* @param string $remotePath Path, URL, to remote DOT file
* @param boolean $clean If true the original DOT file will be cleaned using TRED
* @param string $format Image file format. Optional (png, gif, jpeg, svg). Default value is png
* @param string $graph_type Graph type to create (directed, undirected, readial, circular, fdp, sfdb). Optional. Default directed
* @throws \Exception on errors
* @return \graphviz\phpGraphviz
*/
public function getGraph($remotePath, $clean = false, $format = false, $graph_type = false)
{
if (!$format)
{
$format = 'png';
}
if (!$graph_type)
{
$graph_type = 'directed';
}
if (!$this->isValidFormat($format))
{
throw new \Exception('Filetype `' . $format . '` not valid.');
}
$this->makeDotFile($remotePath);
if ($clean)
{
$this->cleanDotFile();
}
$outputfile = $this->dot_file . '.' . $format;
if (!file_exists($this->dot_file))
{
throw new \Exception('Dot file ' . $this->dot_file . ' not found!');
}
switch($graph_type)
{
case 'directed':
$cmd = 'dot';
break;
case 'undirected':
$cmd = 'neato';
break;
case 'radial':
$cmd = 'twopi';
break;
case 'circular':
$cmd = 'circo';
break;
case 'fpd':
case 'sfdp':
$cmd = $graph_type;
break;
default:
throw new \Exception('" ' . $graph_type . ' " graph type is not supported');
break;
}
$command = $this->graphviz_path . $cmd
. ' -T' . escapeshellarg($format)
. ' -o' . escapeshellarg($outputfile)
. ' ' . escapeshellarg($this->dot_file)
. ' 2>&1';
exec($command, $msg, $return_val);
if ($msg AND !file_exists($outputfile))
{
throw new \Exception('Error in executing dot program');
}
clearstatcache();
/**
* outputs created image
*/
$this->output($format, $outputfile);
}
/**
* Outputs image file content with file headers. Ready to use in any src attributo of an img tag.
* @param string $format output file format
* @param string $outputfile output file path + name
*/
private function output($format, $outputfile)
{
$type = 'image/' . $format;
header('Content-Type:' . $type);
header('Content-Length: ' . filesize($outputfile));
readfile($outputfile);
}
}