Битрикс. Пользователи и группы

31.10.2018

Теги: CMSORMWeb-разработкаБазаДанныхБитриксНовоеЯдроПользовательПраваДоступа

Посмотрим, как можно получать информацию по пользователям, группам пользователей, привязкам пользователей к группам, используя новое ядро и ORM. Сначала познакомимся с классами UserTable (пользователи), GroupTable (группы пользователей) и UserGroupTable (связь между пользователями и группами).

Классы UserTable, GroupTable и UserGroupTable

<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2018 Bitrix
 */
namespace Bitrix\Main;

use Bitrix\Main\DB\SqlExpression;
use Bitrix\Main\Entity;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Search\MapBuilder;

Loc::loadMessages(__FILE__);

class UserTable extends Entity\DataManager
{
    public static function getTableName()
    {
        return 'b_user';
    }

    public static function getUfId()
    {
        return 'USER';
    }

    public static function getMap()
    {
        $connection = Application::getConnection();
        $helper = $connection->getSqlHelper();

        return array(
            'ID' => array(
                'data_type' => 'integer',
                'primary' => true,
                'autocomplete' => true,
            ),
            'LOGIN' => array(
                'data_type' => 'string'
            ),
            'PASSWORD' => array(
                'data_type' => 'string'
            ),
            'EMAIL' => array(
                'data_type' => 'string'
            ),
            'ACTIVE' => array(
                'data_type' => 'boolean',
                'values' => array('N','Y')
            ),
            'DATE_REGISTER' => array(
                'data_type' => 'datetime'
            ),
            'DATE_REG_SHORT' => array(
                'data_type' => 'datetime',
                'expression' => array(
                    $helper->getDatetimeToDateFunction('%s'), 'DATE_REGISTER'
                )
            ),
            'LAST_LOGIN' => array(
                'data_type' => 'datetime'
            ),
            'LAST_LOGIN_SHORT' => array(
                'data_type' => 'datetime',
                'expression' => array(
                    $helper->getDatetimeToDateFunction('%s'), 'LAST_LOGIN'
                )
            ),
            'LAST_ACTIVITY_DATE' => array(
                'data_type' => 'datetime'
            ),
            'TIMESTAMP_X' => array(
                'data_type' => 'datetime'
            ),
            'NAME' => array(
                'data_type' => 'string'
            ),
            'SECOND_NAME' => array(
                'data_type' => 'string'
            ),
            'LAST_NAME' => array(
                'data_type' => 'string'
            ),
            'TITLE' => array(
                'data_type' => 'string'
            ),
            'EXTERNAL_AUTH_ID' => array(
                'data_type' => 'string'
            ),
            'XML_ID' => array(
                'data_type' => 'string'
            ),
            'BX_USER_ID' => array(
                'data_type' => 'string'
            ),
            'CONFIRM_CODE' => array(
                'data_type' => 'string'
            ),
            'LID' => array(
                'data_type' => 'string'
            ),
            'LANGUAGE_ID' => array(
                'data_type' => 'string'
            ),
            'TIME_ZONE_OFFSET' => array(
                'data_type' => 'integer'
            ),
            'PERSONAL_PROFESSION' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_PHONE' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_MOBILE' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_WWW' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_ICQ' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_FAX' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_PAGER' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_STREET' => array(
                'data_type' => 'text'
            ),
            'PERSONAL_MAILBOX' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_CITY' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_STATE' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_ZIP' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_COUNTRY' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_BIRTHDAY' => array(
                'data_type' => 'date'
            ),
            'PERSONAL_GENDER' => array(
                'data_type' => 'string'
            ),
            'PERSONAL_PHOTO' => array(
                'data_type' => 'integer'
            ),
            'PERSONAL_NOTES' => array(
                'data_type' => 'text'
            ),
            'WORK_COMPANY' => array(
                'data_type' => 'string'
            ),
            'WORK_DEPARTMENT' => array(
                'data_type' => 'string'
            ),
            'WORK_PHONE' => array(
                'data_type' => 'string'
            ),
            'WORK_POSITION' => array(
                'data_type' => 'string'
            ),
            'WORK_WWW' => array(
                'data_type' => 'string'
            ),
            'WORK_FAX' => array(
                'data_type' => 'string'
            ),
            'WORK_PAGER' => array(
                'data_type' => 'string'
            ),
            'WORK_STREET' => array(
                'data_type' => 'text'
            ),
            'WORK_MAILBOX' => array(
                'data_type' => 'string'
            ),
            'WORK_CITY' => array(
                'data_type' => 'string'
            ),
            'WORK_STATE' => array(
                'data_type' => 'string'
            ),
            'WORK_ZIP' => array(
                'data_type' => 'string'
            ),
            'WORK_COUNTRY' => array(
                'data_type' => 'string'
            ),
            'WORK_PROFILE' => array(
                'data_type' => 'text'
            ),
            'WORK_LOGO' => array(
                'data_type' => 'integer'
            ),
            'WORK_NOTES' => array(
                'data_type' => 'text'
            ),
            'ADMIN_NOTES' => array(
                'data_type' => 'text'
            ),
            'SHORT_NAME' => array(
                'data_type' => 'string',
                'expression' => array(
                    $helper->getConcatFunction("%s","' '", "UPPER(".$helper->getSubstrFunction("%s", 1, 1).")", "'.'"),
                    'LAST_NAME', 'NAME'
                )
            ),
            'IS_ONLINE' => array(
                'data_type' => 'boolean',
                'values' => array('N', 'Y'),
                'expression' => array(
                    'CASE WHEN %s > '.$helper->addSecondsToDateTime('(-'.self::getSecondsForLimitOnline().')').' THEN \'Y\' ELSE \'N\' END',
                    'LAST_ACTIVITY_DATE',
                )
            ),
            'IS_REAL_USER' => array(
                'data_type' => 'boolean',
                'values' => array('N', 'Y'),
                'expression' => array(
                    'CASE WHEN %s IN ("'.join('", "', static::getExternalUserTypes()).'") THEN \'N\' ELSE \'Y\' END',
                    'EXTERNAL_AUTH_ID',
                )
            ),
            'INDEX' => array(
                'data_type' => 'Bitrix\Main\UserIndex',
                'reference' => array('=this.ID' => 'ref.USER_ID'),
                'join_type' => 'INNER',
            ),
            (new Entity\ReferenceField(
                'COUNTER',
                \Bitrix\Main\UserCounterTable::class,
                Entity\Query\Join::on('this.ID', 'ref.USER_ID')->where('ref.CODE', 'tasks_effective')
            ))
        );
    }

    public static function getSecondsForLimitOnline()
    {
        $seconds = intval(ini_get("session.gc_maxlifetime"));

        if ($seconds == 0)
        {
            $seconds = 1440;
        }
        else if ($seconds < 120)
        {
            $seconds = 120;
        }

        return intval($seconds);
    }

    public static function getActiveUsersCount()
    {
        if (ModuleManager::isModuleInstalled("intranet"))
        {
            $sql = "SELECT COUNT(U.ID) ".
                "FROM b_user U ".
                "WHERE U.ACTIVE = 'Y' ".
                "   AND U.LAST_LOGIN IS NOT NULL ".
                "   AND EXISTS(".
                "       SELECT 'x' ".
                "       FROM b_utm_user UF, b_user_field F ".
                "       WHERE F.ENTITY_ID = 'USER' ".
                "           AND F.FIELD_NAME = 'UF_DEPARTMENT' ".
                "           AND UF.FIELD_ID = F.ID ".
                "           AND UF.VALUE_ID = U.ID ".
                "           AND UF.VALUE_INT IS NOT NULL ".
                "           AND UF.VALUE_INT <> 0".
                "   )";
        }
        else
        {
            $sql = "SELECT COUNT(ID) ".
                "FROM b_user ".
                "WHERE ACTIVE = 'Y' ".
                "   AND LAST_LOGIN IS NOT NULL";
        }

        $connection = Application::getConnection();
        return $connection->queryScalar($sql);
    }

    public static function getUserGroupIds($userId)
    {
        $groups = array();

        // anonymous groups
        $result = GroupTable::getList(array(
            'select' => array('ID'),
            'filter' => array(
                '=ANONYMOUS' => 'Y',
                '=ACTIVE' => 'Y'
            )
        ));

        while ($row = $result->fetch())
        {
            $groups[] = $row['ID'];
        }

        if(!in_array(2, $groups))
            $groups[] = 2;

        if($userId > 0)
        {
            // private groups
            $nowTimeExpression = new SqlExpression(
                static::getEntity()->getConnection()->getSqlHelper()->getCurrentDateTimeFunction()
            );

            $result = GroupTable::getList(array(
                'select' => array('ID'),
                'filter' => array(
                    '=UserGroup:GROUP.USER_ID' => $userId,
                    '=ACTIVE' => 'Y',
                    array(
                        'LOGIC' => 'OR',
                        '=UserGroup:GROUP.DATE_ACTIVE_FROM' => null,
                        '<=UserGroup:GROUP.DATE_ACTIVE_FROM' => $nowTimeExpression,
                    ),
                    array(
                        'LOGIC' => 'OR',
                        '=UserGroup:GROUP.DATE_ACTIVE_TO' => null,
                        '>=UserGroup:GROUP.DATE_ACTIVE_TO' => $nowTimeExpression,
                    ),
                    array(
                        'LOGIC' => 'OR',
                        '!=ANONYMOUS' => 'Y',
                        '=ANONYMOUS' => null
                    )
                )
            ));

            while ($row = $result->fetch())
            {
                $groups[] = $row['ID'];
            }
        }

        sort($groups);

        return $groups;
    }

    public static function getExternalUserTypes()
    {
        static $types = array("bot", "email", "controller", "replica", "imconnector", "sale");
        return $types;
    }

    public static function indexRecord($id)
    {
        $id = intval($id);
        if($id == 0)
        {
            return false;
        }

        $intranetInstalled = ModuleManager::isModuleInstalled('intranet');

        $select = array('ID', 'NAME', 'SECOND_NAME', 'LAST_NAME', 'WORK_POSITION', 'LOGIN', 'EMAIL');
        if ($intranetInstalled)
        {
            $select[] = 'UF_DEPARTMENT';
        }

        $record = parent::getList(array(
            'select' => $select,
            'filter' => array('=ID' => $id)
        ))->fetch();

        if(!is_array($record))
        {
            return false;
        }

        $record['UF_DEPARTMENT_NAMES'] = array();
        if ($intranetInstalled)
        {
            $departmentNames = UserUtils::getDepartmentNames($record['UF_DEPARTMENT']);
            foreach ($departmentNames as $departmentName)
            {
                $record['UF_DEPARTMENT_NAMES'][] = $departmentName['NAME'];
            }
        }

        $departmentName = isset($record['UF_DEPARTMENT_NAMES'][0])? $record['UF_DEPARTMENT_NAMES'][0]: '';
        $searchDepartmentContent = implode(' ', $record['UF_DEPARTMENT_NAMES']);

        UserIndexTable::merge(array(
            'USER_ID' => $id,
            'NAME' => (string)$record['NAME'],
            'SECOND_NAME' => (string)$record['SECOND_NAME'],
            'LAST_NAME' => (string)$record['LAST_NAME'],
            'WORK_POSITION' => (string)$record['WORK_POSITION'],
            'UF_DEPARTMENT_NAME' => (string)$departmentName,
            'SEARCH_USER_CONTENT' => self::generateSearchUserContent($record),
            'SEARCH_ADMIN_CONTENT' => self::generateSearchAdminContent($record),
            'SEARCH_DEPARTMENT_CONTENT' => MapBuilder::create()->addText($searchDepartmentContent)->build(),
        ));

        return true;
    }

    public static function deleteIndexRecord($id)
    {
        UserIndexTable::delete($id);
    }

    private static function generateSearchUserContent(array $fields)
    {
        $result = MapBuilder::create()
            ->addInteger($fields['ID'])
            ->addText($fields['NAME'])
            ->addText($fields['SECOND_NAME'])
            ->addText($fields['LAST_NAME'])
            ->addText($fields['WORK_POSITION'])
            ->addText(implode(' ', $fields['UF_DEPARTMENT_NAMES']))
            ->build();

        return $result;
    }

    private static function generateSearchAdminContent(array $fields)
    {
        $result = MapBuilder::create()
            ->addInteger($fields['ID'])
            ->addText($fields['NAME'])
            ->addText($fields['SECOND_NAME'])
            ->addText($fields['LAST_NAME'])
            ->addEmail($fields['EMAIL'])
            ->addText($fields['WORK_POSITION'])
            ->addText($fields['LOGIN'])
            ->build();

        return $result;
    }

    public static function add(array $data)
    {
        throw new NotImplementedException("Use CUser class.");
    }

    public static function update($primary, array $data)
    {
        throw new NotImplementedException("Use CUser class.");
    }

    public static function delete($primary)
    {
        throw new NotImplementedException("Use CUser class.");
    }

    public static function onAfterAdd(Entity\Event $event)
    {
        $id = $event->getParameter("id");
        static::indexRecord($id);
        return new Entity\EventResult();
    }

    public static function onAfterUpdate(Entity\Event $event)
    {
        $primary = $event->getParameter("id");
        $id = $primary["ID"];
        static::indexRecord($id);
        return new Entity\EventResult();
    }

    public static function onAfterDelete(Entity\Event $event)
    {
        $primary = $event->getParameter("id");
        $id = $primary["ID"];
        static::deleteIndexRecord($id);
        return new Entity\EventResult();
    }
}
<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2014 Bitrix
 */
