Миграция с TV[type=image] в ms2Gallery

На днях стояла задача мигрировать все картинки из TV поля с типом «image» в ms2Gallery. Да при этом в контентах всех ресурсов заменить ссылку старого изображения из TV на новую ссылку из ms2Gallery. К тому-же в конце работы, чтоб удалял старые изображения с сервера, и данные в ТВшках о старых картинках.

Результат работы под катом.


Скрипт положить в корень или можно куда-нибудь глубже в папку и запустить из браузера (надёжнее из консоли).

Чтобы удалялись данные о старых изображениях надо выставить "$remove_old = 1".

<?php

// >> Подключаем
define('MODX_API_MODE', true);

$current_dir = dirname(__FILE__) .'/';
$index_php = $current_dir .'index.php';

$i=0;
while( !file_exists( $index_php ) && $i < 9 )
{
	$current_dir = dirname(dirname($index_php)) .'/';
	$index_php = $current_dir .'index.php';
	$i++;
}

if( file_exists($index_php) )
{
	require_once $index_php;
}
else {
	print "Не удалось подгрузить MODX";
	die;
}
// << Подключаем


// >> Включаем обработку ошибок
$modx->getService('error','error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
// << Включаем обработку ошибок


$modx->addPackage('ms2gallery', MODX_CORE_PATH . 'components/ms2gallery/model/'); // подключаем модель компонента "ms2Gallery"


$tv_id = '6'; // TV с типом Image

$remove_old = 0; // после заливки удалять данные из базы о ТВшке и старый файл с сервера?


// >> Выборка
$q = $modx->newQuery( 'modTemplateVarResource' );
$q->innerJoin(
	'modTemplateVar',
	'modTemplateVar',
	'modTemplateVar.id = modTemplateVarResource.tmplvarid'
);
$q->select(
	array(
		'modTemplateVarResource.contentid as id',
		'modTemplateVarResource.value as filepath',
		'modTemplateVar.source as source',
	)
);
$q->where( array(
	'modTemplateVarResource.tmplvarid = "'. $tv_id .'"'.
	' AND '.
	'modTemplateVar.type = "image"'.
''));
$s = $q->prepare(); //print_r( $q->toSQL() ); die;
$s->execute();
$rows = $s->fetchAll(PDO::FETCH_ASSOC);
unset($q); unset($s);
//print_r( $rows ); die;

if( !is_array($rows) OR !count($rows) ) { print 'Ничего не найдено.'; die; }
// << Выборка


$modx->loadClass('sources.modMediaSource'); // подключаем класс modMediaSource


$slashes = array('////','///','//');

$_rows = $rows;

foreach( $rows as $k => $row )
{
	// >> Получаем данные Источника Медиа
	if( !is_object($mediaSource) )
	{
		$mediaSource = modMediaSource::getDefaultSource( $modx, $row['source'] );
		//$mediaSource->set('ctx', $ctx);
		$mediaSource->initialize();
	}

	$source_base_url = $mediaSource->getBaseUrl();
	//print $source_base_url; die;
	
	unset($mediaSource);
	// << Получаем данные Источника Медиа
	
	
	$filepath		= substr( str_replace( $slashes, '/', '/'. $source_base_url .'/'. $row['filepath'] ), 1);
	$filepath_full	= $current_dir . substr( str_replace( $slashes, '/', '/'. $source_base_url .'/'. $row['filepath'] ), 1);
	
	if( file_exists($filepath_full) )
	{
		//print $row['id'] . $filepath_full; die;
		
		$response_upload = $modx->runProcessor('gallery/upload', array(
				'file'		=> $filepath,
				'id'		=> $row['id'],
			),
			array('processors_path' => MODX_CORE_PATH.'components/ms2gallery/processors/mgr/')
		);
		
		if( isset( $response_upload->response['object']['url'] ) )
		{
			$new_filepath		= substr( str_replace( $slashes, '/', '/'. $response_upload->response['object']['url'] ), 1);
			$new_filepath_full	= $current_dir . substr( str_replace( $slashes, '/', '/'. $response_upload->response['object']['url'] ), 1);
			
			if( file_exists($new_filepath_full) )
			{
				// >> Выборка и замена в ресурсах в поле "content" старого изображения на новое
				$sql = "UPDATE {$modx->getTableName('modResource')} SET content = REPLACE(content, '". $filepath ."', '". $new_filepath ."') WHERE content LIKE '%". $filepath ."%'";
				$q = $modx->prepare($sql);
				$q->execute();
				unset($q);
				// << Выборка и замена в ресурсах в поле "content" старого изображения на новое
			}
		}
		
		unset( $_rows[ array_search( $row, $_rows ) ] );
		
		
		// >> Удаляем старые файл и данные TV, если перезалили в ms2Gallery
		if( $remove_old )
		{
			if( isset( $response_upload->response['object']['url'] ) || ( isset( $response_upload->response['message'] ) && strstr( $response_upload->response['message'], 'уже есть' ) ) )
			{
				if( !search_in_array( $row['filepath'], $_rows ) )
				{
					unlink( $filepath_full );
				}
				
				$q = $modx->newQuery('modTemplateVarResource');
				$q->command('delete');
				$q->where(array(
					'tmplvarid'		=> $tv_id,
					'contentid'		=> $row['id'],
					'value'			=> $row['filepath'],
				));
				$q->prepare();
				//print $q->toSQL(); die;
				$q->stmt->execute();
				unset($q);
			}
		}
		// << Удаляем старые файл и данные TV, если перезалили в ms2Gallery
		
		
		unset($response_upload);
	}
}


// >> Функция поиска в многомерном массиве
function search_in_array( $value, $array )
{
	foreach( $array as $k => $v )
	{
		if( array_search( $value, $v ) )
		{
			return true;
		}
	}
	
	return false;
}
// << Функция поиска в многомерном массиве
Павел Гвоздь
16 августа 2015, 17:36
modx.pro
4
1 821
+5
Поблагодарить автора Отправить деньги

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

Николай
17 августа 2015, 16:52
0
Какое то страшное подключение modx api. Это все делается в 5 строчек:
require_once 'config.core.php';
require_once MODX_CORE_PATH.'model/modx/modx.class.php';
$modx = new modX();
$modx->initialize('web');
$modx->getService('error','error.modError', '', '');
    Павел Гвоздь
    17 августа 2015, 19:40
    0
    Перепишите для себя. Я для себя писал и мне удобно, чтобы скрипт можно было сунуть куда-нибудь.
      Николай
      17 августа 2015, 20:32
      0
      Ваше дело как поступить. Я лишь поправил скрипт подключения для тех, кто будет использовать его в дальнейшем.
        Павел Гвоздь
        17 августа 2015, 20:45
        0
        А в чём отличие Вашего метода подключения и того, что у меня, если не считать множества проверок на существование файла index.php в моём скрипте?

        Мне действительно интересно, может я что-то делаю не так…
          Николай
          17 августа 2015, 20:53
          0
          В моем случае корректно подключается modx и создается обьект, у вас я не вижу этого, вполне вероятно что способ работоспособный, но на сколько правильный — я тут сказать не могу.
            Павел Гвоздь
            17 августа 2015, 21:03
            0
            Разве в index.php не происходит тоже самое?)

            К слову:
            Это все делается в 5 строчек
            Тем способом, которым воспользовался я это можно сделать в 3 строчки:
            define('MODX_API_MODE', true);
            require_once dirname(__FILE__) . '/index.php';
            $modx->getService('error','error.modError');
            Это если Вам нравится делать всё компактно.
              Василий Наумкин
              17 августа 2015, 21:40
              +3
              Да, я тоже так делаю.

              Но и в готовом скрипте такую портянку с нахождением index.php оставлять не стоит. Или убрать совсем, или переписать поиск в цикле на n директорий вверх.
                Павел Гвоздь
                17 августа 2015, 22:09
                +1
                Вот за это спасибо, Василий. Долго думал, как лучше сделать проверку и цикл while почему-то не рассматривал, как вариант. После твоих слов сразу в голову пришёл while. Поправил.
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    8