Skip to content

Commit

Permalink
Merge pull request #760 from hydephp/refactor-the-MakePublicationComm…
Browse files Browse the repository at this point in the history
…and-class

Refactor the publication file creator
  • Loading branch information
caendesilva authored Dec 19, 2022
2 parents 8c2c0df + a5886e3 commit 916f4da
Show file tree
Hide file tree
Showing 5 changed files with 333 additions and 37 deletions.
26 changes: 6 additions & 20 deletions packages/framework/src/Console/Commands/MakePublicationCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

namespace Hyde\Console\Commands;

use Hyde\Console\Commands\Helpers\InputStreamHandler;
use Hyde\Console\Concerns\ValidatingCommand;
use Hyde\Framework\Actions\CreatesNewPublicationPage;
use Hyde\Framework\Features\Publications\Concerns\PublicationFieldTypes;
use Hyde\Framework\Features\Publications\Models\PublicationFieldType;
use Hyde\Framework\Features\Publications\Models\PublicationType;
use Hyde\Framework\Features\Publications\PublicationService;
use Illuminate\Support\Str;
use function implode;
use InvalidArgumentException;
use LaravelZero\Framework\Commands\Command;
use Rgasch\Collection\Collection;
Expand Down Expand Up @@ -134,34 +136,18 @@ protected function hasForceOption(): bool
return (bool) $this->option('force');
}

protected function captureTextFieldInput(PublicationFieldType $field): array
protected function captureTextFieldInput(PublicationFieldType $field): string
{
$lines = [];
$this->output->writeln($field->name." (end with a line containing only '<<<')");
do {
$line = Str::replace("\n", '', fgets(STDIN));
if ($line === '<<<') {
break;
}
$lines[] = $line;
} while (true);
$this->output->writeln($field->name.' (end with an empty line)');

return $lines;
return implode("\n", InputStreamHandler::call());
}

protected function captureArrayFieldInput(PublicationFieldType $field): array
{
$lines = [];
$this->output->writeln($field->name.' (end with an empty line)');
do {
$line = Str::replace("\n", '', fgets(STDIN));
if ($line === '') {
break;
}
$lines[] = trim($line);
} while (true);

return $lines;
return InputStreamHandler::call();
}

protected function captureImageFieldInput(PublicationFieldType $field, PublicationType $pubType): string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@

use Hyde\Framework\Actions\Concerns\CreateAction;
use Hyde\Framework\Actions\Contracts\CreateActionContract;
use Hyde\Framework\Features\Publications\Concerns\PublicationFieldTypes;
use Hyde\Framework\Features\Publications\Models\PublicationFieldType;
use Hyde\Framework\Features\Publications\Models\PublicationType;
use Illuminate\Console\OutputStyle;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use InvalidArgumentException;
use function is_string;
use Rgasch\Collection\Collection;
use RuntimeException;

