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

Refactor publication page creation internals #793

Merged
merged 38 commits into from
Dec 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
cc8620d
Get namespace dynamically
caendesilva Dec 30, 2022
634ab32
Inline fieldClass helper method
caendesilva Dec 30, 2022
fcc4b5d
Extract helper method
caendesilva Dec 30, 2022
c55f5ce
Introduce local variable
caendesilva Dec 30, 2022
75bc273
Split comma-separated values into multiple lines
caendesilva Dec 30, 2022
4e6afd1
Get namespace dynamically
caendesilva Dec 30, 2022
e802e3f
Inline method InputStreamHandler::formatMessage
caendesilva Dec 30, 2022
ca88a3b
Extract method
caendesilva Dec 30, 2022
71dd2db
Shift method arguments to make helper more generic
caendesilva Dec 30, 2022
268944e
Join comma-separated values into a single line
caendesilva Dec 30, 2022
b22b00f
Return null for empty selections
caendesilva Dec 30, 2022
534e9a5
Move up selection as there's no need to compute namespace if it's empty
caendesilva Dec 30, 2022
716fb42
Test with skipping inputs
caendesilva Dec 30, 2022
4faa3e8
Shift newline call to method below
caendesilva Dec 30, 2022
5d71684
Merge conditionals for empty input handling
caendesilva Dec 30, 2022
e292a08
Revert "Shift newline call to method below"
caendesilva Dec 30, 2022
acc590c
Refactor collection to be a class property
caendesilva Dec 30, 2022
a668166
Use the infoComment helper to make the same output
caendesilva Dec 30, 2022
734afc4
Indent output to match other questions
caendesilva Dec 30, 2022
9893a41
Test image input selects the right file
caendesilva Dec 30, 2022
3025d4d
Fix image input selector
caendesilva Dec 30, 2022
c5a4df8
Test command selects the right publication
caendesilva Dec 30, 2022
ac3b425
Switch order of tests
caendesilva Dec 30, 2022
17dc2ea
Test command selects the right publication using the names
caendesilva Dec 30, 2022
7c49339
Remove tests for integer selection of publication types as that doesn…
caendesilva Dec 30, 2022
2be5959
Fix publication type selections so they work in real consoles
caendesilva Dec 30, 2022
632c97a
Apply fixes from StyleCI
StyleCIBot Dec 30, 2022
ef84c22
Add a newline before the end of output
caendesilva Dec 30, 2022
0a8067d
Update finishing message to clarify that everything was completed suc…
caendesilva Dec 30, 2022
66a96f0
Style finishing message using the infoComment helper
caendesilva Dec 30, 2022
6d2df36
Apply fixes from StyleCI
StyleCIBot Dec 30, 2022
fc8c1cf
Add the date for extra test specificity
caendesilva Dec 30, 2022
5ff6f2c
Forgot that we mock the date so we can actually use the entire output...
caendesilva Dec 30, 2022
65cdf06
Revert "Indent output to match other questions"
caendesilva Dec 30, 2022
faa293b
Revert "Indent warning message empty collections"
caendesilva Dec 30, 2022
38322a0
Simplify Carbon call as it's format does not matter here
caendesilva Dec 30, 2022
90e3a7a
Use type cast
caendesilva Dec 30, 2022
6d26e9e
Rename helper method
caendesilva Dec 30, 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 @@ -54,10 +54,4 @@ public static function mockInput(string $input): void
{
self::$mockedStreamBuffer = explode("\n", $input);
}

/** Format a consistent message that can be output to the console */
public static function formatMessage(string $name, string $type = 'values'): string
{
return "<info>Enter $type for field </>[<comment>$name</comment>] (end with an empty line)";
}
}
76 changes: 43 additions & 33 deletions packages/framework/src/Console/Commands/MakePublicationCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Hyde\Framework\Features\Publications\PublicationFieldTypes;
use Hyde\Framework\Features\Publications\PublicationService;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use function implode;
use function in_array;
use InvalidArgumentException;
Expand All @@ -42,15 +43,19 @@ class MakePublicationCommand extends ValidatingCommand

