Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
46 / 46 |
|
100.00% |
13 / 13 |
CRAP | |
100.00% |
1 / 1 |
| PublicationsExtension | |
100.00% |
46 / 46 |
|
100.00% |
13 / 13 |
18 | |
100.00% |
1 / 1 |
| getTypes | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| getPageClasses | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
| discoverFiles | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
| discoverPages | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| discoverPublicationPages | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
| generatePublicationListingPageForType | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
| generatePublicationPaginatedListingPagesForType | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
3 | |||
| generatePublicationTagPages | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| parsePublicationTypes | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
| getSchemaFiles | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getPublicationFiles | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getPublicationFilesForType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| shouldGeneratePublicationTagPages | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Hyde\Publications; |
| 6 | |
| 7 | use Hyde\Foundation\Concerns\HydeExtension; |
| 8 | use Hyde\Foundation\Facades\Files; |
| 9 | use Hyde\Foundation\Kernel\FileCollection; |
| 10 | use Hyde\Foundation\Kernel\PageCollection; |
| 11 | use Hyde\Hyde; |
| 12 | use Hyde\Pages\InMemoryPage; |
| 13 | use Hyde\Publications\Actions\GeneratesPublicationTagPages; |
| 14 | use Hyde\Publications\Models\PublicationType; |
| 15 | use Hyde\Publications\Pages\PublicationListPage; |
| 16 | use Hyde\Publications\Pages\PublicationPage; |
| 17 | use Hyde\Support\Filesystem\SourceFile; |
| 18 | use Illuminate\Support\Collection; |
| 19 | use Illuminate\Support\Str; |
| 20 | |
| 21 | use function glob; |
| 22 | use function range; |
| 23 | use function str_ends_with; |
| 24 | |
| 25 | /** |
| 26 | * @see \Hyde\Publications\Testing\Feature\PublicationsExtensionTest |
| 27 | */ |
| 28 | class PublicationsExtension extends HydeExtension |
| 29 | { |
| 30 | /** @var \Illuminate\Support\Collection<string, \Hyde\Publications\Models\PublicationType> */ |
| 31 | protected Collection $types; |
| 32 | |
| 33 | /** @return \Illuminate\Support\Collection<string, \Hyde\Publications\Models\PublicationType> */ |
| 34 | public function getTypes(): Collection |
| 35 | { |
| 36 | if (! isset($this->types)) { |
| 37 | $this->types = $this->parsePublicationTypes(); |
| 38 | } |
| 39 | |
| 40 | return $this->types; |
| 41 | } |
| 42 | |
| 43 | /** @return array<class-string<\Hyde\Pages\Concerns\HydePage>> */ |
| 44 | public static function getPageClasses(): array |
| 45 | { |
| 46 | return [ |
| 47 | // Since our page classes are not auto-discoverable by Hyde due to the dynamic source directories, |
| 48 | // we run our own discovery logic in the callbacks below. |
| 49 | ]; |
| 50 | } |
| 51 | |
| 52 | public function discoverFiles(FileCollection $collection): void |
| 53 | { |
| 54 | $this->types = $this->parsePublicationTypes(); |
| 55 | |
| 56 | $this->types->each(function (PublicationType $type) use ($collection): void { |
| 57 | Collection::make($this->getPublicationFilesForType($type))->map(function (string $filepath) use ($collection): void { |
| 58 | $collection->put(Hyde::pathToRelative($filepath), SourceFile::make($filepath, PublicationPage::class)); |
| 59 | }); |
| 60 | }); |
| 61 | } |
| 62 | |
| 63 | public function discoverPages(PageCollection $collection): void |
| 64 | { |
| 65 | $this->discoverPublicationPages($collection); |
| 66 | |
| 67 | if (self::shouldGeneratePublicationTagPages()) { |
| 68 | $this->generatePublicationTagPages($collection); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | protected function discoverPublicationPages(PageCollection $instance): void |
| 73 | { |
| 74 | Files::getFiles(PublicationPage::class)->each(function (SourceFile $file) use ($instance): void { |
| 75 | $instance->addPage(PublicationPage::parse(Str::before($file->getPath(), PublicationPage::fileExtension()))); |
| 76 | }); |
| 77 | |
| 78 | $this->types->each(function (PublicationType $type) use ($instance): void { |
| 79 | $this->generatePublicationListingPageForType($type, $instance); |
| 80 | }); |
| 81 | } |
| 82 | |
| 83 | protected function generatePublicationListingPageForType(PublicationType $type, PageCollection $instance): void |
| 84 | { |
| 85 | $page = new PublicationListPage($type); |
| 86 | $instance->put($page->getSourcePath(), $page); |
| 87 | |
| 88 | if ($type->usesPagination()) { |
| 89 | $this->generatePublicationPaginatedListingPagesForType($type, $instance); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | protected function generatePublicationPaginatedListingPagesForType(PublicationType $type, PageCollection $instance): void |
| 94 | { |
| 95 | $paginator = $type->getPaginator(); |
| 96 | |
| 97 | foreach (range(1, $paginator->totalPages()) as $page) { |
| 98 | $paginator->setCurrentPage($page); |
| 99 | $listTemplate = $type->listTemplate; |
| 100 | if (str_ends_with($listTemplate, '.blade.php')) { |
| 101 | $listTemplate = "{$type->getDirectory()}/$listTemplate"; |
| 102 | } |
| 103 | $listingPage = new InMemoryPage("{$type->getDirectory()}/page-$page", [ |
| 104 | 'publicationType' => $type, 'paginatorPage' => $page, |
| 105 | 'title' => $type->name.' - Page '.$page, |
| 106 | ], view: $listTemplate); |
| 107 | $instance->put($listingPage->getSourcePath(), $listingPage); |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | protected function generatePublicationTagPages(PageCollection $collection): void |
| 112 | { |
| 113 | (new GeneratesPublicationTagPages($collection))->__invoke(); |
| 114 | } |
| 115 | |
| 116 | /** @return Collection<string, \Hyde\Publications\Pages\PublicationPage> */ |
| 117 | protected function parsePublicationTypes(): Collection |
| 118 | { |
| 119 | return Collection::make($this->getSchemaFiles())->mapWithKeys(function (string $schemaFile): array { |
| 120 | $type = PublicationType::fromFile(Hyde::pathToRelative($schemaFile)); |
| 121 | |
| 122 | return [$type->getDirectory() => $type]; |
| 123 | }); |
| 124 | } |
| 125 | |
| 126 | protected function getSchemaFiles(): array |
| 127 | { |
| 128 | return glob(Hyde::path(Hyde::getSourceRoot()).'/*/schema.json'); |
| 129 | } |
| 130 | |
| 131 | protected function getPublicationFiles(string $directory): array |
| 132 | { |
| 133 | return glob(Hyde::path("$directory/*.md")); |
| 134 | } |
| 135 | |
| 136 | protected function getPublicationFilesForType(PublicationType $type): array |
| 137 | { |
| 138 | return $this->getPublicationFiles($type->getDirectory()); |
| 139 | } |
| 140 | |
| 141 | protected static function shouldGeneratePublicationTagPages(): bool |
| 142 | { |
| 143 | return count(Publications::getPublicationTags()) > 0; |
| 144 | } |
| 145 | } |