Model/Write/Categories.php
<?php
/**
* Tweakwise (https://www.tweakwise.com/) - All Rights Reserved
*
* @copyright Copyright (c) 2017-2022 Tweakwise.com B.V. (https://www.tweakwise.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
namespace Tweakwise\Magento2TweakwiseExport\Model\Write;
use Tweakwise\Magento2TweakwiseExport\Model\Config;
use Tweakwise\Magento2TweakwiseExport\Model\Helper;
use Tweakwise\Magento2TweakwiseExport\Model\Logger;
use Tweakwise\Magento2TweakwiseExport\Model\Write\Categories\Iterator;
use Magento\Framework\Profiler;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManager;
class Categories implements WriterInterface
{
/**
* @var Iterator
*/
protected $iterator;
/**
* @var StoreManager
*/
protected $storeManager;
/**
* @var Config
*/
protected $config;
/**
* @var Helper
*/
protected $helper;
/**
* @var Logger
*/
protected $log;
/**
* Categories constructor.
*
* @param Iterator $iterator
* @param StoreManager $storeManager
* @param Config $config
* @param Helper $helper
* @param Logger $log
*/
public function __construct(
Iterator $iterator,
StoreManager $storeManager,
Config $config,
Helper $helper,
Logger $log
) {
$this->iterator = $iterator;
$this->storeManager = $storeManager;
$this->config = $config;
$this->helper = $helper;
$this->log = $log;
}
/**
* @param Writer $writer
* @param XMLWriter $xml
* @param StoreInterface|null $store
*/
public function write(Writer $writer, XMLWriter $xml, StoreInterface $store = null): void
{
$xml->startElement('categories');
$writer->flush();
$this->writeCategory($xml, 0, ['entity_id' => 1, 'name' => 'Root', 'position' => 0]);
$stores = [];
if ($store) {
$stores[] = $store;
} else {
$stores = $this->storeManager->getStores();
}
/** @var Store $store */
foreach ($stores as $store) {
if ($this->config->isEnabled($store)) {
$profileKey = 'categories::' . $store->getCode();
try {
Profiler::start($profileKey);
$this->exportStore($writer, $xml, $store);
} finally {
Profiler::stop($profileKey);
}
$this->log->debug(sprintf('Export categories for store %s', $store->getName()));
} else {
$this->log->debug(sprintf('Skip categories for store %s (disabled)', $store->getName()));
}
}
$xml->endElement(); // categories
$writer->flush();
}
/**
* @param Writer $writer
* @param XMLWriter $xml
* @param Store $store
* @param int[] $entityIds
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function exportStore(Writer $writer, XMLWriter $xml, Store $store, array $entityIds = []): void
{
// Set root category as exported
$exportedCategories = [1 => true];
$storeId = $store->getId();
$storeRootCategoryId = (int) $store->getRootCategoryId();
$this->iterator->setStore($store);
// Purge iterator entity ids for the new store
$this->iterator->setEntityIds($entityIds);
foreach ($this->iterator as $index => $data) {
// Skip magento root since we injected our fake root
if ($data['entity_id'] === 1) {
continue;
}
$parentId = (int) $data['parent_id'];
// Store root category extend name so it is clear in tweakwise
// Always export store root category whether it is enabled or not
if ($parentId === 1) {
// Skip category if not root of current store
if ((int) $data['entity_id'] !== $storeRootCategoryId) {
continue;
}
if (!isset($data['name'])) {
$data['name'] = 'Root Category';
}
$data['name'] = $store->getName() . ' - ' . $data['name'];
} elseif (!isset($data['is_active']) || !$data['is_active']) {
continue;
}
if (!isset($exportedCategories[$parentId])) {
continue;
}
// Set category as exported
$exportedCategories[$data['entity_id']] = true;
$this->writeCategory($xml, $storeId, $data);
// Flush every so often
if ($index % 100 === 0) {
$writer->flush();
}
}
// Flush any remaining categories
$writer->flush();
}
/**
* @param XMLWriter $xml
* @param int $storeId
* @param array $data
*/
protected function writeCategory(XMLWriter $xml, int $storeId, array $data): void
{
$tweakwiseId = $this->helper->getTweakwiseId($storeId, $data['entity_id']);
$xml->addCategoryExport($tweakwiseId);
$xml->startElement('category');
$xml->writeElement('categoryid', $tweakwiseId);
$xml->writeElement('rank', $data['position']);
$xml->writeElement('name', $data['name']);
if (isset($data['parent_id']) && $data['parent_id']) {
$xml->startElement('parents');
$parentId = (int) $data['parent_id'];
if ($parentId !== 1) {
$parentId = $this->helper->getTweakwiseId($storeId, $parentId);
}
$xml->writeElement('categoryid', $parentId);
$xml->endElement(); // </parents>
$this->log->debug(sprintf('Export category [%s] %s (parent: %s)', $tweakwiseId, $data['name'], $parentId));
} else {
$this->log->debug(sprintf('Export category [%s] %s (root)', $tweakwiseId, $data['name']));
}
$xml->endElement(); // </category>
}
}