plugin updates

This commit is contained in:
Tony Volpe
2024-06-17 14:48:11 -04:00
parent ecc5fbf831
commit 3751a5a1a6
1318 changed files with 91130 additions and 52250 deletions

View File

@@ -67,7 +67,6 @@ if ( ! class_exists( 'acf_admin_options_page' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function admin_load() {
// globals
@@ -200,7 +199,6 @@ if ( ! class_exists( 'acf_admin_options_page' ) ) :
* @param n/a
* @return n/a
*/
function postbox_submitdiv( $post, $args ) {
/**

View File

@@ -147,7 +147,7 @@ if ( ! class_exists( 'ACF_Admin_Updates' ) ) :
// Check if we should force check the license status.
$force_get_license_status = false;
$retry_license_nonce = acf_request_arg( 'acf_retry_nonce' );
if ( wp_verify_nonce( $retry_license_nonce, 'acf_recheck_status' ) ) {
if ( wp_verify_nonce( $retry_license_nonce, 'acf_recheck_status' ) || ! empty( $_GET['force-license-check'] ) ) {
$force_get_license_status = true;
}

View File

@@ -144,7 +144,7 @@ if ( ! class_exists( 'ACF_Admin_UI_Options_Pages' ) ) :
// Description.
case 'acf-description':
if ( ! empty( $post['description'] ) && is_string( $post['description'] ) ) {
if ( ! empty( $post['description'] ) && ( is_string( $post['description'] ) || is_numeric( $post['description'] ) ) ) {
echo '<span class="acf-description">' . acf_esc_html( $post['description'] ) . '</span>';
} else {
echo '<span class="acf-emdash" aria-hidden="true">—</span>';

View File

@@ -26,18 +26,46 @@ foreach ( acf_get_combined_options_page_settings_tabs() as $tab_key => $tab_labe
$acf_dashicon_link
);
// Set the default value for the icon field.
$acf_default_icon_value = array(
'type' => 'dashicons',
'value' => 'dashicons-admin-generic',
);
$acf_icon_value = $acf_default_icon_value;
// Override the value for backwards compatibility, if it was saved with the key 'icon_url' as a string.
if ( ! empty( $acf_ui_options_page['icon_url'] ) ) {
if ( strpos( $acf_ui_options_page['icon_url'], 'dashicons-' ) === 0 ) {
$acf_icon_value = array(
'type' => 'dashicons',
'value' => $acf_ui_options_page['icon_url'],
);
} else {
$acf_icon_value = array(
'type' => 'url',
'value' => $acf_ui_options_page['icon_url'],
);
}
}
// Override the above value if a 'menu_icon' key exists, and is not empty, which is the new key for storing the icon.
if ( ! empty( $acf_ui_options_page['menu_icon'] ) ) {
$acf_icon_value = $acf_ui_options_page['menu_icon'];
}
acf_render_field_wrap(
array(
'label' => __( 'Menu Icon', 'acf' ),
'type' => 'text',
'name' => 'icon_url',
'key' => 'icon_url',
'class' => 'acf-options-page-menu_icon',
'prefix' => 'acf_ui_options_page',
'value' => $acf_ui_options_page['icon_url'],
'instructions' => $acf_menu_icon_instructions,
'placeholder' => 'dashicons-admin-generic',
'conditions' => array(
'label' => __( 'Menu Icon', 'acf' ),
'type' => 'icon_picker',
'name' => 'menu_icon',
'key' => 'menu_icon',
'class' => 'acf-options-page-menu_icon',
'prefix' => 'acf_ui_options_page',
'required' => false,
'value' => $acf_icon_value,
'default_value' => $acf_default_icon_value,
'conditions' => array(
'field' => 'parent_slug',
'operator' => '==',
'value' => 'none',

View File

@@ -1,6 +1,20 @@
<?php
global $acf_ui_options_page, $acf_parent_page_options;
$acf_duplicate_options_page = acf_get_ui_options_page_from_request_args( 'acfduplicate' );
if ( acf_is_ui_options_page( $acf_duplicate_options_page ) ) {
// Reset vars that likely have to be changed.
$acf_duplicate_options_page['key'] = uniqid( 'ui_options_page_' );
$acf_duplicate_options_page['title'] = '';
$acf_duplicate_options_page['page_title'] = '';
$acf_duplicate_options_page['menu_title'] = '';
$acf_duplicate_options_page['menu_slug'] = '';
// Rest of the vars can be reused.
$acf_ui_options_page = $acf_duplicate_options_page;
}
acf_render_field_wrap(
array(
'label' => __( 'Page Title', 'acf' ),

View File

@@ -11,6 +11,7 @@ defined( 'ABSPATH' ) || exit;
// Register store.
acf_register_store( 'block-types' );
acf_register_store( 'block-cache' );
acf_register_store( 'block-meta-values' );
// Register block.json support handlers.
add_filter( 'block_type_metadata', 'acf_add_block_namespace' );
@@ -65,6 +66,8 @@ function acf_handle_json_block_registration( $settings, $metadata ) {
'attributes' => array(),
'acf_block_version' => 2,
'api_version' => 2,
'validate' => true,
'use_post_meta' => false,
)
);
@@ -78,10 +81,11 @@ function acf_handle_json_block_registration( $settings, $metadata ) {
$settings['supports'] = wp_parse_args(
$settings['supports'],
array(
'align' => true,
'html' => false,
'mode' => true,
'jsx' => true,
'align' => true,
'html' => false,
'mode' => true,
'jsx' => true,
'multiple' => true,
)
);
@@ -105,6 +109,8 @@ function acf_handle_json_block_registration( $settings, $metadata ) {
'mode' => 'mode',
'blockVersion' => 'acf_block_version',
'postTypes' => 'post_types',
'validate' => 'validate',
'usePostMeta' => 'use_post_meta',
);
$textdomain = ! empty( $metadata['textdomain'] ) ? $metadata['textdomain'] : 'acf';
$i18n_schema = get_block_metadata_i18n_schema();
@@ -123,6 +129,12 @@ function acf_handle_json_block_registration( $settings, $metadata ) {
$settings['name'] = $metadata['name'];
$settings['path'] = dirname( $metadata['file'] );
// Prevent blocks that usePostMeta from being nested or saving multiple.
if ( ! empty( $settings['use_post_meta'] ) ) {
$settings['parent'] = array( 'core/post-content' );
$settings['supports']['multiple'] = false;
}
acf_get_store( 'block-types' )->set( $metadata['name'], $settings );
add_action( 'enqueue_block_editor_assets', 'acf_enqueue_block_assets' );
@@ -410,15 +422,17 @@ function acf_validate_block_type( $block ) {
* @since 5.8.0
*
* @param array $block The block props.
* @return array
* @return array|boolean
*/
function acf_prepare_block( $block ) {
// Bail early if no name.
if ( ! isset( $block['name'] ) ) {
return false;
}
// Ensure a block ID is always prefixed with `block_` for meta.
$block['id'] = acf_ensure_block_id_prefix( $block['id'] );
// Get block type and return false if doesn't exist.
$block_type = acf_get_block_type( $block['name'] );
if ( ! $block_type ) {
@@ -522,15 +536,16 @@ function acf_render_block_callback( $attributes, $content = '', $wp_block = null
* @date 28/2/19
* @since 5.7.13
*
* @param array $attributes The block attributes.
* @param string $content The block content.
* @param boolean $is_preview Whether or not the block is being rendered for editing preview.
* @param integer $post_id The current post being edited or viewed.
* @param WP_Block $wp_block The block instance (since WP 5.5).
* @param array $context The block context array.
* @param array $attributes The block attributes.
* @param string $content The block content.
* @param boolean $is_preview Whether or not the block is being rendered for editing preview.
* @param integer $post_id The current post being edited or viewed.
* @param WP_Block $wp_block The block instance (since WP 5.5).
* @param array $context The block context array.
* @param boolean $is_ajax_render Whether or not this is an ACF AJAX render.
* @return string The block HTML.
*/
function acf_rendered_block( $attributes, $content = '', $is_preview = false, $post_id = 0, $wp_block = null, $context = false ) {
function acf_rendered_block( $attributes, $content = '', $is_preview = false, $post_id = 0, $wp_block = null, $context = false, $is_ajax_render = false ) {
$mode = isset( $attributes['mode'] ) ? $attributes['mode'] : 'auto';
$form = ( 'edit' === $mode && $is_preview );
@@ -540,7 +555,11 @@ function acf_rendered_block( $attributes, $content = '', $is_preview = false, $p
}
// Check if we need to generate a block ID.
$attributes['id'] = acf_get_block_id( $attributes, $context );
$force_new_id = false;
if ( acf_block_uses_post_meta( $attributes ) && ! empty( $attributes['id'] ) && empty( $attributes['data'] ) ) {
$force_new_id = true;
}
$attributes['id'] = acf_get_block_id( $attributes, $context, $force_new_id );
// Check if we've already got a cache of this block ID and return it to save rendering if we're in the backend.
if ( $is_preview ) {
@@ -558,19 +577,27 @@ function acf_rendered_block( $attributes, $content = '', $is_preview = false, $p
ob_start();
$validation = false;
if ( $form ) {
// Load the block form since we're in edit mode.
// Set flag for post REST cleanup of media enqueue count during preloads.
acf_set_data( 'acf_did_render_block_form', true );
$block = acf_prepare_block( $attributes );
$block = acf_add_block_meta_values( $block, $post_id );
acf_setup_meta( $block['data'], $block['id'], true );
if ( ! empty( $block['validate'] ) ) {
$validation = acf_get_block_validation_state( $block );
}
$fields = acf_get_block_fields( $block );
if ( $fields ) {
acf_prefix_fields( $fields, "acf-{$block['id']}" );
echo '<div class="acf-block-fields acf-fields">';
acf_render_fields( $fields, $block['id'], 'div', 'field' );
echo '<div class="acf-block-fields acf-fields" data-block-id="' . esc_attr( $block['id'] ) . '">';
acf_render_fields( $fields, acf_ensure_block_id_prefix( $block['id'] ), 'div', 'field' );
echo '</div>';
} else {
echo acf_get_empty_block_form_html( $attributes['name'] ); //phpcs:ignore -- escaped in function.
@@ -578,6 +605,19 @@ function acf_rendered_block( $attributes, $content = '', $is_preview = false, $p
} else {
// Capture block render output.
acf_render_block( $attributes, $content, $is_preview, $post_id, $wp_block, $context );
if ( $is_preview && ! $is_ajax_render ) {
/**
* If we're in preloaded preview, we need to get the validation state for a preview too.
* Because the block render resets meta once it's finished to not pollute $post_id, we need to redo that process here.
*/
$block = acf_prepare_block( $attributes );
$block = acf_add_block_meta_values( $block, $post_id );
acf_setup_meta( $block['data'], $block['id'], true );
if ( ! empty( $block['validate'] ) ) {
$validation = acf_get_block_validation_state( $block );
}
}
}
$html = ob_get_clean();
@@ -602,13 +642,20 @@ function acf_rendered_block( $attributes, $content = '', $is_preview = false, $p
$html = preg_replace( '/<InnerBlocks([\S\s]*?)\/>/', $content, $html );
}
$block_cache = array(
'form' => $form,
'html' => $html,
);
if ( $is_preview && $validation ) {
// If we're in the preview, also store the validation status in the block cache.
$block_cache['validation'] = $validation;
}
// Store in cache for preloading if we're in the backend.
acf_get_store( 'block-cache' )->set(
$attributes['id'],
array(
'form' => $form,
'html' => $html,
)
$block_cache
);
// Prevent edit forms being output to rest endpoints.
@@ -633,7 +680,6 @@ function acf_rendered_block( $attributes, $content = '', $is_preview = false, $p
* @return void|string
*/
function acf_render_block( $attributes, $content = '', $is_preview = false, $post_id = 0, $wp_block = null, $context = false ) {
// Prepare block ensuring all settings and attributes exist.
$block = acf_prepare_block( $attributes );
if ( ! $block ) {
@@ -648,8 +694,7 @@ function acf_render_block( $attributes, $content = '', $is_preview = false, $pos
// Enqueue block type assets.
acf_enqueue_block_type_assets( $block );
// Ensure block ID is prefixed for render.
$block['id'] = acf_ensure_block_id_prefix( $block['id'] );
$block = acf_add_block_meta_values( $block, $post_id );
// Setup postdata allowing get_field() to work.
acf_setup_meta( $block['data'], $block['id'], true );
@@ -700,10 +745,13 @@ function acf_block_render_template( $block, $content, $is_preview, $post_id, $wp
* @return array
*/
function acf_get_block_fields( $block ) {
// Vars.
$fields = array();
// We need at least a block name to check.
if ( empty( $block['name'] ) ) {
return $fields;
}
// Get field groups for this block.
$field_groups = acf_get_field_groups(
array(
@@ -718,7 +766,6 @@ function acf_get_block_fields( $block ) {
}
}
// Return fields.
return $fields;
}
@@ -870,20 +917,24 @@ function acf_ajax_fetch_block() {
// Prepare block ensuring all settings and attributes exist.
$block = acf_prepare_block( $block );
$block = acf_add_block_meta_values( $block, $post_id );
if ( ! $block ) {
wp_send_json_error();
}
// Load field defaults when first previewing a block.
$first_preview = false;
if ( ! empty( $query['preview'] ) && ! $block['data'] ) {
$fields = acf_get_block_fields( $block );
foreach ( $fields as $field ) {
$block['data'][ "_{$field['name']}" ] = $field['key'];
}
$first_preview = true;
}
// Setup postdata allowing form to load meta.
acf_setup_meta( $block['data'], acf_ensure_block_id_prefix( $block['id'] ), true );
acf_setup_meta( $block['data'], $block['id'], true );
// Setup main postdata for post_id.
global $post;
@@ -894,6 +945,21 @@ function acf_ajax_fetch_block() {
// Vars.
$response = array( 'clientId' => $client_id );
// Check if we've recieved serialised form data
$use_post_data = false;
if ( ! empty( $block['data'] ) && is_array( $block['data'] ) ) {
// Ensure we've got field keys posted.
$valid_field_keys = array_filter( array_keys( $block['data'] ), 'acf_is_field_key' );
if ( ! empty( $valid_field_keys ) ) {
$use_post_data = true;
}
}
$query['validate'] = ( ! empty( $query['validate'] ) && ( $query['validate'] === 'true' || $query['validate'] === true ) );
if ( ! empty( $query['validate'] ) || ! empty( $block['validate'] ) ) {
$response['validation'] = acf_get_block_validation_state( $block, $first_preview, $use_post_data );
}
// Query form.
if ( ! empty( $query['form'] ) ) {
@@ -908,8 +974,8 @@ function acf_ajax_fetch_block() {
ob_start();
// Render.
echo '<div class="acf-block-fields acf-fields">';
acf_render_fields( $fields, acf_ensure_block_id_prefix( $block['id'] ), 'div', 'field' );
echo '<div class="acf-block-fields acf-fields" data-block-id="' . esc_attr( $block['id'] ) . '">';
acf_render_fields( $fields, $block['id'], 'div', 'field' );
echo '</div>';
// Store Capture.
@@ -927,7 +993,7 @@ function acf_ajax_fetch_block() {
$is_preview = true;
// Render and store HTML.
$response['preview'] = acf_rendered_block( $block, $content, $is_preview, $post_id, null, $context );
$response['preview'] = acf_rendered_block( $block, $content, $is_preview, $post_id, null, $context, true );
}
// Send response.
@@ -960,7 +1026,15 @@ function acf_get_empty_block_form_html( $block_name ) {
$message = apply_filters( 'acf/blocks/no_fields_assigned_message', $message, $block_name );
return empty( $message ) ? '' : acf_esc_html( '<div class="acf-block-fields acf-fields acf-empty-block-fields">' . $message . '</div>' );
if ( ! is_string( $message ) ) {
$message = '';
}
if ( empty( $message ) ) {
return acf_esc_html( '<div class="acf-empty-block-fields"></div>' );
} else {
return acf_esc_html( '<div class="acf-block-fields acf-fields acf-empty-block-fields">' . $message . '</div>' );
}
}
/**
@@ -995,7 +1069,6 @@ add_filter( 'content_save_pre', 'acf_parse_save_blocks', 5, 1 );
* @return string
*/
function acf_parse_save_blocks_callback( $matches ) {
// Defaults.
$name = isset( $matches['name'] ) ? $matches['name'] : '';
$attrs = isset( $matches['attrs'] ) ? json_decode( $matches['attrs'], true ) : '';
@@ -1007,21 +1080,32 @@ function acf_parse_save_blocks_callback( $matches ) {
}
// Check if we need to generate a block ID.
$block_id = acf_get_block_id( $attrs );
$block_id = acf_ensure_block_id_prefix( acf_get_block_id( $attrs ) );
// Convert "data" to "meta".
// No need to check if already in meta format. Local Meta will do this for us.
if ( isset( $attrs['data'] ) ) {
$attrs['data'] = acf_setup_meta( $attrs['data'], acf_ensure_block_id_prefix( $block_id ) );
if ( ! empty( $attrs['data'] ) ) {
if ( acf_block_uses_post_meta( $attrs ) ) {
// Block ID is used later to retrieve & save values.
$attrs['id'] = $block_id;
// Cache the values until we have a post ID and can save.
$store = acf_get_store( 'block-meta-values' );
$store->set( $block_id, $attrs['data'] );
// No need to store values in post content.
unset( $attrs['data'] );
} else {
// Convert "data" to "meta".
// No need to check if already in meta format. Local Meta will do this for us.
$attrs['data'] = acf_setup_meta( $attrs['data'], $block_id );
}
}
/**
* Filters the block attributes before saving.
*
* @date 18/3/19
* @since 5.7.14
* @since 5.7.14
*
* @param array $attrs The block attributes.
* @param array $attrs The block attributes.
*/
$attrs = apply_filters( 'acf/pre_save_block', $attrs );
@@ -1036,13 +1120,17 @@ function acf_parse_save_blocks_callback( $matches ) {
*
* @since 6.0.0
*
* @param array $attributes A block attributes array.
* @param array $context The block context array, defaults to an empty array.
* @param array $attributes A block attributes array.
* @param array $context The block context array, defaults to an empty array.
* @param boolean $force If we should generate a new block ID even if one exists.
* @return string A block ID.
*/
function acf_get_block_id( $attributes, $context = array() ) {
function acf_get_block_id( $attributes, $context = array(), $force = false ) {
$context = is_array( $context ) ? $context : array();
ksort( $context );
$attributes['_acf_context'] = $context;
if ( empty( $attributes['id'] ) ) {
if ( empty( $attributes['id'] ) || $force ) {
unset( $attributes['id'] );
// Remove all empty string values as they're not present in JS hash building.
@@ -1106,6 +1194,92 @@ function acf_serialize_block_attributes( $block_attributes ) {
return $encoded_attributes;
}
/**
* Handle validating a block's fields and return the validity, and any errors.
*
* This function uses the values loaded into Local Meta, which means they have to be
* converted back to the data format because they can be validated.
*
* @since 6.3
*
* @param array $block An array of the block's data attribute.
* @param boolean $using_defaults True if the block is currently being generated with default values. Default false.
* @param boolean $use_post_data True if we should validate the POSTed data rather than local meta values. Default false.
* @return array An array containing a valid boolean, and an errors array.
*/
function acf_get_block_validation_state( $block, $using_defaults = false, $use_post_data = false ) {
$block_id = $block['id'];
if ( $use_post_data ) {
$errors = acf_validate_block_from_post_data( $block );
} elseif ( $using_defaults || empty( $block['data'] ) ) {
// If data is empty or it's first preview, load the default fields for this block so we can get a required validation state from the current field set.
$errors = acf_validate_block_from_local_meta( $block_id, acf_get_block_fields( $block ) );
} else {
$errors = acf_validate_block_from_local_meta( $block_id, get_field_objects( $block_id, false ) );
}
return array(
'valid' => empty( $errors ),
'errors' => $errors,
);
}
/**
* Handle the specific validation for a block from POSTed values.
*
* @since 6.3.1
*
* @param array $block The block object containing the POSTed values and other block data
* @return array|boolean An array containing the validation errors, or false if there are no errors.
*/
function acf_validate_block_from_post_data( $block ) {
acf_reset_validation_errors();
acf_validate_values( $block['data'], "acf-{$block['id']}" );
$errors = acf_get_validation_errors();
return $errors;
}
/**
* Handle the specific validation for a block from local meta.
*
* This function uses the values loaded into Local Meta, which means they have to be
* converted back to the data format because they can be validated.
*
* @since 6.3.1
*
* @param string $block_id The block ID
* @param array $field_objects The field objects in local meta to be validated.
* @return array|boolean An array containing the validation errors, or false if there are no errors.
*/
function acf_validate_block_from_local_meta( $block_id, $field_objects ) {
if ( empty( $field_objects ) ) {
return false;
}
$skip_conditional_fields = false;
if ( acf_get_data( $block_id . '_loaded_meta_values' ) ) {
$skip_conditional_fields = true;
}
acf_reset_validation_errors();
foreach ( $field_objects as $field ) {
/**
* Skips validation of conditional fields in post meta blocks when
* preloading or during the first AJAX render if preloading is disabled.
*/
if ( $skip_conditional_fields && ! empty( $field['conditional_logic'] ) ) {
continue;
}
$key = $field['key'];
$value = $field['value'];
acf_validate_value( $value, $field, "acf-{$block_id}[{$key}]" );
}
return acf_get_validation_errors();
}
/**
* Set ACF data before a rest call if media scripts have not been enqueued yet for after REST reset.
*
@@ -1146,3 +1320,148 @@ function acf_reset_media_enqueue_after_rest( $response ) {
return $response;
}
add_filter( 'rest_request_after_callbacks', 'acf_reset_media_enqueue_after_rest' );
/**
* Checks if the provided block is configured to save/load post meta.
*
* @since 6.3
*
* @param array $block The block to check.
* @return boolean
*/
function acf_block_uses_post_meta( $block ): bool {
if ( ! empty( $block['name'] ) && ! isset( $block['use_post_meta'] ) ) {
$block = acf_get_block_type( $block['name'] );
}
return ! empty( $block['use_post_meta'] );
}
/**
* Loads ACF field values from the post meta if the block is configured to do so.
*
* @since 6.3
*
* @param array $block The block to get values for.
* @param integer $post_id The ID of the post to retrieve meta from.
* @return array
*/
function acf_add_block_meta_values( $block, $post_id ) {
// Bail if the block already has data (i.e. previewing an update).
if ( ! is_array( $block ) || ! empty( $block['data'] ) ) {
return $block;
}
// Bail if block doesn't load from meta.
if ( ! acf_block_uses_post_meta( $block ) ) {
return $block;
}
// Bail if we don't have a post ID or block ID.
if ( empty( $post_id ) || empty( $block['id'] ) ) {
return $block;
}
$fields = acf_get_block_fields( $block );
if ( empty( $fields ) ) {
return $block;
}
$values = array();
$store = acf_get_store( 'values' );
$block_id = acf_ensure_block_id_prefix( $block['id'] );
foreach ( $fields as $field ) {
$value = acf_get_value( $post_id, $field );
// Make sure we got a value (i.e. $allow_load = true).
if ( ! $store->has( "{$post_id}:{$field['name']}" ) ) {
continue;
}
$store->set( "{$block_id}:{$field['name']}", $value );
$values[ $field['name'] ] = $value;
$values[ '_' . $field['name'] ] = $field['key']; // TODO: Is there a better way to generate this?
}
$block['data'] = $values;
acf_set_data( $block_id . '_loaded_meta_values', true );
return $block;
}
/**
* Stores ACF field values in post meta for any blocks configured to do so.
*
* @since 6.3
*
* @param integer $post_id The ID of the post being saved.
* @param WP_Post $post The post object.
* @return void
*/
function acf_save_block_meta_values( $post_id, $post ) {
$meta_values = acf_get_block_meta_values_to_save( $post->post_content );
if ( empty( $meta_values ) ) {
return;
}
// Save values for any post meta blocks.
acf_save_post( $post_id, $meta_values );
}
add_action( 'save_post', 'acf_save_block_meta_values', 10, 2 );
/**
* Iterates over blocks in post content and retrieves values
* that need to be saved to post meta.
*
* @since 6.3
*
* @param string $content The content saved for the post.
* @return array An array containing the field values that need to be saved.
*/
function acf_get_block_meta_values_to_save( $content = '' ) {
$meta_values = array();
// Bail early if not in a format we expect or if it has no blocks.
if ( ! is_string( $content ) || empty( $content ) || ! has_blocks( $content ) ) {
return $meta_values;
}
$blocks = parse_blocks( $content );
// Bail if no blocks to save.
if ( ! is_array( $blocks ) || empty( $blocks ) ) {
return $meta_values;
}
foreach ( $blocks as $block ) {
// Verify this is an ACF block that should save to meta.
if ( ! acf_block_uses_post_meta( $block['attrs'] ) ) {
continue;
}
// We need a block ID to retrieve the values from cache.
$block_id = ! empty( $block['attrs']['id'] ) ? $block['attrs']['id'] : false;
if ( ! $block_id ) {
continue;
}
// Verify that we have values for this block.
$store = acf_get_store( 'block-meta-values' );
if ( ! $store->has( $block_id ) ) {
continue;
}
// Get the values and remove from cache.
$block_values = $store->get( $block_id );
$store->remove( $block_id );
$meta_values = array_merge( $meta_values, $block_values );
}
return $meta_values;
}

View File

@@ -129,12 +129,27 @@ if ( ! class_exists( 'ACF_Updates' ) ) {
acf_log( $url, $body );
}
$license_key = acf_pro_get_license_key();
if ( ! $license_key ) {
$license_key = '';
}
$site_url = acf_pro_get_home_url();
if ( ! $site_url ) {
$site_url = '';
}
// Make request.
$raw_response = wp_remote_post(
$url,
array(
'timeout' => 10,
'timeout' => 28,
'body' => $body,
'headers' => array(
'X-ACF-Version' => ACF_VERSION,
'X-ACF-License' => $license_key,
'X-ACF-URL' => $site_url,
),
)
);
@@ -186,7 +201,7 @@ if ( ! class_exists( 'ACF_Updates' ) ) {
}
// allow json to include expiration but force minimum and max for safety.
$expiration = $this->get_expiration( $response, DAY_IN_SECONDS, MONTH_IN_SECONDS );
$expiration = $this->get_expiration( $response, DAY_IN_SECONDS );
// update transient.
set_transient( $transient_name, $response, $expiration );
@@ -314,7 +329,7 @@ if ( ! class_exists( 'ACF_Updates' ) ) {
}
// Allow json to include expiration but force minimum and max for safety.
$expiration = $this->get_expiration( $response, DAY_IN_SECONDS, MONTH_IN_SECONDS );
$expiration = $this->get_expiration( $response );
// Update transient and return.
set_transient( $transient_name, $response, $expiration );
@@ -327,11 +342,11 @@ if ( ! class_exists( 'ACF_Updates' ) ) {
* @since 5.6.9
*
* @param mixed $response The response from the server. Default false.
* @param integer $min The minimum expiration limit. Default 0.
* @param integer $max The maximum expiration limit. Default 0.
* @param integer $min The minimum expiration limit. Default 3 hours.
* @param integer $max The maximum expiration limit. Default 7 days.
* @return integer
*/
public function get_expiration( $response = false, $min = 0, $max = 0 ) {
public function get_expiration( $response = false, $min = 10800, $max = 604800 ) {
$expiration = 0;
// Check possible error conditions.

View File

@@ -15,7 +15,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param n/a
* @return n/a
*/
function initialize() {
// vars
@@ -60,7 +59,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param n/a
* @return n/a
*/
function is_enabled() {
return acf_is_filter_enabled( 'clone' );
@@ -78,7 +76,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
*
* @return $field - the field array holding all the field options
*/
function load_field( $field ) {
// bail early if not enabled
@@ -106,7 +103,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $parent (array)
* @return $fields
*/
function acf_get_fields( $fields, $parent ) {
// bail early if empty
@@ -167,7 +163,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $parent (array)
* @return (array)
*/
function get_cloned_fields( $field ) {
// vars
@@ -243,7 +238,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $clone_field (array)
* @return $field
*/
function acf_clone_field( $field, $clone_field ) {
// bail early if this field is being cloned by some other kind of field (future proof)
@@ -323,7 +317,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $clone_field (array)
* @return $field
*/
function acf_clone_clone_field( $field, $clone_field ) {
// modify the $clone_field name
@@ -363,7 +356,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function prepare_field_for_db( $field ) {
// bail early if no sub fields
@@ -414,7 +406,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $field (array) the field array holding all the field options
* @return $value
*/
function load_value( $value, $post_id, $field ) {
// bail early if no sub fields
@@ -524,7 +515,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
*
* @return $value - the modified value
*/
function update_value( $value, $post_id, $field ) {
// bail early if no value
@@ -582,7 +572,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @since 3.6
* @date 23/01/13
*/
function render_field( $field ) {
// bail early if no sub fields
@@ -635,7 +624,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function render_field_block( $field ) {
// vars
@@ -662,7 +650,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function render_field_table( $field ) {
?>
@@ -724,7 +711,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @since 3.6
* @date 23/01/13
*/
function render_field_settings( $field ) {
// temp enable 'local' to allow .json fields to be displayed
@@ -825,7 +811,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $value (mixed)
* @return (array)
*/
function get_clone_setting_choices( $value ) {
// vars
@@ -859,7 +844,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $selector (mixed)
* @return (string)
*/
function get_clone_setting_choice( $selector = '' ) {
// bail early no selector
@@ -899,7 +883,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $field (array)
* @return (string)
*/
function get_clone_setting_field_choice( $field ) {
// bail early if no field
@@ -933,7 +916,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $field_group (array)
* @return (string)
*/
function get_clone_setting_group_choice( $field_group ) {
// bail early if no field group
@@ -956,7 +938,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function ajax_query() {
// validate
@@ -1144,7 +1125,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $field (array)
* @return $field
*/
function acf_prepare_field( $field ) {
// bail early if not cloned
@@ -1172,7 +1152,6 @@ if ( ! class_exists( 'acf_field_clone' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function validate_value( $valid, $value, $field, $input ) {
// bail early if no $value

View File

@@ -95,7 +95,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
* @param $layout (array)
* @return $layout (array)
*/
function get_valid_layout( $layout = array() ) {
// parse
@@ -128,7 +127,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
*
* @return $field - the field array holding all the field options
*/
function load_field( $field ) {
// bail early if no field layouts
@@ -225,7 +223,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
* @since 3.6
* @date 23/01/13
*/
function render_field( $field ) {
// defaults
@@ -326,7 +323,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function render_layout( $field, $layout, $i, $value ) {
// vars
@@ -897,6 +893,10 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
// loop rows
foreach ( $value as $i => $row ) {
// ensure row is an array
if ( ! is_array( $row ) ) {
continue;
}
// get layout
$l = $row['acf_fc_layout'];
@@ -1221,7 +1221,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function delete_field( $field ) {
if ( ! empty( $field['layouts'] ) ) {
@@ -1255,7 +1254,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
*
* @return $field - the modified field
*/
function duplicate_field( $field ) {
// vars
@@ -1496,7 +1494,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
* @param $field (array)
* @return $field
*/
function validate_any_field( $field ) {
// width has changed
@@ -1519,7 +1516,6 @@ if ( ! class_exists( 'acf_field_flexible_content' ) ) :
* @param $field (array)
* @return $field
*/
function translate_field( $field ) {
// translate

View File

@@ -15,7 +15,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
* @param n/a
* @return n/a
*/
function initialize() {
// vars
@@ -64,7 +63,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function input_admin_enqueue_scripts() {
// localize
@@ -87,7 +85,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function ajax_get_attachment() {
// Validate requrest.
@@ -133,7 +130,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function ajax_update_attachment() {
if ( ! isset( $_POST['nonce'] ) ) {
@@ -211,7 +207,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function ajax_get_sort_order() {
// vars
@@ -392,7 +387,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
* @since 3.6
* @date 23/01/13
*/
function render_field( $field ) {
// Enqueue uploader assets.
@@ -522,7 +516,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
*
* @param $field - an array holding all the field's data
*/
function render_field_settings( $field ) {
acf_render_field_setting(
$field,
@@ -734,7 +727,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
*
* @return $value (mixed) the modified value
*/
function format_value( $value, $post_id, $field ) {
// Bail early if no value.
@@ -800,7 +792,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function validate_value( $valid, $value, $field, $input ) {
if ( empty( $value ) || ! is_array( $value ) ) {
@@ -829,7 +820,6 @@ if ( ! class_exists( 'acf_field_gallery' ) ) :
*
* @return $value - the modified value
*/
function update_value( $value, $post_id, $field ) {
// Bail early if no value.

View File

@@ -22,7 +22,6 @@ if ( ! class_exists( 'acf_options_page' ) ) :
* @param n/a
* @return n/a
*/
function __construct() {
/* do nothing */
@@ -122,7 +121,6 @@ if ( ! class_exists( 'acf_options_page' ) ) :
* @param $page (array)
* @return n/a
*/
function add_page( $page ) {
// validate
@@ -152,7 +150,6 @@ if ( ! class_exists( 'acf_options_page' ) ) :
* @param $post_id (int)
* @return $post_id (int)
*/
function add_sub_page( $page ) {
// validate
@@ -184,7 +181,6 @@ if ( ! class_exists( 'acf_options_page' ) ) :
* @param $data (array)
* @return (array)
*/
function update_page( $slug = '', $data = array() ) {
// vars
@@ -216,7 +212,6 @@ if ( ! class_exists( 'acf_options_page' ) ) :
* @param $slug (string)
* @return (mixed)
*/
function get_page( $slug ) {
return isset( $this->pages[ $slug ] ) ? $this->pages[ $slug ] : null;
@@ -233,7 +228,6 @@ if ( ! class_exists( 'acf_options_page' ) ) :
* @param $slug (string)
* @return (mixed)
*/
function get_pages() {
return $this->pages;
@@ -288,7 +282,6 @@ endif; // class_exists check
if ( ! function_exists( 'acf_add_options_page' ) ) :
function acf_add_options_page( $page = '' ) {
return acf_options_page()->add_page( $page );
}

View File

@@ -168,6 +168,7 @@ if ( ! class_exists( 'ACF_UI_Options_Page' ) ) {
'position' => null,
'redirect' => false,
'description' => '',
'menu_icon' => array(),
// Labels tab.
'update_button' => __( 'Update', 'acf' ),
'updated_message' => __( 'Options Updated', 'acf' ),
@@ -335,6 +336,27 @@ if ( ! class_exists( 'ACF_UI_Options_Page' ) ) {
return esc_textarea( $return );
}
/**
* This function returns whether the value was saved prior to the icon picker field or not.
*
* @since 6.3
*
* @param mixed $args The args for the icon field.
* @return boolean
*/
public function value_was_saved_prior_to_icon_picker_field( $args ) {
if (
! empty( $args['menu_icon'] ) &&
is_array( $args['menu_icon'] ) &&
! empty( $args['menu_icon']['type'] ) &&
! empty( $args['menu_icon']['value'] )
) {
return false;
}
return true;
}
/**
* Parses ACF options page settings and returns an array of args
* to be handled by `acf_add_options_page()`.
@@ -397,6 +419,20 @@ if ( ! class_exists( 'ACF_UI_Options_Page' ) ) {
$args[ $setting ] = $value;
}
// Override the icon_url if the value was saved after the icon picker was added to ACF in 6.3.
if ( ! $this->value_was_saved_prior_to_icon_picker_field( $args ) ) {
if ( $args['menu_icon']['type'] === 'url' ) {
$args['icon_url'] = $args['menu_icon']['value'];
}
if ( $args['menu_icon']['type'] === 'media_library' ) {
$image_url = wp_get_attachment_image_url($args['menu_icon']['value']);
$args['icon_url'] = $image_url;
}
if ( $args['menu_icon']['type'] === 'dashicons' ) {
$args['icon_url'] = $args['menu_icon']['value'];
}
}
return apply_filters( 'acf/ui_options_page/registration_args', $args, $post );
}
}

View File

@@ -182,7 +182,7 @@ function acf_pro_check_defined_license() {
* Get translated upstream message
*
* @since 6.2.3
* @param string $text server side message string.
* @param string $text Server side message string.
*
* @return string a translated (or original, if unavailable), message string.
*/
@@ -250,14 +250,16 @@ function acf_pro_get_translated_connect_message( $text ) {
$text .= ' ' . sprintf( __( '%1$s or %2$s.', 'acf' ), $view_license, $check_again );
return $text;
} elseif ( strpos( $text, 'upstream API error' ) !== false ) {
return __( 'An upstream API error occurred when checking your ACF PRO license status. We will retry again shortly.', 'acf' );
} elseif ( strpos( $text, 'scheduled maintenance' ) !== false ) {
return __( 'The ACF activation server is temporarily unavailable for scheduled maintenance. Please try again later.', 'acf' );
return __( 'The ACF activation service is temporarily unavailable for scheduled maintenance. Please try again later.', 'acf' );
} elseif ( strpos( $text, 'Something went wrong' ) !== false ) {
return __( 'The ACF activation server is temporarily unavailable. Please try again later.', 'acf' );
return __( 'The ACF activation service is temporarily unavailable. Please try again later.', 'acf' );
}
/* translators: %s an untranslatable internal upstream error message */
return sprintf( __( 'An unknown error occurred while trying to validate your license: %s.', 'acf' ), $text );
return sprintf( __( 'An unknown error occurred while trying to communicate with the ACF activation service: %s.', 'acf' ), $text );
}
/**
@@ -546,7 +548,7 @@ function acf_pro_activate_license( $license_key, $silent = false, $automatic = f
acf_pro_remove_license_status();
$response = acf_updates()->request( $activation_url, $post );
$expiration = acf_updates()->get_expiration( $response, DAY_IN_SECONDS, MONTH_IN_SECONDS );
$expiration = acf_updates()->get_expiration( $response, DAY_IN_SECONDS );
// Check response is expected JSON array (not string).
if ( is_string( $response ) ) {
@@ -722,40 +724,44 @@ function acf_pro_get_license_status( $force_check = false ) {
// Call the API if necessary, if we have a license.
if ( ( empty( $status ) || $force_check || time() > $next_check ) && $license ) {
$post = array(
'acf_license' => $license,
'wp_url' => acf_pro_get_home_url(),
);
if ( ! get_transient( 'acf_pro_validating_license' ) || $force_check ) {
set_transient( 'acf_pro_validating_license', true, 15 * MINUTE_IN_SECONDS );
$response = acf_updates()->request( 'v2/plugins/validate?p=pro', $post );
$expiration = acf_updates()->get_expiration( $response, DAY_IN_SECONDS, MONTH_IN_SECONDS );
$post = array(
'acf_license' => $license,
'wp_url' => acf_pro_get_home_url(),
);
if ( is_array( $response ) ) {
if ( ! empty( $response['license_status'] ) ) {
$status = $response['license_status'];
}
$response = acf_updates()->request( 'v2/plugins/validate?p=pro', $post );
$expiration = acf_updates()->get_expiration( $response );
// Handle errors from connect.
if ( ! empty( $response['code'] ) && 'activation_not_found' === $response['code'] ) {
// If our activation is no longer found and the user has a defined license, deactivate the license and let the automatic reactivation attempt happen.
if ( defined( 'ACF_PRO_LICENSE' ) ) {
acf_pro_update_license( '' );
acf_pro_check_defined_license();
} else {
$status['error_msg'] = sprintf(
/* translators: %s - URL to ACF updates page */
__( 'Your license key is valid but not activated on this site. Please <a href="%s">deactivate</a> and then reactivate the license.', 'acf' ),
esc_url( admin_url( 'edit.php?post_type=acf-field-group&page=acf-settings-updates#deactivate-license' ) )
);
if ( is_array( $response ) ) {
if ( ! empty( $response['license_status'] ) ) {
$status = $response['license_status'];
}
} elseif ( ! empty( $response['message'] ) ) {
$status['error_msg'] = acf_esc_html( $response['message'] );
}
}
$status['next_check'] = time() + $expiration;
acf_pro_update_license_status( $status );
// Handle errors from connect.
if ( ! empty( $response['code'] ) && 'activation_not_found' === $response['code'] ) {
// If our activation is no longer found and the user has a defined license, deactivate the license and let the automatic reactivation attempt happen.
if ( defined( 'ACF_PRO_LICENSE' ) ) {
acf_pro_update_license( '' );
acf_pro_check_defined_license();
} else {
$status['error_msg'] = sprintf(
/* translators: %s - URL to ACF updates page */
__( 'Your license key is valid but not activated on this site. Please <a href="%s">deactivate</a> and then reactivate the license.', 'acf' ),
esc_url( admin_url( 'edit.php?post_type=acf-field-group&page=acf-settings-updates#deactivate-license' ) )
);
}
} elseif ( ! empty( $response['message'] ) ) {
$status['error_msg'] = acf_esc_html( acf_pro_get_translated_connect_message( $response['message'] ) );
}
}
$status['next_check'] = time() + $expiration;
acf_pro_update_license_status( $status );
}
}
$status = acf_pro_parse_license_status( $status );