Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.FamilyAbsoluteOrder.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 /**
7  * Generation of PHP Document classes
8  *
9  * @author Anakeen
10  * @package FDL
11  * @subpackage
12  */
13 /**
14  */
15 
16 namespace Dcp;
17 
19 {
20  const firstOrder = "::first";
21  const autoOrder = "::auto";
22  /**
23  * @param array $relativeOrders
24  * @param int $familyId
25  *
26  * @brief input relativeOrders is a linear Array
27  * (
28  * [0] => Array
29  * (
30  * [id] => tst_bc500
31  * [parent] =>
32  * [family] => 52973
33  * [prev] => ::first
34  * )
35  * [1] => Array
36  * (
37  * [id] => tst_b550
38  * [parent] => tst_bc500
39  * [family] => 52973
40  * [prev] => ::first
41  * )
42  * ....
43  * @return array
44  */
45  public static function getAbsoluteOrders($relativeOrders, $familyId)
46  {
47  // self::debug($relativeOrders, "");
48  // First get all family ancestors
49  $familyIds = self::getFamilyInherits($familyId);
50  $tree = [];
51  foreach ($familyIds as $familyId) {
52  $subTree = [];
53  foreach ($relativeOrders as $relativeOrder) {
54  if ($relativeOrder["family"] == $familyId) {
55  $subTree[$relativeOrder["id"]] = $relativeOrder;
56  }
57  }
58  self::updateAttributeTree($tree, $subTree);
59  }
60  self::checkTree($tree);
61  $linear = self::linearOrderTree($tree);
62  foreach ($relativeOrders as $relativeOrder) {
63  if (array_search($relativeOrder["id"], $linear) === false) {
64  $linear[] = $relativeOrder["id"];
65  }
66  if ($relativeOrder["parent"] && array_search($relativeOrder["parent"], $linear) === false) {
67  $linear[] = $relativeOrder["parent"];
68  }
69  }
70  return $linear;
71  }
72  /**
73  * Complete information (prev) when absolute numeric order is done
74  *
75  * @param array $attributes
76  * @param $familyId
77  */
78  public static function completeForNumericOrder(array & $attributes, $familyId)
79  {
80  $familyIds = self::getFamilyInherits($familyId);
81  $famAttribute = [];
82  foreach ($familyIds as $familyId) {
83 
84  foreach ($attributes as $oneAttribute) {
85  if ($oneAttribute["family"] == $familyId) {
86  $famAttribute[$oneAttribute["id"]] = $oneAttribute;
87  }
88  }
89  self::completeForNumericOrderByFamilyLevel($famAttribute);
90  foreach ($famAttribute as $oneAttribute) {
91  $key = $oneAttribute["id"] . "/" . $oneAttribute["family"];
92  $attributes[$key] = $oneAttribute;
93  }
94  }
95 
96  uasort($attributes, function ($a, $b)
97  {
98  return self::sortAttributeCallBackfunction($a, $b);
99  });
100  }
101  /**
102  * Complete information (previous) for a attribute set of a given family
103  *
104  * @param array $familyAttributes
105  */
106  protected static function completeForNumericOrderByFamilyLevel(array & $familyAttributes)
107  {
108  foreach ($familyAttributes as & $anAttribute) {
109  $anAttribute["structLevel"] = self::getStructLevel($anAttribute["id"], $familyAttributes);
110  if ($anAttribute["numOrder"] === 0 || (is_float($anAttribute["numOrder"]))) {
111  $absOrder = self::getNumericOrder($anAttribute["id"], $familyAttributes);
112  if ($anAttribute["numOrder"] === 0) {
113  $anAttribute["numOrder"] = $absOrder;
114  } else {
115  $anAttribute["numOrder"] = min($anAttribute["numOrder"], $absOrder);
116  }
117  }
118  $anAttribute["familyLevel"] = self::getFamilyLevel($anAttribute["family"]);
119  }
120 
121  uasort($familyAttributes, function ($a, $b)
122  {
123  return self::sortAttributeCallBackfunction($a, $b);
124  });
125  foreach ($familyAttributes as & $anAttribute) {
126  if (!$anAttribute["prev"]) {
127  $anAttribute["prev"] = self::getPrevious($anAttribute["id"], $familyAttributes);
128  }
129  }
130  uasort($familyAttributes, function ($a, $b)
131  {
132  if ($a["numOrder"] > $b["numOrder"]) {
133  return 1;
134  }
135  if ($a["numOrder"] < $b["numOrder"]) {
136  return -1;
137  }
138  return 0;
139  });
140  }
141  /** @noinspection PhpUnusedPrivateMethodInspection
142  * @param array $r
143  * @param string $text
144  */
145  private static function debug(array $r, $text = "")
146  {
147  printf("\n========= %s======== \n", $text);
148 
149  $first = current($r);
150  printf("%20s|", "index");
151  foreach (array_keys($first) as $h) {
152 
153  printf("%20s|", $h);
154  }
155  print "\n";
156 
157  foreach ($r as $k => $sr) {
158  printf("%20s|", $k);
159  foreach ($sr as $item) {
160  printf("%20s|", $item);
161  }
162  printf("\n");
163  }
164  }
165 
166  protected static function sortAttributeCallBackfunction($a, $b)
167  {
168  if ($a["structLevel"] > $b["structLevel"]) {
169  return 1;
170  }
171  if ($a["structLevel"] < $b["structLevel"]) {
172  return -1;
173  }
174  if ($a["numOrder"] > $b["numOrder"]) {
175  return 1;
176  }
177  if ($a["numOrder"] < $b["numOrder"]) {
178  return -1;
179  }
180  return 0;
181  }
182  /**
183  * Get family level of inheritance of family (0 means top family)
184  *
185  * @param int $famid
186  *
187  * @return int
188  */
189  protected static function getFamilyLevel($famid)
190  {
191  return count(self::getFamilyInherits($famid));
192  }
193  /**
194  * Get family ancestors
195  *
196  * @param $familyId
197  *
198  * @return int[][]
199  */
200  protected static function getFamilyInherits($familyId)
201  {
202  static $inherits = [];
203 
204  if (empty($inherits[$familyId])) {
205  $tfromid[] = $familyId;
206  $childfamilyId = $familyId;
207  while ($childfamilyId = getFamFromId("", $childfamilyId)) {
208  $tfromid[] = $childfamilyId;
209  }
210  $inherits[$familyId] = array_reverse($tfromid);
211  }
212  return $inherits[$familyId];
213  }
214  /**
215  * Get structure level for an attribute (0 means top level - for tabs or frame)
216  *
217  * @param string $attrid
218  * @param array $attributes
219  *
220  * @return int
221  * @throws \Dcp\Core\Exception
222  */
223  protected static function getStructLevel($attrid, array $attributes)
224  {
225  $level = 0;
226  while (!empty($attributes[$attrid]["parent"])) {
227  $attrid = $attributes[$attrid]["parent"];
228  $level++;
229  if ($level > 5) {
230  throw new \Dcp\Core\Exception("ATTR0214", $attrid);
231  }
232  }
233  return $level;
234  }
235  /**
236  * Get previous attribute order when only numeric order is done
237  *
238  * @param string $attrid
239  * @param array $sortedAttributes
240  *
241  * @return string
242  */
243  protected static function getPrevious($attrid, array $sortedAttributes)
244  {
245  $attr = $sortedAttributes[$attrid];
246  $familyLevel = $attr["familyLevel"];
247  $structLevel = $attr["structLevel"];
248  $parent = $attr["parent"];
249  $previous = self::firstOrder;
250 
251  foreach ($sortedAttributes as $attribute) {
252  if ($attribute["id"] === $attrid) {
253  return $previous;
254  }
255  if ($attribute["familyLevel"] <= $familyLevel && $attribute["structLevel"] === $structLevel) {
256  if ($attribute["parent"] === $parent) {
257  $previous = $attribute["id"];
258  } else {
259  // $previous = self::autoOrder;
260 
261  }
262  }
263  }
264  return $previous;
265  }
266  /**
267  * Compute numeric order when no order id done
268  *
269  * @param string $attrid
270  * @param array $attributes
271  *
272  * @return int|float
273  */
274  protected static function getNumericOrder($attrid, array $attributes)
275  {
276  $num = 0;
277  foreach ($attributes as $attribute) {
278  if ($attribute["parent"] === $attrid) {
279  if ($attribute["numOrder"] === 0) {
280  $attribute["numOrder"] = self::getNumericOrder($attribute["id"], $attributes);
281  }
282 
283  if ($num === 0) {
284  $num = $attribute["numOrder"] - 0.5;
285  } else {
286  $num = min($num, $attribute["numOrder"] - 0.5);
287  }
288  }
289  }
290 
291  return $num;
292  }
293  /**
294  * Linearize tree to be a flat array
295  *
296  * @param array $tree
297  *
298  * @return array
299  */
300  protected static function linearOrderTree(array $tree)
301  {
302  $linearOrder = [];
303  foreach ($tree as $node) {
304  if ($node["id"]) {
305  $linearOrder[] = $node["id"];
306  $linearOrder = array_merge($linearOrder, self::linearOrderTree($node["content"]));
307  }
308  }
309  return $linearOrder;
310  }
311  /**
312  * Get childs for a node
313  *
314  * @param array $tree
315  * @param string $attrid
316  * @param array $default
317  *
318  * @return array
319  */
320  protected static function getTreeContent(array $tree, $attrid, $default = [])
321  {
322  foreach ($tree as $node) {
323  if ($node["id"] === $attrid) {
324  return $node["content"];
325  }
326  $content = self::getTreeContent($node["content"], $attrid, false);
327  if ($content !== false) {
328  return $content;
329  }
330  }
331  return $default;
332  }
333  /**
334  * Delete node : return deleted node, false if not found
335  *
336  * @param array $tree
337  * @param $attrid
338  *
339  * @return bool|array
340  */
341  protected static function deleteNode(array & $tree, $attrid)
342  {
343  foreach ($tree as $kNode => & $node) {
344  if ($node["id"] === $attrid) {
345  $dNode = $node;
346  unset($tree[$kNode]);
347  return $dNode;
348  }
349  $content = self::deleteNode($node["content"], $attrid);
350  if ($content !== false) {
351  return $content;
352  }
353  }
354  return false;
355  }
356  /**
357  * Add items to the tree
358  *
359  * @param array $tree
360  * @param array $onlyFamilyTree
361  */
362  protected static function updateAttributeTree(array & $tree, array $onlyFamilyTree)
363  {
364  foreach ($onlyFamilyTree as $attrid => $order) {
365  self::updateAttributeTreeItem($tree, $attrid, $onlyFamilyTree);
366  }
367  }
368  /**
369  * Verify that all attributes are well places in the tree
370  *
371  * @param array $tree
372  * @param string $parent
373  *
374  * @throws Exception
375  *
376  */
377  protected static function checkTree(array & $tree, $parent = "")
378  {
379 
380  foreach ($tree as $child) {
381  if (!isset($child["parent"])) {
382  $child["parent"] = "";
383  }
384 
385  if ($child["parent"] !== $parent) {
386  throw new Exception("ATTR0213", $child["id"], $parent, $child["parent"]);
387  }
388 
389  if ($child["content"]) {
390  self::checkTree($child["content"], $child["id"]);
391  }
392  }
393  }
394  /**
395  * add single item to the tree
396  *
397  * @param array $tree
398  * @param $attrid
399  * @param array $orders
400  */
401  protected static function updateAttributeTreeItem(array & $tree, $attrid, &$orders)
402  {
403  $parent = (!empty($orders[$attrid]["parent"])) ? $orders[$attrid]["parent"] : false;
404  $prev = (!empty($orders[$attrid]["prev"])) ? $orders[$attrid]["prev"] : false;
405 
406  if (empty($orders[$attrid]["isInTree"])) {
407  // $node = ["id" => $attrid, "content" => self::getTreeContent($tree, $attrid)];
408  if (!empty($orders[$attrid]["id"])) {
409  $node = self::deleteNode($tree, $attrid); // To Move it
410  if ($node === false) {
411  $node = ["id" => $attrid, "content" => []];
412  }
413  } else {
414  $node = ["id" => $attrid, "content" => self::getTreeContent($tree, $attrid) ];
415  }
416 
417  if (!$parent) {
418  if ($prev === self::autoOrder) {
419  $tree[] = $node;
420  } elseif ($prev === self::firstOrder) {
421  array_unshift($tree, $node);
422  } elseif ($prev) {
423  if (empty($orders[$prev]["isInTree"])) {
424  self::updateAttributeTreeItem($tree, $prev, $orders);
425  }
426 
427  self::insertAfter($tree, $prev, $node);
428  }
429  } else {
430  $node["parent"] = $parent;
431  if (empty($orders[$parent]["isInTree"])) {
432  self::updateAttributeTreeItem($tree, $parent, $orders);
433  }
434  if ($prev === self::autoOrder) {
435  self::appendNode($tree, $parent, $node);
436  } elseif ($prev === self::firstOrder) {
437  self::prependNode($tree, $parent, $node);
438  } elseif ($prev) {
439  if (empty($orders[$prev]["isInTree"])) {
440  self::updateAttributeTreeItem($tree, $prev, $orders);
441  }
442  self::insertAfter($tree, $prev, $node);
443  }
444  }
445  $orders[$attrid]["isInTree"] = true;
446  }
447  }
448 
449  protected static function insertAfter(array & $array, $ref, array & $new)
450  {
451  foreach ($array as $k => & $v) {
452  if ($v["id"] == $ref) {
453  array_splice($array, $k + 1, 0, [$new]);
454  return true;
455  }
456  if (self::insertAfter($v["content"], $ref, $new)) {
457  return true;
458  }
459  }
460  return false;
461  }
462 
463  protected static function prependNode(array & $array, $parent, array & $new)
464  {
465  foreach ($array as $k => & $v) {
466  if ($v["id"] == $parent) {
467  array_unshift($v["content"], $new);
468  return true;
469  }
470  if (self::prependNode($v["content"], $parent, $new)) {
471  return true;
472  }
473  }
474  return false;
475  }
476 
477  protected static function appendNode(array & $array, $parent, array & $new)
478  {
479  foreach ($array as $k => & $v) {
480  if ($v["id"] == $parent) {
481  $v["content"][] = $new;
482  return true;
483  }
484  if (self::appendNode($v["content"], $parent, $new)) {
485  return true;
486  }
487  }
488  return false;
489  }
490 }
static getPrevious($attrid, array $sortedAttributes)
static updateAttributeTreeItem(array &$tree, $attrid, &$orders)
static appendNode(array &$array, $parent, array &$new)
static completeForNumericOrderByFamilyLevel(array &$familyAttributes)
print< H1 > Check Database< i > $dbaccess</i ></H1 > $a
Definition: checklist.php:45
static getAbsoluteOrders($relativeOrders, $familyId)
input relativeOrders is a linear Array ( [0] => Array ( [id] => tst_bc500 [parent] => [family] => 529...
Exception class use exceptionCode to identifiy correctly exception.
Definition: exceptions.php:19
$attribute
static updateAttributeTree(array &$tree, array $onlyFamilyTree)
static completeForNumericOrder(array &$attributes, $familyId)
static prependNode(array &$array, $parent, array &$new)
static getNumericOrder($attrid, array $attributes)
static insertAfter(array &$array, $ref, array &$new)
static checkTree(array &$tree, $parent="")
print
Definition: checklist.php:49
static deleteNode(array &$tree, $attrid)
getFamFromId($dbaccess, $id)
static getStructLevel($attrid, array $attributes)
static getTreeContent(array $tree, $attrid, $default=[])
← centre documentaire © anakeen