Skip to content

Commit 21b6ebf

Browse files
Added user notification settings
1 parent 645c3a8 commit 21b6ebf

File tree

7 files changed

+293
-147
lines changed

7 files changed

+293
-147
lines changed

migrations/m250223_110111_create_user_notification_settings_table.php

+20-13
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,39 @@ class m250223_110111_create_user_notification_settings_table extends Migration
66
{
77
public function up()
88
{
9-
109
$this->createTable('user_notification_settings', [
1110
'id' => $this->primaryKey(),
12-
'user_id' => $this->integer()->notNull(),
13-
'notification_group_id' => $this->integer()->notNull(),
14-
'telegram' => $this->boolean()->notNull()->defaultValue(true),
15-
'email' => $this->boolean()->notNull()->defaultValue(true),
16-
'push' => $this->boolean()->notNull()->defaultValue(true),
11+
'user_id' => $this->integer()->notNull(), // ID пользователя
12+
'notification_id' => $this->integer()->notNull(), // ID уведомления
13+
'send_email' => $this->boolean()->defaultValue(false), // Разрешить отправку по Email
14+
'send_telegram' => $this->boolean()->defaultValue(false), // Разрешить отправку в Telegram
15+
'send_push' => $this->boolean()->defaultValue(false), // Разрешить отправку Push-уведомлений
1716
'created_at' => $this->timestamp()->defaultExpression('CURRENT_TIMESTAMP'),
1817
'updated_at' => $this->timestamp()->defaultExpression('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'),
1918
]);
20-
21-
// foreign key for user_id
19+
20+
// Добавляем индексы для оптимизации запросов
21+
$this->createIndex('idx-user_notification_settings-user_id', 'user_notification_settings', 'user_id');
22+
$this->createIndex('idx-user_notification_settings-notification_id', 'user_notification_settings', 'notification_id');
23+
24+
// Добавляем внешние ключи
2225
$this->addForeignKey(
2326
'fk-user_notification_settings-user_id',
2427
'user_notification_settings',
2528
'user_id',
2629
'users',
2730
'id',
31+
'CASCADE',
2832
'CASCADE'
2933
);
3034

31-
// foreign key for notification_group_id
3235
$this->addForeignKey(
33-
'fk-user_notification_settings-notification_group_id',
36+
'fk-user_notification_settings-notification_id',
3437
'user_notification_settings',
35-
'notification_group_id',
36-
'notification_groups',
38+
'notification_id',
39+
'notifications',
3740
'id',
41+
'CASCADE',
3842
'CASCADE'
3943
);
4044
}
@@ -45,7 +49,10 @@ public function up()
4549
public function down()
4650
{
4751
$this->dropForeignKey('fk-user_notification_settings-user_id', 'user_notification_settings');
48-
$this->dropForeignKey('fk-user_notification_settings-notification_group_id', 'user_notification_settings');
52+
$this->dropForeignKey('fk-user_notification_settings-notification_id', 'user_notification_settings');
53+
54+
$this->dropIndex('idx-user_notification_settings-user_id', 'user_notification_settings');
55+
$this->dropIndex('idx-user_notification_settings-notification_id', 'user_notification_settings');
4956

5057
$this->dropTable('user_notification_settings');
5158
}

src/controllers/NotificationsController.php

+46-122
Original file line numberDiff line numberDiff line change
@@ -6,146 +6,70 @@
66
use yii\web\Controller;
77
use ZakharovAndrew\user\models\NotificationGroup;
88
use ZakharovAndrew\user\models\Notification;
9+
use ZakharovAndrew\user\models\UserNotificationSetting;
10+
use ZakharovAndrew\user\models\UserRoles;
911
use yii\web\NotFoundHttpException;
1012
use yii\web\Response;
1113

12-
class NotificationAdminController extends Controller
14+
class NotificationsController extends Controller
1315
{
1416
public function actionIndex()
1517
{
16-
$groups = NotificationGroup::find()->all(); // Fetch all notification groups
17-
18+
$userId = Yii::$app->user->id;
19+
20+
$userRoleIds = UserRoles::getUserRolesIds($userId);
21+
22+
// Запрос для получения всех групп уведомлений и связанных с ними уведомлений
23+
$groups = NotificationGroup::find()
24+
->with([
25+
'notifications' => function ($query) use ($userRoleIds) {
26+
// Фильтруем уведомления:
27+
// - Если уведомление связано с ролями, проверяем, есть ли совпадение с ролями пользователя.
28+
// - Если уведомление НЕ связано с ролями, оно доступно всем.
29+
$query->joinWith('roles')
30+
->andWhere([
31+
'or',
32+
['notification_role.role_id' => null], // Уведомления без ролей (доступны всем)
33+
['and', ['notification_role.role_id' => $userRoleIds]], // Уведомления с ролями, соответствующими пользователю
34+
])
35+
->groupBy('notifications.id'); // Группируем по ID уведомлений, чтобы избежать дубликатов
36+
},
37+
])
38+
->all();
39+
1840
return $this->render('index', [
1941
'groups' => $groups,
20-
'model' => new NotificationGroup(),
21-
'modelNotification' => new Notification()
42+
'userId' => $userId,
2243
]);
2344
}
2445

25-
// Action to handle AJAX request for creating a new NotificationGroup
26-
public function actionCreateGroupAjax()
27-
{
28-
Yii::$app->response->format = Response::FORMAT_JSON; // Set response format to JSON
29-
30-
$model = new NotificationGroup();
31-
32-
if ($model->load(Yii::$app->request->post()) && $model->save()) {
33-
return ['success' => true, 'group' => $model]; // Return success response with the new group
34-
}
35-
36-
return ['success' => false, 'errors' => $model->getErrors()]; // Return error response if saving fails
37-
}
38-
39-
public function actionDeleteGroup($id)
40-
{
41-
$model = NotificationGroup::findOne($id);
42-
43-
if ($model) {
44-
$model->delete();
45-
Yii::$app->session->setFlash('success', 'Group deleted successfully.');
46-
} else {
47-
Yii::$app->session->setFlash('error', 'Group not found.');
48-
}
49-
50-
return $this->redirect(['index']); // Перенаправление обратно на страницу с группами
51-
}
52-
53-
54-
/**
55-
* Сreating a notification
56-
* @param integer $groupId - ID of the group to which the notification is added
57-
* @return type
58-
*/
59-
public function actionCreateNotificationAjax($groupId)
46+
public function actionSaveNotificationSetting()
6047
{
61-
Yii::$app->response->format = Response::FORMAT_JSON;
48+
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
6249

63-
$group = $this->findGroup($groupId);
64-
$model = new Notification();
50+
$userId = Yii::$app->request->post('user_id');
51+
$notificationId = Yii::$app->request->post('notification_id');
52+
$type = Yii::$app->request->post('type');
53+
$value = Yii::$app->request->post('value');
6554

66-
if ($model->load(Yii::$app->request->post())) {
67-
$model->notification_group_id = $group->id;
68-
if ($model->save()) {
69-
return ['success' => true, 'notification' => $model];
70-
}
71-
} else {
72-
echo 'asd';
73-
}
74-
75-
return ['success' => false, 'errors' => $model->getErrors()];
76-
}
77-
78-
public function actionEditNotificationAjax($id)
79-
{
80-
Yii::$app->response->format = Response::FORMAT_JSON;
55+
$setting = UserNotificationSetting::findOne([
56+
'user_id' => $userId,
57+
'notification_id' => $notificationId,
58+
]);
8159

82-
$model = Notification::findOne($id);
83-
if (!$model) {
84-
return ['success' => false, 'message' => 'Notification not found'];
60+
if (!$setting) {
61+
$setting = new UserNotificationSetting([
62+
'user_id' => $userId,
63+
'notification_id' => $notificationId,
64+
]);
8565
}
8666

87-
if ($model->load(Yii::$app->request->post())) {
88-
// Save roles
89-
$roleIds = Yii::$app->request->post('Notification')['roles'] ?? [];
90-
$model->setRoles($roleIds);
91-
92-
if ($model->save()) {
93-
// Convert roles to an array for returning in JSON
94-
$roles = array_map(function ($role) {
95-
return $role->id;
96-
}, $model->roles);
97-
98-
return [
99-
'success' => true,
100-
'notification' => [
101-
'id' => $model->id,
102-
'name' => $model->name,
103-
'description' => $model->description,
104-
'code_name' => $model->code_name,
105-
'function_to_call' => $model->function_to_call,
106-
'roles' => $roles,
107-
],
108-
];
109-
}
110-
}
111-
112-
return ['success' => false, 'errors' => $model->getErrors()];
113-
}
114-
115-
public function actionDeleteNotificationAjax($id)
116-
{
117-
Yii::$app->response->format = Response::FORMAT_JSON;
118-
119-
$model = Notification::findOne($id);
120-
if ($model) {
121-
$model->delete();
122-
return ['success' => true];
123-
}
124-
125-
return ['success' => false, 'message' => 'Notification not found'];
126-
}
127-
128-
public function actionEditGroupAjax($id)
129-
{
130-
Yii::$app->response->format = Response::FORMAT_JSON;
131-
132-
$model = $this->findGroup($id);
133-
134-
if ($model->load(Yii::$app->request->post()) && $model->save()) {
135-
return ['success' => true, 'group' => $model];
136-
}
137-
138-
return ['success' => false, 'errors' => $model->getErrors()];
139-
}
140-
141-
142-
// Helper method to find a NotificationGroup by ID
143-
protected function findGroup($id)
144-
{
145-
if (($model = NotificationGroup::findOne($id)) !== null) {
146-
return $model;
67+
$setting->{'send_' . $type} = ($value=="false" ? 0 : 1);
68+
69+
if ($setting->save()) {
70+
return ['success' => true, 'res' => $value];
14771
}
14872

149-
throw new NotFoundHttpException('The requested page does not exist.'); // Throw an error if the group does not exist
73+
return ['success' => false, 'errors' => $setting->getErrors()];
15074
}
15175
}

src/models/Notification.php

+10-11
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,10 @@ public function getGroup()
5656
return $this->hasOne(NotificationGroup::class, ['id' => 'notification_group_id']); // One-to-one relationship with NotificationGroup.
5757
}
5858

59-
/**
60-
* This method defines the relationship between a notification and user settings.
61-
*
62-
* @return \yii\db\ActiveQuery the relation to the UserNotificationSetting model.
63-
*/
64-
public function getUserSettings()
59+
60+
public function getUserSetting($userId)
6561
{
66-
return $this->hasMany(UserNotificationSetting::class, ['notification_id' => 'id']); // One-to-many relationship with UserNotificationSetting.
62+
return UserNotificationSetting::findOne(['notification_id' => $this->id, 'user_id' => $userId]);
6763
}
6864

6965
/**
@@ -96,10 +92,13 @@ public function setRoles($roleIds)
9692
{
9793
$currentRoleIds = $this->getRoleIds(); // Получаем текущие ID ролей
9894

99-
$rolesToAdd = array_diff($roleIds, $currentRoleIds);
100-
101-
$rolesToRemove = array_diff($currentRoleIds, $roleIds);
102-
95+
if (is_array($roleIds)) {
96+
$rolesToAdd = array_diff($roleIds, $currentRoleIds);
97+
$rolesToRemove = array_diff($currentRoleIds, $roleIds);
98+
} else {
99+
$rolesToAdd = [];
100+
$rolesToRemove = $currentRoleIds ?? [];
101+
}
103102

104103
foreach ($rolesToRemove as $roleId) {
105104
$this->unlink('roles', Roles::findOne($roleId), true);
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace ZakharovAndrew\user\models;
4+
5+
use Yii;
6+
use yii\db\ActiveRecord;
7+
use ZakharovAndrew\user\models\User;
8+
use ZakharovAndrew\user\models\Notification;
9+
10+
class UserNotificationSetting extends ActiveRecord
11+
{
12+
public static function tableName()
13+
{
14+
return 'user_notification_settings';
15+
}
16+
17+
public function rules()
18+
{
19+
return [
20+
[['user_id', 'notification_id'], 'required'],
21+
[['user_id', 'notification_id'], 'integer'],
22+
[['send_email', 'send_telegram', 'send_push'], 'boolean'],
23+
];
24+
}
25+
26+
public function attributeLabels()
27+
{
28+
return [
29+
'user_id' => 'User ID',
30+
'notification_id' => 'Notification ID',
31+
'send_email' => 'Send Email',
32+
'send_telegram' => 'Send Telegram',
33+
'send_push' => 'Send Push',
34+
];
35+
}
36+
37+
public function getUser()
38+
{
39+
return $this->hasOne(User::class, ['id' => 'user_id']);
40+
}
41+
42+
public function getNotification()
43+
{
44+
return $this->hasOne(Notification::class, ['id' => 'notification_id']);
45+
}
46+
}

src/models/UserRoles.php

+23-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Yii;
66
use ZakharovAndrew\user\Module;
7+
use yii\helpers\ArrayHelper;
78

89
/**
910
* This is the model class for table "user_roles".
@@ -71,6 +72,26 @@ public static function getUserRoles($user_id)
7172
}, 600);
7273
}
7374

75+
/**
76+
* Get all user IDs roles
77+
*
78+
* @param integer $user_id User ID
79+
* @return array
80+
*/
81+
public static function getUserRolesIds($user_id)
82+
{
83+
return Yii::$app->cache->getOrSet('get_users_roles_ids_'.$user_id, function () use ($user_id) {
84+
return ArrayHelper::getColumn(
85+
static::find()
86+
->select('DISTINCT(user_roles.role_id)')
87+
->where(['user_roles.user_id' => $user_id])
88+
->asArray()
89+
->all(),
90+
'role_id'
91+
);
92+
}, 600);
93+
}
94+
7495
/**
7596
* Get a list of users who have a role
7697
*
@@ -91,7 +112,7 @@ public static function getUsersListByRoleSubject($role, $subject_id = null)
91112
$model->andWhere(["or", ["user_roles.subject_id" => $subject_id], ["subject_id" => null]]);
92113
}
93114

94-
return \yii\helpers\ArrayHelper::getColumn(
115+
return ArrayHelper::getColumn(
95116
$model->asArray()->all(),
96117
'user_id'
97118
);
@@ -127,6 +148,7 @@ public function afterSave($insert, $changedAttributes)
127148
{
128149
parent::afterSave($insert, $changedAttributes);
129150
Yii::$app->cache->delete('get_users_roles_'.$this->user_id);
151+
Yii::$app->cache->delete('get_users_roles_ids_'.$this->user_id);
130152
Yii::$app->cache->delete('get_roles_by_user_'.$this->user_id);
131153
}
132154
}

0 commit comments

Comments
 (0)