Экспорт в YML при нехватке оперативной памяти под php скрипты (версия 2.7.4 и ниже)

Материал из Umicms

Перейти к: навигация, поиск

При нехватки памяти, можно обойти данную проблему написав кастомный макрос, который грубо говоря сохранит по частям все разделы, а потом соединит их в один файл. Ниже будет приведен пример двух кастомных макросов (ymlnew и stepsform) их необходимо прописать в файле classes/modules/eshop/__custom.php . Метод ymlnew() создан на основе существующего метода yml и мало чем отличается от оригинала. stepsform() - новый метод.

public function ymlnew() {
 
$ids_temp = getRequest('ids');
$elements = explode("-", $ids_temp);
$yml_file_temp = getRequest('file');
$yml_file = "./cache/yml{$yml_file_temp}.xml";
$templxsl_temp = getRequest('templxsl');
$templxsl = "./xsl/dump2yml{$templxsl_temp}.xsl";
 
$objectTypes = umiObjectTypesCollection::getInstance();
$objectTypeId = $objectTypes->getBaseType("catalog", "object");
$categoryTypeId = $objectTypes->getBaseType("catalog", "category");
$objectType = $objectTypes->getType($objectTypeId);
 
if($objectType instanceof umiObjectType == false) {
throw new privateException("Object type #{$objectTypeId} not found");
}
 
$priceFieldId = $objectType->getFieldId("price");
if(!$priceFieldId) {
throw new privateException("Price property missed in object type #{$objectTypeId}");
}
 
// select category
$sel = new umiSelection;
$sel->addHierarchyFilter($elements, 100);
$sel->addObjectType($categoryTypeId);
$result = umiSelectionsParser::runSelection($sel);
$elements = array_merge($elements, $result);
 
// select element
if($yml_file_temp){
$sel = new umiSelection;
$sel->addHierarchyFilter($elements, 100);
$sel->addPropertyFilterMore($priceFieldId, 0);
$result = umiSelectionsParser::runSelection($sel);
$elements = array_merge($elements, $result);
}
 
$exporter = new umiXmlExporter();
$exporter->setElements($elements);
$exporter->run();
 
$oDOM = new DomDocument();
$oDOM->loadXML($exporter->getResultFile());
 
$xp = new DOMXPath($oDOM);
$nodes = $xp->query("//property[name = 'opisanie']//value");
 
for ($i = 0; $i < $nodes->length; $i++) {
$node = $nodes->item($i);
$node->nodeValue = strip_tags($node->nodeValue);
}
 
$xslt = new xsltProcessor;
$xslt->registerPHPFunctions();
$xslt->importStyleSheet(DomDocument::load($templxsl));
 
$result = $xslt->transformToXML($oDOM);
file_put_contents($yml_file, $result);
@chmod($yml_file,0755);
 
$url = getServer('HTTP_REFERER');
 
if (!strstr($url,"step")) {
$link = $url."?step=1";
} else {
$offset = (int) strlen($yml_file_temp);
$id_step = substr($url,-$offset);
$id_step++;
$link = substr($url, 0, -$offset)."".$id_step;
}
def_module::redirect($link);
}
 
