PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/WTFW/smdoc/lib/class.graph.php

#
PHP | 376 lines | 298 code | 39 blank | 39 comment | 66 complexity | 1d8fa52ce6ebb51832d7a7ae6dc35121 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0
  1. <?php
  2. /*
  3. Copyright 2003, Paul James
  4. This file is part of the Framework for Object Orientated Web Development (Foowd).
  5. Foowd is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. Foowd is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foowd; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. /*
  18. class.graph.php
  19. Foowd graph class
  20. */
  21. /** METHOD PERMISSIONS **/
  22. if (!defined('PERMISSION_FOOWD_GRAPH_OBJECT_EDIT')) define('PERMISSION_FOOWD_GRAPH_OBJECT_EDIT', 'Gods');
  23. if (!defined('PERMISSION_FOOWD_GRAPH_OBJECT_CSV')) define('PERMISSION_FOOWD_GRAPH_OBJECT_CSV', 'Gods');
  24. /** CLASS DESCRIPTOR **/
  25. if (!defined('META_-1694284669_CLASSNAME')) define('META_-1694284669_CLASSNAME', 'foowd_graph');
  26. if (!defined('META_-1694284669_DESCRIPTION')) define('META_-1694284669_DESCRIPTION', 'Graph');
  27. /** CLASS DECLARATION **/
  28. class foowd_graph extends foowd_object {
  29. var $data;
  30. var $description;
  31. var $width;
  32. var $height;
  33. var $caption_x;
  34. var $caption_y;
  35. var $red, $green, $blue;
  36. /*** CONSTRUCTOR ***/
  37. function foowd_graph(
  38. &$foowd,
  39. $title = NULL,
  40. $data = array(),
  41. $description = NULL,
  42. $width = 300,
  43. $height = 300,
  44. $caption_x = NULL,
  45. $caption_y = NULL,
  46. $colour = array(255, 0, 0),
  47. $viewGroup = NULL,
  48. $adminGroup = NULL,
  49. $deleteGroup = NULL,
  50. $editGroup = NULL
  51. ) {
  52. $foowd->track('foowd_graph->constructor');
  53. // base object constructor
  54. parent::foowd_object($foowd, $title, $viewGroup, $adminGroup, $deleteGroup);
  55. /* set object vars */
  56. $this->data = $data;
  57. $this->description = $description;
  58. $this->width = $width;
  59. $this->height = $height;
  60. $this->caption_x = $caption_x;
  61. $this->caption_y = $caption_y;
  62. $this->red = $colour[0];
  63. $this->green = $colour[1];
  64. $this->blue = $colour[2];
  65. /* set method permissions */
  66. $className = get_class($this);
  67. $this->permissions['edit'] = getPermission($className, 'edit', 'object'. $editGroup);
  68. $this->permissions['csv'] = getPermission($className, 'csv', 'object'. $editGroup);
  69. $foowd->track();
  70. }
  71. /*** SERIALIZE FUNCTIONS ***/
  72. function __wakeup() {
  73. parent::__wakeup();
  74. $this->foowd_vars_meta['data'] = array(
  75. 'x' => '/^[0-9.-]+$/',
  76. 'y' => '/^[0-9.-]+$/'
  77. );
  78. $this->foowd_vars_meta['description'] = '/^.{1,1024}$/';
  79. $this->foowd_vars_meta['width'] = '/^[0-9]{1,4}$/';
  80. $this->foowd_vars_meta['height'] = '/^[0-9]{1,4}$/';
  81. $this->foowd_vars_meta['caption_x'] = '/^.*$/';
  82. $this->foowd_vars_meta['caption_y'] = '/^.*$/';
  83. $this->foowd_vars_meta['red'] = '/^[0-9]{1,3}$/';
  84. $this->foowd_vars_meta['green'] = '/^[0-9]{1,3}$/';
  85. $this->foowd_vars_meta['blue'] = '/^[0-9]{1,3}$/';
  86. }
  87. /*** MEMBER FUNCTIONS ***/
  88. function drawGraph() {
  89. $im = @imagecreate($this->width, $this->height) or trigger_error('Cannot initialize new GD image stream', E_USER_ERROR);
  90. $background_color = imagecolorallocate($im, 255, 255, 255);
  91. $line_colour = imagecolorallocate($im, $this->red, $this->green, $this->blue);
  92. $bar_colour = imagecolorallocate($im, 0, 0, 0);
  93. if (count($this->data) < 2) {
  94. imagestring($im, 1, 0, 0, 'There must be at least two co-ordinates', $bar_colour);
  95. imagestring($im, 1, 0, 10, 'defined to display a graph.', $bar_colour);
  96. } else {
  97. $width = $this->width - 40;
  98. $height = $this->height - 40;
  99. if (count($this->data) > ($height / 30)) { // don't display all values on axis if there are lots of co-ords and not much graph
  100. $displayAllValues = FALSE;
  101. } else {
  102. $displayAllValues = TRUE;
  103. }
  104. imageline($im, 20, 20, 20, $height + 19, $bar_colour);
  105. imageline($im, 20, $height + 19, $width + 19, $height + 19, $bar_colour);
  106. imagestring($im, 1, ($width + 20 - (strlen($this->caption_x) * 5)) / 2, $height + 30, $this->caption_x, $bar_colour);
  107. imagestringup($im, 1, 1, ($height + 20 + (strlen($this->caption_y) * 5)) / 2, $this->caption_y, $bar_colour);
  108. $firstItem = reset($this->data);
  109. $max_x = $firstItem['x']; $min_x = $firstItem['x'];
  110. $max_y = $firstItem['y']; $min_y = $firstItem['y'];
  111. foreach ($this->data as $coords) {
  112. if ($coords['x'] > $max_x) $max_x = $coords['x'];
  113. if ($coords['x'] < $min_x) $min_x = $coords['x'];
  114. if ($coords['y'] > $max_y) $max_y = $coords['y'];
  115. if ($coords['y'] < $min_y) $min_y = $coords['y'];
  116. }
  117. $scale_x = ($width - 1) / ($max_x - $min_x);
  118. $offset_x = $min_x - (20 / $scale_x);
  119. $scale_y = ($height - 1) / ($max_y - $min_y);
  120. $offset_y = $min_y + (20 / $scale_y);;
  121. $start_coords = NULL;
  122. foreach ($this->data as $end_coords) {
  123. if ($start_coords == NULL) {
  124. $start_coords = $end_coords;
  125. } else {
  126. $x1 = intval(($start_coords['x'] - $offset_x) * $scale_x);
  127. $y1 = $height - 1 - intval(($start_coords['y'] - $offset_y) * $scale_y);
  128. $x2 = intval(($end_coords['x'] - $offset_x) * $scale_x);
  129. $y2 = $height - 1 - intval(($end_coords['y'] - $offset_y) * $scale_y);
  130. //echo '(', $x1, ', ', $y1, ')(', $x2, ', ', $y2, ')<br />';
  131. imageline($im, $x1, $y1, $x2, $y2, $line_colour);
  132. if ($displayAllValues) {
  133. imagestring($im, 1, $x1, $height + 20, $start_coords['x'], $bar_colour);
  134. imagestringup($im, 1, 10, $y1, $start_coords['y'], $bar_colour);
  135. }
  136. $start_coords = $end_coords;
  137. }
  138. }
  139. if ($displayAllValues) {
  140. imagestring($im, 1, $x2, $height + 20, $start_coords['x'], $bar_colour);
  141. imagestringup($im, 1, 10, $y2, $start_coords['y'], $bar_colour);
  142. } else {
  143. imagestring($im, 1, 20, $height + 20, $min_x, $bar_colour);
  144. imagestring($im, 1, $width + 20, $height + 20, $max_x, $bar_colour);
  145. imagestringup($im, 1, 10, $height + 20, $min_y, $bar_colour);
  146. imagestringup($im, 1, 10, 20, $max_y, $bar_colour);
  147. }
  148. }
  149. imagepng($im);
  150. }
  151. /*** CLASS METHODS ***/
  152. /* create object */
  153. function class_create(&$foowd, $className) {
  154. $foowd->track('foowd_graph->class_create');
  155. if (function_exists('foowd_prepend')) foowd_prepend($foowd, $this);
  156. echo '<h1>Create new graph object</h1>';
  157. $queryTitle = new input_querystring('title', REGEX_TITLE, NULL);
  158. $createForm = new input_form('createForm', NULL, 'POST', 'Create', NULL);
  159. $createTitle = new input_textbox('createTitle', REGEX_TITLE, $queryTitle->value, 'Title:');
  160. $createDescription = new input_textbox('createDescription', '/^.{1,1024}$/', NULL, 'Description:');
  161. $createWidth = new input_textbox('createWidth', '/^[0-9]{1,4}$/', '300', 'Width:');
  162. $createHeight = new input_textbox('createHeight', '/^[0-9]{1,4}$/', '300', 'Height:');
  163. $createCaptionX = new input_textbox('createCaptionX', '/^.*$/', 'X Axis', 'X Axis Caption:');
  164. $createCaptionY = new input_textbox('createCaptionY', '/^.*$/', 'Y Axis', 'Y Axis Caption:');
  165. $createRed = new input_textbox('createRed', '/^[0-9]{1,3}$/', 255, 'Red:');
  166. $createGreen = new input_textbox('createGreen', '/^[0-9]{1,3}$/', 0, 'Green:');
  167. $createBlue = new input_textbox('createBlue', '/^[0-9]{1,3}$/', 0, 'Blue:');
  168. if ($createForm->submitted() && $createTitle->value != '') {
  169. $object = new $className(
  170. $foowd,
  171. $createTitle->value,
  172. NULL,
  173. $createDescription->value,
  174. $createWidth->value,
  175. $createHeight->value,
  176. $createCaptionX->value,
  177. $createCaptionY->value,
  178. array($createRed->value, $createGreen->value, $createBlue->value)
  179. );
  180. if ($object->objectid != 0 && $object->save($foowd, FALSE)) {
  181. echo '<p>Graph object created and saved.</p>';
  182. echo '<p><a href="', getURI(array('objectid' => $object->objectid, 'classid' => crc32(strtolower($className)), 'method' => 'edit')), '">Click here to add data to it now</a>.</p>';
  183. } else {
  184. trigger_error('Could not create graph object.');
  185. }
  186. } else {
  187. $createForm->addObject($createTitle);
  188. $createForm->addObject($createDescription);
  189. $createForm->addObject($createWidth);
  190. $createForm->addObject($createHeight);
  191. $createForm->addObject($createCaptionX);
  192. $createForm->addObject($createCaptionY);
  193. $createForm->addObject($createRed);
  194. $createForm->addObject($createGreen);
  195. $createForm->addObject($createBlue);
  196. $createForm->display();
  197. }
  198. if (function_exists('foowd_append')) foowd_append($foowd, $this);
  199. $foowd->track();
  200. }
  201. /*** METHODS ***/
  202. /* view object */
  203. function method_view(&$foowd) {
  204. $foowd->track('foowd_graph->method_edit');
  205. if (function_exists('foowd_prepend')) foowd_prepend($foowd, $this);
  206. echo '<h1>', $this->getTitle(), '</h1>';
  207. if ($this->description != NULL) {
  208. echo '<p>', htmlspecialchars($this->description), '</p>';
  209. }
  210. echo '<img src="', getURI(array('objectid' => $this->objectid, 'classid' => $this->classid, 'version' => $this->version, 'method' => 'raw')), '" width="', $this->width, '" height="', $this->height, '" alt="', $this->getTitle(), '" />';
  211. if (function_exists('foowd_append')) foowd_append($foowd, $this);
  212. $foowd->track();
  213. }
  214. function method_raw(&$foowd) {
  215. $foowd->debug = FALSE;
  216. header ("Content-type: image/png");
  217. $this->drawGraph();
  218. }
  219. /* edit object */
  220. function method_edit(&$foowd) {
  221. $foowd->track('foowd_graph->method_edit');
  222. if (function_exists('foowd_prepend')) foowd_prepend($foowd, $this);
  223. echo '<h1>Editing version ', $this->version, ' of "', $this->getTitle(), '"</h1>';
  224. $editForm = new input_form('editForm', NULL, 'POST', 'Save', NULL);
  225. $editCollision = new input_hiddenbox('editCollision', REGEX_DATETIME, time());
  226. if ($editCollision->value >= $this->updated && $editForm->submitted()) { // if we're going to update, reset collision detect
  227. $editCollision->set(time());
  228. }
  229. $editForm->addObject($editCollision);
  230. $editDescription = new input_textbox('editDescription', $this->foowd_vars_meta['description'], $this->description, 'Description:');
  231. $editWidth = new input_textbox('editWidth', $this->foowd_vars_meta['width'], $this->width, 'Width:');
  232. $editHeight = new input_textbox('editHeight', $this->foowd_vars_meta['height'], $this->height, 'Height:');
  233. $editCaptionX = new input_textbox('editCaptionX', $this->foowd_vars_meta['caption_x'], $this->caption_x, 'X Axis Caption:');
  234. $editCaptionY = new input_textbox('editCaptionY', $this->foowd_vars_meta['caption_y'], $this->caption_y, 'Y Axis Caption:');
  235. $editRed = new input_textbox('editRed', $this->foowd_vars_meta['red'], $this->red, 'Red:');
  236. $editGreen = new input_textbox('editGreen', $this->foowd_vars_meta['green'], $this->green, 'Green:');
  237. $editBlue = new input_textbox('editBlue', $this->foowd_vars_meta['blue'], $this->blue, 'Blue:');
  238. $editData = new input_textarray('editData', $this->foowd_vars_meta['data'], $this->data, 'Graph Data');
  239. $editForm->addObject($editDescription);
  240. $editForm->addObject($editWidth);
  241. $editForm->addObject($editHeight);
  242. $editForm->addObject($editCaptionX);
  243. $editForm->addObject($editCaptionY);
  244. $editForm->addObject($editRed);
  245. $editForm->addObject($editGreen);
  246. $editForm->addObject($editBlue);
  247. $editForm->addObject($editData);
  248. if (isset($foowd->user->objectid) && $this->updatorid == $foowd->user->objectid) { // author is same as last author and not anonymous, so can just update
  249. $newVersion = new input_checkbox('newVersion', TRUE, 'Do not archive previous version?');
  250. $editForm->addObject($newVersion);
  251. }
  252. $editForm->display();
  253. if ($editForm->submitted()) {
  254. if ($editCollision->value >= $this->updated) { // has not been changed since form was loaded
  255. $this->description = $editDescription->value;
  256. $this->width = $editWidth->value;
  257. $this->height = $editHeight->value;
  258. $this->caption_x = $editCaptionX->value;
  259. $this->caption_y = $editCaptionY->value;
  260. $this->red = $editRed->value;
  261. $this->green = $editGreen->value;
  262. $this->blue = $editBlue->value;
  263. $this->data = $editData->items;
  264. if (isset($newVersion)) {
  265. $createNewVersion = !$newVersion->checked;
  266. } else {
  267. $createNewVersion = TRUE;
  268. }
  269. if ($this->save($foowd, $createNewVersion)) {
  270. echo '<p>Graph object updated and saved.</p>';
  271. } else {
  272. trigger_error('Could not save graph object.');
  273. }
  274. } else { // edit collision!
  275. echo '<h3>Warning: This object has been updated by another user since you started editing, please reload the edit page and verify their changes before continuing to edit.</h3>';
  276. }
  277. }
  278. if (function_exists('foowd_append')) foowd_append($foowd, $this);
  279. $foowd->track();
  280. }
  281. /* load CSV data */
  282. function method_csv(&$foowd) {
  283. $foowd->track('foowd_graph->method_csv');
  284. if (function_exists('foowd_prepend')) foowd_prepend($foowd, $this);
  285. echo '<h1>Load CSV data</h1>';
  286. $csvForm = new input_form('editForm', NULL, 'POST', 'Load Data', NULL);
  287. $csvFile = new input_file('csvFile', 'CSV File:');
  288. $csvForm->addObject($csvFile);
  289. if (isset($foowd->user->objectid) && $this->updatorid == $foowd->user->objectid) { // author is same as last author and not anonymous, so can just update
  290. $newVersion = new input_checkbox('newVersion', TRUE, 'Do not archive previous version?');
  291. $csvForm->addObject($newVersion);
  292. }
  293. if ($csvForm->submitted()) {
  294. if ($csvFile->isUploaded()) {
  295. if ($fp = fopen($csvFile->file['tmp_name'], 'r')) {
  296. while ($line = fgetcsv($fp, 100)) {
  297. if (isset($line[0]) && isset($line[1])) {
  298. $data[] = array(
  299. 'x' => $line[0],
  300. 'y' => $line[1]
  301. );
  302. }
  303. }
  304. fclose($fp);
  305. if (isset($data)) {
  306. $this->data = $data;
  307. if (isset($newVersion)) {
  308. $createNewVersion = !$newVersion->checked;
  309. } else {
  310. $createNewVersion = TRUE;
  311. }
  312. if ($this->save($foowd, $createNewVersion)) {
  313. echo '<p>Data loaded from CSV file into graph object.</p>';
  314. } else {
  315. trigger_error('Could not save graph object.');
  316. }
  317. } else {
  318. trigger_error('No co-ordinate data in CSV file.');
  319. }
  320. } else {
  321. trigger_error('Could not open CSV file.');
  322. }
  323. } else {
  324. trigger_error($csvFile->getError());
  325. }
  326. } else {
  327. $csvForm->display();
  328. }
  329. if (function_exists('foowd_append')) foowd_append($foowd, $this);
  330. $foowd->track();
  331. }
  332. }
  333. ?>