AdvancedCustomFields / acf

Advanced Custom Fields
http://advancedcustomfields.com/
823 stars 168 forks source link

Insert ACF Block with wp_insert_post #856

Open Matteo-pd opened 11 months ago

Matteo-pd commented 11 months ago

I have an ACF Block called "pd-text". The block contains the fields: title | main_text | pd_block_id | columns_in_row.

When I add block in the Admin panel I have generated code:

<!-- wp:acf/pd-text {"name":"acf/pd-text","data":{"field_62d53c8533fbd":"Block title","field_62d53c8533fc5":"Paragraph 1 - text text text.\r\n\r\nParagraph 2 - text text text\r\nLine two - \u003cstrong\u003eparagraph\u003c/strong\u003e two.\r\n\r\nParagraph 3 - text \u0022quoted text\u0022 text text.","field_63beb8efe0d5c":"my-block-id","field_630f632a63aec":"1"},"mode":"edit"} /-->

I would like to build a code that will insert ACF Blocks to the post_content with the function wp_insert_post();

The problem that I have is that the generated JSON output is incorrect. On the front there aren't rendered html tags

and also not adding the new line.

I found the code to use md5() function to generate underscore field key, but the value is different that this what is on the code above, so I suppose that also is wrong. My question is how to find the field ID?

What I'm doing wrong to save the ACF block with the insert function?

Generated ACF Block JSON:

<!-- wp:acf/pd-text-with-bg-image {"name":"acf\/pd-text-with-bg-image","data":{"_block_pd-text-with-bg-image_columns_in_row":"field_b716db7dfe0831e64233e682bc0a8280","columns_in_row":"1","_block_pd-text-with-bg-image_pd_block_id":"field_27f7ac094f1ba4b063cf82d301713de2","pd_block_id":"my-block-id","_block_pd-text-with-bg-image_title":"field_aa88e266bf0bbbee20d20d4d7172c755","title":"Block title","_block_pd-text-with-bg-image_main_text":"field_922e1888941df5b1fc930ab8a9eaab91","main_text":"Paragraph 1 - text text text.\n \n Paragraph 2 - text text text\n Line two - <strong>paragraph<\/strong> two.\n \n Paragraph 3 - text \"quoted text\" text text."},"mode":"edit"} /-->

My code:

$acfOutput = '';
$acfFields = [];
$blockName = 'pd-text';

$fieldData = [
    'columns_in_row' => '1',
    'pd_block_id' => 'my-block-id',
    'title' => 'Block title',
    'main_text' => 'Paragraph 1 - text text text.

Paragraph 2 - text text text
Line two - <strong>paragraph</strong> two.

Paragraph 3 - text "quoted text" text text.'
];

if(is_array($fieldData)){
    foreach($fieldData as $fieldKey => $fieldVal) {
        $key = 'block_' . $blockName . '_' . $fieldKey;
        $acfFields['_' . $key] = 'field_' . md5($key);
        $acfFields[$fieldKey] = $fieldVal;
    }

    $json = [
                'name' => 'acf/' . $blockName,
                'data' => $acfFields,
                'mode' => 'edit'
    ];

    $fields = json_encode($json);

    $acfOutput = <<<ACFJSON
        <!-- wp:acf/$blockName $fields /-->
    ACFJSON;
}

...

$postData['post_content'] = $acfOutput;

wp_insert_post($postData);
CreativeDive commented 11 months ago

I think this will help you in your case: https://github.com/AdvancedCustomFields/acf/issues/839

Matteo-pd commented 11 months ago

I'm not sure if I good understand, so should I use wp_slash() to create the correct post_content?

How can I generate the underscored key? I expect to get for "main_text" : field_62d53c8533fc5

But

$acfFields['_' . $key] = 'field_' . md5($key); Generates: "_block_pd-text-with-bg-image_main_text":"field_922e1888941df5b1fc930ab8a9eaab91" is it wrong to use md5() ?

CreativeDive commented 11 months ago

Each time the post content goes through wp_update_post() / wp_insert_post() the content has been modified by wp_unslash(). So the post content is not the same like you editing a block in the editor.

wp_update_post( array(
    'ID' => $post_id,
    'post_content' => wp_slash( $update_content ),
) );

You should generally keep this in mind when using wp_update_post() / wp_insert_post().

But I probably just skimmed your topic. You want to generate an ACF block content before it was created manually.

I had never tried that before. But have you already checked the ACF source code to find out how ACF generates the field key?

CreativeDive commented 11 months ago

I can see a field key is generated in this way in acf-field-functions.php using PHP uniqid( 'field_' ).

// Generate key.
$keys = acf_get_data( 'generated_keys' );
if ( isset( $keys[ $field['key'] ] ) ) {
    $field['key'] = $keys[ $field['key'] ];
} else {
    $field['key'] = uniqid( 'field_' );
}

If that's the case, I'm afraid that you can't easily generate it this way. The field keys are already assigned as soon as you create the block manually the first time. Then you could always specify them manually in this way:

$fieldData = [
    'field_875345872345' => [
        'columns_in_row' => '1',
    ],
    'field_568768467586' => [
        'pd_block_id' => 'my-block-id',
    ],
    ...
];