Дополнительные поля WebLoginPE и modUsers

Cниппет WebLoginPE, как известно его пользователям, позволяет использовать при работе с пользователями дополнительные поля. Для работы с этими полями сниппет создает отдельную таблицу (по умолчанию — web_user_attributes_extended), где и хранит значения полей; при этом каждому полю соответствует отдельный столбец в указанной таблице.

Вполне может так быть, что кто-то, как zloyxrom , решит отказаться от WebLoginPE и переделать работу с пользователями, используя класс modUsers из MODxAPI. И сразу же столкнется с проблемой — modUsers знать ничего не знает о дополнительных полях WebLoginPE.

Но решается проблема очень просто, по сути копипастом. Создадим в assets/lib/MODxAPI файл modUsersExt.php c классом modUsersExt:
<?php
require_once('modUsers.php');

class modUsersExt extends modUsers
{

    protected $default_field = array(
        'user' => array(
            'username' => null,
            'password' => null,
            'cachepwd' => null
        ),
        'attribute' => array(
            'fullname' => null,
            'role' => null,
            'email' => null,
            'phone' => null,
            'mobilephone' => null,
            'blocked' => null,
            'blockeduntil' => null,
            'blockedafter' => null,
            'logincount' => null,
            'lastlogin' => null,
            'thislogin' => null,
            'failedlogincount' => null,
            'sessionid' => null,
            'dob' => null,
            'gender' => null,
            'country' => null,
            'city' => null,
            'state' => null,
            'zip' => null,
            'fax' => null,
            'photo' => null,
            'comment' => null
        ),
        'extended' => array(

        ),
        'hidden' => array(
            'internalKey'
        )
    );

    public $extendedTable = 'web_user_attributes_extended';

    public function issetField($key)
    {
        return (array_key_exists($key, $this->default_field['user']) ||
                array_key_exists($key, $this->default_field['attribute']) ||
                array_key_exists($key, $this->default_field['extended']) ||
                in_array($key, $this->default_field['hidden'])
        );
    }

