/app/views/helpers/list.php

https://github.com/ButuzGOL/inside_wildflowercms · PHP · 307 lines · 217 code · 44 blank · 46 comment · 46 complexity · 99ddcb2f83895ce06b3c18e11a879ff8 MD5 · raw file

  1. <?php
  2. class ListHelper extends AppHelper {
  3. public $helpers = array('Html');
  4. private $_defaultSettings = array(
  5. 'model' => '',
  6. 'class' => 'list',
  7. 'id' => '',
  8. 'alias' => 'title',
  9. 'primaryKey' => 'id',
  10. 'emptyMessage' => 'There are no records to display.'
  11. );
  12. private $_emptyMessage = "There are no records to display.";
  13. private $_treeSettings = array(
  14. 'model' => '',
  15. 'alias' => 'title',
  16. 'left' => 'lft',
  17. 'right' => 'rght',
  18. 'primaryKey' => 'id',
  19. 'class' => 'list',
  20. 'emptyMessage' => 'There are no records to display.'
  21. );
  22. static $isOdd = true;
  23. /**
  24. * Generate CRUD list from Cake data
  25. *
  26. * @param array $data MPTT data from model
  27. * @param array $settings Settings
  28. * @param string $cssClass CSS class for the <ul> element
  29. * @return string List HTML or message that there are no records to display
  30. */
  31. function create($data, $settings = array()) {
  32. $settings = array_merge($this->_defaultSettings, $settings);
  33. if (empty($data)) {
  34. return "<p class=\"{$settings['class']}\">{$settings['emptyMessage']}</p>";
  35. }
  36. if (empty($settings['model'])) {
  37. trigger_error('Model class name can not be empty!');
  38. }
  39. // Start the list
  40. $html = "\n<ul";
  41. if (!empty($settings['id'])) {
  42. $html .= " id=\"{$settings['id']}\"";
  43. }
  44. if (!empty($settings['class'])) {
  45. $html .= " class=\"{$settings['class']}\"";
  46. }
  47. $html .= ">\n";
  48. $model = low($settings['model']);
  49. // Rows
  50. foreach ($data as $key => $node) {
  51. $liClass = array();
  52. if ($key % 2 == 0) {
  53. $liClass[] = 'odd';
  54. }
  55. $liClassAttr = '';
  56. if (!empty($liClass)) {
  57. $liClassAttr = ' class="' . implode(' ', $liClass) . '"';
  58. }
  59. $html .= "<li id=\"$model-{$node[$settings['model']][$settings['primaryKey']]}\"$liClassAttr>";
  60. // Item content
  61. if (isset($settings['element'])) {
  62. $view = ClassRegistry::getObject('view');
  63. $html .= $view->element($settings['element'], array('node' => $node));
  64. } else if (function_exists('treeItemCallback')) {
  65. $html .= call_user_func('treeItemCallback', $node, $this->Html);
  66. } else if (function_exists('listItemCallback')) {
  67. $html .= call_user_func('listItemCallback', $node, $this->Html);
  68. } else {
  69. $html .= $this->Html->link(
  70. $node[$settings['model']][$settings['alias']],
  71. array('action' => 'edit', 'id' => $node[$settings['model']][$settings['primaryKey']]));
  72. }
  73. $html .= "</li>\n";
  74. }
  75. $html .= "</ul>\n";
  76. return $html;
  77. }
  78. /**
  79. * Create an unordered nested list from tree data. You can define a function called
  80. * <em>treeItemCallback($nodeData, $htmlHelper)</em> to programaticaly fill
  81. * each list node.
  82. *
  83. * @param array $data
  84. * @param array $settings
  85. * @return string
  86. */
  87. function createNestedTree($data, $settings = array()) {
  88. extract($this->_treeSettings);
  89. extract($settings);
  90. // Determin limits to know when the last top node is found.
  91. if (isset($data[0][$model][$left])) {
  92. $floor = $data[0][$model][$left];
  93. $ceil = $data[0][$model][$right];
  94. foreach ($data as $node) {
  95. if ($node[$model][$right] > $ceil) {
  96. $ceil = $node[$model][$right];
  97. }
  98. }
  99. } else {
  100. $floor = $ceil = 0;
  101. }
  102. $this->_limits = array(array($floor - 1, $ceil + 1));
  103. $this->_childCount = 1;
  104. // Start the list
  105. $return = "\n<ul";
  106. if ($class) {
  107. $return .= " class=\"$class\"";
  108. }
  109. $return .= ">";
  110. foreach ($data as $i => $node) {
  111. $return .= "\n" . str_repeat("\t", $this->_childCount);
  112. $hasChildren = false;
  113. $last = false;
  114. $liClass = array();
  115. if ($node[$model][$right] <> $node[$model][$left] + 1) { // Has some children
  116. $hasChildren = true;
  117. list ($parentLeft, $parentRight) = $this->_get_parent_indexes($node[$model][$left]);
  118. $last= ife($parentRight == ($node[$model][$right] + 1), true, false);
  119. $this->_limits[] = array($node[$model][$left], $node[$model][$right]);
  120. }
  121. if (!$hasChildren && (!isset ($data[$i +1]) || ($node[$model][$right] + 1 <> $data[$i +1][$model][$left]))) {
  122. // it's the last item or the last in the current series
  123. $last = true;
  124. $liClass[] = 'last';
  125. }
  126. if ($i % 2 == 0) {
  127. $liClass[] = 'odd';
  128. }
  129. // Start the list item
  130. $lModel = low($model);
  131. $classAttr = '';
  132. if (!empty($liClass)) {
  133. $_liClass = implode(' ', $liClass);
  134. $classAttr = ' class="' . $_liClass . '"';
  135. }
  136. $return .= "<li id=\"$lModel-{$node[$model][$primaryKey]}\"$classAttr>";
  137. // Item content
  138. if (function_exists('treeItemCallback')) {
  139. $return .= call_user_func('treeItemCallback', $node, $this->Html);
  140. } else {
  141. $return .= $this->Html->link($node[$model][$alias], array('action' => 'edit', 'id' => $node[$model][$primaryKey]));
  142. }
  143. // Close the item
  144. if (isset ($data[$i +1])) {
  145. // If it's not the absolute last item
  146. if ($node[$model][$right] < $data[$i +1][$model][$left]) { // Close uls
  147. for ($j= 1; $j <= ($data[$i +1][$model][$left] - $node[$model][$right] - 1); $j++) {
  148. $this->_childCount--;
  149. if ($this->_childCount < 0) {
  150. trigger_error(__('child count less than 0 in ' . __METHOD__, E_USER_WARNING));
  151. }
  152. $return .= '</li>';
  153. $return .= "\n" . str_repeat("\t", $this->_childCount) . '</ul>';
  154. }
  155. $return .= '</li>';
  156. }
  157. elseif ($node[$model][$right] <> $node[$model][$left] + 1) { // Has some children
  158. $return .= "\n" . str_repeat("\t", $this->_childCount) . '<ul>';
  159. $this->_childCount++;
  160. } else {
  161. $return .= '</li>';
  162. }
  163. } else {
  164. // Last item in data list, close ul items
  165. $return .= '</li>';
  166. for (; $this->_childCount > 1; $this->_childCount--) {
  167. $return .= "\n" . str_repeat("\t", $this->_childCount - 1) . '</ul>';
  168. $return .= "\n" . str_repeat("\t", $this->_childCount - 1) . '</li>';
  169. }
  170. }
  171. }
  172. // Close list
  173. $return .= "</ul>\n";
  174. return $return;
  175. }
  176. /**
  177. * Create an unordered list from tree data. You can define a function called
  178. * <em>listItemCallback($nodeData, $htmlHelper)</em> to programaticaly fill
  179. * each list node.
  180. *
  181. * @param array $data
  182. * @param array $settings
  183. * @return string
  184. */
  185. function createTree($data, $settings = array()) {
  186. $settings = array_merge($this->_treeSettings, $settings);
  187. if (empty($data)) {
  188. return "<p class=\"{$settings['class']}\">{$settings['emptyMessage']}</p>";
  189. }
  190. // Start the list
  191. $return = "\n<ul";
  192. if ($settings['class']) {
  193. $return .= " class=\"{$settings['class']}\"";
  194. }
  195. $return .= ">";
  196. $rightNodes = array();
  197. foreach ($data as $i => $node) {
  198. $level = 0;
  199. // Tree mathematics part I.
  200. // Check if we should remove a node from the stack
  201. while (!empty($rightNodes) && ($rightNodes[count($rightNodes) - 1] < $node[$settings['model']][$settings['right']])) {
  202. array_pop($rightNodes);
  203. }
  204. $level = count($rightNodes);
  205. $liClass = array();
  206. $liClass[] = "level-$level";
  207. // Odd rows CSS class
  208. if ($i % 2 == 0) {
  209. $liClass[] = 'odd';
  210. }
  211. $lModel = low($settings['model']);
  212. $classAttr = '';
  213. if (!empty($liClass)) {
  214. $_liClass = implode(' ', $liClass);
  215. $classAttr = ' class="' . $_liClass . '"';
  216. }
  217. // Start the list item
  218. $return .= "<li id=\"$lModel-{$node[$settings['model']][$settings['primaryKey']]}\"$classAttr>";
  219. // Item content
  220. if (function_exists('listItemCallback')) {
  221. $return .= call_user_func('listItemCallback', $node, $this->Html, $level);
  222. } else {
  223. $return .= $this->Html->link($node[$settings['model']][$alias], array('action' => 'edit', 'id' => $node[$settings['model']][$settings['primaryKey']]));
  224. }
  225. $return .= '</li>';
  226. // Tree mathematics part II.
  227. $rightNodes[] = $node[$settings['model']][$settings['right']];
  228. }
  229. // Close list
  230. $return .= "</ul>\n";
  231. return $return;
  232. }
  233. static function isOdd() {
  234. if (self::$isOdd) {
  235. self::$isOdd = false;
  236. return true;
  237. }
  238. self::$isOdd = true;
  239. return false;
  240. }
  241. static function resetOddCounter() {
  242. self::$isOdd = true;
  243. }
  244. private function _get_parent_indexes($thisLeft) {
  245. if (!$this->_limits) {
  246. return array (
  247. 0,
  248. 0
  249. );
  250. }
  251. $parentLeft= $this->_limits[count($this->_limits) - 1][0];
  252. $parentRight= $this->_limits[count($this->_limits) - 1][1];
  253. if ($parentRight < $thisLeft) {
  254. unset ($this->_limits[count($this->_limits) - 1]);
  255. $this->_limits= array_values($this->_limits);
  256. return $this->_get_parent_indexes($thisLeft);
  257. }
  258. return array (
  259. $parentLeft,
  260. $parentRight
  261. );
  262. }
  263. }