diff --git a/app/src/Lib/Traits/TreeTrait.php b/app/src/Lib/Traits/TreeTrait.php new file mode 100644 index 00000000..e0c31617 --- /dev/null +++ b/app/src/Lib/Traits/TreeTrait.php @@ -0,0 +1,120 @@ + $entity->lft AND lft < $entity->rght + // or something like that. + + $query = null; + + if($hierarchy) { + $query = $this->find('treeList', spacer: '+ '); + } else { + $query = $this->find('list'); + } + + $query = $query->where(['co_id' => $coId]) + // true overrides the default Cake order for treeList so we get + // our items sorted alphabetically instead of by tree ID + ->orderBy(['name' => 'ASC'], true); + + if($id) { + $query = $query->where(['id <>' => $id]); + } + + if(!empty($where)) { + $query = $query->where($where); + } + + return $query->toArray(); + } + + /** + * Application Rule to determine if the parent ID is a potential parent. + * Cake's TreeBehavior will perform checks as part of callbacks (eg) beforeSave, + * but the error messages are not localized and fairly opaque. We'll check for + * common failure modes here and throw better errors before TreeBehavior does + * its thing. + * + * @since COmanage Registyr v5.2.0 + * @param Entity $entity Entity to be validated + * @param array $options Application rule options + * @return boolean true if the Rule check passes, false otherwise + */ + + public function rulePotentialParent($entity, $options) { + // The Entity we're working with, for error messages + $entityNane = Inflector::singularize(StringUtilities::entityToClassName($entity)); + + if(!empty($entity->parent_id)) { + // First check that we're not trying to set ourself to be our own parent + if($entity->id == $entity->parent_id) { + return __d('error', 'tree.parent.same', [$entityNane]); + } + + // This check is based on TreeBehavior::_setParent() + $parent = $this->get($entity->parent_id); + + if($parent->lft > $entity->lft && $parent->lft < $entity->rght) { + return __d('error', 'tree.parent.invalid', [$entityNane]); + } + } + + return true; + } +}