Skip to content

Instantly share code, notes, and snippets.

@Isa3v
Last active February 3, 2021 07:23
Show Gist options
  • Save Isa3v/25732ee833ba92b6a28df2df2b8d4792 to your computer and use it in GitHub Desktop.
Save Isa3v/25732ee833ba92b6a28df2df2b8d4792 to your computer and use it in GitHub Desktop.
yml modx evo

YML выгрузка (MODx evo)

Делаем YML выгрузку через сниппет с возможностью использования php

Задача:

  1. Сформировать YML-файл
  2. Если цена пустая или равна "По запросу", то ее выгружать не нужно
  3. Сложность в том, что цена написана как "100 руб." или "100 евро" и нужно из этого забрать валюту и цифру

Решение:

  • Создаем новый шаблон. Называем его например "YML - выгрузка"
  • Далее создаем сниппет для самой выгрузки. Называем "yml__offers"
  • В созданный нами сниппет вставляем код из "yml__offers.php". Сохраняем
  • В шаблоне ("YML - выгрузка") прописываем вызов нашего сниппета [!yml__offers? startid=9!].
    startid=9
    - это родительская категории с которой начинаем обход документов
  • Создаем страницу на сайте в корне. Называем "yml.xml". Выбираем наш шаблон. Тип содержимого - text/xml

Немного из кода:

В функции "getDocs" есть массив с TV-параметрами:

	$template_vars = array(
		'price', //цена
		'catalogitem.image', //картинка
		//... и т.д
	);

В массив мы добавляем нужные нам тв-параметры. На некоторых сайта используется > 10-30 параметров. Не думаю, что они все нам нужны.

В "$startid" приходит цифра из шаблона (там мы выбирали категорию родительскую). Если не указано в вызове, то по умолчанию будет весь сайт

$startid = (isset($startid)) ? $startid : 0;
[!yml__offers? startid=9!]
<?php
// Получаем через сниппет знаечние родительского блока или обходим весь сайт
$startid = (isset($startid)) ? $startid : 0;
// Собираем все в xml файл и выводим:
// ---------------------------------------------
//Формируем из функции наш список
$docs = getDocs($modx, $startid);
$output = '<?xml version="1.0" encoding="windows-1251"?>'.PHP_EOL;
$output = '<!DOCTYPE yml_catalog SYSTEM "shops.dtd">'.PHP_EOL;
$output .='<yml_catalog date="[*editedon:date=`%Y-%m-%d %H:%M`*]">'.PHP_EOL;
$output .='<shop>'.PHP_EOL;
$output .='<name>[(site_name)]</name>'.PHP_EOL;
$output .='<company>[(site_name)]</company>'.PHP_EOL;
$output .='<url>[(site_url)]</url>'.PHP_EOL;
$output .='<currencies>
<currency id="RUR" rate="1"/>
<currency id="EUR" rate="CBRF"/>
<currency id="USD" rate="CBRF"/>
</currencies>'.PHP_EOL;
/* ------------------Категории------------------ */
$output .='<categories>'.PHP_EOL;
foreach ($docs as $doc) {
if ($doc['isfolder'] == 1){
$output .= '<category id="'.$doc['id'].'" '.($doc['parent'] != $startid ? 'parentId="'.$doc['parent'].'"' : '').'>'.$doc['pagetitle'].'</category>'.PHP_EOL;
}
}
$output .='</categories>';
/* --------------------------------------------- */
/* --------------------Товары------------------- */
$output .='<offers>'.PHP_EOL;
foreach ($docs as $doc) {
if ($doc['isfolder'] == 0 && $doc['tv']['price'] != 'По запросу' && $doc['tv']['price'] != ''){
/*Этот ужас конкретно для моей задачи (нужно было выдернуть руб, евро и прочее. удалить все десятичные)*/
//Вместо цены в output ставим $doc['tv']['price']
//Вместо $cur_offer указываем валюту
preg_match("/(?![\W])[\S].*(?>[\d]+)/i", $doc['tv']['price'], $price_array, PREG_OFFSET_CAPTURE);
$price = str_replace(' ','', $price_array[0][0]);
$price = explode(',', $price);
$price = $price[0];
if (strripos($doc['tv']['price'], 'евро') !== false){
$cur_offer ='EUR';
}elseif(strripos($doc['tv']['price'], 'EURO') !== false){
$cur_offer ='EUR';
}elseif(strripos($doc['tv']['price'], '€') !== false){
$cur_offer ='EUR';
}elseif(strripos($doc['tv']['price'], '$') !== false){
$cur_offer ='USD';
}else{
$cur_offer ='RUR';
}
/*******/
$output .= '<offer id="'.$doc['id'].'" available="true">';
$output .= '<url>[(site_url)][~'.$doc['id'].'~]</url>';
$output .= '<price>'.$price.'</price>';
$output .= '<currencyId>'.$cur_offer.'</currencyId>';
$output .= '<categoryId>'.$doc['parent'].'</categoryId>';
$output .= '<picture>[(site_url)]'.$doc['tv']['catalogitem.image'].'</picture>';
$output .= '<delivery>true</delivery>';
$output .= '<name>'.$doc['pagetitle'].'</name>';
//Максимальное кол-во символов в тексте
$max_length = 170;
//Удаляем из описания теги и html сущности
$desc = yandex_text2xml($doc['content'], true);
$output .= '<description>'.cut_words($max_length, $desc).'</description>';
$output .= '</offer>';
}
}
$output .='</offers>';
/* --------------------------------------------- */
$output .='</shop>';
$output .= '</yml_catalog>';
return $output;
// Функции для сборки
// ---------------------------------------------
// Для обрезки текст
function cut_words($maxlen, $text) {
$len = (mb_strlen($text) > $maxlen)? mb_strripos(mb_substr($text, 0, $maxlen), ' ') : $maxlen;
$cutStr = mb_substr($text, 0, $len);
$temp = (mb_strlen($text) > $maxlen)? $cutStr. '...' : $cutStr;
return $temp;
}
function yandex_text2xml($text, $bHSC = false, $bDblQuote = false)
{
if ($bHSC)
{
$text = htmlspecialchars(strip_tags($text));
if ($bDblQuote)
$text = str_replace('&quot;', '"', $text);
}
$text = preg_replace('/[\x01-\x08\x0B-\x0C\x0E-\x1F]/', "", $text);
$text = str_replace("'", "&apos;", $text);
return $text;
}
// Перебераем тв-парамтры
function getTV($modx, $docid, $template_vars){
$val_tv = $modx->getTemplateVars($template_vars, '*', $docid);
$output = array(); // делаем массив с полученными тв-параметрами
foreach ($val_tv as $key=>$v){
$output[$v['name']] = $v['value']; // Нам нужно только название и значение
}
return $output;
}
//Разбираем документы
function getDocs($modx, $startid){
//Выбираем и сортируем нужные нам параметры
$docs = $modx->getActiveChildren($startid, 'menuindex', 'asc', 'parent,id,editedon,template,published,searchable,pagetitle,type,isfolder,content');
// Полуачем нужные нам TV-парамтеры
$template_vars = array(
'price', //цена
'catalogitem.image', //картинка
//... и т.д
);
//Разбираем и обьединяем
foreach ($docs as $key => $doc){
$id = $doc['id'];
$docs[$key]['tv'] = getTV($modx, $id, $template_vars); // Добавляем тв параметры
$docs = array_merge($docs, getDocs($modx, $id));
}
// Отдаем обратно
return $docs;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment