From 18542b5cbd8ac6bf84ee7d9a8aed31e78cf2ae13 Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Tue, 20 May 2025 17:14:17 +0200
Subject: [PATCH 01/20] First commit
---
assets/src/js/acf.js | 1 +
assets/src/js/custom-sources.js | 22 ++++++++++++++++++++++
includes/Blocks/Bindings.php | 2 --
includes/acf-pattern-functions.php | 10 ++++++++++
secure-custom-fields.php | 1 +
5 files changed, 34 insertions(+), 2 deletions(-)
create mode 100644 assets/src/js/custom-sources.js
create mode 100644 includes/acf-pattern-functions.php
diff --git a/assets/src/js/acf.js b/assets/src/js/acf.js
index 7ca4222e..215fa7c9 100644
--- a/assets/src/js/acf.js
+++ b/assets/src/js/acf.js
@@ -6,3 +6,4 @@ import './_acf-modal.js';
import './_acf-panel.js';
import './_acf-notice.js';
import './_acf-tooltip.js';
+import './custom-sources.js';
diff --git a/assets/src/js/custom-sources.js b/assets/src/js/custom-sources.js
new file mode 100644
index 00000000..703a06f5
--- /dev/null
+++ b/assets/src/js/custom-sources.js
@@ -0,0 +1,22 @@
+/**
+ * WordPress dependencies.
+ */
+import { __ } from '@wordpress/i18n';
+import { registerBlockBindingsSource } from '@wordpress/blocks';
+
+/**
+ * Register SCF Custom Fields block binding source.
+ *
+ * This allows blocks to bind to custom fields managed by
+ * the Secure Custom Fields plugin.
+ */
+
+( function () {
+ registerBlockBindingsSource( {
+ name: 'acf/field',
+ label: 'SCF Custom Fields',
+ getValues: function ( block ) {
+ console.log( block );
+ },
+ } );
+} )();
diff --git a/includes/Blocks/Bindings.php b/includes/Blocks/Bindings.php
index 921558c3..2eda2f19 100644
--- a/includes/Blocks/Bindings.php
+++ b/includes/Blocks/Bindings.php
@@ -31,7 +31,6 @@ public function __construct() {
* Hooked to acf/init, register our binding sources.
*/
public function register_binding_sources() {
- if ( acf_get_setting( 'enable_block_bindings' ) ) {
register_block_bindings_source(
'acf/field',
array(
@@ -39,7 +38,6 @@ public function register_binding_sources() {
'get_value_callback' => array( $this, 'get_value' ),
)
);
- }
}
/**
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
new file mode 100644
index 00000000..6e492e9a
--- /dev/null
+++ b/includes/acf-pattern-functions.php
@@ -0,0 +1,10 @@
+
Date: Fri, 23 May 2025 11:44:41 +0200
Subject: [PATCH 02/20] Experimenting, images still not working
---
.phpcs.xml.dist | 1 +
includes/Blocks/Bindings.php | 59 +++++
includes/acf-pattern-functions.php | 331 ++++++++++++++++++++++++++++-
3 files changed, 388 insertions(+), 3 deletions(-)
diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist
index 404cccb3..bf15db56 100644
--- a/.phpcs.xml.dist
+++ b/.phpcs.xml.dist
@@ -6,6 +6,7 @@
';
+ }
+ }
+
+ // Rebuild block
+ $attributes_json = ! empty( $attributes ) ? wp_json_encode( $attributes, JSON_UNESCAPED_SLASHES ) : '';
+
+ // Only include attributes if we have some
+ $attr_part = '{}' !== $attributes_json ? " {$attributes_json}" : '';
+
+ return "{$block_content}";
+ },
+ $content
+ );
+}
+
+/**
+ * Get the supported binding attributes for a block.
+ *
+ * @param string $block_name The name of the block.
+ * @return array The supported binding attributes for the block.
+ */
+function scf_get_binding_attribute_for_block( $block_name ) {
+ $supported_block_attributes = array(
+ 'core/paragraph' => array( 'content' ),
+ 'core/heading' => array( 'content' ),
+ 'core/image' => array( 'id', 'url', 'title', 'alt' ),
+ 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ),
+ );
+
+ return $supported_block_attributes[ $block_name ] ?? array( 'content' );
+}
+
+/**
+ * Get a placeholder value for a field based on its binding attribute.
+ *
+ * @param string $field_name The name of the field.
+ * @param string $binding_attribute The binding attribute to get a placeholder for.
+ * @return string The placeholder value.
+ */
+function scf_get_placeholder_for_field( $field_name, $binding_attribute = 'content' ) {
+ // Handle specific binding attributes that need special values
+ if ( 'url' === $binding_attribute || 'src' === $binding_attribute ) {
+ return '/api/placeholder/400/300';
+ }
+
+ if ( 'alt' === $binding_attribute ) {
+ return 'Image description';
+ }
+
+ if ( 'id' === $binding_attribute ) {
+ return '0';
+ }
+
+ if ( 'linkTarget' === $binding_attribute ) {
+ return '_self';
+ }
+
+ if ( 'rel' === $binding_attribute ) {
+ return '';
+ }
+
+ // For all other attributes, return a simple generic placeholder
+ return sprintf( '[%s]', ucwords( str_replace( array( '_', '-' ), ' ', $field_name ) ) );
}
From 81b614c00d20eb7b10683756ad37d9da610324b8 Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Fri, 23 May 2025 13:34:09 +0200
Subject: [PATCH 03/20] Some cleaning, image still failing
---
includes/acf-pattern-functions.php | 183 +++++++++++++++++++----------
1 file changed, 124 insertions(+), 59 deletions(-)
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
index 473259c3..0eb10cfb 100644
--- a/includes/acf-pattern-functions.php
+++ b/includes/acf-pattern-functions.php
@@ -143,15 +143,6 @@ function scf_extract_field_mappings( $php_content ) {
$mappings[ $variable ] = $field_name;
}
- // Match get_the_terms patterns
- preg_match_all( '/\$(\w+)\s*=\s*get_the_terms\([^,]+,\s*[\'"]([^\'"]+)[\'"]\)/', $php_content, $terms_matches, PREG_SET_ORDER );
-
- foreach ( $terms_matches as $match ) {
- $variable = $match[1];
- $taxonomy_name = $match[2];
- $mappings[ $variable ] = $taxonomy_name;
- }
-
return $mappings;
}
@@ -196,31 +187,11 @@ function ( $matches ) use ( $field_mappings ) {
// Now process PHP echoes in this block's direct content
$block_modified = false;
$block_content = preg_replace_callback(
- '/<\?php\s+echo\s+esc_html\(\s*(?:the_title\(\)|\$(\w+))\s*\)\s*;\s*\?>|<\?php\s+echo\s+esc_url\(\s*\$(\w+)\s*\)\s*;\s*\?>|<\?php\s+echo\s+\$(\w+)\s*;\s*\?>|<\?php\s+the_title\(\)\s*;\s*\?>/',
+ '/<\?php\s+echo\s+(?:esc_html|esc_attr|esc_url|esc_js|esc_textarea)\(\s*\$(\w+)\s*\)\s*;\s*\?>|<\?php\s+echo\s+\$(\w+)\s*;\s*\?>/',
function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$block_modified ) {
- // Handle different types of PHP echoes
- if ( ! empty( $echo_matches[0] ) && ( strpos( $echo_matches[0], 'the_title()' ) !== false ) ) {
- // Handle the_title() - bind to post title
- if ( 'core/image' === $block_name ) {
- $attributes['metadata']['bindings']['alt'] = array(
- 'source' => 'core/post-meta',
- 'args' => array( 'key' => 'title' ),
- );
- } else {
- $binding_attributes = scf_get_binding_attribute_for_block( $block_name );
- $primary_attribute = $binding_attributes[0] ?? 'content';
- $attributes['metadata']['bindings'][ $primary_attribute ] = array(
- 'source' => 'core/post-meta',
- 'args' => array( 'key' => 'title' ),
- );
- }
- $block_modified = true;
- return 'Post Title';
- }
-
// Extract variable name from different echo patterns
$variable = '';
- for ( $i = 1; $i <= 4; $i++ ) {
+ for ( $i = 1; $i <= 2; $i++ ) {
if ( ! empty( $echo_matches[ $i ] ) ) {
$variable = $echo_matches[ $i ];
break;
@@ -229,32 +200,34 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
if ( $variable && isset( $field_mappings[ $variable ] ) ) {
$field_name = $field_mappings[ $variable ];
+ $escape_type = '';
+
+ // Determine the escape type
+ if ( preg_match( '/esc_(\w+)\(/', $echo_matches[0], $escape_match ) ) {
+ $escape_type = $escape_match[1];
+ }
- // Handle special cases for image blocks
- if ( 'core/image' === $block_name ) {
- if ( strpos( $echo_matches[0], 'esc_url' ) !== false ) {
- $attributes['metadata']['bindings']['url'] = array(
- 'source' => 'scf/field',
+ // Get block binding configuration
+ $binding_config = scf_get_block_binding_config( $block_name, $escape_type );
+
+ if ( $binding_config ) {
+ // Apply the binding configuration
+ foreach ( $binding_config['attributes'] as $attr_name => $attr_config ) {
+ $attributes['metadata']['bindings'][ $attr_name ] = array(
+ 'source' => $attr_config['source'],
'args' => array( 'field' => $field_name ),
);
- $block_modified = true;
- return '/api/placeholder/400/300';
- } elseif ( strpos( $echo_matches[0], 'esc_html' ) !== false ) {
- // This is the image ID
- $attributes['id'] = 0; // Set a placeholder ID
- $block_modified = true;
- return '0';
}
- } else {
- // For non-image blocks, use the standard binding
- $binding_attributes = scf_get_binding_attribute_for_block( $block_name );
- $primary_attribute = $binding_attributes[0] ?? 'content';
- $attributes['metadata']['bindings'][ $primary_attribute ] = array(
- 'source' => 'scf/field',
- 'args' => array( 'field' => $field_name ),
- );
+
+ // Set any additional attributes
+ if ( isset( $binding_config['additional_attributes'] ) ) {
+ foreach ( $binding_config['additional_attributes'] as $attr_name => $attr_value ) {
+ $attributes[ $attr_name ] = $attr_value;
+ }
+ }
+
$block_modified = true;
- return scf_get_placeholder_for_field( $field_name, $primary_attribute );
+ return $binding_config['placeholder'] ?? scf_get_placeholder_for_field( $field_name, $binding_config['primary_attribute'] ?? 'content' );
}
}
@@ -264,13 +237,8 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
$block_content
);
- // For image blocks, ensure we have the proper structure
- if ( 'core/image' === $block_name ) {
- // If we have bindings but no proper image structure, fix it
- if ( isset( $attributes['metadata']['bindings'] ) && ! strpos( $block_content, '
';
- }
- }
+ // Ensure proper block structure based on bindings
+ $block_content = scf_ensure_block_structure( $block_name, $block_content, $attributes );
// Rebuild block
$attributes_json = ! empty( $attributes ) ? wp_json_encode( $attributes, JSON_UNESCAPED_SLASHES ) : '';
@@ -284,6 +252,103 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
);
}
+/**
+ * Get block binding configuration based on block type and escape function.
+ *
+ * @param string $block_name The name of the block.
+ * @param string $escape_type The type of escaping function used.
+ * @return array|null The binding configuration or null if not supported.
+ */
+function scf_get_block_binding_config( $block_name, $escape_type ) {
+ $configs = array(
+ 'core/image' => array(
+ 'url' => array(
+ 'attributes' => array(
+ 'url' => array( 'source' => 'scf/field' ),
+ ),
+ 'placeholder' => '/api/placeholder/400/300',
+ ),
+ 'alt' => array(
+ 'attributes' => array(
+ 'alt' => array( 'source' => 'scf/field' ),
+ ),
+ 'placeholder' => 'Image description',
+ ),
+ 'id' => array(
+ 'attributes' => array(
+ 'id' => array( 'source' => 'scf/field' ),
+ ),
+ 'additional_attributes' => array(
+ 'id' => 0,
+ ),
+ 'placeholder' => '0',
+ ),
+ ),
+ 'core/heading' => array(
+ 'content' => array(
+ 'attributes' => array(
+ 'content' => array( 'source' => 'scf/field' ),
+ ),
+ 'primary_attribute' => 'content',
+ ),
+ ),
+ 'core/paragraph' => array(
+ 'content' => array(
+ 'attributes' => array(
+ 'content' => array( 'source' => 'scf/field' ),
+ ),
+ 'primary_attribute' => 'content',
+ ),
+ ),
+ 'core/button' => array(
+ 'url' => array(
+ 'attributes' => array(
+ 'url' => array( 'source' => 'scf/field' ),
+ ),
+ 'primary_attribute' => 'url',
+ ),
+ 'text' => array(
+ 'attributes' => array(
+ 'text' => array( 'source' => 'scf/field' ),
+ ),
+ 'primary_attribute' => 'text',
+ ),
+ ),
+ );
+
+ // Default configuration for unsupported blocks
+ $default_config = array(
+ 'content' => array(
+ 'attributes' => array(
+ 'content' => array( 'source' => 'scf/field' ),
+ ),
+ 'primary_attribute' => 'content',
+ ),
+ );
+
+ // Get block-specific config or default
+ $block_config = $configs[ $block_name ] ?? $default_config;
+
+ // Return specific escape type config or default content config
+ return $block_config[ $escape_type ] ?? $block_config['content'] ?? null;
+}
+
+/**
+ * Ensure proper block structure based on bindings.
+ *
+ * @param string $block_name The name of the block.
+ * @param string $content The block content.
+ * @param array $attributes The block attributes.
+ * @return string The properly structured block content.
+ */
+function scf_ensure_block_structure( $block_name, $content, $attributes ) {
+ if ( 'core/image' === $block_name && isset( $attributes['metadata']['bindings'] ) && ! strpos( $content, '
';
+ }
+
+ return $content;
+}
+
/**
* Get the supported binding attributes for a block.
*
From 5edb9b1497382805c9f1aa9f3382d8b3db8db1c6 Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Fri, 23 May 2025 17:00:41 +0200
Subject: [PATCH 04/20] Back to something working again
---
includes/acf-pattern-functions.php | 183 ++++++++++-------------------
1 file changed, 59 insertions(+), 124 deletions(-)
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
index 0eb10cfb..473259c3 100644
--- a/includes/acf-pattern-functions.php
+++ b/includes/acf-pattern-functions.php
@@ -143,6 +143,15 @@ function scf_extract_field_mappings( $php_content ) {
$mappings[ $variable ] = $field_name;
}
+ // Match get_the_terms patterns
+ preg_match_all( '/\$(\w+)\s*=\s*get_the_terms\([^,]+,\s*[\'"]([^\'"]+)[\'"]\)/', $php_content, $terms_matches, PREG_SET_ORDER );
+
+ foreach ( $terms_matches as $match ) {
+ $variable = $match[1];
+ $taxonomy_name = $match[2];
+ $mappings[ $variable ] = $taxonomy_name;
+ }
+
return $mappings;
}
@@ -187,11 +196,31 @@ function ( $matches ) use ( $field_mappings ) {
// Now process PHP echoes in this block's direct content
$block_modified = false;
$block_content = preg_replace_callback(
- '/<\?php\s+echo\s+(?:esc_html|esc_attr|esc_url|esc_js|esc_textarea)\(\s*\$(\w+)\s*\)\s*;\s*\?>|<\?php\s+echo\s+\$(\w+)\s*;\s*\?>/',
+ '/<\?php\s+echo\s+esc_html\(\s*(?:the_title\(\)|\$(\w+))\s*\)\s*;\s*\?>|<\?php\s+echo\s+esc_url\(\s*\$(\w+)\s*\)\s*;\s*\?>|<\?php\s+echo\s+\$(\w+)\s*;\s*\?>|<\?php\s+the_title\(\)\s*;\s*\?>/',
function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$block_modified ) {
+ // Handle different types of PHP echoes
+ if ( ! empty( $echo_matches[0] ) && ( strpos( $echo_matches[0], 'the_title()' ) !== false ) ) {
+ // Handle the_title() - bind to post title
+ if ( 'core/image' === $block_name ) {
+ $attributes['metadata']['bindings']['alt'] = array(
+ 'source' => 'core/post-meta',
+ 'args' => array( 'key' => 'title' ),
+ );
+ } else {
+ $binding_attributes = scf_get_binding_attribute_for_block( $block_name );
+ $primary_attribute = $binding_attributes[0] ?? 'content';
+ $attributes['metadata']['bindings'][ $primary_attribute ] = array(
+ 'source' => 'core/post-meta',
+ 'args' => array( 'key' => 'title' ),
+ );
+ }
+ $block_modified = true;
+ return 'Post Title';
+ }
+
// Extract variable name from different echo patterns
$variable = '';
- for ( $i = 1; $i <= 2; $i++ ) {
+ for ( $i = 1; $i <= 4; $i++ ) {
if ( ! empty( $echo_matches[ $i ] ) ) {
$variable = $echo_matches[ $i ];
break;
@@ -200,34 +229,32 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
if ( $variable && isset( $field_mappings[ $variable ] ) ) {
$field_name = $field_mappings[ $variable ];
- $escape_type = '';
-
- // Determine the escape type
- if ( preg_match( '/esc_(\w+)\(/', $echo_matches[0], $escape_match ) ) {
- $escape_type = $escape_match[1];
- }
- // Get block binding configuration
- $binding_config = scf_get_block_binding_config( $block_name, $escape_type );
-
- if ( $binding_config ) {
- // Apply the binding configuration
- foreach ( $binding_config['attributes'] as $attr_name => $attr_config ) {
- $attributes['metadata']['bindings'][ $attr_name ] = array(
- 'source' => $attr_config['source'],
+ // Handle special cases for image blocks
+ if ( 'core/image' === $block_name ) {
+ if ( strpos( $echo_matches[0], 'esc_url' ) !== false ) {
+ $attributes['metadata']['bindings']['url'] = array(
+ 'source' => 'scf/field',
'args' => array( 'field' => $field_name ),
);
+ $block_modified = true;
+ return '/api/placeholder/400/300';
+ } elseif ( strpos( $echo_matches[0], 'esc_html' ) !== false ) {
+ // This is the image ID
+ $attributes['id'] = 0; // Set a placeholder ID
+ $block_modified = true;
+ return '0';
}
-
- // Set any additional attributes
- if ( isset( $binding_config['additional_attributes'] ) ) {
- foreach ( $binding_config['additional_attributes'] as $attr_name => $attr_value ) {
- $attributes[ $attr_name ] = $attr_value;
- }
- }
-
+ } else {
+ // For non-image blocks, use the standard binding
+ $binding_attributes = scf_get_binding_attribute_for_block( $block_name );
+ $primary_attribute = $binding_attributes[0] ?? 'content';
+ $attributes['metadata']['bindings'][ $primary_attribute ] = array(
+ 'source' => 'scf/field',
+ 'args' => array( 'field' => $field_name ),
+ );
$block_modified = true;
- return $binding_config['placeholder'] ?? scf_get_placeholder_for_field( $field_name, $binding_config['primary_attribute'] ?? 'content' );
+ return scf_get_placeholder_for_field( $field_name, $primary_attribute );
}
}
@@ -237,8 +264,13 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
$block_content
);
- // Ensure proper block structure based on bindings
- $block_content = scf_ensure_block_structure( $block_name, $block_content, $attributes );
+ // For image blocks, ensure we have the proper structure
+ if ( 'core/image' === $block_name ) {
+ // If we have bindings but no proper image structure, fix it
+ if ( isset( $attributes['metadata']['bindings'] ) && ! strpos( $block_content, '
';
+ }
+ }
// Rebuild block
$attributes_json = ! empty( $attributes ) ? wp_json_encode( $attributes, JSON_UNESCAPED_SLASHES ) : '';
@@ -252,103 +284,6 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
);
}
-/**
- * Get block binding configuration based on block type and escape function.
- *
- * @param string $block_name The name of the block.
- * @param string $escape_type The type of escaping function used.
- * @return array|null The binding configuration or null if not supported.
- */
-function scf_get_block_binding_config( $block_name, $escape_type ) {
- $configs = array(
- 'core/image' => array(
- 'url' => array(
- 'attributes' => array(
- 'url' => array( 'source' => 'scf/field' ),
- ),
- 'placeholder' => '/api/placeholder/400/300',
- ),
- 'alt' => array(
- 'attributes' => array(
- 'alt' => array( 'source' => 'scf/field' ),
- ),
- 'placeholder' => 'Image description',
- ),
- 'id' => array(
- 'attributes' => array(
- 'id' => array( 'source' => 'scf/field' ),
- ),
- 'additional_attributes' => array(
- 'id' => 0,
- ),
- 'placeholder' => '0',
- ),
- ),
- 'core/heading' => array(
- 'content' => array(
- 'attributes' => array(
- 'content' => array( 'source' => 'scf/field' ),
- ),
- 'primary_attribute' => 'content',
- ),
- ),
- 'core/paragraph' => array(
- 'content' => array(
- 'attributes' => array(
- 'content' => array( 'source' => 'scf/field' ),
- ),
- 'primary_attribute' => 'content',
- ),
- ),
- 'core/button' => array(
- 'url' => array(
- 'attributes' => array(
- 'url' => array( 'source' => 'scf/field' ),
- ),
- 'primary_attribute' => 'url',
- ),
- 'text' => array(
- 'attributes' => array(
- 'text' => array( 'source' => 'scf/field' ),
- ),
- 'primary_attribute' => 'text',
- ),
- ),
- );
-
- // Default configuration for unsupported blocks
- $default_config = array(
- 'content' => array(
- 'attributes' => array(
- 'content' => array( 'source' => 'scf/field' ),
- ),
- 'primary_attribute' => 'content',
- ),
- );
-
- // Get block-specific config or default
- $block_config = $configs[ $block_name ] ?? $default_config;
-
- // Return specific escape type config or default content config
- return $block_config[ $escape_type ] ?? $block_config['content'] ?? null;
-}
-
-/**
- * Ensure proper block structure based on bindings.
- *
- * @param string $block_name The name of the block.
- * @param string $content The block content.
- * @param array $attributes The block attributes.
- * @return string The properly structured block content.
- */
-function scf_ensure_block_structure( $block_name, $content, $attributes ) {
- if ( 'core/image' === $block_name && isset( $attributes['metadata']['bindings'] ) && ! strpos( $content, '
';
- }
-
- return $content;
-}
-
/**
* Get the supported binding attributes for a block.
*
From 37d3297cba0d5aea7b234d3a84a30c671d152dfd Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Fri, 23 May 2025 17:05:42 +0200
Subject: [PATCH 05/20] Image fixed
---
includes/acf-pattern-functions.php | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
index 473259c3..dd376813 100644
--- a/includes/acf-pattern-functions.php
+++ b/includes/acf-pattern-functions.php
@@ -198,26 +198,6 @@ function ( $matches ) use ( $field_mappings ) {
$block_content = preg_replace_callback(
'/<\?php\s+echo\s+esc_html\(\s*(?:the_title\(\)|\$(\w+))\s*\)\s*;\s*\?>|<\?php\s+echo\s+esc_url\(\s*\$(\w+)\s*\)\s*;\s*\?>|<\?php\s+echo\s+\$(\w+)\s*;\s*\?>|<\?php\s+the_title\(\)\s*;\s*\?>/',
function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$block_modified ) {
- // Handle different types of PHP echoes
- if ( ! empty( $echo_matches[0] ) && ( strpos( $echo_matches[0], 'the_title()' ) !== false ) ) {
- // Handle the_title() - bind to post title
- if ( 'core/image' === $block_name ) {
- $attributes['metadata']['bindings']['alt'] = array(
- 'source' => 'core/post-meta',
- 'args' => array( 'key' => 'title' ),
- );
- } else {
- $binding_attributes = scf_get_binding_attribute_for_block( $block_name );
- $primary_attribute = $binding_attributes[0] ?? 'content';
- $attributes['metadata']['bindings'][ $primary_attribute ] = array(
- 'source' => 'core/post-meta',
- 'args' => array( 'key' => 'title' ),
- );
- }
- $block_modified = true;
- return 'Post Title';
- }
-
// Extract variable name from different echo patterns
$variable = '';
for ( $i = 1; $i <= 4; $i++ ) {
@@ -231,7 +211,7 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
$field_name = $field_mappings[ $variable ];
// Handle special cases for image blocks
- if ( 'core/image' === $block_name ) {
+ if ( 'image' === $block_name ) {
if ( strpos( $echo_matches[0], 'esc_url' ) !== false ) {
$attributes['metadata']['bindings']['url'] = array(
'source' => 'scf/field',
@@ -265,7 +245,7 @@ function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$b
);
// For image blocks, ensure we have the proper structure
- if ( 'core/image' === $block_name ) {
+ if ( 'image' === $block_name ) {
// If we have bindings but no proper image structure, fix it
if ( isset( $attributes['metadata']['bindings'] ) && ! strpos( $block_content, '
';
From 080f4470c5ec39286332fa19759d411373df7362 Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Wed, 28 May 2025 14:10:16 +0200
Subject: [PATCH 06/20] Simplify pattern creation with just PHP functions
---
includes/acf-pattern-functions.php | 421 ++++++++++++-----------------
1 file changed, 172 insertions(+), 249 deletions(-)
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
index dd376813..d5417327 100644
--- a/includes/acf-pattern-functions.php
+++ b/includes/acf-pattern-functions.php
@@ -24,7 +24,6 @@ function scf_register_smart_pattern( $pattern_directory ) {
'keywords' => 'Keywords',
'description' => 'Description',
'scf_fieldgroup' => 'SCF Fieldgroup',
- 'conversion' => 'Conversion', // auto, bindings, php
);
$meta_data = get_file_data( $pattern_directory, $headers );
@@ -33,23 +32,8 @@ function scf_register_smart_pattern( $pattern_directory ) {
return new WP_Error( 'invalid_pattern', 'Pattern missing required title or slug' );
}
- // Determine conversion method
- $conversion_method = ( array_key_exists( 'conversion', $meta_data ) ) ? $meta_data['conversion'] : 'auto';
-
- $pattern_content = '';
-
- switch ( $conversion_method ) {
- case 'bindings':
- // Pure binding approach - read static content
- $pattern_content = scf_get_static_pattern_content( $pattern_directory );
- break;
-
- case 'auto':
- default:
- // Smart conversion: PHP to bindings
- $pattern_content = scf_convert_php_to_bindings( $pattern_directory );
- break;
- }
+ // Use the new pattern loading method that doesn't require output buffering
+ $pattern_content = scf_load_pattern_from_file( $pattern_directory );
if ( is_wp_error( $pattern_content ) ) {
return $pattern_content;
@@ -72,244 +56,183 @@ function scf_register_smart_pattern( $pattern_directory ) {
'content' => $pattern_content,
)
);
-
- return array(
- 'slug' => $meta_data['slug'],
- 'title' => $meta_data['title'],
- 'status' => 'registered',
- 'method' => $conversion_method,
- );
}
-/**
- * Convert PHP SCF get_field('my_field') to bindings.
- *
- * @param string $pattern_file The path to the pattern file.
- * @return string The converted HTML content.
- */
-function scf_convert_php_to_bindings( $pattern_file ) {
- // Read the file content
- if ( ! file_exists( $pattern_file ) || ! is_readable( $pattern_file ) ) {
- return new WP_Error( 'pattern_not_readable', 'Pattern file is not readable' );
- }
-
- $content = file_get_contents( $pattern_file );
- if ( false === $content ) {
- return new WP_Error( 'pattern_not_readable', 'Failed to read pattern file' );
+function create_block_with_binding( string $tag, string $source, array $bindings_args = array(), string $inner_content = '' ) {
+ // If tag is specified, map it to the appropriate block type
+ $block = 'core/paragraph'; // Default block type
+ $wrapper_tag = 'p'; // Default HTML wrapper tag
+ $attributes = array(); // Block attributes
+
+ if ($tag !== null) {
+ switch ($tag) {
+ case 'p':
+ $block = 'core/paragraph';
+ $wrapper_tag = 'p';
+ break;
+ case 'h1':
+ $block = 'core/heading';
+ $wrapper_tag = 'h1';
+ $attributes['level'] = 1;
+ break;
+ case 'h2':
+ case 'h': // Support legacy 'h' tag as h2
+ $block = 'core/heading';
+ $wrapper_tag = 'h2';
+ $attributes['level'] = 2;
+ break;
+ case 'h3':
+ $block = 'core/heading';
+ $wrapper_tag = 'h3';
+ $attributes['level'] = 3;
+ break;
+ case 'h4':
+ $block = 'core/heading';
+ $wrapper_tag = 'h4';
+ $attributes['level'] = 4;
+ break;
+ case 'h5':
+ $block = 'core/heading';
+ $wrapper_tag = 'h5';
+ $attributes['level'] = 5;
+ break;
+ case 'h6':
+ $block = 'core/heading';
+ $wrapper_tag = 'h6';
+ $attributes['level'] = 6;
+ break;
+ case 'figure':
+ $block = 'core/image';
+ $wrapper_tag = 'figure';
+ break;
+ case 'img':
+ $block = 'core/image';
+ $wrapper_tag = 'figure';
+ break;
+ case 'button':
+ $block = 'core/button';
+ $wrapper_tag = 'div';
+ break;
+ case 'div':
+ $block = 'core/group';
+ $wrapper_tag = 'div';
+ break;
+ default:
+ $block = 'core/paragraph';
+ $wrapper_tag = 'p';
+ break;
+ }
+ }
+
+
+ // Create inner content with the correct HTML structure
+ $class_attr = '';
+ if (strpos($block, 'heading') !== false) {
+ $class_attr = ' class="wp-block-heading"';
+ }
+ if (strpos($block, 'image') !== false) {
+ $class_attr = ' class="wp-block-image"';
}
-
- // Extract PHP section and HTML section
- if ( ! preg_match( '/^<\?php.*?\?>(.*)/s', $content, $matches ) ) {
- // No PHP section, treat as static content
- return trim( $content );
- }
-
- $php_section = $matches[0];
- $html_section = $matches[1];
-
- // Parse PHP section to find get_field() calls
- $field_mappings = scf_extract_field_mappings( $php_section );
-
- // Convert HTML section by replacing PHP echoes with bindings
- $converted_html = scf_replace_php_echoes_with_bindings( $html_section, $field_mappings );
-
- return trim( $converted_html );
-}
-
-/**
- * Extract field mappings from PHP.
- *
- * @param string $php_content The PHP content to extract field mappings from.
- * @return array The field mappings.
- */
-function scf_extract_field_mappings( $php_content ) {
- $mappings = array();
-
- // Pattern to match: $variable = get_field('field_name') with optional post ID
- preg_match_all( '/\$(\w+)\s*=\s*get_field\([\'"]([^\'"]+)[\'"](?:\s*,\s*[^)]+)?\)/', $php_content, $matches, PREG_SET_ORDER );
-
- foreach ( $matches as $match ) {
- $variable = $match[1];
- $field_name = $match[2];
- $mappings[ $variable ] = $field_name;
- }
-
- // Also match get_sub_field patterns
- preg_match_all( '/\$(\w+)\s*=\s*get_sub_field\([\'"]([^\'"]+)[\'"]\)/', $php_content, $sub_matches, PREG_SET_ORDER );
-
- foreach ( $sub_matches as $match ) {
- $variable = $match[1];
- $field_name = $match[2];
- $mappings[ $variable ] = $field_name;
- }
-
- // Match get_the_terms patterns
- preg_match_all( '/\$(\w+)\s*=\s*get_the_terms\([^,]+,\s*[\'"]([^\'"]+)[\'"]\)/', $php_content, $terms_matches, PREG_SET_ORDER );
-
- foreach ( $terms_matches as $match ) {
- $variable = $match[1];
- $taxonomy_name = $match[2];
- $mappings[ $variable ] = $taxonomy_name;
- }
-
- return $mappings;
-}
-
-/**
- * Replace PHP echoes with block bindings.
- *
- * @param string $html_content The HTML content to replace PHP echoes with block bindings.
- * @param array $field_mappings The field mappings.
- * @return string The converted HTML content.
- */
-function scf_replace_php_echoes_with_bindings( $html_content, $field_mappings ) {
- // Process each individual block, including nested ones
- $html_content = scf_process_blocks_recursively( $html_content, $field_mappings );
-
- return $html_content;
+
+ // Generate content with proper HTML structure
+ if (empty(trim($inner_content))) {
+ if ($tag === 'img' || $tag === 'figure') {
+ $inner_content = sprintf('<%1$s%3$s>
%1$s>', $wrapper_tag, esc_attr(''), $class_attr);
+ } else {
+ $inner_content = sprintf('<%1$s%3$s>%2$s%1$s>', $wrapper_tag, esc_attr(''), $class_attr);
+ }
+
+ } else {
+ // Check if we need to add proper HTML structure
+ if (!preg_match('/^\s*<' . preg_quote($wrapper_tag, '/') . '[\s>]/i', $inner_content)) {
+ // Add class for headings if needed
+ $inner_content = sprintf('<%1$s%3$s>%2$s%1$s>', $wrapper_tag, $inner_content, $class_attr);
+ }
+ }
+
+ // Build block attributes JSON
+ $attr_json = '';
+ if (!empty($bindings_args)) {
+ // Initialize metadata bindings array
+ $attributes['metadata'] = array(
+ 'bindings' => array()
+ );
+
+ // Process each binding argument
+ foreach ((array)$bindings_args as $binding) {
+ // Check if this is a properly formatted binding
+ if (isset($binding['attribute']) && isset($binding['field'])) {
+ $attributes['metadata']['bindings'][$binding['attribute']] = array(
+ 'source' => $source,
+ 'args' => array(
+ 'field' => $binding['field']
+ )
+ );
+ }
+ }
+
+ $attr_json = wp_json_encode($attributes);
+ }
+
+ // Format according to WordPress block structure
+ $content = sprintf(
+ '
+%s
+',
+ esc_attr($block),
+ $attr_json,
+ $inner_content,
+ esc_attr($block)
+ );
+
+ return $content;
}
/**
- * Process blocks recursively.
+ * Load pattern content from a file by reading and processing it directly.
*
- * @param string $content The content to process.
- * @param array $field_mappings The field mappings.
- * @return string The processed content.
- */
-function scf_process_blocks_recursively( $content, $field_mappings ) {
- // Pattern to match WordPress blocks (including nested ones)
- return preg_replace_callback(
- '/(.*?)/s',
- function ( $matches ) use ( $field_mappings ) {
- $block_name = $matches[1];
- $attributes_str = $matches[2] ?? '{}';
- $block_content = $matches[3];
-
- // Parse existing attributes
- $attributes_str = $attributes_str ? $attributes_str : '{}';
- $attributes = json_decode( $attributes_str, true );
- $attributes = $attributes ? $attributes : array();
-
- // Process nested blocks first
- $block_content = scf_process_blocks_recursively( $block_content, $field_mappings );
-
- // Now process PHP echoes in this block's direct content
- $block_modified = false;
- $block_content = preg_replace_callback(
- '/<\?php\s+echo\s+esc_html\(\s*(?:the_title\(\)|\$(\w+))\s*\)\s*;\s*\?>|<\?php\s+echo\s+esc_url\(\s*\$(\w+)\s*\)\s*;\s*\?>|<\?php\s+echo\s+\$(\w+)\s*;\s*\?>|<\?php\s+the_title\(\)\s*;\s*\?>/',
- function ( $echo_matches ) use ( $field_mappings, &$attributes, $block_name, &$block_modified ) {
- // Extract variable name from different echo patterns
- $variable = '';
- for ( $i = 1; $i <= 4; $i++ ) {
- if ( ! empty( $echo_matches[ $i ] ) ) {
- $variable = $echo_matches[ $i ];
- break;
- }
- }
-
- if ( $variable && isset( $field_mappings[ $variable ] ) ) {
- $field_name = $field_mappings[ $variable ];
-
- // Handle special cases for image blocks
- if ( 'image' === $block_name ) {
- if ( strpos( $echo_matches[0], 'esc_url' ) !== false ) {
- $attributes['metadata']['bindings']['url'] = array(
- 'source' => 'scf/field',
- 'args' => array( 'field' => $field_name ),
- );
- $block_modified = true;
- return '/api/placeholder/400/300';
- } elseif ( strpos( $echo_matches[0], 'esc_html' ) !== false ) {
- // This is the image ID
- $attributes['id'] = 0; // Set a placeholder ID
- $block_modified = true;
- return '0';
- }
- } else {
- // For non-image blocks, use the standard binding
- $binding_attributes = scf_get_binding_attribute_for_block( $block_name );
- $primary_attribute = $binding_attributes[0] ?? 'content';
- $attributes['metadata']['bindings'][ $primary_attribute ] = array(
- 'source' => 'scf/field',
- 'args' => array( 'field' => $field_name ),
- );
- $block_modified = true;
- return scf_get_placeholder_for_field( $field_name, $primary_attribute );
- }
- }
-
- // Return original if no mapping found
- return $echo_matches[0];
- },
- $block_content
- );
-
- // For image blocks, ensure we have the proper structure
- if ( 'image' === $block_name ) {
- // If we have bindings but no proper image structure, fix it
- if ( isset( $attributes['metadata']['bindings'] ) && ! strpos( $block_content, '
';
- }
- }
-
- // Rebuild block
- $attributes_json = ! empty( $attributes ) ? wp_json_encode( $attributes, JSON_UNESCAPED_SLASHES ) : '';
-
- // Only include attributes if we have some
- $attr_part = '{}' !== $attributes_json ? " {$attributes_json}" : '';
-
- return "{$block_content}";
- },
- $content
- );
-}
-
-/**
- * Get the supported binding attributes for a block.
+ * This is the recommended method to use instead of scf_parse_pattern_file()
+ * as it doesn't rely on output buffering, which can cause issues.
*
- * @param string $block_name The name of the block.
- * @return array The supported binding attributes for the block.
+ * @since SCF 6.5.1
+ * @param string $pattern_file The pattern file path.
+ * @return string|WP_Error The pattern content or WP_Error on failure.
*/
-function scf_get_binding_attribute_for_block( $block_name ) {
- $supported_block_attributes = array(
- 'core/paragraph' => array( 'content' ),
- 'core/heading' => array( 'content' ),
- 'core/image' => array( 'id', 'url', 'title', 'alt' ),
- 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ),
- );
-
- return $supported_block_attributes[ $block_name ] ?? array( 'content' );
-}
-
-/**
- * Get a placeholder value for a field based on its binding attribute.
- *
- * @param string $field_name The name of the field.
- * @param string $binding_attribute The binding attribute to get a placeholder for.
- * @return string The placeholder value.
- */
-function scf_get_placeholder_for_field( $field_name, $binding_attribute = 'content' ) {
- // Handle specific binding attributes that need special values
- if ( 'url' === $binding_attribute || 'src' === $binding_attribute ) {
- return '/api/placeholder/400/300';
- }
-
- if ( 'alt' === $binding_attribute ) {
- return 'Image description';
- }
-
- if ( 'id' === $binding_attribute ) {
- return '0';
- }
-
- if ( 'linkTarget' === $binding_attribute ) {
- return '_self';
- }
-
- if ( 'rel' === $binding_attribute ) {
- return '';
- }
-
- // For all other attributes, return a simple generic placeholder
- return sprintf( '[%s]', ucwords( str_replace( array( '_', '-' ), ' ', $field_name ) ) );
+function scf_load_pattern_from_file( $pattern_file ) {
+ if ( ! file_exists( $pattern_file ) || ! is_readable( $pattern_file ) ) {
+ return new WP_Error( 'pattern_not_found', 'Pattern file not found or not readable' );
+ }
+
+ // For PHP files, execute directly without reading the entire file first
+ if ( pathinfo( $pattern_file, PATHINFO_EXTENSION ) === 'php' ) {
+ try {
+ // Create a closure that mimics the include environment but returns the content
+ $sandbox = function( $file_path ) {
+ ob_start();
+ $result = include $file_path;
+ $output = ob_get_clean();
+
+ // If the file returns a string directly (recommended pattern),
+ // use that instead of captured output
+ if ( is_string( $result ) ) {
+ return $result;
+ }
+
+ // Otherwise return the captured output
+ return $output;
+ };
+
+ return $sandbox( $pattern_file );
+ } catch ( Exception $e ) {
+ return new WP_Error( 'pattern_execution_error', $e->getMessage() );
+ }
+ }
+
+ // For non-PHP files (like HTML), only now do we read the file
+ $file_content = file_get_contents( $pattern_file );
+ if ( false === $file_content ) {
+ return new WP_Error( 'pattern_read_error', 'Unable to read pattern file contents' );
+ }
+
+ return $file_content;
}
From 2b15a95eada464c3815ed49e7a443ce67e4edee9 Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Wed, 28 May 2025 14:51:47 +0200
Subject: [PATCH 07/20] Enable as an experiment
---
includes/acf-pattern-functions.php | 4 +-
includes/admin/beta-features.php | 10 ++---
.../class-scf-beta-feature-code-patterns.php | 37 +++++++++++++++++++
secure-custom-fields.php | 5 ++-
4 files changed, 48 insertions(+), 8 deletions(-)
create mode 100644 includes/admin/beta-features/class-scf-beta-feature-code-patterns.php
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
index d5417327..64d879d7 100644
--- a/includes/acf-pattern-functions.php
+++ b/includes/acf-pattern-functions.php
@@ -12,7 +12,7 @@
* @param string $pattern_directory The directory containing the pattern file.
* @return array|WP_Error The pattern registration result or a WP_Error if the pattern is invalid.
*/
-function scf_register_smart_pattern( $pattern_directory ) {
+function experimental_scf_register_pattern( $pattern_directory ) {
if ( ! file_exists( $pattern_directory ) || ! is_readable( $pattern_directory ) ) {
return new WP_Error( 'pattern_not_found', 'Pattern file not found' );
}
@@ -58,7 +58,7 @@ function scf_register_smart_pattern( $pattern_directory ) {
);
}
-function create_block_with_binding( string $tag, string $source, array $bindings_args = array(), string $inner_content = '' ) {
+function experimental_create_block_with_binding( string $tag, string $source, array $bindings_args = array(), string $inner_content = '' ) {
// If tag is specified, map it to the appropriate block type
$block = 'core/paragraph'; // Default block type
$wrapper_tag = 'p'; // Default HTML wrapper tag
diff --git a/includes/admin/beta-features.php b/includes/admin/beta-features.php
index 1051fd58..5f32bf49 100644
--- a/includes/admin/beta-features.php
+++ b/includes/admin/beta-features.php
@@ -35,8 +35,7 @@ class SCF_Admin_Beta_Features {
* @return void
*/
public function __construct() {
- // Temporarily disabled - will be enabled when beta feature is ready
- // add_action( 'admin_menu', array( $this, 'admin_menu' ), 20 );
+ add_action( 'admin_menu', array( $this, 'admin_menu' ), 20 );
}
/**
@@ -88,7 +87,8 @@ public function get_beta_features() {
public function localize_beta_features() {
$beta_features = array();
foreach ( $this->get_beta_features() as $name => $beta_feature ) {
- $beta_features[ $name ] = $beta_feature->is_enabled();
+ $is_enabled = $beta_feature->is_enabled();
+ $beta_features[ $name ] = $is_enabled;
}
acf_localize_data(
@@ -155,7 +155,7 @@ public function admin_body_class( $classes ) {
*/
private function include_beta_features() {
acf_include( 'includes/admin/beta-features/class-scf-beta-feature.php' );
- acf_include( 'includes/admin/beta-features/class-scf-beta-feature-editor-sidebar.php' );
+ acf_include( 'includes/admin/beta-features/class-scf-beta-feature-code-patterns.php' );
add_action( 'scf/include_admin_beta_features', array( $this, 'register_beta_features' ) );
@@ -170,7 +170,7 @@ private function include_beta_features() {
* @return void
*/
public function register_beta_features() {
- scf_register_admin_beta_feature( 'SCF_Admin_Beta_Feature_Editor_Sidebar' );
+ scf_register_admin_beta_feature( 'SCF_Admin_Beta_Feature_Code_Patterns' );
}
/**
diff --git a/includes/admin/beta-features/class-scf-beta-feature-code-patterns.php b/includes/admin/beta-features/class-scf-beta-feature-code-patterns.php
new file mode 100644
index 00000000..a0bb8016
--- /dev/null
+++ b/includes/admin/beta-features/class-scf-beta-feature-code-patterns.php
@@ -0,0 +1,37 @@
+name = 'code_patterns';
+ $this->title = __( 'Add SCF Code Patterns', 'secure-custom-fields' );
+ $this->description = __( 'Provides an API to register code patterns.', 'secure-custom-fields' );
+ }
+ }
+endif;
diff --git a/secure-custom-fields.php b/secure-custom-fields.php
index 5e6bacbf..2ae913ab 100644
--- a/secure-custom-fields.php
+++ b/secure-custom-fields.php
@@ -169,7 +169,9 @@ public function initialize() {
acf_include( 'includes/acf-field-group-functions.php' );
acf_include( 'includes/acf-form-functions.php' );
acf_include( 'includes/acf-meta-functions.php' );
- acf_include( 'includes/acf-pattern-functions.php' );
+ if ( get_option( 'scf_beta_feature_code_patterns_enabled' ) ) {
+ acf_include( 'includes/acf-pattern-functions.php' );
+ }
acf_include( 'includes/acf-post-functions.php' );
acf_include( 'includes/acf-user-functions.php' );
acf_include( 'includes/acf-value-functions.php' );
@@ -880,6 +882,7 @@ function scf_plugin_uninstall() {
// List of known beta features.
$beta_features = array(
'editor_sidebar',
+ 'code_patterns',
);
foreach ( $beta_features as $beta_feature ) {
From 64cde78a8d091f5b100b419ea6c73f3da46329f6 Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Wed, 28 May 2025 17:07:06 +0200
Subject: [PATCH 08/20] Fix images
---
includes/Blocks/Bindings.php | 11 +++++++++--
includes/acf-pattern-functions.php | 5 +++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/includes/Blocks/Bindings.php b/includes/Blocks/Bindings.php
index c8dd559f..aad5ca35 100644
--- a/includes/Blocks/Bindings.php
+++ b/includes/Blocks/Bindings.php
@@ -39,7 +39,7 @@ public function register_binding_sources() {
)
);
register_block_bindings_source(
- 'scf/field',
+ 'scf/experimental-field',
array(
'label' => _x( 'SCF Fields', 'The core SCF block binding source name for fields on the current page', 'secure-custom-fields' ),
'uses_context' => array( 'postId', 'postType' ),
@@ -77,7 +77,6 @@ public function scf_get_block_binding_value( $source_attrs, $block_instance, $at
switch ( $attribute_name ) {
case 'content':
return is_array( $value ) ? ( $value['alt'] ?? '' ) : (string) $value;
- case 'src':
case 'url':
if ( is_array( $value ) && isset( $value['url'] ) ) {
return $value['url'];
@@ -94,6 +93,14 @@ public function scf_get_block_binding_value( $source_attrs, $block_instance, $at
return get_post_meta( $value, '_wp_attachment_image_alt', true );
}
return '';
+ case 'id':
+ if ( is_array( $value ) && isset( $value['id'] ) ) {
+ return (string) $value['id'];
+ }
+ if ( is_numeric( $value ) ) {
+ return (string) $value;
+ }
+ return '';
default:
return is_string( $value ) ? $value : '';
}
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
index 64d879d7..6ac10629 100644
--- a/includes/acf-pattern-functions.php
+++ b/includes/acf-pattern-functions.php
@@ -58,7 +58,7 @@ function experimental_scf_register_pattern( $pattern_directory ) {
);
}
-function experimental_create_block_with_binding( string $tag, string $source, array $bindings_args = array(), string $inner_content = '' ) {
+function experimental_create_block_with_binding( string $tag, array $bindings_args = array(), string $inner_content = '' ) {
// If tag is specified, map it to the appropriate block type
$block = 'core/paragraph'; // Default block type
$wrapper_tag = 'p'; // Default HTML wrapper tag
@@ -163,7 +163,8 @@ function experimental_create_block_with_binding( string $tag, string $source, ar
// Check if this is a properly formatted binding
if (isset($binding['attribute']) && isset($binding['field'])) {
$attributes['metadata']['bindings'][$binding['attribute']] = array(
- 'source' => $source,
+ // TODO: We can pass the source as a variable so it will work with any binding source.
+ 'source' => 'scf/experimental-field',
'args' => array(
'field' => $binding['field']
)
From d6bd7d83b384900738f4cf91068be3f20075562e Mon Sep 17 00:00:00 2001
From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com>
Date: Wed, 28 May 2025 17:50:05 +0200
Subject: [PATCH 09/20] Group it if not before
---
includes/acf-pattern-functions.php | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/includes/acf-pattern-functions.php b/includes/acf-pattern-functions.php
index 6ac10629..750010fb 100644
--- a/includes/acf-pattern-functions.php
+++ b/includes/acf-pattern-functions.php
@@ -163,7 +163,7 @@ function experimental_create_block_with_binding( string $tag, array $bindings_ar
// Check if this is a properly formatted binding
if (isset($binding['attribute']) && isset($binding['field'])) {
$attributes['metadata']['bindings'][$binding['attribute']] = array(
- // TODO: We can pass the source as a variable so it will work with any binding source.
+ // TODO: We can pass the source as a variable so it will work with any source.
'source' => 'scf/experimental-field',
'args' => array(
'field' => $binding['field']
@@ -223,17 +223,25 @@ function scf_load_pattern_from_file( $pattern_file ) {
return $output;
};
- return $sandbox( $pattern_file );
+ $pattern_content = $sandbox( $pattern_file );
} catch ( Exception $e ) {
return new WP_Error( 'pattern_execution_error', $e->getMessage() );
}
+ } else {
+ // For non-PHP files (like HTML), only now do we read the file
+ $pattern_content = file_get_contents( $pattern_file );
+ if ( false === $pattern_content ) {
+ return new WP_Error( 'pattern_read_error', 'Unable to read pattern file contents' );
+ }
}
-
- // For non-PHP files (like HTML), only now do we read the file
- $file_content = file_get_contents( $pattern_file );
- if ( false === $file_content ) {
- return new WP_Error( 'pattern_read_error', 'Unable to read pattern file contents' );
+
+ // Wrap the pattern content in a group block if it's not already a group block
+ if (!preg_match('/^\n