Skip to content

Instantly share code, notes, and snippets.

@andronex
Last active August 29, 2015 14:17
Show Gist options
  • Save andronex/8c59b4d27ffdfa2e699f to your computer and use it in GitHub Desktop.
Save andronex/8c59b4d27ffdfa2e699f to your computer and use it in GitHub Desktop.
Плагин для поиска по тексту ресурса ключевых слов для дальнейшего присвоения номеров релевантных тексту блоков с контентом. Ключевые слова содержаться в системной настройке my_search_words Для работы нужна либо отдельная библиотека phpMorphy или msearch2 с ней.
Плагин вешаем на событие OnDocFormSave
Создать системную настройку с именем my_search_words
Тип: текстовая область
Содержимое заполняется по принципу: слово:1:1,слово_2:2:2
* слово - слово для поиска в тексте ресурса
* первое число - номер блока ДО контента
* второе число - номер блока ПОСЛЕ контента
Создать TV с именем, например, blocks
содержимое для ресурса будет заполняться автоматически в виде: 1;1, 2:2...
* первое число - номер первого блока ДО контента
* второе число - номер второго блока ПОСЛЕ контента
Имена чанков до: beforeB1, beforeB2...
Имена чанков после: afterB1, afterB2...
<?php
$eventName = $modx->event->name;
switch($eventName) {
case 'OnDocFormSave':
$templNum = 3;//номер шаблона ресурса для обработки (остальные ресурсы при сохранении обработаны не будут)
$tvNum = 'tv2';//номер TV поля с номерами блоков для вывода @var type string
$tvNumInt = 2;//номер TV поля с номерами блоков для вывода @var type integer
if (($mode == 'new') && (($resource->get('template')) == $templNum) && (!$resource->get($tvNum)) && ($string = $resource->content)) {
$search = $modx->getOption('my_search_words');//получаем содержимое системной настройки my_search_words
$lang = 'ru_RU';//язык словаря
require_once MODX_CORE_PATH.'components/msearch2/phpmorphy/src/common.php'; //подключаем phpMorphy
try {
$morphy = new phpMorphy(
MODX_CORE_PATH.'components/msearch2/phpmorphy/dicts/'
,$lang
,array('storage' => PHPMORPHY_STORAGE_FILE));
} catch(phpMorphy_Exception $e) {
die('Error occured while creating phpMorphy instance: ' . $e->getMessage());
}
$search = mb_strtoupper($search,'utf8');//перевод слов для поиска в верхний регистр
$string = preg_replace("/[[:punct:]]/","",mb_strtoupper(strip_tags(str_replace('&nbsp;',' ',htmlspecialchars_decode($string,ENT_QUOTES))),'utf8'));
$string = explode(' ',$string);//разбиение строки в массив по пробелу между словами (каждое слово - элемент массива)
$string = array_diff($string, array(''));//удаление из массива пустых значений
// @var type array();
$lemma = $slovoform = $new_string = $beforeNum = $afterNum = array();
foreach ($string as $val) {
$lemma = $morphy->lemmatize($val);//получение для всех слов из массива базовой формы (леммы)
if(is_array($lemma)){
foreach ($lemma as $lemms) {
$new_string[] = $lemms;
}
}
}
$search = explode(',',$search);
$search = implode(':',$search);
$search = explode(':',$search);
$search = array_chunk($search, 3);//разделение на массивы по 3 элемента в каждом, т.е. "0 -> СЛОВО, 1 -> 2, 2 -> 2", где 1 и 2 - номера блоков ДО и ПОСЛЕ
foreach ($search as $val) {
$beforeNum[] = $val[1];//номер блока ДО
$afterNum[] = $val[2];//номер блока ПОСЛЕ
$slovoform = $morphy->getAllForms($val[0]);//все словоформы слова для поиска
if(is_array($slovoform)){
foreach ($slovoform as $sforms) {
if(array_search($sforms, $new_string)) {//если поисковое слово найдено в тексте, то окончательно присваиваем номера блоков
$before = $val[1];
$after = $val[2];
break 2;
}
}
}
}
if (!$before || !$after) {//если номера блоков ещё не определены, т.е. совпадений в тексте с поисковыми словами не найдено
$bMin = min($beforeNum);
$bMax = max($beforeNum);
$aMin = min($afterNum);
$aMax = max($afterNum);
$before = rand($bMin,$bMax);//рандомно назначаем номера блоков в пределах заданных номеров в системной переменной my_search_words
$after = rand($aMin,$aMax);
}
if(!$resource->setTVValue($tvNumInt, $before.';'.$after)) {
$modx->log(modX::LOG_LEVEL_ERROR, 'Ошибка при сохранении ТВ blocks для вновь создаваемого ресурса.');
}
}
break;
}
<?php
/**
* Сниппет * Выводит блоки ДО и ПОСЛЕ контента и сам контент между ними.
*/
if ($res = $modx->resource) {
$numTV = 2; //номер id TV поля, example @input = 3;3
$nameBefB = 'beforeB'; //имя чанка с блоками ДО, example @input = beforeB + integer
$nameAftB = 'afterB'; //имя чанка с блоками ПОСЛЕ, example @input = afterB + integer
$content = $res->get('content');
$blocks = $res->getTVValue($numTV);
if($blocks) $blocks = explode(';', $blocks); else return $content;
$block_before = $blocks[0];
$block_after = $blocks[1];
$block_before = $modx->getChunk($nameBefB . $block_before);
$block_after = $modx->getChunk($nameAftB . $block_after);
if ($block_before && $block_after) return $block_before . $content . $block_after; else return $content;
}
else return null;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment