Skip to content

Commit 0207c7a

Browse files
authored
Merge pull request #730 from hydephp/refactor-make-publication-command
Refactor the make publication command and add more tests for it
2 parents 0c44d9d + eeacf9b commit 0207c7a

File tree

4 files changed

+222
-110
lines changed

4 files changed

+222
-110
lines changed

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

+137-94
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,24 @@
44

55
namespace Hyde\Console\Commands;
66

7+
use function array_flip;
8+
use function array_keys;
9+
use function array_merge;
10+
use function file_exists;
711
use Hyde\Console\Commands\Interfaces\CommandHandleInterface;
812
use Hyde\Console\Concerns\ValidatingCommand;
913
use Hyde\Framework\Actions\CreatesNewPublicationType;
14+
use Hyde\Framework\Features\Publications\Models\PublicationFieldType;
1015
use Hyde\Framework\Features\Publications\PublicationService;
1116
use Illuminate\Support\Str;
1217
use InvalidArgumentException;
18+
use function is_dir;
1319
use LaravelZero\Framework\Commands\Command;
1420
use Rgasch\Collection\Collection;
21+
use function scandir;
22+
use function strtolower;
23+
use function trim;
24+
use function ucfirst;
1525

1626
/**
1727
* Hyde Command to create a new publication type.
@@ -43,49 +53,14 @@ public function safeHandle(): int
4353

4454
$fields = $this->captureFieldsDefinitions();
4555

46-
$this->output->writeln('<bg=magenta;fg=white>Choose the default field you wish to sort by:</>');
47-
$this->line(' 0: dateCreated (meta field)');
48-
$offset = 0;
49-
foreach ($fields as $k => $v) {
50-
$offset = $k + 1;
51-
$this->line(" $offset: $v[name]");
52-
}
53-
$selected = (int) $this->askWithValidation('selected', "Sort field (0-$offset)", ['required', 'integer', "between:0,$offset"], 0);
54-
$sortField = $selected ? $fields[$selected - 1]['name'] : '__createdAt';
55-
56-
$this->output->writeln('<bg=magenta;fg=white>Choose the default sort direction:</>');
57-
$this->line(' 1 - Ascending (oldest items first if sorting by dateCreated)');
58-
$this->line(' 2 - Descending (newest items first if sorting by dateCreated)');
59-
$selected = (int) $this->askWithValidation('selected', 'Sort field (1-2)', ['required', 'integer', 'between:1,2'], 2);
60-
$sortDirection = match ($selected) {
61-
1 => 'ASC',
62-
2 => 'DESC',
63-
};
64-
65-
$pageSize = (int) $this->askWithValidation(
66-
'pageSize',
67-
'Enter the pageSize (0 for no limit)',
68-
['required', 'integer', 'between:0,100'],
69-
25
70-
);
71-
$prevNextLinks = (bool) $this->askWithValidation(
72-
'prevNextLinks',
73-
'Generate previous/next links in detail view (y/n)',
74-
['required', 'string', 'in:y,n'],
75-
'y'
76-
);
56+
$sortField = $this->getSortField($fields);
7757

78-
$this->output->writeln('<bg=magenta;fg=white>Choose a canonical name field (the values of this field have to be unique!):</>');
79-
$fieldNames = [];
80-
foreach ($fields as $k => $v) {
81-
if ($v->type != 'image' && $v->type != 'tag') {
82-
$fieldNames[] = $v->name;
83-
$offset = $k + 1;
84-
$this->line(" $offset: $v->name");
85-
}
86-
}
87-
$selected = (int) $this->askWithValidation('selected', "Canonical field (1-$offset)", ['required', 'integer', "between:1,$offset"], 1);
88-
$canonicalField = $fieldNames[$selected - 1];
58+
$sortDirection = $this->getSortDirection();
59+
60+
$pageSize = $this->getPageSize();
61+
$prevNextLinks = $this->getPrevNextLinks();
62+
63+
$canonicalField = $this->getCanonicalField($fields);
8964

9065
$creator = new CreatesNewPublicationType($title, $fields, $canonicalField, $sortField, $sortDirection, $pageSize, $prevNextLinks, $this->output);
9166
$creator->create();
@@ -104,71 +79,139 @@ protected function captureFieldsDefinitions(): Collection
10479
$this->line('');
10580
$this->output->writeln("<bg=cyan;fg=white>Field #$count:</>");
10681

107-
$field = Collection::create();
82+
$fieldData = [];
10883
do {
109-
$field->name = Str::kebab(trim($this->askWithValidation('name', 'Field name', ['required'])));
110-
$duplicate = $fields->where('name', $field->name)->count();
111-
if ($duplicate) {
112-
$this->error("Field name [$field->name] already exists!");
113-
}
84+
$fieldData['name'] = Str::kebab(trim($this->askWithValidation('name', 'Field name', ['required'])));
85+
$duplicate = $this->checkIfFieldIsDuplicate($fields, $fieldData['name']);
11486
} while ($duplicate);
11587

116-
$this->line('Field type:');
117-
$this->line(' 1 - String');
118-
$this->line(' 2 - Boolean ');
119-
$this->line(' 3 - Integer');
120-
$this->line(' 4 - Float');
121-
$this->line(' 5 - Datetime (YYYY-MM-DD (HH:MM:SS))');
122-
$this->line(' 6 - URL');
123-
$this->line(' 7 - Array');
124-
$this->line(' 8 - Text');
125-
$this->line(' 9 - Local Image');
126-
$this->line(' 10 - Tag (select value from list)');
127-
$type = (int) $this->askWithValidation('type', 'Field type (1-10)', ['required', 'integer', 'between:1,10'], 1);
88+
$type = $this->getFieldType();
12889

12990
if ($type < 10) {
13091
do {
131-
$field->min = trim($this->askWithValidation('min', 'Min value (for strings, this refers to string length)', ['required', 'string'], 0));
132-
$field->max = trim($this->askWithValidation('max', 'Max value (for strings, this refers to string length)', ['required', 'string'], 0));
133-
$lengthsValid = true;
134-
if ($field->max < $field->min) {
135-
$lengthsValid = false;
136-
$this->output->warning('Field length [max] must be [>=] than [min]');
137-
}
92+
$fieldData['min'] = trim($this->askWithValidation('min', 'Min value (for strings, this refers to string length)', ['required', 'string'], 0));
93+
$fieldData['max'] = trim($this->askWithValidation('max', 'Max value (for strings, this refers to string length)', ['required', 'string'], 0));
94+
$lengthsValid = $this->validateLengths($fieldData['min'], $fieldData['max']);
13895
} while (! $lengthsValid);
13996
} else {
140-
$allTags = PublicationService::getAllTags();
141-
$offset = 1;
142-
foreach ($allTags as $k=>$v) {
143-
$this->line(" $offset - $k");
144-
$offset++;
145-
}
146-
$offset--; // The above loop overcounts by 1
147-
$selected = $this->askWithValidation('tagGroup', 'Tag Group', ['required', 'integer', "between:1,$offset"], 0);
148-
$field->tagGroup = $allTags->keys()->{$selected - 1};
149-
$field->min = 0;
150-
$field->max = 0;
97+
$fieldData = $this->getFieldDataForTag($fieldData);
15198
}
152-
$addAnother = $this->askWithValidation('addAnother', '<bg=magenta;fg=white>Add another field (y/n)</>', ['required', 'string', 'in:y,n'], 'y');
99+
$addAnother = $this->askWithValidation('addAnother', '<bg=magenta;fg=white>Add another field (y/n)</>', ['required', 'string', 'in:y,n'], 'n');
153100

154101
// map field choice to actual field type
155-
$field->type = match ($type) {
156-
1 => 'string',
157-
2 => 'boolean',
158-
3 => 'integer',
159-
4 => 'float',
160-
5 => 'datetime',
161-
6 => 'url',
162-
7 => 'array',
163-
8 => 'text',
164-
9 => 'image',
165-
10 => 'tag',
166-
};
167-
168-
$fields->add($field);
102+
$fieldData['type'] = PublicationFieldType::TYPES[$type];
103+
104+
$fields->add(PublicationFieldType::fromArray($fieldData));
169105
$count++;
170-
} while (strtolower($addAnother) != 'n');
106+
} while (strtolower($addAnother) !== 'n');
171107

172108
return $fields;
173109
}
110+
111+
protected function getFieldType(): int
112+
{
113+
$options = PublicationFieldType::TYPES;
114+
foreach ($options as $key => $value) {
115+
$options[$key] = ucfirst($value);
116+
}
117+
$options[5] = 'Datetime (YYYY-MM-DD (HH:MM:SS))';
118+
$options[6] = 'URL';
119+
$options[9] = 'Local Image';
120+
$options[10] = 'Tag (select value from list)';
121+
122+
return (int) $this->choice('Field type', $options, 1) + 1;
123+
}
124+
125+
protected function getSortField(Collection $fields): string
126+
{
127+
$options = array_merge(['dateCreated (meta field)'], $fields->pluck('name')->toArray());
128+
129+
$selected = $this->choice('Choose the default field you wish to sort by', $options, 'dateCreated (meta field)');
130+
131+
return $selected === 'dateCreated (meta field)' ? '__createdAt' : $options[(array_flip($options)[$selected])];
132+
}
133+
134+
protected function getSortDirection(): string
135+
{
136+
$options = [
137+
'Ascending (oldest items first if sorting by dateCreated)' => 'ASC',
138+
'Descending (newest items first if sorting by dateCreated)' => 'DESC',
139+
];
140+
141+
return $options[$this->choice('Choose the default sort direction', array_keys($options), 'Ascending (oldest items first if sorting by dateCreated)')];
142+
}
143+
144+
protected function getPageSize(): int
145+
{
146+
return (int) $this->askWithValidation(
147+
'pageSize',
148+
'Enter the pageSize (0 for no limit)',
149+
['required', 'integer', 'between:0,100'],
150+
25
151+
);
152+
}
153+
154+
protected function getPrevNextLinks(): bool
155+
{
156+
return (bool) $this->askWithValidation(
157+
'prevNextLinks',
158+
'Generate previous/next links in detail view (y/n)',
159+
['required', 'string', 'in:y,n'],
160+
'y'
161+
);
162+
}
163+
164+
protected function getCanonicalField(Collection $fields): string
165+
{
166+
$options = $fields->reject(function (PublicationFieldType $field): bool {
167+
// Temporary verbose check to see code coverage
168+
if ($field->type === 'image') {
169+
return true;
170+
} elseif ($field->type === 'tag') {
171+
return true;
172+
} else {
173+
return false;
174+
}
175+
})->pluck('name');
176+
177+
return $this->choice('Choose a canonical name field (the values of this field have to be unique!)', $options->toArray(), $options->first());
178+
}
179+
180+
protected function validateLengths(string $min, string $max): bool
181+
{
182+
if ($max < $min) {
183+
$this->error('Field length [max] cannot be less than [min]');
184+
185+
return false;
186+
}
187+
188+
return true;
189+
}
190+
191+
protected function getFieldDataForTag(array $fieldData): array
192+
{
193+
$allTags = PublicationService::getAllTags();
194+
$offset = 1;
195+
foreach ($allTags as $k => $v) {
196+
$this->line(" $offset - $k");
197+
$offset++;
198+
}
199+
$offset--; // The above loop overcounts by 1
200+
$selected = $this->askWithValidation('tagGroup', 'Tag Group', ['required', 'integer', "between:1,$offset"], 0);
201+
$fieldData['tagGroup'] = $allTags->keys()->{$selected - 1};
202+
$fieldData['min'] = 0;
203+
$fieldData['max'] = 0;
204+
205+
return $fieldData;
206+
}
207+
208+
protected function checkIfFieldIsDuplicate(Collection $fields, $name): bool
209+
{
210+
$duplicate = $fields->where('name', $name)->count();
211+
if ($duplicate) {
212+
$this->error("Field name [$name] already exists!");
213+
}
214+
215+
return (bool) $duplicate;
216+
}
174217
}

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

+13-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,19 @@ class PublicationFieldType implements SerializableContract
1717
{
1818
use Serializable;
1919

20-
public final const TYPES = ['string', 'boolean', 'integer', 'float', 'datetime', 'url', 'array', 'text', 'image', 'tag'];
20+
public final const TYPES = [
21+
1 => 'string',
22+
2 => 'boolean',
23+
3 => 'integer',
24+
4 => 'float',
25+
5 => 'datetime',
26+
6 => 'url',
27+
7 => 'array',
28+
8 => 'text',
29+
9 => 'image',
30+
10 => 'tag',
31+
];
32+
2133
public final const DEFAULT_RULES = [
2234
'string' => ['required', 'string', 'between'],
2335
'boolean' => ['required', 'boolean'],

0 commit comments

Comments
 (0)