namespace Bitrix\Main;

use Bitrix\Main\Entity;

class GroupTable extends Entity\DataManager
{
    public static function getTableName()
    {
        return 'b_group';
    }

    public static function getMap()
    {
        return array(
            'ID' => array(
                'data_type' => 'integer',
                'primary' => true,
                'autocomplete' => true,
            ),
            'TIMESTAMP_X' => array(
                'data_type' => 'datetime'
            ),
            'ACTIVE' => array(
                'data_type' => 'boolean',
                'values' => array('N', 'Y')
            ),
            'C_SORT' => array(
                'data_type' => 'integer'
            ),
            'ANONYMOUS' => array(
                'data_type' => 'boolean',
                'values' => array('N', 'Y')
            ),
            'NAME' => array(
                'data_type' => 'string'
            ),
            'DESCRIPTION' => array(
                'data_type' => 'string'
            ),
            'STRING_ID' => array(
                'data_type' => 'string'
            ),
        );
    }
}
<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2012 Bitrix
 */
namespace Bitrix\Main;

use Bitrix\Main\Entity;
use Bitrix\Main\Localization\Loc;

Loc::loadMessages(__FILE__);

class UserGroupTable extends Entity\DataManager
{
    public static function getTableName()
    {
        return 'b_user_group';
    }

