151 lines
4.3 KiB
PHP
151 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace Modules\ProfessionalProject\Entities;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class PpProjectCategory extends Model
|
|
{
|
|
protected $table = 'pp_project_categories';
|
|
|
|
protected $guarded = ['id'];
|
|
|
|
public function projects()
|
|
{
|
|
return $this->belongsToMany(PpProject::class, 'pp_project_category', 'category_id', 'project_id');
|
|
}
|
|
|
|
public function members()
|
|
{
|
|
return $this->belongsToMany(\App\User::class, 'pp_project_category_members', 'category_id', 'user_id');
|
|
}
|
|
|
|
public function creator()
|
|
{
|
|
return $this->belongsTo(\App\User::class, 'created_by');
|
|
}
|
|
|
|
public function parent()
|
|
{
|
|
return $this->belongsTo(self::class, 'parent_id');
|
|
}
|
|
|
|
public function children()
|
|
{
|
|
return $this->hasMany(self::class, 'parent_id')->orderBy('position')->orderBy('name');
|
|
}
|
|
|
|
public function scopeForBusiness($query, $business_id)
|
|
{
|
|
return $query->where('business_id', $business_id);
|
|
}
|
|
|
|
public function scopeRoots($query)
|
|
{
|
|
return $query->whereNull('parent_id');
|
|
}
|
|
|
|
public function isRoot(): bool
|
|
{
|
|
return empty($this->parent_id);
|
|
}
|
|
|
|
public function hasChildren(): bool
|
|
{
|
|
if ($this->relationLoaded('children')) {
|
|
return $this->children->isNotEmpty();
|
|
}
|
|
|
|
return $this->children()->exists();
|
|
}
|
|
|
|
/**
|
|
* @return int[]
|
|
*/
|
|
public static function descendantIds(int $business_id, int $category_id): array
|
|
{
|
|
$by_parent = self::forBusiness($business_id)->get(['id', 'parent_id'])->groupBy('parent_id');
|
|
$ids = [];
|
|
$queue = [$category_id];
|
|
|
|
while (! empty($queue)) {
|
|
$current = array_shift($queue);
|
|
foreach ($by_parent->get($current, collect()) as $child) {
|
|
$ids[] = $child->id;
|
|
$queue[] = $child->id;
|
|
}
|
|
}
|
|
|
|
return $ids;
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, self>
|
|
*/
|
|
public static function breadcrumb(int $business_id, ?int $category_id): Collection
|
|
{
|
|
if (empty($category_id)) {
|
|
return collect();
|
|
}
|
|
|
|
$map = self::forBusiness($business_id)->get(['id', 'parent_id', 'name'])->keyBy('id');
|
|
$trail = collect();
|
|
$current = $map->get($category_id);
|
|
|
|
while ($current) {
|
|
$trail->prepend($current);
|
|
$current = $current->parent_id ? $map->get($current->parent_id) : null;
|
|
}
|
|
|
|
return $trail;
|
|
}
|
|
|
|
public static function treeDropdown(int $business_id, ?int $exclude_id = null, ?int $prefix_id = null): array
|
|
{
|
|
$roots = self::forBusiness($business_id)->roots()->orderBy('position')->orderBy('name')->get();
|
|
$all = self::forBusiness($business_id)->orderBy('position')->orderBy('name')->get()->groupBy('parent_id');
|
|
$exclude = $exclude_id ? array_merge([$exclude_id], self::descendantIds($business_id, $exclude_id)) : [];
|
|
|
|
$options = [];
|
|
$walk = function ($nodes, $depth = 0) use (&$walk, &$options, $all, $exclude) {
|
|
foreach ($nodes as $node) {
|
|
if (in_array($node->id, $exclude, true)) {
|
|
continue;
|
|
}
|
|
$options[$node->id] = str_repeat('— ', $depth).$node->name;
|
|
$walk($all->get($node->id, collect()), $depth + 1);
|
|
}
|
|
};
|
|
$walk($roots);
|
|
|
|
return $options;
|
|
}
|
|
|
|
public static function dropdown($business_id)
|
|
{
|
|
return collect(self::treeDropdown($business_id));
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, self>
|
|
*/
|
|
public static function treeForBusiness(int $business_id): Collection
|
|
{
|
|
$all = self::forBusiness($business_id)->orderBy('position')->orderBy('name')->get();
|
|
|
|
return self::buildTree($all);
|
|
}
|
|
|
|
public static function buildTree(Collection $categories, ?int $parent_id = null): Collection
|
|
{
|
|
return ($parent_id === null ? $categories->whereNull('parent_id') : $categories->where('parent_id', $parent_id))
|
|
->values()
|
|
->map(function ($category) use ($categories) {
|
|
$category->setRelation('children', self::buildTree($categories, $category->id));
|
|
|
|
return $category;
|
|
});
|
|
}
|
|
}
|