Экспорт в 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 файл, он будет храниться в корне сайта.
