From b1667e1ff8997062fd0b2c72d3459c9aaa091638 Mon Sep 17 00:00:00 2001 From: Andrey Helldar Date: Fri, 5 Sep 2025 04:31:10 +0300 Subject: [PATCH] Added the Progress Bar output switch when starting the formation of feeds --- config/feeds.php | 15 ++++++ docs/snippets/advanced-directive-array.xml | 20 ++++---- .../advanced-directive-attributes.xml | 10 ++-- docs/snippets/advanced-directive-cdata.xml | 8 ++-- docs/snippets/advanced-directive-mixed.xml | 8 ++-- docs/snippets/advanced-directive-value.xml | 8 ++-- docs/snippets/advanced-element-attribute.xml | 8 ++-- .../advanced-element-header-footer.xml | 4 +- .../advanced-element-info-before-false.xml | 4 +- docs/snippets/advanced-element-info.xml | 4 +- docs/snippets/advanced-element-root.xml | 4 +- docs/snippets/receipt-instagram-feed.xml | 48 +++++++++---------- docs/snippets/receipt-sitemap-feed.xml | 4 +- docs/snippets/receipt-yandex-feed.xml | 46 +++++++++--------- src/Commands/FeedGenerateCommand.php | 24 ++++++++-- src/Services/GeneratorService.php | 24 ++++++---- .../Console/Generation/ProgressBarTest.php | 20 ++++++++ 17 files changed, 160 insertions(+), 99 deletions(-) create mode 100644 tests/Feature/Console/Generation/ProgressBarTest.php diff --git a/config/feeds.php b/config/feeds.php index e51840f..6606358 100644 --- a/config/feeds.php +++ b/config/feeds.php @@ -51,4 +51,19 @@ */ 'background' => (bool) env('FEED_SCHEDULE_RUN_BACKGROUND', true), ], + + /** + * Console display options. + */ + 'console' => [ + /** + * Enables a progress bar when generating feeds in the console. + * + * When set to true, the feed:generate command will display a + * progress bar showing the execution progress. + * + * Default is false. + */ + 'progress_bar' => (bool) env('FEED_CONSOLE_PROGRESS_BAR_ENABLED', false), + ], ]; diff --git a/docs/snippets/advanced-directive-array.xml b/docs/snippets/advanced-directive-array.xml index cefa69b..119ffcb 100644 --- a/docs/snippets/advanced-directive-array.xml +++ b/docs/snippets/advanced-directive-array.xml @@ -2,18 +2,18 @@ - Hanna Kertzmann - https://via.placeholder.com/640x480.png/006633?text=voluptatem - https://via.placeholder.com/640x480.png/00cc33?text=neque - https://via.placeholder.com/640x480.png/00bbee?text=nisi - https://via.placeholder.com/640x480.png/00ccbb?text=quia + Kayley Hermann + https://via.placeholder.com/640x480.png/00aa77?text=eos + https://via.placeholder.com/640x480.png/00ff66?text=voluptatem + https://via.placeholder.com/640x480.png/00ee33?text=qui + https://via.placeholder.com/640x480.png/005555?text=aut - Maximus Russel - https://via.placeholder.com/640x480.png/000088?text=sint - https://via.placeholder.com/640x480.png/00cc44?text=natus - https://via.placeholder.com/640x480.png/007788?text=vel - https://via.placeholder.com/640x480.png/00aaff?text=excepturi + Dr. Alek Stamm PhD + https://via.placeholder.com/640x480.png/0077dd?text=necessitatibus + https://via.placeholder.com/640x480.png/00ee00?text=nulla + https://via.placeholder.com/640x480.png/003377?text=id + https://via.placeholder.com/640x480.png/0022bb?text=necessitatibus diff --git a/docs/snippets/advanced-directive-attributes.xml b/docs/snippets/advanced-directive-attributes.xml index b4028f4..b0c7909 100644 --- a/docs/snippets/advanced-directive-attributes.xml +++ b/docs/snippets/advanced-directive-attributes.xml @@ -1,16 +1,16 @@ - + https://example.com - Oral Little - + Lila Jones + - Immanuel Hintz - + Denis Hane + diff --git a/docs/snippets/advanced-directive-cdata.xml b/docs/snippets/advanced-directive-cdata.xml index 88f7717..367b802 100644 --- a/docs/snippets/advanced-directive-cdata.xml +++ b/docs/snippets/advanced-directive-cdata.xml @@ -2,12 +2,12 @@ - Lizzie Kris PhD]]> - gorczany.chance@example.com + Jazmyne Carroll]]> + qcrona@example.org - Mr. Christ Keeling]]> - haylee.schaefer@example.net + Prof. Aida Gusikowski]]> + will.amber@example.org diff --git a/docs/snippets/advanced-directive-mixed.xml b/docs/snippets/advanced-directive-mixed.xml index 3dbf40e..fe505a9 100644 --- a/docs/snippets/advanced-directive-mixed.xml +++ b/docs/snippets/advanced-directive-mixed.xml @@ -2,17 +2,17 @@ - Fleta Emmerich + Jana Purdy Foo - kristoffer86@example.com + greenfelder.karley@example.net - Jordi Dicki + Brandt Bernhard Foo - dwaters@example.net + king.orlando@example.com diff --git a/docs/snippets/advanced-directive-value.xml b/docs/snippets/advanced-directive-value.xml index afa44c9..d7debc0 100644 --- a/docs/snippets/advanced-directive-value.xml +++ b/docs/snippets/advanced-directive-value.xml @@ -2,12 +2,12 @@ - Llewellyn Bednar - caterina67@example.com + Elvie Lowe I + zwalker@example.org - Dr. Janick Nolan - grussel@example.org + Trenton Lindgren DDS + josefa42@example.com diff --git a/docs/snippets/advanced-element-attribute.xml b/docs/snippets/advanced-element-attribute.xml index 755c29a..a3e2ae3 100644 --- a/docs/snippets/advanced-element-attribute.xml +++ b/docs/snippets/advanced-element-attribute.xml @@ -1,13 +1,13 @@ - + 1 - Dedrick Maggio + Jarrett Stark - + 2 - Miss Eugenia Streich IV + Nathan Shields diff --git a/docs/snippets/advanced-element-header-footer.xml b/docs/snippets/advanced-element-header-footer.xml index e144ba6..95527d2 100644 --- a/docs/snippets/advanced-element-header-footer.xml +++ b/docs/snippets/advanced-element-header-footer.xml @@ -3,11 +3,11 @@ 1 - Marilou Dooley + Miss Myrtice Durgan Jr. 2 - Mireya Larson II + Wayne Padberg diff --git a/docs/snippets/advanced-element-info-before-false.xml b/docs/snippets/advanced-element-info-before-false.xml index e82865c..ac27496 100644 --- a/docs/snippets/advanced-element-info-before-false.xml +++ b/docs/snippets/advanced-element-info-before-false.xml @@ -6,11 +6,11 @@ 1 - Van Gaylord Jr. + Earnest Bashirian Jr. 2 - Mr. Jerome Cartwright + Noemi Altenwerth III diff --git a/docs/snippets/advanced-element-info.xml b/docs/snippets/advanced-element-info.xml index 08b4b49..7b01df1 100644 --- a/docs/snippets/advanced-element-info.xml +++ b/docs/snippets/advanced-element-info.xml @@ -6,11 +6,11 @@ 1 - Mr. Darwin Abshire + Jaden Boehm 2 - Eric Collins + Adelbert Kihn diff --git a/docs/snippets/advanced-element-root.xml b/docs/snippets/advanced-element-root.xml index 0a4da00..7e183be 100644 --- a/docs/snippets/advanced-element-root.xml +++ b/docs/snippets/advanced-element-root.xml @@ -3,11 +3,11 @@ 1 - Colt Jenkins IV + Frances Treutel 2 - Mr. Jesse Bradtke + Mr. Brad Kirlin DDS diff --git a/docs/snippets/receipt-instagram-feed.xml b/docs/snippets/receipt-instagram-feed.xml index eec3fe2..a9e6138 100644 --- a/docs/snippets/receipt-instagram-feed.xml +++ b/docs/snippets/receipt-instagram-feed.xml @@ -6,46 +6,46 @@ 1 - - - https://example.com/products/aliquid-aliquam-odit-id-in-ea-veritatis-fuga-voluptas - https://via.placeholder.com/640x480.png/004400?text=quos - https://via.placeholder.com/640x480.png/009988?text=aut - https://via.placeholder.com/640x480.png/000077?text=enim - consequatur + + + https://example.com/products/sint-dolor-omnis-doloribus-aut-numquam-aliquid-perspiciatis-doloribus + https://via.placeholder.com/640x480.png/00bbaa?text=quo + https://via.placeholder.com/640x480.png/009988?text=nostrum + https://via.placeholder.com/640x480.png/0066dd?text=rerum + et new in stock - 168 - 168 + 719 + 719 12345 active - - 21 + + 24 adult - + 1000 2000 2 - - - https://example.com/products/dolorum-perferendis-hic-officia-cumque-aperiam-sed - https://via.placeholder.com/640x480.png/003366?text=accusantium - https://via.placeholder.com/640x480.png/0066ee?text=eum - https://via.placeholder.com/640x480.png/00bbaa?text=autem - quae + + + https://example.com/products/qui-et-veritatis-molestias-non-voluptatem + https://via.placeholder.com/640x480.png/00cc33?text=distinctio + https://via.placeholder.com/640x480.png/00aa33?text=omnis + https://via.placeholder.com/640x480.png/0033ee?text=voluptatem + corporis new in stock - 531 - 531 + 183 + 183 12345 active - - 49 + + 21 adult - + 1000 2000 diff --git a/docs/snippets/receipt-sitemap-feed.xml b/docs/snippets/receipt-sitemap-feed.xml index 7631c56..a6102af 100644 --- a/docs/snippets/receipt-sitemap-feed.xml +++ b/docs/snippets/receipt-sitemap-feed.xml @@ -2,12 +2,12 @@ - https://example.com/products/repudiandae-porro-consequatur-sunt + https://example.com/products/quo-et-ut-eum-labore-libero-est-asperiores 2025-09-04T04:08:12+00:00 0.9 - https://example.com/products/enim-doloribus-distinctio-explicabo + https://example.com/products/nemo-aperiam-vel-sit-eos-et-eos 2025-09-04T04:08:12+00:00 0.9 diff --git a/docs/snippets/receipt-yandex-feed.xml b/docs/snippets/receipt-yandex-feed.xml index 2c2841b..06cda79 100644 --- a/docs/snippets/receipt-yandex-feed.xml +++ b/docs/snippets/receipt-yandex-feed.xml @@ -17,35 +17,35 @@ - https://example.com/products/molestiae-amet-amet-dolor-iste - GD-!F-9F - reprehenderit accusantium molestiae minus - Libero autem dolorem labore voluptatibus. Minima laborum eveniet autem aut expedita veniam voluptate. Autem fuga distinctio accusantium consectetur. + https://example.com/products/iure-ad-nisi-odit-fugiat-non-aut-exercitationem + GD-^V#W` + nemo quisquam voluptate praesentium + Ut rerum libero nobis. A quis corrupti assumenda laudantium aut similique. Iste magnam dolor non saepe dolores non aut. Accusamus et natus rerum provident. true - 574 + 980 RUR - voluptatem - https://via.placeholder.com/640x480.png/00cc33?text=quis - https://via.placeholder.com/640x480.png/00cc99?text=illum - https://via.placeholder.com/640x480.png/00ee33?text=rem - GD-!F-9F - 7 - female + aut + https://via.placeholder.com/640x480.png/000055?text=laborum + https://via.placeholder.com/640x480.png/002200?text=eligendi + https://via.placeholder.com/640x480.png/00eecc?text=quaerat + GD-^V#W` + 8 + male - https://example.com/products/officia-dolores-porro-asperiores-inventore - GD-)M%K* - quae unde delectus incidunt - Modi ut quae quia aspernatur autem. Odio deserunt eos asperiores sed quaerat. Harum et laborum sit quia est et voluptatem ea. + https://example.com/products/sed-et-non-non + GD-P]H/Z + enim ut voluptatum natus + Omnis ut non iusto qui repudiandae sint fuga modi. Consequatur ipsum quibusdam labore. Culpa qui asperiores sint similique. true - 695 + 595 RUR - et - https://via.placeholder.com/640x480.png/00ee44?text=nostrum - https://via.placeholder.com/640x480.png/0066ee?text=rerum - https://via.placeholder.com/640x480.png/003399?text=nulla - GD-)M%K* - 1 + sint + https://via.placeholder.com/640x480.png/00ddcc?text=fuga + https://via.placeholder.com/640x480.png/00bb66?text=quia + https://via.placeholder.com/640x480.png/00bbaa?text=doloribus + GD-P]H/Z + 6 male diff --git a/src/Commands/FeedGenerateCommand.php b/src/Commands/FeedGenerateCommand.php index f2a3152..503d948 100644 --- a/src/Commands/FeedGenerateCommand.php +++ b/src/Commands/FeedGenerateCommand.php @@ -13,6 +13,7 @@ use Symfony\Component\Console\Input\InputArgument; use function app; +use function config; use function is_numeric; #[AsCommand('feed:generate', 'Generate XML feeds')] @@ -29,12 +30,24 @@ public function handle(GeneratorService $generator, FeedQuery $query): void continue; } - $this->components->info($feed); - - $generator->feed(app($feed), $this->output); + $this->hasProgressBar() + ? $this->performWithProgressBar($generator, $feed) + : $this->performWithoutProgressBar($generator, $feed); } } + protected function performWithProgressBar(GeneratorService $generator, string $feed): void + { + $this->components->info($feed); + + $generator->feed(app($feed), $this->output); + } + + protected function performWithoutProgressBar(GeneratorService $generator, string $feed): void + { + $this->components->task($feed, fn () => $generator->feed(app($feed))); + } + protected function feedable(FeedQuery $feeds): array { if (! $id = $this->argument('feed')) { @@ -63,6 +76,11 @@ protected function messageYellow(string $message): string return $this->yellow($message); } + protected function hasProgressBar(): bool + { + return config()?->boolean('feeds.console.progress_bar'); + } + protected function getArguments(): array { return [ diff --git a/src/Services/GeneratorService.php b/src/Services/GeneratorService.php index 812632e..9569c2e 100644 --- a/src/Services/GeneratorService.php +++ b/src/Services/GeneratorService.php @@ -10,6 +10,7 @@ use DragonCode\LaravelFeed\Queries\FeedQuery; use Illuminate\Console\OutputStyle; use Illuminate\Database\Eloquent\Collection; +use Symfony\Component\Console\Helper\ProgressBar; use function blank; use function collect; @@ -26,7 +27,7 @@ public function __construct( protected FeedQuery $query, ) {} - public function feed(Feed $feed, OutputStyle $output): void + public function feed(Feed $feed, ?OutputStyle $output = null): void { $file = $this->openFile( $path = $feed->path() @@ -44,11 +45,11 @@ public function feed(Feed $feed, OutputStyle $output): void $this->setLastActivity($feed); } - protected function performItem($file, Feed $feed, OutputStyle $output): void // @pest-ignore-type + protected function performItem($file, Feed $feed, ?OutputStyle $output): void // @pest-ignore-type { - $bar = $output->createProgressBar( - $feed->builder()->count() - ); + // @codeCoverageIgnoreStart + $bar = $this->progressBar($feed, $output); + // @codeCoverageIgnoreEnd $feed->builder()->chunkById($feed->chunkSize(), function (Collection $models) use ($file, $feed, $bar) { $content = []; @@ -58,14 +59,14 @@ protected function performItem($file, Feed $feed, OutputStyle $output): void // $feed->item($model) ); - $bar->advance(); + $bar?->advance(); } $this->append($file, implode(PHP_EOL, $content), $feed->path()); }); - $bar->finish(); - $output->newLine(); + $bar?->finish(); + $output?->newLine(); } protected function performHeader($file, Feed $feed): void // @pest-ignore-type @@ -146,4 +147,11 @@ protected function setLastActivity(Feed $feed): void get_class($feed) ); } + + protected function progressBar(Feed $feed, ?OutputStyle $output): ?ProgressBar + { + return $output?->createProgressBar( + $feed->builder()->count() + ); + } } diff --git a/tests/Feature/Console/Generation/ProgressBarTest.php b/tests/Feature/Console/Generation/ProgressBarTest.php new file mode 100644 index 0000000..37f21a1 --- /dev/null +++ b/tests/Feature/Console/Generation/ProgressBarTest.php @@ -0,0 +1,20 @@ +set('feeds.console.progress_bar', $enabled); + + $command = artisan(FeedGenerateCommand::class); + + getAllFeeds()->each( + fn (Feed $feed) => $command->expectsOutputToContain($feed->class) + ); + + $command->assertSuccessful()->run(); +})->with('boolean');