Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add schema properties as class properties for stronger type system #679

Merged
merged 100 commits into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
6f2477a
Add schema properties as class properties
caendesilva Nov 20, 2022
d5927af
Declare property types
caendesilva Nov 20, 2022
d2ade96
Deprecate protected property
caendesilva Nov 20, 2022
82b858d
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
931b420
Style
caendesilva Nov 20, 2022
f7de5de
Create PublicationTypeTest.php
caendesilva Nov 20, 2022
9627050
Link to the test
caendesilva Nov 20, 2022
bc9f061
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
928d7cc
Add static PublicationType::fromFile helper method
caendesilva Nov 20, 2022
29433a0
Use static helper instead of using new PublicationType
caendesilva Nov 20, 2022
34c9022
Generate new constructor
caendesilva Nov 20, 2022
7fed1d9
Make non schema properties optional for easier mocking
caendesilva Nov 20, 2022
dffaf20
Construct all the arguments
caendesilva Nov 20, 2022
d5303d9
Update get helper method
caendesilva Nov 20, 2022
5395be2
Remove resolved todo
caendesilva Nov 20, 2022
68f2a74
Remove deprecated array property and accessors
caendesilva Nov 20, 2022
ef87ac9
Join comma-separated values into a single line
caendesilva Nov 20, 2022
5c515ac
Implements JsonSerializable, Arrayable
caendesilva Nov 20, 2022
7e7efe4
Use JsonSerializesArrayable
caendesilva Nov 20, 2022
f5415f6
Implement toArray method
caendesilva Nov 20, 2022
d3020bf
Move up static helper methods
caendesilva Nov 20, 2022
d8bc8c1
Import functions
caendesilva Nov 20, 2022
b755695
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
7d349b3
Add base test
caendesilva Nov 20, 2022
e372985
Dynamically handle test
caendesilva Nov 20, 2022
47195e2
Test serialization
caendesilva Nov 20, 2022
8690976
Test with path information
caendesilva Nov 20, 2022
8a638c3
Refactor to handle $schemaFile dynamically
caendesilva Nov 20, 2022
4cf0ee9
Refactor test helper to be dynamic
caendesilva Nov 20, 2022
e1811ea
Implement save method
caendesilva Nov 20, 2022
46d02fc
Clean up after the test
caendesilva Nov 20, 2022
6bcef66
Allow output directory to be customized
caendesilva Nov 20, 2022
a44cb91
Ensure the directory exists
caendesilva Nov 20, 2022
709ca02
Fix test
caendesilva Nov 20, 2022
5868206
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
3ed83b0
Merge test helpers
caendesilva Nov 20, 2022
f9bc88f
Revert "Merge test helpers"
caendesilva Nov 20, 2022
c4a2b53
Make protected test helpers public static
caendesilva Nov 20, 2022
49e33f3
Use self for static method
caendesilva Nov 20, 2022
ae1f79c
Replace self with static
caendesilva Nov 20, 2022
c024768
Throw more helpful exception when schema parsing fails
caendesilva Nov 20, 2022
939f802
Add unrelated todo
caendesilva Nov 20, 2022
6252415
Revert "Make protected test helpers public static"
caendesilva Nov 20, 2022
b518e5e
Revert "Use self for static method"
caendesilva Nov 20, 2022
9ac2da1
Extract testing trait
caendesilva Nov 20, 2022
64009b8
Revert "Extract testing trait"
caendesilva Nov 20, 2022
8a55a3e
Copy over test helper method
caendesilva Nov 20, 2022
a14a51e
Use test helper method
caendesilva Nov 20, 2022
8d9b044
Use getter instead of protected property
caendesilva Nov 20, 2022
e3704d0
Update to use added class properties
caendesilva Nov 20, 2022
d478053
Check if file exists and throw more explicit exception when missing
caendesilva Nov 20, 2022
5305c3a
Update path to match test data
caendesilva Nov 20, 2022
9cb167d
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
164b7e2
Create test-publication-schema.json
caendesilva Nov 20, 2022
c1388b0
Use testing fixture
caendesilva Nov 20, 2022
e9823d7
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
8290b5f
Use testing fixture
caendesilva Nov 20, 2022
80d53db
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
07996b9
Test can load from JSON files
caendesilva Nov 20, 2022
0080771
Merge directory into array and use array unpacking for constructor
caendesilva Nov 20, 2022
5fae8da
Use array merge instead of coalesce assignment
caendesilva Nov 20, 2022
7926eeb
Inline local variable
caendesilva Nov 20, 2022
5067036
Rename internal helper method
caendesilva Nov 20, 2022
f72db55
Extract semantic helper method
caendesilva Nov 20, 2022
259df4a
Remove always null variable as value cannot be gotten from schema file
caendesilva Nov 20, 2022
4742052
Inline local variable
caendesilva Nov 20, 2022
02448c0
Inline local variable
caendesilva Nov 20, 2022
e127259
Shift array semantics
caendesilva Nov 20, 2022
6daf303
Wrap long line to multiple lines
caendesilva Nov 20, 2022
145148c
Use static instead of self
caendesilva Nov 20, 2022
9284f57
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
554ef9f
Breaking: Change publication schema property pagesize to pageSize
caendesilva Nov 21, 2022
84a9c33
Add getIdentifier method
caendesilva Nov 21, 2022
8789b25
Update case
caendesilva Nov 21, 2022
9a48a43
Apply fixes from StyleCI
StyleCIBot Nov 21, 2022
a470002
Use assertEqualsIgnoringLineEndingType
caendesilva Nov 21, 2022
593ee68
Create CreatesNewPublicationTypeSchemaTest.php
caendesilva Nov 21, 2022
f1ddc23
Move test to sub namespace
caendesilva Nov 21, 2022
58e1980
Update class PHPDoc
caendesilva Nov 21, 2022
5ab2e4e
Rename CreatesNewPublicationTypeSchema to CreatesNewPublicationType
caendesilva Nov 21, 2022
dcad25e
Rename test for renamed class
caendesilva Nov 21, 2022
ab28eaa
Implement CreatesNewPublicationTypeTest
caendesilva Nov 21, 2022
8feaf25
Apply fixes from StyleCI
StyleCIBot Nov 21, 2022
cf0cbf6
Outfile should be absolute
caendesilva Nov 21, 2022
c7dd3ea
Print message as sprintf with relative path
caendesilva Nov 21, 2022
0a5a910
Refactor to use the PublicationType object
caendesilva Nov 21, 2022
fd2aa89
Remove mkdir handled by save method
caendesilva Nov 21, 2022
b2a08cb
Implement Jsonable
caendesilva Nov 21, 2022
7dbf151
Default to pretty print JSON
caendesilva Nov 21, 2022
d85bd7e
Use toJson helper
caendesilva Nov 21, 2022
23683ef
Inline local array
caendesilva Nov 21, 2022
c53be82
Move down property assignment
caendesilva Nov 21, 2022
508f0d1
Pass along output style and use it instead of echo
caendesilva Nov 21, 2022
4e50c47
Remove unused trait
caendesilva Nov 21, 2022
5fb5244
Clean up imports
caendesilva Nov 21, 2022
09126ac
Apply fixes from StyleCI
StyleCIBot Nov 21, 2022
586bda8
Add linking tag
caendesilva Nov 21, 2022
85ff161
Expect fixed output
caendesilva Nov 21, 2022
f5251f4
Display finish output
caendesilva Nov 21, 2022
a2b2244
Apply fixes from StyleCI
StyleCIBot Nov 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Exception;
use Hyde\Console\Commands\Interfaces\CommandHandleInterface;
use Hyde\Framework\Actions\CreatesNewPublicationTypeSchema;
use Hyde\Framework\Actions\CreatesNewPublicationType;
use Hyde\Framework\Features\Publications\PublicationHelper;
use InvalidArgumentException;
use LaravelZero\Framework\Commands\Command;
Expand Down Expand Up @@ -60,10 +60,10 @@ public function handle(): int
2 => 'DESC',
};

