diff --git a/app/modules/tag/TagModule.php b/app/modules/tag/TagModule.php new file mode 100644 index 0000000..ff826c6 --- /dev/null +++ b/app/modules/tag/TagModule.php @@ -0,0 +1,8 @@ +menuService = new MenuService(); + $this->migrationService = new MigrationService(); + } + + /** + * @throws \Exception + */ + public function init(): void + { + $this->migrationService->runAtPath("{KERNEL_APP_MODULES}/tag/migrations"); + + $this->menuService->createItem([ + "label" => "Тэги", + "url" => "/admin/tag", + "slug" => "tag", + ]); + + $this->menuService->createItem([ + "label" => "Тэги", + "url" => "/admin/settings/tag", + "slug" => "tag_settings", + "parent_slug" => "settings" + ]); + + OptionService::createFromParams("entity_tag_list", "{}", "Список тегов"); + } + + /** + * @throws \Exception + */ + public function deactivate(): void + { + $this->menuService->removeItemBySlug("tag"); + $this->menuService->removeItemBySlug("tag_settings"); + + OptionService::removeOptionByKey("entity_tag_list"); + + $this->migrationService->rollbackAtPath("{KERNEL_APP_MODULES}/tag/migrations"); + } + + public function formInputs(string $entity, Model $model = null): void + { + if (isset($model->id)) { + $value = TagEntityService::getTagsByEntity($entity, $model->id); + } + + $input = SelectBuilder::build("tag[]", [ + 'class' => 'form-control', + 'placeholder' => 'Теги', + 'value' => $value ?? '', + 'multiple' => "multiple", + 'options' => Tag::getTagLabelByEntity($entity) + ]); + $input->setLabel("Теги"); + $input->create()->render(); + } + + public function saveInputs(string $entity, Model $model, Request $request): void + { + TagEntity::where("entity", $entity)->where("entity_id", $model->id)->delete(); + + $tags = $request->post("tag"); + if (is_array($tags)) { + foreach ($tags as $tag) { + $tagEntity = new TagEntity(); + $tagEntity->entity = $entity; + $tagEntity->entity_id = $model->id; + $tagEntity->tag_id = $tag; + $tagEntity->save(); + } + } + } + + + public function getItems(string $entity, Model $model): array|string + { + $tags = TagEntity::where("entity", $entity)->where("entity_id", $model->id)->with("tag")->get(); + $tagsStr = ""; + foreach ($tags as $tag) { + $tagsStr .= $tag->tag->label . ", "; + } + + return substr($tagsStr, 0, -2); + } + + public function getItem(string $entity, string $entity_id): string + { + $tags = TagEntity::where("entity", $entity)->where("entity_id", $entity_id)->get(); + $tagsStr = ""; + foreach ($tags as $tag) { + $tagsStr .= $tag->tag->label . ", "; + } + + return substr($tagsStr, 0, -2); + } + + public function deleteItems(string $entity, Model $model): void + { + TagEntity::where("entity", $entity)->where("entity_id", $model->id)->delete(); + } +} \ No newline at end of file diff --git a/kernel/app_modules/tag/controllers/TagController.php b/kernel/app_modules/tag/controllers/TagController.php new file mode 100644 index 0000000..e20b907 --- /dev/null +++ b/kernel/app_modules/tag/controllers/TagController.php @@ -0,0 +1,120 @@ +cgView->viewPath = KERNEL_APP_MODULES_DIR . "/tag/views/tag/"; + $this->tagService = new TagService(); + } + + public function actionCreate(): void + { + $this->cgView->render("form.php"); + } + + #[NoReturn] public function actionAdd(): void + { + $tagForm = new CreateTagForm(); + $tagForm->load($_REQUEST); + if ($tagForm->validate()){ + $tag = $this->tagService->create($tagForm); + if ($tag){ + $this->redirect("/admin/tag/view/" . $tag->id); + } + } + $this->redirect("/admin/tag/create"); + } + + public function actionIndex($page_number = 1): void + { + $this->cgView->render("index.php", ['page_number' => $page_number]); + } + + /** + * @throws Exception + */ + public function actionView($id): void + { + $tag = Tag::find($id); + + if (!$tag){ + throw new Exception(message: "The tag not found"); + } + $this->cgView->render("view.php", ['tag' => $tag]); + } + + /** + * @throws Exception + */ + public function actionUpdate($id): void + { + $model = Tag::find($id); + if (!$model){ + throw new Exception(message: "The tag not found"); + } + + $this->cgView->render("form.php", ['model' => $model]); + } + + /** + * @throws Exception + */ + public function actionEdit($id): void + { + $tag = Tag::find($id); + if (!$tag){ + throw new Exception(message: "The tag not found"); + } + $tagForm = new CreateTagForm(); + $tagService = new TagService(); + $tagForm->load($_REQUEST); + if ($tagForm->validate()) { + $tag = $tagService->update($tagForm, $tag); + if ($tag) { + $this->redirect("/admin/tag/view/" . $tag->id); + } + } + $this->redirect("/admin/tag/update/" . $id); + } + + #[NoReturn] public function actionDelete($id): void + { + $post = Tag::find($id)->first(); + $post->delete(); + $this->redirect("/admin/tag/"); + } + + public function actionSettings(): void + { + $this->cgView->render('settingsForm.php'); + } + + #[NoReturn] public function actionSaveSettings(): void + { + $request = new Request(); + $entities = $request->post('entity'); + EntityRelation::configurationEntitiesByProperty($entities, 'tag'); + + Flash::setMessage("success", "Настройка прошла успешно"); + $this->redirect("/admin/settings/tag", 302); + } + +} \ No newline at end of file diff --git a/kernel/app_modules/tag/controllers/TagEntityController.php b/kernel/app_modules/tag/controllers/TagEntityController.php new file mode 100644 index 0000000..8df18d0 --- /dev/null +++ b/kernel/app_modules/tag/controllers/TagEntityController.php @@ -0,0 +1,49 @@ +cgView->viewPath = KERNEL_APP_MODULES_DIR . "/tag/views/tag_entity/"; + } + + /** + * @param $page_number + * @return void + */ + public function actionIndex($page_number = 1): void + { + $this->cgView->render("index.php", ['page_number' => $page_number]); + } + + /** + * @throws Exception + */ + public function actionView($id): void + { + $tagEntity = TagEntity::find($id); + + if (!$tagEntity){ + throw new Exception(message: "The tag entity not found"); + } + $this->cgView->render("view.php", ['tagEntity' => $tagEntity]); + } + +} \ No newline at end of file diff --git a/kernel/app_modules/tag/migrations/2024_10_08_093710_create_tag_table.php b/kernel/app_modules/tag/migrations/2024_10_08_093710_create_tag_table.php new file mode 100644 index 0000000..810dece --- /dev/null +++ b/kernel/app_modules/tag/migrations/2024_10_08_093710_create_tag_table.php @@ -0,0 +1,33 @@ +schema->create('tag', function (Blueprint $table) { + $table->increments('id'); + $table->string('label', 255)->nullable(false); + $table->string('entity', 255)->nullable(false); + $table->string('slug', 255)->unique(); + $table->integer('status')->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + \kernel\App::$db->schema->dropIfExists('tag'); + } + +}; diff --git a/kernel/app_modules/tag/migrations/2024_11_25_122506_create_tag_entity_table.php b/kernel/app_modules/tag/migrations/2024_11_25_122506_create_tag_entity_table.php new file mode 100644 index 0000000..11c4c2a --- /dev/null +++ b/kernel/app_modules/tag/migrations/2024_11_25_122506_create_tag_entity_table.php @@ -0,0 +1,32 @@ +schema->create('tag_entity', function (Blueprint $table) { + $table->increments('id'); + $table->integer('tag_id')->nullable(false); + $table->string('entity', 255)->nullable(false); + $table->integer('entity_id')->nullable(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + \kernel\App::$db->schema->dropIfExists('tag_entity'); + } +}; diff --git a/kernel/app_modules/tag/models/Tag.php b/kernel/app_modules/tag/models/Tag.php new file mode 100644 index 0000000..df4c8ee --- /dev/null +++ b/kernel/app_modules/tag/models/Tag.php @@ -0,0 +1,61 @@ + 'Заголовок', + 'entity' => 'Сущность', + 'slug' => 'Slug', + 'status' => 'Статус', + ]; + } + + /** + * @return string[] + */ + public static function getStatus(): array + { + return [ + self::DISABLE_STATUS => "Не активный", + self::ACTIVE_STATUS => "Активный", + ]; + } + + public static function getTagListByEntity(string $entity): array + { + return self::where("entity", $entity)->get()->toArray(); + } + + public static function getTagLabelByEntity(string $entity): array + { + $result = []; + $tags = self::getTagListByEntity($entity); + foreach ($tags as $tag){ + $result[$tag['id']] = $tag['label']; + } + + return $result; + } + +} \ No newline at end of file diff --git a/kernel/app_modules/tag/models/TagEntity.php b/kernel/app_modules/tag/models/TagEntity.php new file mode 100644 index 0000000..e1a8956 --- /dev/null +++ b/kernel/app_modules/tag/models/TagEntity.php @@ -0,0 +1,32 @@ + 'тег', + 'entity' => 'Сущность', + 'entity_id' => 'Идентификатор сущности', + ]; + } + + public function tag(): \Illuminate\Database\Eloquent\Relations\BelongsTo + { + return $this->belongsTo(Tag::class); + } +} \ No newline at end of file diff --git a/kernel/app_modules/tag/models/forms/CreateTagEntityForm.php b/kernel/app_modules/tag/models/forms/CreateTagEntityForm.php new file mode 100644 index 0000000..52a029f --- /dev/null +++ b/kernel/app_modules/tag/models/forms/CreateTagEntityForm.php @@ -0,0 +1,19 @@ + 'required', + 'entity' => '', + 'entity_id' => '', + ]; + } + +} \ No newline at end of file diff --git a/kernel/app_modules/tag/models/forms/CreateTagForm.php b/kernel/app_modules/tag/models/forms/CreateTagForm.php new file mode 100644 index 0000000..8f68633 --- /dev/null +++ b/kernel/app_modules/tag/models/forms/CreateTagForm.php @@ -0,0 +1,20 @@ + 'required|min-str-len:5|max-str-len:30', + 'entity' => 'required', + 'slug' => '', + 'status' => '' + ]; + } + +} \ No newline at end of file diff --git a/kernel/app_modules/tag/routs/tag.php b/kernel/app_modules/tag/routs/tag.php new file mode 100644 index 0000000..adb1c9e --- /dev/null +++ b/kernel/app_modules/tag/routs/tag.php @@ -0,0 +1,34 @@ +group(["prefix" => "admin"], function (CgRouteCollector $router) { + App::$collector->group(["before" => "auth"], function (RouteCollector $router) { + App::$collector->group(["prefix" => "tag"], function (CGRouteCollector $router) { + App::$collector->get('/', [\app\modules\tag\controllers\TagController::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\app\modules\tag\controllers\TagController::class, 'actionIndex']); + App::$collector->get('/create', [\app\modules\tag\controllers\TagController::class, 'actionCreate']); + App::$collector->post("/", [\app\modules\tag\controllers\TagController::class, 'actionAdd']); + App::$collector->get('/view/{id}', [\app\modules\tag\controllers\TagController::class, 'actionView']); + App::$collector->any('/update/{id}', [\app\modules\tag\controllers\TagController::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\app\modules\tag\controllers\TagController::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\app\modules\tag\controllers\TagController::class, 'actionDelete']); + }); + App::$collector->group(["prefix" => "tag_entity"], function (CGRouteCollector $router) { + App::$collector->get('/', [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionIndex']); + App::$collector->get('/create', [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionCreate']); + App::$collector->post("/", [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionAdd']); + App::$collector->get('view/{id}', [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionView']); + App::$collector->any('/update/{id}', [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\kernel\app_modules\tag\controllers\TagEntityController::class, 'actionDelete']); + }); + App::$collector->group(["prefix" => "settings"], function (CGRouteCollector $router) { + App::$collector->get('/tag', [\app\modules\tag\controllers\TagController::class, 'actionSettings']); + App::$collector->post('/tag/update', [\app\modules\tag\controllers\TagController::class, 'actionSaveSettings']); + }); + }); +}); \ No newline at end of file diff --git a/kernel/app_modules/tag/service/TagEntityService.php b/kernel/app_modules/tag/service/TagEntityService.php new file mode 100644 index 0000000..00cacfa --- /dev/null +++ b/kernel/app_modules/tag/service/TagEntityService.php @@ -0,0 +1,51 @@ +tag_id = $form_model->getItem('tag_id'); + $model->entity = $form_model->getItem('entity'); + $model->entity_id = $form_model->getItem('entity_id'); + if ($model->save()){ + return $model; + } + + return false; + } + + public function update(FormModel $form_model, TagEntity $tag): false|TagEntity + { + $tag->tag_id = $form_model->getItem('tag_id'); + $tag->entity = $form_model->getItem('entity'); + $tag->entity_id = $form_model->getItem('entity_id'); + + if ($tag->save()){ + return $tag; + } + + return false; + } + + public static function getTagsByEntity(string $entity, int $entity_id): array + { + $tags= TagEntity::where("entity_id", $entity_id)->where("entity", $entity)->get(); + $value = []; + foreach ($tags as $tag) { + $value[$tag->id] = $tag->tag->label; + } + + return $value; + } + +} \ No newline at end of file diff --git a/kernel/app_modules/tag/service/TagService.php b/kernel/app_modules/tag/service/TagService.php new file mode 100644 index 0000000..1a69ba6 --- /dev/null +++ b/kernel/app_modules/tag/service/TagService.php @@ -0,0 +1,43 @@ +label = $form_model->getItem('label'); + $model->entity = $form_model->getItem('entity'); + $model->status = $form_model->getItem('status'); + $model->slug = Slug::createSlug($form_model->getItem('label'), Tag::class); + if ($model->save()){ + return $model; + } + + return false; + } + + public function update(FormModel $form_model, Tag $tag): false|Tag + { + if ($tag->label !== $form_model->getItem('label')) { + $tag->slug = Slug::createSlug($form_model->getItem('label'), Tag::class); + } + $tag->label = $form_model->getItem('label'); + $tag->entity = $form_model->getItem('entity'); + $tag->status = $form_model->getItem('status'); + + if ($tag->save()){ + return $tag; + } + + return false; + } + +} \ No newline at end of file diff --git a/kernel/app_modules/tag/views/tag/form.php b/kernel/app_modules/tag/views/tag/form.php new file mode 100644 index 0000000..2685b40 --- /dev/null +++ b/kernel/app_modules/tag/views/tag/form.php @@ -0,0 +1,58 @@ +beginForm(isset($model) ? "/admin/tag/edit/" . $model->id : "/admin/tag"); + +$form->field(class: \itguild\forms\inputs\TextInput::class, name: "label", params: [ + 'class' => "form-control", + 'placeholder' => 'Заголовок', + 'value' => $model->label ?? '' +]) + ->setLabel("Заголовок") + ->render(); + +$form->field(class: \itguild\forms\inputs\Select::class, name: "entity", params: [ + 'class' => "form-control", + 'value' => $model->entity ?? '' +]) + ->setLabel("Сущность") + ->setOptions(\kernel\EntityRelation::getEntityList()) + ->render(); + +$form->field(\itguild\forms\inputs\Select::class, 'status', [ + 'class' => "form-control", + 'value' => $model->status ?? '' +]) + ->setLabel("Статус") + ->setOptions(Tag::getStatus()) + ->render(); +?> +