PageRenderTime 64ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/site/sites/all/modules/click_heatmap/clickheat/classes/HeatmapFromClicks.class.php

https://bitbucket.org/kaerast/ppl
PHP | 280 lines | 205 code | 11 blank | 64 comment | 43 complexity | 88c32e7d1d598904d1d61564f5aba1ea MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. <?php
  2. /**
  3. * ClickHeat : Classe de génération des cartes depuis un fichier ClickHeat / Maps generation class from a ClickHeat logfile
  4. *
  5. * Cette classe est VOLONTAIREMENT écrite pour PHP 4
  6. * This class is VOLUNTARILY written for PHP 4
  7. *
  8. * @author Yvan Taviaud - LabsMedia - www.labsmedia.com
  9. * @since 12/05/2007
  10. **/
  11. class HeatmapFromClicks extends Heatmap
  12. {
  13. /** @var array $files Fichiers de suivi à étudier / Logfiles to use */
  14. var $files = array();
  15. /** @var string $browser Browser filter */
  16. var $browser;
  17. /** @var array $layout Webpage layout */
  18. var $layout;
  19. /** @var integer $minScreen Screen filter */
  20. var $minScreen;
  21. /** @var integer $maxScreen Screen filter */
  22. var $maxScreen;
  23. /**
  24. * Add a file to parse and check existence
  25. *
  26. * @param string $file
  27. */
  28. function addFile($file)
  29. {
  30. if (file_exists($file))
  31. {
  32. $this->files[] = $file;
  33. }
  34. }
  35. /**
  36. * Do some tasks before drawing (database connection...)
  37. **/
  38. function startDrawing()
  39. {
  40. return true;
  41. }
  42. /**
  43. * Find pixels coords and draw these on the current image
  44. *
  45. * @param integer $image Number of the image (to be used with $this->height)
  46. * @return boolean Success
  47. **/
  48. function drawPixels($image)
  49. {
  50. /** If it's not the first image, just use the value stored in the temp files */
  51. if ($image !== 0)
  52. {
  53. if (file_exists($this->cache.sprintf($this->file, $image).'_log'))
  54. {
  55. $f = fopen($this->cache.sprintf($this->file, $image).'_log', 'r');
  56. while (feof($f) === false)
  57. {
  58. $click = explode('|', trim(fgets($f, 1024)));
  59. if (count($click) === 3)
  60. {
  61. $x = (int) $click[0];
  62. $y = (int) $click[1];
  63. $c = (bool) $click[2];
  64. if ($this->heatmap === true)
  65. {
  66. /** Apply a calculus for the step, with increases the speed of rendering: step = 3, then pixel is drawn at x = 2 (center of a 3x3 square) */
  67. $x -= $x % $this->step - $this->startStep;
  68. $y -= $y % $this->step - $this->startStep;
  69. /** Add 1 to the current color of this pixel (color which represents the sum of clicks on this pixel) */
  70. $color = imagecolorat($this->image, $x, $y) + 1;
  71. imagesetpixel($this->image, $x, $y, $color);
  72. $this->maxClicks = max($this->maxClicks, $color);
  73. }
  74. else
  75. {
  76. /** Put a red or green cross at the click location */
  77. $color = $c === true ? 0xFF0000 : 0x00DC00;
  78. imageline($this->image, $x - 2, $y - 2, $x + 2, $y + 2, $color);
  79. imageline($this->image, $x + 2, $y - 2, $x - 2, $y + 2, $color);
  80. }
  81. }
  82. }
  83. fclose($f);
  84. unlink($this->cache.sprintf($this->file, $image).'_log');
  85. }
  86. return true;
  87. }
  88. $leftWidth = (int) $this->layout[1];
  89. $centerWidth = (int) $this->layout[2];
  90. $rightWidth = (int) $this->layout[3];
  91. if ($leftWidth !== 0 && $centerWidth !== 0 && $rightWidth === 0)
  92. {
  93. /** Fixed left menu and fixed center ? Fall back to a fixed left menu only */
  94. $leftWidth += $centerWidth;
  95. $centerWidth = 0;
  96. }
  97. elseif ($leftWidth === 0 && $centerWidth !== 0 && $rightWidth !== 0)
  98. {
  99. /** Fixed right menu and fixed center ? Fall back to a fixed right menu only */
  100. $rightWidth += $centerWidth;
  101. $centerWidth = 0;
  102. }
  103. elseif ($leftWidth !== 0 && $centerWidth !== 0 && $rightWidth !== 0)
  104. {
  105. /** Everything is fixed ?? */
  106. return $this->raiseError(LANG_ERROR_FIXED);
  107. }
  108. $totalWidth = $leftWidth + $centerWidth + $rightWidth;
  109. for ($file = 0; $file < count($this->files); $file++)
  110. {
  111. /** Read clicks in the log file */
  112. $f = @fopen($this->files[$file], 'r');
  113. if ($f === false)
  114. {
  115. return $this->raiseError(LANG_ERROR_FILE.': '.$this->files[$file]);
  116. }
  117. $buffer = '';
  118. $count = 0;
  119. while (true)
  120. {
  121. $buffer .= fgets($f, 1024);
  122. /** Grouping by 1000 clicks */
  123. if (feof($f) === false && $count++ !== 1000)
  124. {
  125. continue;
  126. }
  127. /** Do a regular match (faster and easier for large volume of data) */
  128. preg_match_all('~^(\d+)\|(\d+)\|(\d+)\|'.($this->browser === 'all' ? '[a-z]+' : $this->browser).'\|(\d)$~m', $buffer, $clicks);
  129. $buffer = '';
  130. for ($i = 0, $max = count($clicks[1]); $i < $max; $i++)
  131. {
  132. $x = (int) $clicks[1][$i]; // X
  133. $y = (int) $clicks[2][$i]; // Y
  134. $w = (int) $clicks[3][$i]; // display width
  135. $c = ($clicks[4][$i] < 3); // left click
  136. /** X is not in the range of sizes, or right click for heatmap, or X is greater than screen size, the website is too large for the window, so we don't know where the click is... ignore those clicks */
  137. if ($x <= $this->minScreen || $x > $this->maxScreen || $this->heatmap === true && $c === false || $x > $w)
  138. {
  139. continue;
  140. }
  141. /** Correction of X for liquid and/or fixed layouts */
  142. if ($w <= $totalWidth)
  143. {
  144. /** Display's width is less than fixed content's one, X is absolute, many thanks to «rollenc» for pointing this out and this fix */
  145. }
  146. elseif ($leftWidth !== 0 && $centerWidth === 0 && $rightWidth === 0)
  147. {
  148. /** Left fixed menu */
  149. if ($x <= $leftWidth)
  150. {
  151. /** Click in the left menu: X is good */
  152. }
  153. else
  154. {
  155. /** Apply a percentage on the rest of the screen */
  156. $x = $leftWidth + ceil(($this->width - $leftWidth) * ($x - $leftWidth) / ($w - $leftWidth));
  157. }
  158. }
  159. elseif ($leftWidth === 0 && $centerWidth === 0 && $rightWidth !== 0)
  160. {
  161. /** Right fixed menu */
  162. if ($w - $x <= $rightWidth)
  163. {
  164. /** Click in the right menu: X is good, but relative to the right border */
  165. $x = $this->width - ($w - $x);
  166. }
  167. else
  168. {
  169. /** Apply a percentage on the rest of the screen */
  170. $x = ceil(($this->width - $rightWidth) * $x / ($w - $rightWidth));
  171. }
  172. }
  173. elseif ($leftWidth !== 0 && $centerWidth === 0 && $rightWidth !== 0)
  174. {
  175. /** Left and right fixed menus */
  176. if ($w - $x <= $rightWidth)
  177. {
  178. /** Click in the right menu: X is good, but relative to the right border */
  179. $x = $this->width - ($w - $x);
  180. }
  181. elseif ($x <= $leftWidth)
  182. {
  183. /** Click in the left menu: X is good */
  184. }
  185. else
  186. {
  187. /** Apply a percentage on the rest of the screen */
  188. $x = $leftWidth + ceil(($this->width - $leftWidth - $rightWidth) * ($x - $leftWidth) / ($w - $leftWidth - $rightWidth));
  189. }
  190. }
  191. elseif ($leftWidth === 0 && $centerWidth !== 0 && $rightWidth === 0)
  192. {
  193. /** Fixed centered content */
  194. if (abs($x - $w / 2) <= $centerWidth / 2)
  195. {
  196. /** Click is in the centered content */
  197. $x = ($this->width - $w) / 2 + $x;
  198. }
  199. elseif ($x < $w / 2)
  200. {
  201. /** Click is at the left of the centered content */
  202. $x = ($this->width - $centerWidth) / ($w - $centerWidth) * $x;
  203. }
  204. else
  205. {
  206. /** Click is at the right of the centered content */
  207. $x = ($this->width + $centerWidth) / 2 + ($this->width - $centerWidth) / ($w - $centerWidth) * ($x - ($w + $centerWidth) / 2);
  208. }
  209. }
  210. else
  211. {
  212. /** Layout 100% */
  213. $x = $this->width / $w * $x;
  214. }
  215. $x = (int) $x;
  216. $y = (int) $y;
  217. if ($x < 0 || $x >= $this->width)
  218. {
  219. continue;
  220. }
  221. if ($y >= 0 && $y < $this->height)
  222. {
  223. if ($this->heatmap === true)
  224. {
  225. /** Apply a calculus for the step, with increases the speed of rendering: step = 3, then pixel is drawn at x = 2 (center of a 3x3 square) */
  226. $x -= $x % $this->step - $this->startStep;
  227. $y -= $y % $this->step - $this->startStep;
  228. /** Add 1 to the current color of this pixel (color which represents the sum of clicks on this pixel) */
  229. $color = imagecolorat($this->image, $x, $y) + 1;
  230. imagesetpixel($this->image, $x, $y, $color);
  231. $this->maxClicks = max($this->maxClicks, $color);
  232. }
  233. else
  234. {
  235. /** Put a red or green cross at the click location */
  236. $color = $c === true ? 0xFF0000 : 0x00DC00;
  237. imageline($this->image, $x - 2, $y - 2, $x + 2, $y + 2, $color);
  238. imageline($this->image, $x + 2, $y - 2, $x - 2, $y + 2, $color);
  239. }
  240. }
  241. else
  242. {
  243. /** Append to the temporary log of this image */
  244. error_log($x.'|'.($y % $this->height).'|'.$c."\n", 3, $this->cache.sprintf($this->file, ceil($y / $this->height) - 1).'_log');
  245. }
  246. /** Looking for the maximum height of click */
  247. $this->maxY = max($y, $this->maxY);
  248. }
  249. unset($clicks);
  250. if ($count !== 1001)
  251. {
  252. break;
  253. }
  254. $count = 0;
  255. }
  256. fclose($f);
  257. }
  258. return true;
  259. }
  260. /**
  261. * Do some cleaning or ending tasks (close database, reset array...)
  262. **/
  263. function finishDrawing()
  264. {
  265. $this->files = array();
  266. return true;
  267. }
  268. }
  269. ?>