Update to v5.12.2

This commit is contained in:
Titouan Mathis 2022-06-22 10:39:06 +02:00
parent f2b5e4f594
commit b62db9a98d
No known key found for this signature in database
GPG Key ID: A292A3DB3103F19D
34 changed files with 11222 additions and 9389 deletions

67
acf.php
View File

@ -3,9 +3,10 @@
Plugin Name: Advanced Custom Fields PRO
Plugin URI: https://www.advancedcustomfields.com
Description: Customize WordPress with powerful, professional and intuitive fields.
Version: 5.11.4
Version: 5.12.2
Author: Delicious Brains
Author URI: https://www.advancedcustomfields.com
Update URI: https://www.advancedcustomfields.com/pro
Text Domain: acf
Domain Path: /lang
*/
@ -19,7 +20,7 @@ if ( ! class_exists( 'ACF' ) ) :
class ACF {
/** @var string The plugin version number. */
var $version = '5.11.4';
var $version = '5.12.2';
/** @var array The plugin settings array. */
var $settings = array();
@ -100,6 +101,7 @@ if ( ! class_exists( 'ACF' ) ) :
'rest_api_enabled' => true,
'rest_api_format' => 'light',
'rest_api_embed_links' => true,
'preload_blocks' => true,
);
// Include utility functions.
@ -193,6 +195,8 @@ if ( ! class_exists( 'ACF' ) ) :
add_action( 'init', array( $this, 'init' ), 5 );
add_action( 'init', array( $this, 'register_post_types' ), 5 );
add_action( 'init', array( $this, 'register_post_status' ), 5 );
add_action( 'activated_plugin', array( $this, 'deactivate_other_instances' ) );
add_action( 'pre_current_active_plugins', array( $this, 'plugin_deactivated_notice' ) );
// Add filters.
add_filter( 'posts_where', array( $this, 'posts_where' ), 10, 2 );
@ -444,6 +448,65 @@ if ( ! class_exists( 'ACF' ) ) :
);
}
/**
* Checks if another version of ACF/ACF PRO is active and deactivates it.
* Hooked on `activated_plugin` so other plugin is deactivated when current plugin is activated.
*
* @param string $plugin The plugin being activated.
*/
public function deactivate_other_instances( $plugin ) {
if ( ! in_array( $plugin, array( 'advanced-custom-fields/acf.php', 'advanced-custom-fields-pro/acf.php' ) ) ) {
return;
}
$plugin_to_deactivate = 'advanced-custom-fields/acf.php';
$deactivated_notice_id = '1';
// If we just activated the free version, deactivate the pro version.
if ( $plugin === $plugin_to_deactivate ) {
$plugin_to_deactivate = 'advanced-custom-fields-pro/acf.php';
$deactivated_notice_id = '2';
}
if ( is_multisite() && is_network_admin() ) {
$active_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
$active_plugins = array_keys( $active_plugins );
} else {
$active_plugins = (array) get_option( 'active_plugins', array() );
}
foreach ( $active_plugins as $plugin_basename ) {
if ( $plugin_to_deactivate === $plugin_basename ) {
set_transient( 'acf_deactivated_notice_id', $deactivated_notice_id, 1 * HOUR_IN_SECONDS );
deactivate_plugins( $plugin_basename );
return;
}
}
}
/**
* Displays a notice when either ACF or ACF PRO is automatically deactivated.
*/
public function plugin_deactivated_notice() {
$deactivated_notice_id = get_transient( 'acf_deactivated_notice_id' );
if ( ! in_array( $deactivated_notice_id, array( '1', '2' ) ) ) {
return;
}
$message = __( "Advanced Custom Fields and Advanced Custom Fields PRO should not be active at the same time. We've automatically deactivated Advanced Custom Fields.", 'acf' );
if ( '2' === $deactivated_notice_id ) {
$message = __( "Advanced Custom Fields and Advanced Custom Fields PRO should not be active at the same time. We've automatically deactivated Advanced Custom Fields PRO.", 'acf' );
}
?>
<div class="updated" style="border-left: 4px solid #ffba00;">
<p><?php echo esc_html( $message ); ?></p>
</div>
<?php
delete_transient( 'acf_deactivated_notice_id' );
}
/**
* posts_where
*

View File

@ -1,6 +0,0 @@
/******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/
/******/
/******/ })()
;

View File

@ -1,6 +0,0 @@
/******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/
/******/
/******/ })()
;

View File

@ -1,6 +0,0 @@
/******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/
/******/
/******/ })()
;

View File

@ -1,6 +0,0 @@
/******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/
/******/
/******/ })()
;

View File

@ -1,6 +0,0 @@
/******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/
/******/
/******/ })()
;

View File

@ -1,6 +0,0 @@
/******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/
/******/
/******/ })()
;

View File

