This commit is contained in:
2025-08-01 14:29:50 +03:00
parent 2ab819ff30
commit b86b8ff923
54 changed files with 1512 additions and 672 deletions

View File

@@ -0,0 +1,31 @@
<?php
namespace kernel\modules\notification;
use kernel\Flash;
use kernel\modules\notification\contracts\NotificationChannelInterface;
use kernel\modules\notification\contracts\NotificationMessage;
use kernel\modules\user\models\User;
class NotificationDispatcher
{
protected array $channels = [];
public function addChannel(string $channelName, NotificationChannelInterface $channel): void
{
$this->channels[$channelName] = $channel;
}
public function dispatch(NotificationMessage $notification, User $user): void
{
foreach ($notification->via() as $channelName) {
if (isset($this->channels[$channelName])) {
try {
$this->channels[$channelName]->send($notification, $user);
} catch (\Exception $e) {
Flash::setMessage("error", $e->getMessage());
}
}
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace kernel\modules\notification;
use kernel\Module;
use kernel\modules\menu\service\MenuService;
use kernel\services\MigrationService;
class NotificationModule extends Module
{
public MenuService $menuService;
public MigrationService $migrationService;
public function __construct()
{
$this->menuService = new MenuService();
$this->migrationService = new MigrationService();
}
/**
* @throws \Exception
*/
public function init(): void
{
$this->migrationService->runAtPath("kernel/modules/notification/migrations");
$this->menuService->createItem([
"label" => "Уведомления",
"url" => "/admin/notification",
"slug" => "notification"
]);
}
/**
* @throws \Exception
*/
public function deactivate(): void
{
$this->migrationService->rollbackAtPath("kernel/modules/notification/migrations");
$this->menuService->removeItemBySlug("notification");
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace kernel\modules\notification\channels;
use kernel\Flash;
use kernel\modules\notification\contracts\NotificationChannelInterface;
use kernel\modules\notification\contracts\NotificationMessage;
use kernel\modules\notification\models\User;
class DatabaseChannel implements NotificationChannelInterface
{
public function send(NotificationMessage $notification, User $user): bool
{
try {
$user->notifications()->create([
'message' => $notification->getMessage(),
'data' => $notification->toArray()
]);
return true;
} catch (\Exception $e) {
Flash::setMessage("error", $e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace kernel\modules\notification\channels;
use kernel\helpers\SMTP;
use kernel\modules\notification\contracts\NotificationChannelInterface;
use kernel\modules\notification\contracts\NotificationMessage;
use kernel\modules\user\models\User;
use PHPMailer\PHPMailer\Exception;
class EmailChannel implements NotificationChannelInterface
{
/**
* @throws Exception
*/
public function send(NotificationMessage $notification, User $user): bool
{
$smtp = new SMTP();
// Здесь можно использовать Laravel Mail
// \Illuminate\Support\Facades\Mail::to($user->email)
// ->send(new \App\Mail\NotificationMail(
// $notification->getSubject(),
// $notification->getMessage()
// ));
return $smtp->send_html([
'address' => $user->email,
'subject' => $notification->getSubject(),
'body' => $notification->getMessage(),
'from_name' => $_ENV['MAIL_SMTP_USERNAME'],
]);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace kernel\modules\notification\channels;
use kernel\modules\notification\contracts\NotificationChannelInterface;
use kernel\modules\notification\contracts\NotificationMessage;
use kernel\modules\user\models\User;
class SmsChannel implements NotificationChannelInterface
{
public function send(NotificationMessage $notification, User $user): bool
{
if (empty($user->phone)) {
return false;
}
// Интеграция с SMS-сервисом
//$smsService = new \App\Services\SmsService();
//return $smsService->send($user->phone, $notification->getMessage());
return true;
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace kernel\modules\notification\channels;
use kernel\Flash;
use kernel\modules\notification\contracts\NotificationChannelInterface;
use kernel\modules\notification\contracts\NotificationMessage;
use kernel\modules\notification\models\User;
class TelegramChannel implements NotificationChannelInterface
{
protected string $botToken;
public function __construct(string $botToken)
{
$this->botToken = $botToken;
}
public function send(NotificationMessage $notification, User $user): bool
{
if (empty($user->telegram_chat_id)) {
return false;
}
$httpClient = new \GuzzleHttp\Client();
try {
$response = $httpClient->post("https://api.telegram.org/bot{$this->botToken}/sendMessage", [
'form_params' => [
'chat_id' => $user->telegram_chat_id,
'text' => $notification->getMessage(),
'parse_mode' => 'HTML'
]
]);
return $response->getStatusCode() === 200;
} catch (\Exception $e) {
Flash::setMessage("error", $e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace kernel\modules\notification\contracts;
use kernel\modules\notification\models\User;
interface NotificationChannelInterface
{
public function send(NotificationMessage $notification, User $user): bool;
}

View File

@@ -0,0 +1,31 @@
<?php
namespace kernel\modules\notification\contracts;
abstract class NotificationMessage
{
protected array $channels = [];
abstract public function getMessage(): string;
abstract public function getSubject(): string;
public function via(): array
{
return $this->channels;
}
public function addChannel(string $channel): void
{
if (!in_array($channel, $this->channels)) {
$this->channels[] = $channel;
}
}
public function toArray(): array
{
return [
'message' => $this->getMessage(),
'subject' => $this->getSubject(),
];
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace kernel\modules\notification\controllers;
use JetBrains\PhpStorm\NoReturn;
use kernel\AdminController;
use kernel\Flash;
use kernel\helpers\Debug;
use kernel\modules\notification\models\forms\CreateNotificationForm;
use kernel\modules\notification\models\Notification;
use kernel\modules\notification\service\NotificationService;
use kernel\modules\option\models\forms\CreateOptionForm;
class NotificationController extends AdminController
{
private NotificationService $optionService;
public function init(): void
{
parent::init();
$this->cgView->viewPath = KERNEL_MODULES_DIR . '/notification/views/';
$this->optionService = new NotificationService();
}
public function actionCreate(): void
{
$this->cgView->render('form.php');
}
#[NoReturn] public function actionAdd(): void
{
$optionForm = new CreateNotificationForm();
$optionForm->load($_REQUEST);
if ($optionForm->validate()) {
$option = $this->optionService->create($optionForm);
if ($option) {
Flash::setMessage("success", "notification успешно создана.");
$this->redirect('/admin/notification');
}
}
Flash::setMessage("error", $optionForm->getErrorsStr());
$this->redirect('/admin/notification/create');
}
public function actionIndex($page_number = 1): void
{
$this->cgView->render('index.php', ['page_number' => $page_number]);
}
/**
* @throws \Exception
*/
public function actionView(int $id): void
{
$option = Notification::find($id);
if (!$option) {
throw new \Exception('notification not found');
}
$this->cgView->render("view.php", ['option' => $option]);
}
/**
* @throws \Exception
*/
public function actionUpdate(int $id): void
{
$model = Notification::find($id);
if (!$model) {
throw new \Exception('notification not found');
}
$this->cgView->render("form.php", ['model' => $model]);
}
/**
* @throws \Exception
*/
public function actionEdit(int $id): void
{
$option = Notification::find($id);
if (!$option) {
throw new \Exception('Option not found');
}
$optionForm = new CreateOptionForm();
$optionForm->load($_REQUEST);
if ($optionForm->validate()) {
$option = $this->optionService->update($optionForm, $option);
if ($option) {
$this->redirect('/admin/notification/view/' . $option->id);
}
}
$this->redirect('/admin/notification/update/' . $id);
}
#[NoReturn] public function actionDelete(int $id): void
{
Notification::find($id)->delete();
Flash::setMessage("success", "notification успешно удалена.");
$this->redirect('/admin/notification');
}
}

View File

@@ -0,0 +1,13 @@
{
"name": "Notifications",
"version": "0.1",
"author": "ITGuild",
"slug": "notification",
"type": "entity",
"description": "Notifications module",
"module_class": "kernel\\modules\\notification\\NotificationModule",
"module_class_file": "{KERNEL_MODULES}/notification/NotificationModule.php",
"routs": "routs/notification.php",
"migration_path": "migrations",
"dependence": "user,menu"
}

View File

@@ -0,0 +1,41 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
\kernel\App::$db->schema->create('notification', function (Blueprint $table) {
$table->id();
// Связь с пользователем
$table->unsignedBigInteger('user_id');
// Основные данные уведомления
$table->string('type')->index(); // Класс уведомления (например, App\Notifications\OrderCreated)
$table->text('message'); // Текст уведомления
$table->string('subject')->nullable(); // Тема (для email)
$table->json('data')->nullable(); // Дополнительные данные в JSON
// Статус уведомления
$table->boolean('is_read')->default(false);
$table->integer('status')->default(1);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
\kernel\App::$db->schema->dropIfExists('notification');
}
};

View File

@@ -0,0 +1,71 @@
<?php
namespace kernel\modules\notification\models;
use Illuminate\Database\Eloquent\Model;
use kernel\modules\user\models\User;
/**
* @property int $id
* @property int $user_id
* @property bool $is_read
* @property array|string $data
* @property string $type
* @property string $message
* @property string $subject
* @property int $status
*/
class Notification extends Model
{
const DISABLE_STATUS = 0;
const TO_SEND_STATUS = 1;
const SENT_STATUS = 2;
protected $table = 'notification';
protected $fillable = ['user_id', 'message', 'is_read', 'data', 'type', 'subject', 'status'];
protected $casts = [
'is_read' => 'boolean',
'data' => 'array'
];
public static function labels(): array
{
return [
'user_id' => 'Пользователь',
'message' => 'Сообщение',
'subject' => 'Тема',
'is_read' => 'Прочитано',
'data' => 'Данные',
'type' => 'Тип',
'status' => 'Статус'
];
}
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class);
}
public function markAsRead(): static
{
$this->update(['is_read' => true]);
return $this;
}
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::DISABLE_STATUS => "Не активный",
self::TO_SEND_STATUS => "На отправку",
self::SENT_STATUS => "Отправлено",
];
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace kernel\modules\notification\models;
class User extends \kernel\modules\user\models\User
{
public function notifications(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(Notification::class);
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace kernel\modules\notification\models\forms;
use kernel\FormModel;
/**
* @property string $key
* @property string $value
* @property string $label
* @property integer $status
*/
class CreateNotificationForm extends FormModel
{
public function rules(): array
{
return [
'user_id' => 'required|integer',
'message' => 'required',
'is_read' => '',
'data' => '',
'type' => 'required',
'subject' => '',
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
use kernel\App;
use Phroute\Phroute\RouteCollector;
App::$collector->group(["prefix" => "admin"], function (RouteCollector $router) {
App::$collector->group(["before" => "auth"], function (RouteCollector $router) {
App::$collector->group(["prefix" => "notification"], callback: function (RouteCollector $router) {
App::$collector->get('/', [\kernel\modules\notification\controllers\NotificationController::class, 'actionIndex']);
App::$collector->get('/page/{page_number}', [\kernel\modules\notification\controllers\NotificationController::class, 'actionIndex']);
App::$collector->get('/create', [\kernel\modules\notification\controllers\NotificationController::class, 'actionCreate']);
App::$collector->post("/", [\kernel\modules\notification\controllers\NotificationController::class, 'actionAdd']);
App::$collector->get('/view/{id}', [\kernel\modules\notification\controllers\NotificationController::class, 'actionView']);
App::$collector->any('/update/{id}', [\kernel\modules\notification\controllers\NotificationController::class, 'actionUpdate']);
App::$collector->any("/edit/{id}", [\kernel\modules\notification\controllers\NotificationController::class, 'actionEdit']);
App::$collector->get('/delete/{id}', [\kernel\modules\notification\controllers\NotificationController::class, 'actionDelete']);
});
});
});

View File

@@ -0,0 +1,57 @@
<?php
namespace kernel\modules\notification\service;
use kernel\FormModel;
use kernel\modules\notification\models\Notification;
class NotificationService
{
public function create(FormModel $form_model): false|Notification
{
$model = new Notification();
$model->user_id = $form_model->getItem('user_id');
$model->message = $form_model->getItem('message');
$model->is_read = $form_model->getItem('is_read');
$model->data = $form_model->getItem('data');
$model->type = $form_model->getItem('type');
$model->subject = $form_model->getItem('subject');
$model->status = $form_model->getItem('status');
if ($model->save()) {
return $model;
}
return false;
}
public function update(FormModel $form_model, Notification $notification): false|Notification
{
$notification->user_id = $form_model->getItem('user_id');
$notification->message = $form_model->getItem('message');
$notification->is_read = $form_model->getItem('is_read');
$notification->data = $form_model->getItem('data');
$notification->type = $form_model->getItem('type');
$notification->subject = $form_model->getItem('subject');
$notification->status = $form_model->getItem('status');
if ($notification->save()) {
return $notification;
}
return false;
}
// public function createOptionArr(): array
// {
// foreach (Option::all()->toArray() as $option) {
// $optionArr[$option['id']] = $option['key'];
// }
// if (!empty($optionArr)) {
// return $optionArr;
// }
// return [];
// }
}

View File

@@ -0,0 +1,16 @@
<?php
namespace kernel\modules\option\table\columns;
use Itguild\Tables\ActionColumn\ActionColumn;
class OptionDeleteActionColumn extends ActionColumn
{
protected string $prefix = "/delete/";
public function fetch(): string
{
$link = $this->baseUrl . $this->prefix . $this->id;
return " <a href='$link' class='btn btn-danger'>Удалить</a> ";
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace kernel\modules\option\table\columns;
use Itguild\Tables\ActionColumn\ActionColumn;
class OptionEditActionColumn extends ActionColumn
{
protected string $prefix = "/update/";
public function fetch(): string
{
$link = $this->baseUrl . $this->prefix . $this->id;
return " <a href='$link' class='btn btn-success'>Редактировать</a> ";
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace kernel\modules\option\table\columns;
use Itguild\Tables\ActionColumn\ActionColumn;
class OptionViewActionColumn extends ActionColumn
{
protected string $prefix = "/";
public function fetch()
{
$link = $this->baseUrl . $this->prefix . $this->id;
return " <a href='$link' class='btn btn-primary'>Просмотр</a> ";
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
* @var Notification $model
*/
use itguild\forms\ActiveForm;
use kernel\modules\notification\models\Notification;
$form = new ActiveForm();
$form->beginForm(isset($model) ? "/admin/notification/edit/" . $model->id : "/admin/notification");
$form->field(class: \itguild\forms\inputs\Select::class, name: "user_id", params: [
'class' => "form-control",
'value' => $model->user_id ?? ''
])
->setLabel(Notification::labels()['user_id'])
->setOptions(\kernel\modules\user\service\UserService::createUsernameArr())
->render();
$form->field(\itguild\forms\inputs\TextInput::class, 'subject', [
'class' => "form-control",
'placeholder' => Notification::labels()['subject'],
'value' => $model->subject ?? ''
])
->setLabel(Notification::labels()['subject'])
->render();
$form->field(\itguild\forms\inputs\TextInput::class, 'type', [
'class' => "form-control",
'placeholder' => Notification::labels()['type'],
'value' => $model->type ?? ''
])
->setLabel(Notification::labels()['type'])
->render();
$form->field(\itguild\forms\inputs\TextArea::class, 'message', [
'class' => "form-control",
'placeholder' => Notification::labels()['message'],
'value' => $model->message ?? ''
])
->setLabel(Notification::labels()['message'])
->render();
$form->field(\itguild\forms\inputs\Checkbox::class, 'is_read', [
'class' => "form-check-input",
'placeholder' => Notification::labels()['is_read'],
'value' => $model->is_read ?? ''
])
->setLabel(Notification::labels()['is_read'])
->render();
$form->field(\itguild\forms\inputs\Select::class, 'status', [
'class' => "form-control",
'value' => $model->status ?? ''
])
->setLabel("Статус")
->setOptions(Notification::getStatus())
->render();
?>
<div class="row">
<div class="col-sm-2">
<?php
$form->field(\itguild\forms\inputs\Button::class, name: "btn-submit", params: [
'class' => "btn btn-primary ",
'value' => 'Отправить',
'typeInput' => 'submit'
])
->render();
?>
</div>
<div class="col-sm-2">
<?php
$form->field(\itguild\forms\inputs\Button::class, name: "btn-reset", params: [
'class' => "btn btn-warning",
'value' => 'Сбросить',
'typeInput' => 'reset'
])
->render();
?>
</div>
</div>
<?php
$form->endForm();

View File

@@ -0,0 +1,44 @@
<?php
/**
* @var \Illuminate\Database\Eloquent\Collection $options
* @var int $page_number
*/
use Itguild\EloquentTable\EloquentDataProvider;
use Itguild\EloquentTable\ListEloquentTable;
use kernel\modules\notification\models\Notification;
use kernel\widgets\IconBtn\IconBtnCreateWidget;
use kernel\widgets\IconBtn\IconBtnDeleteWidget;
use kernel\widgets\IconBtn\IconBtnEditWidget;
use kernel\widgets\IconBtn\IconBtnViewWidget;
$table = new ListEloquentTable(new EloquentDataProvider(Notification::class, [
'current_page' => $page_number,
'per_page' => 5,
'params' => ["class" => "table table-bordered", "border" => "2"],
'baseUrl' => "/admin/notification",
]));
$table->beforePrint(function () {
return IconBtnCreateWidget::create(['url' => '/admin/notification/create'])->run();
});
$table->columns([
"status" => [
"value" => function ($cell) {
return Notification::getStatus()[$cell];
}]
]);
$table->addAction(function($row) {
return IconBtnViewWidget::create(['url' => '/admin/notification/view/' . $row['id']])->run();
});
$table->addAction(function($row) {
return IconBtnEditWidget::create(['url' => '/admin/Notification/update/' . $row['id']])->run();
});
$table->addAction(function($row) {
return IconBtnDeleteWidget::create(['url' => '/admin/Notification/delete/' . $row['id']])->run();
});
$table->create();
$table->render();

View File

@@ -0,0 +1,32 @@
<?php
/**
* @var \Illuminate\Database\Eloquent\Collection $option
*/
use Itguild\EloquentTable\ViewEloquentTable;
use Itguild\EloquentTable\ViewJsonTableEloquentModel;
use kernel\IGTabel\btn\DangerBtn;
use kernel\IGTabel\btn\PrimaryBtn;
use kernel\IGTabel\btn\SuccessBtn;
use kernel\widgets\IconBtn\IconBtnDeleteWidget;
use kernel\widgets\IconBtn\IconBtnEditWidget;
use kernel\widgets\IconBtn\IconBtnListWidget;
$table = new ViewEloquentTable(new ViewJsonTableEloquentModel($option, [
'params' => ["class" => "table table-bordered", "border" => "2"],
'baseUrl' => "/admin/user",
]));
$table->beforePrint(function () use ($option) {
$btn = IconBtnListWidget::create(['url' => '/admin/option'])->run();
$btn .= IconBtnEditWidget::create(['url' => '/admin/option/update/' . $option->id])->run();
$btn .= IconBtnDeleteWidget::create(['url' => '/admin/option/delete/' . $option->id])->run();
return $btn;
});
$table->rows([
'status' => (function ($data) {
return \kernel\modules\option\models\Notification::getStatus()[$data];
})
]);
$table->create();
$table->render();

View File

@@ -3,6 +3,7 @@
namespace kernel\modules\option\service;
use kernel\FormModel;
use kernel\helpers\Debug;
use kernel\modules\option\models\Option;
class OptionService
@@ -49,6 +50,26 @@ class OptionService
return false;
}
public static function createOrUpdate(string $key, string $value, string $label = ''): false|Option
{
/** @var Option $option */
$option = self::getItemObject($key);
if (!$option) {
$option = new Option();
$option->key = $key;
}
$option->value = $value;
if (!empty($label)){
$option->label = $label;
}
if ($option->save()) {
return $option;
}
return false;
}
/**
* @param $key
* @return false|array|string
@@ -63,6 +84,20 @@ class OptionService
return false;
}
/**
* @param $key
* @return false|array|string|Option
*/
public static function getItemObject($key): false|array|string|Option
{
$item = Option::where("key", $key)->first();
if ($item){
return $item;
}
return false;
}
public static function removeOptionByKey(string $key): bool
{
$option = Option::where("key", $key)->first();

View File

@@ -33,4 +33,9 @@ class PostService
return false;
}
public static function getListArr()
{
return Post::pluck('title', 'id')->toArray();
}
}

View File

@@ -8,6 +8,7 @@ use kernel\App;
use kernel\Flash;
use kernel\helpers\Debug;
use kernel\Mailing;
use kernel\modules\secure\models\forms\ChangePasswordForm;
use kernel\modules\secure\models\forms\LoginEmailForm;
use kernel\modules\secure\models\forms\LoginForm;
use kernel\modules\secure\models\forms\RegisterForm;
@@ -40,7 +41,7 @@ class SecureController extends AdminController
// $this->cgView->render('login.php');
}
#[NoReturn] public function actionAuth(): void
#[NoReturn] public function actionAuth($basePath = '/admin'): void
{
$loginForm = new LoginForm();
$loginForm->load($_REQUEST);
@@ -51,19 +52,36 @@ class SecureController extends AdminController
else {
$field = "username";
}
$user = $this->userService->getByField($field, $loginForm->getItem("username"));
if (!$user){
Flash::setMessage("error", "User not found.");
$this->redirect("/admin/login", code: 302);
$this->redirect($basePath . "/login", code: 302);
}
if (password_verify($loginForm->getItem("password"), $user->password_hash)) {
setcookie('user_id', $user->id, time()+60*60*24, '/', $_SERVER['SERVER_NAME'], false);
$this->redirect("/admin", code: 302);
$this->redirect($basePath . '/', code: 302);
} else {
Flash::setMessage("error", "Username or password incorrect.");
$this->redirect("/admin/login", code: 302);
$this->redirect($basePath . "/login", code: 302);
}
}
#[NoReturn] public function actionChangePassword($basePath = '/admin'): void
{
$changePasswordForm = new ChangePasswordForm();
$changePasswordForm->load($_REQUEST);
$user = UserService::getAuthUser();
if (password_verify($changePasswordForm->getItem("old_password"), $user->password_hash)) {
$user->password_hash = password_hash($changePasswordForm->getItem("new_password"), PASSWORD_DEFAULT);
$user->save();
Flash::setMessage("success", "Пароль успешно изменен.");
$this->redirect($basePath . '', code: 302);
} else {
Flash::setMessage("error", "Username or password incorrect.");
$this->redirect($basePath . "", code: 302);
}
}
@@ -148,25 +166,25 @@ class SecureController extends AdminController
$this->cgView->render('register.php');
}
public function actionRegistration(): void
public function actionRegistration($basePath = '/admin'): void
{
$regForm = new RegisterForm();
$regForm->load($_REQUEST);
if ($this->userService->getByField('username', $regForm->getItem("username"))) {
Flash::setMessage("error", "Username already exists.");
$this->redirect("/admin/register", code: 302);
$this->redirect($basePath . "/register", code: 302);
}
if ($this->userService->getByField('email', $regForm->getItem("email"))) {
Flash::setMessage("error", "Email already exists.");
$this->redirect("/admin/register", code: 302);
$this->redirect($basePath . "/register", code: 302);
}
$user = $this->userService->create($regForm);
if ($user){
setcookie('user_id', $user->id, time()+60*60*24, '/', $_SERVER['SERVER_NAME'], false);
$this->redirect("/admin", code: 302);
$this->redirect($basePath . "/", code: 302);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace kernel\modules\secure\models\forms;
use kernel\FormModel;
class ChangePasswordForm extends FormModel
{
public function rules(): array
{
return [
'old_password' => 'required|min-str-len:6|max-str-len:50',
'new_password' => 'required|min-str-len:6|max-str-len:50',
];
}
}

View File

@@ -7,6 +7,7 @@ use JetBrains\PhpStorm\NoReturn;
use kernel\AdminController;
use kernel\EntityRelation;
use kernel\FileUpload;
use kernel\Flash;
use kernel\helpers\Debug;
use kernel\modules\user\models\forms\CreateUserForm;
use kernel\modules\user\models\User;
@@ -55,6 +56,7 @@ class UserController extends AdminController
$this->redirect("/admin/user/view/" . $user->id);
}
}
Flash::setMessage("error", $userForm->getErrorsStr());
$this->redirect("/admin/user/create");
}

View File

@@ -2,6 +2,7 @@
namespace kernel\modules\user\service;
use itguild\forms\ActiveForm;
use kernel\FormModel;
use kernel\helpers\Debug;
use kernel\modules\user\models\User;
@@ -122,4 +123,12 @@ class UserService
$user->save();
}
public static function getList(): array
{
return User::select('id', 'username')->get()
->pluck('username', 'id')
->toArray();
}
}

View File

@@ -47,6 +47,8 @@ if (!isset($model)) {
$model = new User();
}
$entityRelations->renderEntityAdditionalPropertyFormBySlug("user", $model);
?>
<div class="row">
<div class="col-sm-2">

View File

@@ -1,7 +1,7 @@
<?php
/**
* @var \Illuminate\Database\Eloquent\Collection $user
* @var User $user
*/
use kernel\modules\user\models\User;
@@ -54,4 +54,6 @@ $table->rows([
}
]);
$table->create();
$table->render();
$table->render();
\kernel\App::$hook->runHooksByEntity('user_view', ['user' => $user]);