Expand All @@ -29,8 +32,8 @@ public function __construct(
protected ?OutputStyle $output = null,
) {
$canonicalFieldName = $this->pubType->canonicalField;
$canonicalFieldDefinition = $this->pubType->getFields()->filter(fn (PublicationFieldType $field): bool => $field->name === $canonicalFieldName)->first() ?? throw new RuntimeException("Could not find field definition for '$canonicalFieldName'");
$canonicalValue = $canonicalFieldDefinition->type !== 'array' ? $this->fieldData->{$canonicalFieldName} : $this->fieldData->{$canonicalFieldName}[0];
$canonicalFieldDefinition = $this->pubType->getCanonicalFieldDefinition();
$canonicalValue = $this->getCanonicalValue($canonicalFieldDefinition, $canonicalFieldName);
$canonicalStr = Str::of($canonicalValue)->substr(0, 64);

$fileName = $this->formatStringForStorage($canonicalStr->slug()->toString());
Expand All @@ -47,15 +50,18 @@ protected function handleCreate(): void
/** @var PublicationFieldType $fieldDefinition */
$fieldDefinition = $this->pubType->getFields()->where('name', $name)->firstOrFail();

if ($fieldDefinition->type == 'text') {
if ($fieldDefinition->type === PublicationFieldTypes::Text) {
$output .= "$name: |\n";
if (is_string($value)) {
$value = Str::of($value)->explode("\n");
}
foreach ($value as $line) {
$output .= " $line\n";
}
continue;
}

if ($fieldDefinition->type == 'array') {
if ($fieldDefinition->type === PublicationFieldTypes::Array) {
$output .= "$name:\n";
foreach ($value as $item) {
$output .= " - \"$item\"\n";
Expand All @@ -72,4 +78,24 @@ protected function handleCreate(): void

$this->save($output);
}

protected function getCanonicalValue(PublicationFieldType $canonicalFieldDefinition, string $canonicalFieldName): string
{
if ($canonicalFieldName === '__createdAt') {
return Carbon::now()->format('Y-m-d H:i:s');
}

try {
// TODO: Is it reasonable to use arrays as canonical field values?
if ($canonicalFieldDefinition->type === PublicationFieldTypes::Array) {
$canonicalValue = $this->fieldData->{$canonicalFieldName}[0];
} else {
$canonicalValue = $this->fieldData->{$canonicalFieldName};
}

return $canonicalValue;
} catch (InvalidArgumentException $exception) {
throw new RuntimeException("Could not find field value for '$canonicalFieldName' which is required for as it's the type's canonical field", 404, $exception);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use function json_decode;
use Rgasch\Collection\Collection;
use RuntimeException;
use function str_starts_with;

/**
* @see \Hyde\Framework\Testing\Feature\PublicationTypeTest
Expand Down Expand Up @@ -117,6 +118,15 @@ public function getFieldRules(bool $reload = false): Collection
}), false);
}

public function getCanonicalFieldDefinition(): PublicationFieldType
{
if (str_starts_with($this->canonicalField, '__')) {
return new PublicationFieldType('string', $this->canonicalField, 0, 0);
}

return $this->getFields()->filter(fn (PublicationFieldType $field): bool => $field->name === $this->canonicalField)->first();
}

public function save(?string $path = null): void
{
$path ??= $this->getSchemaFile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@

namespace Hyde\Framework\Testing\Feature\Actions;

use function file_get_contents;
use Hyde\Facades\Filesystem;
use Hyde\Framework\Actions\CreatesNewPublicationPage;
use Hyde\Framework\Features\Publications\Models\PublicationType;
use Hyde\Hyde;
use Hyde\Testing\TestCase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Rgasch\Collection\Collection;
use RuntimeException;
use Symfony\Component\Yaml\Yaml;

/**
* @covers \Hyde\Framework\Actions\CreatesNewPublicationPage
Expand Down Expand Up @@ -53,19 +57,200 @@ public function testCreate()
', file_get_contents(Hyde::path('test-publication/hello-world.md')));
}

protected function makePublicationType(): PublicationType
public function testWithTextType()
{
$pubType = $this->makePublicationType([[
'type' => 'string',
'name' => 'title',
'min' => 0,
'max' => 128,
], [
'type' => 'text',
'name' => 'description',
'min' => 0,
'max' => 128,
]]);

$fieldData = Collection::make([
'title' => 'Hello World',
'description' => 'This is a description
It can be multiple lines.',
]);

$creator = new CreatesNewPublicationPage($pubType, $fieldData);
$creator->create();

$this->assertTrue(File::exists(Hyde::path('test-publication/hello-world.md')));
$this->assertEquals('---
__createdAt: 2022-01-01 00:00:00
title: Hello World
description: |
This is a description
It can be multiple lines.
---
## Write something awesome.
', file_get_contents(Hyde::path('test-publication/hello-world.md')));
}

public function testWithArrayType()
{
$pubType = $this->makePublicationType([[
'type' => 'string',
'name' => 'title',
'min' => 0,
'max' => 128,
], [
'type' => 'array',
'name' => 'tags',
'min' => 0,
'max' => 128,
]]);

$fieldData = Collection::make([
'title' => 'Hello World',
'tags' => ['tag1', 'tag2'],
]);

$creator = new CreatesNewPublicationPage($pubType, $fieldData);
$creator->create();

$this->assertTrue(File::exists(Hyde::path('test-publication/hello-world.md')));
$this->assertEquals('---
__createdAt: 2022-01-01 00:00:00
title: Hello World
tags:
- "tag1"
- "tag2"
---
## Write something awesome.
', file_get_contents(Hyde::path('test-publication/hello-world.md')));
}

public function testCreateWithoutSupplyingCanonicalField()
{
$pubType = $this->makePublicationType();
$fieldData = Collection::make([]);

$this->expectException(RuntimeException::class);
$this->expectExceptionMessage("Could not find field value for 'title' which is required for as it's the type's canonical field");
$creator = new CreatesNewPublicationPage($pubType, $fieldData);
$creator->create();
}

public function testCreateWithoutSupplyingRequiredField()
{
$pubType = $this->makePublicationType([[
'type' => 'string',
'name' => 'title',
'min' => 0,
'max' => 128,
], [
'type' => 'string',
'name' => 'slug',
'min' => 0,
'max' => 128,
]]);

$fieldData = Collection::make([
'title' => 'Hello World',
]);

$creator = new CreatesNewPublicationPage($pubType, $fieldData);
$creator->create();

// Since the inputs are collected by the command, with the shipped code this should never happen.
// If a developer is using the action directly, it's their responsibility to ensure the data is valid.

$this->assertTrue(File::exists(Hyde::path('test-publication/hello-world.md')));
$this->assertEquals('---
__createdAt: 2022-01-01 00:00:00
title: Hello World
---
## Write something awesome.
', file_get_contents(Hyde::path('test-publication/hello-world.md')));
}

public function testItCreatesValidYaml()
{
$pubType = $this->makePublicationType([[
'type' => 'string',
'name' => 'title',
'min' => 0,
'max' => 128,
], [
'type' => 'text',
'name' => 'description',
'min' => 0,
'max' => 128,
], [

'type' => 'array',
'name' => 'tags',
'min' => 0,
'max' => 128,
]]);

$fieldData = Collection::make([
'title' => 'Hello World',
'description' => 'This is a description.
It can be multiple lines.',
'tags' => ['tag1', 'tag2'],
]);

$creator = new CreatesNewPublicationPage($pubType, $fieldData);
$creator->create();

$this->assertTrue(File::exists(Hyde::path('test-publication/hello-world.md')));
$contents = file_get_contents(Hyde::path('test-publication/hello-world.md'));
$this->assertEquals('---
__createdAt: 2022-01-01 00:00:00
title: Hello World
description: |
This is a description.
It can be multiple lines.
tags:
- "tag1"
- "tag2"
---
## Write something awesome.
',
$contents
);

$this->assertSame([
'__createdAt' => 1640995200,
'title' => 'Hello World',
'description' => 'This is a description.
It can be multiple lines.
',
'tags' => [
'tag1',
'tag2',
],
], Yaml::parse(Str::between($contents, '---', '---')));
}

protected function makePublicationType(array $fields = [
[
'type' => 'string',
'name' => 'title',
'min' => 0,
'max' => 128,
],
]): PublicationType
{
return new PublicationType(
'test',
'title',
fields: [
[
'type' => 'string',
'name' => 'title',
'min' => 0,
'max' => 128,
],
],
fields: $fields,
directory: 'test-publication',
);
}
Expand Down
Loading

0 comments on commit 916f4da

Please sign in to comment.