    /**
     * @param $id
     * @return $this
     */
    public function edit($id)
    {
        $id = is_scalar($id) ? trim($id) : '';
        if ($this->getID() != $id) {
            $this->close();
            $this->newDoc = false;

            if (!$find = $this->findUser($id)) {
                $this->id = null;
            }else {
                $result = $this->query("
                    SELECT * from {$this->makeTable('web_user_attributes')} as attribute
                    LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
                    LEFT JOIN {$this->makeTable($this->extendedTable)} as extended ON user.id=extended.internalKey
                    WHERE BINARY {$find}='{$this->escape($id)}'
                ");
                $this->field = $this->modx->db->getRow($result);

                $this->id = empty($this->field['internalKey']) ? null : $this->get('internalKey');
                unset($this->field['id']);
                unset($this->field['internalKey']);
            }
        }
        return $this;
    }

    /**
     * @param null $fire_events
     * @param bool $clearCache
     * @return bool|int|null|void
     */
    public function save($fire_events = null, $clearCache = false)
    {
        if ($this->get('email') == '' || $this->get('username') == '' || $this->get('password') == '') {
            $this->log['EmptyPKField'] = 'Email, username or password is empty <pre>' . print_r($this->toArray(), true) . '</pre>';
            return false;
        }

        if (!$this->checkUnique('web_users', 'username')) {
            $this->log['UniqueUsername'] = 'username not unique <pre>' . print_r($this->get('username'), true) . '</pre>';
            return false;
        }

        if (!$this->checkUnique('web_user_attributes', 'email', 'internalKey')) {
            $this->log['UniqueEmail'] = 'Email not unique <pre>' . print_r($this->get('email'), true) . '</pre>';
            return false;
        }

        /*$this->invokeEvent('OnBeforeDocFormSave',array (
            "mode" => $this->newDoc ? "new" : "upd",
            "id" => $this->id ? $this->id : ''
        ),$fire_events);*/

        $fld = $this->toArray();
        foreach ($this->default_field['user'] as $key => $value) {
            $tmp = $this->get($key);
            if ($this->newDoc && ( !is_int($tmp) && $tmp=='')) {
                if($tmp == $value){
                    //take default value from global config
                }
                $this->field[$key] = $value;
            }
            $this->Uset($key, 'user');
            unset($fld[$key]);
        }
        if (!empty($this->set['user'])) {
            if ($this->newDoc) {
                $SQL = "INSERT into {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']);
            } else {
                $SQL = "UPDATE {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']) . " WHERE id = " . $this->id;
            }
            $this->query($SQL);
        }

        if ($this->newDoc) {
            $this->id = $this->modx->db->getInsertId();
        }

        foreach ($this->default_field['attribute'] as $key => $value) {
            $tmp = $this->get($key);
            if ($this->newDoc && ( !is_int($tmp) && $tmp=='')) {
                if($tmp == $value){
                    //take default value from global config
                }
                $this->field[$key] = $value;
            }
            $this->Uset($key, 'attribute');
            unset($fld[$key]);
        }
        if (!empty($this->set['attribute'])) {
            if ($this->newDoc) {
                $this->set('internalKey', $this->id)->Uset('internalKey', 'attribute');
                $SQL = "INSERT into {$this->makeTable('web_user_attributes')} SET " . implode(', ', $this->set['attribute']);
            } else {
                $SQL = "UPDATE {$this->makeTable('web_user_attributes')} SET " . implode(', ', $this->set['attribute']) . " WHERE  internalKey = " . $this->getID();
            }
            $this->query($SQL);
        }

        foreach ($this->default_field['extended'] as $key => $value) {
            $tmp = $this->get($key);
            if ($this->newDoc && ( !is_int($tmp) && $tmp=='')) {
                if($tmp == $value){
                    //take default value from global config
                }
                $this->field[$key] = $value;
            }
            $this->Uset($key, 'extended');
            unset($fld[$key]);
        }
        if (!empty($this->set['extended'])) {
            if ($this->newDoc) {
                $this->set('internalKey', $this->id)->Uset('internalKey', 'extended');
                $SQL = "INSERT into {$this->makeTable($this->extendedTable)} SET " . implode(', ', $this->set['extended']);
            } else {
                $SQL = "UPDATE {$this->makeTable($this->extendedTable)} SET " . implode(', ', $this->set['extended']) . " WHERE  internalKey = " . $this->getID();
            }
            $this->query($SQL);
        }

        foreach ($fld as $key => $value) {
            if ($value == '') continue;
            $result = $this->query("SELECT `setting_value` FROM {$this->makeTable('web_user_settings')} WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}'");
            if ($this->modx->db->getRecordCount($result) > 0) {
                $this->query("UPDATE {$this->makeTable('web_user_settings')} SET `setting_value` = '{$value}' WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}';");
            } else {
                $this->query("INSERT into {$this->makeTable('web_user_settings')} SET `webuser` = {$this->id},`setting_name` = '{$key}',`setting_value` = '{$value}';");
            }
        }
        if (!$this->newDoc && $this->givenPassword) {
            $this->invokeEvent('OnWebChangePassword',array(
                'userObj'       => $this,
                'userid'        => $this->id,
			    'user'	        => $this->toArray(),
			    'userpassword'	=> $this->givenPassword,
                'internalKey'   => $this->id,
                'username'      => $this->get('username')
            ),$fire_events);
        }
        $this->invokeEvent('OnWebSaveUser',array (
            'userObj'   => $this,
            'mode'      => $this->newDoc ? "new" : "upd",
            'id'        => $this->id,
            'user'      => $this->toArray()
        ),$fire_events);

        if ($clearCache) {
            $this->clearCache($fire_events);
        }
        return $this->id;
    }

    public function delete($ids, $fire_events = null)
    {
        if ($this->edit($ids)) {
            $flag = $this->query("
          DELETE user,attribute,extended FROM {$this->makeTable('web_user_attributes')} as attribute
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
            LEFT JOIN {$this->makeTable($this->extendedTable)} as extended ON user.id=extended.internalKey
            WHERE attribute.internalKey='{$this->escape($this->getID())}'");
            $this->query("DELETE FROM {$this->makeTable('web_user_settings')} WHERE webuser='{$this->getID()}'");
            $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE webuser='{$this->getID()}'");
            $this->invokeEvent('OnWebDeleteUser', array(
                'userObj'       => $this,
                'userid'        => $this->getID(),
                'internalKey'   => $this->getID(),
                'username'      => $this->get('username'),
                'timestamp'     => time()
            ), $fire_events);
        } else {
            $flag = false;
        }
        $this->close();
        return $flag;
    }
}


Как можно понять из кода, в этом классе меняются основные методы класса modUsers с учетом существования дополнительной таблицы атрибутов. Чтобы этим классом пользоваться достаточно заполнить массив extended в свойстве default_field по аналогии с уже имеющимися там массивами. Ну и предварительно создать таблицу, например:

CREATE TABLE `modx_web_user_attributes_extended` (
`id` int(10) NOT NULL auto_increment,
`internalKey` int(10) NOT NULL,
`firstField` TEXT NOT NULL default '',
`secondField` int(10) NOT NULL default 0,
`thirdField` datetime NOT NULL,
PRIMARY KEY  (`id`),
KEY `userid` (`internalKey`)
) ENGINE=MyISAM


При более внимательном рассмотрении класса modUsersExt можно заметить новое свойство extendedTable c именем таблицы дополнительных атрибутов. Это позволяет хранить дополнительные поля в разных таблицах, как WebLoginPE, а также еще немного упростить работу с дополнительными полями — например для вышеприведенной таблицы достаточно просто расширить класс modUsersExt:

<?php
require_once('modUsersExt.php');

class customUser extends modUsersExt
{
    public $extendedTable = 'web_user_attributes_extended';

    public function __construct(DocumentParser $modx, $debug = false) {
        parent::__construct($modx, $debug);
        $this->default_field['extended'] = array(
            'firstField'=>'',
            'secondField'=>0,
            'thirdField'=>0,
        );
    }
}


Если пользоваться FormLister, то для последнего примера нужно добавить при вызове параметры:

&model=`\customUser`
&modelPath=`assets/lib/MODxAPI/customUser.php`


После этого контроллеры, работающие с пользователями, будут работать через расширенную модель и успешно сохранять дополнительные поля.

31 комментарий

avatar
Круто, спасибо!
avatar
Не пробовал в работе DLUsers для создания ЛК и авторизации?
avatar
Пробовал, не понравилось (: В итоге появился FormLister.
avatar
Отличное решение! Как раз недавно пришлось проделать похожую работу, только так и не дошли руки причесать код чтобы отправить вам пулл-реквест)
avatar
как можно сделать, чтобы в админке дополнительные поля можно было смотреть и редактировать?
  • dim2
  • 0
avatar
Что-то где-то туплю.
Сделал все как тут написано. Создал в таблице web_user_attributes_extended столбцы addr и inn.

Добавил запись в customuser:

class customUser extends modUsersExt
{
    public $extendedTable = 'web_user_attributes_extended';

    public function __construct(DocumentParser $modx, $debug = false) {
        parent::__construct($modx, $debug);
        $this->default_field['extended'] = array(
            'inn'=>'0',
            'addr'=>'not set'
        );
    }
}


В вызове, само собой, делаю

[!FormLister?
.....
&controller=`Register`
&model=`\customUser`
&modelPath=`assets/lib/MODxAPI/customUser.php`
.......
!]

При регистрации пользователя теперь в таблице web_user_attributes_extended появляются значения, заданны в default.

Но как мне их передать из самой формы регистрации?
Пробовал у элементов указывать name в виде и «inn», и «extended[inn]», и «extended.inn» — данные из формы все равно не сохраняются в таблице.
avatar
&allowedFields=`inn,addr,username,email,phone...`
avatar
Спасибо, Добрый человек!

Почему-то меня смутила вот эта фраза в документации, поэтому я этот параметр вообще не указывал:
allowedFields

Разрешенные для обработки поля. Поля, не указанные в списке, игнорируются.
Если не задано, то разрешены все поля.
Проверил, действительно заработало.
Но теперь всплыла еще одна сложность.

У меня поле addr содержит данные в виде JSON (они «готовятся» сторонним яваскриптом на этапе заполнения формы), и я эти данные хочу в неизменном виде сохранить в базу.

Но они сохраняются не в первозданном виде, видимо, FormLister их как-то режет. Я посмотрел в событиях, что выводит FormLister, и что сохранилось в базу данных — и там и там значение получилось такое:
[addr] => {«0»:{«header»:«адрес 1»,«address»:«вав ава ва»},«1»:{«header»:«адрес 2»,«address»:«ва ава ава»sanitize_seed_cwcbva32ffso8ocks044k8ww8}sanitize_seed_cwcbva32ffso8ocks044k8ww8}sanitize_seed_cwcbva32ffso8ocks044k8ww8
, то есть видно, что перед закрывающимися скобками добавилось некое «sanitize_seed_cwcbva32ffso8ocks044k8ww8».
Как этот «sanitize» можно убрать?
Комментарий отредактирован 2017-05-05 15:51:32 пользователем Dreamer
avatar
Режет Evo, так что с этой сложностью нужно обращаться сюда: github.com/modxcms/evolution/issues
avatar
Я сделал тестик — простую форму на чистом html, и единственый вызов сниппета, в котором вывожу $_POST — и там ничего не вырезано, данные в POST нормальные… Или FormLister использует не POST напрямую, а какие-то другие подготовленные modx-ом данные?
avatar
А почему бы для тестика не сделать сложную форму, где js подставляет в поля json, тогда и будет понятно все. Ну или без тестика: github.com/modxcms/evolution/blob/develop/manager/includes/protect.inc.php#L59-L64
avatar
Сделал. Данные формы выводятся напрямую в шаблоне, js тоже подключается в шаблоне — данные формы в одном из полей преобразуются в json, все это самбитится и сниппетом выводится получившееся значение $_POST. Все выводится хорошо, скобочки не портятся.
Комментарий отредактирован 2017-05-07 11:25:24 пользователем Dreamer
avatar
Все выводится хорошо, скобочки не портятся.

Что выводится хорошо, это да: github.com/modxcms/evolution/blob/develop/manager/includes/document.parser.class.inc.php#L772 А вот если сделать в сниппете die(var_dump($_POST)), то будет уже не очень хорошо. Но в общем-то это уже не важно, потому что я учел этот идиотизм и в версии 1.6.0 все будет нормально. Путаницу с allowedFields я тоже устранил (:
avatar
То есть я правильно понимаю, что сегодняшний танец с бубном мне нужен, чтобы эти скобочки не мешали «прямо сейчас», а в следующей версии FormLister этот бубен можно будет удалить и забыть про него?
avatar
Да, в следующей версии FormLister будет сам вырезать при загрузке данных из $_POST/$_GET/$_REQUEST — можно из всего массива сразу, можно из отдельных полей.
avatar
Я бы отправлял данные как есть, а json делал уже на сервере.
avatar
Или можно в prepareProcess сделать:

$sanitize_seed = 'sanitize_seed_' . base_convert(md5(MODX_MANAGER_PATH.'includes/protect.inc.php'),16,36);
$field = str_replace($sanitize_seed,'',$FormLister->get('field'));
$FormLister->setField('field',$field);
Комментарий отредактирован 2017-05-06 00:56:25 пользователем Pathologic
avatar
Я пытаюсь это реализовать. Сделал сначала с этим кодом, мне парсер выругался на метод get(). Я заменил его на метод GetField, так как в классе FormLister.abstract.php нашел в описании класса только его — сниппет стал вызываться без ошибок, но данные в таблицу базы данных все равно в таком виде помещаются:
{«0»:{«header»:«99999»,«address»:«11111»},«1»:{«header»:«555555»,«address»:«666666»sanitize_seed_cwcbva32ffso8ocks044k8ww8}sanitize_seed_cwcbva32ffso8ocks044k8ww8}sanitize_seed_cwcbva32ffso8ocks044k8ww8

У меня сейчас вот так выглядит вызов FormLister:

[!FormLister?
.......
&controller=`Register`
&model=`\customUser`
&modelPath=`assets/lib/MODxAPI/customUser.php`
&prepareProcess=`PrepereRegUser` 
......!]


Сниппет PrepereRegUser соответственно выглядит вот так:

$sanitize_seed = 'sanitize_seed_' . base_convert(md5(MODX_MANAGER_PATH.'includes/protect.inc.php'),16,36);
$field = str_replace($sanitize_seed,'',$FormLister->getField('addr'));
$FormLister->setField('addr',$field);
avatar
Я проверил на простой форме, вместо addr поле message. Результат такой:

array (size=5)
  'formid' => string 'basic' (length=5)
  'name' => string '' (length=0)
  'email' => string '' (length=0)
  'phone' => string '' (length=0)
  'message' => string '{"0":{"header":"99999","address":"11111"},"1":{"header":"555555","address":"666666"}}' (length=85)
avatar
Без prepare:

array (size=5)
  'formid' => string 'basic' (length=5)
  'name' => string '' (length=0)
  'email' => string '' (length=0)
  'phone' => string '' (length=0)
  'message' => string '{"0":{"header":"99999","address":"11111"},"1":{"header":"555555","address":"666666"sanitize_seed_a35oxap7ku0w0wcok84sog08w}sanitize_seed_a35oxap7ku0w0wcok84sog08w}sanitize_seed_a35oxap7ku0w0wcok84sog08w' (length=202)
avatar
Я разобрался. У меня значение переменной $sanitize_seed пр данном методе получалось другое, не такое, как рассчитывается в файле protect.inc.php.

Я сниппет переделал вот так, теперь все работает:


global $sanitize_seed;
str_replace($sanitize_seed,'',$FormLister->getField('addr'));
$FormLister->setField('addr',$field);


Спасибо!
avatar
У меня значение переменной $sanitize_seed пр данном методе получалось другое, не такое, как рассчитывается в файле protect.inc.php.

А сервер какой? Windows?
avatar
Да, тестирую с помощью пакета OpenServer под Windows.
avatar
Вот по идее должно быть правильно:

$sanitize_seed = 'sanitize_seed_' . base_convert(md5(realpath(MODX_MANAGER_PATH.'includes/protect.inc.php')),16,36);
avatar
Разумеется, после обновление modUsers теперь эта штука работать перестала (юзер перестал прописываться в группу), именно из-за копипаста :)

Аккуратно внес новый копипаст, перекопировав изменившиеся части переопределенных функций из соответствующих методов базового класса, но при каждом обновлении это менять — не айс.

Может, как-то можно эту задачу решить просто дерганием нужных функций базового класса, без копипастов? :)