protected PublicationType $publicationType;

/** @var \Illuminate\Support\Collection<string, PublicationType> */
protected Collection $fieldData;

public function safeHandle(): int
{
$this->title('Creating a new publication!');

$this->publicationType = $this->getPublicationTypeSelection();
$this->fieldData = new Collection();

$fieldData = $this->collectFieldData();
$this->collectFieldData();

$creator = new CreatesNewPublicationPage($this->publicationType, $fieldData, (bool) $this->option('force'));
$creator = new CreatesNewPublicationPage($this->publicationType, $this->fieldData, (bool) $this->option('force'));
if ($creator->hasFileConflict()) {
$this->error('Error: A publication already exists with the same canonical field value');
if ($this->confirm('Do you wish to overwrite the existing file?')) {
Expand All @@ -63,20 +68,18 @@ public function safeHandle(): int
}
$creator->create();

$this->info("Created file {$creator->getOutputPath()}");
$this->infoComment('All done! Created file', $creator->getOutputPath());

return Command::SUCCESS;
}

protected function getPublicationTypeSelection(): PublicationType
{
$publicationTypes = $this->getPublicationTypes();

$publicationTypeSelection = $this->argument('publicationType') ?? $publicationTypes->keys()->get(
(int) $this->choice(
'Which publication type would you like to create a publication item for?',
$publicationTypes->keys()->toArray()
)
$publicationTypeSelection = $this->argument('publicationType') ??
$this->choice(
'Which publication type would you like to create a publication item for?',
$publicationTypes->keys()->toArray()
);

if ($publicationTypes->has($publicationTypeSelection)) {
Expand All @@ -88,7 +91,6 @@ protected function getPublicationTypeSelection(): PublicationType
throw new InvalidArgumentException("Unable to locate publication type [$publicationTypeSelection]");
}

/** @return \Illuminate\Support\Collection<string, PublicationType> */
protected function getPublicationTypes(): Collection
{
$publicationTypes = PublicationService::getPublicationTypes();
Expand All @@ -99,57 +101,50 @@ protected function getPublicationTypes(): Collection
return $publicationTypes;
}

/** @return \Illuminate\Support\Collection<string, string|array|null> */
protected function collectFieldData(): Collection
protected function collectFieldData(): void
{
$this->newLine();
$this->info('Now please enter the field data:');
$data = new Collection();

/** @var PublicationField $field */
foreach ($this->publicationType->getFields() as $field) {
if (str_starts_with($field->name, '__')) {
continue;
}

$this->newLine();
$fieldInput = $this->captureFieldInput($field);
if ($fieldInput !== null) {
$data->put($field->name, $fieldInput);
if (empty($fieldInput)) {
$this->line("<fg=gray> > Skipping field $field->name</>");
} else {
$this->fieldData->put($field->name, $fieldInput);
}
}

return $data;
$this->newLine();
}

protected function captureFieldInput(PublicationField $field): ?PublicationFieldValue
{
$selection = match ($field->type) {
return match ($field->type) {
PublicationFieldTypes::Text => $this->captureTextFieldInput($field),
PublicationFieldTypes::Array => $this->captureArrayFieldInput($field),
PublicationFieldTypes::Image => $this->captureImageFieldInput($field),
PublicationFieldTypes::Tag => $this->captureTagFieldInput($field),
default => new ($field->type->fieldClass())($this->askWithValidation($field->name, "Enter data for field </>[<comment>$field->name</comment>]", $field->getValidationRules()->toArray())),
default => $this->captureOtherFieldInput($field),
};

if (empty($selection)) {
$this->line("<fg=gray> > Skipping field $field->name</>");

return null;
}

return $selection;
}

protected function captureTextFieldInput(PublicationField $field): TextField
{
$this->line(InputStreamHandler::formatMessage($field->name, 'lines'));
$this->infoComment('Enter lines for field', $field->name, '</>(end with an empty line)');

return new TextField(implode("\n", InputStreamHandler::call()));
}

protected function captureArrayFieldInput(PublicationField $field): ArrayField
{
$this->line(InputStreamHandler::formatMessage($field->name));
$this->infoComment('Enter values for field', $field->name, '</>(end with an empty line)');

return new ArrayField(InputStreamHandler::call());
}
Expand All @@ -163,10 +158,7 @@ protected function captureImageFieldInput(PublicationField $field): ?ImageField
return $this->handleEmptyOptionsCollection($field, 'media file', "No media files found in directory _media/{$this->publicationType->getIdentifier()}/");
}

$filesArray = $mediaFiles->toArray();
$selection = (int) $this->choice('Which file would you like to use?', $filesArray);

return new ImageField($filesArray[$selection]);
return new ImageField($this->choice('Which file would you like to use?', $mediaFiles->toArray()));
}

protected function captureTagFieldInput(PublicationField $field): ?TagField
Expand All @@ -189,6 +181,24 @@ protected function captureTagFieldInput(PublicationField $field): ?TagField
return new TagField($choice);
}

protected function captureOtherFieldInput(PublicationField $field): ?PublicationFieldValue
{
$selection = $this->askForFieldData($field->name, $field->getValidationRules()->toArray());
if (empty($selection)) {
return null;
}

$namespace = Str::beforeLast(PublicationFieldValue::class, '\\');
$className = "$namespace\\{$field->type->name}Field";

return new $className($selection);
}

protected function askForFieldData(string $name, array $rules): string
{
return $this->askWithValidation($name, "Enter data for field </>[<comment>$name</comment>]", $rules);
}

/** @return null */
protected function handleEmptyOptionsCollection(PublicationField $field, string $type, string $message)
{
Expand All @@ -197,7 +207,7 @@ protected function handleEmptyOptionsCollection(PublicationField $field, string
}

$this->newLine();
$this->warn(" <fg=red>Warning:</> $message");
$this->warn("<fg=red>Warning:</> $message");
if ($this->confirm('Would you like to skip this field?', true)) {
return null;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class CreatesNewPublicationPage extends CreateAction implements CreateActionCont
*/
public function __construct(PublicationType $pubType, Collection $fieldData, bool $force = false)
{
$fieldData->prepend(new DatetimeField(Carbon::now()->format('Y-m-d H:i:s')), '__createdAt');
$fieldData->prepend(new DatetimeField((string) Carbon::now()), '__createdAt');

$this->pubType = $pubType;
$this->fieldData = $fieldData;
Expand All @@ -56,11 +56,11 @@ protected function getCanonicalValue(): string
{
$canonicalFieldName = $this->pubType->canonicalField;
if ($canonicalFieldName === '__createdAt') {
return $this->getFieldValue('__createdAt')->getValue()->format('Y-m-d H:i:s');
return $this->getFieldFromCollection('__createdAt')->getValue()->format('Y-m-d H:i:s');
}

if ($this->fieldData->has($canonicalFieldName)) {
$field = $this->getFieldValue($canonicalFieldName);
$field = $this->getFieldFromCollection($canonicalFieldName);

return (string) $field->getValue(); // TODO here we can check if field has interface allowing it to be canonical, else throw exception
} else {
Expand All @@ -87,7 +87,7 @@ protected function normalizeData(Collection $data): array
})->toArray();
}

protected function getFieldValue(string $key): PublicationFieldValue
protected function getFieldFromCollection(string $key): PublicationFieldValue
{
return $this->fieldData->get($key);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,4 @@ public static function canonicable(): array
self::Text,
];
}

public function fieldClass(): string
{
return "Hyde\\Framework\\Features\\Publications\\Models\\PublicationFieldValues\\{$this->name}Field";
}
}
Loading