    public static function getMap()
    {
        return array(
            'USER_ID' => array(
                'data_type' => 'integer',
                'primary' => true
            ),
            'USER' => array(
                'data_type' => 'User',
                'reference' => array('=this.USER_ID' => 'ref.ID')
            ),
            'GROUP_ID' => array(
                'data_type' => 'integer',
                'primary' => true
            ),
            'GROUP' => array(
                'data_type' => 'Group',
                'reference' => array('=this.GROUP_ID' => 'ref.ID')
            ),
            'DATE_ACTIVE_FROM' => array(
                'data_type' => 'datetime',
            ),
            'DATE_ACTIVE_TO' => array(
                'data_type' => 'datetime',
            ),
        );
    }
}

Выборка групп пользователей

Выбираем все группы, кроме основной группы администраторов:

$result = \Bitrix\Main\GroupTable::getList(
    array(
        // выбераем название, идентификатор, символьный код, сортировку
        'select' => array('NAME', 'ID', 'STRING_ID', 'C_SORT'),
        // все группы, кроме основной группы администраторов
        'filter' => array('!ID' => '1')
    )
);

while ($arGroup = $result->fetch()) {
    print_r($arGroup);
}
Array
(
    [NAME] => Все пользователи (в том числе неавторизованные)
    [ID] => 2
    [STRING_ID] => 
    [C_SORT] => 2
)
Array
(
    [NAME] => Пользователи, имеющие право голосовать за рейтинг
    [ID] => 3
    [STRING_ID] => RATING_VOTE
    [C_SORT] => 3
)
Array
(
    [NAME] => Пользователи имеющие право голосовать за авторитет
    [ID] => 4
    [STRING_ID] => RATING_VOTE_AUTHORITY
    [C_SORT] => 4
)
Array
(
    [NAME] => Почтовые пользователи
    [ID] => 5
    [STRING_ID] => MAIL_INVITED
    [C_SORT] => 201
)
Array
(
    [NAME] => Зарегистрированные пользователи
    [ID] => 6
    [STRING_ID] => REGISTERED_USERS
    [C_SORT] => 3
)
Array
(
    [NAME] => Администраторы интернет-магазина
    [ID] => 7
    [STRING_ID] => sale_administrator
    [C_SORT] => 200
)
Array
(
    [NAME] => Контент-редакторы
    [ID] => 8
    [STRING_ID] => content_editor
    [C_SORT] => 300
)
Array
(
    [NAME] => Постоянные покупатели
    [ID] => 9
    [STRING_ID] => 
    [C_SORT] => 100
)
Array
(
    [NAME] => Оптовые покупатели
    [ID] => 10
    [STRING_ID] => 
    [C_SORT] => 100
)