Если бы можно было в возможность самого modUsers в эти функции в нужный фрагмент заложить вызов того самого пользовательского запроса, из-за которого собственно и переписаны эти методы класса — было бы супер!
avatar
Если кто тоже это использует — то у меня работающий ко в файле moduserext теперь такой: (выкинул там по-возможности часть кода, воспользовавшись методами и переменными базового класса, но метод save пока не осилил :) )
<?php
require_once('modUsers.php');

class modUsersExt extends modUsers
{
    public $extendedTable = 'web_user_attributes_extended';

    public function issetField($key)
    {
	if(array_key_exists($key, $this->default_field['extended']))
		return true;
        return parent::issetField($key);
    }


    /**
     * @param $id
     * @return $this
     */
    public function edit($id)
    {
        $id = is_scalar($id) ? trim($id) : '';
        if ($this->getID() != $id) {
            $this->close();
            $this->newDoc = false;

            if (!$find = $this->findUser($id)) {
                $this->id = null;
            } else {
                $result = $this->query("
                    SELECT * from {$this->makeTable('web_user_attributes')} as attribute
                    LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
                    LEFT JOIN {$this->makeTable($this->extendedTable)} as extended ON user.id=extended.internalKey
                    WHERE BINARY {$find}='{$this->escape($id)}'
                ");
                $this->field = $this->modx->db->getRow($result);

                $this->id = empty($this->field['internalKey']) ? null : $this->get('internalKey');
                $this->store($this->toArray());
                unset($this->field['id']);
                unset($this->field['internalKey']);
            }
        }

        return $this;
    }


    /**
     * @param bool $fire_events
     * @param bool $clearCache
     * @return bool|int|null|void
     */
    public function save($fire_events = false, $clearCache = false)
    {
        if ($this->get('email') == '' || $this->get('username') == '' || $this->get('password') == '') {
            $this->log['EmptyPKField'] = 'Email, username or password is empty <pre>' . print_r($this->toArray(),
                    true) . '</pre>';

            return false;
        }

        if (!$this->checkUnique('web_users', 'username')) {
            $this->log['UniqueUsername'] = 'username not unique <pre>' . print_r($this->get('username'),
                    true) . '</pre>';

            return false;
        }

        if (!$this->checkUnique('web_user_attributes', 'email', 'internalKey')) {
            $this->log['UniqueEmail'] = 'Email not unique <pre>' . print_r($this->get('email'), true) . '</pre>';

            return false;
        }
        $this->set('sessionid', '');
        $fld = $this->toArray();
        foreach ($this->default_field['user'] as $key => $value) {
            $tmp = $this->get($key);
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
                $this->field[$key] = $value;
            }
            $this->Uset($key, 'user');
            unset($fld[$key]);
        }
        if (!empty($this->set['user'])) {
            if ($this->newDoc) {
                $SQL = "INSERT into {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']);
            } else {
                $SQL = "UPDATE {$this->makeTable('web_users')} SET " . implode(', ',
                        $this->set['user']) . " WHERE id = " . $this->id;
            }
            $this->query($SQL);
        }

        if ($this->newDoc) {
            $this->id = $this->modx->db->getInsertId();
        }

        foreach ($this->default_field['attribute'] as $key => $value) {
            $tmp = $this->get($key);
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
                $this->field[$key] = $value;
            }
            $this->Uset($key, 'attribute');
            unset($fld[$key]);
        }
        if (!empty($this->set['attribute'])) {
            if ($this->newDoc) {
                $this->set('internalKey', $this->id)->Uset('internalKey', 'attribute');
                $SQL = "INSERT into {$this->makeTable('web_user_attributes')} SET " . implode(', ',
                        $this->set['attribute']);
            } else {
                $SQL = "UPDATE {$this->makeTable('web_user_attributes')} SET " . implode(', ',
                        $this->set['attribute']) . " WHERE  internalKey = " . $this->getID();
            }
            $this->query($SQL);
        }

//dream added====
        foreach ($this->default_field['extended'] as $key => $value) {
            $tmp = $this->get($key);
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
                $this->field[$key] = $value;
            }
            $this->Uset($key, 'extended');
            unset($fld[$key]);
        }
        if (!empty($this->set['extended'])) {
            if ($this->newDoc) {
                $this->set('internalKey', $this->id)->Uset('internalKey', 'extended');
                $SQL = "INSERT into {$this->makeTable($this->extendedTable)} SET " . implode(', ',
                        $this->set['extended']);
            } else {
                $SQL = "UPDATE {$this->makeTable($this->extendedTable)} SET " . implode(', ',
                        $this->set['extended']) . " WHERE  internalKey = " . $this->getID();
            }
            $this->query($SQL);
/*
            if ($this->newDoc) {
                $this->set('internalKey', $this->id)->Uset('internalKey', 'extended');
                $SQL = "INSERT into {$this->makeTable($this->extendedTable)} SET " . implode(', ', $this->set['extended']);
            } else {
                $SQL = "UPDATE {$this->makeTable($this->extendedTable)} SET " . implode(', ', $this->set['extended']) . " WHERE  internalKey = " . $this->getID();
            }
            $this->query($SQL);
*/
        }

//--------




        unset($fld['id']);
        foreach ($fld as $key => $value) {
            if ($value == '' || !$this->isChanged($key)) {
                continue;
            }
            $result = $this->query("SELECT `setting_value` FROM {$this->makeTable('web_user_settings')} WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}'");
            if ($this->modx->db->getRecordCount($result) > 0) {
                $this->query("UPDATE {$this->makeTable('web_user_settings')} SET `setting_value` = '{$value}' WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}';");
            } else {
                $this->query("INSERT into {$this->makeTable('web_user_settings')} SET `webuser` = {$this->id},`setting_name` = '{$key}',`setting_value` = '{$value}';");
            }
        }
        if (!$this->newDoc && $this->givenPassword) {
            $this->invokeEvent('OnWebChangePassword', array(
                'userObj'      => $this,
                'userid'       => $this->id,
                'user'         => $this->toArray(),
                'userpassword' => $this->givenPassword,
                'internalKey'  => $this->id,
                'username'     => $this->get('username')
            ), $fire_events);
        }
        
        if ($this->groupIds) $this->setUserGroups($this->id, $this->groupIds);
        
        $this->invokeEvent('OnWebSaveUser', array(
            'userObj' => $this,
            'mode'    => $this->newDoc ? "new" : "upd",
            'id'      => $this->id,
            'user'    => $this->toArray()
        ), $fire_events);

        if ($clearCache) {
            $this->clearCache($fire_events);
        }

        return $this->id;
    }

    /**
     * @param $ids
     * @param bool $fire_events
     * @return bool|null|void
     */
    public function delete($ids, $fire_events = false)
    {
        if ($this->edit($ids)) {
            $flag = $this->query("
          DELETE user,attribute FROM {$this->makeTable('web_user_attributes')} as attribute
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
            LEFT JOIN {$this->makeTable($this->extendedTable)} as extended ON user.id=extended.internalKey
            WHERE attribute.internalKey='{$this->escape($this->getID())}'");
            $this->query("DELETE FROM {$this->makeTable('web_user_settings')} WHERE webuser='{$this->getID()}'");
            $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE webuser='{$this->getID()}'");
            $this->invokeEvent('OnWebDeleteUser', array(
                'userObj'     => $this,
                'userid'      => $this->getID(),
                'internalKey' => $this->getID(),
                'username'    => $this->get('username'),
                'timestamp'   => time()
            ), $fire_events);
        } else {
            $flag = false;
        }
        $this->close();

        return $flag;
    }
}
avatar
Если бы можно было в возможность самого modUsers в эти функции в нужный фрагмент заложить вызов того самого пользовательского запроса, из-за которого собственно и переписаны эти методы класса — было бы супер!

Да, такая проблема есть и не только с modUsers. Создавайте issue, будет время попробую переписать (по сути тут нужно выделить запросы в отдельные методы и их уже переопределять, а не целиком save, edit, delete).
avatar
Ок, issue так issue :)
avatar
Ой, что-то я круто тормознул. Был уверен, что добавил этот вопрос на github, а сейчас обратил внимание, что попросту забыл. Исправляюсь:
github.com/evolution-cms/evolution/issues/185
avatar
Лучше создавать там, где разрабатывается, потому что возникает часто путаница: github.com/AgelxNash/DocLister
avatar
Ага, продублировал.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.