belongsTo(Page::class, 'parent_id'); } public function children(): HasMany { return $this->hasMany(Page::class, 'parent_id')->orderBy('ord'); } public function sections(): MorphToMany { return $this->objects()->wherePivot('group', '=', 'sections'); } public function sidebars(): MorphToMany { return $this->objects()->wherePivot('group', '=', 'sidebars'); } public function publications(): HasMany { return $this->hasMany(Publication::class); } public function registries(): HasMany { return $this->hasMany(Registry::class); } public function scopeBySlug($query, $slug) { $query->where(['slug' => $slug]); } public function scopeNthParentSlug($query, $nth, $slug) { $query->whereHas(implode('.', array_fill(0, $nth, 'parent')), function($query) use($slug) { $query->bySlug($slug); }); } public function getLinkAttribute(): string { return '/' . $this->parents->reverse()->push($this)->pluck('slug')->implode('/'); } public function getParentsAttribute(): Collection { $page = $this; $result = collect([]); while ($page = $page->parent) $result->push($page); return $result; } public function getParsedTypeAttribute(): array { return ['name' => $this->type, 'title' => PageType::TITLES[$this->type] ?? null]; } public function getRegistryAttribute(): Model { return $this->registries()->firstOrCreate(); } public function addSection($typeName, $ord = null): ?Model { return $this->createObject($typeName, $ord, 'sections'); } public function addSidebar($typeName = 'page-sidebar', $ord = null): ?Model { return $this->createObject($typeName, $ord, 'sidebars'); } public static function byUrl($url) { if ($url = trim($url, '/ ')) { $query = self::query(); collect(explode('/', $url))->reverse()->values()->each(function($slug, $index) use ($query) { if ($slug !== '') { $index ? $query->nthParentSlug($index, $slug) : $query->bySlug($slug); } }); return $query->first(); } return null; } public static function root() { return self::query()->where(['parent_id' => 0])->orderBy('ord')->get(); } }