Принадлежность пользователя к группам

Выбираем все активные группы текущего пользователя:

$result = \Bitrix\Main\UserGroupTable::getList(
    array(
        // выбираем все активные группы текущего пользователя
        'filter' => array('USER_ID' => $GLOBALS['USER']->GetID(), 'GROUP.ACTIVE' => 'Y'),
        // выбираем идентификатор группы символьный код группы и наименование группы
        'select' => array('GROUP_ID', 'GROUP_CODE' => 'GROUP.STRING_ID', 'GROUP_NAME' => 'GROUP.NAME'),
        // сортируем в соответствии с сортировкой групп
        'order' => array('GROUP.C_SORT' => 'ASC'),
    )
);

while ($arGroup = $result->fetch()) {
    print_r($arGroup);
}
Array
(
    [GROUP_ID] => 3
    [GROUP_CODE] => RATING_VOTE
    [GROUP_NAME] => Пользователи, имеющие право голосовать за рейтинг
)
Array
(
    [GROUP_ID] => 6
    [GROUP_CODE] => REGISTERED_USERS
    [GROUP_NAME] => Зарегистрированные пользователи
)
Array
(
    [GROUP_ID] => 4
    [GROUP_CODE] => RATING_VOTE_AUTHORITY
    [GROUP_NAME] => Пользователи имеющие право голосовать за авторитет
)

