Массовая чистка дубликатов УРЛов

Бывает, зайдешь на сайт, и видишь там вот такое: ![13-10-2016 01-01-11.jpg](/assets/images/resized/2016/2226/13-10-2016 01-01-11.jpg) Ладно если это 5-10 документов. А если это 160, как в моем случае? Бывает и больше. Вот опять лень меня победила и я решил написать скрипт, который делает выборку таких конфликтных документов и исправляет им УРЛы автоматом.

Принимайте скрипт:

ini_set('display_errors', 1);
$modx->setLogLevel(3);
$modx->setLogTarget('HTML');

$table = $modx->getTableName("modResource");

$q = $modx->newQuery("modResource");

$alias = $q->getAlias();

$q->select(array(
    "{$alias}.*",
));

$q->query['from']['tables'][] = array(
    "table" => "(select count(*) as total, uri from {$table} as c group by c.uri)",
    "alias" => "t1",
);

$q->where(array(
    "{$alias}.alias:!="   => "",
    "{$alias}.uri:!="   => "",
    "{$alias}.uri = t1.uri",
    "t1.total > 1",
));

foreach($modx->getIterator("modResource", $q) as $doc){
    
    $i = 10;
    
    while($doc->isDuplicateAlias() AND $i > 0){
        
        $i--;
        
        preg_match("/(.*?)\-?(\d*)$/u", $doc->alias, $match);
        
        $doc->alias = "{$match[1]}-{$match[2]}" . rand(1,9);
    }
    
    if($doc->isDirty('alias')){
        $doc->save();
    }
}

print "\n End";

P.S. По поводу написания таких составных запросов я писал здесь.

Comments

Скрипт работает, но в нём не учтена системная настройка «global_duplicate_uri_check» в выключенном состоянии — так что дублирование в других контекстах будет пресекать на корню в любом случае.

Да, резонное замечание. Здесь проверка дублей отдается самому классу modResource, а он не учитывает эту настройку. Но если вы хотите учесть дубликаты только в рамках одного контекста, вы можете передавать его вторым параметром: $doc->isDuplicateAlias('', $doc->context_key);

Тогда проверка дублей будет только в рамках контекста документа. Кстати, в методе modResource::duplicate именно так и делается:

$dupeContext = $this->xpdo->getOption('global_duplicate_uri_check', $options, false) ? '' : $newResource->get('context_key');
if ($newResource->isDuplicateAlias($aliasPath, $dupeContext)) {
    $alias = '';
    if ($newResource->get('uri_override')) {
        $newResource->set('uri_override', false);
    }
}