PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/smarty_plugins/block.report.php

http://github.com/MrAnchovy/kohana-module-smarty
PHP | 264 lines | 177 code | 30 blank | 57 comment | 46 complexity | 7ea783f6dd2e7d1430b954c4e0415be2 MD5 | raw file
  1. <?php
  2. /**
  3. * Smarty {report}{/report} block plugin
  4. *
  5. * Banded Report Generator Framework
  6. *
  7. * This is the main block for this framework and it acts as a container for the
  8. * rest of the {report_*} block types and handles the looping requirements of
  9. * the given dataset.
  10. *
  11. * @type block
  12. * @name report
  13. * @version 0.1.6
  14. * @see http://www.phpinsider.com/smarty-forum/viewtopic.php?t=4125
  15. *
  16. * @author boots < jayboots @at@ yahoo com >
  17. * @copyright brainpower, boots, 2004-2005
  18. * @license LGPL
  19. *
  20. * @thanks messju mohr, sophistry
  21. *
  22. * @param recordset REQUIRED
  23. * @param record REQUIRED
  24. * @param groups default: null
  25. * @param resort default: false
  26. */
  27. function smarty_block_report($params, $content, &$smarty, &$repeat)
  28. {
  29. $_params =& smarty_get_current_plugin_params($smarty);
  30. if (is_null($content)) {
  31. $_params['report'] = smarty_block_report__initialize($smarty, $repeat, $params);
  32. smarty_block_report__process_next($smarty, $repeat, $_params['report']);
  33. } else {
  34. smarty_block_report__process_next($smarty, $repeat, $_params['report']);
  35. if (!$repeat)
  36. return smarty_block_report__return_content($smarty, $repeat, $_params['report'], $content);
  37. }
  38. }
  39. function smarty_block_report__initialize(&$smarty, &$repeat, $params)
  40. {
  41. if (!array_key_exists('recordset', $params)) {
  42. $smarty->trigger_error("{report}: parameter 'recordset' not given.", E_USER_ERROR);
  43. }
  44. if (!array_key_exists('record', $params)) {
  45. $smarty->trigger_error("{report}: parameter 'record' not given.", E_USER_ERROR);
  46. }
  47. $_params = array(
  48. // setup the basic report data structure
  49. 'recordset' => (is_array($params['recordset'])) ? $params['recordset'] : array()
  50. , 'buffer' => ''
  51. , 'header' => array('report'=>array('buffer'=>''), 'group'=>array('buffer'=>array()))
  52. , 'group' => array()
  53. , 'groups' => array()
  54. , 'stats' => array()
  55. // setup the record data sub-structure
  56. , 'record' => array(
  57. 'name' => $params['record']
  58. , 'count' => (is_array($params['recordset'])) ? count($params['recordset']) : 0
  59. , 'first' => false
  60. , 'last' => false
  61. , 'iteration' => 0
  62. , 'prev' => null
  63. , 'curr' => null
  64. , 'next' => null
  65. , 'fields' => (is_array($params['recordset']) && count($params['recordset'])) ? array_keys($params['recordset'][0]) : array()
  66. )
  67. );
  68. // setup groups, if any
  69. if (array_key_exists('groups', $params)) {
  70. $groups = preg_split("/[\s,]+/", $params['groups'], -1, PREG_SPLIT_NO_EMPTY);
  71. $_params['groups'] = $groups;
  72. foreach ($_params['groups'] as $group) {
  73. if (!in_array($group, $_params['record']['fields'], true)) {
  74. $smarty->trigger_error("{report}: given group '$group' does not have a corresponding record field in given recordset.", E_USER_ERROR);
  75. return;
  76. }
  77. }
  78. // re-sort array
  79. if (array_key_exists('resort', $params) && $params['resort']) {
  80. smarty_block_report__group_sort($groups);
  81. usort($_params['recordset'], 'smarty_block_report__group_sort');
  82. }
  83. }
  84. return $_params;
  85. }
  86. function smarty_block_report__process_next(&$smarty, &$repeat, &$params)
  87. {
  88. // iterate the recordset
  89. $recordset =& $params['recordset'];
  90. $record =& $params['record'];
  91. $group =& $params['group'];
  92. // increase current counts
  93. ++$record['iteration'];
  94. if (is_null($record['prev']) && is_null($record['curr']) && count($recordset)) {
  95. // on the first iteration we load current and next
  96. $record['curr'] = array_shift($recordset);
  97. $record['next'] = (count($recordset)) ? array_shift($recordset) : null;
  98. $record['first'] = true;
  99. foreach ($record['curr'] as $field=>$value) {
  100. $params['stats']['sum'][$field] = $value;
  101. $params['stats']['count'][$field] = 1;
  102. $params['stats']['avg'][$field] = $value;
  103. }
  104. } else if (!is_null($record['next'])) {
  105. // on a normal iteration we load current from next and then reload next
  106. $record['prev'] = $record['curr'];
  107. $record['curr'] = $record['next'];
  108. $record['next'] = (count($recordset)) ? array_shift($recordset) : null;
  109. $record['first'] = false;
  110. foreach ($record['curr'] as $field=>$value) {
  111. if (is_numeric($value)) {
  112. $params['stats']['sum'][$field] += $value;
  113. ++$params['stats']['count'][$field];
  114. $params['stats']['avg'][$field] = $params['stats']['sum'][$field]/$params['stats']['count'][$field];
  115. }
  116. }
  117. } else {
  118. // there were no iterations at all
  119. // decrease current counts to counter-act increase
  120. --$record['iteration']; // should = -1
  121. }
  122. // is there anything left to do?
  123. $repeat = !$record['last'];
  124. $record['last'] = is_null($record['next']) && !is_null($record['curr']);
  125. // process grouping levels
  126. foreach ($params['groups'] as $_group) {
  127. if (!is_null($record['curr'])) {
  128. if ($record['prev'][$_group] != $record['curr'][$_group] OR ($record['prev'][$prev_group] != $record['curr'][$prev_group])) {
  129. $group[$_group]['first'] = true;
  130. foreach ($record['curr'] as $field=>$value) {
  131. $group[$_group]['stats']['sum'][$field] = $value;
  132. $group[$_group]['stats']['count'][$field] = 1;
  133. $group[$_group]['stats']['avg'][$field] = $value;
  134. }
  135. } else {
  136. $group[$_group]['first'] = false;
  137. foreach ($record['curr'] as $field=>$value) {
  138. if (is_numeric($value)) {
  139. $group[$_group]['stats']['sum'][$field] += $value;
  140. ++$group[$_group]['stats']['count'][$field];
  141. $group[$_group]['stats']['avg'][$field] = $group[$_group]['stats']['sum'][$field]/$group[$_group]['stats']['count'][$field];
  142. }
  143. }
  144. }
  145. if ($record['last']) {
  146. $group[$_group]['last'] = true;
  147. } else if (($record['curr'][$_group] == $record['next'][$_group]) AND ($record['curr'][$prev_group] != $record['next'][$prev_group])) {
  148. $group[$_group]['last'] = true;
  149. } else if (($record['curr'][$_group] != $record['next'][$_group])) {
  150. $group[$_group]['last'] = true;
  151. } else {
  152. $group[$_group]['last'] = false;
  153. }
  154. } else {
  155. $group[$_group]['first'] = is_null($record['prev']);
  156. $group[$_group]['last'] = is_null($record['next']);
  157. }
  158. $prev_group = $_group;
  159. }
  160. if (isset($record['curr'])) {
  161. $smarty->assign($record['name'], $record['curr']);
  162. }
  163. }
  164. function smarty_block_report__return_content(&$smarty, &$repeat, &$params, $content)
  165. {
  166. // only return content generated stored in the output buffer by sub {report_*}
  167. $buffer = str_replace('##SMARTY_BLOCK_REPORT_HEADER##', $params['header']['report']['buffer'], $params['buffer']);
  168. foreach ($params['header']['group']['buffer'] as $group=>$headers) {
  169. foreach ($headers as $group_buffer) {
  170. $buffer = preg_replace("/##SMARTY_BLOCK_GROUP_HEADER_{$group}##/", smarty_block_report__quote_replace($group_buffer), $buffer, 1);
  171. }
  172. }
  173. return $buffer;
  174. }
  175. function smarty_block_report__quote_replace($string)
  176. {
  177. return strtr($string, array('\\' => '\\\\', '$' => '\\$'));
  178. }
  179. /**
  180. * multi-column recordset sorter callback for use with usort et al.
  181. *
  182. * usage:
  183. * smarty_block_report__group_sort($sort_keys_array);
  184. * usort($recordset, 'smarty_block_report__group_sort');
  185. *
  186. * where:
  187. * $recordset is an indexed array of records and each record is an associative
  188. * array having the same set of fields in each record
  189. *
  190. * $sort_key_array is an array of key names which are present in every record
  191. * of the recordset and are given in the required sort order
  192. */
  193. function smarty_block_report__group_sort($a, $b=null)
  194. {
  195. static $sort_keys = array();
  196. if (is_null($b) && !is_null($a)) {
  197. // when $b is null, the $a is assumed to contain the keys to sort on
  198. $sort_keys = $a;
  199. } else {
  200. $result = 0; // assume equal
  201. foreach ($sort_keys as $key) {
  202. if ($a[$key] < $b[$key]) {
  203. $result = -1;
  204. break;
  205. } else if ($a[$key] > $b[$key]) {
  206. $result = 1;
  207. break;
  208. }
  209. }
  210. return $result;
  211. }
  212. }
  213. /**
  214. * GENERAL PLUGIN HELPERS
  215. */
  216. function &smarty_get_parent_plugin_params(&$smarty, $parent_plugin_name)
  217. {
  218. for ($i=count($smarty->_tag_stack)-1; $i>=0; $i--) {
  219. $tag_name = $smarty->_tag_stack[$i][0];
  220. if ($tag_name == $parent_plugin_name) break;
  221. }
  222. if ($i<0) {
  223. /* $parent_plugin_name not found */
  224. list($plugin_name, $plugin_params) = $smarty->_tag_stack[count($smarty->_tag_stack)-1];
  225. $smarty->trigger_error("\{$plugin_name\}: not inside \{$parent_plugin_name\}-context", E_USER_ERROR);
  226. return;
  227. } else {
  228. return $smarty->_tag_stack[$i][1];
  229. }
  230. }
  231. function &smarty_get_current_plugin_params(&$smarty)
  232. {
  233. return $smarty->_tag_stack[count($smarty->_tag_stack)-1][1];
  234. }