Выбираем всех активных пользователей группы:

$result = \Bitrix\Main\UserGroupTable::getList(
    array(
        // выбираем всех активных пользователей группы ID=7 (администраторы интернет-магазина)
        'filter' => array('GROUP_ID' => 7, 'USER.ACTIVE' => 'Y'),
        // выбираем идентификатор пользователя, имя, фамилию и e-mail
        'select' => array(
            'USER_ID',
            'NAME'       => 'USER.NAME',
            'LAST_NAME'  => 'USER.LAST_NAME',
            'USER_EMAIL' => 'USER.EMAIL'),
        // сортируем по идентификатору пользователя
        'order' => array('USER.ID' => 'ASC'),
    )
);

while ($arUser = $result->fetch()) {
    print_r($arUser);
}
Array
(
    [USER_ID] => 5
    [NAME] => Сергей
    [LAST_NAME] => Иванов
    [USER_EMAIL] => ivanov.s@mail.ru
)

Также можно выбирать активные группы пользователя и с помощью \Bitrix\Main\GroupTable. Код ниже учитывает временные рамки нахождения пользователя в группе:

$nowTimeExpression = new \Bitrix\Main\DB\SqlExpression(
    \Bitrix\Main\UserTable::getEntity()->getConnection()->getSqlHelper()->getCurrentDateTimeFunction()
);

