TestHelper/Data/StoreProvider.php
<?php
/**
* Tweakwise (https://www.tweakwise.com/) - All Rights Reserved
*
* @copyright Copyright (c) 2017-2022 Tweakwise.com B.V. (https://www.tweakwise.com)
* @license Proprietary and confidential, Unauthorized copying of this file, via any medium is strictly prohibited
*/
namespace Tweakwise\Magento2TweakwiseExport\TestHelper\Data;
use BadMethodCallException;
use Faker\Factory;
use Faker\Generator;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Indexer\IndexerInterfaceFactory;
use Magento\Store\Api\Data\GroupInterface;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Api\Data\WebsiteInterface;
use Magento\Store\Model\GroupFactory;
use Magento\Store\Model\StoreFactory;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Store\Model\WebsiteFactory;
class StoreProvider
{
/**
* @var Generator
*/
protected $faker;
/**
* @var EntityHydrator
*/
protected $hydrator;
/**
* @var WebsiteFactory
*/
protected $websiteFactory;
/**
* @var GroupFactory
*/
protected $groupFactory;
/**
* @var StoreFactory
*/
protected $storeFactory;
/**
* @var CategoryProvider
*/
protected $categoryProvider;
/**
* @var IndexerInterfaceFactory
*/
protected $indexerFactory;
/**
* @var StoreManagerInterface
*/
protected $storeManager;
/**
* StoreProvider constructor.
*
* @param EntityHydrator $hydrator
* @param WebsiteFactory $websiteFactory
* @param GroupFactory $groupFactory
* @param StoreFactory $storeFactory
* @param CategoryProvider $categoryProvider
* @param StoreManagerInterface $storeManager
* @param IndexerInterfaceFactory $indexerFactory
*/
public function __construct(
EntityHydrator $hydrator,
WebsiteFactory $websiteFactory,
GroupFactory $groupFactory,
StoreFactory $storeFactory,
CategoryProvider $categoryProvider,
StoreManagerInterface $storeManager,
IndexerInterfaceFactory $indexerFactory
) {
$this->faker = Factory::create();
$this->hydrator = $hydrator;
$this->websiteFactory = $websiteFactory;
$this->groupFactory = $groupFactory;
$this->storeFactory = $storeFactory;
$this->categoryProvider = $categoryProvider;
$this->indexerFactory = $indexerFactory;
$this->storeManager = $storeManager;
}
/**
* @param string $code
* @return WebsiteInterface|null
*/
public function getWebsite(string $code)
{
try {
return $this->storeManager->getWebsite($code);
} catch (NoSuchEntityException $e) {
return null;
}
}
/**
* Ensure website is created if it does not exists.
*
* @param array $data
* @return WebsiteInterface
*/
public function createWebsite(array $data = []): WebsiteInterface
{
$website = $this->websiteFactory->create();
$website->setName($this->faker->firstName());
$website->setCode($this->sanitizeCode($website->getName()));
$website->setSortOrder(10);
$this->hydrator->hydrate($data, $website);
$existingWebsite = $this->getWebsite($website->getCode());
if ($existingWebsite) {
return $existingWebsite;
}
$website->save();
return $website;
}
/**
* Ensure website is removed, does not doe anything if website did not exist.
* Will return true if website was found and removed, otherwise will return false.
*
* @param string $code
* @return bool
* @throws \Exception
* @throws BadMethodCallException
*/
public function removeWebsite(string $code): bool
{
$website = $this->getWebsite($code);
if ($website === null) {
return false;
}
if (!method_exists($website, 'delete')) {
throw new BadMethodCallException(sprintf('Method delete not found on %s', \get_class($website)));
}
$website->delete();
return true;
}
/**
* @param string $code
* @return GroupInterface|null
*/
public function getStoreGroup(string $code)
{
try {
// Must use getGroups here even the API reports getGroup should return also with group code, it does not.
foreach ($this->storeManager->getGroups(true) as $group) {
if ($group->getCode() === $code) {
return $group;
}
}
return null;
} catch (NoSuchEntityException $e) {
return null;
}
}
/**
* Ensure store group is created if it does not exists.
*
* @param WebsiteInterface $website
* @param array $data
* @return GroupInterface
*/
public function createStoreGroup(WebsiteInterface $website = null, array $data = []): GroupInterface
{
if ($website === null) {
$website = $this->createWebsite();
}
$group = $this->groupFactory->create();
$group->setName($this->faker->domainName);
$group->setCode($this->sanitizeCode($website->getCode() . strtolower($group->getName())));
$group->setWebsiteId($website->getId());
$group->setRootCategoryId($this->categoryProvider->getDefaultRootId());
$this->hydrator->hydrate($data, $group);
$existingGroup = $this->getStoreGroup($group->getCode());
if ($existingGroup) {
return $existingGroup;
}
$group->save();
return $group;
}
/**
* Ensure store group is removed, does not doe anything if store group did not exist.
* Will return true if store group was found and removed, otherwise will return false.
*
* @param string $code
* @return bool
* @throws \Exception
* @throws BadMethodCallException
*/
public function removeStoreGroup(string $code): bool
{
$group = $this->getStoreGroup($code);
if ($group === null) {
return false;
}
if (!method_exists($group, 'delete')) {
throw new BadMethodCallException(sprintf('Method delete not found on %s', \get_class($group)));
}
$group->delete();
return true;
}
/**
* @param string $code
* @return StoreInterface|null
*/
public function getStoreView(string $code)
{
try {
return $this->storeManager->getStore($code);
} catch (NoSuchEntityException $e) {
return null;
}
}
/**
* @param GroupInterface|null $group
* @param array $data
* @return StoreInterface
*/
public function createStoreView(GroupInterface $group = null, array $data = []): StoreInterface
{
if ($group === null) {
$group = $this->createStoreGroup();
}
$store = $this->storeFactory->create();
$store->setName($this->faker->domainName);
$store->setCode($this->sanitizeCode($store->getName()));
$store->setWebsiteId($group->getWebsiteId());
$store->setGroupId($group->getId());
$store->setSortOrder(10);
$store->setIsActive(true);
$this->hydrator->hydrate($data, $store);
$existingStore = $this->getStoreView($store->getCode());
if ($existingStore) {
return $existingStore;
}
$store->save();
$this->reindex();
return $store;
}
/**
* Ensure store view is removed, does not doe anything if store view did not exist.
* Will return true if store view was found and removed, otherwise will return false.
*
* @param string $code
* @return bool
* @throws \Exception
* @throws BadMethodCallException
*/
public function removeStoreView(string $code): bool
{
$store = $this->getWebsite($code);
if ($store === null) {
return false;
}
if (!method_exists($store, 'delete')) {
throw new BadMethodCallException(sprintf('Method delete not found on %s', \get_class($store)));
}
$store->delete();
return true;
}
/**
* Reindex flat and full text so we have the required tables
*/
protected function reindex()
{
$indexer = $this->indexerFactory->create();
$indexer->load('catalogsearch_fulltext');
$indexer->reindexAll();
}
/**
* @param string $code
* @return string
*/
protected function sanitizeCode(string $code): string
{
$code = strtolower($code);
$code = preg_replace('/[^a-zA-Z0-9]/', '_', $code);
return $code;
}
}