[miniShop2] - Перенос изображений в Selectel

В данном топике решается проблема переноса изображений с сайта на Selectel Cloud Storage.
Ситуация с которой пришлось столкнуться — магазин наполнялся и все было хорошо, в какой то момент решили перейти на облачное хранилище. По хорошему нужно было создать новый медиасорс и его привязаться к Selectel, а затем задать его по дефолту, но было сделано иначе. Просто MS2 Images настроили на Selectel и дальше приняли спокойно наполнять.
И вроде бы все нормально, но… что же со старыми файлами что лежат на хостинге? А да, с ними проблемка…
Под катом скрипт для переноса вот таких изображений в облако.


— Первое, наперво сделать бэкап.

— Второе
Создать медиасорс TMP и задать в нем несуществующий путь, например
basePath - assets/images/products/tmp/
В процессе обработки будет задавать продукту source TMP и удалять старые изображения из БД.
Чтобы физически они не удалялись нужен данный фокус.

— Третье
Создать файлик, где вам удобно и поместить в него следующий код
gist.github.com/vgrish/f6cf18f77f52058b4db2289c7795b78b

<?php
ini_set('display_errors', 1);
ini_set('error_reporting', -1);
define('MODX_API_MODE', true);
$productionConfig = (dirname(dirname(__FILE__))) . '/index.php';
if (file_exists($productionConfig)) {
    /** @noinspection PhpIncludeInspection */
    require_once $productionConfig;
} else {
    die;
}
// load services
$modx->setLogTarget('FILE');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->getService('error', 'error.modError');
$modx->error->message = null;
// 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);
$path = MODX_BASE_PATH . 'assets/images/products/';
$q = $modx->newQuery('msProduct');
$q->innerJoin('msProductFile', 'msProductFile', 'msProduct.id = msProductFile.product_id');
$q->where(array(
    'msProductFile.parent'   => 0,
    'msProductFile.url:LIKE' => '%/assets/images/products/%',
));
$q->sortby('msProduct.id', 'ASC');
$q->limit(1);
/** @var msProduct $product */
$product = $modx->getObject('msProduct', $q);
if ($product) {
    $modx->log(modX::LOG_LEVEL_ERROR, "Process product " . $product->get('id'));
    $files = scandir($path . $product->get('id'));
    foreach ($files as $idx => $file) {
        if ($file == '.' || $file == '..') {
            unset($files[$idx]);
            continue;
        };
        if (is_dir($path . $product->get('id') . '/' . $file)) {
            unset($files[$idx]);
            continue;
        }
        $files[$idx] = $path . $product->get('id') . '/' . $file;
    }
    $modx->log(modX::LOG_LEVEL_ERROR, print_r($files, 1));
    // set TMP source
    $product->set('source', 3);
    $product->save();
    /** @var msProductFile[] $images */
    $images = $product->getMany('Files', array('parent' => 0, 'url:LIKE' => '%/assets/images/products/%',));
    foreach ($images as $image) {
        $image->remove();
    }
    // set MS2 Images source
    $product->set('source', 2);
    $product->save();
    if (!empty($files)) {
        foreach ($files as $image) {
            $name = explode('/', $image);
            $name = end($name);
            if (!file_exists($image)) {
                $modx->log(modX::LOG_LEVEL_ERROR, "Could not import image \"$v\" to gallery. File \"$image\" not found on server.");
            } else {
                $response = $modx->runProcessor('gallery/upload',
                    array('id' => $product->get('id'), 'name' => $name, 'file' => $image),
                    array('processors_path' => MODX_CORE_PATH . 'components/minishop2/processors/mgr/')
                );
                if ($response->isError()) {
                    $modx->log(modX::LOG_LEVEL_ERROR, "Error on upload \"$v\": \n" . print_r($response->getAllErrors(), 1));
                } else {
                    $modx->log(modX::LOG_LEVEL_INFO, "Successful upload  \"$v\": \n" . print_r($response->getObject(), 1));
                }
            }
        }
    }
}
$count = $modx->getCount('msProductFile', array(
    'parent'   => 0,
    'url:LIKE' => '%/assets/images/products/%',
));
$modx->log(modX::LOG_LEVEL_ERROR, "Total " . $count);
if ($count AND $product) {
    $uri = parse_url($_SERVER['REQUEST_URI']);
    $siteUrl = $modx->getOption('site_url', null, MODX_SITE_URL);
    $stepRedirect = trim($siteUrl, '/') . $uri['path'];
    $refreshDelay = 2;
    header("Refresh: {$refreshDelay}; url={$stepRedirect}");
} else {
    $modx->log(modX::LOG_LEVEL_ERROR, "Process product END");
}

в данном случае
TMP source - идентификатор 3
MS2 Images source - идентификатор 2
Если у вас другие идентификаторы, то сделайте замену по коду.

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

PS. Все спасибо за внимание. НЕ ЗАБЫВАЕМ ПРО БЭКАП!!!
Володя
22 сентября 2017, 09:13
modx.pro
12
2 635
+7
Поблагодарить автора Отправить деньги

Комментарии: 2

Алекс Назаренко
12 октября 2017, 17:08
0
Спасибо! Очень кстати пришлось.
    Danil
    28 мая 2020, 02:40
    0
    А простое обновление превью через процессор «mgr/gallery/generate»
    $resources = $modx->getCollection('msProductFile', $q);
    foreach ($resources as $resource) {
        $modx->runProcessor('mgr/gallery/generate', array('id' => $resource->id),
            array('processors_path' => $modx->getOption('core_path').'components/minishop2/processors/'));
    }
    не подойдет, если файлы заранее перенес в Selectel?
    Старые изображения из бд удалятся? Если нет, то как тогда можно почистить от мусора таблицу? А то такое чувство что в ней записей раза в 2 больше чем нужно.
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      2