QR_code_generator/app/Models/Pages/Page.php

172 lines
5.5 KiB
PHP

<?php
namespace App\Models\Pages;
use App\Models\Objects\Field;
use App\Models\Publications\Publication;
use App\Models\Registries\Registry;
use App\Models\User;
use App\Support\HasObjectsTrait;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
class Page extends Model {
use UuidScopeTrait, SoftDeletes, HasObjectsTrait, RelationValuesTrait;
protected $dates = [
];
protected $fillable = [
'uuid',
'parent_id',
'slug',
'type',
'sub_type',
'name',
'title',
'h1',
'ord'
];
protected $hidden = [
'id'
];
public function parent(): BelongsTo {
return $this->belongsTo(Page::class, 'parent_id');
}
public function children(): HasMany {
return $this->hasMany(Page::class, 'parent_id')->orderBy('ord');
}
public function siblings(): HasMany {
return $this->hasMany(Page::class, 'parent_id', 'parent_id');
}
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 isEditable(User $user): bool {
return $user->isModerator && $user->membership()->whereHas('objects', function($query) {
Field::applyFilters($query, collect(['types' => 'company-member-properties', 'moderate-pages' => $this->parents->add($this)->pluck('uuid')->all()]));
})->exists();
}
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 === '/') return Page::query()->where(['parent_id' => 0, 'slug' => ''])->first();
elseif ($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 function move($ord, ?Page $parent = null) {
$prevParent = $this->parent;
if (($parent->id ?? 0) === ($prevParent->id ?? 0)) {
($ord > $this->ord) ? $this->moveSet('backward', $this->ord, $ord, $parent) : $this->moveSet('forward', $ord, $this->ord, $parent);
} else $this->moveSet('forward', $ord, null, $parent);
$this->update(['parent_id' => $parent->id ?? 0, 'ord' => $ord]);
$this->trimIndexes([$prevParent->id ?? 0, $parent->id ?? 0]);
}
public function moveSet($dir = 'forward', $ordFrom = null, $ordTo = null, ?Page $parent = null) {
$query = Page::query()->where(['parent_id' => $parent->id ?? 0])->orderBy('ord');
if ($ordFrom !== null) $query->where('ord', '>=', $ordFrom);
if ($ordTo !== null) $query->where('ord', '<=', $ordTo);
$query->get()->each(function($page) use($dir) {
$page->update(['ord' => ($dir === 'forward') ? ($page->ord + 1) : ($page->ord - 1)]);
});
}
public function trimIndexes($parentIds) {
collect(is_array($parentIds) ? $parentIds : [$parentIds])->unique()->each(function($parentId) {
Page::query()->where(['parent_id' => $parentId])->orderBy('ord')->orderBy('id')->get()->each(function($page, $index) {
if ($page->ord !== $index) $page->update(['ord' => $index]);
});
});
}
public function getMaxOrd(): int {
$res = $this->siblings()->max('ord');
return ($res !== null) ? ($res + 1) : 0;
}
public static function root() {
return self::query()->where(['parent_id' => 0])->orderBy('ord')->get();
}
public static function main() {
return self::query()->firstOrCreate(['parent_id' => -1]);
}
}