EntityImport

Компонент предназначен для организации импорта различных сущностей.
Метки:

Документация

Читать

Компонент EntityImport предоставляет набор абстрактных классов для реализации импорта различных сущностей на сайте. В компоненте также реализован обработчик данных для Nodus, в связи с чем становиться возможным настроить импорт элементов нодуса с минимальными трудозатратами.

Сам компонент делится на 2 основных части:

  • Handler - класс реализует методы обработки данных и загрузки их в систему. Занимается непосредственно импортом данных.
  • Reader - класс реализует методы получения данных, необходимых для Handler.

Такое разделение позволяет создавать для одного обработчика нескольких парсеров данных (например получение данных из файлов csv или xml).

Обработчик. Component.EntityImport.App.Handlers

Все обработчики должны располагаться в папке app/components/EntityImport/app/Handlers/. Все модули, расположенные в этой директории, будут автоматически зарегистрированы в компоненте, и будут доступны по имени. Так же, возможно группирование модулей в папки, но в этом случае именем, под которым будет зарегистрирован компонент, будет результат конкатенации имени директории и файла.

Сами модули должны расширять базовый абстрактный класс Component.EntityImport.Handler и реализовывать в нем метод process_on_row($data, $current_row_index).

Данный метод должен производить сохранение данных в системе. На вход ему будут переданы следующие переменные:

  • $data - массив, содержащий данные одного элемента (например одной строки из файла), предоставленные Reader.
  • $current_row_index - номер итерации.
// app/components/EntityImport/app/Handlers/MyHandler.php

Core::load('Component.EntityImport.App.Handler');

class Component_EntityImport_Handlers_MyHandler extends Component_EntityImport_App_Handler
	implements Core_ModuleInterface
{
	...
	protected function process_on_row($data, $row_index)
	{
		//какой-то код ...
	}
	...
}

Результатом работы метода должно будет булево значение (true/false) - результат обработки записи.

В случае, если необходимо произвести какие-либо действия до или после импорта, необходимо переопределить методы:

  • before_import($source) - выполняется перед запуском импорта. В случае если метод вернет false процесс импорта не будет запущен, т.е данный метод можно использовать для дополнительной проверки перед началом импорта.
  • after_import() - выполняется по завершении импорта.
// app/components/EntityImport/app/Handlers/MyHandler.php

Core::load('Component.EntityImport.App.Handler');

class Component_EntityImport_Handlers_MyHandler extends Component_EntityImport_App_Handler
	implements Core_ModuleInterface
{
	...
	protected function before_import($source)
	{
		//какие-то действия до импорта ...
		return true;
	}

	protected function after_import()
	{
		//какие-то действия после ...
	}
	...
}

Парсер. Component.EntityImport.App.Readers

Все парсеры должны располагаться в папке app/components/EntityImport/app/Readers/. Для этой директории справедливы все правила, что и для app/components/EntityImport/app/Handlers/.

Сами модули должны расширять базовый абстрактный класс Component.EntityImport.Reader, реализуя методы:

  • open($source) - методу на вход передается ресурс, с которым был вызван импорт, и должен производить открытие его на чтение. Например для парсеров, работающих с файлами, здесь будет передан путь к файлу.
  • read - метод вызывается в обработчике и должен возвращать данные одного элемента (например распарсенные данные одной строки).
  • close - метод производит действия по завершению работы с открытыми данными.

В компоненте уже предусмотрены парсеры csv- и xml-файлов.

  • Component.EntityImport.Reader.File.CSV. Параметры модуля:
    • delimeter - разделитель полей в файле (один символ). По умолчанию имеет значение «;».
    • enclosure - символ ограничителя поля (один символ). По умолчанию имеет значение «"».
    • temp_dir - парсер позволяет получать файлы расположенные на внешних ресурсах, в этом случае файл сначала будет сохранен во временной директории
    • lock_file_lifetime - время ожидания завершения предыдущего импорта. Перед началом импорта парсер создает блокирующий файл и пока этот файл существует, все последующие запуски импорта будут игнорироваться. В этой настройке указывается максимальное время жизни этого файла в секундах.
  • Component.EntityImport.Reader.File.XML. Параметры модуля:
    • tag_name - имя тега, по элементам которых будет создан итератор.
    • encoding - кодировка файла. По умолчанию UTF-8.
    • options - битовая маска, состоящая из LIBXML-констант (см. http://php.net/manual/ru/libxml.constants.php).
    • temp_dir - парсер позволяет получать файлы, расположенные на внешних ресурсах. В этом случае, файл сначала будет сохранен во временной директории.
    • lock_file_lifetime - время ожидания завершения предыдущего импорта. Перед началом импорта парсер создает блокирующий файл и пока этот файл существует, все последующие запуски импорта будут игнорироваться. В этой настройке указывается максимальное время жизни этого файла в секундах.

В случае, если ваш модуль будет расширять один из этих классов, необходимо будет реализовать метод parse_row($row). Данный метод должен возвратить распарсенные данные в том виде, в котором их ожидает обработчик. Для настройки параметров модуля необходимо переопределить метод setup(), в котором нужно вызвать метод parms

// ...
	public function setup()
	{
		parent::setup();
		$this->parms(array(

		// разделитель поля (только один символ)
		'delimeter' => ';',

		// символ ограничителя поля (только один символ)
		'enclosure' => '"',
		));
	return $this;

	}
// ...

Логирование. Component.EntityImport.Log

В компоненте реализована система логирования посредством класса Component.EntityImport.Log. В модуле предусмотрены несколько уровней ошибок для их логирования:

  • Component.EntityImport.Log::LOG_LEVEL_NOTICE = 1 - простые уведомления;
  • Component.EntityImport.Log::LOG_LEVEL_WARNING = 2 - предупреждения, ошибки не критичные для хода импорта;
  • Component.EntityImport.Log::LOG_LEVEL_ERROR = 4 - критическая ошибка, приведшая к прекращению импорта;

В модулях обработчика и парсера есть метод log(), который возвращает экземпляр этого класса. Для добавления сообщения в журнал необходимо воспользоваться одним из следующих методов: notice(), warning() или error() в зависимости от типа вашего сообщения.

Применение CLI для запуска импорта

Для запуска импорта из cli в компоненте предусмотрена соответствующая команда:

php index.php entityimport_run HandlerName ReaderType filepath [--log_level=7 [,--verbose=yes]]

где:

  • HandlerName - имя зарегистрированного обработчика.
  • ReaderName - имя зарегистрированного парсера.
  • filepath - ресурс, с которым запустится импорт (для модулей расширяющих Component.EntityImport.Reader.File.CSV или Component.EntityImport.Reader.File.XML путь к файлу).
  • --log_level - битовая маска из констант Component.EntityImport.Log. Указывает, какие сообщения необходимо протоколировать (по умолчанию 7 - т.е все виды сообщений).
  • --verbose - если указан (yes/no), то все сообщения будут выводиться на экран.

Обработчик для импорта данных Nodus-сущностей

В компоненте реализован обработчик для импорта данных элементов Nodus. Парсер к этому обработчику должен возвращать массив вида:

...
protected function parse_row($row)
	{
		return array(
			'field_name' => 'field_value'
		)
}

Данный обработчик в процессе импорта конвертирует входные данные в значения вида CMS.Fields.Types.

Поддерживаемые типы

На данный момент поддерживаются следующие типы (список будет расширяться).

  • input - при импорте проверяется тип поля в mysql и значение приводится к этому типу. Например, если в поле тип указан как price, то значение должно быть числом (в качестве разделителя дробной части может быть как «.» так и «,»).
  • multilang_ext - значением должен быть массив вида array('lang_code' => 'lang_value', ...).
  • checkbox - в случае, если значением будет одно из да, 1, yes, true, on, то чекбокс будет включен.
  • select - значением может быть как ключ варианта, так и его заголовок.
  • array - значением может быть массив или строка - результат сериализации массива.
  • gallery - значением может быть как массив со списком адресов к изображениям, так и строка разделенных адресов. Иначе загрузка файлов не будет произведена. В процессе импорта сравнивается md5 новых файлов и уже загруженных, и только в случае, если они будут разные, файл будет заменен. Все изображения, загруженные ранее и не указанные в переданном списке, будут удалены.
  • static_multilink - значение: массив ключей вариантов.
  • youtube - значение: ссылка на ролик с youtube.
  • nodus_taxonomy_plain_select - значением может быть как id термина, так и его название.
  • nodus_taxonomy_tree_select - значением будет либо массив (путь до термина начиная с корня), либо строка вида key1=>key2, состоящая из id или заголовков терминов.
  • nodus_taxonomy_multilink - массив из id или заголовков терминов.
  • nodus_items_select - массив id или заголовков элементов.
  • nodus_items_multilink, nodus_items_multilink_advanced - массив id или заголовков элементов.
  • map_coords - либо массив вида array(lat =>' ' , lng =>' ', zoom =>' '), либо строка, состоящая из этих значений разделенных «,» или «;».

Применение CLI

Так же в компоненте можно запустить импорт этого обработчика из cli. Для этого необходимо выполнить следующую команду:

php index.php entityimport_run_nodus datatype ReaderType filepath [--action_with_not_found[,--log_level[, --verbose=yes]]]

где

  • datatype - дататайп (datatype) нодуса, для которого производится импорт данных.
  • ReaderType - тип импорта. Именем парсера будет результат конкатенации datatype и ReaderType. Например, datatype = page, ReaderType = csv - именем модуля парсера будет pagecsv.
  • --action_with_not_found - действие с элементами, которых до этого не было в файле:
  • remove - удалить.
  • disable - деактивировать.
  • skip - пропустить (по умолчанию).

Остальные параметры будут аналогичны вызову любого другого импорта (см. п. Применение CLI для запуска импорта).

Для примера рассмотрим создание обработчика элементов нодуса с типом page и парсера к нему. Предположим, что импорт осуществляется посредством загрузки следующего файла

// ../sync/page.csv
page1;Импорт1;текст текст текст
page2;Импорт2;текст текст текст

Все, что для этого нужно сделать - это создать модуль парсера в директории app/components/EntityImport/app/Readers/. Т.к. файл с данными имеет формат csv, то базовым классом парсера будет является класс Component.EntityImport.Reader.File.CSV.

// app/components/EntityImport/app/Readers/Page/CSV.php

Core::load('Component.EntityImport.App.Reader.File.CSV');

class Component_EntityImport_App_Readers_Page_CSV extends Component_EntityImport_App_Reader_File_CSV
implements Core_ModuleInterface
{
	public function setup()
	{
		parent::setup();
		// говорим парсеру, что разделителем полей в файле является ;
		$this->parms(array('delimiter' => ';'));
		return $this;
	}

	protected function parse_row($row)
	{
		// конвертируем данные из файла в вид понятный обработчику
		return array(
			'code' => $row[0], // внешний код эл-та, является обязательным
			// остальные поля
			'title' => $row[1],
			'content' => $row[2],
			);
	}
}

Теперь в консоли выполняем команду:

php index.php entityimport_run_nodus page csv ../sync/page.csv --action_with_not_found=skip --verbose=1

которая запустит процесс импорта.

Все версии

Обращаем ваше внимание, что установка и обновление компонентов штатным способом осуществляется из системы управления вашим сайтом ("Библиотека компонентов"). Данный раздел несет прежде всего информационную функцию. Однако, вы можете скачивать инсталляционные пакеты компонентов в целях ознакомления или в случае если функционирование библиотеки компонентов по какой-то причине затруднено.


Версия Дата
0.0.9
Изменения

Исправлена ошибка с удалением Entity

20.02.2019
0.0.8 05.04.2016
0.0.7 16.03.2016
0.0.6 16.03.2016
0.0.5 01.03.2016
0.0.4 09.02.2016
0.0.3
Изменения
Component.EntityImport.CLI - изменен вызов cli entityimport_run Теперь при вызове entityimport_run имя reader необходимо указывать полностью Component.EntityImport.Handlers.ORM Для обработки записей отстутсвующих в импорте, в ридере можно определить метод disable_items($mapper, $remove), где * $mapper - маппер указывающий на выборку отсутсвующих записей * $remove - действие над записями, с которым был запушен импорт (флаг action_with_not_found) Component.Handlers.Nodus: при запуске импорта через entityimport_run можно передать параметр --datatype Component.EntityImport.FieldsConverter.Attaches: при импорте сохраняется порядок файлов. требует обновления TAO до 2.1.111
04.12.2015
0.0.2 27.11.2015
0.0.1 16.02.2015