$pagesize = (int) PublicationHelper::askWithValidation(
$pageSize = (int) PublicationHelper::askWithValidation(
$this,
'pagesize',
'Enter the pagesize (0 for no limit)',
'pageSize',
'Enter the pageSize (0 for no limit)',
['required', 'integer', 'between:0,100'],
25
);
Expand All @@ -86,14 +86,16 @@ public function handle(): int
$canonicalField = $fields[$selected - 1]['name'];

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

return Command::FAILURE;
}

$this->info('Publication type created successfully!');

return Command::SUCCESS;
}

Expand Down
3 changes: 3 additions & 0 deletions packages/framework/src/Foundation/PageCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
* This class is stored as a singleton in the HydeKernel.
* You would commonly access it via one of the facades:
*
* @todo We could improve this by catching exceptions and rethrowing them using a
* DiscoveryException to make it clear that the problem is with the discovery process.
*
* @see \Hyde\Foundation\Facades\PageCollection
* @see \Hyde\Hyde::pages()
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace Hyde\Framework\Actions;

use Hyde\Framework\Actions\Interfaces\CreateActionInterface;
use Hyde\Framework\Features\Publications\Models\PublicationType;
use Hyde\Framework\Features\Publications\PublicationHelper;
use Hyde\Hyde;
use Illuminate\Console\OutputStyle;
use Rgasch\Collection\Collection;
use function sprintf;

