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"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');