Structure with blocks does does add json in output

i am trying to convert regular structures with title + (kirby)textarea fields to
structure with blocks - where as i am trying to convert the title to heading, and text to text… and it seems there’s some structures which work, and others who add the json into what’s being saved…

Before when i had pretty: true, it seem to have that while using the regular panel saving function as well, even though i have seen in earlier versions. by now pretty is disabled though.

                            $title = null;
                            $text = null;
                            $features = $page->features()->yaml();
                            foreach($features as &$feature){
                                $blocks = new Kirby\Cms\Blocks();
                                if(isset($feature['title']) && $feature['title'] != null){
                                    $title = new Kirby\Cms\Block([
                                        'content' => [
                                          'text' => (string)markdown($feature['title']),
                                          'level' => 'h2',
                                        ],
                                        'type' => 'heading',
                                    ]);
                                    $blocks = $blocks->add(new Kirby\Cms\Blocks([$title]));

                                }
                                if(isset($feature['text']) && $feature['text'] != null){
                                    $text = new Kirby\Cms\Block([
                                        'content' => [
                                            'text' => (string)markdown($feature['text']),
                                        ],
                                        'type' => 'text',
                                    ]);
                                    $blocks = $blocks->add(new Kirby\Cms\Blocks([$text]));
                                }
                                if($blocks->count() == 0) continue;
                                $feature['blocks'] = Data::encode($blocks->toArray(),'json');
// tried many different variations of encoding (yaml, json, just plain toArray
                            }
                            $page->update([
                                'features' => Data::encode($features,'yaml'),
                            ]);

There’s a few similar threads and infos, but all didn’t seem work…

Output e.g.

<div id="123">
[{"content":{"text":"[{\"content\":{\"text\":\"
Some Title here

\",\"level\":\"h2\"},\"id\":\"5350f449-f6d6-45eb-b4a8-1d75cdc36bbe\",\"isHidden\":false,\"type\":\"heading\"},{\"content\":{\"text\":\"
some text here here
.....
....
</div>

While others in the same loop may be fine.

In the Content File it seems as though it’s saving the whole thing wrongful in those cases.

blocks: '[{"content":{"text":"<p>[{\"content\":{\"text\":\...........

As it can be seen, it’s escaping and whatever.

The Structures come from version 3.9.x; and i am trying to convert it in a route using 4.1.2.

In the Structures, sometimes it’s saved with

field: >
longer text
or
field: |
longer text
or
field: ‘something’

By now i have also tested, if i create only a text structure and add the heading as a string (e.g. <h2>Bla</h2>

then the problem still happens. Is there another attempt to create blocks / update inside the structure and save the page?

<?php

$features = $page->features()->yaml(); //might as well use toSTructure here, but doesn't matter
$blocks   = new Kirby\Cms\Blocks();
foreach ($features as $feature) {
	if (($feature['title'] ?? null) !== null) {
		$title  = new Kirby\Cms\Block([
			'content' => [
				'text'  => (string)markdown($feature['title']),
				'level' => 'h2',
			],
			'type'    => 'heading',
		]);
		$blocks = $blocks->add($title);
		
	}
	if (($feature['text'] ?? null) !== null) {
		$text   = new Kirby\Cms\Block([
			'content' => [
				'text' => (string)markdown($feature['text']),
			],
			'type'    => 'text',
		]);
		$blocks = $blocks->add($text);
	}
}
$page->update([
	'features' => json_encode($blocks->toArray()),
]);

My features structure is not being replaced by the blocks…

It’s like

features:
  label: features
  type: structure
  fields:
     cover:
       type: files
       multiple: false
       query: page.images
     blocks:
        type: blocks
     title:
         type: title
     text:
         type: textarea

in this example the title and text is gonna be replaced by the blocks.

i assume in your example, it’s replacing the structure with blocks?

the output is being called as following

foreach($page->features()->tostructure() as $feature){

  // Use things like $cover fotos from the structure

foreach($feature->blocks()->toBlocks() as $block){

 // use $block similar to what is showin in the docs page

}
}

the replacement of title+text just offers a bit more flexiblity than just using text.

Right.

But I don’t understand what you want to achieve instead.

Please format your code blocks correctly to make them readable, thanks.

sorry for the formatting, i made adjustments…

simply saying it’s not just the top field $page->features()

but the blocks should be saved within the structure.

// e.g. cards-list- view html output
foreach($page->features()->toStructure() as $feature){
  if($cover = $feature->cover()->toFile()){
      echo $cover->url(); 
  }
  foreach($feature->blocks()->toBlocks() as $blocks){
      // render $blocks similar to the blocks example
     // heading blocks
     // text blocks
     // etc
  }
}

in another post there was another user where it also difficult to use blocks within a structure. so i also wonder since some structures are correct, which is weird.

This is the desired output, the data right now is saved within the structure in the title and text field, so my goal is to update the structure keeping everything else, but transfer title + text as both available types of blocks, still within the structure.

$feature['blocks'] = Data::encode($blocks->toArray(),'json');

in my code in the first post, you can see me accessing and overwriting the structure on the fly trying to add into

page > features (structure) > blocks (blocks)

while keeping everything else like cover.

On the second look (being out on the phone) the issue might just be the use of

The second

Which might do blocks within blocks. And thus causing the issue. Will try if that is the issue.

$features = $page->features()->yaml(); //might as well use toSTructure here, but doesn't matter
                            $arr = [];
                            $i = 0; foreach ($features as $feature) {
                                $blocks = new Kirby\Cms\Blocks();

                                if (($feature['title'] ?? null) !== null) {
                                    $title  = new Kirby\Cms\Block([
                                        'content' => [
                                            'text'  => (string)markdown($feature['title']),
                                            'level' => 'h2',
                                        ],
                                        'type'    => 'heading',
                                    ]);
                                    $blocks = $blocks->add($title);
                                    
                                }
                                if (($feature['text'] ?? null) !== null) {
                                    $text   = new Kirby\Cms\Block([
                                        'content' => [
                                            'text' => (string)markdown($feature['text']),
                                        ],
                                        'type'    => 'text',
                                    ]);
                                    $blocks = $blocks->add($text);
                                }
                                if (($feature['cover'] ?? null) !== null) {
                                    $arr[$i]['cover'] = $feature['cover'];
                                }
                                $arr[$i]['blocks'] = Data::encode($blocks->toArray(),'json');
                                $i++;
                            }

                            $page->update([
                                'features' => Data::encode($arr, 'yaml'),
                            ]);

another attempt, still no success, my assumption is, that structures with blocks do not work flawless… Getting a text + textarea to update that info inside a structure > block shouldn’t be that hard.

It seems if there’s no structure, then I don’t run into that problem whatsoever.

As mentioned, there were similar problems before… like here:

Further investigation, it seems, it matters how the data is being saved…

Features:

-
  title: This data seems to work
  text: 'Seeing this text is in single quotes, the building of the block is working fine'

-
  title: > 
    Some more Title even with
    Multiple Lines seem to work
  text: >
    That also applies to multiple Lines of text
    like this one 

- 
  title: 'More Titles'
  text: |
    This is causing the behavior where the json content
    is saved uncorrectly and this outputs the json

What is being saved in the content-file

Features:

- 
  blocks: '[{"content":{"text":"<p>[{\"content\":{\"text\":\"Lorem Ipsum?\",\"level\":\"h2\"},\"id\":\"9f864657-9890-4cff-9165-d48590bf8797\",\"isHidden\":false,\"type\":\"heading\"},{\"content\":{\"text\":\"Some More Text 123.\"},\"id\":\"a57e8aa9-22d0-4b18-8b43-c23bb5f9ad9a\",\"isHidden\":false,\"type\":\"text\"}]</p>"},"id":"0c801327-19f0-44f7-b372-914bd8c3f482","isHidden":false,"type":"text"}]'

maybe there’s a way to update the structures first programmically and then build blocks

or is there an alternative?