Показать сообщение отдельно
Старый 13.08.2012, 11:33   #31  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Небольшое дополнение к методу createKeywordMap()
Во-первых, спасибо за замечательный проект! Очень полезная модификация, делающая возможным настраивать оповещения для других. Также очень удачной оказалась доработка шаблонов оповещений с тем, чтобы в них можно было подставлять значения полей и методов табличного буфера, однако, эта подстановка получилась несколько... мощнее, чем то, что можно доверить пользователям Вот как был доработан внутренний цикл поиска и "обсчета" макросов из шаблона - блок if (!keywords.exists(keyword)) метода createKeywordMap(), который вызывается из \Data Dictionary\Tables\EventInbox\Methods\initFromBuffer:
X++:
// по умолчанию вернем в виде значения сам token - так проще "отлаживать" шаблоны
keyword_value = #startReplaceToken + keyword + #endReplaceToken;
if (match(@"<[a-z_][a-z0-9_]*\(\)>", keyword))
{
    switch (keyword)
    {
        case @"modifiedBy_Name()" :
            keyword_value = getUserFIO(_buffer.modifiedBy);
            break;
        case @"createdBy_Name()" :
            keyword_value = getUserFIO(_buffer.createdBy);
            break;
        default :
            tblMethodName = strreplace(keyword, '()', '');
            if (this.mayEvaluateTableMethodReturnValue(bufferTable.id(), tblMethodName))
            {
                keyword_value = strfmt("%1", bufferTable.callObject(tblMethodName, _buffer));
            }
            break;
    }
}
else
{
    bufferFldId = fieldname2Id(_buffer.tableid, keyword);
    if (bufferFldId)
    {
        keyword_value = strfmt("%1", _buffer.(bufferFldId));
    }
}
Изменения сделаны такие:
  • немного строже проверяется что в шаблоне дергается метод таблицы;
  • добавлены два "встроенных" метода, возвращающих имя автора создания/последнего изменения записи (getUserFIO() - "макрос", который возвращает имя по коду пользователя);
  • добавлена проверка на то, можно ли собственно вызывать в данном контексте тот экземплярный табличный метод, который указан в шаблоне.
Последняя проверка сделана из тех соображений, чтобы не дать пользователям с помощью шаблона уведомлений вызывать методы, которые не являются display-ными и вообще могут что-то поменять в базе (например, метод delete() ). Проверка выглядит вот так:
X++:
// можно ли дернуть табличный метод для получения его возвращаемого значения и подстановки этого значения вместо имени метода в письмо?
private boolean mayEvaluateTableMethodReturnValue(tableId _tableId, SysMethodName _instanceMethodName)
{
    Types       returnType;
    DictMethod  dictMethod = new DictMethod(UtilElementType::TableInstanceMethod, _tableId, _instanceMethodName);
    boolean     ret = false;
    ;
    if (    dictMethod
        &&  dictMethod.parameterCnt()   == 0
        &&  dictMethod.displayType()    == DisplayFunctionType::Get
       )
    {
        if (dictMethod.returnType() == Types::UserType)
        {
            returnType = extendedTypeId2Type(dictMethod.returnId());
        }
        else
        {
            returnType = dictMethod.returnType();
        }
        // является ли тип возвращаемого значения значимым (т.е. не ссылочным)?
        ret =   returnType == Types::String
            ||  returnType == Types::RString
            ||  returnType == Types::VarString
            ||  returnType == Types::Integer
            ||  returnType == Types::Int64
            ||  returnType == Types::Real
            ||  returnType == Types::Date
            ||  returnType == Types::UtcDateTime
            ||  returnType == Types::Enum
            ||  returnType == Types::Guid
            ||  returnType == Types::Time
                ;
    }
    return ret;
}
За это сообщение автора поблагодарили: Logger (3), Ivanhoe (5), Aquarius (1).