| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- <?php
- /**
- * 重庆赤晓店信息科技有限公司
- * https://www.chixiaodian.com
- * Copyright (c) 2023 赤店商城 All rights reserved.
- */
- namespace app\librarys\shareTree\behaviors;
- use app\librarys\shareTree\exceptions\LogicException;
- use yii\base\Behavior;
- use yii\db\ActiveQuery;
- use yii\db\Expression;
- /**
- * @property ActiveQuery $owner
- */
- class ClosureTableQueryBehavior extends Behavior
- {
- /**
- * 深度检查
- *
- * @param int|null $depth
- * @throws LogicException
- */
- protected function depthCheck(?int $depth = null): void
- {
- if ($depth !== null && $depth < 0) {
- throw new LogicException('深度必须是正整数');
- }
- }
- /**
- * 获取元素的所有子节点
- *
- * @param int $ownerId
- * @param bool|false $withParent
- * @param int|null $depth
- * @param bool|false $eagerLoading
- * @return ActiveQuery
- */
- public function childs(
- int $ownerId,
- bool $withParent = false,
- ?int $depth = null,
- bool $eagerLoading = false
- ): ActiveQuery {
- $this->owner->innerJoinWith('treePathsChild treePathsChild', $eagerLoading)
- ->andWhere(['treePathsChild.parent_id' => $ownerId]);
- if (!$withParent) {
- $this->owner
- ->andWhere(['!=', 'treePathsChild.child_id', $ownerId]);
- }
- if ($depth !== null) {
- $this->depthCheck($depth);
- /** @var self $subQuery */
- $subQuery = ($this->owner->modelClass::find())
- ->select(new Expression('treePathOwner.child_level + :depth', [':depth' => $depth]))
- ->owner($ownerId);
- $this->owner
- ->andWhere(['<=', 'treePathsChild.child_level', $subQuery]);
- }
- return $this->owner;
- }
- /**
- * 获取元素的所有父节点
- *
- * @param int $ownerId
- * @param bool|false $withChild
- * @param int|null $depth
- * @param bool|false $eagerLoading
- * @return ActiveQuery
- * @throws LogicException
- */
- public function parents(
- int $ownerId,
- bool $withChild = false,
- ?int $depth = null,
- bool $eagerLoading = false
- ): ActiveQuery {
- $this->owner
- ->innerJoinWith('treePathsParent treePathsParent', $eagerLoading)
- ->andWhere(['treePathsParent.child_id' => $ownerId]);
- if (!$withChild) {
- $this->owner
- ->andWhere(['!=', 'treePathsParent.parent_id', $ownerId]);
- }
- if ($depth !== null) {
- $this->depthCheck($depth);
- /** @var self $subQuery */
- $subQuery = ($this->owner->modelClass::find())
- ->select(
- new Expression(
- 'IF(treePathOwner.child_level <= :depth, 1, treePathOwner.child_level - :depth)',
- [':depth' => $depth]
- )
- )
- ->owner($ownerId);
- $this->owner
- ->andWhere(['>=', 'treePathsParent.parent_level', $subQuery]);
- }
- return $this->owner;
- }
- /**
- * 获取元素父节点
- *
- * @param int $ownerId
- * @param bool $eagerLoading
- * @return ActiveQuery
- */
- public function parent(int $ownerId, bool $eagerLoading = false): ActiveQuery
- {
- return $this->owner
- ->innerJoinWith('treePathsNearestParent treePathsNearestParent', $eagerLoading)
- ->andWhere(['treePathsNearestParent.parent_id' => $ownerId])
- ->andWhere(['treePathsNearestParent.child_id' => $ownerId]);
- }
- /**
- * 获取所有根节点
- *
- * @param bool $eagerLoading
- * @return ActiveQuery
- */
- public function roots(bool $eagerLoading = false): ActiveQuery
- {
- return $this->owner
- ->innerJoinWith('treePathsParent treePathsParent', $eagerLoading)
- ->andWhere(['treePathsParent.nearest_parent_id' => 0]);
- }
- /**
- * 获取元素直系子节点
- *
- * @param int $ownerId
- * @param bool $eagerLoading
- * @return ActiveQuery
- */
- public function nearestChilds(int $ownerId, bool $eagerLoading = false): ActiveQuery
- {
- return $this->owner
- ->innerJoinWith('treePathsChild treePathsChild', $eagerLoading)
- ->andWhere(['treePathsChild.nearest_parent_id' => $ownerId])
- ->andWhere(['treePathsChild.parent_id' => $ownerId]);
- }
- /**
- * 查询元素条件
- *
- * @param int $ownerId
- * @param bool $eagerLoading
- * @return ActiveQuery
- */
- public function owner(int $ownerId, bool $eagerLoading = false): ActiveQuery
- {
- return $this->owner
- ->innerJoinWith('treePathOwner treePathOwner', $eagerLoading)
- ->andWhere(['treePathOwner.parent_id' => $ownerId])
- ->andWhere(['treePathOwner.child_id' => $ownerId]);
- }
- }
|