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// Artichow configuration 11/* <php5> */ 12if(is_file(dirname(__FILE__)."/Artichow.cfg.php")) { // For PHP 4+5 version 13 require_once dirname(__FILE__)."/Artichow.cfg.php"; 14} 15/* </php5> */ 16 17// Some useful files 18require_once ARTICHOW."/Component.class.php"; 19require_once ARTICHOW."/Image.class.php"; 20require_once ARTICHOW."/common.php"; 21 22require_once ARTICHOW."/inc/Grid.class.php"; 23require_once ARTICHOW."/inc/Tools.class.php"; 24require_once ARTICHOW."/inc/Drawer.class.php"; 25require_once ARTICHOW."/inc/Math.class.php"; 26require_once ARTICHOW."/inc/Tick.class.php"; 27require_once ARTICHOW."/inc/Axis.class.php"; 28require_once ARTICHOW."/inc/Legend.class.php"; 29require_once ARTICHOW."/inc/Mark.class.php"; 30require_once ARTICHOW."/inc/Label.class.php"; 31require_once ARTICHOW."/inc/Text.class.php"; 32require_once ARTICHOW."/inc/Color.class.php"; 33require_once ARTICHOW."/inc/Font.class.php"; 34require_once ARTICHOW."/inc/Gradient.class.php"; 35 36// Catch all errors 37ob_start(); 38 39/** 40 * A graph 41 * 42 * @package Artichow 43 */ 44class awGraph extends awImage { 45 46 /** 47 * Graph name 48 * 49 * @var string 50 */ 51 protected $name; 52 53 /** 54 * Cache timeout 55 * 56 * @var int 57 */ 58 protected $timeout = 0; 59 60 /** 61 * Graph timing ? 62 * 63 * @var bool 64 */ 65 protected $timing; 66 67 /** 68 * Components 69 * 70 * @var array 71 */ 72 private $components = array(); 73 74 /** 75 * Graph title 76 * 77 * @var Label 78 */ 79 public $title; 80 81 /** 82 * Construct a new awgraph 83 * 84 * @param int $width Graph width 85 * @param int $height Graph height 86 * @param string $name Graph name for the cache (must be unique). Let it null to not use the cache. 87 * @param int $timeout Cache timeout (unix timestamp) 88 */ 89 public function __construct($width = NULL, $height = NULL, $name = NULL, $timeout = 0) { 90 91 parent::__construct(); 92 93 $this->setSize($width, $height); 94 95 if(ARTICHOW_CACHE) { 96 97 $this->name = $name; 98 $this->timeout = $timeout; 99 100 // Clean sometimes all the cache 101 if(mt_rand(0, 5000) === 0) { 102 awGraph::cleanCache(); 103 } 104 105 if($this->name !== NULL) { 106 107 $file = ARTICHOW."/cache/".$this->name."-time"; 108 109 if(is_file($file)) { 110 111 $type = awGraph::cleanGraphCache($file); 112 113 if($type === NULL) { 114 awGraph::deleteFromCache($this->name); 115 } else { 116 header("Content-Type: image/".$type); 117 readfile(ARTICHOW."/cache/".$this->name.""); 118 exit; 119 } 120 121 } 122 123 } 124 125 } 126 127 128 $this->title = new awLabel( 129 NULL, 130 new awDejaVuSans(16), 131 NULL, 132 0 133 ); 134 $this->title->setAlign(awLabel::CENTER, awLabel::BOTTOM); 135 136 } 137 138 /** 139 * Delete a graph from the cache 140 * 141 * @param string $name Graph name 142 * @return bool TRUE on success, FALSE on failure 143 */ 144 public static function deleteFromCache($name) { 145 146 if(ARTICHOW_CACHE) { 147 148 if(is_file(ARTICHOW."/cache/".$name."-time")) { 149 unlink(ARTICHOW."/cache/".$name.""); 150 unlink(ARTICHOW."/cache/".$name."-time"); 151 } 152 153 } 154 155 } 156 157 /** 158 * Delete all graphs from the cache 159 */ 160 public static function deleteAllCache() { 161 162 if(ARTICHOW_CACHE) { 163 164 $dp = opendir(ARTICHOW."/cache"); 165 166 while($file = readdir($dp)) { 167 if($file !== '.' and $file != '..') { 168 unlink(ARTICHOW."/cache/".$file); 169 } 170 } 171 172 } 173 174 } 175 176 /** 177 * Clean cache 178 */ 179 public static function cleanCache() { 180 181 if(ARTICHOW_CACHE) { 182 183 $glob = glob(ARTICHOW."/cache/*-time"); 184 185 foreach($glob as $file) { 186 187 $type = awGraph::cleanGraphCache($file); 188 189 if($type === NULL) { 190 $name = ereg_replace(".*/(.*)\-time", "\\1", $file); 191 awGraph::deleteFromCache($name); 192 } 193 194 } 195 196 } 197 198 } 199 200 /** 201 * Enable/Disable graph timing 202 * 203 * @param bool $timing 204 */ 205 public function setTiming($timing) { 206 $this->timing = (bool)$timing; 207 } 208 209 /** 210 * Add a component to the graph 211 * 212 * @param awComponent $component 213 */ 214 public function add(awComponent $component) { 215 216 $this->components[] = $component; 217 218 } 219 220 /** 221 * Build the graph and draw component on it 222 * Image is sent to the user browser 223 */ 224 public function draw() { 225 226 if($this->timing) { 227 $time = microtimeFloat(); 228 } 229 230 $this->create(); 231 232 foreach($this->components as $component) { 233 234 $this->drawComponent($component); 235 236 } 237 238 $this->drawTitle(); 239 $this->drawShadow(); 240 241 if($this->timing) { 242 $this->drawTiming(microtimeFloat() - $time); 243 } 244 245 $this->send(); 246 247 if(ARTICHOW_CACHE) { 248 249 if($this->name !== NULL) { 250 251 $data = ob_get_contents(); 252 253 if(is_writable(ARTICHOW."/cache") === FALSE) { 254 trigger_error("Cache directory is not writable"); 255 } 256 257 $file = ARTICHOW."/cache/".$this->name.""; 258 file_put_contents($file, $data); 259 260 $file .= "-time"; 261 file_put_contents($file, $this->timeout."\n".$this->getFormat()); 262 263 } 264 265 } 266 267 } 268 269 private function drawTitle() { 270 271 $drawer = $this->getDrawer(); 272 273 $point = new awPoint( 274 $this->width / 2, 275 10 276 ); 277 278 $this->title->draw($drawer, $point); 279 280 } 281 282 private function drawTiming($time) { 283 284 $drawer = $this->getDrawer(); 285 286 $label = new awLabel; 287 $label->set("(".sprintf("%.3f", $time)." s)"); 288 $label->setAlign(awLabel::LEFT, awLabel::TOP); 289 $label->border->show(); 290 $label->setPadding(1, 0, 0, 0); 291 $label->setBackgroundColor(new awColor(230, 230, 230, 25)); 292 293 $label->draw($drawer, new awPoint(5, $drawer->height - 5)); 294 295 } 296 297 private static function cleanGraphCache($file) { 298 299 list( 300 $time, 301 $type 302 ) = explode("\n", file_get_contents($file)); 303 304 $time = (int)$time; 305 306 if($time !== 0 and $time < time()) { 307 return NULL; 308 } else { 309 return $type; 310 } 311 312 313 } 314 315} 316 317registerClass('Graph'); 318 319/* 320 * To preserve PHP 4 compatibility 321 */ 322function microtimeFloat() { 323 list($usec, $sec) = explode(" ", microtime()); 324 return (float)$usec + (float)$sec; 325} 326?> 327