Skip to content

Commit 4fe2bb8

Browse files
authored
Merge pull request #679 from hydephp/refactor-publications
Add schema properties as class properties for stronger type system
2 parents 4319761 + a2b2244 commit 4fe2bb8

15 files changed

+372
-110
lines changed

packages/framework/src/Console/Commands/MakePublicationTypeCommand.php

+7-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Exception;
88
use Hyde\Console\Commands\Interfaces\CommandHandleInterface;
9-
use Hyde\Framework\Actions\CreatesNewPublicationTypeSchema;
9+
use Hyde\Framework\Actions\CreatesNewPublicationType;
1010
use Hyde\Framework\Features\Publications\PublicationHelper;
1111
use InvalidArgumentException;
1212
use LaravelZero\Framework\Commands\Command;
@@ -60,10 +60,10 @@ public function handle(): int
6060
2 => 'DESC',
6161
};
6262

63-
$pagesize = (int) PublicationHelper::askWithValidation(
63+
$pageSize = (int) PublicationHelper::askWithValidation(
6464
$this,
65-
'pagesize',
66-
'Enter the pagesize (0 for no limit)',
65+
'pageSize',
66+
'Enter the pageSize (0 for no limit)',
6767
['required', 'integer', 'between:0,100'],
6868
25
6969
);
@@ -86,14 +86,16 @@ public function handle(): int
8686
$canonicalField = $fields[$selected - 1]['name'];
8787

8888
try {
89-
$creator = new CreatesNewPublicationTypeSchema($title, $fields, $canonicalField, $sortField, $sortDirection, $pagesize, $prevNextLinks);
89+
$creator = new CreatesNewPublicationType($title, $fields, $canonicalField, $sortField, $sortDirection, $pageSize, $prevNextLinks, $this->output);
9090
$creator->create();
9191
} catch (Exception $e) {
9292
$this->error('Error: '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine());
9393

9494
return Command::FAILURE;
9595
}
9696

97+
$this->info('Publication type created successfully!');
98+
9799
return Command::SUCCESS;
98100
}
99101

packages/framework/src/Foundation/PageCollection.php

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
* This class is stored as a singleton in the HydeKernel.
2525
* You would commonly access it via one of the facades:
2626
*
27+
* @todo We could improve this by catching exceptions and rethrowing them using a
28+
* DiscoveryException to make it clear that the problem is with the discovery process.
29+
*
2730
* @see \Hyde\Foundation\Facades\PageCollection
2831
* @see \Hyde\Hyde::pages()
2932
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Hyde\Framework\Actions;
6+
7+
use Hyde\Framework\Actions\Interfaces\CreateActionInterface;
8+
use Hyde\Framework\Features\Publications\Models\PublicationType;
9+
use Hyde\Framework\Features\Publications\PublicationHelper;
10+
use Hyde\Hyde;
11+
use Illuminate\Console\OutputStyle;
12+
use Rgasch\Collection\Collection;
13+
use function sprintf;
14+
15+
/**
16+
* Scaffold a new publication type schema.
17+
*
18+
* @see \Hyde\Framework\Testing\Feature\Actions\CreatesNewPublicationTypeSchemaTest
19+
*/
20+
class CreatesNewPublicationType implements CreateActionInterface
21+
{
22+
protected string $result;
23+
24+
public function __construct(
25+
protected string $name,
26+
protected Collection $fields,
27+
protected string $canonicalField,
28+
protected string $sortField,
29+
protected string $sortDirection,
30+
protected int $pageSize,
31+
protected bool $prevNextLinks,
32+
protected ?OutputStyle $output = null,
33+
) {
34+
}
35+
36+
public function create(): void
37+
{
38+
$dirName = PublicationHelper::formatNameForStorage($this->name);
39+
$outFile = Hyde::path("$dirName/schema.json");
40+
41+
$type = new PublicationType(
42+
$this->name,
43+
$this->canonicalField,
44+
$this->sortField,
45+
$this->sortDirection,
46+
$this->pageSize,
47+
$this->prevNextLinks,
48+
"{$dirName}_detail",
49+
"{$dirName}_list",
50+
$this->fields->toArray()
51+
);
52+
53+
$this->output?->writeln(sprintf('Saving publication data to [%s]', Hyde::pathToRelative($outFile)));
54+
55+
$type->save($outFile);
56+
$this->result = $type->toJson();
57+
}
58+
59+
public function getResult(): string
60+
{
61+
return $this->result;
62+
}
63+
}

packages/framework/src/Framework/Actions/CreatesNewPublicationTypeSchema.php

-65
This file was deleted.

packages/framework/src/Framework/Features/Publications/Models/PublicationListPage.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Hyde\Hyde;
1010
use Hyde\Pages\BladePage;
1111
use Illuminate\Support\Facades\Blade;
12+
use InvalidArgumentException;
1213
use function str_contains;
1314
use function view;
1415

@@ -37,14 +38,19 @@ public function compile(): string
3738
'publications' => PublicationHelper::getPublicationsForPubType($this->type),
3839
];
3940

40-
$template = $this->type->getSchema()['listTemplate'];
41+
$template = $this->type->listTemplate;
4142
if (str_contains($template, '::')) {
4243
return view($template, $data)->render();
4344
}
4445

4546
// Using the Blade facade we can render any file without having to register the directory with the view finder.
47+
$viewPath = Hyde::path("{$this->type->getDirectory()}/$template").'.blade.php';
48+
if (! file_exists($viewPath)) {
49+
throw new InvalidArgumentException("View [$viewPath] not found.");
50+
}
51+
4652
return Blade::render(
47-
file_get_contents(Hyde::path("{$this->type->getDirectory()}/$template").'.blade.php'), $data
53+
file_get_contents($viewPath), $data
4854
);
4955
}
5056

packages/framework/src/Framework/Features/Publications/Models/PublicationType.php

+88-16
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,122 @@
44

55
namespace Hyde\Framework\Features\Publications\Models;
66

7+
use function dirname;
8+
use Exception;
9+
use function file_get_contents;
10+
use Hyde\Framework\Concerns\InteractsWithDirectories;
711
use Hyde\Hyde;
12+
use Hyde\Support\Concerns\JsonSerializesArrayable;
13+
use Illuminate\Contracts\Support\Arrayable;
14+
use Illuminate\Contracts\Support\Jsonable;
15+
use Illuminate\Support\Str;
16+
use function json_decode;
17+
use JsonSerializable;
18+
use RuntimeException;
819

