Subversion Repositories Applications.gtt

Rev

Rev 61 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
60 jpm 1
<?php
2
/*
3
 * This work is hereby released into the Public Domain.
4
 * To view a copy of the public domain dedication,
5
 * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
6
 * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
7
 *
8
 */
9
 
10
require_once dirname(__FILE__)."/Image.class.php";
11
 
12
 
13
/**
14
 * A graph
15
 *
16
 * @package Artichow
17
 */
18
class awGraph extends awImage {
19
 
20
	/**
21
	 * Graph name
22
	 *
23
	 * @var string
24
	 */
25
	protected $name;
26
 
27
	/**
28
	 * Cache timeout
29
	 *
30
	 * @var int
31
	 */
32
	protected $timeout = 0;
33
 
34
	/**
35
	 * Graph timing ?
36
	 *
37
	 * @var bool
38
	 */
39
	protected $timing;
40
 
41
	/**
42
	 * Components
43
	 *
44
	 * @var array
45
	 */
46
	private $components = array();
47
 
48
	/**
49
	 * Some labels to add to the component
50
	 *
51
	 * @var array
52
	 */
53
	protected $labels = array();
54
 
55
	/**
56
	 * Graph title
57
	 *
58
	 * @var Label
59
	 */
60
	public $title;
61
 
62
	/**
63
	 * File cache location
64
	 *
65
	 * @var string
66
	 */
67
	private $fileCache;
68
 
69
	/**
70
	 * Time file cache location
71
	 *
72
	 * @var string
73
	 */
74
	private $fileCacheTime;
75
 
76
	/**
77
	 * Drawing mode to return the graph
78
	 *
79
	 * @var int
80
	 */
81
	const DRAW_RETURN = 1;
82
 
83
	/**
84
	 * Drawing mode to display the graph
85
	 *
86
	 * @var int
87
	 */
88
	const DRAW_DISPLAY = 2;
89
 
90
	/**
91
	 * Construct a new graph
92
	 *
93
	 * @param int $width Graph width
94
	 * @param int $height Graph height
95
	 * @param string $name Graph name for the cache (must be unique). Let it null to not use the cache.
96
	 * @param int $timeout Cache timeout (unix timestamp)
97
	 */
98
	public function __construct($width = NULL, $height = NULL, $name = NULL, $timeout = 0) {
99
 
100
		parent::__construct();
101
 
102
		$this->setSize($width, $height);
103
 
104
		if(ARTICHOW_CACHE) {
105
 
106
			$this->name = $name;
107
			$this->timeout = $timeout;
108
 
109
			// Clean sometimes all the cache
110
			if(mt_rand(0, 5000) ===  0) {
111
				awGraph::cleanCache();
112
			}
113
 
114
			// Take the graph from the cache if possible
115
			if($this->name !== NULL) {
116
 
117
				$this->fileCache = ARTICHOW_CACHE_DIRECTORY."/".$this->name;
118
				$this->fileCacheTime = $this->fileCache."-time";
119
 
120
				if(is_file($this->fileCache)) {
121
 
122
					$type = awGraph::cleanGraphCache($this->fileCacheTime);
123
 
124
					if($type === NULL) {
125
						awGraph::deleteFromCache($this->name);
126
					} else {
127
						header("Content-Type: image/".$type);
128
						echo file_get_contents($this->fileCache);
129
						exit;
130
					}
131
 
132
				}
133
 
134
			}
135
 
136
		}
137
 
138
		$this->title = new awLabel(
139
			NULL,
140
			new awTuffy(16),
141
			NULL,
142
 
143
		);
144
		$this->title->setAlign(awLabel::CENTER, awLabel::BOTTOM);
145
 
146
	}
147
 
148
	/**
149
	 * Delete a graph from the cache
150
	 *
151
	 * @param string $name Graph name
152
	 * @return bool TRUE on success, FALSE on failure
153
	 */
154
	public static function deleteFromCache($name) {
155
 
156
		if(ARTICHOW_CACHE) {
157
 
158
			if(is_file(ARTICHOW_CACHE_DIRECTORY."/".$name."-time")) {
159
				unlink(ARTICHOW_CACHE_DIRECTORY."/".$name."");
160
				unlink(ARTICHOW_CACHE_DIRECTORY."/".$name."-time");
161
			}
162
 
163
		}
164
 
165
	}
166
 
167
	/**
168
	 * Delete all graphs from the cache
169
	 */
170
	public static function deleteAllCache() {
171
 
172
		if(ARTICHOW_CACHE) {
173
 
174
			$dp = opendir(ARTICHOW_CACHE_DIRECTORY);
175
 
176
			while($file = readdir($dp)) {
177
				if($file !== '.' and $file != '..') {
178
					unlink(ARTICHOW_CACHE_DIRECTORY."/".$file);
179
				}
180
			}
181
 
182
		}
183
 
184
	}
185
 
186
	/**
187
	 * Clean cache
188
	 */
189
	public static function cleanCache() {
190
 
191
		if(ARTICHOW_CACHE) {
192
 
193
			$glob = glob(ARTICHOW_CACHE_DIRECTORY."/*-time");
194
 
195
			foreach($glob as $file) {
196
 
197
				$type = awGraph::cleanGraphCache($file);
198
 
199
				if($type === NULL) {
200
					$name = ereg_replace(".*/(.*)\-time", "\\1", $file);
201
					awGraph::deleteFromCache($name);
202
				}
203
 
204
			}
205
 
206
		}
207
 
208
	}
209
 
210
	/**
211
	 * Enable/Disable Graph timing
212
	 *
213
	 * @param bool $timing
214
	 */
215
	public function setTiming($timing) {
216
		$this->timing = (bool)$timing;
217
	}
218
 
219
	/**
220
	 * Add a component to the graph
221
	 *
222
	 * @param awComponent $component
223
	 */
224
	public function add(awComponent $component) {
225
 
226
		$this->components[] = $component;
227
 
228
	}
229
 
230
	/**
231
	 * Add a label to the component
232
	 *
233
	 * @param awLabel $label
234
	 * @param int $x Position on X axis of the center of the text
235
	 * @param int $y Position on Y axis of the center of the text
236
	 */
237
	public function addLabel(awLabel $label, $x, $y) {
238
 
239
		$this->labels[] = array(
240
			$label, $x, $y
241
		);
242
 
243
	}
244
 
245
	/**
246
	 * Add a label to the component with absolute position
247
	 *
248
	 * @param awLabel $label
249
	 * @param awPoint $point Text position
250
	 */
251
	public function addAbsLabel(awLabel $label, awPoint $point) {
252
 
253
		$this->labels[] = array(
254
			$label, $point
255
		);
256
 
257
	}
258
 
259
	/**
260
	 * Build the graph and draw component on it
261
	 *
262
	 * @param string $mode Display mode (can be a file name)
263
	 */
264
	public function draw($mode = Graph::DRAW_DISPLAY) {
265
 
266
		if($this->timing) {
267
			$time = microtimeFloat();
268
		}
269
 
270
		$this->create();
271
 
272
		foreach($this->components as $component) {
273
 
274
			$this->drawComponent($component);
275
 
276
		}
277
 
278
		$this->drawTitle();
279
		$this->drawShadow();
280
		$this->drawLabels();
281
 
282
		if($this->timing) {
283
			$this->drawTiming(microtimeFloat() - $time);
284
		}
285
 
286
		// Create graph
287
		$data = $this->get();
288
 
289
		// Put the graph in the cache if needed
290
		$this->cache($data);
291
 
292
		switch($mode) {
293
 
294
			case Graph::DRAW_DISPLAY :
295
				$this->sendHeaders();
296
				echo $data;
297
				break;
298
 
299
			case Graph::DRAW_RETURN :
300
				return $data;
301
 
302
			default :
303
				if(is_string($mode)) {
304
					file_put_contents($mode, $data);
305
				} else {
306
					awImage::drawError("Class Graph: Unable to draw the graph.");
307
				}
308
 
309
		}
310
 
311
	}
312
 
313
	private function drawLabels() {
314
 
315
		$driver = $this->getDriver();
316
 
317
		foreach($this->labels as $array) {
318
 
319
			if(count($array) === 3) {
320
 
321
				// Text in relative position
322
				list($label, $x, $y) = $array;
323
 
324
				$point = new awPoint(
325
					$x * $this->width,
326
					$y * $this->height
327
				);
328
 
329
			} else {
330
 
331
				// Text in absolute position
332
				list($label, $point) = $array;
333
 
334
			}
335
 
336
			$label->draw($driver, $point);
337
 
338
		}
339
 
340
	}
341
 
342
	private function drawTitle() {
343
 
344
		$driver = $this->getDriver();
345
 
346
		$point = new awPoint(
347
			$this->width / 2,
348
			10
349
		);
350
 
351
		$this->title->draw($driver, $point);
352
 
353
	}
354
 
355
	private function drawTiming($time) {
356
 
357
		$driver = $this->getDriver();
358
 
359
		$label = new awLabel;
360
		$label->set("(".sprintf("%.3f", $time)." s)");
361
		$label->setAlign(awLabel::LEFT, awLabel::TOP);
362
		$label->border->show();
363
		$label->setPadding(1, 0, 0, 0);
364
		$label->setBackgroundColor(new awColor(230, 230, 230, 25));
365
 
366
		$label->draw($driver, new awPoint(5, $driver->imageHeight - 5));
367
 
368
	}
369
 
370
	private function cache($data) {
371
		if(ARTICHOW_CACHE and $this->name !== NULL) {
372
 
373
			if(is_writable(ARTICHOW_CACHE_DIRECTORY) === FALSE) {
374
				awImage::drawError("Class Graph: Cache directory is not writable.");
375
			}
376
 
377
			file_put_contents($this->fileCache, $data);
378
			file_put_contents($this->fileCacheTime, $this->timeout."\n".$this->getFormatString());
379
 
380
		}
381
	}
382
 
383
	private static function cleanGraphCache($file) {
384
 
385
		list(
386
			$time,
387
			$type
388
		) = explode("\n", file_get_contents($file));
389
 
390
		$time = (int)$time;
391
 
392
		if($time !== 0 and $time < time()) {
393
			return NULL;
394
		} else {
395
			return $type;
396
		}
397
 
398
 
399
	}
400
 
401
}
402
 
403
registerClass('Graph');
404
 
405
/*
406
 * To preserve PHP 4 compatibility
407
 */
408
function microtimeFloat() {
409
	list($usec, $sec) = explode(" ", microtime());
410
	return (float)$usec + (float)$sec;
411
}
412
?>