Migrate backend to Porto architecture and fix minor bugs

- Fully transitioned the backend to the Porto architectural pattern
- Improved code organization and maintainability
- Fixed minor bugs and inconsistencies
This commit is contained in:
F4ilji
2025-05-12 08:47:43 +05:00
parent 76deaf75f3
commit c01016a154
620 changed files with 16218 additions and 6073 deletions
+21
View File
@@ -0,0 +1,21 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="7">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
<item index="3" class="java.lang.String" itemvalue="noscript" />
<item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" />
<item index="6" class="java.lang.String" itemvalue="div" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
</profile>
</component>
-40
View File
@@ -1,40 +0,0 @@
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Laravel\Fortify\Contracts\CreatesNewUsers;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
/**
* Validate and create a newly registered user.
*
* @param array<string, string> $input
*/
public function create(array $input): User
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique(User::class),
],
'password' => $this->passwordRules(),
])->validate();
return User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
}
}
@@ -1,18 +0,0 @@
<?php
namespace App\Actions\Fortify;
use Illuminate\Validation\Rules\Password;
trait PasswordValidationRules
{
/**
* Get the validation rules used to validate passwords.
*
* @return array<int, \Illuminate\Contracts\Validation\Rule|array<mixed>|string>
*/
protected function passwordRules(): array
{
return ['required', 'string', Password::default(), 'confirmed'];
}
}
-29
View File
@@ -1,29 +0,0 @@
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\ResetsUserPasswords;
class ResetUserPassword implements ResetsUserPasswords
{
use PasswordValidationRules;
/**
* Validate and reset the user's forgotten password.
*
* @param array<string, string> $input
*/
public function reset(User $user, array $input): void
{
Validator::make($input, [
'password' => $this->passwordRules(),
])->validate();
$user->forceFill([
'password' => Hash::make($input['password']),
])->save();
}
}
+14 -15
View File
@@ -2,24 +2,23 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Enums\EducationalProgramStatus; use App\Containers\AdditionalEducation\Models\AdditionalEducation;
use App\Enums\PostStatus; use App\Containers\AppStructure\Models\Page;
use App\Models\AcademicJournal; use App\Containers\Article\Enums\PostStatus;
use App\Models\AdditionalEducation; use App\Containers\Article\Models\Post;
use App\Models\Department; use App\Containers\Education\Models\EducationalProgram;
use App\Models\Division; use App\Containers\Event\Models\Event;
use App\Models\EducationalProgram; use App\Containers\InstituteStructure\Models\Department;
use App\Models\Event; use App\Containers\InstituteStructure\Models\Division;
use App\Models\Faculty; use App\Containers\InstituteStructure\Models\Faculty;
use App\Models\LibraryNews; use App\Containers\User\Models\User;
use App\Models\Page; use App\Ship\Enums\Education\EducationalProgramStatus;
use App\Models\Post;
use App\Models\User;
use App\Models\VirtualExhibition;
use Illuminate\Console\Command;
use Spatie\Sitemap\Sitemap; use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url; use Spatie\Sitemap\Tags\Url;
use Illuminate\Console\Command;
class GenerateSitemap extends Command class GenerateSitemap extends Command
{ {
+3 -2
View File
@@ -2,9 +2,10 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use Illuminate\Console\Command; use App\Containers\AppStructure\Models\Page;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\Models\Page; use Illuminate\Console\Command;
class RegisterRoutes extends Command class RegisterRoutes extends Command
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\AdditionalEducation\Data\Resources;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\AdditionalEducation\Data\Resources;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
@@ -1,8 +1,7 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\AdditionalEducation\Data\Resources;
use App\Enums\FormEducation;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\AdditionalEducation\Data\Resources;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\AdditionalEducation\Loaders;
class AliasesLoader
{
/**
* @var array
*/
public array $aliases = [];
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\AdditionalEducation\Loaders;
class MiddlewareLoader
{
/**
* @var array
*/
public array $middleware = [];
/**
* @var array
*/
public array $middlewareGroups = [];
/**
* @var array
*/
public array $routeMiddleware = [];
/**
* @var array
*/
public array $middlewarePriority = [];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\AdditionalEducation\Loaders;
class ProvidersLoader
{
/**
* @var array
*/
public array $providers = [];
}
@@ -1,10 +1,13 @@
<?php <?php
namespace App\Models; namespace App\Containers\AdditionalEducation\Models;
use App\Enums\FormEducation; use App\Ship\Enums\Education\FormEducation;
use App\Ship\Models\Model;
use App\Ship\Models\Seo;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphOne;
class AdditionalEducation extends Model class AdditionalEducation extends Model
{ {
@@ -17,15 +20,13 @@ class AdditionalEducation extends Model
'form_education' => FormEducation::class, 'form_education' => FormEducation::class,
]; ];
public function category() public function category(): BelongsTo
{ {
return $this->belongsTo(AdditionalEducationCategory::class, 'category_id', 'id'); return $this->belongsTo(AdditionalEducationCategory::class, 'category_id', 'id');
} }
public function seo() public function seo(): MorphOne
{ {
return $this->morphOne(Seo::class, 'seoable'); return $this->morphOne(Seo::class, 'seoable');
} }
} }
@@ -1,10 +1,12 @@
<?php <?php
namespace App\Models; namespace App\Containers\AdditionalEducation\Models;
use Illuminate\Database\Eloquent\Builder; use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class AdditionalEducationCategory extends Model class AdditionalEducationCategory extends Model
{ {
@@ -12,22 +14,20 @@ class AdditionalEducationCategory extends Model
protected $guarded = false; protected $guarded = false;
public function scopeWithActivePrograms(Builder $query) public function scopeWithActivePrograms(Builder $query): Builder
{ {
return $query->with(['additionalEducations' => function ($query) { return $query->with(['additionalEducations' => function ($query) {
$query->where('is_active', true); $query->where('is_active', true);
}]); }]);
} }
public function additionalEducations() public function additionalEducations(): HasMany
{ {
return $this->hasMany(AdditionalEducation::class, 'category_id', 'id'); return $this->hasMany(AdditionalEducation::class, 'category_id', 'id');
} }
public function direction() public function direction(): BelongsTo
{ {
return $this->belongsTo(DirectionAdditionalEducation::class, 'dir_addit_educat_id', 'id'); return $this->belongsTo(DirectionAdditionalEducation::class, 'dir_addit_educat_id', 'id');
} }
} }
@@ -1,9 +1,10 @@
<?php <?php
namespace App\Models; namespace App\Containers\AdditionalEducation\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany;
class DirectionAdditionalEducation extends Model class DirectionAdditionalEducation extends Model
{ {
@@ -12,7 +13,7 @@ class DirectionAdditionalEducation extends Model
protected $guarded = false; protected $guarded = false;
public function additionalEducationCategories() public function additionalEducationCategories(): HasMany
{ {
return $this->hasMany(AdditionalEducationCategory::class, 'dir_addit_educat_id', 'id'); return $this->hasMany(AdditionalEducationCategory::class, 'dir_addit_educat_id', 'id');
} }
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\AdditionalEducation\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\AdditionalEducationCategory; use App\Containers\AdditionalEducation\Models\AdditionalEducationCategory;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class AdditionalEducationCategoryPolicy class AdditionalEducationCategoryPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\AdditionalEducation\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\AdditionalEducation; use App\Containers\AdditionalEducation\Models\AdditionalEducation;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class AdditionalEducationPolicy class AdditionalEducationPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\AdditionalEducation\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\DirectionAdditionalEducation; use App\Containers\AdditionalEducation\Models\DirectionAdditionalEducation;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class DirectionAdditionalEducationPolicy class DirectionAdditionalEducationPolicy
@@ -1,29 +1,25 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Containers\AdditionalEducation\UI\WEB\Controllers;
use App\Enums\CacheKeys; use App\Containers\AdditionalEducation\Data\Resources\AdditionalEducationCategoryPreviewResource;
use App\Enums\FormEducation; use App\Containers\AdditionalEducation\Data\Resources\AdditionalEducationCategoryResource;
use App\Http\Resources\AdditionalEducationCategoryPreviewResource; use App\Containers\AdditionalEducation\Data\Resources\AdditionalEducationResource;
use App\Http\Resources\AdditionalEducationCategoryResource; use App\Containers\AdditionalEducation\Data\Resources\DirectionAdditionalEducationResource;
use App\Http\Resources\AdditionalEducationResource; use App\Containers\AdditionalEducation\Models\AdditionalEducation;
use App\Http\Resources\ClientBreadcrumbPage; use App\Containers\AdditionalEducation\Models\AdditionalEducationCategory;
use App\Http\Resources\ClientBreadcrumbSection; use App\Containers\AdditionalEducation\Models\DirectionAdditionalEducation;
use App\Http\Resources\ClientBreadcrumbSubSection; use App\Ship\Contracts\SeoServiceInterface;
use App\Http\Resources\DirectionAdditionalEducationResource; use App\Ship\Controllers\Controller;
use App\Models\AdditionalEducation; use App\Ship\Enums\CacheKeys;
use App\Models\AdditionalEducationCategory; use App\Ship\Enums\Education\FormEducation;
use App\Models\DirectionAdditionalEducation;
use App\Models\Page;
use App\Services\App\Breadcrumb\BreadcrumbService;
use App\Services\App\Seo\SeoPageProvider;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Inertia\Inertia; use Inertia\Inertia;
class ClientAdditionalEducationController extends Controller class ClientAdditionalEducationController extends Controller
{ {
public function __construct(readonly SeoPageProvider $seoPageProvider){} public function __construct(readonly SeoServiceInterface $seoPageProvider){}
public function index(Request $request): \Inertia\Response public function index(Request $request): \Inertia\Response
@@ -0,0 +1,12 @@
<?php
use App\Containers\AdditionalEducation\UI\WEB\Controllers\ClientAdditionalEducationController;
use Illuminate\Support\Facades\Route;
Route::middleware('access-check')->group(function () {
Route::get('/additional-education/{slug}', [ClientAdditionalEducationController::class, 'show'])->name('client.additionalEducation.show');
Route::get('/additional-education/', [ClientAdditionalEducationController::class, 'index'])->name('client.additionalEducation.index');
});
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\AppStructure\Loaders;
class AliasesLoader
{
/**
* @var array
*/
public array $aliases = [];
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\AppStructure\Loaders;
class MiddlewareLoader
{
/**
* @var array
*/
public array $middleware = [];
/**
* @var array
*/
public array $middlewareGroups = [];
/**
* @var array
*/
public array $routeMiddleware = [];
/**
* @var array
*/
public array $middlewarePriority = [];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\AppStructure\Loaders;
class ProvidersLoader
{
/**
* @var array
*/
public array $providers = [];
}
@@ -1,9 +1,10 @@
<?php <?php
namespace App\Models; namespace App\Containers\AppStructure\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany;
class MainSection extends Model class MainSection extends Model
{ {
@@ -11,7 +12,7 @@ class MainSection extends Model
protected $guarded = false; protected $guarded = false;
public function subSections() public function subSections(): HasMany
{ {
return $this->hasMany(SubSection::class); return $this->hasMany(SubSection::class);
} }
@@ -1,11 +1,12 @@
<?php <?php
namespace App\Models; namespace App\Containers\AppStructure\Models;
use App\Enums\PostStatus; use App\Ship\Models\Model;
use App\Ship\Models\Seo;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphOne;
class Page extends Model class Page extends Model
{ {
@@ -18,7 +19,7 @@ class Page extends Model
return $this->belongsTo(SubSection::class, 'sub_section_id'); return $this->belongsTo(SubSection::class, 'sub_section_id');
} }
public function seo() public function seo(): MorphOne
{ {
return $this->morphOne(Seo::class, 'seoable'); return $this->morphOne(Seo::class, 'seoable');
} }
@@ -27,5 +28,4 @@ class Page extends Model
'content' => 'array', 'content' => 'array',
'settings' => 'array', 'settings' => 'array',
]; ];
} }
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Models; namespace App\Containers\AppStructure\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\AppStructure\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\MainSection; use App\Containers\AppStructure\Models\MainSection;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class MainSectionPolicy class MainSectionPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\AppStructure\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\Page; use App\Containers\AppStructure\Models\Page;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class PagePolicy class PagePolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\AppStructure\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\SubSection; use App\Containers\AppStructure\Models\SubSection;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class SubSectionPolicy class SubSectionPolicy
@@ -0,0 +1,15 @@
<?php
namespace App\Containers\AppStructure\UI\API\Controllers;
use App\Containers\AppStructure\Models\MainSection;
use App\Containers\AppStructure\UI\API\Transformers\NavigationResource;
use App\Ship\Controllers\Controller;
class NavigateController extends Controller
{
public function index()
{
return NavigationResource::collection(MainSection::with('subSections.pages')->orderBy('sort', 'asc')->get());
}
}
@@ -0,0 +1,11 @@
<?php
use App\Containers\AppStructure\UI\API\Controllers\NavigateController;
use Illuminate\Support\Facades\Route;
Route::middleware('ensure.browser')->group(function () {
Route::get('/getNavigation', [NavigateController::class, 'index'])->name('client.main.navigate');
});
@@ -0,0 +1,23 @@
<?php
namespace App\Containers\AppStructure\UI\API\Transformers;
use App\Ship\Resources\JsonResource;
class NavigationResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'subSections' => SubSectionNavigateResource::collection($this->whenLoaded('subSections')->sortBy('sort')),
];
}
}
@@ -1,18 +1,18 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\AppStructure\UI\API\Transformers;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ClientPageNavigateResource extends JsonResource use App\Ship\Resources\JsonResource;
class PageNavigateResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
* *
* @return array<string, mixed> * @return array<string, mixed>
*/ */
public function toArray(Request $request): array public function toArray($request): array
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -0,0 +1,25 @@
<?php
namespace App\Containers\AppStructure\UI\API\Transformers;
use App\Ship\Resources\JsonResource;
class SubSectionNavigateResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'pages' => PageNavigateResource::collection($this->whenLoaded('pages')),
];
}
}
@@ -1,24 +1,44 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Containers\AppStructure\UI\CLI\Commands;
use App\Enums\EducationalProgramStatus; use App\Ship\Abstracts\Commands\ConsoleCommand as AbstractConsoleCommand;
use App\Enums\PostStatus; use App\Containers\AdditionalEducation\Models\AdditionalEducation;
use App\Models\EducationalProgram; use App\Containers\AppStructure\Models\Page;
use App\Models\Page; use App\Containers\Article\Enums\PostStatus;
use App\Models\Post; use App\Containers\Article\Models\Post;
use App\Models\Division; use App\Containers\Education\Models\EducationalProgram;
use App\Models\Event; // Добавляем модель Event use App\Containers\Event\Models\Event;
use App\Models\AdditionalEducation; // Добавляем модель AdditionalEducation use App\Containers\InstituteStructure\Models\Department;
use App\Models\Faculty; // Добавляем модель Faculty use App\Containers\InstituteStructure\Models\Division;
use App\Models\Department; // Добавляем модель Department use App\Containers\InstituteStructure\Models\Faculty;
use App\Models\User; // Добавляем модель User use App\Containers\User\Models\User;
use App\Ship\Enums\Education\EducationalProgramStatus;
use Spatie\Sitemap\Sitemap; use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url; use Spatie\Sitemap\Tags\Url;
class GenerateSitemapController extends Controller class GenerateSitemap extends AbstractConsoleCommand
{ {
public function index() /**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sitemap:generate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Генерирует карту сайта';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{ {
$sitemap = Sitemap::create(); $sitemap = Sitemap::create();
@@ -35,8 +55,6 @@ class GenerateSitemapController extends Controller
// Сохраняем карту сайта в файл // Сохраняем карту сайта в файл
$sitemap->writeToFile(public_path('sitemap.xml')); $sitemap->writeToFile(public_path('sitemap.xml'));
return 'Sitemap generated successfully!';
} }
protected function generatePages(Sitemap $sitemap) protected function generatePages(Sitemap $sitemap)
@@ -44,6 +62,10 @@ class GenerateSitemapController extends Controller
$pages = Page::query() $pages = Page::query()
->where('is_visible', true) ->where('is_visible', true)
->where('code', 200) ->where('code', 200)
->where('path', '!=', null)
->where('is_url', false)
->where('title', '!=', null)
->where('searchable', true)
->get(); ->get();
$this->addUrlsToSitemap($sitemap, $pages, function($page) { $this->addUrlsToSitemap($sitemap, $pages, function($page) {
@@ -0,0 +1,53 @@
<?php
namespace App\Containers\AppStructure\UI\CLI\Commands;
use App\Ship\Abstracts\Commands\ConsoleCommand as AbstractConsoleCommand;
use App\Containers\AppStructure\Models\Page;
use Illuminate\Support\Facades\Route;
class RegisterRoutes extends AbstractConsoleCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'routes:register';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Register application routes in the database';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$routes = Route::getRoutes();
foreach ($routes as $route) {
// Проверяем, существует ли маршрут в базе данных
if (!Page::where('path', '=', $route->uri)->where('is_registered', '=', true)->exists()) {
// Если не существует, создаем новую запись
Page::create([
'path' => $route->uri,
'is_registered' => true,
'is_url' => false,
'searchable' => false,
'code' => 200,
]);
$this->info("Маршрут зарегистрирован: " . $route->uri);
} else {
$this->info("Маршрут уже существует: " . $route->uri);
}
}
$this->info('Все маршруты успешно проверены.');
}
}
@@ -1,29 +1,17 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Containers\AppStructure\UI\WEB\Controllers;
use App\Http\Requests\Page\StoreRequest; use App\Containers\AppStructure\Models\Page;
use App\Http\Requests\Page\UpdateRequest; use App\Containers\AppStructure\UI\WEB\Transformers\PageResource;
use App\Http\Resources\ClientBreadcrumbPage; use App\Ship\Contracts\SeoServiceInterface;
use App\Http\Resources\ClientBreadcrumbSection; use App\Ship\Controllers\Controller;
use App\Http\Resources\ClientBreadcrumbSubSection;
use App\Http\Resources\ClientNavigationResource;
use App\Http\Resources\MainSectionResource;
use App\Http\Resources\PageResource;
use App\Http\Resources\RegisteredPageResource;
use App\Models\MainSection;
use App\Models\Page;
use App\Models\Post;
use App\Services\App\Seo\SeoPageProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Redirect;
use Inertia\Inertia; use Inertia\Inertia;
class PageController extends Controller class PageController extends Controller
{ {
public function __construct(readonly SeoPageProvider $seoPageProvider){} public function __construct(readonly SeoServiceInterface $seoPageProvider){}
public function render(string $path): \Inertia\Response public function render(string $path): \Inertia\Response
{ {
@@ -37,7 +25,6 @@ class PageController extends Controller
->first(); ->first();
}); });
if ($page === null) { if ($page === null) {
abort(404); abort(404);
} }
@@ -45,6 +32,7 @@ class PageController extends Controller
$seo = $this->seoPageProvider->getSeoForModel($page); $seo = $this->seoPageProvider->getSeoForModel($page);
$page = new PageResource($page); $page = new PageResource($page);
@@ -52,7 +40,10 @@ class PageController extends Controller
abort($page->code); abort($page->code);
} }
return inertia()->render('Page', [
return Inertia::render('Page', compact('page', 'subSectionPages', 'seo')); 'page' => $page,
'subSectionPages' => $subSectionPages,
'seo' => $seo,
]);
} }
} }
@@ -1,18 +1,18 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\AppStructure\UI\WEB\Transformers;
use Illuminate\Http\Request; use App\Ship\Resources\JsonResource;
use Illuminate\Http\Resources\Json\JsonResource;
class PageResource extends JsonResource class PageResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
* *
* @return array<string, mixed> * @param \App\Ship\Requests\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/ */
public function toArray(Request $request): array public function toArray($request)
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -0,0 +1,39 @@
<?php
namespace App\Containers\Article\Actions;
use App\Containers\Article\Tasks\BuildFiltersTask;
use App\Containers\Article\Tasks\GetCategoriesTask;
use App\Containers\Article\Tasks\GetPostsTask;
use App\Containers\Article\Tasks\GetTagsTask;
use App\Containers\Article\UI\WEB\Transformers\PostListResource;
use App\Ship\Contracts\SeoServiceInterface;
class ListPostsAction
{
public function __construct(
private readonly GetPostsTask $getPostsTask,
private readonly GetCategoriesTask $getCategoriesTask,
private readonly GetTagsTask $getTagsTask,
private readonly BuildFiltersTask $buildFiltersTask,
private readonly SeoServiceInterface $seoPageProvider,
) {}
public function run(array $filters): array
{
$posts = $this->getPostsTask->run($filters);
$categories = $this->getCategoriesTask->run();
$tags = $this->getTagsTask->run();
$filtersData = $this->buildFiltersTask->run($filters);
$seo = $this->seoPageProvider->getSeoForCurrentPage();
return [
'posts' => inertia()->deepMerge(fn() => PostListResource::collection($posts->items())),
'posts_pagination' => $posts->toArray(),
'filters' => $filtersData,
'categories' => $categories,
'tags' => $tags,
'seo' => $seo,
];
}
}
@@ -0,0 +1,8 @@
<?php
namespace App\Containers\Article\Actions;
class ViewPostAction
{
}
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Enums; namespace App\Containers\Article\Enums;
use Filament\Support\Contracts\HasLabel; use Filament\Support\Contracts\HasLabel;
use Filament\Support\Contracts\HasColor; use Filament\Support\Contracts\HasColor;
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Article\Loaders;
class AliasesLoader
{
/**
* @var array
*/
public array $aliases = [];
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Article\Loaders;
class MiddlewareLoader
{
/**
* @var array
*/
public array $middleware = [];
/**
* @var array
*/
public array $middlewareGroups = [];
/**
* @var array
*/
public array $routeMiddleware = [];
/**
* @var array
*/
public array $middlewarePriority = [];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Article\Loaders;
class ProvidersLoader
{
/**
* @var array
*/
public array $providers = [];
}
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Models; namespace App\Containers\Article\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
class Category extends Model class Category extends Model
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace App\Containers\Article\Models;
use App\Containers\Article\Enums\PostStatus;
use App\Containers\User\Models\User;
use App\Containers\Widget\Models\Slide;
use App\Ship\Traits\HasSeo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Spatie\Tags\HasTags;
class Post extends Model
{
use HasFactory, HasTags, HasSeo;
protected $guarded = false;
public function category() : BelongsTo
{
return $this->belongsTo(Category::class);
}
public function author() : BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
public function slide(): MorphOne
{
return $this->morphOne(Slide::class, 'slidable');
}
protected $casts = [
'content' => 'array',
'authors' => 'array',
'status' => PostStatus::class,
'images' => 'array'
];
}
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Models; namespace App\Containers\Article\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model class Tag extends Model
{ {
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Article\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\Category; use App\Containers\Article\Models\Category;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class CategoryPolicy class CategoryPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Article\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\Post; use App\Containers\Article\Models\Post;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy class PostPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Article\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\Tag; use App\Containers\Article\Models\Tag;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class TagPolicy class TagPolicy
@@ -0,0 +1,88 @@
<?php
namespace App\Containers\Article\Tasks;
use App\Containers\Article\Models\Category;
use App\Containers\Article\UI\WEB\Transformers\CategoryResource;
use App\Containers\Article\UI\WEB\Transformers\TagResource;
use App\Ship\Builders\FilterBuilder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class BuildFiltersTask
{
public function __construct(
private readonly FilterBuilder $filterBuilder
) {}
public function run(array $filters): array
{
// Сброс фильтров перед новым запуском
$this->filterBuilder->reset();
// 1. Поисковый фильтр
$this->filterBuilder->add(
key: 'search_filter',
type: 'search',
value: $filters['search'] ?? null,
param: 'search'
);
// 2. Категории
$categoriesContent = [];
if (!empty($filters['category'])) {
$categoriesSlugs = Arr::wrap($filters['category']);
foreach ($categoriesSlugs as $item) {
$cacheKey = 'category_content_' . $item;
$categoriesContent[$item] = Cache::remember($cacheKey, now()->addHours(1), function () use ($item) {
return new CategoryResource(Category::where('slug', $item)->first());
});
}
}
$this->filterBuilder->add(
key: 'category_filter',
type: 'category',
value: $categoriesSlugs ?? null,
param: 'category',
content: $categoriesContent
);
// 3. Теги
$tagsContent = [];
if (!empty($filters['tag'])) {
$tagsSlugs = Arr::wrap($filters['tag']);
foreach ($tagsSlugs as $item) {
$cacheKey = 'tag_content_' . $item;
$tagsContent[$item] = Cache::remember($cacheKey, now()->addHours(1), function () use ($item) {
return new TagResource(DB::table('tags')
->where(DB::raw("JSON_UNQUOTE(JSON_EXTRACT(slug, '$.ru'))"), $item)
->first());
});
}
}
$this->filterBuilder->add(
key: 'tag_filter',
type: 'tag',
value: $tagsSlugs ?? null,
param: 'tag',
content: $tagsContent
);
// 4. Сортировка
$this->filterBuilder->add(
key: 'sortingBy_filter',
type: 'sort',
value: $filters['sort'] ?? null,
param: 'sort'
);
return $this->filterBuilder->get();
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Containers\Article\Tasks;
use App\Containers\Article\Models\Category;
use App\Containers\Article\UI\WEB\Transformers\CategoryResource;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Support\Facades\Cache;
class GetCategoriesTask
{
public function run(): AnonymousResourceCollection
{
return Cache::remember('categories', now()->addHours(48), function () {
return CategoryResource::collection(Category::has('posts')->get());
});
}
}
@@ -0,0 +1,45 @@
<?php
namespace App\Containers\Article\Tasks;
use App\Containers\Article\Models\Post;
use Illuminate\Support\Facades\Cache;
use Illuminate\Pagination\LengthAwarePaginator;
use Carbon\Carbon;
class GetPostsTask
{
public function run(array $filters): LengthAwarePaginator
{
$cacheKey = 'posts_' . md5(serialize($filters));
return Cache::remember($cacheKey, now()->addHours(1), function () use ($filters) {
$query = Post::query()
->with('category')
->select('title', 'slug', 'authors', 'category_id', 'preview', 'search_data', 'publish_at')
->where('status', 'published')
->where('publish_at', '<', Carbon::now())
->when(!empty($filters['tag']), function ($query) use ($filters) {
if (is_array($filters['tag'])) {
return $query->withAnyTags($filters['tag']);
}
$slugsArray = explode(',', $filters['tag']);
return $query->withAnyTags($slugsArray);
})
->when(!empty($filters['category']), function ($query) use ($filters) {
if (is_array($filters['category'])) {
$query->whereHas('category', function ($query) use ($filters) {
$query->whereIn('slug', $filters['category']);
});
}
})
->when(!empty($filters['search']), function ($query) use ($filters) {
$query->whereRaw('LOWER(title) like ?', ["%".strtolower($filters['search'])."%"]);
});
$sort = $filters['sort'] ?? 'desc';
return $query->orderBy('publish_at', $sort)->paginate(9)->withQueryString();
});
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Containers\Article\Tasks;
use App\Containers\Article\Models\Post;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Spatie\Tags\Tag;
class GetTagsTask
{
public function run()
{
return Cache::remember('tags', now()->addHours(1), function () {
$tagIds = DB::table('taggables')
->distinct()
->select('tag_id')
->where('taggable_type', Post::class)
->get()
->pluck('tag_id');
return Tag::whereIn('id', $tagIds)->get();
});
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Containers\Article\UI\WEB\Controllers;
use App\Containers\Article\Actions\ListPostsAction;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class IndexPostController extends Controller
{
public function __construct(
private readonly ListPostsAction $listPostsAction,
) {}
public function __invoke(Request $request)
{
$filters = $request->only(['search', 'category', 'tag', 'sort', 'page']);
$data = $this->listPostsAction->run($filters);
return inertia()->render('Client/Posts/Index', $data);
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Containers\Article\UI\WEB\Controllers;
use App\Containers\Article\Models\Post;
use App\Containers\Article\UI\WEB\Transformers\PostItemResource;
use App\Ship\Enums\CacheKeys;
use App\Ship\Contracts\SeoServiceInterface;
use App\Ship\Requests\Request;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Inertia\Inertia;
class ShowPostController extends \App\Ship\Controllers\Controller
{
public function __construct(private readonly SeoServiceInterface $seoPageProvider){}
public function __invoke(Request $request, $slug): \Inertia\Response
{
$postData = Cache::remember(
CacheKeys::POST_PREFIX->value . $slug,
now()->addHours(1),
fn() => Post::where('slug', $slug)
->where('publish_at', '<', Carbon::now())
->firstOrFail()
);
$seo = Cache::remember(
CacheKeys::POST_PREFIX->value . 'seo_' . $slug,
now()->addHours(1),
fn() => $this->seoPageProvider->getSeoForModel($postData)
);
return inertia()->render('Client/Posts/Show', [
'post' => new PostItemResource($postData),
'seo' => $seo,
]);
}
}
@@ -0,0 +1,14 @@
<?php
use App\Containers\Article\UI\WEB\Controllers\IndexPostController;
use App\Containers\Article\UI\WEB\Controllers\ShowPostController;
use Illuminate\Support\Facades\Route;
Route::middleware('access-check')->group(function () {
Route::get('/news', IndexPostController::class)->name('client.post.index');
Route::get('/news/{slug}', ShowPostController::class)->name('client.post.show');
});
@@ -1,18 +1,21 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Article\UI\WEB\Transformers;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Ship\Requests\Request;
use App\Ship\Resources\JsonResource;
class CategoryResource extends JsonResource class CategoryResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
* *
* @return array<string, mixed> * @param \App\Ship\Requests\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/ */
public function toArray(Request $request): array public function toArray($request): array
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -1,19 +1,19 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Article\UI\WEB\Transformers;
use App\Ship\Resources\JsonResource;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource class PostItemResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
* *
* @return array<string, mixed> * @param \App\Ship\Requests\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/ */
public function toArray(Request $request): array public function toArray($request)
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -22,7 +22,7 @@ class PostResource extends JsonResource
'content' => $this->content, 'content' => $this->content,
'is_published' => $this->is_published, 'is_published' => $this->is_published,
'category' => $this->category, 'category' => $this->category,
'tags' => ClientTagResource::collection($this->tags()->get()), 'tags' => TagResource::collection($this->tags()->get()),
'authors' => $this->authors, 'authors' => $this->authors,
'gallery' => $this->images, 'gallery' => $this->images,
'reading_time' => $this->reading_time, 'reading_time' => $this->reading_time,
@@ -1,19 +1,19 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Article\UI\WEB\Transformers;
use App\Ship\Resources\JsonResource;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ClientPostListResource extends JsonResource class PostListResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
* *
* @return array<string, mixed> * @param \App\Ship\Requests\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/ */
public function toArray(Request $request): array public function toArray($request)
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Article\UI\WEB\Transformers;
use App\Ship\Requests\Request;
use App\Ship\Resources\JsonResource;
class TagResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \App\Ship\Requests\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug,
];
}
}
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Enums; namespace App\Containers\Education\Enums;
use Filament\Support\Contracts\HasLabel; use Filament\Support\Contracts\HasLabel;
use Filament\Support\Contracts\HasColor; use Filament\Support\Contracts\HasColor;
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Education\Loaders;
class AliasesLoader
{
/**
* @var array
*/
public array $aliases = [];
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Education\Loaders;
class MiddlewareLoader
{
/**
* @var array
*/
public array $middleware = [];
/**
* @var array
*/
public array $middlewareGroups = [];
/**
* @var array
*/
public array $routeMiddleware = [];
/**
* @var array
*/
public array $middlewarePriority = [];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Education\Loaders;
class ProvidersLoader
{
/**
* @var array
*/
public array $providers = [];
}
@@ -1,9 +1,11 @@
<?php <?php
namespace App\Models; namespace App\Containers\Education\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
class AdmissionCampaign extends Model class AdmissionCampaign extends Model
{ {
@@ -15,16 +17,12 @@ class AdmissionCampaign extends Model
'info' => 'array' 'info' => 'array'
]; ];
public function degrees() public function admission_plans(): HasMany
{
return $this->hasMany(CampaignDegree::class);
}
public function admission_plans()
{ {
return $this->hasMany(AdmissionPlan::class, 'admission_campaigns_id', 'id'); return $this->hasMany(AdmissionPlan::class, 'admission_campaigns_id', 'id');
} }
public function educationalPrograms() public function educationalPrograms(): HasManyThrough
{ {
return $this->hasManyThrough( return $this->hasManyThrough(
EducationalProgram::class, EducationalProgram::class,
@@ -1,9 +1,10 @@
<?php <?php
namespace App\Models; namespace App\Containers\Education\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AdmissionPlan extends Model class AdmissionPlan extends Model
{ {
@@ -16,12 +17,12 @@ class AdmissionPlan extends Model
'contests' => 'array' 'contests' => 'array'
]; ];
public function educationalProgram() public function educationalProgram(): BelongsTo
{ {
return $this->belongsTo(EducationalProgram::class, 'educational_programs_id', 'id'); return $this->belongsTo(EducationalProgram::class, 'educational_programs_id', 'id');
} }
public function admissionCampaign() public function admissionCampaign(): BelongsTo
{ {
return $this->belongsTo(AdmissionCampaign::class, 'admission_campaigns_id', 'id'); return $this->belongsTo(AdmissionCampaign::class, 'admission_campaigns_id', 'id');
} }
@@ -1,11 +1,12 @@
<?php <?php
namespace App\Models; namespace App\Containers\Education\Models;
use App\Enums\LevelEducational; use App\Ship\Enums\Education\LevelEducational;
use Illuminate\Database\Eloquent\Factories\HasFactory; use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
class DirectionStudy extends Model class DirectionStudy extends Model
@@ -18,17 +19,12 @@ class DirectionStudy extends Model
'lvl_edu' => LevelEducational::class, 'lvl_edu' => LevelEducational::class,
]; ];
public function degree() public function programs(): HasMany
{
return $this->belongsTo(CampaignDegree::class, 'campaign_degree_id', 'id');
}
public function programs()
{ {
return $this->hasMany(EducationalProgram::class); return $this->hasMany(EducationalProgram::class);
} }
public function scopeWithActivePrograms(Builder $query) public function scopeWithActivePrograms(Builder $query): Builder
{ {
return $query->with(['programs' => function ($query) { return $query->with(['programs' => function ($query) {
$query->whereHas('admission_plans.admissionCampaign', function ($q) { $query->whereHas('admission_plans.admissionCampaign', function ($q) {
@@ -37,31 +33,31 @@ class DirectionStudy extends Model
}]); }]);
} }
public function scopeWithActiveAdmissionCampaign(Builder $query) public function scopeWithActiveAdmissionCampaign(Builder $query): Builder
{ {
return $query->whereHas('programs.admission_plans.admissionCampaign', function ($q) { return $query->whereHas('programs.admission_plans.admissionCampaign', function ($q) {
$q->where('status', 1); $q->where('status', 1);
}); });
} }
public function scopeWithAdmissionCampaignByYear(Builder $query, string $year) public function scopeWithAdmissionCampaignByYear(Builder $query, string $year): Builder
{ {
return $query->whereHas('programs.admission_plans.admissionCampaign', function ($q) use ($year) { return $query->whereHas('programs.admission_plans.admissionCampaign', function ($q) use ($year) {
$q->where('status', 1)->where('academic_year', $year); $q->where('status', 1)->where('academic_year', $year);
}); });
} }
public function scopeForBachelorLevel(Builder $query) public function scopeForBachelorLevel(Builder $query): Builder
{ {
return $query->where('lvl_edu', LevelEducational::BACHELOR); return $query->where('lvl_edu', LevelEducational::BACHELOR);
} }
public function scopeForMiddleLevel(Builder $query) public function scopeForMiddleLevel(Builder $query): Builder
{ {
return $query->whereIn('lvl_edu', [LevelEducational::MIDDLE_LEVEL_SPECIALIST_TRAINING, LevelEducational::PREPARATION_OF_QUALIFIED_WORKERS]); return $query->whereIn('lvl_edu', [LevelEducational::MIDDLE_LEVEL_SPECIALIST_TRAINING, LevelEducational::PREPARATION_OF_QUALIFIED_WORKERS]);
} }
public function scopeForMasterLevel(Builder $query) public function scopeForMasterLevel(Builder $query): Builder
{ {
return $query->where('lvl_edu', LevelEducational::MASTER); return $query->where('lvl_edu', LevelEducational::MASTER);
} }
@@ -1,14 +1,19 @@
<?php <?php
namespace App\Models; namespace App\Containers\Education\Models;
use App\Enums\LevelEducational; use App\Containers\InstituteStructure\Models\Department;
use App\Ship\Enums\Education\LevelEducational;
use App\Ship\Models\Model;
use App\Ship\Traits\HasSeo;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class EducationalProgram extends Model class EducationalProgram extends Model
{ {
use HasFactory; use HasFactory, HasSeo;
protected $guarded = false; protected $guarded = false;
@@ -20,24 +25,19 @@ class EducationalProgram extends Model
'lvl_edu' => LevelEducational::class, 'lvl_edu' => LevelEducational::class,
]; ];
public function directionStudy() public function directionStudy(): BelongsTo
{ {
return $this->belongsTo(DirectionStudy::class); return $this->belongsTo(DirectionStudy::class);
} }
public function departments() public function departments(): BelongsToMany
{ {
return $this->belongsToMany(Department::class, 'program_department'); return $this->belongsToMany(Department::class, 'program_department');
} }
public function admission_plans() public function admission_plans(): HasMany
{ {
return $this->hasMany(AdmissionPlan::class, 'educational_programs_id', 'id'); return $this->hasMany(AdmissionPlan::class, 'educational_programs_id', 'id');
} }
public function seo()
{
return $this->morphOne(Seo::class, 'seoable');
}
} }
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Education\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\AdmissionCampaign; use App\Containers\Education\Models\AdmissionCampaign;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class AdmissionCampaignPolicy class AdmissionCampaignPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Education\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\AdmissionPlan; use App\Containers\Education\Models\AdmissionPlan;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class AdmissionPlanPolicy class AdmissionPlanPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Education\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\DirectionStudy; use App\Containers\Education\Models\DirectionStudy;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class DirectionStudyPolicy class DirectionStudyPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Education\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\EducationalProgram; use App\Containers\Education\Models\EducationalProgram;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class EducationalProgramPolicy class EducationalProgramPolicy
@@ -0,0 +1,15 @@
<?php
namespace App\Containers\Education\UI\API\Controllers;
use App\Containers\Education\Models\AdmissionCampaign;
use App\Ship\Controllers\Controller;
class AcademicYearController extends Controller
{
public function __invoke()
{
$activeCampaign = AdmissionCampaign::query()->where('status', 1)->firstOrFail();
return $activeCampaign->academic_year;
}
}
@@ -1,7 +1,8 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Containers\Education\UI\API\Controllers;
use App\Http\Controllers\Controller;
use App\Jobs\CreateAdmissionPlan; use App\Jobs\CreateAdmissionPlan;
use App\Jobs\CreateDirectionStudy; use App\Jobs\CreateDirectionStudy;
use App\Jobs\CreateEducationalProgram; use App\Jobs\CreateEducationalProgram;
@@ -1,7 +1,8 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Containers\Education\UI\API\Controllers;
use App\Http\Controllers\Controller;
use App\Jobs\CreateDirectionStudy; use App\Jobs\CreateDirectionStudy;
use App\Jobs\CreateEducationalProgram; use App\Jobs\CreateEducationalProgram;
use App\Services\Vicon\EducationalProgram\EducationalProgramService; use App\Services\Vicon\EducationalProgram\EducationalProgramService;
@@ -0,0 +1,13 @@
<?php
use App\Containers\Education\UI\API\Controllers\AcademicYearController;
use App\Containers\Education\UI\API\Controllers\UpdateAdmissionPlansDataApiController;
use App\Containers\Education\UI\API\Controllers\UpdateEduDataApiController;
use Illuminate\Support\Facades\Route;
Route::get('/getAcademicYear', AcademicYearController::class)->name('academic.year');
Route::middleware(['auth', 'superadmin'])->group(function () {
Route::get('/get-edu-program-data', [UpdateEduDataApiController::class, 'index']);
Route::get('/get-admission-plans-data', [UpdateAdmissionPlansDataApiController::class, 'index']);
});
@@ -1,26 +1,27 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Containers\Education\UI\WEB\Controllers;
use App\Enums\BudgetEducation; use App\Containers\Education\Models\AdmissionCampaign;
use App\Enums\CacheKeys; use App\Containers\Education\Models\AdmissionPlan;
use App\Enums\FormEducation; use App\Containers\Education\Models\DirectionStudy;
use App\Enums\LevelEducational; use App\Containers\Education\Models\EducationalProgram;
use App\Http\Resources\DirectionStudyResource; use App\Containers\Education\UI\WEB\Transformers\DirectionStudyResource;
use App\Http\Resources\EducationalProgramFullResource; use App\Containers\Education\UI\WEB\Transformers\EducationalProgramResource;
use App\Models\AdmissionCampaign; use App\Ship\Contracts\SeoServiceInterface;
use App\Models\AdmissionPlan; use App\Ship\Controllers\Controller;
use App\Models\DirectionStudy; use App\Ship\Enums\CacheKeys;
use App\Models\EducationalProgram; use App\Ship\Enums\Education\BudgetEducation;
use App\Services\App\Seo\SeoPageProvider; use App\Ship\Enums\Education\FormEducation;
use Illuminate\Http\Request; use App\Ship\Enums\Education\LevelEducational;
use App\Ship\Requests\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Inertia\Inertia; use Inertia\Inertia;
class ClientProgramController extends Controller class ClientProgramController extends Controller
{ {
public function __construct(readonly SeoPageProvider $seoPageProvider){} public function __construct(readonly SeoServiceInterface $seoPageProvider){}
public function index(Request $request): \Inertia\Response public function index(Request $request): \Inertia\Response
{ {
@@ -130,7 +131,7 @@ class ClientProgramController extends Controller
return $this->seoPageProvider->getSeoForModel($programModel); return $this->seoPageProvider->getSeoForModel($programModel);
}); });
$program = new EducationalProgramFullResource($programModel); $program = new EducationalProgramResource($programModel);
return Inertia::render('Client/Programs/Show', compact('program', 'formsEdu', 'seo')); return Inertia::render('Client/Programs/Show', compact('program', 'formsEdu', 'seo'));
} }
@@ -0,0 +1,12 @@
<?php
use App\Containers\Education\UI\WEB\Controllers\ClientProgramController;
use Illuminate\Support\Facades\Route;
Route::middleware('access-check')->group(function () {
Route::get('/programs/', [ClientProgramController::class, 'index'])->name('client.program.index');
Route::get('/program/{slug}', [ClientProgramController::class, 'show'])->name('client.program.show');
});
@@ -0,0 +1,18 @@
<?php
namespace App\Containers\Education\UI\WEB\Transformers;
use App\Ship\Resources\JsonResource;
class DirectionStudyResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'code' => $this->code,
'programs' => EducationalProgramBasicResource::collection($this->programs),
];
}
}
@@ -1,11 +1,11 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Education\UI\WEB\Transformers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
class EducationalProgramResource extends JsonResource class EducationalProgramBasicResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
@@ -1,21 +1,14 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Education\UI\WEB\Transformers;
use App\Enums\FormEducation; use App\Ship\Enums\Education\FormEducation;
use App\Enums\LevelEducational; use App\Ship\Resources\JsonResource;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class EducationalProgramFullResource extends JsonResource class EducationalProgramResource extends JsonResource
{ {
/**
* Преобразовать ресурс в массив. public function toArray($request): array
*
* @param Request $request
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Event\Loaders;
class AliasesLoader
{
/**
* @var array
*/
public array $aliases = [];
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Event\Loaders;
class MiddlewareLoader
{
/**
* @var array
*/
public array $middleware = [];
/**
* @var array
*/
public array $middlewareGroups = [];
/**
* @var array
*/
public array $routeMiddleware = [];
/**
* @var array
*/
public array $middlewarePriority = [];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Event\Loaders;
class ProvidersLoader
{
/**
* @var array
*/
public array $providers = [];
}
@@ -1,15 +1,16 @@
<?php <?php
namespace App\Models; namespace App\Containers\Event\Models;
use App\Ship\Models\Model;
use App\Ship\Traits\HasSeo;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Spatie\Tags\HasTags; use Spatie\Tags\HasTags;
class Event extends Model class Event extends Model
{ {
use HasFactory, HasTags; use HasFactory, HasTags, HasSeo;
protected $guarded = false; protected $guarded = false;
@@ -17,10 +18,6 @@ class Event extends Model
'content' => 'array', 'content' => 'array',
]; ];
public function seo()
{
return $this->morphOne(Seo::class, 'seoable');
}
public function category() : BelongsTo public function category() : BelongsTo
{ {
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Models; namespace App\Containers\Event\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
class EventCategory extends Model class EventCategory extends Model
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Event\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\EventCategory; use App\Containers\Event\Models\EventCategory;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class EventCategoryPolicy class EventCategoryPolicy
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Policies; namespace App\Containers\Event\Policies;
use App\Models\User; use App\Containers\User\Models\User;
use App\Models\Event; use App\Containers\Event\Models\Event;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
class EventPolicy class EventPolicy
@@ -1,29 +1,24 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Containers\Event\UI\WEB\Controllers;
use App\Enums\CacheKeys; use App\Containers\Event\Models\Event;
use App\Http\Resources\ClientBreadcrumbPage; use App\Containers\Event\Models\EventCategory;
use App\Http\Resources\ClientBreadcrumbSection; use App\Containers\Event\UI\WEB\Transformers\EventCategoryResource;
use App\Http\Resources\ClientBreadcrumbSubSection; use App\Containers\Event\UI\WEB\Transformers\EventPreviewResource;
use App\Http\Resources\ClientEventCategoryResource; use App\Containers\Event\UI\WEB\Transformers\EventResource;
use App\Http\Resources\ClientEventFullResource; use App\Ship\Contracts\SeoServiceInterface;
use App\Http\Resources\ClientEventResource; use App\Ship\Controllers\Controller;
use App\Http\Resources\ClientNavigationResource; use App\Ship\Enums\CacheKeys;
use App\Models\Event; use App\Ship\Requests\Request;
use App\Models\EventCategory;
use App\Models\Page;
use App\Services\App\Breadcrumb\BreadcrumbService;
use App\Services\App\Seo\SeoPageProvider;
use Carbon\Carbon; use Carbon\Carbon;
use DateTime; use DateTime;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Inertia\Inertia; use Inertia\Inertia;
class ClientEventController extends Controller class ClientEventController extends Controller
{ {
public function __construct(readonly SeoPageProvider $seoPageProvider){} public function __construct(readonly SeoServiceInterface $seoPageProvider){}
public function index(Request $request): \Inertia\Response public function index(Request $request): \Inertia\Response
{ {
@@ -45,7 +40,7 @@ class ClientEventController extends Controller
$categories = Cache::remember( $categories = Cache::remember(
CacheKeys::EVENTS_PREFIX->value . 'categories', CacheKeys::EVENTS_PREFIX->value . 'categories',
now()->addDay(), now()->addDay(),
fn() => ClientEventCategoryResource::collection(EventCategory::has('events')->get()) fn() => EventCategoryResource::collection(EventCategory::has('events')->get())
); );
$filters = $this->getFilters(); $filters = $this->getFilters();
@@ -82,7 +77,7 @@ class ClientEventController extends Controller
} }
); );
$event = new ClientEventFullResource($eventModel); $event = new EventResource($eventModel);
return Inertia::render('Client/Events/Show', compact( return Inertia::render('Client/Events/Show', compact(
@@ -104,7 +99,7 @@ class ClientEventController extends Controller
$categories = Cache::remember( $categories = Cache::remember(
CacheKeys::EVENTS_PREFIX->value . 'categories', CacheKeys::EVENTS_PREFIX->value . 'categories',
now()->addDay(), now()->addDay(),
fn() => ClientEventCategoryResource::collection(EventCategory::has('events')->get()) fn() => EventCategoryResource::collection(EventCategory::has('events')->get())
); );
$filters = $this->getFilters(); $filters = $this->getFilters();
@@ -149,7 +144,7 @@ class ClientEventController extends Controller
private function getEvents(array $currentDate) private function getEvents(array $currentDate)
{ {
return ClientEventResource::collection(Event::select('title', 'slug', 'event_date_start', 'event_time_start', 'address', 'is_online', 'category_id') return EventPreviewResource::collection(Event::select('title', 'slug', 'event_date_start', 'event_time_start', 'address', 'is_online', 'category_id')
->whereDate('event_date_start', '=', $currentDate['fullDate']) ->whereDate('event_date_start', '=', $currentDate['fullDate'])
->with('category') ->with('category')
->when(request()->input('is_online'), function ($query, $value) { ->when(request()->input('is_online'), function ($query, $value) {
@@ -172,7 +167,7 @@ class ClientEventController extends Controller
private function getEventsArchive() private function getEventsArchive()
{ {
return ClientEventResource::collection(Event::select('title', 'slug', 'event_date_start', 'event_time_start', 'address', 'is_online', 'category_id') return EventPreviewResource::collection(Event::select('title', 'slug', 'event_date_start', 'event_time_start', 'address', 'is_online', 'category_id')
->whereDate('event_date_start', '<', now()) ->whereDate('event_date_start', '<', now())
->with('category') ->with('category')
->when(request()->input('is_online'), function ($query, $value) { ->when(request()->input('is_online'), function ($query, $value) {
@@ -223,8 +218,6 @@ class ClientEventController extends Controller
// Получаем массив без ключей // Получаем массив без ключей
// Извлекаем уникальные даты из событий // Извлекаем уникальные даты из событий
return $events->map(function ($event) { return $events->map(function ($event) {
$date = new DateTime($event->event_date_start); $date = new DateTime($event->event_date_start);
@@ -252,7 +245,7 @@ class ClientEventController extends Controller
$categoriesContent = []; $categoriesContent = [];
if (request()->input('category')) { if (request()->input('category')) {
foreach (request()->input('category') as $item) { foreach (request()->input('category') as $item) {
$categoriesContent[$item] = new ClientEventCategoryResource(EventCategory::where('slug', $item)->first()); $categoriesContent[$item] = new EventCategoryResource(EventCategory::where('slug', $item)->first());
} }
} }
@@ -0,0 +1,13 @@
<?php
use App\Containers\Event\UI\WEB\Controllers\ClientEventController;
use Illuminate\Support\Facades\Route;
Route::middleware('access-check')->group(function () {
Route::get('/events', [ClientEventController::class, 'index'])->name('client.event.index');
Route::get('/events/archive', [ClientEventController::class, 'archive'])->name('client.event.archive'); // Доделать builder
Route::get('/events/{slug}', [ClientEventController::class, 'show'])->name('client.event.show');
});
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Event\UI\WEB\Transformers;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource; use App\Ship\Resources\JsonResource;
class EventCategoryResource extends JsonResource class EventCategoryResource extends JsonResource
{ {
@@ -12,7 +12,7 @@ class EventCategoryResource extends JsonResource
* *
* @return array<string, mixed> * @return array<string, mixed>
*/ */
public function toArray(Request $request): array public function toArray($request): array
{ {
return parent::toArray($request); return parent::toArray($request);
} }
@@ -1,19 +1,18 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Event\UI\WEB\Transformers;
use Illuminate\Http\Request; use App\Ship\Resources\JsonResource;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
class ClientEventResource extends JsonResource class EventPreviewResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
* *
* @return array<string, mixed> * @return array<string, mixed>
*/ */
public function toArray(Request $request): array public function toArray($request): array
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -1,13 +1,11 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Event\UI\WEB\Transformers;
use Illuminate\Http\Request; use App\Ship\Resources\JsonResource;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Ramsey\Uuid\Type\Integer;
class ClientEventFullResource extends JsonResource class EventResource extends JsonResource
{ {
/** /**
* Transform the resource into an array. * Transform the resource into an array.
@@ -15,7 +13,7 @@ class ClientEventFullResource extends JsonResource
* @return array<string, mixed> * @return array<string, mixed>
*/ */
public function toArray(Request $request): array public function toArray($request): array
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -1,10 +1,9 @@
<?php <?php
namespace App\Http\Resources; namespace App\Containers\Event\UI\WEB\Transformers;
use App\Ship\Resources\JsonResource;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class EventThumbnailResource extends JsonResource class EventThumbnailResource extends JsonResource
{ {
@@ -13,7 +12,7 @@ class EventThumbnailResource extends JsonResource
* *
* @return array<string, mixed> * @return array<string, mixed>
*/ */
public function toArray(Request $request): array public function toArray($request): array
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\InstituteStructure\Loaders;
class AliasesLoader
{
/**
* @var array
*/
public array $aliases = [];
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\InstituteStructure\Loaders;
class MiddlewareLoader
{
/**
* @var array
*/
public array $middleware = [];
/**
* @var array
*/
public array $middlewareGroups = [];
/**
* @var array
*/
public array $routeMiddleware = [];
/**
* @var array
*/
public array $middlewarePriority = [];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\InstituteStructure\Loaders;
class ProvidersLoader
{
/**
* @var array
*/
public array $providers = [];
}
@@ -1,13 +1,18 @@
<?php <?php
namespace App\Models; namespace App\Containers\InstituteStructure\Models;
use App\Containers\Education\Models\EducationalProgram;
use App\Containers\User\Models\User;
use App\Ship\Models\Model;
use App\Ship\Traits\HasSeo;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Department extends Model class Department extends Model
{ {
use HasFactory; use HasFactory, HasSeo;
protected $guarded = false; protected $guarded = false;
@@ -15,27 +20,22 @@ class Department extends Model
'content' => 'array', 'content' => 'array',
]; ];
public function seo() public function faculty(): BelongsTo
{
return $this->morphOne(Seo::class, 'seoable');
}
public function faculty()
{ {
return $this->belongsTo(Faculty::class); return $this->belongsTo(Faculty::class);
} }
public function workers() public function workers(): BelongsToMany
{ {
return $this->belongsToMany(User::class, 'workers_departments')->withPivot(['position', 'sort', 'service_email', 'service_phone', 'cabinet']); return $this->belongsToMany(User::class, 'workers_departments')->withPivot(['position', 'sort', 'service_email', 'service_phone', 'cabinet']);
} }
public function programs() public function programs(): BelongsToMany
{ {
return $this->belongsToMany(EducationalProgram::class, 'program_department'); return $this->belongsToMany(EducationalProgram::class, 'program_department');
} }
public function teachers() public function teachers(): BelongsToMany
{ {
return $this->belongsToMany(User::class, 'teachers_departments')->withPivot(['teaching_position', 'sort', 'service_email', 'service_phone', 'cabinet']); return $this->belongsToMany(User::class, 'teachers_departments')->withPivot(['teaching_position', 'sort', 'service_email', 'service_phone', 'cabinet']);
} }

Some files were not shown because too many files have changed in this diff Show More