@ -18,6 +18,8 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0,_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
const md5 = __webpack_require__(/*! md5 */ "./node_modules/md5/md5.js");
(($, undefined) => {
// Dependencies.
const {
@ -71,7 +73,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
* @date 31/07/2020
* @since 5.9.0
*
* @param object props The block props (of which, the attributes properties is destructured)
* @param {object} props The block props (of which, the attributes properties is destructured)
* @return bool
*/
@ -89,7 +91,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
* @date 31/07/2020
* @since 5.9.0
*
* @param object props The block props (of which, the attributes and clientId properties are destructured)
* @param {object} props The block props (of which, the attributes and clientId properties are destructured)
* @return bool
*/
@ -99,7 +101,88 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
attributes,
clientId
} = _ref2;
return getBlocks().filter(block => block.attributes.id === attributes.id).filter(block => block.clientId !== clientId).length;
return !!getBlocks().filter(block => block.attributes.id === attributes.id).filter(block => block.clientId !== clientId).length;
}
/**
* Returns true if a block (identified by client ID) is nested in a query loop block.
*
* @date 17/1/22
* @since 5.12
*
* @param {string} clientId A block client ID
* @return boolean
*/
function isBlockInQueryLoop(clientId) {
const parents = wp.data.select('core/block-editor').getBlockParents(clientId);
const parentsData = wp.data.select('core/block-editor').getBlocksByClientId(parents);
return parentsData.filter(block => block.name === 'core/query').length;
}
/**
* Returns true if we're currently inside the WP 5.9+ site editor.
*
* @date 08/02/22
* @since 5.12
*
* @return boolean
*/
function isSiteEditor() {
return typeof pagenow === 'string' && pagenow === 'site-editor';
}
/**
* Returns true if the block editor is currently showing the desktop device type preview.
*
* This function will always return true in the site editor as it uses the
* edit-post store rather than the edit-site store.
*
* @date 15/02/22
* @since 5.12
*
* @return boolean
*/
function isDesktopPreviewDeviceType() {
const editPostStore = select('core/edit-post'); // Return true if the edit post store isn't available (such as in the widget editor)
if (!editPostStore) return true; // Return true if the function doesn't exist
if (!editPostStore.__experimentalGetPreviewDeviceType) return true;
return 'Desktop' === editPostStore.__experimentalGetPreviewDeviceType();
}
/**
* Returns true if the block editor is currently in template edit mode.
*
* @date 16/02/22
* @since 5.12
*
* @return boolean
*/
function isEditingTemplate() {
const editPostStore = select('core/edit-post'); // Return false if the edit post store isn't available (such as in the widget editor)
if (!editPostStore) return false; // Return false if the function doesn't exist
if (!editPostStore.isEditingTemplate) return false;
return editPostStore.isEditingTemplate();
}
/**
* Returns true if we're currently inside an iFramed non-desktop device preview type (WP5.9+)
*
* @date 15/02/22
* @since 5.12
*
* @return boolean
*/
function isiFramedMobileDevicePreview() {
return $('iframe[name=editor-canvas]').length && !isDesktopPreviewDeviceType();
}
/**
* Registers a block type.
@ -171,7 +254,14 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
mode: {
type: 'string'
}
}; // Append edit and save functions.
}; // Apply anchor supports to avoid block editor default writing to ID.
if (blockType.supports.anchor) {
attributes.anchor = {
type: 'string'
};
} // Append edit and save functions.
let ThisBlockEdit = BlockEdit;
let ThisBlockSave = BlockSave; // Apply align_text functionality.
@ -201,14 +291,13 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
attributes,
apiVersion: 2,
edit: props => (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(ThisBlockEdit, props),
save: props => {
return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(ThisBlockSave, useBlockProps.save());
}
save: () => (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(ThisBlockSave, null)
}); // Add to storage.
blockTypes[blockType.name] = blockType; // Register with WP.
const result = wp.blocks.registerBlockType(blockType.name, blockType); // Fix bug in 'core/anchor/attribute' filter overwriting attribute.
// Required for < WP5.9
// See https://github.com/WordPress/gutenberg/issues/15240
if (result.attributes.anchor) {
@ -258,22 +347,21 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
* @date 27/2/19
* @since 5.7.13
*
* @param object args An object of key=>value pairs used to filter results.
* @param {object} args An object of key=>value pairs used to filter results.
* @return array.
*/
function getBlocks(args) {
// Get all blocks (avoid deprecated warning).
let blocks = select('core/block-editor').getBlocks(); // Append innerBlocks.
let blocks = []; // Local function to recurse through all child blocks and add to the blocks array.
let i = 0;
const recurseBlocks = block => {
blocks.push(block);
select('core/block-editor').getBlocks(block.clientId).forEach(recurseBlocks);
}; // Trigger initial recursion for parent level blocks.
while (i < blocks.length) {
blocks = blocks.concat(blocks[i].innerBlocks);
i++;
} // Loop over args and filter.
select('core/block-editor').getBlocks().forEach(recurseBlocks); // Loop over args and filter.
for (const k in args) {
blocks = blocks.filter(_ref4 => {
@ -286,10 +374,23 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
return blocks;
} // Data storage for AJAX requests.
}
/**
* Storage for the AJAX queue.
*
* @const {array}
*/
const ajaxQueue = {};
/**
* Storage for cached AJAX requests for block content.
*
* @since 5.12
* @const {array}
*/
const fetchCache = {};
/**
* Fetches a JSON result from the AJAX API.
*
@ -304,44 +405,54 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
function fetchBlock(args) {
const {
attributes = {},
context = {},
query = {},
delay = 0
} = args; // Use storage or default data.
} = args; // Build a unique queue ID from block data
const {
id
} = attributes;
const data = ajaxQueue[id] || {
const queueId = md5(JSON.stringify(_objectSpread(_objectSpread(_objectSpread({}, attributes), context), query)));
const data = ajaxQueue[queueId] || {
query: {},
timeout: false,
promise: $.Deferred()
promise: $.Deferred(),
started: false
}; // Append query args to storage.
data.query = _objectSpread(_objectSpread({}, data.query), query); // Set fresh timeout.
data.query = _objectSpread(_objectSpread({}, data.query), query);
if (data.started) return data.promise; // Set fresh timeout.
clearTimeout(data.timeout);
data.timeout = setTimeout(() => {
$.ajax({
url: acf.get('ajaxurl'),
dataType: 'json',
type: 'post',
cache: false,
data: acf.prepareForAjax({
action: 'acf/ajax/fetch-block',
block: JSON.stringify(attributes),
query: data.query
})
}).always(() => {
// Clean up queue after AJAX request is complete.
ajaxQueue[id] = null;
}).done(function () {
data.promise.resolve.apply(this, arguments);
}).fail(function () {
data.promise.reject.apply(this, arguments);
});
data.started = true;
if (fetchCache[queueId]) {
ajaxQueue[queueId] = null;
data.promise.resolve.apply(fetchCache[queueId][0], fetchCache[queueId][1]);
} else {
$.ajax({
url: acf.get('ajaxurl'),
dataType: 'json',
type: 'post',
cache: false,
data: acf.prepareForAjax({
action: 'acf/ajax/fetch-block',
block: JSON.stringify(attributes),
context: JSON.stringify(context),
query: data.query
})
}).always(() => {
// Clean up queue after AJAX request is complete.
ajaxQueue[queueId] = null;
}).done(function () {
fetchCache[queueId] = [this, arguments];
data.promise.resolve.apply(this, arguments);
}).fail(function () {
data.promise.reject.apply(this, arguments);
});
}
}, delay); // Update storage.
ajaxQueue[id] = data; // Return promise.
ajaxQueue[queueId] = data; // Return promise.
return data.promise;
}
@ -613,7 +724,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
setup() {
const {
name,
attributes
attributes,
clientId
} = this.props;
const blockType = getBlockType(name); // Restrict current mode.
@ -623,18 +735,22 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
}
}
switch (blockType.mode) {
case 'edit':
restrictMode(['edit', 'preview']);
break;
if (isBlockInQueryLoop(clientId) || isSiteEditor() || isiFramedMobileDevicePreview() || isEditingTemplate()) {
restrictMode(['preview']);
} else {
switch (blockType.mode) {
case 'edit':
restrictMode(['edit', 'preview']);
break;
case 'preview':
restrictMode(['preview', 'edit']);
break;
case 'preview':
restrictMode(['preview', 'edit']);
break;
default:
restrictMode(['auto']);
break;
default:
restrictMode(['auto']);
break;
}
}
}
@ -642,16 +758,23 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
const {
name,
attributes,
setAttributes
setAttributes,
clientId
} = this.props;
const {
const blockType = getBlockType(name);
const forcePreview = isBlockInQueryLoop(clientId) || isSiteEditor() || isiFramedMobileDevicePreview() || isEditingTemplate();
let {
mode
} = attributes;
const blockType = getBlockType(name); // Show toggle only for edit/preview modes.
if (forcePreview) {
mode = 'preview';
} // Show toggle only for edit/preview modes and for blocks not in a query loop/FSE.
let showToggle = blockType.supports.mode;
if (mode === 'auto') {
if (mode === 'auto' || forcePreview) {
showToggle = false;
} // Configure toggle variables.
@ -801,7 +924,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
}
maybePreload(blockId) {
if (this.state.html === undefined) {
if (this.state.html === undefined && !isBlockInQueryLoop(this.props.clientId)) {
const preloadedBlocks = acf.get('preloadedBlocks');
if (preloadedBlocks && preloadedBlocks[blockId]) {
@ -985,18 +1108,19 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
fetch() {
// Extract props.
const {
attributes
attributes,
context
} = this.props; // Try preloaded data first.
const preloaded = this.maybePreload(attributes.id);
if (preloaded) {
return;
} // Request AJAX and update HTML on complete.
// const preloaded = this.maybePreload( attributes.id );
//
// if ( preloaded ) {
// return;
// }
// Request AJAX and update HTML on complete.
fetchBlock({
attributes,
context,
query: {
form: true
}
@ -1066,8 +1190,13 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
attributes,
name
} = _ref10;
this.id = `BlockPreview-${attributes.id}`;
const blockType = getBlockType(name);
const contextPostId = acf.isget(this.props, 'context', 'postId');
this.id = `BlockPreview-${attributes.id}`; // Apply the contextPostId to the ID if set to stop query loop ID duplication.
if (contextPostId) {
this.id = `BlockPreview-${attributes.id}-${contextPostId}`;
}
if (blockType.supports.jsx) {
this.renderMethod = 'jsx';
@ -1079,6 +1208,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
let args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
const {
attributes = this.props.attributes,
context = this.props.context,
delay = 0
} = args; // Remember attributes used to fetch HTML.
@ -1087,14 +1217,11 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
}); // Try preloaded data first.
const preloaded = this.maybePreload(attributes.id);
if (preloaded) {
return;
} // Request AJAX and update HTML on complete.
if (preloaded) return; // Request AJAX and update HTML on complete.
fetchBlock({
attributes,
context,
query: {
preview: true
},
@ -1128,7 +1255,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
const thisAttributes = this.props.attributes; // Update preview if block data has changed.
if (!compareObjects(nextAttributes, thisAttributes)) {
let delay = 0; // Delay fetch when editing className or anchor to simulate conscistent logic to custom fields.
let delay = 0; // Delay fetch when editing className or anchor to simulate consistent logic to custom fields.
if (nextAttributes.className !== thisAttributes.className) {
delay = 300;
@ -1760,6 +1887,356 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
};
})(jQuery);
/***/ }),
/***/ "./node_modules/charenc/charenc.js":
/*!*****************************************!*\
!*** ./node_modules/charenc/charenc.js ***!
\*****************************************/
/***/ (function(module) {
var charenc = {
// UTF-8 encoding
utf8: {
// Convert a string to a byte array
stringToBytes: function(str) {
return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
},
// Convert a byte array to a string
bytesToString: function(bytes) {
return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
}
},
// Binary encoding
bin: {
// Convert a string to a byte array
stringToBytes: function(str) {
for (var bytes = [], i = 0; i < str.length; i++)
bytes.push(str.charCodeAt(i) & 0xFF);
return bytes;
},
// Convert a byte array to a string
bytesToString: function(bytes) {
for (var str = [], i = 0; i < bytes.length; i++)
str.push(String.fromCharCode(bytes[i]));
return str.join('');
}
}
};
module.exports = charenc;
/***/ }),
/***/ "./node_modules/crypt/crypt.js":
/*!*************************************!*\
!*** ./node_modules/crypt/crypt.js ***!
\*************************************/
/***/ (function(module) {
(function() {
var base64map
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
crypt = {
// Bit-wise rotation left
rotl: function(n, b) {
return (n << b) | (n >>> (32 - b));
},
// Bit-wise rotation right
rotr: function(n, b) {
return (n << (32 - b)) | (n >>> b);
},
// Swap big-endian to little-endian and vice versa
endian: function(n) {
// If number given, swap endian
if (n.constructor == Number) {
return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
}
// Else, assume array and swap all items
for (var i = 0; i < n.length; i++)
n[i] = crypt.endian(n[i]);
return n;
},
// Generate an array of any length of random bytes
randomBytes: function(n) {
for (var bytes = []; n > 0; n--)
bytes.push(Math.floor(Math.random() * 256));
return bytes;
},
// Convert a byte array to big-endian 32-bit words
bytesToWords: function(bytes) {
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
words[b >>> 5] |= bytes[i] << (24 - b % 32);
return words;
},
// Convert big-endian 32-bit words to a byte array
wordsToBytes: function(words) {
for (var bytes = [], b = 0; b < words.length * 32; b += 8)
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
return bytes;
},
// Convert a byte array to a hex string
bytesToHex: function(bytes) {
for (var hex = [], i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join('');
},
// Convert a hex string to a byte array
hexToBytes: function(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
},
// Convert a byte array to a base-64 string
bytesToBase64: function(bytes) {
for (var base64 = [], i = 0; i < bytes.length; i += 3) {
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
for (var j = 0; j < 4; j++)
if (i * 8 + j * 6 <= bytes.length * 8)
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
else
base64.push('=');
}
return base64.join('');
},
// Convert a base-64 string to a byte array
base64ToBytes: function(base64) {
// Remove non-base-64 characters
base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
imod4 = ++i % 4) {
if (imod4 == 0) continue;
bytes.push(((base64map.indexOf(base64.charAt(i - 1))
& (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
| (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
}
return bytes;
}
};
module.exports = crypt;
})();
/***/ }),
/***/ "./node_modules/is-buffer/index.js":
/*!*****************************************!*\
!*** ./node_modules/is-buffer/index.js ***!
\*****************************************/
/***/ (function(module) {
/*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
// The _isBuffer check is for Safari 5-7 support, because it's missing
// Object.prototype.constructor. Remove this eventually
module.exports = function (obj) {
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
}
function isBuffer (obj) {
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
}
// For Node v0.10 support. Remove this eventually.
function isSlowBuffer (obj) {
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
}
/***/ }),
/***/ "./node_modules/md5/md5.js":
/*!*********************************!*\
!*** ./node_modules/md5/md5.js ***!
\*********************************/
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
(function(){
var crypt = __webpack_require__(/*! crypt */ "./node_modules/crypt/crypt.js"),
utf8 = (__webpack_require__(/*! charenc */ "./node_modules/charenc/charenc.js").utf8),
isBuffer = __webpack_require__(/*! is-buffer */ "./node_modules/is-buffer/index.js"),
bin = (__webpack_require__(/*! charenc */ "./node_modules/charenc/charenc.js").bin),
// The core
md5 = function (message, options) {
// Convert to byte array
if (message.constructor == String)
if (options && options.encoding === 'binary')
message = bin.stringToBytes(message);
else
message = utf8.stringToBytes(message);
else if (isBuffer(message))
message = Array.prototype.slice.call(message, 0);
else if (!Array.isArray(message) && message.constructor !== Uint8Array)
message = message.toString();
// else, assume byte array already
var m = crypt.bytesToWords(message),
l = message.length * 8,
a = 1732584193,
b = -271733879,
c = -1732584194,
d = 271733878;
// Swap endian
for (var i = 0; i < m.length; i++) {
m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
}
// Padding
m[l >>> 5] |= 0x80 << (l % 32);
m[(((l + 64) >>> 9) << 4) + 14] = l;
// Method shortcuts
var FF = md5._ff,
GG = md5._gg,
HH = md5._hh,
II = md5._ii;
for (var i = 0; i < m.length; i += 16) {
var aa = a,
bb = b,
cc = c,
dd = d;
a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
c = FF(c, d, a, b, m[i+10], 17, -42063);
b = FF(b, c, d, a, m[i+11], 22, -1990404162);
a = FF(a, b, c, d, m[i+12], 7, 1804603682);
d = FF(d, a, b, c, m[i+13], 12, -40341101);
c = FF(c, d, a, b, m[i+14], 17, -1502002290);
b = FF(b, c, d, a, m[i+15], 22, 1236535329);
a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
c = GG(c, d, a, b, m[i+11], 14, 643717713);
b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
d = GG(d, a, b, c, m[i+10], 9, 38016083);
c = GG(c, d, a, b, m[i+15], 14, -660478335);
b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
d = GG(d, a, b, c, m[i+14], 9, -1019803690);
c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
a = GG(a, b, c, d, m[i+13], 5, -1444681467);
d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
b = GG(b, c, d, a, m[i+12], 20, -1926607734);
a = HH(a, b, c, d, m[i+ 5], 4, -378558);
d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
c = HH(c, d, a, b, m[i+11], 16, 1839030562);
b = HH(b, c, d, a, m[i+14], 23, -35309556);
a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
b = HH(b, c, d, a, m[i+10], 23, -1094730640);
a = HH(a, b, c, d, m[i+13], 4, 681279174);
d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
d = HH(d, a, b, c, m[i+12], 11, -421815835);
c = HH(c, d, a, b, m[i+15], 16, 530742520);
b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
a = II(a, b, c, d, m[i+ 0], 6, -198630844);
d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
c = II(c, d, a, b, m[i+14], 15, -1416354905);
b = II(b, c, d, a, m[i+ 5], 21, -57434055);
a = II(a, b, c, d, m[i+12], 6, 1700485571);
d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
c = II(c, d, a, b, m[i+10], 15, -1051523);
b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
d = II(d, a, b, c, m[i+15], 10, -30611744);
c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
b = II(b, c, d, a, m[i+13], 21, 1309151649);
a = II(a, b, c, d, m[i+ 4], 6, -145523070);
d = II(d, a, b, c, m[i+11], 10, -1120210379);
c = II(c, d, a, b, m[i+ 2], 15, 718787259);
b = II(b, c, d, a, m[i+ 9], 21, -343485551);
a = (a + aa) >>> 0;
b = (b + bb) >>> 0;
c = (c + cc) >>> 0;
d = (d + dd) >>> 0;
}
return crypt.endian([a, b, c, d]);
};
// Auxiliary functions
md5._ff = function (a, b, c, d, x, s, t) {
var n = a + (b & c | ~b & d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._gg = function (a, b, c, d, x, s, t) {
var n = a + (b & d | c & ~d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._hh = function (a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._ii = function (a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
// Package private blocksize
md5._blocksize = 16;
md5._digestsize = 16;
module.exports = function (message, options) {
if (message === undefined || message === null)
throw new Error('Illegal argument ' + message);
var digestbytes = crypt.wordsToBytes(md5(message, options));
return options && options.asBytes ? digestbytes :
options && options.asString ? bin.bytesToString(digestbytes) :
crypt.bytesToHex(digestbytes);
};
})();
/***/ }),
/***/ "./node_modules/object-assign/index.js":

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -321,7 +321,7 @@
// Provide a custom renaming callback to avoid renaming parent row attributes.
rename: function (name, value, search, replace) {
// Rename id attributes from "field_1-search" to "field_1-replace".
if (name === 'id') {
if (name === 'id' || name === 'for') {
return value.replace(fieldKey + '-' + search, fieldKey + '-' + replace); // Rename name and for attributes from "[field_1][search]" to "[field_1][replace]".
} else {
return value.replace(fieldKey + '][' + search, fieldKey + '][' + replace);
@ -1330,7 +1330,7 @@
// Provide a custom renaming callback to avoid renaming parent row attributes.
rename: function (name, value, search, replace) {
// Rename id attributes from "field_1-search" to "field_1-replace".
if (name === 'id') {
if (name === 'id' || name === 'for') {
return value.replace(fieldKey + '-' + search, fieldKey + '-' + replace); // Rename name and for attributes from "[field_1][search]" to "[field_1][replace]".
} else {
return value.replace(fieldKey + '][' + search, fieldKey + '][' + replace);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1394,6 +1394,8 @@ function acf_duplicate_fields( $fields = array(), $parent_id = 0 ) {
}
acf_append_data( 'generated_keys', $keys );
$duplicates = array();
// Duplicate fields.
foreach ( $fields as $field ) {
$field_id = $field['ID'] ? $field['ID'] : $field['key'];

View File

@ -60,27 +60,46 @@ function acf_get_value( $post_id, $field ) {
// Get field name.
$field_name = $field['name'];
// If we still don't have a proper field array, the field doesn't exist currently.
// Get field ID & type.
$decoded = acf_decode_post_id( $post_id );
$allow_load = true;
// If we don't have a proper field array, the field doesn't exist currently.
if ( empty( $field['type'] ) && empty( $field['key'] ) ) {
// Get field ID & type.
$decoded = acf_decode_post_id( $post_id );
// Check if we should trigger warning about accessing fields too early via action.
do_action( 'acf/get_invalid_field_value', $field, __FUNCTION__ );
if ( apply_filters( 'acf/prevent_access_to_unknown_fields', false ) || ( 'option' === $decoded['type'] && 'options' !== $decoded['id'] ) ) {
return null;
$allow_load = false;
}
}
// If we're using a non options_ option key, ensure we have a valid reference key.
if ( 'option' === $decoded['type'] && 'options' !== $decoded['id'] ) {
$meta = acf_get_metadata( $post_id, $field_name, true );
if ( ! $meta ) {
$allow_load = false;
} elseif ( $meta !== $field['key'] ) {
if ( ! isset( $field['__key'] ) || $meta !== $field['__key'] ) {
$allow_load = false;
}
}
}
// Load Store.
$store = acf_get_store( 'values' );
// If we're allowing load, check the store or load value from database.
if ( $allow_load ) {
if ( $store->has( "$post_id:$field_name" ) ) {
return $store->get( "$post_id:$field_name" );
}
do_action( 'acf/get_invalid_field_value', $field, __FUNCTION__ );
$value = acf_get_metadata( $post_id, $field_name );
}
// Check store.
$store = acf_get_store( 'values' );
if ( $store->has( "$post_id:$field_name" ) ) {
return $store->get( "$post_id:$field_name" );
}
// Load value from database.
$value = acf_get_metadata( $post_id, $field_name );
// Use field's default_value if no meta was found.
if ( $value === null && isset( $field['default_value'] ) ) {
$value = $field['default_value'];
@ -98,8 +117,10 @@ function acf_get_value( $post_id, $field ) {
*/
$value = apply_filters( 'acf/load_value', $value, $post_id, $field );
// Update store.
$store->set( "$post_id:$field_name", $value );
// Update store if we allowed the value load.
if ( $allow_load ) {
$store->set( "$post_id:$field_name", $value );
}
// Return value.
return $value;

View File

@ -238,7 +238,7 @@ function acf_get_object_type_rest_base( $type_object ) {
* Extract the ID of a given object/array. This supports all expected types handled by our update_fields() and
* load_fields() callbacks.
*
* @param WP_Post|WP_User|WP_Term|array $object
* @param WP_Post|WP_User|WP_Term|WP_Comment|array $object
* @return int|mixed|null
*/
function acf_get_object_id( $object ) {
@ -247,9 +247,10 @@ function acf_get_object_id( $object ) {
case WP_User::class:
case WP_Post::class:
return (int) $object->ID;
case WP_Term::class:
return (int) $object->term_id;
case WP_Comment::class:
return (int) $object->comment_ID;
}
} elseif ( isset( $object['id'] ) ) {
return (int) $object['id'];

View File

@ -3071,39 +3071,29 @@ function acf_get_attachment( $attachment ) {
}
/*
* acf_get_truncated
*
* This function will truncate and return a string
*
* @type function
* @date 8/08/2014
* @since 5.0.0
*
* @param $text (string)
* @param $length (int)
* @return (string)
*/
/**
* This function will truncate and return a string
*
* @date 8/08/2014
* @since 5.0.0
*
* @param string $text The text to truncate.
* @param int $length The number of characters to allow in the string.
*
* @return string
*/
function acf_get_truncated( $text, $length = 64 ) {
// vars
$text = trim( $text );
$the_length = strlen( $text );
$the_length = function_exists( 'mb_strlen' ) ? mb_strlen( $text ) : strlen( $text );
// cut
$return = substr( $text, 0, ( $length - 3 ) );
// ...
if ( $the_length > ( $length - 3 ) ) {
$cut_length = $length - 3;
$return = function_exists( 'mb_substr' ) ? mb_substr( $text, 0, $cut_length ) : substr( $text, 0, $cut_length );
if ( $the_length > $cut_length ) {
$return .= '...';
}
// return
return $return;
}
/*

View File

@ -48,8 +48,15 @@ if ( ! class_exists( 'ACF_Form_Gutenberg' ) ) :
// Call edit_form_after_title manually.
add_action( 'block_editor_meta_box_hidden_fields', array( $this, 'block_editor_meta_box_hidden_fields' ) );
// Cusotmize editor metaboxes.
// Customize editor metaboxes.
add_filter( 'filter_block_editor_meta_boxes', array( $this, 'filter_block_editor_meta_boxes' ) );
// Trigger ACF enqueue scripts as the site editor doesn't trigger this from form-post.php
acf_enqueue_scripts(
array(
'uploader' => true,
)
);
}
/**

View File

@ -8,6 +8,12 @@
*/
function acf_get_field_rest_schema( array $field ) {
$type = acf_get_field_type( $field['type'] );
$schema = array();
if ( ! is_object( $type ) || ! method_exists( $type, 'get_rest_schema' ) ) {
return $schema;
}
$schema = $type->get_rest_schema( $field );
/**

View File

@ -19,17 +19,18 @@ class ACF_Rest_Api {
private $embed_links;
public function __construct() {
add_action( 'rest_api_init', array( $this, 'initialize' ) );
add_filter( 'rest_pre_dispatch', array( $this, 'initialize' ), 10, 3 );
add_action( 'rest_api_init', array( $this, 'register_field' ) );
}
public function initialize() {
public function initialize( $response, $handler, $request ) {
if ( ! acf_get_setting( 'rest_api_enabled' ) ) {
return;
}
// Parse request and set the object for local access.
$this->request = new ACF_Rest_Request();
$this->request->parse_request();
$this->request->parse_request( $request );
// Register the 'acf' REST property.
$this->register_field();
@ -44,7 +45,16 @@ class ACF_Rest_Api {
/**
* Register our custom property as a REST field.
*/
private function register_field() {
public function register_field() {
if ( ! acf_get_setting( 'rest_api_enabled' ) ) {
return;
}
if ( ! $this->request instanceof ACF_Rest_Request ) {
$this->request = new ACF_Rest_Request();
$this->request->parse_request( null );
}
$base = $this->request->object_sub_type;
// If the object sub type ($post_type, $taxonomy, 'user') cannot be determined from the current request,
@ -57,6 +67,15 @@ class ACF_Rest_Api {
$base = $this->request->child_object_type;
}
// If we've already registered this route, no need to do it again.
if ( acf_did( 'acf/register_rest_field' ) ) {
global $wp_rest_additional_fields;
if ( isset( $wp_rest_additional_fields[ $base ], $wp_rest_additional_fields[ $base ]['acf'] ) ) {
return;
}
}
register_rest_field(
$base,
'acf',
@ -326,8 +345,9 @@ class ACF_Rest_Api {
*/
private function make_identifier( $object_id, $object_type ) {
$formats = array(
'user' => 'user_%s',
'term' => 'term_%s',
'user' => 'user_%s',
'term' => 'term_%s',
'comment' => 'comment_%s',
);
return isset( $formats[ $object_type ] )
@ -394,7 +414,7 @@ class ACF_Rest_Api {
$match = true;
}
if ( 'user' === $object_type ) {
if ( in_array( $object_type, array( 'user', 'comment' ) ) ) {
$match = true;
}
}
@ -420,7 +440,7 @@ class ACF_Rest_Api {
$object_type_groups = array();
foreach ( $field_groups as $field_group ) {
if ( ! $field_group['show_in_rest'] ) {
if ( empty( $field_group['show_in_rest'] ) ) {
continue;
}
@ -463,6 +483,11 @@ class ACF_Rest_Api {
case 'term':
$args = array( 'taxonomy' => $object_sub_type );
break;
case 'comment':
$comment = get_comment( $object_id );
$post_type = get_post_type( $comment->comment_post_ID );
$args = array( 'comment' => $post_type );
break;
case 'post':
default:
$args = array( 'post_id' => $object_id );

View File

@ -51,9 +51,9 @@ class ACF_Rest_Request {
/**
* Determine all required information from the current request.
*/
public function parse_request() {
public function parse_request( $request ) {
$this->set_http_method();
$this->set_current_route();
$this->set_current_route( $request );
$this->build_supported_routes();
$this->set_url_params();
$this->set_object_types();
@ -102,8 +102,12 @@ class ACF_Rest_Request {
/**
* Get the current REST route as determined by WordPress.
*/
private function set_current_route() {
$this->current_route = empty( $GLOBALS['wp']->query_vars['rest_route'] ) ? null : $GLOBALS['wp']->query_vars['rest_route'];
private function set_current_route( $request ) {
if ( $request ) {
$this->current_route = $request->get_route();
} else {
$this->current_route = empty( $GLOBALS['wp']->query_vars['rest_route'] ) ? null : $GLOBALS['wp']->query_vars['rest_route'];
}
}
/**
@ -141,13 +145,17 @@ class ACF_Rest_Request {
$this->supported_routes[] = '/wp/v2/(?P<rest_base>users)';
$this->supported_routes[] = '/wp/v2/(?P<rest_base>users)/(?P<id>[\d]+)';
$this->supported_routes[] = '/wp/v2/(?P<rest_base>users)/me';
// Add comment routes.
$this->supported_routes[] = '/wp/v2/(?P<rest_base>comments)';
$this->supported_routes[] = '/wp/v2/(?P<rest_base>comments)/(?P<id>[\d]+)';
}
/**
* Loop through supported routes to find matching pattern. Use matching pattern to determine any URL parameters.
*/
private function set_url_params() {
if ( ! $this->supported_routes ) {
if ( ! $this->supported_routes || ! is_string( $this->current_route ) ) {
return;
}
@ -183,7 +191,8 @@ class ACF_Rest_Request {
// check post types then check taxonomies if a matching post type cannot be found.
if ( $base === 'users' ) {
$this->object_type = $this->object_sub_type = 'user';
} elseif ( $base === 'comments' ) {
$this->object_type = $this->object_sub_type = 'comment';
} elseif ( $post_type = $this->get_post_type_by_rest_base( $base ) ) {
$this->object_type = 'post';
$this->object_sub_type = $post_type->name;

View File

@ -273,12 +273,14 @@ if ( ! class_exists( 'ACF_Updates' ) ) :
'wp_version' => get_bloginfo( 'version' ),
'wp_language' => get_bloginfo( 'language' ),
'wp_timezone' => get_option( 'timezone_string' ),
'php_version' => PHP_VERSION,
)
),
'acf' => wp_json_encode(
array(
'acf_version' => get_option( 'acf_version' ),
'acf_pro' => ( defined( 'ACF_PRO' ) && ACF_PRO ),
'block_count' => acf_pro_get_registered_block_count(),
)
),
);

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,8 @@ function acf_register_block_type( $block ) {
$block['name'],
array(
'attributes' => acf_get_block_type_default_attributes( $block ),
'uses_context' => $block['usesContext'],
'api_version' => 2,
'render_callback' => 'acf_render_block_callback',
)
);
@ -218,6 +220,7 @@ function acf_validate_block_type( $block ) {
'keywords' => array(),
'supports' => array(),
'post_types' => array(),
'usesContext' => array(),
'render_template' => false,
'render_callback' => false,
'enqueue_style' => false,
@ -246,6 +249,15 @@ function acf_validate_block_type( $block ) {
)
);
// Add default 'usesContext' settings.
$block['usesContext'] = wp_parse_args(
$block['usesContext'],
array(
'postId',
'postType',
)
);
// Correct "Experimental" flags.
if ( isset( $block['supports']['__experimental_jsx'] ) ) {
$block['supports']['jsx'] = $block['supports']['__experimental_jsx'];
@ -327,31 +339,38 @@ function acf_render_block_callback( $attributes, $content = '', $wp_block = null
* @param bool $is_preview Whether or not the block is being rendered for editing preview.
* @param int $post_id The current post being edited or viewed.
* @param WP_Block $wp_block The block instance (since WP 5.5).
* @return string The block HTML.
* @param array $context The block context array.
* @return string The block HTML.
*/
function acf_rendered_block( $attributes, $content = '', $is_preview = false, $post_id = 0, $wp_block = null ) {
function acf_rendered_block( $attributes, $content = '', $is_preview = false, $post_id = 0, $wp_block = null, $context = false ) {
$mode = isset( $attributes['mode'] ) ? $attributes['mode'] : 'auto';
// If context is available from the WP_Block class object and we have no context of our own, use that.
if ( empty( $context ) && ! empty( $wp_block->context ) ) {
$context = $wp_block->context;
}
ob_start();
if ( 'edit' === $mode && $is_preview ) {
// Load the block form since we're in edit mode.
$block = acf_prepare_block( $attributes );
acf_setup_meta( $block['data'], $block['id'], true );
$fields = acf_get_block_fields( $block );
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>';
} else {
// if ( 'edit' === $mode && $is_preview ) {
// Load the block form since we're in edit mode.
// $block = acf_prepare_block( $attributes );
// acf_setup_meta( $block['data'], $block['id'], true );
// $fields = acf_get_block_fields( $block );
// 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>';
// } else {
// Capture block render output.
acf_render_block( $attributes, $content, $is_preview, $post_id, $wp_block );
}
acf_render_block( $attributes, $content, $is_preview, $post_id, $wp_block, $context );
// }
$html = ob_get_clean();
if ( in_array( $mode, array( 'preview', 'auto' ) ) && $is_preview ) {
//if ( in_array( $mode, array( 'preview', 'auto' ) ) && $is_preview ) {
if ( $is_preview ) {
$html = '<div class="acf-block-preview">' . $html . '</div>';
}
@ -378,9 +397,10 @@ function acf_rendered_block( $attributes, $content = '', $is_preview = false, $p
* @param bool $is_preview Whether or not the block is being rendered for editing preview.
* @param int $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.
* @return void
*/
function acf_render_block( $attributes, $content = '', $is_preview = false, $post_id = 0, $wp_block = null ) {
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 );
@ -401,7 +421,7 @@ function acf_render_block( $attributes, $content = '', $is_preview = false, $pos
// Call render_callback.
if ( is_callable( $block['render_callback'] ) ) {
call_user_func( $block['render_callback'], $block, $content, $is_preview, $post_id, $wp_block );
call_user_func( $block['render_callback'], $block, $content, $is_preview, $post_id, $wp_block, $context );
// Or include template.
} elseif ( $block['render_template'] ) {
@ -509,12 +529,14 @@ function acf_enqueue_block_assets() {
// During the edit screen loading, WordPress renders all blocks in its own attempt to preload data.
// Retrieve any cached block HTML and include this in the localized data.
$preloaded_blocks = acf_get_store( 'block-cache' )->get_data();
acf_localize_data(
array(
'preloadedBlocks' => $preloaded_blocks,
)
);
if ( acf_get_setting( 'preload_blocks' ) ) {
$preloaded_blocks = acf_get_store( 'block-cache' )->get_data();
acf_localize_data(
array(
'preloadedBlocks' => $preloaded_blocks,
)
);
}
}
/**
@ -563,7 +585,7 @@ function acf_enqueue_block_type_assets( $block_type ) {
function acf_ajax_fetch_block() {
// Validate ajax request.
if ( ! acf_verify_ajax() ) {
wp_send_json_error();
wp_send_json_error();
}
// Get request args.
@ -572,22 +594,35 @@ function acf_ajax_fetch_block() {
'block' => false,
'post_id' => 0,
'query' => array(),
'context' => array(),
)
);
$block = $args['block'];
$post_id = $args['post_id'];
$query = $args['query'];
$block = $args['block'];
$query = $args['query'];
$raw_context = $args['context'];
$post_id = $args['post_id'];
// Bail early if no block.
if ( ! $block ) {
wp_send_json_error();
}
// Unslash and decode $_POST data.
// Unslash and decode $_POST data for block and context.
$block = wp_unslash( $block );
$block = json_decode( $block, true );
$context = false;
if ( ! empty( $raw_context ) ) {
$raw_context = wp_unslash( $raw_context );
$raw_context = json_decode( $raw_context, true );
if ( is_array( $raw_context ) ) {
$context = $raw_context;
// Check if a postId is set in the context, otherwise try and use it the default post_id.
$post_id = isset( $context['postId'] ) ? intval( $context['postId'] ) : intval( $args['post_id'] );
}
}
// Prepare block ensuring all settings and attributes exist.
if ( ! $block = acf_prepare_block( $block ) ) {
wp_send_json_error();
@ -604,6 +639,11 @@ function acf_ajax_fetch_block() {
// Setup postdata allowing form to load meta.
acf_setup_meta( $block['data'], $block['id'], true );
// Setup main postdata for post_id.
global $post;
$post = get_post( $post_id );
setup_postdata( $post );
// Vars.
$response = array();
@ -637,7 +677,7 @@ function acf_ajax_fetch_block() {
$is_preview = true;
// Render and store HTML.
$response['preview'] = acf_rendered_block( $block, $content, $is_preview, $post_id );
$response['preview'] = acf_rendered_block( $block, $content, $is_preview, $post_id, null, $context );
}
// Send response.
@ -702,13 +742,8 @@ function acf_parse_save_blocks_callback( $matches ) {
$attrs['data'] = acf_setup_meta( $attrs['data'], $attrs['id'] );
}
// Prevent wp_targeted_link_rel from corrupting JSON.
remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
remove_filter( 'content_save_pre', 'wp_targeted_link_rel' );
remove_filter( 'content_save_pre', 'balanceTags', 50 );
/**
* Filteres the block attributes before saving.
* Filters the block attributes before saving.
*
* @date 18/3/19
* @since 5.7.14
@ -717,6 +752,36 @@ function acf_parse_save_blocks_callback( $matches ) {
*/
$attrs = apply_filters( 'acf/pre_save_block', $attrs );
// Return new comment
return '<!-- wp:' . $name . ' ' . acf_json_encode( $attrs ) . ' ' . $void . '-->';
// Gutenberg expects a specific encoding format.
$attrs = acf_serialize_block_attributes( $attrs );
return '<!-- wp:' . $name . ' ' . $attrs . ' ' . $void . '-->';
}
/**
* This directly copied from the WordPress core `serialize_block_attributes()` function.
*
* We need this in order to make sure that block attributes are stored in a way that is
* consistent with how Gutenberg sends them over from JS, and so that things like wp_kses()
* work as expected. Copied from core to get around a bug that was fixed in 5.8.1 or on the off chance
* that folks are still using WP 5.3 or below.
*
* TODO: Remove this when we refactor `acf_parse_save_blocks_callback()` to use `serialize_block()`,
* or when we're confident that folks aren't using WP versions prior to 5.8.
*
* @since 5.12
*
* @param array $block_attributes Attributes object.
* @return string Serialized attributes.
*/
function acf_serialize_block_attributes( $block_attributes ) {
$encoded_attributes = wp_json_encode( $block_attributes, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
$encoded_attributes = preg_replace( '/--/', '\\u002d\\u002d', $encoded_attributes );
$encoded_attributes = preg_replace( '/</', '\\u003c', $encoded_attributes );
$encoded_attributes = preg_replace( '/>/', '\\u003e', $encoded_attributes );
$encoded_attributes = preg_replace( '/&/', '\\u0026', $encoded_attributes );
// Regex: /\\"/
$encoded_attributes = preg_replace( '/\\\\"/', '\\u0022', $encoded_attributes );
return $encoded_attributes;
}

View File

@ -393,6 +393,14 @@ function acf_pro_update_license( $key = '' ) {
}
/**
* Get count of registered ACF Blocks
*
* @return int
*/
function acf_pro_get_registered_block_count() {
return acf_get_store( 'block-types' )->count();
}
/**
* Activates the submitted license key
@ -408,7 +416,7 @@ function acf_pro_update_license( $key = '' ) {
function acf_pro_activate_license( $license_key, $silent = false ) {
// Connect to API.
$post = array(
$post = array(
'acf_license' => trim( $license_key ),
'acf_version' => acf_get_setting( 'version' ),
'wp_name' => get_bloginfo( 'name' ),
@ -416,7 +424,10 @@ function acf_pro_activate_license( $license_key, $silent = false ) {
'wp_version' => get_bloginfo( 'version' ),
'wp_language' => get_bloginfo( 'language' ),
'wp_timezone' => get_option( 'timezone_string' ),
'php_version' => PHP_VERSION,
'block_count' => acf_pro_get_registered_block_count(),
);
$response = acf_updates()->request( 'v2/plugins/activate?p=pro', $post );
// Check response is expected JSON array (not string).

View File

@ -2,9 +2,9 @@
Contributors: elliotcondon
Tags: acf, fields, custom fields, meta, repeater
Requires at least: 4.7
Tested up to: 5.8.1
Tested up to: 5.9.3
Requires PHP: 5.6
Stable tag: 5.11.4
Stable tag: 5.12.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
@ -76,6 +76,45 @@ From your WordPress dashboard
== Changelog ==
= 5.12.2 =
*Release Date 6th April 2022*
* Fix - Cloned fields in custom named options pages now behave correctly
* Fix - Default values and the `acf/load_value` filter are now applied if a field value load [fails security validation](https://www.advancedcustomfields.com/resources/acf-field-functions/#non-acf-data)
* Fix - The ACF field is no longer present in REST responses if the ACF REST API setting is disabled
* Fix - Duplicating a flexible content layout or repeater row now also replaces the field ID in `for` attributes
= 5.12.1 =
*Release Date 23rd March 2022*
* New - REST API now supports the comment route for displaying ACF fields.
* Fix - ACF now validates access to option page field values when accessing via field keys the same way as field names. [View More](https://www.advancedcustomfields.com/resources/acf-field-functions/#non-acf-data)
* Fix - REST API now correctly validates fields for POST update requests
* Fix - Fixed an issue where invalid field types caused an error during REST API requests
* Fix - Fixed a PHP warning when duplicating an empty field group
* Fix - Fixed a bug preventing block duplication detection changing an ACF Blocks ID if it was nested deeper than one level inside another block
* Fix - Fixed a bug where the `acf-block-preview` wrapper might not appear around a block if it was saved in edit mode
* i18n - Updated several translations from user contributions (Thanks to Dariusz Zielonka, Mikko Kekki and Alberto!)
= 5.12 =
*Release Date 23rd February 2022*
* [View Release Post](https://www.advancedcustomfields.com/blog/acf-5-12-released/)
* New - ACF blocks now support the new Full Site Editor included in WordPress 5.9
* New - ACF blocks now support the WordPress Query Loop block
* New - Added block caching system to reduce the number of AJAX calls in the block editor
* Enhancement - Block preloading can now be disabled by using "acf_update_setting( 'preload_blocks', false );" in the "acf/init" action hook
* Enhancement - ACF and ACF PRO will now detect if each other are active and deactivate the other plugin on plugin activation
* Fix - Fixed an issue with the media library not working correctly in ACF Blocks in WordPress 5.9.1
* Fix - Fixed an issue where anchors weren't working correctly in WordPress 5.9
* Fix - Fixed an issue where the "unfiltered_html" capability wasn't being used by ACF blocks
* Fix - Fixed an issue where it was impossible to update an ACF block inside the widget block editor
* Fix - Fixed an issue where ACF fields might not appear in REST API calls made via internal WordPress functions
* Fix - Warnings and PHP 8.1 deprecation notices in REST API
* Fix - Better support for double byte characters in "acf_get_truncated()" (props @cabradb)
* i18n - Broken link in the Croatian translation
* i18n - Automated building of acf.pot for translators in each release
= 5.11.4 =
*Release Date - 2nd December 2021*