/**
* Scaffold a new publication type schema.
*
* @see \Hyde\Framework\Testing\Feature\Actions\CreatesNewPublicationTypeSchemaTest
*/
class CreatesNewPublicationType implements CreateActionInterface
{
protected string $result;

public function __construct(
protected string $name,
protected Collection $fields,
protected string $canonicalField,
protected string $sortField,
protected string $sortDirection,
protected int $pageSize,
protected bool $prevNextLinks,
protected ?OutputStyle $output = null,
) {
}

public function create(): void
{
$dirName = PublicationHelper::formatNameForStorage($this->name);
$outFile = Hyde::path("$dirName/schema.json");

$type = new PublicationType(
$this->name,
$this->canonicalField,
$this->sortField,
$this->sortDirection,
$this->pageSize,
$this->prevNextLinks,
"{$dirName}_detail",
"{$dirName}_list",
$this->fields->toArray()
);

$this->output?->writeln(sprintf('Saving publication data to [%s]', Hyde::pathToRelative($outFile)));

$type->save($outFile);
$this->result = $type->toJson();
}

public function getResult(): string
{
return $this->result;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Hyde\Hyde;
use Hyde\Pages\BladePage;
use Illuminate\Support\Facades\Blade;
use InvalidArgumentException;
use function str_contains;
use function view;

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

$template = $this->type->getSchema()['listTemplate'];
$template = $this->type->listTemplate;
if (str_contains($template, '::')) {
return view($template, $data)->render();
}

// Using the Blade facade we can render any file without having to register the directory with the view finder.
$viewPath = Hyde::path("{$this->type->getDirectory()}/$template").'.blade.php';
if (! file_exists($viewPath)) {
throw new InvalidArgumentException("View [$viewPath] not found.");
}

return Blade::render(
file_get_contents(Hyde::path("{$this->type->getDirectory()}/$template").'.blade.php'), $data
file_get_contents($viewPath), $data
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,122 @@

namespace Hyde\Framework\Features\Publications\Models;

use function dirname;
use Exception;
use function file_get_contents;
use Hyde\Framework\Concerns\InteractsWithDirectories;
use Hyde\Hyde;
use Hyde\Support\Concerns\JsonSerializesArrayable;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Str;
use function json_decode;
use JsonSerializable;
use RuntimeException;

class PublicationType
/**
* @see \Hyde\Framework\Testing\Feature\PublicationTypeTest
*/
class PublicationType implements JsonSerializable, Jsonable, Arrayable
{
protected string $schemaFile;
use JsonSerializesArrayable;
use InteractsWithDirectories;

protected string $directory;
protected array $schema;

public static function get(string $name): self
public string $name;
public string $canonicalField;
public string $sortField;
public string $sortDirection;
public int $pageSize;
public bool $prevNextLinks;
public string $detailTemplate;
public string $listTemplate;
public array $fields;

public static function get(string $name): static
{
return static::fromFile(Hyde::path("$name/schema.json"));
}

public static function fromFile(string $schemaFile): static
{
try {
return new static(...array_merge(
static::parseSchemaFile($schemaFile),
static::getRelativeDirectoryName($schemaFile))
);
} catch (Exception $exception) {
throw new RuntimeException("Could not parse schema file $schemaFile", 0, $exception);
}
}

public function __construct(string $name, string $canonicalField, string $sortField, string $sortDirection, int $pageSize, bool $prevNextLinks, string $detailTemplate, string $listTemplate, array $fields, ?string $directory = null)
{
return new self(Hyde::path("$name/schema.json"));
$this->name = $name;
$this->canonicalField = $canonicalField;
$this->sortField = $sortField;
$this->sortDirection = $sortDirection;
$this->pageSize = $pageSize;
$this->prevNextLinks = $prevNextLinks;
$this->detailTemplate = $detailTemplate;
$this->listTemplate = $listTemplate;
$this->fields = $fields;

if ($directory) {
$this->directory = $directory;
}
}

public function __construct(string $schemaFile)
public function toArray(): array
{
$this->schemaFile = $schemaFile;
$this->directory = Hyde::pathToRelative(dirname($schemaFile));
$this->schema = static::parseSchema($schemaFile);
return [
'name' => $this->name,
'canonicalField' => $this->canonicalField,
'sortField' => $this->sortField,
'sortDirection' => $this->sortDirection,
'pageSize' => $this->pageSize,
'prevNextLinks' => $this->prevNextLinks,
'detailTemplate' => $this->detailTemplate,
'listTemplate' => $this->listTemplate,
'fields' => $this->fields,
];
}

public function __get(string $name): mixed
public function toJson($options = JSON_PRETTY_PRINT): string
{
return $this->$name ?? $this->schema[$name] ?? null;
return json_encode($this->toArray(), $options);
}

public function getIdentifier(): string
{
return $this->directory ?? Str::slug($this->name);
}

public function getSchemaFile(): string
{
return $this->schemaFile;
return "$this->directory/schema.json";
}

public function getDirectory(): string
{
return $this->directory;
}

public function getSchema(): array
public function save(?string $path = null): void
{
return $this->schema;
$path ??= $this->getSchemaFile();
$this->needsParentDirectory($path);
file_put_contents($path, json_encode($this->toArray(), JSON_PRETTY_PRINT));
}

protected static function parseSchema(string $schemaFile): array
protected static function parseSchemaFile(string $schemaFile): array
{
return json_decode(file_get_contents($schemaFile), true, 512, JSON_THROW_ON_ERROR);
}

// TODO build list pages and detail pages for each publication type
protected static function getRelativeDirectoryName(string $schemaFile): array
{
return ['directory' => Hyde::pathToRelative(dirname($schemaFile))];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static function getPublicationTypes(): Collection

$pubTypes = Collection::create();
foreach ($schemaFiles as $schemaFile) {
$publicationType = new PublicationType($schemaFile);
$publicationType = PublicationType::fromFile($schemaFile);
$pubTypes->{$publicationType->getDirectory()} = $publicationType;
}

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

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

$media = Collection::create();
foreach ($files as $file) {
Expand Down
2 changes: 1 addition & 1 deletion packages/framework/src/Pages/PublicationPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ protected function renderComponent(): string
'publication' => $this,
];

$template = $this->type->getSchema()['detailTemplate'];
$template = $this->type->detailTemplate;
if (str_contains($template, '::')) {
return view($template, $data)->render();
}
Expand Down
Loading