Open hdodov opened 5 years ago
how page fields
The page
field does not exists, the field is called pages
.
foreach ($page->items()->toStructure() as $entry) { $entry->blueprint(); // [icon, name] }
IMO, that loop doesn't make sense, it would return the same stuff over and over again, because a structure field always has the same fields.
Oops, yes, edited my comment above to pages
.
IMO, that loop doesn't make sense, it would return the same stuff over and over again, because a structure field always has the same fields.
That's my point kind of. If you pass $entry
in other functions, you can call $entry->blueprint()->fields()
and know what data to expect in that structure entry. Otherwise, you need to store the page blueprints, extract the structure blueprint's fields
and pass it along with the entry:
$fieldsBlueprint = $page->blueprint()->fields();
$structureEntryBlueprint = $fieldsBlueprint['items']['fields'] ?? null;
foreach ($page->items()->toStructure() as $entry) {
doSomethingWith($entry, $structureEntryBlueprint);
}
As opposed to simply:
foreach ($page->items()->toStructure() as $entry) {
doSomethingWith($entry); // get the blueprint from within the function
}
Passing along the blueprints as an argument is unnecessary pollution. But the big problem is that the Site
, Page
and File
have a blueprint()
method, while StructureObject
doesn't. This means that if you want to create a function that processes models recursively, you have to handle occurrences of StructureObject
separately and pass blueprints in the arguments, while the other classes don't need that.
This is a snippet from a class I'm making:
/**
* Recursively walks over a Model.
* @param Kirby\Cms\Model $model
* @param array|null $blueprint used for models without a blueprint() method
* like StructureObject
* @return array|null
*/
public function walk(Model $model, array $blueprint = null)
{
if (!$blueprint) {
$blueprint = $model->blueprint()->fields();
}
$data = null;
$content = $model->content($this->settings['language']);
foreach ($blueprint as $key => $fieldBlueprint) {
$field = $content->$key();
$fieldData = $this->walkField($fieldBlueprint, $field);
if ($fieldData !== null) {
$data[$key] = $fieldData;
}
}
return $data;
}
In the walkField
method, I call walk
when the field is of type structure
, so recursion occurs.
While it works fine, the whole $blueprints
part is kind of ugly. My whole idea with this issue is to unify the API so you can handle recursion easier.
I'm writing a Walker class that allows you to recursively walk over a Model's fields, resolving structures in the process. The
Site
,Page
, andFile
classes all have ablueprint()
method, but entries in aStructure
(StructureObject
instances) don't.I get that this is probably due to structures not having their own blueprint file, but it still makes sense to have a
blueprint()
method. After all, a structure entry is like a nested Model.Let's say I have this page blueprint:
I would be great if:
It makes sense to have blueprints for Structure and StructureObject classes. Also, notice how the pages and structure fields would have identical APIs.