publications module alfa

master
Константин 2023-06-07 17:27:58 +03:00
parent 73af945046
commit e134c9b0cc
11 changed files with 286 additions and 6 deletions

View File

@ -20,7 +20,7 @@ class PagesController extends Controller {
}
public function find(Request $request): ?JsonResponse {
return ($page = Page::byUrl($request->get('url'))) ? fractal($page, new PageTransformer())->respond() : null;
return ($model = Page::byUrl($request->get('url'))) ? fractal($model, new PageTransformer())->respond() : null;
}
public function index(Request $request): JsonResponse {

View File

@ -0,0 +1,50 @@
<?php
namespace App\Http\Controllers\Api\Publications;
use App\Http\Controllers\Controller;
use App\Models\Pages\Page;
use App\Models\Publications\Publication;
use App\Transformers\Publications\PublicationTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class PublicationsController extends Controller {
protected Publication $model;
public function __construct(Publication $model) {
$this->model = $model;
}
public function find(Request $request): ?JsonResponse {
return ($model = Publication::byUrl($request->get('url'))) ? fractal($model, new PublicationTransformer())->respond() : null;
}
public function index(Request $request): JsonResponse {
$query = $this->model->query();
if ($page = Page::byUuid($request->get('page'))->first()) $query->where(['page_id' => $page->id]);
$paginator = $query->paginate(config('app.pagination_limit'));
return fractal($paginator, new PublicationTransformer())->respond();
}
public function show(Request $request, $id): JsonResponse {
$model = $this->model->byUuid($id)->firstOrFail();
return fractal($model, new PublicationTransformer())->respond();
}
public function store(Request $request): void {
}
public function update(Request $request, $uuid): void {
}
public function destroy(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$model->delete();
return response()->json(null, 204);
}
}

View File

@ -2,6 +2,7 @@
namespace App\Models\Pages;
use App\Models\Publications\Publication;
use App\Support\HasObjectsTrait;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
@ -50,6 +51,10 @@ class Page extends Model {
return $this->objects()->wherePivot('group', '=', 'sidebars');
}
public function publications(): HasMany {
return $this->hasMany(Publication::class);
}
public function scopeBySlug($query, $slug) {
$query->where(['slug' => $slug]);
@ -91,7 +96,7 @@ class Page extends Model {
public static function byUrl($url) {
if ($url = trim($url, '/ ')) {
$query = self::query();
collect(explode('/', $url))->reverse()->values()->each(function ($slug, $index) use ($query) {
collect(explode('/', $url))->reverse()->values()->each(function($slug, $index) use ($query) {
if ($slug !== '') {
$index ? $query->nthParentSlug($index, $slug) : $query->bySlug($slug);
}

View File

@ -4,10 +4,12 @@ namespace App\Models\Pages;
class PageType {
public const CONTENT = 'content';
public const PUBLICATIONS = 'publications';
public const REGISTRY = 'registry';
public const TITLES = [
self::CONTENT => 'Контентная страница',
self::PUBLICATIONS => 'Страница публикаций',
self::REGISTRY => 'Страница реестра'
];
}

View File

@ -0,0 +1,96 @@
<?php
namespace App\Models\Publications;
use App\Models\Asset;
use App\Models\Pages\Page;
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\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class Publication extends Model {
use UuidScopeTrait, SoftDeletes, HasObjectsTrait, RelationValuesTrait;
protected $dates = [
];
protected $fillable = [
'uuid',
'page_id',
'poster_id',
'author_id',
'slug',
'type',
'name',
'excerpt',
'is_published'
];
protected $hidden = [
'id'
];
public function page(): BelongsTo {
return $this->belongsTo(Page::class);
}
public function poster(): BelongsTo {
return $this->belongsTo(Asset::class);
}
public function author(): BelongsTo {
return $this->belongsTo(User::class);
}
public function sections(): MorphToMany {
return $this->objects()->wherePivot('group', '=', 'sections');
}
public function sidebars(): MorphToMany {
return $this->objects()->wherePivot('group', '=', 'sidebars');
}
public function scopeBySlug($query, $slug) {
$query->where(['slug' => $slug]);
}
public function getLinkAttribute(): string {
return ($this->page->link ?? '') . "/{$this->slug}";
}
public function getParsedTypeAttribute(): array {
return ['name' => $this->type, 'title' => PublicationType::TITLES[$this->type] ?? null];
}
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, '/ ')) {
$slugs = explode('/', $url);
$publicationSlug = array_pop($slugs);
$pageUrl = implode('/', $slugs);
if ($pageUrl) {
return ($page = Page::byUrl($pageUrl)) ? $page->publications()->bySlug($publicationSlug)->first() : null;
} else return self::bySlug($publicationSlug)->first();
}
return null;
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Models\Publications;
class PublicationType {
public const NEWS = 'news';
public const TITLES = [
self::NEWS => 'Новость'
];
}

View File

@ -5,6 +5,7 @@ namespace App\Transformers\Pages;
use App\Models\Pages\Page;
use App\Services\PermissionsService;
use App\Transformers\Objects\ObjectTransformer;
use App\Transformers\Publications\PublicationTransformer;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Primitive;
@ -16,7 +17,7 @@ class PageTransformer extends TransformerAbstract {
];
protected array $availableIncludes = [
'children', 'parent', 'parents', 'sections', 'sidebars', 'permissions'
'children', 'parent', 'parents', 'sections', 'sidebars', 'publications', 'permissions'
];
public function transform(Page $model): array {
@ -53,6 +54,10 @@ class PageTransformer extends TransformerAbstract {
return $this->collection($model->sidebars, new ObjectTransformer());
}
public function includePublications(Page $model): Collection {
return $this->collection($model->publications, new PublicationTransformer());
}
public function includePermissions(Page $model): Primitive {
return $this->primitive((new PermissionsService($model))->get());
}

View File

@ -0,0 +1,65 @@
<?php
namespace App\Transformers\Publications;
use App\Models\Pages\Page;
use App\Models\Publications\Publication;
use App\Services\PermissionsService;
use App\Transformers\Assets\AssetTransformer;
use App\Transformers\Objects\ObjectTransformer;
use App\Transformers\Pages\PageTransformer;
use App\Transformers\Users\UserTransformer;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Primitive;
use League\Fractal\TransformerAbstract;
class PublicationTransformer extends TransformerAbstract {
protected array $defaultIncludes = [
];
protected array $availableIncludes = [
'page', 'poster', 'author', 'sections', 'sidebars', 'permissions'
];
public function transform(Page $model): array {
return [
'id' => $model->uuid,
'slug' => $model->slug,
'link' => $model->link,
'type' => $model->parsedType,
'name' => $model->name,
'excerpt' => $model->excerpt,
'is_published' => boolval($model->is_published),
'created_at' => $model->created_at ? $model->created_at->toIso8601String() : null,
'updated_at' => $model->updated_at ? $model->updated_at->toIso8601String() : null
];
}
public function includePage(Publication $model): ?Item {
return $model->page ? $this->item($model->page, new PageTransformer()) : null;
}
public function includePoster(Publication $model): ?Item {
return $model->poster ? $this->item($model->poster, new AssetTransformer()) : null;
}
public function includeAuthor(Publication $model): ?Item {
return $model->author ? $this->item($model->author, new UserTransformer()) : null;
}
public function includeSections(Publication $model): Collection {
return $this->collection($model->sections, new ObjectTransformer());
}
public function includeSidebars(Publication $model): Collection {
return $this->collection($model->sidebars, new ObjectTransformer());
}
public function includePermissions(Publication $model): Primitive {
return $this->primitive((new PermissionsService($model))->get());
}
}

View File

@ -0,0 +1,41 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePublicationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('publications', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('page_id')->index()->default(0);
$table->integer('poster_id')->index()->nullable();
$table->integer('author_id')->index()->nullable();
$table->string('slug')->index()->nullable();
$table->string('type')->index()->nullable();
$table->string('name')->index()->nullable();
$table->text('excerpt')->nullable();
$table->boolean('is_published')->index()->default(0);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('publications');
}
}

View File

@ -3,6 +3,7 @@
namespace Database\Seeders\Pages;
use App\Models\Pages\Page;
use App\Models\Pages\PageType;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
@ -128,8 +129,8 @@ class PagesTableSeeder extends Seeder
],
'Пресс-центр' => [
'children' => [
'Новости' => [],
'СМИ о нас' => [],
'Новости' => ['type' => PageType::PUBLICATIONS],
'СМИ о нас' => ['type' => PageType::REGISTRY],
'Фотогалерея' => [],
'Видеоархив' => [],
'Контакты для СМИ' => [],
@ -152,7 +153,7 @@ class PagesTableSeeder extends Seeder
{
$slug = Str::slug(Str::transliterate($name));
$page = Page::firstOrCreate(['parent_id' => $parent->id ?? 0, 'slug' => $slug]);
$page->update(['name' => $name]);
$page->update(['name' => $name, 'type' => $data['type'] ?? PageType::CONTENT]);
if ($v = collect($data)->except('children')->all()) $page->update($v);
$ord = 0;
collect($data['children'] ?? [])->each(function ($data, $name) use ($page, &$ord) {

View File

@ -19,6 +19,10 @@ Route::get('pages/root', 'Api\Pages\PagesController@root');
Route::get('pages/find', 'Api\Pages\PagesController@find');
Route::get('pages/{id}', 'Api\Pages\PagesController@show');
Route::get('publications', 'Api\Publications\PublicationsController@index');
Route::get('publications/find', 'Api\Publications\PublicationsController@find');
Route::get('publications/{id}', 'Api\Publications\PublicationsController@show');
Route::group(['middleware' => ['auth:api']], function() {
Route::apiResource('users', 'Api\Users\UsersController');
Route::apiResource('roles', 'Api\Users\RolesController');