public function stepsform($id_parent){
 
if(!$hierarchy = umiHierarchy::getInstance()->getChilds($id_parent,false,true,1,5)){
return "Скорее всего указан неверный id ({$id_parent}) Основного раздела";
}
// Массив из основных разделов
$id_category = array_keys($hierarchy);
 
foreach($id_category as $key => $id){
   $ChildsCount= umiHierarchy::getInstance()->getChildsCount($id);
   if(!$ChildsCount) unset($id_category[$key]); 
}
sort($id_category);
 
$size = sizeof($id_category);
 
// Массив со всеми основными разделами, перечисленными через знак "-"
$id = implode($id_category,"-");
 
if(array_key_exists('step',$_GET) && $size >= $_GET['step']){
$step = (int)$_GET['step'];
$index = $step - 1;
$name = umiHierarchy::getInstance()->getElement($id_category[$index])->getName();
$itog =<<<HTML
{$step}-й раздел из {$size}: <br /><br />
<form id="steps" action="/eshop/ymlnew/" method="post">
<input style="visibility:hidden" type="checkbox" checked="checked" name="ids" value="{$id_category[$index]}" />
<input style="visibility:hidden" type="checkbox" checked="checked" name="file" value="{$step}" />
<input style="visibility:hidden" type="checkbox" checked="checked" name="templxsl" value="3" />
<input type="submit" value="Экспорт раздела с id = {$id_category[$index]} ({$name})" />
</form>
<script language="JavaScript">setTimeout('document.getElementById("steps").submit()', 10000);</script>
HTML;
return $itog;
}
if(!array_key_exists('step',$_GET)){
 
$itog =<<<HTML
<form action="/eshop/ymlnew/" method="post">
<input style="visibility:hidden" type="checkbox" checked="checked" name="ids" value="{$id}" />
<input style="visibility:hidden" type="checkbox" checked="checked" name="file" value="0" />
<input style="visibility:hidden" type="checkbox" checked="checked" name="templxsl" value="2" />
<input type="submit" value="Начать экспорт в YML" />
</form>
HTML;
 
return $itog;
}
 
// Блок соединения всех xml файлов: yml0.xml, yml1.xml, ... в файл yml.xml
if(array_key_exists('step',$_GET) && sizeof($id_category) < $_GET['step']){
$category = "./cache/yml0.xml";
$handle_category = fopen($category, "r");
$size = filesize($category) - 22;
$category_itog = fread($handle_category,$size);
$handle = fopen("./yml.xml", "w+");
 
fwrite($handle, $category_itog);
fclose($handle_category);
fwrite($handle, "<offers>");
 
for($i = 1; $i <= sizeof($id_category); $i++){
$offers = "./cache/yml{$i}.xml";
$handle_offers = fopen($offers, "r");
fread($handle_offers,91);
$size_offers = filesize($offers) - 101;
$offers_itog = fread($handle_offers,$size_offers);
fwrite($handle, $offers_itog);
fclose($handle_offers);
 
}
 
fwrite($handle, "</offers></shop></yml_catalog>");
fclose($handle);
}
return "<a href = \"/yml.xml\">Ссылка на итоговый YML файл</a>";
}

В методе stepsform(), такие тэги как HTML; должны быть у самого левого края php файла. Также необходимо в создать в той же папке eshop файл permissions.custom.php с таким содержанием:

<?php
$permissions = Array('basket' => Array('ymlnew','stepsform'));
?>

Необходимо также добавить два .xsl шаблона в папку xsl. Имена шаблонов:

- dump2yml2.xsl

- dump2yml3.xsl

Шаблоны аналогичны шаблону dump2yml.xsl, только в шаблоне dump2yml2.xsl, в блоке:

<xsl:template match="umicmsDump">

необходимо удалить блок:

<offers>
<xsl:apply-templates select="object[/umicmsDump/element[behaviour/method = 'object']/@objectId = @id]"/>
<!--xsl:apply-templates select="element[behaviour/method = 'object']"/-->
</offers>

а в шаблоне dump2yml3.xsl, в блоке:

<xsl:template match="umicmsDump">

оставить только:

<offers>
<xsl:apply-templates select="object[/umicmsDump/element[behaviour/method = 'object']/@objectId = @id]"/>
<!--xsl:apply-templates select="element[behaviour/method = 'object']"/-->
</offers>

Далее создаем в админке отдельную страницу контента, допустим ymlexport, в контенте прописываем макрос: %eshop stepsform(xxx)%

Xxx – тут должен быть id основного раздела, в котором находятся остальные разделы с объектами каталога. Переходим на страницу: _http://домен/ymlexport

Нажимаем кнопку "Начать экспорт в YML" и ждем пока не завершится процесс экспорта, в конце будет дана ссылка на итоговый yml.xml файл, он будет храниться в корне сайта.

Личные инструменты