$result = \Bitrix\Main\GroupTable::getList(
    array(
        'select' => array('ID', 'NAME', 'STRING_ID'),
        'filter' => array(
            '=UserGroup:GROUP.USER_ID' => $GLOBALS['USER']->GetID(),
            '=ACTIVE' => 'Y',
            array(
                'LOGIC' => 'OR',
                '=UserGroup:GROUP.DATE_ACTIVE_FROM' => null,
                '<=UserGroup:GROUP.DATE_ACTIVE_FROM' => $nowTimeExpression,
            ),
            array(
                'LOGIC' => 'OR',
                '=UserGroup:GROUP.DATE_ACTIVE_TO' => null,
                '>=UserGroup:GROUP.DATE_ACTIVE_TO' => $nowTimeExpression,
            ),
            array(
                'LOGIC' => 'OR',
                '!=ANONYMOUS' => 'Y',
                '=ANONYMOUS' => null
            )
        )
    )
);

while($arGroup = $result->fetch()) {
    print_r($arGroup);
}
Array
(
    [ID] => 3
    [NAME] => Пользователи, имеющие право голосовать за рейтинг
    [STRING_ID] => RATING_VOTE
)
Array
(
    [ID] => 4
    [NAME] => Пользователи имеющие право голосовать за авторитет
    [STRING_ID] => RATING_VOTE_AUTHORITY
)
Array
(
    [ID] => 6
    [NAME] => Зарегистрированные пользователи
    [STRING_ID] => REGISTERED_USERS
)

Выборка пользователей и информации о них

Выборка трех последних авторизовавшихся пользователей:

$result = \Bitrix\Main\UserTable::getList(
    array(
        // выбираем идентификатор и генерируемое поле SHORT_NAME
        'select' => array('ID', 'SHORT_NAME'),
        // все группы, кроме основной группы администраторов
        'filter' => array('!ID' => '1'),
        // сортировка по времени последней авторизации
        'order'  => array('LAST_LOGIN' => 'DESC'),
        // только три последних пользователя
        'limit'  => 3
    )
);

while ($arUser = $result->fetch()) {
    print_r($arUser);
}

Выборка количества активных пользователей на сайте:

echo \Bitrix\Main\UserTable::getActiveUsersCount();

Получение массива идентификаторов активных групп пользователя:

print_r(\Bitrix\Main\UserTable::getUserGroupIds($GLOBALS['USER']->GetID()));

Добавить пользователя в группу

Добавить пользователя с идентифкатором 2 в группу с идентификатором 7:

\Bitrix\Main\UserGroupTable::add(
    array(
        'USER_ID' => 2,
        'GROUP_ID' => 7,
    )
);

Удалить пользователя из группы

Удалить пользователя с идентифкатором 2 из группы с идентификатором 7:

\Bitrix\Main\UserGroupTable::delete(
    array(
        'USER_ID' => 2,
        'GROUP_ID' => 7,
    )
);

Поиск: CMS • DataManager • GroupTable • ORM • UserGroupTable • UserTable • Web-разработка • add • delete • getActiveUsersCount • getList • getUserGroupIds • База данных • Битрикс • Группа • Новое ядро • Пользователь • Права доступа • Таблица

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.