OldClosureTableQueryBehavior.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\librarys\shareTree\behaviors;
  8. use app\librarys\shareTree\exceptions\LogicException;
  9. use yii\base\Behavior;
  10. use yii\db\ActiveQuery;
  11. use yii\db\Expression;
  12. /**
  13. * @property ActiveQuery $owner
  14. */
  15. class OldClosureTableQueryBehavior extends Behavior
  16. {
  17. /**
  18. * 深度检查
  19. *
  20. * @param int|null $depth
  21. * @throws LogicException
  22. */
  23. protected function depthCheck(?int $depth = null): void
  24. {
  25. if ($depth !== null && $depth < 0) {
  26. throw new LogicException('深度必须是正整数');
  27. }
  28. }
  29. /**
  30. * 获取元素的所有子节点
  31. *
  32. * @param int $ownerId
  33. * @param bool|false $withParent
  34. * @param int|null $depth
  35. * @param bool|false $eagerLoading
  36. * @return ActiveQuery
  37. */
  38. public function childs(
  39. int $ownerId,
  40. bool $withParent = false,
  41. ?int $depth = null,
  42. bool $eagerLoading = false
  43. ): ActiveQuery {
  44. $this->owner->innerJoinWith('oldTreePathsChild oldTreePathsChild', $eagerLoading)
  45. ->andWhere(['oldTreePathsChild.parent_id' => $ownerId]);
  46. if (!$withParent) {
  47. $this->owner
  48. ->andWhere(['!=', 'oldTreePathsChild.child_id', $ownerId]);
  49. }
  50. if ($depth !== null) {
  51. $this->depthCheck($depth);
  52. /** @var self $subQuery */
  53. $subQuery = ($this->owner->modelClass::findOld())
  54. ->select(new Expression('oldTreePathsChild.child_level + :depth', [':depth' => $depth]))
  55. ->owner($ownerId);
  56. $this->owner
  57. ->andWhere(['<=', 'oldTreePathsChild.child_level', $subQuery]);
  58. }
  59. return $this->owner;
  60. }
  61. /**
  62. * 获取元素的所有父节点
  63. *
  64. * @param int $ownerId
  65. * @param bool|false $withChild
  66. * @param int|null $depth
  67. * @param bool|false $eagerLoading
  68. * @return ActiveQuery
  69. * @throws LogicException
  70. */
  71. public function parents(
  72. int $ownerId,
  73. bool $withChild = false,
  74. ?int $depth = null,
  75. bool $eagerLoading = false
  76. ): ActiveQuery {
  77. $this->owner
  78. ->innerJoinWith('oldTreePathsChild oldTreePathsChild', $eagerLoading)
  79. ->andWhere(['oldTreePathsChild.child_id' => $ownerId]);
  80. if (!$withChild) {
  81. $this->owner
  82. ->andWhere(['!=', 'oldTreePathsChild.parent_id', $ownerId]);
  83. }
  84. if ($depth !== null) {
  85. $this->depthCheck($depth);
  86. /** @var self $subQuery */
  87. $subQuery = ($this->owner->modelClass::findOld())
  88. ->select(
  89. new Expression(
  90. 'IF(oldTreePathsChild.child_level <= :depth, 1, oldTreePathsChild.child_level - :depth)',
  91. [':depth' => $depth]
  92. )
  93. )
  94. ->owner($ownerId);
  95. $this->owner
  96. ->andWhere(['>=', 'oldTreePathsChild.parent_level', $subQuery]);
  97. }
  98. return $this->owner;
  99. }
  100. /**
  101. * 获取元素父节点
  102. *
  103. * @param int $ownerId
  104. * @param bool $eagerLoading
  105. * @return ActiveQuery
  106. */
  107. public function parent(int $ownerId, bool $eagerLoading = false): ActiveQuery
  108. {
  109. return $this->owner
  110. ->innerJoinWith('oldTreePathsNearestParent oldTreePathsNearestParent', $eagerLoading)
  111. ->andWhere(['oldTreePathsNearestParent.parent_id' => $ownerId])
  112. ->andWhere(['oldTreePathsNearestParent.child_id' => $ownerId]);
  113. }
  114. /**
  115. * 获取所有根节点
  116. *
  117. * @param bool $eagerLoading
  118. * @return ActiveQuery
  119. */
  120. public function roots(bool $eagerLoading = false): ActiveQuery
  121. {
  122. return $this->owner
  123. ->innerJoinWith('oldTreePathsParent oldTreePathsParent', $eagerLoading)
  124. ->andWhere(['oldTreePathsParent.nearest_parent_id' => 0]);
  125. }
  126. /**
  127. * 获取元素直系子节点
  128. *
  129. * @param int $ownerId
  130. * @param bool $eagerLoading
  131. * @return ActiveQuery
  132. */
  133. public function nearestChilds(int $ownerId, bool $eagerLoading = false): ActiveQuery
  134. {
  135. return $this->owner
  136. ->innerJoinWith('oldTreePathsChild oldTreePathsChild', $eagerLoading)
  137. ->andWhere(['oldTreePathsChild.nearest_parent_id' => $ownerId])
  138. ->andWhere(['oldTreePathsChild.parent_id' => $ownerId]);
  139. }
  140. /**
  141. * 查询元素条件
  142. *
  143. * @param int $ownerId
  144. * @param bool $eagerLoading
  145. * @return ActiveQuery
  146. */
  147. public function owner(int $ownerId, bool $eagerLoading = false): ActiveQuery
  148. {
  149. return $this->owner
  150. ->innerJoinWith('oldTreePathOwner oldTreePathOwner', $eagerLoading)
  151. ->andWhere(['oldTreePathOwner.parent_id' => $ownerId])
  152. ->andWhere(['oldTreePathOwner.child_id' => $ownerId]);
  153. }
  154. }