Обновление полей ресурсов на основе csv-файла иморта (modx 2.8.8 + minishop 2)
Задача была обновить поля у ресурсов (ресурсы: категории, товары; поля: основные, дополнительные (тв)).
Обновление изображений (галерея) в задачу не входило.
Возможно, кому-нибудь пригодится. Если будут корректировки/замечания, буду только рад.
Пытался использовать модуль importX, но оказалось,что существующий функционал модуля затирает все тв-поля, которых не было в csv-файле, но они были заполнены у ресурсов (вина не самого модуля, а процессора update, который он использует).
Решил данную задачу, немного изменив скрипт csv.php (/core/components/minishop2/import/csv.php). Большое спасибо его создателю за труд!
1. Пример файла импорта import.csv:
Остальные поля — заполняются по необходимости. Если в файле какие-то поля пустые, то обновление по ним не произойдет.
Директория размещения файла импорта — любая папка в корне проекта, в нашем случае — import.
2. Вызов скрипта — через веб-интерфейс. Пример, вызова для нашего файла импорта:
Директория размещения скрипта — любая папка в корне проекта, в нашем случае — import
3. Сам скрипт (csvUpdate.php):
0
Обновление изображений (галерея) в задачу не входило.
Возможно, кому-нибудь пригодится. Если будут корректировки/замечания, буду только рад.
Решил данную задачу, немного изменив скрипт csv.php (/core/components/minishop2/import/csv.php). Большое спасибо его создателю за труд!
1. Пример файла импорта import.csv:
id;pagetitle;tv1;tv2
189;Заголовок Товар 1;Сео-заголовок для товара 1;Сео-описание для товара 1
320;Заголовок Категория 1;Сео-заголовок для для категории;Сео-описание для для категориигде id — id ресурса. Обязательное полеОстальные поля — заполняются по необходимости. Если в файле какие-то поля пустые, то обновление по ним не произойдет.
Директория размещения файла импорта — любая папка в корне проекта, в нашем случае — import.
2. Вызов скрипта — через веб-интерфейс. Пример, вызова для нашего файла импорта:
[ваш домен]/import/csvUpdate.php?file=/import/import.csv&fields=id,pagetitle,tv1,tv2Если разделитель полей отличен от ';', то необходимо указать параметр &delimeter=[ваш разделитель]Директория размещения скрипта — любая папка в корне проекта, в нашем случае — import
3. Сам скрипт (csvUpdate.php):
<?php
const MODX_API_MODE = true;
require_once '../core/config/config.inc.php';
require_once MODX_BASE_PATH . 'index.php';
$file = @$_REQUEST['file'];
$fields = @$_REQUEST['fields'];
$delimeter = @$_REQUEST['delimeter'];
$is_debug = false;
// Load main services
/** @var modX $modx */
$modx->setLogLevel($is_debug ? modX::LOG_LEVEL_INFO : modX::LOG_LEVEL_ERROR);
$modx->getService('error', 'error.modError');
// Time limit
set_time_limit(600);
$tmp = 'Trying to set time limit = 600 sec: ';
$tmp .= ini_get('max_execution_time') == 600 ? 'done' : 'error';
$modx->log(modX::LOG_LEVEL_INFO, $tmp);
// Check required options
if (empty($fields)) {
$modx->log(modX::LOG_LEVEL_ERROR, 'You must specify the parameter "fields". It needed for parse of your file.');
exit;
}
$keys = array_map('trim', explode(',', strtolower($fields)));
$requiredField = 'id';
if (!in_array($requiredField, $keys)) {
$modx->log(modX::LOG_LEVEL_ERROR, 'Field "' . $requiredField . '" not exists in csv file. Please fix import file');
exit;
}
if (empty($delimeter)) {
$delimeter = ';';
}
// Check file
if (empty($file)) {
$error = 'You must specify an file in the ';
$modx->log(modX::LOG_LEVEL_ERROR, $error);
exit;
} elseif (!preg_match('/\.csv$/i', $file)) {
$modx->log(modX::LOG_LEVEL_ERROR, 'Wrong file extension. File must be an *.csv.');
exit;
}
$file = str_replace('//', '/', MODX_BASE_PATH . $file);
if (!file_exists($file)) {
$modx->log(modX::LOG_LEVEL_ERROR, 'File not found at ' . $file . '.');
exit;
}
// Import!
$handle = fopen($file, "r");
$rows = $updated = 0;
$not_updated = [];
$csv = fgetcsv($handle, 0, $delimeter);
while (($csv = fgetcsv($handle, 0, $delimeter)) !== false) {
$rows++;
$data = [];
$dataTvs = [];
$modx->error->reset();
foreach ($keys as $k => $v) {
if (!isset($csv[$k])) {
exit('Field "' . $v . '" not exists in file. Please fix import file or parameter "fields".');
}
if (preg_match('/^tv(\d+)$/', $v)){
$tvId = substr($v, 2);
$dataTvs[$tvId] = $csv[$k];
} else {
$data[$v] = $csv[$k];
}
}
// update resource
$res = $modx->getObject('modResource', $data['id']);
if ($res) {
array_shift($data);
if (!empty($data)) {
foreach ($data as $key => $field) {
if (empty($field)) {
continue;
}
$res->set($key, $field);
}
$res->save();
}
if (!empty($dataTvs)) {
foreach ($dataTvs as $key => $field_tv) {
if (empty($field_tv)) {
continue;
}
$res->setTVValue((int)$key, $field_tv);
}
}
$updated++;
$modx->log(modX::LOG_LEVEL_INFO, "Successfully updated");
} else {
$not_updated[] = $data['id'];
$modx->log(modX::LOG_LEVEL_ERROR, "Error on update resource id={$data['id']}. It doesn't exist.\n");
}
if ($is_debug) {
$modx->log(
modX::LOG_LEVEL_INFO,
'You in debug mode, so we process only 1 row. Time: ' . number_format(
microtime(true) - $modx->startTime,
7
) . " s"
);
exit;
}
}
fclose($handle);
echo "Import complete in " . number_format(microtime(true) - $modx->startTime, 7) . " s
";
echo "Total rows: $rows
";
echo "Updated: $updated
";
if (!empty($not_updated)) {
echo "Not updated (resources ids): " . implode(',', $not_updated);
}