Более простой способ получить расширенные метаданные в ilUIHookPluginGUI?

В настоящее время я пишу плагин для ILIAS. Сам плагин совсем не сложен, но содержит несколько проблем, хотя я думаю, что мы могли бы сделать его проще, как есть.

Ситуация следующая: у нас есть глобальное расширенное поле метаданных, добавленное в раздел пользовательских метаданных с биективным идентификатором. Поле активируется в хранилище возражений с указанным курсом. Мы манипулировали GUI с помощью плагина на основе ilUIHookPluginGUI,

Код для этого... ну... посмотрите сами.

Прежде всего, мы сохраняем идентификатор нового поля метаданных в настройках ConfigGUI для плагина:

$field_settings = new ilSetting("foo");
$field_id_value = $field_settings->set("field_id",$_POST["field_id"]);

В нашем классе, который расширяется ilUIHookPluginGUI мы загружаем настройку следующим образом и у нас есть идентификатор поля:

$field_settings = new ilSetting("foo");
$field_id_value = $field_settings->get("field_id");

Теперь самое интересное. С этим идентификатором и ref_id объекта (ну, мы также загружаем объект, чтобы получить ObjId), мы можем загрузить значение поля метаданных, установленного на курсе:

$object = \ilObjectFactory::getInstanceByRefId($_GET[ 'ref_id' ]);
$obj_id = $object->getId();

$result = $DIC->database()->query("SELECT value FROM adv_md_values_text WHERE obj_id = '".$obj_id."' AND field_id = '".$field_id_value."'");
$value = $DIC->database()->fetchAssoc($result);
$is_active = $value['value'];

Вопрос в том... есть ли более простой способ достичь моего результата?

Бест, Лора

1 ответ

Хороший вопрос Прежде всего, обратите внимание, что я считаю, что расширенному сервису метаданных в ILIAS не хватает хорошего readme-файла, который бы четко обозначал, каким интерфейсом предлагается интерфейс для таких задач, как ваша. Некоторое время назад мне также пришлось столкнуться с этим сервисом и столкнуться с похожими проблемами. Надеюсь, ваш вопрос поможет немного лучше документировать это, и я сам с нетерпением жду других предложений, зная, что мое тоже не очень хорошо. Если у вас есть какие-либо ресурсы, мы будем очень благодарны за продвижение введения хорошего readme для сервисов, а также за продвижение сервисов к использованию шаблона репозитория с понятным интерфейсом.

Принимая во внимание ваш вопрос о том, что можно улучшить: в строках кода я вижу три основных вопроса:

  1. Хранение идентификатора в конфиге вашего плагина. Ваш плагин будет неконфигурируем для нетехнических людей. Однако и для вас это будет подвержено ошибкам, подумайте об экспорте-импорте материалов из тестовой установки в производство.
  2. Доступ к значению по запросу вместо службы.
  3. Использование новых и статических функций внутри вашего кода делает его непроверенным.

Шаг 1 Давайте начнем с первого. Обратите внимание, что мне не удалось решить эту проблему без введения нового (новый запрос). Плохо знаю. Я надеюсь, что есть лучшее решение, я не нашел его после быстрого исследования. Вы сохраняете идентификатор, так как заголовок поля не является надежно уникальным, верно? Это правильно, однако, вы можете подумать о сохранении триплета field_title, record_title и (возможно) области видимости. Обратите внимание, что вам, возможно, не нужен объем, поскольку вы хотите использовать его глобально. Функция, возвращающая вас, и массив, содержащий field_id и record_id, может выглядеть так:

function getFieldAndRecordIdByFieldTitles($field_title, $record_title, $scope_title){
        $query = "select field.field_id,field.record_id from adv_mdf_definition as field
            INNER JOIN adv_md_record as record ON record.record_id = field.record_id
            INNER JOIN adv_md_record_scope as scope ON scope.record_id = field.record_id
            INNER JOIN object_reference as ref ON scope.ref_id = ref.ref_id
            INNER JOIN object_data as scope_data ON ref.obj_id = scope_data.obj_id
            WHERE field.title='$field_title' AND record.title='$record_title' AND scope_data.title = '$scope_title'";

        $set = $this->dic()->database()->query($query);
        if($row = $this->dic()->database()->fetchAssoc($set))
        {
            return array_values($row);
        }
    }

Затем получите ваши значения так:

list($field_id,$record_id) = getFieldAndRecordIdByFieldTitles("my_field", "my_record", "my_scope");

Обратите внимание, что я знаю, что я ввожу новый запрос здесь. Извините, это было лучшее, что я мог придумать. Я уверен, что там вы найдете лучшее решение, если ваше исследование немного, дайте нам знать, если успешно. Тем не менее, мы удалим один на следующем шаге.

Шаг 2 Воспользуйтесь недокументированным сервисом, чтобы получить выгоду от предварительных метаданных. Поскольку теперь у вас есть идентификатор записи и идентификатор поля, вы можете сделать это следующим образом:

$record_values = new ilAdvancedMDValues($record_id, $obj_id);
$record_values->read();
$ADTGroup = $ilAdvancedMDValues->getADTGroup();
$ADT = $ilADTGroup->getElement($field_id);
$value = $ADT->getText(); 
/**if you have text, others are possible, such as:              
        switch (true) {
            case ($ADT instanceof ilADTText):
                break;
            case ($ADT instanceof ilADTDate):
                $value = $ADT->getDate();
                break;
            case ($ADT instanceof ilADTExternalLink):
                $... = $ADT->getUrl();
                $... = $ADT->getTitle();
                break;
            case ($ADT instanceof ilADTInternalLink):
                $... = $ADT->setTargetRefId($value);
        }
**/

Обратите внимание, что ADT также не имеют документов. Там может быть лучший способ, чтобы получить значение из этого.

Шаг 3 Оберните ваши статические и новые в некоторую зависимость для инъекций. Я обычно использую раздутый образец конструктора, чтобы сделать это. Выглядит так:

public function __construct(InjectedSettings $mySettings = null)
{
    if (!$mySettings) //Case in the default scenario
    {
        $this->mySettings = new InjectedSettings();
    } else //used e.g. for unit tests, where you can stuff the constructor with a mock
    {
        $this->mySettings = $mySettings;
    }
    $this->mySettings->doSometing();
}

Обратите внимание, что это не настоящая деп. впрыск, все еще вы все еще используете новый, но я думаю, что очень работоспособное решение использовать dep. инъекция, по крайней мере, для тестового контекста в Илиас.

Это помогает? Я надеюсь, что будут другие (лучшие ответы, а также).

Другие вопросы по тегам