DimMount / dimmount.treetables

Модуль для работы с иерархическими структурами Nested Sets и Closure Table в Битрикс
MIT License
4 stars 0 forks source link

В методе treeOnAfterAdd() срабатывает исключение, если константа USE_GLOBAL_ACTIVE = false #1

Closed krllgranin closed 6 years ago

krllgranin commented 6 years ago

Если поле GLOBAL_ACTIVE отсутствует в таблице срабатывает исключение.

Unknown field definition `GLOBAL_ACTIVE` (GLOBAL_ACTIVE) for Categories Entity. (100)  
        C:\server\www\project\public_html\bitrix\modules\main\lib\entity\querychain.php:334 
#0: Bitrix\Main\Entity\QueryChain::getChainByDefinition(object, string)
    C:\server\www\project\public_html\bitrix\modules\main\lib\entity\query.php:1848
#1: Bitrix\Main\Entity\Query->getRegisteredChain(string, boolean)
    C:\server\www\project\public_html\bitrix\modules\main\lib\entity\query.php:551
#2: Bitrix\Main\Entity\Query->addToSelectChain(string, NULL)
    C:\server\www\project\public_html\bitrix\modules\main\lib\entity\query.php:1278
#3: Bitrix\Main\Entity\Query->buildQuery()
    C:\server\www\project\public_html\bitrix\modules\main\lib\entity\query.php:486
#4: Bitrix\Main\Entity\Query->exec()
    C:\server\www\project\public_html\bitrix\modules\main\lib\entity\datamanager.php:256
#5: Bitrix\Main\Entity\DataManager::getList(array)
    C:\server\www\project\public_html\bitrix\modules\main\lib\entity\datamanager.php:171
#6: Bitrix\Main\Entity\DataManager::getRow(array)
    C:\server\www\project\public_html\local\modules\dimmount.treetables\lib\nsdatamanager.php:569
#7: DimMount\TreeTables\NSDataManager::treeOnAfterUpdate(object)

GLOBAL_ACTIVE фигурирует еще в нескольких местах без проверки константы USE_GLOBAL_ACTIVE и вызывает исключение.

DimMount commented 6 years ago

Можно поподробней? С примером кода, вызывающего ошибку?

krllgranin commented 6 years ago

Ошибка возникает при обновлении элемента в обработчике события NSDataManager::treeOnAfterUpdate() (563 строка dimmount.treetables/lib/nsdatamanager.php).

Смоделировать ошибку можно выполнив код:

use Orm\Categories\CategoriesTable;
use Bitrix\Main\Loader;

$id = 1;
$data = [
  'ACTIVE' => 'Y',
  'NAME' => 'Тест',
  'SORT' => '0',
  'HINT' => '',
  'PARENT_ID' => ''
];

$result = CategoriesTable::update($id, $data);

Orm класс:

<?php

namespace Orm\Categories;

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Type\DateTime;
use Bitrix\Main\Entity;
use Bitrix\Main\Loader;
use DimMount\TreeTables;

if (!Loader::includeModule('dimmount.treetables')) {
    return false;
}

class CategoriesTable extends TreeTables\NSDataManager
{
    const USE_GLOBAL_ACTIVE = false;

    public static function getTableName()
    {
        return 'z_ci_categories';
    }

    public static function getMap()
    {
        Loc::loadMessages(__FILE__);

        return array(
            'ID' => array(
                'data_type' => 'integer',
                'primary' => true,
                'autocomplete' => true
            ),
            'ACTIVE' => array(
                'data_type' => 'string',
                'title' => Loc::getMessage('CATEGORIES_ACTIVE'),
                'default_value' => 'Y'
            ),
            /*'GLOBAL_ACTIVE' => array(
                'data_type' => 'string',
                'title' => Loc::getMessage('CATEGORIES_GLOBAL_ACTIVE'),
                'default_value' => 'Y'
            ),*/
            'XML_ID' => array(
                'data_type' => 'string',
                'title' => Loc::getMessage('CATEGORIES_XML_ID'),
                'validation' => function () {
                    return [
                        new Entity\Validator\Unique()
                    ];
                }
            ),
            'NAME' => array(
                'data_type' => 'string',
                'title' => Loc::getMessage('CATEGORIES_NAME'),
                'required' => true
            ),
            'SORT' => array(
                'data_type' => 'integer',
                'title' => Loc::getMessage('CATEGORIES_SORT'),
                'default_value' => 500
            ),
            'HINT' => array(
                'data_type' => 'string',
                'title' => Loc::getMessage('CATEGORIES_HINT')
            ),

            /**
             * Поля для реализации Nested Set
             */
            'PARENT_ID' => array(
                'data_type' => 'string',
                'title' => Loc::getMessage('CATEGORIES_PARENT_ID')
            ),
            'DEPTH_LEVEL' => array(
                'data_type' => 'integer',
                'title' => Loc::getMessage('CATEGORIES_DEPTH_LEVEL')
            ),
            'LEFT_MARGIN' => array(
                'data_type' => 'integer',
                'title' => Loc::getMessage('CATEGORIES_LEFT_MARGIN')
            ),
            'RIGHT_MARGIN' => array(
                'data_type' => 'integer',
                'title' => Loc::getMessage('CATEGORIES_RIGHT_MARGIN')
            ),
            'PARENT_CATEGORY' => array(
                'data_type' => '\Orm\Categories\CategoriesTable',
                'reference' => array('=this.PARENT_ID' => 'ref.ID'),
            ),

            'DATE_CREATE' => array(
                'data_type' => 'datetime',
                'title' => Loc::getMessage('CATEGORIES_DATE_CREATE'),
                'default_value' => new DateTime()
            ),
            'CREATED_BY' => array(
                'data_type' => 'integer',
                'title' => Loc::getMessage('CATEGORIES_CREATED_BY'),
                'default_value' => static::getUserId()
            ),
            'MODIFIED_BY' => array(
                'data_type' => 'integer',
                'title' => Loc::getMessage('CATEGORIES_MODIFIED_BY'),
                'default_value' => static::getUserId()
            )
        );
    }

    /**
     * @inheritdoc
     */
    public static function update($primary, array $data)
    {
        $data['MODIFIED_BY'] = static::getUserId();

        return parent::update($primary, $data);
    }

    /**
     * Возвращает идентификатор пользователя.
     *
     * @return int|null
     */
    public static function getUserId()
    {
        global $USER;

        return $USER->GetID();
    }
}
DimMount commented 6 years ago

Ошибка у Вас кроется вот здесь:

public static function update($primary, array $data)
{
    $data['MODIFIED_BY'] = static::getUserId();
    return parent::update($primary, $data);
}

Вы вызываете метод update родителя, а у родителя константа USE_GLOBAL_ACTIVE может иметь другое значение. Для модификации полей перед записью в битриксе используются события. В данном случае Вам следует использовать:

public static function onBeforeUpdate(Entity\Event $event)
{
    $result = new Entity\EventResult;

    $result->modifyFields([
        'MODIFIED_BY' => static::getUserId()
    ]);

    return $result;
}

переопределять метод update не нужно

krllgranin commented 6 years ago

Действительно. Спасибо!