Интерфейс бана пользователя

Смотрю, что-то заметка про аватар пользователя оказалась слишком простой, поднимем немного градус.
Покажу как будет выглядеть интерфейс бана пользователя по итогу.



Ниже представлен код, куски которого когда-то писали коллеги по данному сайту и чатику в телеграме.
А я уже дописал чего не хватало и собрал все в кучку.


Необходимо будет выполнить несколько шагов
  1. Создание полей в базе
  2. Плагин
  3. Создание чанка для письма-уведомления

Cоздать в базе следующие поля для таблицы (modx)_user_attributes:

Ниже, в плагине каждое поле описано подробнее.

isbanned: int. по умолчанию: 0
banneduntil: datetime. по умолчанию: NULL
banned_noticed: int. по умолчанию: 0
banned_notice_text: text

Плагин:

  • расширение класса пользователя
  • интерфейс на extjs
  • уведомление пользователя (если необходимо)
Создайте плагин с любым названием, например: userBanned и укажите следующие события
OnMODXInit
OnUserFormPrerender
OnUserSave

<?php
switch ($modx->event->name) {
    
    // Расширяем класс пользователя
    case "OnMODXInit":
        
		$modx->loadClass('modUserProfile');
		
		//////////////////////////////
		
		$modx->map['modUserProfile']['fields']['isbanned'] = 0;
		$modx->map['modUserProfile']['fieldMeta']['isbanned'] = array(
			'dbtype' => 'int',
			'precision' => 1,
			'attributes' => 'unsigned',
			'phptype' => 'integer',
			'null' => true,
			'default' => 0
		);
		
		//////////////////////////////
		
		$modx->map['modUserProfile']['fields']['banneduntil'] = NULL;
		$modx->map['modUserProfile']['fieldMeta']['banneduntil'] = array(
			'dbtype' => 'datetime',  
			'phptype' => 'datetime',
			'null' => true
		);
		
		//////////////////////////////
		
		$modx->map['modUserProfile']['fields']['banned_noticed'] = 0;
		$modx->map['modUserProfile']['fieldMeta']['banned_noticed'] = array(
			'dbtype' => 'int',
			'precision' => 1,
			'attributes' => 'unsigned',
			'phptype' => 'integer',
			'null' => true,
			'default' => 0,
		);
		
		//////////////////////////////
		
		$modx->map['modUserProfile']['fields']['banned_notice_text'] = 0;
		$modx->map['modUserProfile']['fieldMeta']['banned_notice_text'] = array(
			'dbtype' => 'text', 
			'phptype' => 'string', 
			'default' => '',
		);
          
        break;        
    
    // Строим интерфейс для админа
    case "OnUserFormPrerender":
        if (!isset($user) || $user->get('id') < 1) {
            return;
        }

        if (!$modx->getCount('modPlugin', array('name' => 'AjaxManager', 'disabled' => false))) {
            
            $data['isbanned'] = $user->Profile->isbanned ? 'true' : 'false';
            $data['banneduntil'] = $user->Profile->banneduntil;             
            $data['banned_notice_text'] = $user->Profile->banned_notice_text;             

            $modx->controller->addHtml("
                <script type='text/javascript'>
                    Ext.ComponentMgr.onAvailable('modx-user-tabs', function() {
                        this.on('beforerender', function() {
                            // Получаем колонки первой вкладки
                            var leftCol = this.items.items[0].items.items[0].items.items[0];
                            var rightCol = this.items.items[0].items.items[0].items.items[1];

             
                            // Добавляем чекбокс
                            rightCol.items.insert(13, 'modx-user-isbanned', new Ext.form.Checkbox({
                                id: 'modx-user-isbanned',
                                name: 'isbanned',
                                hideLabel: true,
                                boxLabel: 'Забанить комментирование',
                                description: 'Запрещает комментировать новости',
                                xtype: 'xcheckbox',
                                inputValue: 1,
                                listeners: {
                                    beforerender: function(that) {
                                        that.hiddenField = new Ext.Element(document.createElement('input')).set({
                                            type: 'hidden',
                                            name: that.name,
                                            value: 0,
                                        });
                                    },
                                    afterrender: function(that) {
                                        that.el.insertHtml('beforeBegin', that.hiddenField.dom.outerHTML);
                                    },
                                },
                                checked: {$data['isbanned']},
                            })); 
                             
                            rightCol.items.insert(14, 'modx-user-banneduntil', new Ext.form.DateField({
                                id: 'modx-user-banneduntil',
                                name: 'banneduntil',
                                fieldLabel: 'Забанен до',
                                xtype: 'datefield',
                                anchor: '100%',
                                value: '{$data['banneduntil']}',
                            })); 
                            
                             
                            rightCol.items.insert(15, 'modx-user-banned_notice_text', new Ext.form.TextArea({
                                id: 'modx-user-banned_notice_text',
                                name: 'banned_notice_text',
                                fieldLabel: 'Текст уведомления о бане',
                                xtype: 'textarea',
                                anchor: '100%',
                                value: '{$data['banned_notice_text']}',
                            }));                             
                            
                        });
                    });
                </script>
            ");
        }
        break;


    // Уведомляем пользователя что его забанили - отправка письма
    case "OnUserSave": 
                
            $profile = $user->getOne('Profile');
            $emailTo = $profile->get('email');
            $isbanned = $profile->get('isbanned');
            $isnoticed = $profile->get('banned_noticed');
            $notice_text = $profile->get('banned_notice_text') ?: " Вы забанены администрацией сайта";
             
            $emailFrom = $modx->getOption('emailsender');
            
            if($isbanned && !$isnoticed) {
                
                $message = $modx->getChunk('emailUserBanned', [
                    'text' => $notice_text 
                ]);
                
                $modx->getService('mail', 'mail.modPHPMailer');
                $modx->mail->set(modMail::MAIL_BODY,$message);
                $modx->mail->set(modMail::MAIL_FROM, $emailFrom);
                $modx->mail->set(modMail::MAIL_FROM_NAME, 'Администрация site.ru');
                $modx->mail->set(modMail::MAIL_SUBJECT,'Пользователь забанен');
                $modx->mail->address('to', $emailTo);
                $modx->mail->setHTML(true);
                if (!$modx->mail->send()) {
                    $modx->log(modX::LOG_LEVEL_ERROR,'Что-то пошло не так, уведомление пользователю о бане не отправлено: '.$modx->mail->mailer->ErrorInfo);
                }
                $modx->mail->reset();
                
                $profile->set('banned_noticed',1);
                $profile->save();
            }            
            
            // убрать флаг что пользователь уже был уведомлён
            if(!$isbanned && $isnoticed) {
                $profile->set('banned_noticed',0);
                $profile->save();
            }
          
        break;        
    
}

Чанк письма emailUserBanned, в него передается плейсхолдер text. Для тестирования достаточно в данном чанке вызвать плейсхолдер
[[+text]]
По итогу в профиле пользователя мы получим следующие поля
isbanned: Забанен пользователь или нет (1|0)
banneduntil: Дата, до которой он забнен
banned_noticed: Был ли уже уведомлен пользователь (данное поле не выведено в интерфейс)
banned_notice_text: Текст сообщения для пользователя

Как это все можно использовать:

Я использую для блокирования возможности комментирования пользователей.
Комментарии сделаны с помощью компонента Tickets.
Чтобы не дать пользователю комментировать можно:

1) Скрыть форму
В чанке или в шаблоне простое условие на феноме:

{if $_modx->user.isbanned}  тут уведомление что юзер забанен {else}  тут чанк формы {/if}

2) Плагином проверять может ли юзер писать комментарии
Событие OnBeforeCommentSave

<?php
switch ($modx->event->name) {
	case 'OnBeforeCommentSave': 
        
        // проверка, чтобы забаненный пользователь не пытался вставить форму в код ручками
        $profile = $modx->user->getOne('Profile'); 
        if($isbanned = $profile->get('isbanned')) {
            $modx->event->output('User is banned!');
        }
             
	break;
}

Ну и бонусом сниппет, который проверяет если юзер забанен и не истек ли срок бана. Код можно перетащить в плагин, кому надо, приложите немного усилий.
Я вызываю сниппет на каждой странице

<?php

if($modx->user->isAuthenticated()) {
    $profile = $modx->user->getOne('Profile'); 
    $isbanned = $profile->get('isbanned'); 
    $bannedtime = $profile->get('banneduntil');

    if($isbanned && strtotime($bannedtime) > time()) {
        $modx->setPlaceholder('banned', true);
    } else {
        $profile->set('isbanned', false);
        $profile->set('banneduntil', null);
        $profile->save();
    }     
    
}

return;

Затем в чанках и шаблонах будет доступен плейсхолдер banned
{$_modx->getPlaceholder('banned')}
Всё.
Евгений Webinmd
27 апреля 2021, 10:49
modx.pro
3
834
+15

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
0