Skip to content

Commit

Permalink
Added Admin Grid: Google Shopping Feeds; Added Admin menu section: ru…
Browse files Browse the repository at this point in the history
…n_as_root
  • Loading branch information
Denis Slepnev committed Sep 22, 2022
1 parent b063d85 commit 6a8f235
Show file tree
Hide file tree
Showing 28 changed files with 867 additions and 19 deletions.
86 changes: 86 additions & 0 deletions Api/Data/FeedInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace RunAsRoot\GoogleShoppingFeed\Api\Data;

interface FeedInterface
{
const FILENAME = 'filename';

const PATH = 'path';

const LINK = 'link';

const LAST_GENERATED = 'last_generated';

const STORE = 'store';

/**
* Feed file name
*
* @return string
*/
public function getFileName(): string;

/**
* @param string $fileName
*
* @return $this
*/
public function setFileName(string $fileName): FeedInterface;

/**
* Feed media path
*
* @return string
*/
public function getPath(): string;

/**
* @param string $path
*
* @return $this
*/
public function setPath(string $path): FeedInterface;

/**
* Feed Link for Google
*
* @return string
*/
public function getLink(): string;

/**
* @param string $link
*
* @return $this
*/
public function setLink(string $link): FeedInterface;

/**
* Feed Last Generated Time
*
* @return string
*/
public function getLastGenerated(): string;

/**
* @param string $lastGenerated
*
* @return $this
*/
public function setLastGenerated(string $lastGenerated): FeedInterface;

/**
* Feed Store View
*
* @return string
*/
public function getStore(): string;

/**
* @param string $store
*
* @return $this
*/
public function setStore(string $store): FeedInterface;
}
15 changes: 15 additions & 0 deletions Api/FeedRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace RunAsRoot\GoogleShoppingFeed\Api;

use RunAsRoot\GoogleShoppingFeed\Api\Data\FeedInterface;

interface FeedRepositoryInterface
{
/**
* Retrieve list of feeds
*
* @return FeedInterface[]
*/
public function getList(): array;
}
25 changes: 25 additions & 0 deletions Controller/Adminhtml/Google/Feeds.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace RunAsRoot\GoogleShoppingFeed\Controller\Adminhtml\Google;

class Feeds extends \Magento\Backend\App\Action
{
protected $resultPageFactory = false;

public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
}

public function execute()
{
$resultPage = $this->resultPageFactory->create();
$resultPage->getConfig()->getTitle()->prepend((__('Google Shopping Feeds')));

return $resultPage;
}
}
90 changes: 90 additions & 0 deletions Model/Feed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace RunAsRoot\GoogleShoppingFeed\Model;

use RunAsRoot\GoogleShoppingFeed\Api\Data\FeedInterface;

class Feed extends \Magento\Framework\Model\AbstractExtensibleModel
implements \RunAsRoot\GoogleShoppingFeed\Api\Data\FeedInterface
{

/**
* @inheritDoc
*/
public function getFileName(): string
{
return $this->getData(self::FILENAME);
}

/**
* @inheritDoc
*/
public function setFileName(string $fileName): FeedInterface
{
return $this->setData(self::FILENAME, $fileName);
}

/**
* @inheritDoc
*/
public function getPath(): string
{
return $this->getData(self::PATH);
}

/**
* @inheritDoc
*/
public function setPath(string $path): FeedInterface
{
return $this->setData(self::PATH, $path);
}

/**
* @inheritDoc
*/
public function getLink(): string
{
return $this->getData(self::LINK);
}

/**
* @inheritDoc
*/
public function setLink(string $link): FeedInterface
{
return $this->setData(self::LINK, $link);
}

/**
* @inheritDoc
*/
public function getLastGenerated(): string
{
return $this->getData(self::LAST_GENERATED);
}

/**
* @inheritDoc
*/
public function setLastGenerated(string $lastGenerated): FeedInterface
{
return $this->setData(self::LAST_GENERATED, $lastGenerated);
}

/**
* @inheritDoc
*/
public function getStore(): string
{
return $this->getData(self::STORE);
}

/**
* @inheritDoc
*/
public function setStore(string $store): FeedInterface
{
return $this->setData(self::STORE, $store);
}
}
57 changes: 57 additions & 0 deletions Model/FeedRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace RunAsRoot\GoogleShoppingFeed\Model;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use RunAsRoot\GoogleShoppingFeed\Reader\FileReaderProvider;

class FeedRepository implements \RunAsRoot\GoogleShoppingFeed\Api\FeedRepositoryInterface
{
private FileReaderProvider $fileReaderProvider;

private FeedFactory $feedFactory;

public function __construct(
FileReaderProvider $fileReaderProvider,
FeedFactory $feedFactory
)
{
$this->fileReaderProvider = $fileReaderProvider;
$this->feedFactory = $feedFactory;
}

/**
* @inheritDoc
* @throws NoSuchEntityException
* @throws LocalizedException
*/
public function getList(): array
{
$fileReader = $this->fileReaderProvider->get();

try {
$files = $fileReader->read();
} catch (LocalizedException $e) {
throw new LocalizedException(__($e->getMessage()));
}

$feeds = [];

foreach ($files as $file) {
/** @var Feed $feed */
$feed = $this->feedFactory->create();

$feed->setFileName($file['fileName']);
$feed->setPath($file['path']);
$feed->setLink($file['link']);
$feed->setLastGenerated($file['fileGenerationTime']);
$feed->setStore($file['store']);

$feeds[] = $feed->toArray();
}


return $feeds;
}
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,7 @@ Performs iteration on all products provided by this collection provider `\RunAsR
### Add new attribute to feed
1. Create new attribute data provider. @see interface `\RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\AttributeHandlerInterface`.
2. Add configuration for new attribute in `\RunAsRoot\GoogleShoppingFeed\Enum\AttributesToImportEnumInterface::ATTRIBUTES`.

## Google Shopping Feeds Grid
Generated feeds could be reviewed inside Admin Backoffice
* Navigate to Marketing -> run_as_root -> Google Shopping Feed
87 changes: 87 additions & 0 deletions Reader/FileReader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace RunAsRoot\GoogleShoppingFeed\Reader;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Phrase;
use Magento\Framework\UrlInterface;
use FilesystemIterator;
use FilesystemIteratorFactory;
use DateTime;


class FileReader
{
private UrlInterface $urlBuilder;

private FilesystemIteratorFactory $filesystemIteratorFactory;

private DateTime $dateTime;

private string $destination;

public function __construct(
UrlInterface $urlBuilder,
FilesystemIteratorFactory $filesystemIteratorFactory,
DateTime $dateTime
)
{
$this->urlBuilder = $urlBuilder;
$this->filesystemIteratorFactory = $filesystemIteratorFactory;
$this->dateTime = $dateTime;
}

/**
* @throws NoSuchEntityException
* @throws LocalizedException
*/
public function read(): array
{
if (empty($this->destination)) {
throw new LocalizedException(
new Phrase('The destination is not set')
);
}

try {
$dir = $this->filesystemIteratorFactory->create([
'path' => DirectoryList::MEDIA . DIRECTORY_SEPARATOR . $this->destination,
'flags' => FilesystemIterator::SKIP_DOTS
]);
} catch (\UnexpectedValueException $exception) {
return [];
}

$result = [];
$storeMediaUrl = $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]);

while ($dir->valid()) {
if (!$dir->isDir()) {
$this->dateTime->setTimestamp($dir->getMTime());
$fileGenerationTime = $this->dateTime->format('Y-m-d H:i:s');
$fileName = $dir->getFilename();
$stores = null;
preg_match('/_store_(\w+)_feed/', $fileName, $stores);
$result[] = [
'path' => $dir->getPath() . DIRECTORY_SEPARATOR . $fileName,
'fileGenerationTime' => $fileGenerationTime,
'link' => $storeMediaUrl . $dir,
'fileName' => $fileName,
'store' => $stores[1] ?? 'default'
];
}

$dir->next();
}

return $result;
}

public function setDestination(string $value): FileReader
{
$this->destination = $value;
return $this;
}
}
Loading

0 comments on commit 6a8f235

Please sign in to comment.