Skip to content

Commit

Permalink
Mass message rework (#3494)
Browse files Browse the repository at this point in the history
* wip: mass messaging rework

* WIP notifications

* feat: mass messaging

* chore: tidy force migration

* chore: remove dev template

* style: styleci fixes

* fix: mass message bypass notification settings + mass message bypass purification

* fix: typo in alerts page
  • Loading branch information
samerton committed Mar 31, 2024
1 parent 91763a2 commit 9ce7b65
Show file tree
Hide file tree
Showing 34 changed files with 1,386 additions and 314 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -9,6 +9,7 @@
/vendor
/core/assets/vendor
/uploads/avatars/**
/uploads/logos/**
/node_modules/
composer.lock
checksums.json
Expand Down
47 changes: 39 additions & 8 deletions core/classes/Core/Alert.php
Expand Up @@ -12,13 +12,16 @@ class Alert
/**
* Creates an alert for the specified user.
*
* @param int $user_id Contains the ID of the user who we are creating the alert for.
* @param string $type Contains the alert type, eg 'tag' for user tagging.
* @param array $text_short Contains the alert text in short form for the dropdown.
* @param array $text Contains full information about the alert.
* @param string $link Contains link to view the alert, defaults to #.
* @deprecated Use Alert::send instead
*
* @param int $user_id Contains the ID of the user who we are creating the alert for.
* @param string $type Contains the alert type, eg 'tag' for user tagging.
* @param array $text_short Contains the alert text in short form for the dropdown.
* @param array $text Contains full information about the alert.
* @param ?string $link Contains link to view the alert, defaults to #.
* @param ?string $content Optional alert content.
*/
public static function create(int $user_id, string $type, array $text_short, array $text, string $link = '#'): void
public static function create(int $user_id, string $type, array $text_short, array $text, ?string $link = '#', string $content = null): void
{
$db = DB::getInstance();

Expand All @@ -30,13 +33,41 @@ public static function create(int $user_id, string $type, array $text_short, arr

$language = new Language($text_short['path'], $language->first()->short_code);

$text_short = $text_short['content'] ?? str_replace($text_short['replace'] ?? '', $text_short['replace_with'] ?? '', $language->get($text_short['file'], $text_short['term']));
$text = $text['content'] ?? str_replace($text['replace'] ?? '', $text['replace_with'] ?? '', $language->get($text['file'], $text['term']));

$db->insert('alerts', [
'user_id' => $user_id,
'type' => $type,
'url' => $link,
'content_short' => str_replace($text_short['replace'] ?? '', $text_short['replace_with'] ?? '', $language->get($text_short['file'], $text_short['term'])),
'content' => str_replace($text['replace'] ?? '', $text['replace_with'] ?? '', $language->get($text['file'], $text['term'])),
'content_short' => $text_short,
'content' => $text,
'content_rich' => $content,
'created' => date('U'),
]);
}

/**
* Post a new alert to a user.
*
* @param int $userId
* @param string $title
* @param string $content
* @param string|null $link Optional link to redirect the user to on click
* @param bool $skipPurify If true the content will not be purified before displaying to user - use with care
* @return void
*/
public static function send(int $userId, string $title, string $content, ?string $link = '', bool $skipPurify = false)
{
DB::getInstance()->insert('alerts', [
'user_id' => $userId,
'type' => 'alert',
'url' => $link ?? '',
'content_short' => $title, // Column maintained for legacy reasons
'content' => $title,
'content_rich' => $content,
'created' => date('U'),
'bypass_purify' => $skipPurify,
]);
}

Expand Down
41 changes: 40 additions & 1 deletion core/classes/Core/User.php
Expand Up @@ -6,7 +6,7 @@
* @author Samerton
* @author Partydragen
* @author Aberdeener
* @version 2.1.2
* @version 2.2.0
* @license MIT
*/
class User
Expand Down Expand Up @@ -1122,4 +1122,43 @@ public function savePlaceholders(int $server_id, array $placeholders): void
]);
}
}

/**
* Get user's notification preferences.
*
* TODO: return type (PHP 8)
*
* @param string $type Optional type of notification to filter by
*
* @return UserNotificationData|UserNotificationData[]|null
*/
public function getNotificationPreferences(string $type = '')
{
if ($this->exists()) {
$where = 'user_id = ?';
$whereVars = [$this->data()->id];

if (!empty($type)) {
$where .= ' AND `type` = ?';
$whereVars[] = $type;
}

$this->_db->get(
<<<SQL
SELECT `type`, `alert`, `email`
FROM nl2_users_notification_preferences
WHERE $where
SQL,
$whereVars
);

if (!empty($type)) {
return $this->_db->first();
}

return $this->_db->results();
}

return null;
}
}
22 changes: 22 additions & 0 deletions core/classes/DTO/UserNotificationData.php
@@ -0,0 +1,22 @@
<?php
/**
* Represents notification data which belongs to a user.
*
* @package NamelessMC\DTO
* @author Samerton
* @version 2.2.0
* @license MIT
*/
class UserNotificationData
{
public bool $alert;
public bool $email;
public string $type;

public function __construct(object $row)
{
$this->alert = $row->alert;
$this->email = $row->email;
$this->type = $row->type;
}
}
2 changes: 1 addition & 1 deletion core/classes/Queue/Task.php
Expand Up @@ -157,7 +157,7 @@ public function fromId(int $id): ?Task
$this->_scheduledFor = $task->scheduled_for;
$this->_status = $task->status;
$this->_task = $task->task;
$this->_userId = $task->userId;
$this->_userId = $task->user_id;

return $this;
}
Expand Down
1 change: 1 addition & 0 deletions core/init.php
Expand Up @@ -388,6 +388,7 @@
$cc_nav->add('cc_alerts', $language->get('user', 'alerts'), URL::build('/user/alerts'));
$cc_nav->add('cc_messaging', $language->get('user', 'messaging'), URL::build('/user/messaging'));
$cc_nav->add('cc_connections', $language->get('user', 'connections'), URL::build('/user/connections'));
$cc_nav->add('cc_notification_settings', $language->get('user', 'notification_settings'), URL::build('/user/notification_settings'));
$cc_nav->add('cc_settings', $language->get('user', 'profile_settings'), URL::build('/user/settings'));

// Placeholders enabled?
Expand Down
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class CreateUsersNotificationPreferencesTable extends AbstractMigration
{
public function change(): void
{
$table = $this->table('nl2_users_notification_preferences');

$table
->addColumn('user_id', 'integer', ['length' => 11])
->addColumn('type', 'string', ['length' => 64])
->addColumn('alert', 'boolean', ['default' => false])
->addColumn('email', 'boolean', ['default' => false]);

$table->addForeignKey('user_id', 'nl2_users', 'id', ['delete' => 'CASCADE']);

$table->create();
}
}
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

use Phinx\Db\Adapter\MysqlAdapter;
use Phinx\Migration\AbstractMigration;

final class AddContentRichToAlertsTable extends AbstractMigration
{
public function change(): void
{
$this->table('nl2_alerts')
->addColumn('content_rich', 'text', ['default' => null, 'limit' => MysqlAdapter::TEXT_MEDIUM, 'null' => true])
->update();
}
}
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class AddPurifyBypassColumToAlertsTable extends AbstractMigration
{
public function change(): void
{
$this->table('nl2_alerts')
->addColumn('bypass_purify', 'boolean', ['default' => false])
->update();
}
}
1 change: 1 addition & 0 deletions custom/panel_templates/Default/core/announcements.tpl
Expand Up @@ -25,6 +25,7 @@
<h1 class="h3 mb-0 text-gray-800">{$ANNOUNCEMENTS}</h1>
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{$PANEL_INDEX}">{$DASHBOARD}</a></li>
<li class="breadcrumb-item active">{$COMMUNICATIONS}</li>
<li class="breadcrumb-item active">{$ANNOUNCEMENTS}</li>
</ol>
</div>
Expand Down
1 change: 1 addition & 0 deletions custom/panel_templates/Default/core/announcements_form.tpl
Expand Up @@ -25,6 +25,7 @@
<h1 class="h3 mb-0 text-gray-800">{$ANNOUNCEMENTS}</h1>
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{$PANEL_INDEX}">{$DASHBOARD}</a></li>
<li class="breadcrumb-item active">{$COMMUNICATIONS}</li>
<li class="breadcrumb-item active">{$ANNOUNCEMENTS}</li>
</ol>
</div>
Expand Down
90 changes: 0 additions & 90 deletions custom/panel_templates/Default/core/emails_mass_message.tpl

This file was deleted.

0 comments on commit 9ce7b65

Please sign in to comment.