diff --git a/docs/snippets/advanced-directive-array.xml b/docs/snippets/advanced-directive-array.xml index 6c50bd5..59f49fa 100644 --- a/docs/snippets/advanced-directive-array.xml +++ b/docs/snippets/advanced-directive-array.xml @@ -2,18 +2,18 @@ - Ms. Kassandra Brakus - https://via.placeholder.com/640x480.png/00ddcc?text=accusamus - https://via.placeholder.com/640x480.png/0099aa?text=atque - https://via.placeholder.com/640x480.png/003399?text=excepturi - https://via.placeholder.com/640x480.png/00aacc?text=autem + Dr. Albert Gaylord PhD + https://via.placeholder.com/640x480.png/0033bb?text=repellendus + https://via.placeholder.com/640x480.png/0055cc?text=vel + https://via.placeholder.com/640x480.png/00aaff?text=facere + https://via.placeholder.com/640x480.png/006633?text=rerum - Jermain Gulgowski - https://via.placeholder.com/640x480.png/0055cc?text=qui - https://via.placeholder.com/640x480.png/008877?text=aut - https://via.placeholder.com/640x480.png/00ee66?text=sint - https://via.placeholder.com/640x480.png/003333?text=quaerat + Lia Jerde + https://via.placeholder.com/640x480.png/00cc55?text=cupiditate + https://via.placeholder.com/640x480.png/0055dd?text=ut + https://via.placeholder.com/640x480.png/006633?text=nobis + https://via.placeholder.com/640x480.png/007733?text=dolor diff --git a/docs/snippets/advanced-directive-attributes.php b/docs/snippets/advanced-directive-attributes.php index bea2f08..7241a72 100644 --- a/docs/snippets/advanced-directive-attributes.php +++ b/docs/snippets/advanced-directive-attributes.php @@ -29,9 +29,4 @@ public function item(Model $model): FeedItem { return new AttributesDirectiveFeedItem($model); } - - public function filename(): string - { - return '../../../../../../../../../docs/snippets/advanced-directive-attributes.xml'; - } } diff --git a/docs/snippets/advanced-directive-attributes.xml b/docs/snippets/advanced-directive-attributes.xml index be8ac69..7d4ec20 100644 --- a/docs/snippets/advanced-directive-attributes.xml +++ b/docs/snippets/advanced-directive-attributes.xml @@ -1,16 +1,16 @@ - + https://example.com - Rachelle Stokes - + Emile Kling + - Dr. Chelsie Schroeder Jr. - + Miss Kamille Stracke DDS + diff --git a/docs/snippets/advanced-directive-cdata.xml b/docs/snippets/advanced-directive-cdata.xml index 88d7145..2d0a4e1 100644 --- a/docs/snippets/advanced-directive-cdata.xml +++ b/docs/snippets/advanced-directive-cdata.xml @@ -2,12 +2,12 @@ - Jasper Cassin PhD]]> - rasheed17@example.net + Mortimer Hermiston]]> + lura20@example.net - Jeffrey Kilback DVM]]> - sienna75@example.net + Esta Bins]]> + alessia.bins@example.net diff --git a/docs/snippets/advanced-directive-mixed.xml b/docs/snippets/advanced-directive-mixed.xml index aad8c0b..22e4a00 100644 --- a/docs/snippets/advanced-directive-mixed.xml +++ b/docs/snippets/advanced-directive-mixed.xml @@ -2,17 +2,17 @@ - Israel Shanahan + Dr. Adrien Price DDS Foo - estefania92@example.org + alessandra73@example.com - Dewitt Kessler DDS + Dr. Randall Weber Foo - xfisher@example.com + cristian08@example.org diff --git a/docs/snippets/advanced-directive-value.xml b/docs/snippets/advanced-directive-value.xml index 21dd770..b1e4e7d 100644 --- a/docs/snippets/advanced-directive-value.xml +++ b/docs/snippets/advanced-directive-value.xml @@ -2,12 +2,12 @@ - Icie Crooks - langosh.okey@example.org + Linnie Kuhn + russel.ledner@example.org - Dr. Reta Langosh IV - cecilia35@example.com + Enos Torphy Sr. + sonya44@example.com diff --git a/docs/snippets/advanced-element-attribute.php b/docs/snippets/advanced-element-attribute.php index 27aa1f4..e1801d1 100644 --- a/docs/snippets/advanced-element-attribute.php +++ b/docs/snippets/advanced-element-attribute.php @@ -22,9 +22,4 @@ public function item(Model $model): FeedItem { return new AttributeFeedItem($model); } - - public function filename(): string - { - return '../../../../../../../../../docs/snippets/advanced-element-attribute.xml'; - } } diff --git a/docs/snippets/advanced-element-attribute.xml b/docs/snippets/advanced-element-attribute.xml index e55c0eb..8687ac9 100644 --- a/docs/snippets/advanced-element-attribute.xml +++ b/docs/snippets/advanced-element-attribute.xml @@ -1,13 +1,13 @@ - + 1 - Eriberto Lind + Ara Littel - + 2 - Mr. Michael Reilly + Sylvia Rippin diff --git a/docs/snippets/advanced-element-header-footer.php b/docs/snippets/advanced-element-header-footer.php index 16f00dd..019dd2a 100644 --- a/docs/snippets/advanced-element-header-footer.php +++ b/docs/snippets/advanced-element-header-footer.php @@ -24,9 +24,4 @@ public function footer(): string { return "\nThis is a custom footer element"; } - - public function filename(): string - { - return '../../../../../../../../../docs/snippets/advanced-element-header-footer.xml'; - } } diff --git a/docs/snippets/advanced-element-header-footer.xml b/docs/snippets/advanced-element-header-footer.xml index 645e456..05cd1d9 100644 --- a/docs/snippets/advanced-element-header-footer.xml +++ b/docs/snippets/advanced-element-header-footer.xml @@ -3,11 +3,11 @@ 1 - Prof. Joe Hills + Brayan Schaefer 2 - Alyson Hoppe + Jedidiah Mayer diff --git a/docs/snippets/advanced-element-info.php b/docs/snippets/advanced-element-info.php index a7c163b..0016c42 100644 --- a/docs/snippets/advanced-element-info.php +++ b/docs/snippets/advanced-element-info.php @@ -21,9 +21,4 @@ public function info(): FeedInfo { return new InfoMethodFeedInfo; } - - public function filename(): string - { - return '../../../../../../../../../docs/snippets/advanced-element-info.xml'; - } } diff --git a/docs/snippets/advanced-element-info.xml b/docs/snippets/advanced-element-info.xml index e22f202..5469fdd 100644 --- a/docs/snippets/advanced-element-info.xml +++ b/docs/snippets/advanced-element-info.xml @@ -6,11 +6,11 @@ 1 - Millie Predovic + Dr. Aurelio Hermann DDS 2 - Dominic Mitchell Sr. + Gardner Farrell diff --git a/docs/snippets/advanced-element-root.php b/docs/snippets/advanced-element-root.php index 30a33a7..8c0fa36 100644 --- a/docs/snippets/advanced-element-root.php +++ b/docs/snippets/advanced-element-root.php @@ -29,9 +29,4 @@ public function root(): ElementData ] ); } - - public function filename(): string - { - return '../../../../../../../../../docs/snippets/advanced-element-root.xml'; - } } diff --git a/docs/snippets/advanced-element-root.xml b/docs/snippets/advanced-element-root.xml index fe893a8..3a7bcd1 100644 --- a/docs/snippets/advanced-element-root.xml +++ b/docs/snippets/advanced-element-root.xml @@ -3,11 +3,11 @@ 1 - Merle Kulas + Emilie Rosenbaum 2 - Prof. Tristin Hahn Jr. + Gail Lindgren diff --git a/docs/snippets/receipt-instagram-feed-item.php b/docs/snippets/receipt-instagram-feed-item.php index 5827ae5..80ace7f 100644 --- a/docs/snippets/receipt-instagram-feed-item.php +++ b/docs/snippets/receipt-instagram-feed-item.php @@ -5,8 +5,10 @@ namespace App\Feeds\Items; use DragonCode\LaravelFeed\Feeds\Items\FeedItem; +use Illuminate\Support\Arr; -use function route; +use function collect; +use function fake; /** @property-read \App\Models\Product $model */ class InstagramFeedItem extends FeedItem @@ -19,21 +21,48 @@ public function name(): string public function toArray(): array { return [ - 'g:id' => $this->model->id, - 'g:title' => $this->model->title, + 'g:id' => $this->model->id, - 'g:description' => [ - '@cdata' => $this->model->description, - ], - - 'g:brand' => $this->model->brand, + 'g:title' => ['@cdata' => $this->model->title], + 'g:description' => ['@cdata' => $this->model->description], 'g:link' => route('products.show', $this->model->slug), - 'g:image_link' => $this->model->image, + 'g:image_link' => $this->firstImage(), + + '@g:additional_image_link' => $this->images(), + + 'g:brand' => $this->model->brand, + 'g:condition' => 'new', + 'g:availability' => 'in stock', + + 'g:price' => $this->model->price, + 'g:sale_price' => $this->model->price, + + 'g:item_group_id' => 12345, + + 'g:status' => 'active', + + 'g:color' => ['@cdata' => fake()->colorName()], + + 'g:size' => fake()->numberBetween(10, 50), - 'g:availability' => $this->model->quantity ? 'in stock' : 'out of stock', - 'g:status' => $this->model->quantity ? 'active' : 'inactive', - 'g:price' => $this->model->price, + 'g:age_group' => 'adult', + + 'g:material' => ['@cdata' => fake()->word()], + 'g:pattern' => ['@cdata' => 'regular'], + + 'g:google_product_category' => 1000, + 'g:fb_product_category' => 2000, ]; } + + protected function firstImage(): string + { + return Arr::first($this->model->images); + } + + protected function images(): array + { + return collect($this->model->images)->skip(1)->all(); + } } diff --git a/docs/snippets/receipt-instagram-feed.php b/docs/snippets/receipt-instagram-feed.php index 4c45f37..800f197 100644 --- a/docs/snippets/receipt-instagram-feed.php +++ b/docs/snippets/receipt-instagram-feed.php @@ -4,14 +4,14 @@ namespace App\Feeds; +use App\Feeds\Items\InstagramFeedItem; use App\Models\Product; +use DragonCode\LaravelFeed\Data\ElementData; use DragonCode\LaravelFeed\Feeds\Feed; use DragonCode\LaravelFeed\Feeds\Items\FeedItem; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; -use function config; - class InstagramFeed extends Feed { public function builder(): Builder @@ -19,6 +19,11 @@ public function builder(): Builder return Product::query(); } + public function root(): ElementData + { + return new ElementData('offers'); + } + public function header(): string { $name = config('app.name'); @@ -38,13 +43,13 @@ public function footer(): string return "\n\n"; } - public function filename(): string + public function item(Model $model): FeedItem { - return 'instagram.xml'; + return new InstagramFeedItem($model); } - public function item(Model $model): FeedItem + public function filename(): string { - return new Items\InstagramFeedItem($model); + return 'instagram.xml'; } } diff --git a/docs/snippets/receipt-instagram-feed.xml b/docs/snippets/receipt-instagram-feed.xml new file mode 100644 index 0000000..aa12111 --- /dev/null +++ b/docs/snippets/receipt-instagram-feed.xml @@ -0,0 +1,57 @@ + + + Laravel + https://example.com + + + + 1 + + + https://example.com/products/quaerat-voluptatem-consequuntur-cumque-aut-sit-dolorem + https://via.placeholder.com/640x480.png/00ff22?text=esse + https://via.placeholder.com/640x480.png/007788?text=ea + https://via.placeholder.com/640x480.png/006644?text=eveniet + explicabo + new + in stock + 527 + 527 + 12345 + active + + 45 + adult + + + 1000 + 2000 + + + 2 + + + https://example.com/products/et-non-neque-molestias-in + https://via.placeholder.com/640x480.png/00ffee?text=totam + https://via.placeholder.com/640x480.png/0044ff?text=voluptatem + https://via.placeholder.com/640x480.png/00aabb?text=expedita + quis + new + in stock + 864 + 864 + 12345 + active + + 29 + adult + + + 1000 + 2000 + + + + + + \ No newline at end of file diff --git a/docs/snippets/receipt-instagram-result.xml b/docs/snippets/receipt-instagram-result.xml deleted file mode 100644 index 7dabc92..0000000 --- a/docs/snippets/receipt-instagram-result.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - Laravel - https://example.com - - 1 - Inventore Vero Commodi - - Rempel PLC - https://example.com/products/ratione-deserunt-eum-qui-quia-eligendi-omnis-praesentium-ipsam - https://via.placeholder.com/640x480.png/007700?text=sed - in stock - active - 427 - - - 2 - Ipsam Beatae Corporis - - Bosco Inc - https://example.com/products/exercitationem-corrupti-a-consectetur-nisi-maiores-odit - https://via.placeholder.com/640x480.png/00ff55?text=molestias - in stock - active - 242 - - - 3 - Dicta Vel Nisi - - Kihn Inc - https://example.com/products/dolorem-dolorem-dolores-repellat-ducimus - https://via.placeholder.com/640x480.png/007733?text=enim - in stock - active - 240 - - - 4 - Qui Expedita Dolores - - Ferry-Lesch - https://example.com/products/sed-commodi-cumque-modi-qui - https://via.placeholder.com/640x480.png/007744?text=veritatis - in stock - active - 378 - - - 5 - Beatae Quas Aut - - Tromp, Ratke and Wyman - https://example.com/products/neque-quia-laborum-eius-ipsum-architecto-unde-nobis - https://via.placeholder.com/640x480.png/004466?text=nam - in stock - active - 166 - - - 6 - Magni Quibusdam Architecto - - Weissnat Group - https://example.com/products/iure-qui-alias-ipsum - https://via.placeholder.com/640x480.png/00cc11?text=sint - in stock - active - 362 - - - 7 - Fugit Qui Vitae - - Kilback Inc - https://example.com/products/rerum-pariatur-quae-dolorem-numquam-est - https://via.placeholder.com/640x480.png/00bb77?text=doloribus - in stock - active - 355 - - - 8 - Tempora Praesentium Vitae - - Bayer-Dach - https://example.com/products/qui-voluptate-et-est-ullam-magnam-et - https://via.placeholder.com/640x480.png/009955?text=expedita - in stock - active - 562 - - - 9 - Alias Cupiditate Ea - - Gorczany LLC - https://example.com/products/dolorem-architecto-voluptas-odio-nulla-et-possimus-temporibus - https://via.placeholder.com/640x480.png/00ddaa?text=necessitatibus - in stock - active - 683 - - - 10 - Quis Excepturi Sit - - Gorczany, Turner and Hansen - https://example.com/products/consectetur-nam-asperiores-nisi-sit-odit - https://via.placeholder.com/640x480.png/00dd55?text=sit - in stock - active - 978 - - - diff --git a/docs/snippets/receipt-sitemap-feed-item.php b/docs/snippets/receipt-sitemap-feed-item.php index d8255d8..8d6f88a 100644 --- a/docs/snippets/receipt-sitemap-feed-item.php +++ b/docs/snippets/receipt-sitemap-feed-item.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Feeds\Items\Sitemaps; +namespace App\Feeds\Sitemaps\Items; use DragonCode\LaravelFeed\Feeds\Items\FeedItem; diff --git a/docs/snippets/receipt-sitemap-feed.php b/docs/snippets/receipt-sitemap-feed.php index 6abc69c..1821b67 100644 --- a/docs/snippets/receipt-sitemap-feed.php +++ b/docs/snippets/receipt-sitemap-feed.php @@ -4,7 +4,7 @@ namespace App\Feeds\Sitemaps; -use App\Feeds\Items\Sitemaps\ProductFeedItem; +use App\Feeds\Sitemaps\Items\ProductFeedItem; use App\Models\Product; use DragonCode\LaravelFeed\Data\ElementData; use DragonCode\LaravelFeed\Feeds\Feed; @@ -32,18 +32,18 @@ public function builder(): Builder public function root(): ElementData { return new ElementData( - $this->name, - $this->attributes + name : $this->name, + attributes: $this->attributes, ); } - public function filename(): string + public function item(Model $model): FeedItem { - return 'sitemaps/products.xml'; + return new ProductFeedItem($model); } - public function item(Model $model): FeedItem + public function filename(): string { - return new ProductFeedItem($model); + return 'sitemaps/products.xml'; } } diff --git a/docs/snippets/receipt-sitemap-feed.xml b/docs/snippets/receipt-sitemap-feed.xml new file mode 100644 index 0000000..96916a5 --- /dev/null +++ b/docs/snippets/receipt-sitemap-feed.xml @@ -0,0 +1,15 @@ + + + + + https://example.com/products/aliquid-sed-velit-consectetur-sunt-consequuntur-atque-ut + 2025-09-04T04:08:12+00:00 + 0.9 + + + https://example.com/products/nam-vitae-autem-dolorum-dolores-impedit-velit + 2025-09-04T04:08:12+00:00 + 0.9 + + + diff --git a/docs/snippets/receipt-sitemap-result.xml b/docs/snippets/receipt-sitemap-result.xml deleted file mode 100644 index d72bd21..0000000 --- a/docs/snippets/receipt-sitemap-result.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - https://example.com/products/deleniti-tempora-iure-et - 2025-08-30T19:57:10+00:00 - 0.9 - - - https://example.com/products/beatae-itaque-sit-odit-enim-id-voluptatum-reiciendis-eos - 2025-08-30T19:57:10+00:00 - 0.9 - - - https://example.com/products/rem-pariatur-tenetur-perferendis-nesciunt - 2025-08-30T19:57:10+00:00 - 0.9 - - - https://example.com/products/minus-porro-aut-quidem-quos-excepturi-totam - 2025-08-30T19:57:10+00:00 - 0.9 - - - https://example.com/products/amet-possimus-temporibus-non-consequatur-doloremque-dolorem-voluptas - 2025-08-30T19:57:10+00:00 - 0.9 - - diff --git a/docs/snippets/receipt-yandex-feed-info.php b/docs/snippets/receipt-yandex-feed-info.php index 154a236..12cd717 100644 --- a/docs/snippets/receipt-yandex-feed-info.php +++ b/docs/snippets/receipt-yandex-feed-info.php @@ -39,10 +39,6 @@ public function toArray(): array '@attributes' => ['id' => 539], '@value' => 'Велосипедки', ], - [ - '@attributes' => ['id' => 44], - '@value' => 'Ремни', - ], ], ], ]; diff --git a/docs/snippets/receipt-yandex-feed-item.php b/docs/snippets/receipt-yandex-feed-item.php index 31b2f18..a0f1313 100644 --- a/docs/snippets/receipt-yandex-feed-item.php +++ b/docs/snippets/receipt-yandex-feed-item.php @@ -6,8 +6,6 @@ use DragonCode\LaravelFeed\Feeds\Items\FeedItem; -use function route; - /** @property-read \App\Models\Product $model */ class YandexFeedItem extends FeedItem { diff --git a/docs/snippets/receipt-yandex-feed.php b/docs/snippets/receipt-yandex-feed.php index a11db2e..e207595 100644 --- a/docs/snippets/receipt-yandex-feed.php +++ b/docs/snippets/receipt-yandex-feed.php @@ -4,6 +4,8 @@ namespace App\Feeds; +use App\Feeds\Info\YandexFeedInfo; +use App\Feeds\Items\YandexFeedItem; use App\Models\Product; use DragonCode\LaravelFeed\Data\ElementData; use DragonCode\LaravelFeed\Feeds\Feed; @@ -42,16 +44,16 @@ public function footer(): string public function info(): FeedInfo { - return new Info\YandexFeedInfo; + return new YandexFeedInfo; } - public function filename(): string + public function item(Model $model): FeedItem { - return 'yandex.xml'; + return new YandexFeedItem($model); } - public function item(Model $model): FeedItem + public function filename(): string { - return new Items\YandexFeedItem($model); + return 'yandex.xml'; } } diff --git a/docs/snippets/receipt-yandex-feed.xml b/docs/snippets/receipt-yandex-feed.xml new file mode 100644 index 0000000..d0c7d43 --- /dev/null +++ b/docs/snippets/receipt-yandex-feed.xml @@ -0,0 +1,54 @@ + + + + + +Laravel +Laravel +Laravel +https://example.com +test@example.com + + + + + Домашние майки + Велосипедки + + + + https://example.com/products/repellendus-cum-doloribus-quo-ad-odio-eum + GD-T[LF&quot;JWL + quo eveniet accusantium omnis + Asperiores officiis ex doloremque deleniti. Inventore in odit assumenda laborum blanditiis reiciendis. Est quo id ad excepturi voluptatem nisi. Qui voluptatum omnis iure sint dolor aperiam omnis. + true + 613 + RUR + non + https://via.placeholder.com/640x480.png/0088aa?text=perspiciatis + https://via.placeholder.com/640x480.png/0000ff?text=blanditiis + https://via.placeholder.com/640x480.png/00eedd?text=quisquam + GD-T[LF"JWL + 0 + male + + + https://example.com/products/temporibus-corrupti-illo-ad-vel-et + GD-*^FQIZ%K + velit ut blanditiis omnis + Doloribus dolorem omnis est commodi nam deleniti tempore. Non voluptates illum quis. Ab possimus quidem soluta ut officia. Voluptatem iste ipsa quia impedit ratione. + true + 142 + RUR + est + https://via.placeholder.com/640x480.png/0088aa?text=alias + https://via.placeholder.com/640x480.png/00ee22?text=iusto + https://via.placeholder.com/640x480.png/00bb55?text=ducimus + GD-*^FQIZ%K + 8 + male + + + + + \ No newline at end of file diff --git a/docs/snippets/receipt-yandex-result.xml b/docs/snippets/receipt-yandex-result.xml deleted file mode 100644 index 3f37e82..0000000 --- a/docs/snippets/receipt-yandex-result.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - Laravel - Laravel - Laravel - https://example.com - - - - - - Домашние майки - Велосипедки - Ремни - - - - - https://example.com/products/quia-inventore-explicabo-aut-est-et-deserunt - GD-A - Itaque Beatae At - Cum fugiat eos consequatur libero enim occaecati dolores et. Voluptas illo quia facere provident maxime. - true - 935 - RUR - Ryan-Dach - https://via.placeholder.com/640x480.png/00dd00?text=voluptatem - https://via.placeholder.com/640x480.png/00cc44?text=aspernatur - https://via.placeholder.com/640x480.png/00bbdd?text=numquam - GD-A - 0 - female - - - https://example.com/products/iste-reprehenderit-nihil-earum-quod-autem-tempora - GD-QUI - Porro Est Sed - Velit commodi est qui dolorem quo. Repellendus consequatur qui et aliquam soluta vel. Quis est possimus laudantium rerum sit. - true - 316 - RUR - King-Jones - https://via.placeholder.com/640x480.png/00bbdd?text=magnam - https://via.placeholder.com/640x480.png/0088cc?text=consequatur - https://via.placeholder.com/640x480.png/00dd99?text=excepturi - GD-QUI - 9 - female - - - https://example.com/products/aspernatur-omnis-aut-libero-vitae-officiis-facere-est - GD-PERSPICIATIS - Soluta Possimus Exercitationem - Numquam non vel et. Corporis voluptatem omnis ducimus laudantium sit quis quia. Voluptas ad ex saepe veniam sit voluptate. Voluptatem perspiciatis exercitationem exercitationem tempora. - true - 965 - RUR - Hauck, Koepp and Beatty - https://via.placeholder.com/640x480.png/005599?text=consequatur - https://via.placeholder.com/640x480.png/002288?text=voluptate - https://via.placeholder.com/640x480.png/00cc33?text=in - GD-PERSPICIATIS - 3 - female - - - https://example.com/products/cumque-aut-fugit-quia - GD-NON - Ipsum Consequuntur Nostrum - Quia accusantium minus maiores vero debitis. Id magni commodi id recusandae. Doloremque et animi dolore. - true - 716 - RUR - Steuber PLC - https://via.placeholder.com/640x480.png/0044ee?text=voluptatibus - https://via.placeholder.com/640x480.png/00ffaa?text=est - https://via.placeholder.com/640x480.png/0033bb?text=incidunt - GD-NON - 5 - male - - - https://example.com/products/rerum-vel-excepturi-est-non-est - GD-VOLUPTATEM - Rerum Aut Ut - Rerum velit sit soluta vitae numquam. Dolor at ut repellat ut sit fugiat ea molestias. Atque omnis aut amet ut deserunt et autem. Voluptatem deleniti beatae quia sapiente ipsum incidunt. - true - 877 - RUR - Cruickshank, Jerde and Walker - https://via.placeholder.com/640x480.png/008899?text=fuga - https://via.placeholder.com/640x480.png/00bbaa?text=quia - https://via.placeholder.com/640x480.png/0022aa?text=architecto - GD-VOLUPTATEM - 5 - male - - - https://example.com/products/consequatur-expedita-et-et-laudantium-alias-ipsam - GD-NIHIL - Asperiores Cupiditate Non - Quia nobis voluptas perferendis. Repellendus veritatis labore voluptates mollitia error sunt. Nobis veritatis iure repudiandae accusamus ipsum odit. Rerum minima est adipisci assumenda dolores omnis. - true - 954 - RUR - Howell-Hauck - https://via.placeholder.com/640x480.png/007799?text=adipisci - https://via.placeholder.com/640x480.png/001122?text=dolor - https://via.placeholder.com/640x480.png/0033ee?text=fuga - GD-NIHIL - 9 - female - - - https://example.com/products/voluptatem-eligendi-qui-id-quia-qui - GD-BEATAE - Eos Dolorem Quibusdam - Inventore nulla optio inventore illum alias repellendus a. Et veniam ut earum tempora corporis. A quia ullam laborum. Et qui ut et corporis. - true - 681 - RUR - Becker, Schoen and Ankunding - https://via.placeholder.com/640x480.png/0011aa?text=impedit - https://via.placeholder.com/640x480.png/00aacc?text=nesciunt - https://via.placeholder.com/640x480.png/0011ee?text=veritatis - GD-BEATAE - 6 - female - - - https://example.com/products/et-provident-eaque-odio-ut-esse-ipsa-quisquam - GD-UT - Officia Nihil Maxime - Aut mollitia nostrum cum voluptatum. Accusamus qui voluptatem voluptas delectus iure enim facere. Provident quidem ipsam quis alias. - true - 795 - RUR - Windler Inc - https://via.placeholder.com/640x480.png/008899?text=qui - https://via.placeholder.com/640x480.png/007733?text=molestiae - https://via.placeholder.com/640x480.png/002222?text=dolores - GD-UT - 4 - female - - - https://example.com/products/aut-tempora-et-animi-sit-aliquam - GD-DOLOR - Odio Tempora Iusto - Non qui temporibus sed rerum non nihil. Consequuntur earum velit cupiditate ex. Magnam tenetur illo tempore saepe tenetur sint. Molestiae sint dicta eius ipsam. Tempora consequatur quam ut ut et. - true - 347 - RUR - Rolfson, Kub and Quigley - https://via.placeholder.com/640x480.png/00dd33?text=similique - https://via.placeholder.com/640x480.png/005577?text=quas - https://via.placeholder.com/640x480.png/007744?text=eum - GD-DOLOR - 1 - female - - - https://example.com/products/quam-aut-hic-corporis-ab-rem-rerum-quae - GD-IPSA - Perferendis Commodi Laborum - Expedita officia illum explicabo numquam voluptas ut a earum. Amet ratione fuga non. Et voluptatem velit reprehenderit. - true - 574 - RUR - Konopelski-Dicki - https://via.placeholder.com/640x480.png/003333?text=quis - https://via.placeholder.com/640x480.png/00cc88?text=necessitatibus - https://via.placeholder.com/640x480.png/0099ee?text=unde - GD-IPSA - 3 - female - - - - diff --git a/docs/topics/receipt-instagram.topic b/docs/topics/receipt-instagram.topic index 3090706..3de94d9 100644 --- a/docs/topics/receipt-instagram.topic +++ b/docs/topics/receipt-instagram.topic @@ -35,6 +35,6 @@ - + diff --git a/docs/topics/receipt-sitemap.topic b/docs/topics/receipt-sitemap.topic index 54e5c07..5289503 100644 --- a/docs/topics/receipt-sitemap.topic +++ b/docs/topics/receipt-sitemap.topic @@ -56,7 +56,7 @@ - + diff --git a/docs/topics/receipt-yandex.topic b/docs/topics/receipt-yandex.topic index b540e34..7a19f1c 100644 --- a/docs/topics/receipt-yandex.topic +++ b/docs/topics/receipt-yandex.topic @@ -39,6 +39,6 @@ - + diff --git a/tests/Feature/Docs/ReceiptTest.php b/tests/Feature/Docs/ReceiptTest.php new file mode 100644 index 0000000..21177ca --- /dev/null +++ b/tests/Feature/Docs/ReceiptTest.php @@ -0,0 +1,78 @@ +count(2)->create(); + + $model = Feed::create([ + 'class' => $feed, + 'title' => $feed, + ]); + + artisan(FeedGenerateCommand::class, ['feed' => $model->id]) + ->assertSuccessful() + ->run(); + + foreach ($files as $from => $to) { + copyFeedFileToDoc($from, $to, $replaces, false); + } +})->with([ + 'sitemap' => [ + 'feed' => ReceiptSitemapFeed::class, + + 'files' => [ + 'ReceiptSitemapFeed' => 'receipt-sitemap-feed.php', + 'Items/ReceiptSitemapFeedItem' => 'receipt-sitemap-feed-item.php', + ], + + 'replaces' => [ + 'ReceiptSitemapFeed' => 'ProductFeed', + 'Workbench\App\Feeds\Docs' => 'App\Feeds\Sitemaps', + + '../../../../../../../../../docs/snippets/receipt-sitemap-feed.xml' => 'sitemaps/products.xml', + ], + ], + + 'yandex' => [ + 'feed' => ReceiptYandexFeed::class, + + 'files' => [ + 'ReceiptYandexFeed' => 'receipt-yandex-feed.php', + 'Info/ReceiptYandexFeedInfo' => 'receipt-yandex-feed-info.php', + 'Items/ReceiptYandexFeedItem' => 'receipt-yandex-feed-item.php', + ], + + 'replaces' => [ + 'ReceiptYandexFeed' => 'YandexFeed', + 'Workbench\App\Feeds\Docs' => 'App\Feeds', + + '../../../../../../../../../docs/snippets/receipt-yandex-feed.xml' => 'yandex.xml', + ], + ], + + 'instagram' => [ + 'feed' => ReceiptInstagramFeed::class, + + 'files' => [ + 'ReceiptInstagramFeed' => 'receipt-instagram-feed.php', + 'Items/ReceiptInstagramFeedItem' => 'receipt-instagram-feed-item.php', + ], + + 'replaces' => [ + 'ReceiptInstagramFeed' => 'InstagramFeed', + 'Workbench\App\Feeds\Docs' => 'App\Feeds', + + '../../../../../../../../../docs/snippets/receipt-instagram-feed.xml' => 'instagram.xml', + ], + ], +]); diff --git a/tests/Helpers/docs.php b/tests/Helpers/docs.php index bf680f6..7bb3cc6 100644 --- a/tests/Helpers/docs.php +++ b/tests/Helpers/docs.php @@ -4,20 +4,32 @@ use function Orchestra\Testbench\workbench_path; -function copyFeedFileToDoc(string $source, string $target): void +function copyFeedFileToDoc(string $source, string $target, array $replaces = [], bool $cutFilename = true): void { $sourceFile = workbench_path('app/Feeds/Docs/' . $source . '.php'); $targetFile = __DIR__ . '/../../docs/snippets/' . $target; $content = file_get_contents($sourceFile); + if (! empty($replaces)) { + $content = str_replace( + array_keys($replaces), + array_values($replaces), + $content + ); + } + $content = str_replace([ - 'Workbench\App\Models\User', 'Workbench\App\Feeds\Docs', + 'Workbench\App\\', ], [ - 'App\Models\User', 'App\Feeds', + 'App\\', ], $content); + if ($cutFilename) { + $content = preg_replace('/(\n\s+public\sfunction\sfilename\(\):\sstring\n\s+{\n\s+.*\n\s+})/', '', $content); + } + file_put_contents($targetFile, $content); } diff --git a/workbench/app/Feeds/Docs/Info/ReceiptYandexFeedInfo.php b/workbench/app/Feeds/Docs/Info/ReceiptYandexFeedInfo.php new file mode 100644 index 0000000..2b26aa3 --- /dev/null +++ b/workbench/app/Feeds/Docs/Info/ReceiptYandexFeedInfo.php @@ -0,0 +1,46 @@ + config('app.name'), + 'company' => config('app.name'), + 'platform' => config('app.name'), + + 'url' => config('app.url'), + 'email' => config('emails.manager'), + + 'currencies' => [ + '@currency' => [ + [ + '@attributes' => [ + 'id' => 'RUR', + 'rate' => '1', + ], + ], + ], + ], + + 'categories' => [ + '@category' => [ + [ + '@attributes' => ['id' => 41], + '@value' => 'Домашние майки', + ], + [ + '@attributes' => ['id' => 539], + '@value' => 'Велосипедки', + ], + ], + ], + ]; + } +} diff --git a/workbench/app/Feeds/Docs/Items/ReceiptInstagramFeedItem.php b/workbench/app/Feeds/Docs/Items/ReceiptInstagramFeedItem.php new file mode 100644 index 0000000..3ad3ac0 --- /dev/null +++ b/workbench/app/Feeds/Docs/Items/ReceiptInstagramFeedItem.php @@ -0,0 +1,68 @@ + $this->model->id, + + 'g:title' => ['@cdata' => $this->model->title], + 'g:description' => ['@cdata' => $this->model->description], + + 'g:link' => route('products.show', $this->model->slug), + 'g:image_link' => $this->firstImage(), + + '@g:additional_image_link' => $this->images(), + + 'g:brand' => $this->model->brand, + 'g:condition' => 'new', + 'g:availability' => 'in stock', + + 'g:price' => $this->model->price, + 'g:sale_price' => $this->model->price, + + 'g:item_group_id' => 12345, + + 'g:status' => 'active', + + 'g:color' => ['@cdata' => fake()->colorName()], + + 'g:size' => fake()->numberBetween(10, 50), + + 'g:age_group' => 'adult', + + 'g:material' => ['@cdata' => fake()->word()], + 'g:pattern' => ['@cdata' => 'regular'], + + 'g:google_product_category' => 1000, + 'g:fb_product_category' => 2000, + ]; + } + + protected function firstImage(): string + { + return Arr::first($this->model->images); + } + + protected function images(): array + { + return collect($this->model->images)->skip(1)->all(); + } +} diff --git a/workbench/app/Feeds/Docs/Items/ReceiptSitemapFeedItem.php b/workbench/app/Feeds/Docs/Items/ReceiptSitemapFeedItem.php new file mode 100644 index 0000000..e518781 --- /dev/null +++ b/workbench/app/Feeds/Docs/Items/ReceiptSitemapFeedItem.php @@ -0,0 +1,29 @@ + route('products.show', $this->model->slug), + + 'lastmod' => $this->model->updated_at->toIso8601String(), + + 'priority' => 0.9, + ]; + } +} diff --git a/workbench/app/Feeds/Docs/Items/ReceiptYandexFeedItem.php b/workbench/app/Feeds/Docs/Items/ReceiptYandexFeedItem.php new file mode 100644 index 0000000..5127238 --- /dev/null +++ b/workbench/app/Feeds/Docs/Items/ReceiptYandexFeedItem.php @@ -0,0 +1,61 @@ + $this->model->id, + + 'available' => ! empty($this->model->quantity) ? 'true' : 'false', + + 'type' => 'vendor.model', + ]; + } + + public function toArray(): array + { + return [ + 'url' => route('products.show', $this->model->slug), + + 'barcode' => $this->model->article, + 'name' => $this->model->title, + 'description' => $this->model->description, + + 'delivery' => 'true', + 'price' => $this->model->price, + + 'currencyId' => 'RUR', + 'vendor' => $this->model->brand, + + '@picture' => $this->model->images, + + '@param' => [ + [ + '@attributes' => ['name' => 'Артикул'], + '@value' => $this->model->article, + ], + [ + '@attributes' => ['name' => 'Код цвета'], + '@value' => fake()->randomDigit(), + ], + [ + '@attributes' => ['name' => 'Пол'], + '@value' => fake()->boolean() ? 'male' : 'female', + ], + ], + ]; + } +} diff --git a/workbench/app/Feeds/Docs/ReceiptInstagramFeed.php b/workbench/app/Feeds/Docs/ReceiptInstagramFeed.php new file mode 100644 index 0000000..afa70d0 --- /dev/null +++ b/workbench/app/Feeds/Docs/ReceiptInstagramFeed.php @@ -0,0 +1,55 @@ + + + $name + $url + + XML; + } + + public function footer(): string + { + return "\n\n"; + } + + public function item(Model $model): FeedItem + { + return new ReceiptInstagramFeedItem($model); + } + + public function filename(): string + { + return '../../../../../../../../../docs/snippets/receipt-instagram-feed.xml'; + } +} diff --git a/workbench/app/Feeds/Docs/ReceiptSitemapFeed.php b/workbench/app/Feeds/Docs/ReceiptSitemapFeed.php new file mode 100644 index 0000000..8f1c969 --- /dev/null +++ b/workbench/app/Feeds/Docs/ReceiptSitemapFeed.php @@ -0,0 +1,49 @@ + 'http://www.sitemaps.org/schemas/sitemap/0.9', + 'xmlns:xhtml' => 'http://www.w3.org/1999/xhtml', + 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1', + 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1', + 'xmlns:news' => 'http://www.google.com/schemas/sitemap-news/0.9', + ]; + + public function builder(): Builder + { + return Product::query(); + } + + public function root(): ElementData + { + return new ElementData( + name : $this->name, + attributes: $this->attributes, + ); + } + + public function item(Model $model): FeedItem + { + return new ReceiptSitemapFeedItem($model); + } + + public function filename(): string + { + return '../../../../../../../../../docs/snippets/receipt-sitemap-feed.xml'; + } +} diff --git a/workbench/app/Feeds/Docs/ReceiptYandexFeed.php b/workbench/app/Feeds/Docs/ReceiptYandexFeed.php new file mode 100644 index 0000000..1526b81 --- /dev/null +++ b/workbench/app/Feeds/Docs/ReceiptYandexFeed.php @@ -0,0 +1,59 @@ +toIso8601String(); + + return << + + + XML; + } + + public function footer(): string + { + return "\n"; + } + + public function info(): FeedInfo + { + return new ReceiptYandexFeedInfo; + } + + public function item(Model $model): FeedItem + { + return new ReceiptYandexFeedItem($model); + } + + public function filename(): string + { + return '../../../../../../../../../docs/snippets/receipt-yandex-feed.xml'; + } +} diff --git a/workbench/app/Models/Product.php b/workbench/app/Models/Product.php index b3aee87..57e2f7f 100644 --- a/workbench/app/Models/Product.php +++ b/workbench/app/Models/Product.php @@ -15,6 +15,7 @@ class Product extends Model use HasFactory; protected $fillable = [ + 'slug', 'article', 'title', 'description', diff --git a/workbench/database/factories/ProductFactory.php b/workbench/database/factories/ProductFactory.php index 9015532..dfe949c 100644 --- a/workbench/database/factories/ProductFactory.php +++ b/workbench/database/factories/ProductFactory.php @@ -7,6 +7,8 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; +use function fake; + class ProductFactory extends Factory { public function definition(): array @@ -14,6 +16,7 @@ public function definition(): array return [ 'article' => Str::of(fake()->unique()->password(4, 8))->upper()->prepend('GD-')->toString(), + 'slug' => fake()->unique()->slug(), 'title' => fake()->unique()->words(4, true), 'description' => fake()->text(), 'brand' => fake()->word(), diff --git a/workbench/database/migrations/2025_08_30_235243_create_products_table.php b/workbench/database/migrations/2025_08_30_235243_create_products_table.php index c9db018..3695d3d 100644 --- a/workbench/database/migrations/2025_08_30_235243_create_products_table.php +++ b/workbench/database/migrations/2025_08_30_235243_create_products_table.php @@ -12,6 +12,7 @@ public function up(): void Schema::create('products', static function (Blueprint $table) { $table->id(); + $table->string('slug')->unique(); $table->string('article'); $table->string('title');