Skip to content

Conversation

@bastianallgeier
Copy link
Member

@bastianallgeier bastianallgeier commented Aug 19, 2025

Description

This PR explores a new API to query and manipulate nested structured data for structure fields, entry fields, layouts, blocks and even blueprints - basically anything that is expressed in nested arrays.

The hope for this experiment is to create a solid foundation for an PHP API that we can use to access and manipulate deeply nested data in a more performant and reliable way. This would give us the opportunity to build structure, block and layout fields with backend connected drawers and would also be a major step forward for a blueprint editor where we need the same for tabs, columns, fields etc.

Naming

So far, I've called the classes and namespace Module, but that maybe not that great. There's also an idea to refactor our existing Item classes, but that would be quite complex without breaking changes.

Demo

Here`s an example that you can toss into Tinkerwell or a simple test.php to play around with it:

use Kirby\Modules\Modules;
use Kirby\Modules\Module;

$blocks = json_encode([
  "a" => [
    "id" => "foo",
    "isHidden" => true,
    "type" => "quote",
    "content" => [
      "text" => "Foo"
    ]
  ]
]);

$structure = Data::encode(
  [
    [
      "title" => "Structure Child 1"
    ],
    [
      "title" => "Structure Child 2"
    ]
  ],
  "json"
);

$yaml = <<<YAML
- title: Row 1
  uuid: row-1
  children: 
    - title: Child 1      
      blocks: $blocks
    - title: Child 2      
      blocks: $blocks
- title: Row 2
  children: $structure
YAML;

$data = Data::decode($yaml, "yaml");
$modules = Modules::from(data: $data);

$parent = $modules->find("row-1");

$parent->update([
  "title" => "Nice Row 1"
]);

$child = $parent->modules("children")->find(0);

$child->update([
  "title" => "Nice Child 1"
]);

$child
  ->modules("blocks")
  ->find("foo")
  ->update([
    "title" => "Super Block"
  ]);

$parent->toArray();

Here's another example:

use Kirby\Modules\Modules;
use Kirby\Modules\Module;

$diner = Modules::from(
  data: [
    "starter" => [
      "title" => "Starter",
      "options" => [
        [
          "title" => "Potato soup",
          "uuid" => "potato",
          "ingredients" => [
            [
              "name" => "Potato",
              "uuid" => "potato"
            ]
          ]
        ]
      ]
    ],
    "main" => [
      "title" => "Main",
      "options" => [
        [
          "title" => "Beef",
          "ingredients" => [
            [
              "name" => "Salt"
            ]
          ]
        ]
      ]
    ],
    "dessert" => [
      "title" => "Dessert",
      "options" => [
        [
          "title" => "Deep fried mars",
          "ingredients" => [
            [
              "name" => "Mars"
            ],
            [
              "name" => "Sugar"
            ]
          ],
          "uuid" => "mars"
        ]
      ]
    ]
  ]
);

$diner->find("dessert/options/mars/ingredients")->changeSort([1, 2]);

$diner->toArray();

@bastianallgeier bastianallgeier changed the base branch from main to develop-minor August 19, 2025 15:10
@bastianallgeier bastianallgeier requested a review from a team August 19, 2025 15:11
@bastianallgeier bastianallgeier force-pushed the lab/bastian/structured-data branch from 74e7034 to eb81c64 Compare October 9, 2025 14:07
@bastianallgeier bastianallgeier force-pushed the lab/bastian/structured-data branch from eb81c64 to 2f31449 Compare October 20, 2025 14:02
@bastianallgeier bastianallgeier force-pushed the lab/bastian/structured-data branch from 2f31449 to 1f71f82 Compare October 20, 2025 14:02
if ($format === 'auto') {
$format = 'yaml';

if (json_validate($data) === true) {

Check failure

Code scanning / Psalm

UndefinedFunction Error

Function Kirby\Nodes\json_validate does not exist
return trim($this->parent?->path() . '/' . $this->id(), '/');
}

public function toArray(Closure|null $callback = null): array

Check failure

Code scanning / Psalm

ParamNameMismatch Error

Argument 1 of Kirby\Nodes\Nodes::toArray has wrong name $callback, expecting $map as defined by Kirby\Cms\Collection::toArray
return trim($this->parent?->path() . '/' . $this->id(), '/');
}

public function toArray(Closure|null $callback = null): array

Check failure

Code scanning / Psalm

ParamNameMismatch Error

Argument 1 of Kirby\Nodes\Nodes::toArray has wrong name $callback, expecting $map as defined by Kirby\Toolkit\Collection::toArray
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants