diff --git a/Api/Data/FeedInterface.php b/Api/Data/FeedInterface.php new file mode 100644 index 0000000..1b52258 --- /dev/null +++ b/Api/Data/FeedInterface.php @@ -0,0 +1,86 @@ +resultPageFactory = $resultPageFactory; + } + + public function execute() + { + $resultPage = $this->resultPageFactory->create(); + $resultPage->getConfig()->getTitle()->prepend((__('Google Shopping Feeds'))); + + return $resultPage; + } +} \ No newline at end of file diff --git a/Model/Feed.php b/Model/Feed.php new file mode 100644 index 0000000..9009289 --- /dev/null +++ b/Model/Feed.php @@ -0,0 +1,90 @@ +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); + } +} \ No newline at end of file diff --git a/Model/FeedRepository.php b/Model/FeedRepository.php new file mode 100644 index 0000000..ec5ecdf --- /dev/null +++ b/Model/FeedRepository.php @@ -0,0 +1,57 @@ +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; + } +} \ No newline at end of file diff --git a/README.md b/README.md index 9d05db3..52ff6ae 100644 --- a/README.md +++ b/README.md @@ -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 \ No newline at end of file diff --git a/Reader/FileReader.php b/Reader/FileReader.php new file mode 100644 index 0000000..a017323 --- /dev/null +++ b/Reader/FileReader.php @@ -0,0 +1,87 @@ +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; + } +} \ No newline at end of file diff --git a/Reader/FileReaderProvider.php b/Reader/FileReaderProvider.php new file mode 100644 index 0000000..c97d168 --- /dev/null +++ b/Reader/FileReaderProvider.php @@ -0,0 +1,24 @@ +fileReaderFactory = $fileReaderFactory; + } + + public function get(): FileReader + { + $fileReader = $this->fileReaderFactory->create(); + $fileReader->setDestination(XmlFileWriterProvider::DIRECTORY_PATH); + + return $fileReader; + } +} \ No newline at end of file diff --git a/Test/Unit/Converter/ArrayToXmlConverterTest.php b/Test/Unit/Converter/ArrayToXmlConverterTest.php index 731739f..4e88024 100644 --- a/Test/Unit/Converter/ArrayToXmlConverterTest.php +++ b/Test/Unit/Converter/ArrayToXmlConverterTest.php @@ -33,16 +33,16 @@ private function getProductRow(): array { return [ [ - 'category_url' => 'https://app.seidenland.test/bettdecken/naturhaardecken', + 'category_url' => 'https://app.default.test/bettdecken/naturhaardecken', 'color' => null, 'description' => 'product-description', 'ean' => '4000863525821', 'gender' => null, 'item_group_id' => 'FAN-53KBBW01V0011', - 'image_link' => 'https://app.seidenland.test/media/catalog/product/cache/775fcb5986783027a0f3aac116b4fff3/c/a/cashmere-duo-winterdecke-53kbbw01v0009-frankenstolz-2_2.jpg', + 'image_link' => 'https://app.default.test/media/catalog/product/cache/775fcb5986783027a0f3aac116b4fff3/c/a/cashmere-duo-winterdecke-53kbbw01v0009-frankenstolz-2_2.jpg', 'additional_image_link' => [ - 0 => 'https://app.seidenland.test/media/catalog/product/cache/775fcb5986783027a0f3aac116b4fff3/o/e/oeko-tex-zertifizierte-schadstoffkontrollierte-bettwaren-frankenstolz_3_2_1_2_2_4_1_1_3_2_2_2_2.jpg', - 1 => 'https://app.seidenland.test/media/catalog/product/cache/775fcb5986783027a0f3aac116b4fff3/f/a/fan-bettwaren-made-in-germany_2_2_1_2_2_4_1_1_3_2_2_2_2.jpg' + 0 => 'https://app.default.test/media/catalog/product/cache/775fcb5986783027a0f3aac116b4fff3/o/e/oeko-tex-zertifizierte-schadstoffkontrollierte-bettwaren-frankenstolz_3_2_1_2_2_4_1_1_3_2_2_2_2.jpg', + 1 => 'https://app.default.test/media/catalog/product/cache/775fcb5986783027a0f3aac116b4fff3/f/a/fan-bettwaren-made-in-germany_2_2_1_2_2_4_1_1_3_2_2_2_2.jpg' ], 'is_in_stock' => 'in_stock', 'manufacturer' => 'f.a.n. Frankenstolz', @@ -81,7 +81,7 @@ private function getProductRow(): array ], ], 'sku' => 'FAN-53KBBW01V0011-155/220', - 'url' => 'https://app.seidenland.test/cashmere-90-duo-bettdecke-extra-warm-frankenstolz?tec_size_bettwaren_config=1113', + 'url' => 'https://app.default.test/cashmere-90-duo-bettdecke-extra-warm-frankenstolz?tec_size_bettwaren_config=1113', ] ]; } @@ -97,8 +97,8 @@ private function getExpectedResult(): string - - + + @@ -133,7 +133,7 @@ private function getExpectedResult(): string - + diff --git a/Test/Unit/DataProvider/AttributeHandlers/AdditionalImageLinkProviderTest.php b/Test/Unit/DataProvider/AttributeHandlers/AdditionalImageLinkProviderTest.php index 651c6f1..2f566a8 100644 --- a/Test/Unit/DataProvider/AttributeHandlers/AdditionalImageLinkProviderTest.php +++ b/Test/Unit/DataProvider/AttributeHandlers/AdditionalImageLinkProviderTest.php @@ -99,8 +99,8 @@ public function testGet(): void ->method('getFile') ->willReturn($productImageThree); - $productImageLinkTwo = 'https://app.seidenland.test/media/catalog/product/o/e/image-two.jpg'; - $productImageLinkThree = 'https://app.seidenland.test/media/catalog/product/o/e/image-three.jpg'; + $productImageLinkTwo = 'https://app.default.test/media/catalog/product/o/e/image-two.jpg'; + $productImageLinkThree = 'https://app.default.test/media/catalog/product/o/e/image-three.jpg'; $this->productImageUrlProviderMock ->expects($this->exactly(2)) diff --git a/Test/Unit/DataProvider/AttributeHandlers/CategoryUrlProviderTest.php b/Test/Unit/DataProvider/AttributeHandlers/CategoryUrlProviderTest.php index 57dd852..db8b422 100644 --- a/Test/Unit/DataProvider/AttributeHandlers/CategoryUrlProviderTest.php +++ b/Test/Unit/DataProvider/AttributeHandlers/CategoryUrlProviderTest.php @@ -82,7 +82,7 @@ public function testGet(): void ->method('getRequestPath') ->willReturn($requestPath); - $categoryUrl = 'https://www.seidenland.de/waschen-pflegen/speick-naturkosmetik'; + $categoryUrl = 'https://www.default/waschen-pflegen/speick-naturkosmetik'; $this->urlMock ->expects($this->once()) ->method('getDirectUrl') diff --git a/Test/Unit/DataProvider/AttributeHandlers/ImageLinkProviderTest.php b/Test/Unit/DataProvider/AttributeHandlers/ImageLinkProviderTest.php index 532339d..10f3c10 100644 --- a/Test/Unit/DataProvider/AttributeHandlers/ImageLinkProviderTest.php +++ b/Test/Unit/DataProvider/AttributeHandlers/ImageLinkProviderTest.php @@ -56,7 +56,7 @@ public function testItShouldReturnTheChildProductImageUrl(): void ->method('getImage') ->willReturn($image); - $productImageLink = 'https://app.seidenland.test/media/catalog/product/o/c/child-product-image.jpg'; + $productImageLink = 'https://app.default.test/media/catalog/product/o/c/child-product-image.jpg'; $this->productImageUrlProviderMock ->expects($this->once()) @@ -96,7 +96,7 @@ public function testItShouldReturnTheParentProductImageUrl(): void ->method('getImage') ->willReturn($image); - $productImageLink = 'https://app.seidenland.test/media/catalog/product/o/c/parent-product-image.jpg'; + $productImageLink = 'https://app.default.test/media/catalog/product/o/c/parent-product-image.jpg'; $this->productImageUrlProviderMock ->expects($this->once()) diff --git a/Test/Unit/DataProvider/ProductImageProviderTest.php b/Test/Unit/DataProvider/ProductImageProviderTest.php index 44f0480..ca0be4d 100644 --- a/Test/Unit/DataProvider/ProductImageProviderTest.php +++ b/Test/Unit/DataProvider/ProductImageProviderTest.php @@ -13,7 +13,7 @@ final class ProductImageProviderTest extends TestCase { private ProductImageUrlProvider $sut; - private string $imageUrl = 'https://app.seidenland.test/media/catalog/product/c/a/image.jpg'; + private string $imageUrl = 'https://app.default.test/media/catalog/product/c/a/image.jpg'; private string $imagePath = 'c/a/image.jpg'; protected function setUp(): void diff --git a/Test/Unit/Model/FeedRepositoryTest.php b/Test/Unit/Model/FeedRepositoryTest.php new file mode 100644 index 0000000..bd4add6 --- /dev/null +++ b/Test/Unit/Model/FeedRepositoryTest.php @@ -0,0 +1,94 @@ +fileReaderProviderMock = $this->createMock(FileReaderProvider::class); + $this->feedFactoryMock = $this->createMock(FeedFactory::class); + + $this->sut = new FeedRepository($this->fileReaderProviderMock, $this->feedFactoryMock); + } + + public function testLocalizedExceptionThrown(): void + { + $fileReaderMock = $this->createMock(FileReader::class); + $this->fileReaderProviderMock->method('get')->willReturn($fileReaderMock); + + $expectedLogMessage = 'The destination is not set'; + + $this->fileReaderProviderMock->expects($this->once()) + ->method('get') + ->willThrowException(new LocalizedException(__($expectedLogMessage))); + + $this->expectExceptionMessage($expectedLogMessage); + + $this->sut->getList(); + } + + public function testGetListEmptyResult(): void + { + $fileReaderMock = $this->createMock(FileReader::class); + $this->fileReaderProviderMock->method('get')->willReturn($fileReaderMock); + + $fileReaderMock->method('read')->willReturn([]); + + $this->assertEquals([], $this->sut->getList()); + } + + public function testGetList(): void + { + $fileReaderMock = $this->createMock(FileReader::class); + $this->fileReaderProviderMock->method('get')->willReturn($fileReaderMock); + + $file = [ + 'fileName' => 'base_store_default_feed.xml', + 'path' => 'media/run_as_root/feed/base_store_default_feed.xml', + 'link' => 'https://local.magento2.com/media/run_as_root/feed/base_store_default_feed.xml', + 'fileGenerationTime' => date('Y-m-d H:i:s'), + 'store' => 'default' + ]; + + $files = [ + $file + ]; + + $fileReaderMock->method('read')->willReturn($files); + + $feedMock = $this->createMock(Feed::class); + $this->feedFactoryMock->method('create')->willReturn($feedMock); + + $feedMock->method('setFileName')->with($file['fileName'])->willReturn($feedMock); + $feedMock->method('setPath')->with($file['path'])->willReturn($feedMock); + $feedMock->method('setLink')->with($file['link'])->willReturn($feedMock); + $feedMock->method('setLastGenerated')->with($file['fileGenerationTime'])->willReturn($feedMock); + $feedMock->method('setStore')->with($file['store'])->willReturn($feedMock); + + $feedMock->method('toArray')->willReturn([ + 'filename' => $file['fileName'], + 'path' => $file['path'], + 'link' => $file['link'], + 'last_generated' => $file['fileGenerationTime'], + 'store' => $file['store'] + ]); + + $this->assertArrayHasKey('link', $this->sut->getList()[0]); + } +} diff --git a/Test/Unit/Reader/FileReaderProviderTest.php b/Test/Unit/Reader/FileReaderProviderTest.php new file mode 100644 index 0000000..2093775 --- /dev/null +++ b/Test/Unit/Reader/FileReaderProviderTest.php @@ -0,0 +1,40 @@ +fileReaderFactoryMock = $this->createMock(FileReaderFactory::class); + + $this->sut = new FileReaderProvider($this->fileReaderFactoryMock); + } + + public function testGet() + { + $fileReaderMock = $this->createMock(FileReader::class); + $destination = 'run_as_root/feed'; + + $this->fileReaderFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($fileReaderMock); + + $fileReaderMock->expects($this->once()) + ->method('setDestination') + ->with($destination) + ->willReturnSelf(); + + $this->sut->get(); + } +} diff --git a/Test/Unit/Reader/FileReaderTest.php b/Test/Unit/Reader/FileReaderTest.php new file mode 100644 index 0000000..8cc1767 --- /dev/null +++ b/Test/Unit/Reader/FileReaderTest.php @@ -0,0 +1,99 @@ +urlBuilderMock = $this->getMockBuilder(UrlInterface::class)->getMock(); + $this->dirFactoryMock = $this->createMock(\FilesystemIteratorFactory::class); + $this->dateTimeMock = $this->getMockBuilder(DateTime::class)->getMock(); + + $this->dirMock = $this->createMock(\FilesystemIterator::class); + + $this->dirFactoryMock->method('create')->with([ + 'path' => DirectoryList::MEDIA . DIRECTORY_SEPARATOR . self::DESTINATION, + 'flags' => \FilesystemIterator::SKIP_DOTS + ])->willReturn($this->dirMock); + + $this->sut = new FileReader($this->urlBuilderMock, $this->dirFactoryMock, $this->dateTimeMock); + $this->sut->setDestination(self::DESTINATION); + } + + public function testDirDoesntExists(): void + { + $this->dirFactoryMock->method('create')->with([ + 'path' => DirectoryList::MEDIA . DIRECTORY_SEPARATOR . self::DESTINATION, + 'flags' => \FilesystemIterator::SKIP_DOTS + ])->willThrowException(new \UnexpectedValueException); + + $this->assertEquals([], $this->sut->read()); + } + + public function testReadWithoutFiles(): void + { + + $this->dirMock->method('valid')->willReturnOnConsecutiveCalls(true, true, false); + + $storeMediaUrl = 'https://local.magento2.com/media'; + $this->urlBuilderMock->method('getBaseUrl') + ->with(['_type' => UrlInterface::URL_TYPE_MEDIA]) + ->willReturn($storeMediaUrl); + + $this->dirMock->method('isDir')->willReturn(true); + + $this->assertEquals([], $this->sut->read()); + } + + public function testRead(): void + { + + $this->dirMock->method('valid')->willReturnOnConsecutiveCalls(true, true, false); + + $storeMediaUrl = 'https://local.magento2.com/media'; + $this->urlBuilderMock->method('getBaseUrl') + ->with(['_type' => UrlInterface::URL_TYPE_MEDIA]) + ->willReturn($storeMediaUrl); + + $this->dirMock->method('isDir')->willReturn(false); + + $fileGenerationTime = '2022-09-21 15:10:58'; + $filename = 'base_store_default_feed_1.xml'; + $filePath = self::DESTINATION; + $fileMTime = 1663686469; + + $this->dirMock->method('getMTime')->willReturn($fileMTime); + $this->dateTimeMock->method('setTimestamp') + ->with($fileMTime) + ->willReturn($fileMTime); + $this->dateTimeMock->method('format') + ->with('Y-m-d H:i:s') + ->willReturn($fileGenerationTime); + $this->dirMock->method('getFilename')->willReturn($filename); + $this->dirMock->method('getPath')->willReturn($filePath); + + $resultItem = current($this->sut->read()); + + $this->assertArrayHasKey('link', $resultItem); + $this->assertArrayHasKey('fileGenerationTime', $resultItem); + } +} diff --git a/Test/Unit/Ui/DataProvider/GoogleFeeds/ListingDataProviderTest.php b/Test/Unit/Ui/DataProvider/GoogleFeeds/ListingDataProviderTest.php new file mode 100644 index 0000000..1a901a7 --- /dev/null +++ b/Test/Unit/Ui/DataProvider/GoogleFeeds/ListingDataProviderTest.php @@ -0,0 +1,66 @@ +createMock(ReportingInterface::class); + $searchCriteriaBuilderMock = $this->createMock(SearchCriteriaBuilder::class); + $requestMock = $this->createMock(RequestInterface::class); + $filterBuilderMock = $this->createMock(FilterBuilder::class); + $this->feedRepositoryMock = $this->createMock(FeedRepositoryInterface::class); + + $this->sut = new ListingDataProvider( + $name, + $primaryFieldName, + $requestFieldName, + $reportingMock, + $searchCriteriaBuilderMock, + $requestMock, + $filterBuilderMock, + $this->feedRepositoryMock + ); + } + + public function getEmptyDataTest(): void + { + $this->feedRepositoryMock->method('getList')->willReturn([]); + $expected = [ + 'items' => [], + 'totalRecords' => 0 + ]; + + $this->assertEquals($expected, $this->sut->getData()); + } + + public function testGetDataTest() + { + $item = [ + 'filename' => 'base_store_default_feed.xml', + 'path' => 'media/run_as_root/feed/base_store_default_feed.xml', + 'link' => 'https://local.magento2.com/media/run_as_root/feed/base_store_default_feed.xml', + 'last_generated' => date('Y-m-d H:i:s'), + 'store' => 'default' + ]; + + $this->feedRepositoryMock->method('getList')->willReturn([$item]); + $this->assertArrayHasKey('link', $this->sut->getData()['items'][0]); + } +} diff --git a/Test/Unit/Writer/FileWriterTest.php b/Test/Unit/Writer/FileWriterTest.php index fb97415..e8baf78 100644 --- a/Test/Unit/Writer/FileWriterTest.php +++ b/Test/Unit/Writer/FileWriterTest.php @@ -37,7 +37,7 @@ public function testWrite(): void { $streamMock = $this->getMockBuilder(FileWriteInterface::class)->getMock(); - $destination = 'media/run_as_root/feed/base_store_seidenland_de_feed.xml'; + $destination = 'media/run_as_root/feed/base_store_default_feed.xml'; $this->sut->setDestination($destination); $this->mediaDirectoryMock diff --git a/Test/Unit/Writer/XmlFileWriterProviderTest.php b/Test/Unit/Writer/XmlFileWriterProviderTest.php index ac8f852..b4976c8 100644 --- a/Test/Unit/Writer/XmlFileWriterProviderTest.php +++ b/Test/Unit/Writer/XmlFileWriterProviderTest.php @@ -50,7 +50,7 @@ public function testGet1(): void ->with($storeId) ->willReturn($websiteMock); - $storeCode = 'seidenland_de'; + $storeCode = 'default'; $storeMock->expects($this->once()) ->method('getCode') ->willReturn($storeCode); @@ -67,7 +67,7 @@ public function testGet1(): void $fileWriterMock->expects($this->once()) ->method('setDestination') - ->with('run_as_root/feed/base_store_seidenland_de_feed.xml') + ->with('run_as_root/feed/base_store_default_feed.xml') ->willReturnSelf(); $this->sut->get($storeMock); diff --git a/Ui/DataProvider/GoogleFeeds/ListingDataProvider.php b/Ui/DataProvider/GoogleFeeds/ListingDataProvider.php new file mode 100644 index 0000000..50faad7 --- /dev/null +++ b/Ui/DataProvider/GoogleFeeds/ListingDataProvider.php @@ -0,0 +1,52 @@ +feedRepository = $feedRepository; + } + + public function getData(): array + { + $items = $this->feedRepository->getList(); + return [ + 'items' => $items, + 'totalRecords' => count($items) + ]; + } +} \ No newline at end of file diff --git a/etc/acl.xml b/etc/acl.xml new file mode 100644 index 0000000..b795db6 --- /dev/null +++ b/etc/acl.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/etc/adminhtml/menu.xml b/etc/adminhtml/menu.xml new file mode 100644 index 0000000..59aa866 --- /dev/null +++ b/etc/adminhtml/menu.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/etc/adminhtml/routes.xml b/etc/adminhtml/routes.xml new file mode 100644 index 0000000..781acd5 --- /dev/null +++ b/etc/adminhtml/routes.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml index e306199..beb09cb 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -81,4 +81,9 @@ special_price + + + diff --git a/etc/module.xml b/etc/module.xml index 82c3d91..36626bf 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - + diff --git a/registration.php b/registration.php index 10b99c6..b0ab70d 100644 --- a/registration.php +++ b/registration.php @@ -4,4 +4,8 @@ use Magento\Framework\Component\ComponentRegistrar; -ComponentRegistrar::register(ComponentRegistrar::MODULE, 'RunAsRoot_Feed', __DIR__); +ComponentRegistrar::register( + ComponentRegistrar::MODULE, + 'RunAsRoot_GoogleShoppingFeed', + __DIR__ +); diff --git a/view/adminhtml/layout/run_as_root_google_feeds.xml b/view/adminhtml/layout/run_as_root_google_feeds.xml new file mode 100644 index 0000000..41bd502 --- /dev/null +++ b/view/adminhtml/layout/run_as_root_google_feeds.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/view/adminhtml/ui_component/google_shopping_feed_listing.xml b/view/adminhtml/ui_component/google_shopping_feed_listing.xml new file mode 100644 index 0000000..9a89038 --- /dev/null +++ b/view/adminhtml/ui_component/google_shopping_feed_listing.xml @@ -0,0 +1,54 @@ + ++ + + google_shopping_feed_listing.google_shopping_feed_listing_data_source + google_shopping_feed_listing.google_shopping_feed_listing_data_source + + google_shopping_feed_columns + + + + RunAsRoot\GoogleShoppingFeed\Ui\DataProvider\GoogleFeeds\ListingDataProvider + google_shopping_feed_listing_data_source + filename + filename + + + Magento_Ui/js/grid/provider + + + filename + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file