From 40751aeeb9a808b93f1d679e67ca596666e6a1e6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 21 Oct 2023 15:32:55 +0000 Subject: [PATCH 01/20] Merge pull request #1393 from hydephp/improve-source-file-creator-actions Improve source file creator actions https://github.com/hydephp/develop/commit/27268768379f1bba40e5b07564a13068d1610889 --- .../Actions/CreatesNewMarkdownPostFile.php | 13 ++- .../Actions/CreatesNewPageSourceFile.php | 25 ++++- .../Actions/CreatesNewPageSourceFileTest.php | 51 +++++++++ .../Feature/Commands/MakePageCommandTest.php | 1 + .../Feature/Commands/MakePostCommandTest.php | 4 + tests/Unit/CreatesNewMarkdownPostFileTest.php | 104 ++++++++++++++++++ 6 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 tests/Unit/CreatesNewMarkdownPostFileTest.php diff --git a/src/Framework/Actions/CreatesNewMarkdownPostFile.php b/src/Framework/Actions/CreatesNewMarkdownPostFile.php index c59383ee..3f1f4ea9 100644 --- a/src/Framework/Actions/CreatesNewMarkdownPostFile.php +++ b/src/Framework/Actions/CreatesNewMarkdownPostFile.php @@ -7,10 +7,9 @@ use Hyde\Framework\Exceptions\FileConflictException; use Hyde\Facades\Filesystem; use Hyde\Pages\MarkdownPost; +use Illuminate\Support\Carbon; use Illuminate\Support\Str; -use function date; - /** * Offloads logic for the make:post command. * @@ -28,6 +27,7 @@ class CreatesNewMarkdownPostFile protected string $author; protected string $date; protected string $identifier; + protected ?string $customContent; /** * Construct the class. @@ -36,15 +36,18 @@ class CreatesNewMarkdownPostFile * @param string|null $description The Post Meta Description. * @param string|null $category The Primary Post Category. * @param string|null $author The Username of the Author. + * @param string|null $date Optionally specify a custom date. + * @param string|null $customContent Optionally specify custom post content. */ - public function __construct(string $title, ?string $description, ?string $category, ?string $author) + public function __construct(string $title, ?string $description, ?string $category, ?string $author, ?string $date = null, ?string $customContent = null) { $this->title = $title; $this->description = $description ?? 'A short description used in previews and SEO'; $this->category = $category ?? 'blog'; $this->author = $author ?? 'default'; + $this->customContent = $customContent; - $this->date = date('Y-m-d H:i'); + $this->date = Carbon::make($date ?? Carbon::now())->format('Y-m-d H:i'); $this->identifier = Str::slug($title); } @@ -58,7 +61,7 @@ public function __construct(string $title, ?string $description, ?string $catego */ public function save(bool $force = false): string { - $page = new MarkdownPost($this->identifier, $this->toArray(), '## Write something awesome.'); + $page = new MarkdownPost($this->identifier, $this->toArray(), $this->customContent ?? '## Write something awesome.'); if ($force !== true && Filesystem::exists($page->getSourcePath())) { throw new FileConflictException($page->getSourcePath()); diff --git a/src/Framework/Actions/CreatesNewPageSourceFile.php b/src/Framework/Actions/CreatesNewPageSourceFile.php index 13cf19b2..60ff6686 100644 --- a/src/Framework/Actions/CreatesNewPageSourceFile.php +++ b/src/Framework/Actions/CreatesNewPageSourceFile.php @@ -13,6 +13,8 @@ use Hyde\Framework\Concerns\InteractsWithDirectories; use Hyde\Framework\Exceptions\UnsupportedPageTypeException; +use function trim; +use function sprintf; use function file_put_contents; use function file_exists; use function basename; @@ -37,7 +39,9 @@ class CreatesNewPageSourceFile protected string $subDir = ''; protected bool $force; - public function __construct(string $title, string $pageClass = MarkdownPage::class, bool $force = false) + protected ?string $customContent; + + public function __construct(string $title, string $pageClass = MarkdownPage::class, bool $force = false, ?string $customContent = null) { $this->validateType($pageClass); $this->pageClass = $pageClass; @@ -45,6 +49,7 @@ public function __construct(string $title, string $pageClass = MarkdownPage::cla $this->title = $this->parseTitle($title); $this->filename = $this->fileName($title); $this->force = $force; + $this->customContent = $customContent; $this->outputPath = $this->makeOutputPath($pageClass); } @@ -100,7 +105,7 @@ protected function createBladeFile(): void @php(\$title = "$this->title")
-

$this->title

