Бывает, зайдешь на сайт, и видишь там вот такое: ?
Ладно если это 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. По поводу написания таких составных запросов я писал здесь.
А как это юзать? Куда вставлять или откуда выполнять?
Скрипт работает, но в нём не учтена системная настройка «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); } }