9-
class PublicationType
20+
/**
21+
* @see \Hyde\Framework\Testing\Feature\PublicationTypeTest
22+
*/
23+
class PublicationType implements JsonSerializable, Jsonable, Arrayable
1024
{
11-
protected string $schemaFile;
25+
use JsonSerializesArrayable;
26+
use InteractsWithDirectories;
27+
1228
protected string $directory;
13-
protected array $schema;
1429

15-
public static function get(string $name): self
30+
public string $name;
31+
public string $canonicalField;
32+
public string $sortField;
33+
public string $sortDirection;
34+
public int $pageSize;
35+
public bool $prevNextLinks;
36+
public string $detailTemplate;
37+
public string $listTemplate;
38+
public array $fields;
39+
40+
public static function get(string $name): static
41+
{
42+
return static::fromFile(Hyde::path("$name/schema.json"));
43+
}
44+
45+
public static function fromFile(string $schemaFile): static
46+
{
47+
try {
48+
return new static(...array_merge(
49+
static::parseSchemaFile($schemaFile),
50+
static::getRelativeDirectoryName($schemaFile))
51+
);
52+
} catch (Exception $exception) {
53+
throw new RuntimeException("Could not parse schema file $schemaFile", 0, $exception);
54+
}
55+
}
56+
57+
public function __construct(string $name, string $canonicalField, string $sortField, string $sortDirection, int $pageSize, bool $prevNextLinks, string $detailTemplate, string $listTemplate, array $fields, ?string $directory = null)
1658
{
17-
return new self(Hyde::path("$name/schema.json"));
59+
$this->name = $name;
60+
$this->canonicalField = $canonicalField;
61+
$this->sortField = $sortField;
62+
$this->sortDirection = $sortDirection;
63+
$this->pageSize = $pageSize;
64+
$this->prevNextLinks = $prevNextLinks;
65+
$this->detailTemplate = $detailTemplate;
66+
$this->listTemplate = $listTemplate;
67+
$this->fields = $fields;
68+
69+
if ($directory) {
70+
$this->directory = $directory;
71+
}
1872
}
1973

20-
public function __construct(string $schemaFile)
74+
public function toArray(): array
2175
{
22-
$this->schemaFile = $schemaFile;
23-
$this->directory = Hyde::pathToRelative(dirname($schemaFile));
24-
$this->schema = static::parseSchema($schemaFile);
76+
return [
77+
'name' => $this->name,
78+
'canonicalField' => $this->canonicalField,
79+
'sortField' => $this->sortField,
80+
'sortDirection' => $this->sortDirection,
81+
'pageSize' => $this->pageSize,
82+
'prevNextLinks' => $this->prevNextLinks,
83+
'detailTemplate' => $this->detailTemplate,
84+
'listTemplate' => $this->listTemplate,
85+
'fields' => $this->fields,
86+
];
2587
}
2688

27-
public function __get(string $name): mixed
89+
public function toJson($options = JSON_PRETTY_PRINT): string
2890
{
29-
return $this->$name ?? $this->schema[$name] ?? null;
91+
return json_encode($this->toArray(), $options);
92+
}
93+
94+
public function getIdentifier(): string
95+
{
96+
return $this->directory ?? Str::slug($this->name);
3097
}
3198

3299
public function getSchemaFile(): string
33100
{
34-
return $this->schemaFile;
101+
return "$this->directory/schema.json";
35102
}
36103

37104
public function getDirectory(): string
38105
{
39106
return $this->directory;
40107
}
41108

42-
public function getSchema(): array
109+
public function save(?string $path = null): void
43110
{
44-
return $this->schema;
111+
$path ??= $this->getSchemaFile();
112+
$this->needsParentDirectory($path);
113+
file_put_contents($path, json_encode($this->toArray(), JSON_PRETTY_PRINT));
45114
}
46115

47-
protected static function parseSchema(string $schemaFile): array
116+
protected static function parseSchemaFile(string $schemaFile): array
48117
{
49118
return json_decode(file_get_contents($schemaFile), true, 512, JSON_THROW_ON_ERROR);
50119
}
51120

52-
// TODO build list pages and detail pages for each publication type
121+
protected static function getRelativeDirectoryName(string $schemaFile): array
122+
{
123+
return ['directory' => Hyde::pathToRelative(dirname($schemaFile))];
124+
}
53125
}

packages/framework/src/Framework/Features/Publications/PublicationHelper.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public static function getPublicationTypes(): Collection
7272

7373
$pubTypes = Collection::create();
7474
foreach ($schemaFiles as $schemaFile) {
75-
$publicationType = new PublicationType($schemaFile);
75+
$publicationType = PublicationType::fromFile($schemaFile);
7676
$pubTypes->{$publicationType->getDirectory()} = $publicationType;
7777
}
7878

@@ -87,7 +87,7 @@ public static function getPublicationTypes(): Collection
8787
public static function getPublicationsForPubType(PublicationType $pubType, $sort = true): Collection
8888
{
8989
$root = base_path();
90-
$files = glob("$root/{$pubType->directory}/*.md");
90+
$files = glob("$root/{$pubType->getDirectory()}/*.md");
9191

9292
$publications = Collection::create();
9393
foreach ($files as $file) {
@@ -109,7 +109,7 @@ public static function getPublicationsForPubType(PublicationType $pubType, $sort
109109
public static function getMediaForPubType(PublicationType $pubType, $sort = true): Collection
110110
{
111111
$root = Hyde::path();
112-
$files = glob("$root/_media/{$pubType->directory}/*.{jpg,jpeg,png,gif,pdf}", GLOB_BRACE);
112+
$files = glob("$root/_media/{$pubType->getDirectory()}/*.{jpg,jpeg,png,gif,pdf}", GLOB_BRACE);
113113

114114
$media = Collection::create();
115115
foreach ($files as $file) {

packages/framework/src/Pages/PublicationPage.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected function renderComponent(): string
4747
'publication' => $this,
4848
];
4949

50-
$template = $this->type->getSchema()['detailTemplate'];
50+
$template = $this->type->detailTemplate;
5151
if (str_contains($template, '::')) {
5252
return view($template, $data)->render();
5353
}

0 commit comments

Comments
 (0)