+ {$this->getBladePageContent()}
@endsection @@ -111,7 +116,7 @@ protected function createBladeFile(): void protected function createMarkdownFile(): void { - (new MarkdownPage($this->formatIdentifier(), ['title' => $this->title], "# $this->title"))->save(); + (new MarkdownPage($this->formatIdentifier(), ['title' => $this->title], $this->getMarkdownPageContent()))->save(); } protected function createDocumentationFile(): void @@ -137,4 +142,18 @@ protected function failIfFileCannotBeSaved(string $path): void throw new FileConflictException($path); } } + + protected function getBladePageContent(): string + { + $baseContent = "

$this->title

"; + + return $this->customContent + ? trim(sprintf("%s\n\n
\n %s\n
", $baseContent, $this->customContent)) + : $baseContent; + } + + protected function getMarkdownPageContent(): string + { + return trim(sprintf("# $this->title\n\n%s", $this->customContent ?? '')); + } } diff --git a/tests/Feature/Actions/CreatesNewPageSourceFileTest.php b/tests/Feature/Actions/CreatesNewPageSourceFileTest.php index e278885f..4b32145f 100644 --- a/tests/Feature/Actions/CreatesNewPageSourceFileTest.php +++ b/tests/Feature/Actions/CreatesNewPageSourceFileTest.php @@ -133,6 +133,57 @@ public function test_that_a_documentation_file_can_be_created_and_contains_expec Filesystem::unlink('_docs/test-page.md'); } + public function test_that_a_markdown_file_can_be_created_with_custom_content() + { + (new CreatesNewPageSourceFile('Test Page', customContent: 'Hello World!'))->save(); + + $this->assertFileExists(Hyde::path('_pages/test-page.md')); + + $this->assertSame( + <<<'MARKDOWN' + --- + title: 'Test Page' + --- + + # Test Page + + Hello World! + + MARKDOWN + , + file_get_contents(Hyde::path('_pages/test-page.md')) + ); + Filesystem::unlink('_pages/test-page.md'); + } + + public function test_that_a_blade_file_can_be_created_with_custom_content() + { + (new CreatesNewPageSourceFile('Test Page', BladePage::class, customContent: 'Hello World!'))->save(); + + $this->assertFileExists(Hyde::path('_pages/test-page.blade.php')); + + $this->assertEquals( + <<<'BLADE' + @extends('hyde::layouts.app') + @section('content') + @php($title = "Test Page") + +
+

Test Page

+ +
+ Hello World! +
+
+ + @endsection + + BLADE, file_get_contents(Hyde::path('_pages/test-page.blade.php')) + ); + + Filesystem::unlink('_pages/test-page.blade.php'); + } + public function test_that_the_file_path_can_be_returned() { $this->assertSame( diff --git a/tests/Feature/Commands/MakePageCommandTest.php b/tests/Feature/Commands/MakePageCommandTest.php index 795822c2..bae51389 100644 --- a/tests/Feature/Commands/MakePageCommandTest.php +++ b/tests/Feature/Commands/MakePageCommandTest.php @@ -12,6 +12,7 @@ /** * @covers \Hyde\Console\Commands\MakePageCommand + * @covers \Hyde\Framework\Actions\CreatesNewPageSourceFile */ class MakePageCommandTest extends TestCase { diff --git a/tests/Feature/Commands/MakePostCommandTest.php b/tests/Feature/Commands/MakePostCommandTest.php index 91da9a9f..f275a9e0 100644 --- a/tests/Feature/Commands/MakePostCommandTest.php +++ b/tests/Feature/Commands/MakePostCommandTest.php @@ -8,6 +8,10 @@ use Hyde\Hyde; use Hyde\Testing\TestCase; +/** + * @covers \Hyde\Console\Commands\MakePostCommand + * @covers \Hyde\Framework\Actions\CreatesNewMarkdownPostFile + */ class MakePostCommandTest extends TestCase { public function test_command_has_expected_output_and_creates_valid_file() diff --git a/tests/Unit/CreatesNewMarkdownPostFileTest.php b/tests/Unit/CreatesNewMarkdownPostFileTest.php new file mode 100644 index 00000000..ef889878 --- /dev/null +++ b/tests/Unit/CreatesNewMarkdownPostFileTest.php @@ -0,0 +1,104 @@ +assertSame([ + 'title' => 'Example Title', + 'description' => 'A short description used in previews and SEO', + 'category' => 'blog', + 'author' => 'default', + 'date' => '2024-01-01 00:00', + ], $action->toArray()); + } + + public function testWithCustomData() + { + $action = new CreatesNewMarkdownPostFile('foo', 'bar', 'baz', 'qux', '2024-06-01 12:20'); + + $this->assertSame([ + 'title' => 'foo', + 'description' => 'bar', + 'category' => 'baz', + 'author' => 'qux', + 'date' => '2024-06-01 12:20', + ], $action->toArray()); + } + + public function testSave() + { + $action = new CreatesNewMarkdownPostFile('Example Post', null, null, null); + $action->save(); + + $path = Hyde::path('_posts/example-post.md'); + + $this->assertSame(<<<'MARKDOWN' + --- + title: 'Example Post' + description: 'A short description used in previews and SEO' + category: blog + author: default + date: '2024-01-01 00:00' + --- + + ## Write something awesome. + + MARKDOWN, file_get_contents($path)); + + unlink($path); + } + + public function testSaveWithCustomContent() + { + $action = new CreatesNewMarkdownPostFile('Example Post', null, null, null, null, 'Hello World!'); + $action->save(); + + $path = Hyde::path('_posts/example-post.md'); + + $this->assertSame(<<<'MARKDOWN' + --- + title: 'Example Post' + description: 'A short description used in previews and SEO' + category: blog + author: default + date: '2024-01-01 00:00' + --- + + Hello World! + + MARKDOWN, file_get_contents($path)); + + unlink($path); + } + + public function testCustomDateNormalisation() + { + $action = new CreatesNewMarkdownPostFile('Example Post', null, null, null, 'Jan 1 2024 8am'); + + $this->assertSame('2024-01-01 08:00', $action->toArray()['date']); + } +} From 438508f3581557ecb5c4cd73b3d7384dda116fa1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 26 Oct 2023 18:50:23 +0000 Subject: [PATCH 02/20] Merge pull request #1392 from hydephp/realtime-compiler-dashboard-improvements Interactive realtime compiler dashboard feature https://github.com/hydephp/develop/commit/5cc10c79d44183d0d675b07ee7d4a67fe1d3cf3d --- config/hyde.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/config/hyde.php b/config/hyde.php index d744efa2..90962d76 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -403,10 +403,24 @@ */ 'server' => [ + // The default port the preview is served on 'port' => env('SERVER_PORT', 8080), + + // The default host the preview is served on 'host' => env('SERVER_HOST', 'localhost'), - 'dashboard' => env('SERVER_DASHBOARD', true), + + // Should preview pages be saved to the output directory? 'save_preview' => true, + + // Should the realtime compiler dashboard be enabled? + 'dashboard' => env('SERVER_DASHBOARD', true), + + // Can the dashboard make edits to the project file system? + 'dashboard_editor' => true, + + // Should the dashboard show tips? + 'dashboard_tips' => true, + ], /* From 4893476568779cda9b1bc2618988baf4820b3712 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 27 Oct 2023 08:12:52 +0000 Subject: [PATCH 03/20] Merge pull request #1395 from hydephp/realtime-compiler-dashboard-improvements Update realtime compiler dashboard configuration schema https://github.com/hydephp/develop/commit/b563dc6eb5ff2f180f466e02302bab16c617777a --- config/hyde.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/config/hyde.php b/config/hyde.php index 90962d76..f9126cb3 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -399,6 +399,8 @@ |-------------------------------------------------------------------------- | | Here you can configure settings for the built-in realtime compiler server. + | The server also includes a magic dashboard feature that supercharges + | your local development! This feature can alo be customised here. | */ @@ -412,14 +414,17 @@ // Should preview pages be saved to the output directory? 'save_preview' => true, - // Should the realtime compiler dashboard be enabled? - 'dashboard' => env('SERVER_DASHBOARD', true), + // Configure the realtime compiler dashboard + 'dashboard' => [ + // Should the realtime compiler dashboard be enabled? + 'enabled' => env('SERVER_DASHBOARD', true), - // Can the dashboard make edits to the project file system? - 'dashboard_editor' => true, + // Can the dashboard make edits to the project file system? + 'interactive' => true, - // Should the dashboard show tips? - 'dashboard_tips' => true, + // Should the dashboard show tips? + 'tips' => true, + ], ], From ffd197da642699b005b45d8b3b5a8425ed13208f Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 27 Oct 2023 16:01:15 +0000 Subject: [PATCH 04/20] Merge pull request #1396 from hydephp/navigation-data-factory-cleanup Break down complex helper method https://github.com/hydephp/develop/commit/528cd86a2d2cddee4af0a044511ef22f097a4afa --- .../Factories/NavigationDataFactory.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Framework/Factories/NavigationDataFactory.php b/src/Framework/Factories/NavigationDataFactory.php index 0a4a90a4..3c8267f8 100644 --- a/src/Framework/Factories/NavigationDataFactory.php +++ b/src/Framework/Factories/NavigationDataFactory.php @@ -89,9 +89,8 @@ protected function makeHidden(): bool { return $this->isInstanceOf(MarkdownPost::class) || $this->searchForHiddenInFrontMatter() - || in_array($this->routeKey, Config::getArray('hyde.navigation.exclude', ['404'])) - || (! $this->isInstanceOf(DocumentationPage::class) && $this->pageIsInSubdirectory() && ($this->getSubdirectoryConfiguration() === 'hidden')) - && (basename($this->identifier) !== 'index'); + || $this->isPageHiddenInNavigationConfiguration() + || $this->isNonDocumentationPageInHiddenSubdirectory(); } protected function makePriority(): int @@ -119,6 +118,19 @@ private function searchForHiddenInFrontMatter(): ?bool ?? $this->invert($this->getMatter('navigation.visible')); } + private function isPageHiddenInNavigationConfiguration(): ?bool + { + return in_array($this->routeKey, Config::getArray('hyde.navigation.exclude', ['404'])); + } + + private function isNonDocumentationPageInHiddenSubdirectory(): bool + { + return ! $this->isInstanceOf(DocumentationPage::class) + && $this->pageIsInSubdirectory() + && $this->getSubdirectoryConfiguration() === 'hidden' + && basename($this->identifier) !== 'index'; + } + private function searchForPriorityInFrontMatter(): ?int { return $this->getMatter('navigation.priority') From d6208d7ee0cb89e3aa73e5913a318e33264500d5 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 27 Oct 2023 17:09:15 +0000 Subject: [PATCH 05/20] Merge pull request #1398 from hydephp/custom-file-not-found-exception-messages Add option for full control over the FileNotFoundException message https://github.com/hydephp/develop/commit/9f94f7fa3f2560bf3d52f5f9751df03fe78dbb8a --- src/Framework/Exceptions/FileNotFoundException.php | 4 ++-- tests/Unit/CustomExceptionsTest.php | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Framework/Exceptions/FileNotFoundException.php b/src/Framework/Exceptions/FileNotFoundException.php index 8bd6298c..417a18e3 100644 --- a/src/Framework/Exceptions/FileNotFoundException.php +++ b/src/Framework/Exceptions/FileNotFoundException.php @@ -17,8 +17,8 @@ class FileNotFoundException extends Exception /** @var int */ protected $code = 404; - public function __construct(?string $path = null) + public function __construct(?string $path = null, ?string $customMessage = null) { - parent::__construct($path ? sprintf('File [%s] not found.', Hyde::pathToRelative($path)) : $this->message); + parent::__construct($customMessage ?? ($path ? sprintf('File [%s] not found.', Hyde::pathToRelative($path)) : $this->message)); } } diff --git a/tests/Unit/CustomExceptionsTest.php b/tests/Unit/CustomExceptionsTest.php index 30c7eec4..5103307b 100644 --- a/tests/Unit/CustomExceptionsTest.php +++ b/tests/Unit/CustomExceptionsTest.php @@ -56,6 +56,11 @@ public function testFileNotFoundExceptionWithAbsolutePath() $this->assertSame('File [foo] not found.', (new FileNotFoundException(Hyde::path('foo')))->getMessage()); } + public function testFileNotFoundExceptionWithCustomPath() + { + $this->assertSame('foo', (new FileNotFoundException(customMessage: 'foo'))->getMessage()); + } + public function testRouteNotFoundExceptionWithDefaultMessage() { $this->assertSame('Route not found.', (new RouteNotFoundException())->getMessage()); From 10eb1a86f2bef3f903e373d23180fdddb794bfb6 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Fri, 27 Oct 2023 19:38:42 +0200 Subject: [PATCH 06/20] Merge changes from https://github.com/hydephp/develop/pull/1400 Manual merge, as token does not have permission to edit workflows. --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index fe329025..510d55e2 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -61,5 +61,5 @@ jobs: - name: Ping statistics server with test results run: | cd hyde - curl https://gist.githubusercontent.com/caendesilva/d76fc6d73cb488863a8f6fda18a7c8c4/raw/1d22747e5064b40e4da05e7666d1ab1d2766de7a/ping-openanalytics-testrunner.php -o ping.php + curl https://raw.githubusercontent.com/hydephp/develop/cfbf8fb97505359266f849edef4757ae76a922b5/monorepo/scripts/ping-openanalytics-testrunner.php -o ping.php php ping.php "Framework CI Matrix" ${{ secrets.OPENANALYTICS_TOKEN }} From e58871ccdbc393a40986b64cce88c0d349a8c131 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 27 Oct 2023 17:55:51 +0000 Subject: [PATCH 07/20] Merge pull request #1399 from hydephp/general-bugfixes Use a custom exception message when failing to get image size https://github.com/hydephp/develop/commit/cda8c665540f157d16acebe5950a194b6fbd412d --- src/Framework/Features/Blogging/Models/FeaturedImage.php | 2 +- tests/Unit/FeaturedImageUnitTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Framework/Features/Blogging/Models/FeaturedImage.php b/src/Framework/Features/Blogging/Models/FeaturedImage.php index d2b68603..25f80a2b 100644 --- a/src/Framework/Features/Blogging/Models/FeaturedImage.php +++ b/src/Framework/Features/Blogging/Models/FeaturedImage.php @@ -217,7 +217,7 @@ protected function getContentLengthForLocalImage(): int $storagePath = Hyde::mediaPath($this->source); if (! file_exists($storagePath)) { - throw new FileNotFoundException(sprintf('Image at %s does not exist', Hyde::pathToRelative($storagePath))); + throw new FileNotFoundException(customMessage: sprintf('Featured image [%s] not found.', Hyde::pathToRelative($storagePath))); } return filesize($storagePath); diff --git a/tests/Unit/FeaturedImageUnitTest.php b/tests/Unit/FeaturedImageUnitTest.php index e5fea9fc..3fae872b 100644 --- a/tests/Unit/FeaturedImageUnitTest.php +++ b/tests/Unit/FeaturedImageUnitTest.php @@ -124,7 +124,7 @@ public function testGetContentLength() public function testFeaturedImageGetContentLengthWithNoSource() { $this->expectException(FileNotFoundException::class); - $this->expectExceptionMessage('Image at _media/foo does not exist'); + $this->expectExceptionMessage('Featured image [_media/foo] not found.'); $image = new FeaturedImage('_media/foo', ...$this->defaultArguments()); $this->assertEquals(0, $image->getContentLength()); From 2440025dca63536ad440817d3465b883a8957a38 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Fri, 27 Oct 2023 20:17:38 +0200 Subject: [PATCH 08/20] Run tests with Junit reporting --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 510d55e2..49844181 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -54,7 +54,7 @@ jobs: - name: Set environment to testing run: cd hyde && echo "ENV=testing" > .env - name: Execute tests (Unit and Feature tests) via PHPUnit/Pest - run: cd hyde && vendor/bin/pest + run: cd hyde && vendor/bin/pest --log-junit report.xml env: ENV: testing From 7f0a0c1fc95d3ba03f8084e35077d02bef47898f Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Fri, 27 Oct 2023 20:30:22 +0200 Subject: [PATCH 09/20] Merge changes from https://github.com/hydephp/develop/pull/1402 Manual merge, as token does not have permission to edit workflows. --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 49844181..b8c54efe 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -61,5 +61,5 @@ jobs: - name: Ping statistics server with test results run: | cd hyde - curl https://raw.githubusercontent.com/hydephp/develop/cfbf8fb97505359266f849edef4757ae76a922b5/monorepo/scripts/ping-openanalytics-testrunner.php -o ping.php + curl https://raw.githubusercontent.com/hydephp/develop/6e9d17f31879f4ccda13a3fec4029c9663bccec0/monorepo/scripts/ping-openanalytics-testrunner.php -o ping.php php ping.php "Framework CI Matrix" ${{ secrets.OPENANALYTICS_TOKEN }} From d6bac3a589883a3337b0c7ecf30b60a0d8e7685f Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 28 Oct 2023 14:36:46 +0000 Subject: [PATCH 10/20] Merge pull request #1407 from hydephp/duplicate-navigation-items-should-give-precedence-to-config-defined-items Update navigation menu generator to remove duplicates after sorting https://github.com/hydephp/develop/commit/409fbe145793c9ec40c1875caae8f415ef1603ee --- .../Features/Navigation/BaseNavigationMenu.php | 2 +- tests/Feature/NavigationMenuTest.php | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Framework/Features/Navigation/BaseNavigationMenu.php b/src/Framework/Features/Navigation/BaseNavigationMenu.php index 4b501247..d802662c 100644 --- a/src/Framework/Features/Navigation/BaseNavigationMenu.php +++ b/src/Framework/Features/Navigation/BaseNavigationMenu.php @@ -26,8 +26,8 @@ public static function create(): static $menu = new static(); $menu->generate(); - $menu->removeDuplicateItems(); $menu->sortByPriority(); + $menu->removeDuplicateItems(); return $menu; } diff --git a/tests/Feature/NavigationMenuTest.php b/tests/Feature/NavigationMenuTest.php index 203fb92f..bd2fcebf 100644 --- a/tests/Feature/NavigationMenuTest.php +++ b/tests/Feature/NavigationMenuTest.php @@ -161,7 +161,22 @@ public function test_duplicates_are_removed_when_adding_in_config_regardless_of_ $this->assertEquals($expected, $menu->items); } - // TODO test when there are duplicates, config items take precedence + public function test_config_items_take_precedence_over_generated_items() + { + $this->file('_pages/foo.md'); + + config(['hyde.navigation.custom' => [NavItem::forLink('bar', 'Foo')]]); + + $menu = NavigationMenu::create(); + + $expected = collect([ + NavItem::fromRoute(Routes::get('index')), + NavItem::forLink('bar', 'Foo'), + ]); + + $this->assertCount(count($expected), $menu->items); + $this->assertEquals($expected, $menu->items); + } public function test_documentation_pages_that_are_not_index_are_not_added_to_the_menu() { From 5a9ea3ee10b6717707b38084f71fe70ab373b324 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 28 Oct 2023 15:43:34 +0000 Subject: [PATCH 11/20] Merge pull request #1408 from hydephp/code-cleanup Remove low priority todo comments https://github.com/hydephp/develop/commit/d5b24d891eec98c1a47a2c353bb0a914a9a0be1c --- src/Framework/Features/Blogging/Models/FeaturedImage.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Framework/Features/Blogging/Models/FeaturedImage.php b/src/Framework/Features/Blogging/Models/FeaturedImage.php index 25f80a2b..71bf71ee 100644 --- a/src/Framework/Features/Blogging/Models/FeaturedImage.php +++ b/src/Framework/Features/Blogging/Models/FeaturedImage.php @@ -225,9 +225,7 @@ protected function getContentLengthForLocalImage(): int protected function getContentLengthForRemoteImage(): int { - // TODO: We may want to globalize this check in the config, but for now, - // we just check the server arguments and skip remote requests if - // the --no-api flag is present (in the build command call) + // Check if the --no-api flag is set when running the build command, and if so, skip the API call. if (! (isset($_SERVER['argv']) && in_array('--no-api', $_SERVER['argv'], true))) { $headers = Http::withHeaders([ 'User-Agent' => Config::getString('hyde.http_user_agent', 'RSS Request Client'), From ddb3fa174bf5b03cb0e6e2b16f346395790ecd4b Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 28 Oct 2023 15:52:47 +0000 Subject: [PATCH 12/20] Merge pull request #1409 from hydephp/improve-featured-image-factory-exception-message Update the featured image factory to specify the file causing an exception https://github.com/hydephp/develop/commit/3980228604792aef7eee7022afea2254f0dbd809 --- src/Framework/Factories/BlogPostDataFactory.php | 5 ++++- src/Framework/Factories/FeaturedImageFactory.php | 9 ++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Framework/Factories/BlogPostDataFactory.php b/src/Framework/Factories/BlogPostDataFactory.php index a8dbfc59..8eb80a3d 100644 --- a/src/Framework/Factories/BlogPostDataFactory.php +++ b/src/Framework/Factories/BlogPostDataFactory.php @@ -41,10 +41,13 @@ class BlogPostDataFactory extends Concerns\PageDataFactory implements BlogPostSc protected readonly ?PostAuthor $author; protected readonly ?FeaturedImage $image; + private readonly string $filePath; + public function __construct(CoreDataObject $pageData) { $this->matter = $pageData->matter; $this->markdown = $pageData->markdown; + $this->filePath = $pageData->sourcePath; $this->description = $this->makeDescription(); $this->category = $this->makeCategory(); @@ -98,7 +101,7 @@ protected function makeAuthor(): ?PostAuthor protected function makeImage(): ?FeaturedImage { if ($this->getMatter('image')) { - return FeaturedImageFactory::make($this->matter); + return FeaturedImageFactory::make($this->matter, $this->filePath); } return null; diff --git a/src/Framework/Factories/FeaturedImageFactory.php b/src/Framework/Factories/FeaturedImageFactory.php index 5501edf8..a844ae1c 100644 --- a/src/Framework/Factories/FeaturedImageFactory.php +++ b/src/Framework/Factories/FeaturedImageFactory.php @@ -30,6 +30,7 @@ class FeaturedImageFactory extends Concerns\PageDataFactory implements FeaturedI public function __construct( private readonly FrontMatter $matter, + private readonly ?string $filePath = null, ) { $this->source = $this->makeSource(); $this->altText = $this->getStringMatter('image.altText'); @@ -58,9 +59,9 @@ public function toArray(): array ]; } - public static function make(FrontMatter $matter): FeaturedImage + public static function make(FrontMatter $matter, ?string $filePath = null): FeaturedImage { - return new FeaturedImage(...(new static($matter))->toArray()); + return new FeaturedImage(...(new static($matter, $filePath))->toArray()); } protected function makeSource(): string @@ -68,9 +69,7 @@ protected function makeSource(): string $value = $this->getStringMatter('image') ?? $this->getStringMatter('image.source'); if (empty($value)) { - // Todo, we might want to add a note about which file caused the error. - // We could also check for these before calling the factory, and just ignore the image if it's not valid. - throw new RuntimeException('No featured image source was found'); + throw new RuntimeException(sprintf('No featured image source was found in "%s"', $this->filePath ?? 'unknown file')); } if (FeaturedImage::isRemote($value)) { From 33d93884513c5fffdbae9cb560b2668bd42a4991 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 28 Oct 2023 18:01:18 +0000 Subject: [PATCH 13/20] Merge pull request #1410 from hydephp/code-quality Improve type coverage https://github.com/hydephp/develop/commit/68471d74a6ec52144e05b89175470b3c538c7ab1 --- src/Console/Commands/PublishHomepageCommand.php | 2 ++ src/Facades/Filesystem.php | 2 +- src/Foundation/Kernel/Filesystem.php | 10 +++++++++- src/Framework/Actions/BladeMatterParser.php | 6 +++++- .../Actions/PreBuildTasks/CleanSiteDirectory.php | 2 ++ .../Factories/NavigationDataFactory.php | 1 + src/Framework/Features/Metadata/MetadataBag.php | 16 +++++++++++++--- .../Features/Navigation/DropdownNavItem.php | 9 +++++++-- src/Framework/Services/BuildTaskService.php | 13 +++++++++++-- 9 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/Console/Commands/PublishHomepageCommand.php b/src/Console/Commands/PublishHomepageCommand.php index 9b10552f..05744d01 100644 --- a/src/Console/Commands/PublishHomepageCommand.php +++ b/src/Console/Commands/PublishHomepageCommand.php @@ -31,6 +31,7 @@ class PublishHomepageCommand extends Command /** @var string */ protected $description = 'Publish one of the default homepages to index.blade.php.'; + /** @var array */ protected array $options = [ 'welcome'=> [ 'name' => 'Welcome', @@ -96,6 +97,7 @@ protected function formatPublishableChoices(): array })->values()->toArray(); } + /** @return Collection */ protected function getTemplateOptions(): Collection { return new Collection($this->options); diff --git a/src/Facades/Filesystem.php b/src/Facades/Filesystem.php index d1f3bdad..56991dd0 100644 --- a/src/Facades/Filesystem.php +++ b/src/Facades/Filesystem.php @@ -63,7 +63,7 @@ public static function relativePath(string $path): string * * @param string $pattern * @param int $flags - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public static function smartGlob(string $pattern, int $flags = 0): Collection { diff --git a/src/Foundation/Kernel/Filesystem.php b/src/Foundation/Kernel/Filesystem.php index a51df395..dcc8f79e 100644 --- a/src/Foundation/Kernel/Filesystem.php +++ b/src/Foundation/Kernel/Filesystem.php @@ -65,6 +65,8 @@ public function path(string $path = ''): string * Get an absolute file path from a supplied relative path. * * Input types are matched, meaning that if the input is a string so will the output be. + * + * @param string|array $path */ public function pathToAbsolute(string|array $path): string|array { @@ -143,6 +145,8 @@ public function vendorPath(string $path = '', string $package = 'framework'): st /** * Touch one or more files in the project's directory. + * + * @param string|array $path */ public function touch(string|array $path): bool { @@ -159,6 +163,8 @@ public function touch(string|array $path): bool /** * Unlink one or more files in the project's directory. + * + * @param string|array $path */ public function unlink(string|array $path): bool { @@ -185,9 +191,11 @@ public function unlinkIfExists(string $path): bool return false; } + /** @return \Illuminate\Support\Collection */ public function smartGlob(string $pattern, int $flags = 0): Collection { return collect(\Hyde\Facades\Filesystem::glob($pattern, $flags)) - ->map(fn (string $path): string => $this->pathToRelative($path)); + ->map(fn (string $path): string => $this->pathToRelative($path)) + ->values(); } } diff --git a/src/Framework/Actions/BladeMatterParser.php b/src/Framework/Actions/BladeMatterParser.php index 78aefd59..1f6c03f2 100644 --- a/src/Framework/Actions/BladeMatterParser.php +++ b/src/Framework/Actions/BladeMatterParser.php @@ -121,6 +121,7 @@ protected static function extractValue(string $line): string return trim($key); } + /** @return scalar|array */ protected static function getValueWithType(string $value): mixed { $value = trim($value); @@ -138,6 +139,7 @@ protected static function getValueWithType(string $value): mixed return json_decode($value) ?? $value; } + /** @return array */ protected static function parseArrayString(string $string): array { $array = []; @@ -167,7 +169,9 @@ protected static function parseArrayString(string $string): array $pair = explode('=>', $token); // Add key/value pair to array - $array[static::getValueWithType(trim(trim($pair[0]), "'"))] = static::getValueWithType(trim(trim($pair[1]), "'")); + $key = (string) static::getValueWithType(trim(trim($pair[0]), "'")); + $value = static::getValueWithType(trim(trim($pair[1]), "'")); + $array[$key] = $value; } return $array; diff --git a/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php b/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php index d7ea838f..d03c6a9d 100644 --- a/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php +++ b/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php @@ -57,8 +57,10 @@ protected function askIfUnsafeDirectoryShouldBeEmptied(): bool )); } + /** @return array */ protected function safeOutputDirectories(): array { + /** @var array $directories */ return Config::getArray('hyde.safe_output_directories', ['_site', 'docs', 'build']); } } diff --git a/src/Framework/Factories/NavigationDataFactory.php b/src/Framework/Factories/NavigationDataFactory.php index 3c8267f8..3068855c 100644 --- a/src/Framework/Factories/NavigationDataFactory.php +++ b/src/Framework/Factories/NavigationDataFactory.php @@ -201,6 +201,7 @@ protected function getSubdirectoryConfiguration(): string return Config::getString('hyde.navigation.subdirectories', 'hidden'); } + /** @param class-string $class */ protected function isInstanceOf(string $class): bool { return is_a($this->pageClass, $class, true); diff --git a/src/Framework/Features/Metadata/MetadataBag.php b/src/Framework/Features/Metadata/MetadataBag.php index e39c6171..5d0c2aa4 100644 --- a/src/Framework/Features/Metadata/MetadataBag.php +++ b/src/Framework/Features/Metadata/MetadataBag.php @@ -20,9 +20,16 @@ */ class MetadataBag implements Htmlable { + /** @var array */ protected array $links = []; + + /** @var array */ protected array $metadata = []; + + /** @var array */ protected array $properties = []; + + /** @var array */ protected array $generics = []; public function toHtml(): string @@ -59,7 +66,7 @@ public function add(MetadataElementContract|string $element): static return $this->addElement('properties', $element); } - return $this->addGenericElement($element); + return $this->addGenericElement((string) $element); } protected function addElement(string $type, MetadataElementContract $element): static @@ -76,12 +83,15 @@ protected function addGenericElement(string $element): static return $this; } + /** @return array */ protected function getPrefixedArray(string $type): array { + /** @var array $bag */ + $bag = $this->{$type}; + $array = []; - /** @var MetadataElementContract $element */ - foreach ($this->{$type} as $key => $element) { + foreach ($bag as $key => $element) { $array["$type:$key"] = $element; } diff --git a/src/Framework/Features/Navigation/DropdownNavItem.php b/src/Framework/Features/Navigation/DropdownNavItem.php index f1adc1cc..aef24a99 100644 --- a/src/Framework/Features/Navigation/DropdownNavItem.php +++ b/src/Framework/Features/Navigation/DropdownNavItem.php @@ -26,11 +26,13 @@ public function __construct(string $label, array $items, ?int $priority = null) $this->items = $items; } + /** @param array $items */ public static function fromArray(string $name, array $items): static { return new static($name, $items); } + /** @return Collection */ public function getItems(): Collection { return collect($this->items); @@ -38,10 +40,13 @@ public function getItems(): Collection private function searchForDropdownPriorityInNavigationConfig(string $groupKey): ?int { - return Config::getArray('hyde.navigation.order', [ + /** @var array $config */ + $config = Config::getArray('hyde.navigation.order', [ 'index' => 0, 'posts' => 10, 'docs/index' => 100, - ])[$groupKey] ?? null; + ]); + + return $config[$groupKey] ?? null; } } diff --git a/src/Framework/Services/BuildTaskService.php b/src/Framework/Services/BuildTaskService.php index 2e58293b..a976526e 100644 --- a/src/Framework/Services/BuildTaskService.php +++ b/src/Framework/Services/BuildTaskService.php @@ -42,7 +42,7 @@ public function __construct() { $this->registerFrameworkTasks(); - $this->registerTasks(Config::getArray('hyde.build_tasks', [])); + $this->registerTasks($this->findTasksInConfig()); $this->registerTasks($this->findTasksInAppDirectory()); } @@ -52,7 +52,7 @@ public function setOutput(?OutputStyle $output): void $this->output = $output; } - /** @return array> */ + /** @return array|class-string<\Hyde\Framework\Features\BuildTasks\PostBuildTask>> */ public function getRegisteredTasks(): array { return array_map(fn (BuildTask $task): string => $task::class, array_values($this->buildTasks)); @@ -87,6 +87,7 @@ protected function registerTaskInService(PreBuildTask|PostBuildTask $task): void $this->buildTasks[$this->makeTaskIdentifier($task)] = $task; } + /** @param class-string<\Hyde\Framework\Features\BuildTasks\PreBuildTask|\Hyde\Framework\Features\BuildTasks\PostBuildTask> $task */ protected function registerIf(string $task, bool $condition): void { if ($condition) { @@ -94,6 +95,7 @@ protected function registerIf(string $task, bool $condition): void } } + /** @param array<\Hyde\Framework\Features\BuildTasks\PreBuildTask|\Hyde\Framework\Features\BuildTasks\PostBuildTask|class-string<\Hyde\Framework\Features\BuildTasks\PreBuildTask|\Hyde\Framework\Features\BuildTasks\PostBuildTask>> $tasks */ protected function registerTasks(array $tasks): void { foreach ($tasks as $task) { @@ -101,6 +103,13 @@ protected function registerTasks(array $tasks): void } } + /** @return array|class-string<\Hyde\Framework\Features\BuildTasks\PostBuildTask>> */ + protected function findTasksInConfig(): array + { + return Config::getArray('hyde.build_tasks', []); + } + + /** @return array|class-string<\Hyde\Framework\Features\BuildTasks\PostBuildTask>> */ protected function findTasksInAppDirectory(): array { return Filesystem::smartGlob('app/Actions/*BuildTask.php')->map(function (string $file): string { From 2e551410168b6ba68708041f49499da859d4bd98 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 28 Oct 2023 18:25:39 +0000 Subject: [PATCH 14/20] Merge pull request #1411 from hydephp/code-quality General code quality cleanups https://github.com/hydephp/develop/commit/c00dbf462b5fa3fcf9a35f635e0ce3103534169a --- src/Facades/Config.php | 3 ++- .../Features/Metadata/MetadataBag.php | 19 ++++++------------- tests/Feature/TypedConfigFacadeTest.php | 9 +++++++++ .../HyperlinksUrlPathHelpersTest.php | 3 +-- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/Facades/Config.php b/src/Facades/Config.php index aaaa51d5..cc0c3b9a 100644 --- a/src/Facades/Config.php +++ b/src/Facades/Config.php @@ -7,6 +7,7 @@ use TypeError; use function sprintf; +use function call_user_func; /** * An extension of the Laravel Config facade with extra @@ -56,7 +57,7 @@ public static function getNullableString(string $key, string $default = null): ? protected static function validated(mixed $value, string $type, string $key): mixed { - if (! ("is_$type")($value)) { + if (! call_user_func("is_$type", $value)) { throw new TypeError(sprintf('%s(): Config value %s must be of type %s, %s given', __METHOD__, $key, $type, gettype($value))); } diff --git a/src/Framework/Features/Metadata/MetadataBag.php b/src/Framework/Features/Metadata/MetadataBag.php index 5d0c2aa4..ff8a036d 100644 --- a/src/Framework/Features/Metadata/MetadataBag.php +++ b/src/Framework/Features/Metadata/MetadataBag.php @@ -54,19 +54,12 @@ public function get(): array public function add(MetadataElementContract|string $element): static { - if ($element instanceof LinkElement) { - return $this->addElement('links', $element); - } - - if ($element instanceof MetadataElement) { - return $this->addElement('metadata', $element); - } - - if ($element instanceof OpenGraphElement) { - return $this->addElement('properties', $element); - } - - return $this->addGenericElement((string) $element); + return match (true) { + $element instanceof LinkElement => $this->addElement('links', $element), + $element instanceof MetadataElement => $this->addElement('metadata', $element), + $element instanceof OpenGraphElement => $this->addElement('properties', $element), + default => $this->addGenericElement((string) $element), + }; } protected function addElement(string $type, MetadataElementContract $element): static diff --git a/tests/Feature/TypedConfigFacadeTest.php b/tests/Feature/TypedConfigFacadeTest.php index e2166653..2f0afd3e 100644 --- a/tests/Feature/TypedConfigFacadeTest.php +++ b/tests/Feature/TypedConfigFacadeTest.php @@ -7,6 +7,7 @@ use Hyde\Facades\Config; use Hyde\Testing\TestCase; use TypeError; +use stdClass; use function config; @@ -159,6 +160,14 @@ public function testGetNullableString() $this->assertNull(Config::getNullableString('foo')); } + public function testInvalidTypeMessage() + { + config(['foo' => new stdClass()]); + $this->expectException(TypeError::class); + $this->expectExceptionMessage('Hyde\Facades\Config::validated(): Config value foo must be of type array, object given'); + Config::getArray('foo'); + } + protected function runUnitTest($actual, $expected, $method): void { config(['foo' => $actual]); diff --git a/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php b/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php index 4e7811aa..8a400d7a 100644 --- a/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php +++ b/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php @@ -10,8 +10,7 @@ use Hyde\Testing\TestCase; /** - * @covers \Hyde\Foundation\Kernel\Hyperlinks::hasSiteUrl - * @covers \Hyde\Foundation\Kernel\Hyperlinks::url + * @covers \Hyde\Foundation\Kernel\Hyperlinks * @covers \Hyde\Framework\Exceptions\BaseUrlNotSetException */ class HyperlinksUrlPathHelpersTest extends TestCase From 1a645df1ffe819eeffebded596a3beb6d5e394e0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 28 Oct 2023 18:59:40 +0000 Subject: [PATCH 15/20] Merge pull request #1412 from hydephp/set-build-flag-in-runtime-configuration Add runtime configuration option for the `--no-api` build flag https://github.com/hydephp/develop/commit/285f8195488e0eb2a34e8e2be55ee369fdf32b33 --- src/Foundation/Internal/LoadConfiguration.php | 5 +++++ src/Framework/Features/Blogging/Models/FeaturedImage.php | 3 +-- tests/Unit/LoadConfigurationTest.php | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Foundation/Internal/LoadConfiguration.php b/src/Foundation/Internal/LoadConfiguration.php index 3bf2a204..b4b51bf4 100644 --- a/src/Foundation/Internal/LoadConfiguration.php +++ b/src/Foundation/Internal/LoadConfiguration.php @@ -85,6 +85,11 @@ private function loadRuntimeConfiguration(Application $app, RepositoryContract $ if (in_array('--pretty-urls', $_SERVER['argv'], true)) { $repository->set('hyde.pretty_urls', true); } + + // Check if the `--no-api` CLI argument is set, and if so, set the config value accordingly. + if (in_array('--no-api', $_SERVER['argv'], true)) { + $repository->set('hyde.api_calls', false); + } } } } diff --git a/src/Framework/Features/Blogging/Models/FeaturedImage.php b/src/Framework/Features/Blogging/Models/FeaturedImage.php index 71bf71ee..ac016f42 100644 --- a/src/Framework/Features/Blogging/Models/FeaturedImage.php +++ b/src/Framework/Features/Blogging/Models/FeaturedImage.php @@ -13,7 +13,6 @@ use Hyde\Framework\Exceptions\FileNotFoundException; use Hyde\Markdown\Contracts\FrontMatter\SubSchemas\FeaturedImageSchema; -use function in_array; use function array_key_exists; use function array_flip; use function file_exists; @@ -226,7 +225,7 @@ protected function getContentLengthForLocalImage(): int protected function getContentLengthForRemoteImage(): int { // Check if the --no-api flag is set when running the build command, and if so, skip the API call. - if (! (isset($_SERVER['argv']) && in_array('--no-api', $_SERVER['argv'], true))) { + if (Config::getBool('hyde.api_calls', true)) { $headers = Http::withHeaders([ 'User-Agent' => Config::getString('hyde.http_user_agent', 'RSS Request Client'), ])->head($this->getSource())->headers(); diff --git a/tests/Unit/LoadConfigurationTest.php b/tests/Unit/LoadConfigurationTest.php index 15bcbf7a..d1125608 100644 --- a/tests/Unit/LoadConfigurationTest.php +++ b/tests/Unit/LoadConfigurationTest.php @@ -17,7 +17,7 @@ public function testItLoadsRuntimeConfiguration() { $serverBackup = $_SERVER; - $_SERVER['argv'] = ['--pretty-urls']; + $_SERVER['argv'] = ['--pretty-urls', '--no-api']; $app = new Application(getcwd()); @@ -25,10 +25,12 @@ public function testItLoadsRuntimeConfiguration() $loader->bootstrap($app); $this->assertTrue(config('hyde.pretty_urls')); + $this->assertFalse(config('hyde.api_calls')); $_SERVER = $serverBackup; $loader->bootstrap($app); $this->assertFalse(config('hyde.pretty_urls')); + $this->assertNull(config('hyde.api_calls')); } } From 0ec601c7009d9ac5822bec40fdcadc639865f0a6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 29 Oct 2023 10:03:36 +0000 Subject: [PATCH 16/20] Merge pull request #1413 from hydephp/refactor-colored-blockquote-internals Refactor colored blockquote internals to extract class name from signature https://github.com/hydephp/develop/commit/0108b875c4e75f7275afc15eac099688dbbcf843 --- .../Processing/ColoredBlockquotes.php | 72 +++++++++---------- .../Processing/ShortcodeProcessor.php | 12 +++- .../ColoredBlockquoteShortcodesTest.php | 29 +++++--- .../Markdown/ShortcodeProcessorTest.php | 21 ++++++ 4 files changed, 84 insertions(+), 50 deletions(-) diff --git a/src/Markdown/Processing/ColoredBlockquotes.php b/src/Markdown/Processing/ColoredBlockquotes.php index 835f435d..f37d807b 100644 --- a/src/Markdown/Processing/ColoredBlockquotes.php +++ b/src/Markdown/Processing/ColoredBlockquotes.php @@ -7,19 +7,22 @@ use Hyde\Markdown\Contracts\MarkdownShortcodeContract; use Hyde\Markdown\Models\Markdown; -use function str_replace; +use function ltrim; +use function explode; use function sprintf; use function str_starts_with; -use function strlen; -use function substr; use function trim; /** - * @internal This class may be refactored to work with a single class instead of five, thus extending this class is discouraged. + * @internal This class may be refactored further, thus extending this class is discouraged. */ -abstract class ColoredBlockquotes implements MarkdownShortcodeContract +class ColoredBlockquotes implements MarkdownShortcodeContract { - protected static string $signature = '>color'; + /** @var string The core signature. We combine this with an additional check for color later. */ + protected static string $signature = '>'; + + /** @var array */ + protected static array $signatures = ['>danger', '>info', '>success', '>warning']; public static function signature(): string { @@ -28,49 +31,40 @@ public static function signature(): string public static function resolve(string $input): string { - return str_starts_with($input, static::signature()) + return self::stringStartsWithSignature($input) ? static::expand($input) : $input; } - protected static function expand(string $input): string + /** + * @internal + * + * @return array + */ + public static function getSignatures(): array { - return sprintf( - '
%s
', - static::getClassNameFromSignature(static::signature()), - trim(Markdown::render(trim(substr($input, strlen(static::signature())), ' '))) - ); + return self::$signatures; } - protected static function getClassNameFromSignature(string $signature): string + protected static function expand(string $input): string { - return str_replace('>', '', $signature); + $parts = explode(' ', $input, 2); + $class = ltrim($parts[0], '>'); + $contents = trim($parts[1] ?? '', ' '); + + return sprintf('
%s
', + $class, trim(Markdown::render($contents)) + ); } - /** @return ColoredBlockquotes[] */ - public static function get(): array + protected static function stringStartsWithSignature(string $input): bool { - return [ - /** @internal */ - new class extends ColoredBlockquotes - { - protected static string $signature = '>danger'; - }, - /** @internal */ - new class extends ColoredBlockquotes - { - protected static string $signature = '>info'; - }, - /** @internal */ - new class extends ColoredBlockquotes - { - protected static string $signature = '>success'; - }, - /** @internal */ - new class extends ColoredBlockquotes - { - protected static string $signature = '>warning'; - }, - ]; + foreach (static::$signatures as $signature) { + if (str_starts_with($input, $signature)) { + return true; + } + } + + return false; } } diff --git a/src/Markdown/Processing/ShortcodeProcessor.php b/src/Markdown/Processing/ShortcodeProcessor.php index c9cf4d3f..2f28c91e 100644 --- a/src/Markdown/Processing/ShortcodeProcessor.php +++ b/src/Markdown/Processing/ShortcodeProcessor.php @@ -97,9 +97,15 @@ public function addShortcode(MarkdownShortcodeContract $shortcode): void protected function discoverShortcodes(): void { - $this->addShortcodesFromArray( - ColoredBlockquotes::get() - ); + // Add the built-in shortcodes. + + foreach (ColoredBlockquotes::getSignatures() as $signature) { + $this->shortcodes[$signature] = new ColoredBlockquotes(); + } + + $this->addShortcodesFromArray([ + // + ]); } protected function getOutput(): string diff --git a/tests/Feature/ColoredBlockquoteShortcodesTest.php b/tests/Feature/ColoredBlockquoteShortcodesTest.php index 1c51a624..063429d9 100644 --- a/tests/Feature/ColoredBlockquoteShortcodesTest.php +++ b/tests/Feature/ColoredBlockquoteShortcodesTest.php @@ -14,27 +14,40 @@ */ class ColoredBlockquoteShortcodesTest extends UnitTestCase { - public function testGetMethod() + public function testSignature() { - $this->assertCount(4, ColoredBlockquotes::get()); - $this->assertContainsOnlyInstancesOf(ColoredBlockquotes::class, - ColoredBlockquotes::get() + $this->assertSame('>', ColoredBlockquotes::signature()); + } + + public function testSignatures() + { + $this->assertSame( + ['>danger', '>info', '>success', '>warning'], + ColoredBlockquotes::getSignatures() ); } public function testResolveMethod() { $this->assertSame( - '

foo

', - ColoredBlockquotes::resolve('>color foo') + '

foo

', + ColoredBlockquotes::resolve('>info foo') ); } public function testCanUseMarkdownWithinBlockquote() { $this->assertSame( - '

foo bar

', - ColoredBlockquotes::resolve('>color foo **bar**') + '

foo bar

', + ColoredBlockquotes::resolve('>info foo **bar**') + ); + } + + public function testWithUnrelatedClass() + { + $this->assertSame( + '>foo foo', + ColoredBlockquotes::resolve('>foo foo') ); } } diff --git a/tests/Feature/Services/Markdown/ShortcodeProcessorTest.php b/tests/Feature/Services/Markdown/ShortcodeProcessorTest.php index e44d55ee..559c1c84 100644 --- a/tests/Feature/Services/Markdown/ShortcodeProcessorTest.php +++ b/tests/Feature/Services/Markdown/ShortcodeProcessorTest.php @@ -62,4 +62,25 @@ public static function resolve(string $input): string $this->assertArrayHasKey('foo', $processor->getShortcodes()); $this->assertEquals('bar', $processor->run()); } + + public function test_shortcodes_can_be_added_to_processor_using_array() + { + $processor = new ShortcodeProcessor('foo'); + + $processor->addShortcodesFromArray([new class implements MarkdownShortcodeContract + { + public static function signature(): string + { + return 'foo'; + } + + public static function resolve(string $input): string + { + return 'bar'; + } + }]); + + $this->assertArrayHasKey('foo', $processor->getShortcodes()); + $this->assertEquals('bar', $processor->run()); + } } From c3504dad928bc0c839cbd8ad8a0f369a0a503b56 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 29 Oct 2023 13:41:26 +0000 Subject: [PATCH 17/20] Merge pull request #1414 from hydephp/code-quality Additional minor code quality and type improvements https://github.com/hydephp/develop/commit/a121e9cc478bd877d7b5b06ea9c7cc5602d8227e --- src/Console/Commands/BuildSiteCommand.php | 17 +++++++++++++---- src/Console/Commands/DebugCommand.php | 5 ++++- src/Console/Commands/MakePageCommand.php | 7 ++++++- src/Facades/Config.php | 1 + src/Facades/Filesystem.php | 1 - .../Internal/LoadYamlConfiguration.php | 2 ++ .../PreBuildTasks/CleanSiteDirectory.php | 4 +++- .../Factories/NavigationDataFactory.php | 19 ++++++++++++++----- .../Blogging/Models/FeaturedImage.php | 1 + src/Framework/Features/Navigation/NavItem.php | 5 ++++- .../XmlGenerators/SitemapGenerator.php | 4 ++-- src/Framework/Services/ValidationService.php | 3 ++- .../Processing/CodeblockFilepathProcessor.php | 1 + src/Pages/DocumentationPage.php | 11 ++++++++--- src/Support/BuildWarnings.php | 14 ++++++++++---- 15 files changed, 71 insertions(+), 24 deletions(-) diff --git a/src/Console/Commands/BuildSiteCommand.php b/src/Console/Commands/BuildSiteCommand.php index b7458af6..0de82bb3 100644 --- a/src/Console/Commands/BuildSiteCommand.php +++ b/src/Console/Commands/BuildSiteCommand.php @@ -46,8 +46,7 @@ public function handle(): int $this->service = new BuildService($this->output); - $this->taskService = app(BuildTaskService::class); - $this->taskService->setOutput($this->output); + $this->configureBuildTaskService(); $this->runPreBuildActions(); @@ -62,11 +61,21 @@ public function handle(): int return $this->getExitCode(); } + protected function configureBuildTaskService(): void + { + /** @var BuildTaskService $taskService */ + $taskService = app(BuildTaskService::class); + + $this->taskService = $taskService; + $this->taskService->setOutput($this->output); + } + protected function runPreBuildActions(): void { if ($this->option('no-api')) { $this->info('Disabling external API calls'); $this->newLine(); + /** @var array $config */ $config = Config::getArray('hyde.features', []); unset($config[array_search('torchlight', $config)]); Config::set(['hyde.features' => $config]); @@ -132,7 +141,7 @@ protected function runNodeCommand(string $command, string $message, ?string $act $output = shell_exec(sprintf( '%s%s', - app()->environment() === 'testing' ? 'echo ' : '', + (string) app()->environment() === 'testing' ? 'echo ' : '', $command )); @@ -150,7 +159,7 @@ protected function hasWarnings(): bool protected function getExitCode(): int { if ($this->hasWarnings() && BuildWarnings::reportsWarningsAsExceptions()) { - return self::INVALID; + return Command::INVALID; } return Command::SUCCESS; diff --git a/src/Console/Commands/DebugCommand.php b/src/Console/Commands/DebugCommand.php index ab9b34b9..cf8db2f3 100644 --- a/src/Console/Commands/DebugCommand.php +++ b/src/Console/Commands/DebugCommand.php @@ -70,7 +70,10 @@ protected function printVerbosePathInformation(): void protected function printEnabledFeatures(): void { - foreach (Config::getArray('hyde.features') as $feature) { + /** @var array $features */ + $features = Config::getArray('hyde.features', []); + + foreach ($features as $feature) { $this->line(" - $feature"); } } diff --git a/src/Console/Commands/MakePageCommand.php b/src/Console/Commands/MakePageCommand.php index bbcc6210..d5edac94 100644 --- a/src/Console/Commands/MakePageCommand.php +++ b/src/Console/Commands/MakePageCommand.php @@ -80,7 +80,7 @@ protected function validateOptions(): void protected function getTitle(): string { return $this->argument('title') - ?? $this->ask('What is the title of the page?') + ?? $this->askForString('What is the title of the page?') ?? 'My New Page'; } @@ -116,4 +116,9 @@ protected function getTypeOption(): ?string return null; } + + protected function askForString(string $question, ?string $default = null): ?string + { + return $this->ask($question, $default); + } } diff --git a/src/Facades/Config.php b/src/Facades/Config.php index cc0c3b9a..405aa727 100644 --- a/src/Facades/Config.php +++ b/src/Facades/Config.php @@ -46,6 +46,7 @@ public static function getFloat(string $key, float $default = null): float /** @experimental Could possibly be merged by allowing null returns if default is null? Preferably with generics so the type is matched by IDE support. */ public static function getNullableString(string $key, string $default = null): ?string { + /** @var array|string|int|bool|float|null $value */ $value = static::get($key, $default); if ($value === null) { diff --git a/src/Facades/Filesystem.php b/src/Facades/Filesystem.php index 56991dd0..3229bc58 100644 --- a/src/Facades/Filesystem.php +++ b/src/Facades/Filesystem.php @@ -7,7 +7,6 @@ use Hyde\Foundation\HydeKernel; use Hyde\Framework\Concerns\Internal\ForwardsIlluminateFilesystem; use Illuminate\Support\Collection; -use Illuminate\Support\Facades\File; use function app; diff --git a/src/Foundation/Internal/LoadYamlConfiguration.php b/src/Foundation/Internal/LoadYamlConfiguration.php index 47fb8f66..59fcc1da 100644 --- a/src/Foundation/Internal/LoadYamlConfiguration.php +++ b/src/Foundation/Internal/LoadYamlConfiguration.php @@ -45,6 +45,7 @@ protected function hasYamlConfigFile(): bool || file_exists(Hyde::path('hyde.yaml')); } + /** @return array */ protected function getYaml(): array { return (array) Yaml::parse(file_get_contents($this->getFile())); @@ -64,6 +65,7 @@ protected function mergeParsedConfiguration(): void // If the Yaml file contains namespaces, we merge those using more granular logic // that only applies the namespace data to each configuration namespace. if ($this->configurationContainsNamespaces($yaml)) { + /** @var array> $yaml */ foreach ($yaml as $namespace => $data) { $this->mergeConfiguration($namespace, (array) $data); } diff --git a/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php b/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php index d03c6a9d..f00e37ce 100644 --- a/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php +++ b/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php @@ -61,6 +61,8 @@ protected function askIfUnsafeDirectoryShouldBeEmptied(): bool protected function safeOutputDirectories(): array { /** @var array $directories */ - return Config::getArray('hyde.safe_output_directories', ['_site', 'docs', 'build']); + $directories = Config::getArray('hyde.safe_output_directories', ['_site', 'docs', 'build']); + + return $directories; } } diff --git a/src/Framework/Factories/NavigationDataFactory.php b/src/Framework/Factories/NavigationDataFactory.php index 3068855c..dd6d9a8f 100644 --- a/src/Framework/Factories/NavigationDataFactory.php +++ b/src/Framework/Factories/NavigationDataFactory.php @@ -139,10 +139,13 @@ private function searchForPriorityInFrontMatter(): ?int private function searchForLabelInConfig(): ?string { - return Config::getArray('hyde.navigation.labels', [ + /** @var array $config */ + $config = Config::getArray('hyde.navigation.labels', [ 'index' => 'Home', DocumentationPage::homeRouteName() => 'Docs', - ])[$this->routeKey] ?? null; + ]); + + return $config[$this->routeKey] ?? null; } private function searchForPriorityInConfigs(): ?int @@ -160,19 +163,25 @@ private function searchForPriorityInSidebarConfig(): ?int // Adding an offset makes so that pages with a front matter priority that is lower can be shown first. // This is all to make it easier to mix ways of adding priorities. + /** @var array $config */ + $config = Config::getArray('docs.sidebar_order', []); + return $this->offset( - array_flip(Config::getArray('docs.sidebar_order', []))[$this->identifier] ?? null, + array_flip($config)[$this->identifier] ?? null, self::CONFIG_OFFSET ); } private function searchForPriorityInNavigationConfig(): ?int { - return Config::getArray('hyde.navigation.order', [ + /** @var array $config */ + $config = Config::getArray('hyde.navigation.order', [ 'index' => 0, 'posts' => 10, 'docs/index' => 100, - ])[$this->routeKey] ?? null; + ]); + + return $config[$this->routeKey] ?? null; } private function canUseSubdirectoryForGroups(): bool diff --git a/src/Framework/Features/Blogging/Models/FeaturedImage.php b/src/Framework/Features/Blogging/Models/FeaturedImage.php index ac016f42..02b2ab3e 100644 --- a/src/Framework/Features/Blogging/Models/FeaturedImage.php +++ b/src/Framework/Features/Blogging/Models/FeaturedImage.php @@ -226,6 +226,7 @@ protected function getContentLengthForRemoteImage(): int { // Check if the --no-api flag is set when running the build command, and if so, skip the API call. if (Config::getBool('hyde.api_calls', true)) { + /** @var string[][] $headers */ $headers = Http::withHeaders([ 'User-Agent' => Config::getString('hyde.http_user_agent', 'RSS Request Client'), ])->head($this->getSource())->headers(); diff --git a/src/Framework/Features/Navigation/NavItem.php b/src/Framework/Features/Navigation/NavItem.php index db775d43..7a57b554 100644 --- a/src/Framework/Features/Navigation/NavItem.php +++ b/src/Framework/Features/Navigation/NavItem.php @@ -125,7 +125,10 @@ public function isCurrent(): bool protected static function getRouteGroup(Route $route): ?string { - return static::normalizeGroupKey($route->getPage()->data('navigation.group')); + /** @var string|null $group */ + $group = $route->getPage()->data('navigation.group'); + + return static::normalizeGroupKey($group); } protected static function normalizeGroupKey(?string $group): ?string diff --git a/src/Framework/Features/XmlGenerators/SitemapGenerator.php b/src/Framework/Features/XmlGenerators/SitemapGenerator.php index 933f1e61..64b5690c 100644 --- a/src/Framework/Features/XmlGenerators/SitemapGenerator.php +++ b/src/Framework/Features/XmlGenerators/SitemapGenerator.php @@ -8,6 +8,7 @@ use Hyde\Hyde; use SimpleXMLElement; +use Hyde\Facades\Config; use Hyde\Pages\BladePage; use Hyde\Pages\MarkdownPage; use Hyde\Pages\MarkdownPost; @@ -18,7 +19,6 @@ use function filemtime; use function in_array; -use function config; use function date; use function time; @@ -61,7 +61,7 @@ protected function addRoute(Route $route): void $this->addChild($urlItem, 'lastmod', $this->getLastModDate($route->getSourcePath())); $this->addChild($urlItem, 'changefreq', 'daily'); - if (config('hyde.sitemap.dynamic_priority', true)) { + if (Config::getBool('hyde.sitemap.dynamic_priority', true)) { $this->addChild($urlItem, 'priority', $this->getPriority( $route->getPageClass(), $route->getPage()->getIdentifier() )); diff --git a/src/Framework/Services/ValidationService.php b/src/Framework/Services/ValidationService.php index 44023770..da7c0fa7 100644 --- a/src/Framework/Services/ValidationService.php +++ b/src/Framework/Services/ValidationService.php @@ -13,6 +13,7 @@ use Hyde\Support\Models\ValidationResult as Result; use function count; +use function call_user_func; use function get_class_methods; use function array_intersect; use function file_exists; @@ -38,7 +39,7 @@ public static function checks(): array public function run(string $check): Result { - return $this->$check(new Result); + return call_user_func([$this, $check], new Result); } public function check_validators_can_run(Result $result): Result diff --git a/src/Markdown/Processing/CodeblockFilepathProcessor.php b/src/Markdown/Processing/CodeblockFilepathProcessor.php index b75f9125..97070ebb 100644 --- a/src/Markdown/Processing/CodeblockFilepathProcessor.php +++ b/src/Markdown/Processing/CodeblockFilepathProcessor.php @@ -28,6 +28,7 @@ class CodeblockFilepathProcessor implements MarkdownPreProcessorContract, Markdo { protected static string $torchlightKey = ''; + /** @var array */ protected static array $patterns = [ '// filepath: ', '// filepath ', diff --git a/src/Pages/DocumentationPage.php b/src/Pages/DocumentationPage.php index 79bba5cf..2dd04b03 100644 --- a/src/Pages/DocumentationPage.php +++ b/src/Pages/DocumentationPage.php @@ -10,6 +10,11 @@ use Hyde\Pages\Concerns\BaseMarkdownPage; use Hyde\Support\Models\Route; +use function trim; +use function sprintf; +use function unslash; +use function basename; + /** * Page class for documentation pages. * @@ -37,16 +42,16 @@ public static function homeRouteName(): string /** @see https://hydephp.com/docs/1.x/documentation-pages#automatic-edit-page-button */ public function getOnlineSourcePath(): string|false { - if (config('docs.source_file_location_base') === null) { + if (Config::getNullableString('docs.source_file_location_base') === null) { return false; } - return trim((string) config('docs.source_file_location_base'), '/').'/'.$this->identifier.'.md'; + return sprintf('%s/%s.md', trim(Config::getString('docs.source_file_location_base'), '/'), $this->identifier); } public static function hasTableOfContents(): bool { - return config('docs.table_of_contents.enabled', true); + return Config::getBool('docs.table_of_contents.enabled', true); } /** diff --git a/src/Support/BuildWarnings.php b/src/Support/BuildWarnings.php index 99f9fd13..84a0db7f 100644 --- a/src/Support/BuildWarnings.php +++ b/src/Support/BuildWarnings.php @@ -18,10 +18,10 @@ */ class BuildWarnings { - /** @var array */ + /** @var array<\Hyde\Framework\Exceptions\BuildWarning> */ protected array $warnings = []; - public static function getInstance(): static + public static function getInstance(): self { $app = Container::getInstance(); @@ -29,7 +29,10 @@ public static function getInstance(): static $app->singleton(self::class); } - return $app->make(self::class); + /** @var \Hyde\Support\BuildWarnings $instance */ + $instance = $app->make(self::class); + + return $instance; } public static function report(BuildWarning|string $warning): void @@ -79,8 +82,11 @@ protected static function renderWarnings(OutputStyle $output, bool $verbose): vo protected static function renderWarningsAsExceptions(OutputStyle $output): void { + /** @var ExceptionHandler $handler */ + $handler = app(ExceptionHandler::class); + foreach (static::getWarnings() as $warning) { - app(ExceptionHandler::class)->renderForConsole($output, $warning); + $handler->renderForConsole($output, $warning); } } } From 0724521e65d81d21618d42bafd8bdf9490141e67 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 29 Oct 2023 13:50:43 +0000 Subject: [PATCH 18/20] Merge pull request #1416 from hydephp/add-base-command-ask-for-string-helper Extract a shared base Command method for asking for a string https://github.com/hydephp/develop/commit/65c81dfae1742f0a9fb1abfff9d912786b1655f5 --- src/Console/Commands/MakePageCommand.php | 7 +---- src/Console/Commands/MakePostCommand.php | 6 ---- src/Console/Concerns/Command.php | 9 ++++++ tests/Feature/CommandTest.php | 40 ++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/Console/Commands/MakePageCommand.php b/src/Console/Commands/MakePageCommand.php index d5edac94..e3f47510 100644 --- a/src/Console/Commands/MakePageCommand.php +++ b/src/Console/Commands/MakePageCommand.php @@ -9,7 +9,7 @@ use Hyde\Pages\BladePage; use Hyde\Pages\DocumentationPage; use Hyde\Pages\MarkdownPage; -use LaravelZero\Framework\Commands\Command; +use Hyde\Console\Concerns\Command; use function strtolower; use function ucfirst; @@ -116,9 +116,4 @@ protected function getTypeOption(): ?string return null; } - - protected function askForString(string $question, ?string $default = null): ?string - { - return $this->ask($question, $default); - } } diff --git a/src/Console/Commands/MakePostCommand.php b/src/Console/Commands/MakePostCommand.php index 7346949c..510784e2 100644 --- a/src/Console/Commands/MakePostCommand.php +++ b/src/Console/Commands/MakePostCommand.php @@ -8,7 +8,6 @@ use Hyde\Console\Concerns\Command; use Hyde\Framework\Actions\CreatesNewMarkdownPostFile; -use function is_string; use function sprintf; use function ucwords; @@ -99,9 +98,4 @@ protected function createPostFile(CreatesNewMarkdownPostFile $creator): int return (int) $exception->getCode(); } } - - protected function askForString(string $question, ?string $default = null): ?string - { - return is_string($answer = $this->output->ask($question, $default)) ? $answer : null; - } } diff --git a/src/Console/Concerns/Command.php b/src/Console/Concerns/Command.php index 0eff7580..00274510 100644 --- a/src/Console/Concerns/Command.php +++ b/src/Console/Concerns/Command.php @@ -9,6 +9,7 @@ use Hyde\Facades\Config; use LaravelZero\Framework\Commands\Command as BaseCommand; +use function is_string; use function array_keys; use function array_values; use function realpath; @@ -128,4 +129,12 @@ public function indentedLine(int $spaces, string $string): void { $this->line(str_repeat(' ', $spaces).$string); } + + public function askForString(string $question, ?string $default = null): ?string + { + /** @var string|null $answer */ + $answer = $this->output->ask($question, $default); + + return is_string($answer) ? $answer : $default; + } } diff --git a/tests/Feature/CommandTest.php b/tests/Feature/CommandTest.php index cab20e33..68424a5e 100644 --- a/tests/Feature/CommandTest.php +++ b/tests/Feature/CommandTest.php @@ -215,6 +215,39 @@ public function testCanEnableThrowOnException() $this->assertSame(1, $code); } + public function testAskForString() + { + $this->testOutput(function ($command) { + $this->assertSame('foo', $command->askForString('foo')); + }, function ($output) { + $output->shouldReceive('ask')->once()->withArgs(function (string $question, ?string $default): bool { + return $this->assertIsSame('foo', $question) && $this->assertIsNull($default); + })->andReturn('foo'); + }); + } + + public function testAskForStringWithDefaultValue() + { + $this->testOutput(function ($command) { + $this->assertSame('foo', $command->askForString('foo', 'bar')); + }, function ($output) { + $output->shouldReceive('ask')->once()->withArgs(function (string $question, ?string $default): bool { + return $this->assertIsSame('foo', $question) && $this->assertIsSame('bar', $default); + })->andReturn('foo'); + }); + } + + public function testAskForStringWithDefaultValueSupplyingNull() + { + $this->testOutput(function ($command) { + $this->assertSame('bar', $command->askForString('foo', 'bar')); + }, function ($output) { + $output->shouldReceive('ask')->once()->withArgs(function (string $question, ?string $default): bool { + return $this->assertIsSame('foo', $question) && $this->assertIsSame('bar', $default); + })->andReturn(null); + }); + } + protected function assertIsSame(string $expected, string $actual): bool { $this->assertSame($expected, $actual); @@ -222,6 +255,13 @@ protected function assertIsSame(string $expected, string $actual): bool return $actual === $expected; } + protected function assertIsNull(mixed $expected): bool + { + $this->assertNull($expected); + + return $expected === null; + } + protected function testOutput(Closure $closure, Closure $expectations = null): void { $command = new MockableTestCommand(); From 55e1f18d135aebf75994f91eb3582dfce86a434e Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 29 Oct 2023 14:12:06 +0000 Subject: [PATCH 19/20] Merge pull request #1417 from hydephp/code-quality Clean up test https://github.com/hydephp/develop/commit/5ad417a91a1e62027cef451e128457d17c380cbd --- tests/Unit/BuildTaskServiceUnitTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Unit/BuildTaskServiceUnitTest.php b/tests/Unit/BuildTaskServiceUnitTest.php index e998a2ba..1b08979d 100644 --- a/tests/Unit/BuildTaskServiceUnitTest.php +++ b/tests/Unit/BuildTaskServiceUnitTest.php @@ -111,7 +111,7 @@ public function testRegisterTaskWithoutChildExtensionThrowsException() public function testRegisterTaskWithBaseClassThrowsException() { $this->expectException(TypeError::class); - $this->service->registerTask(InstansiableTestBuildTask::class); + $this->service->registerTask(InstantiableTestBuildTask::class); } public function testRegisterTaskWithAlreadyRegisteredTask() @@ -293,9 +293,9 @@ public function testServiceFindsTasksInAppDirectory() $filesystem = Mockery::mock(Filesystem::class, [$kernel])->makePartial() ->shouldReceive('smartGlob')->once() ->with('app/Actions/*BuildTask.php', 0) - ->andReturn(collect([/** TODO */]))->getMock(); + ->andReturn(collect())->getMock(); - // Inject mock into Kernel (No better way to do this at the moment) + // Inject mock into Kernel (new ReflectionClass($kernel))->getProperty('filesystem')->setValue($kernel, $filesystem); $this->createService(); @@ -322,7 +322,7 @@ protected function verifyMockeryExpectations(): void } } -class InstansiableTestBuildTask extends BuildTask +class InstantiableTestBuildTask extends BuildTask { public function handle(): void { From e37fef95ac3bfe44e64638a5ddcea676c9607506 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 30 Oct 2023 17:39:35 +0000 Subject: [PATCH 20/20] Merge pull request #1421 from hydephp/release-v1.3.0 HydePHP v1.3.0 - 2023-10-30 https://github.com/hydephp/develop/commit/0ed0f152d6c9c8bb4f425574bc66ba2c3c6f6563 --- src/Foundation/HydeKernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Foundation/HydeKernel.php b/src/Foundation/HydeKernel.php index a4c97389..552538b2 100644 --- a/src/Foundation/HydeKernel.php +++ b/src/Foundation/HydeKernel.php @@ -49,7 +49,7 @@ class HydeKernel implements SerializableContract use Serializable; use Macroable; - final public const VERSION = '1.2.1'; + final public const VERSION = '1.3.0'; protected static self $instance;