This commit is contained in:
Elliot Condon 2019-04-05 09:26:51 +02:00 committed by Remco Tolsma
parent 572cf5bf74
commit 58f0d87e05
54 changed files with 9208 additions and 9867 deletions

27
acf.php
View File

@ -3,7 +3,7 @@
Plugin Name: Advanced Custom Fields PRO
Plugin URI: https://www.advancedcustomfields.com/
Description: Customize WordPress with powerful, professional and intuitive fields.
Version: 5.7.10
Version: 5.7.13
Author: Elliot Condon
Author URI: http://www.elliotcondon.com/
Copyright: Elliot Condon
@ -18,7 +18,7 @@ if( ! class_exists('ACF') ) :
class ACF {
/** @var string The plugin version number */
var $version = '5.7.10';
var $version = '5.7.13';
/** @var array The plugin settings array */
var $settings = array();
@ -118,27 +118,31 @@ class ACF {
$this->define( 'ACF', true );
$this->define( 'ACF_VERSION', $version );
$this->define( 'ACF_PATH', $path );
//$this->define( 'ACF_DEV', true );
// api
include_once( ACF_PATH . 'includes/api/api-helpers.php');
acf_include('includes/api/api-input.php');
acf_include('includes/api/api-value.php');
acf_include('includes/api/api-field.php');
acf_include('includes/api/api-field-group.php');
acf_include('includes/api/api-template.php');
acf_include('includes/api/api-term.php');
// Include models.
acf_include('includes/class-acf-data.php');
// Include functions.
acf_include('includes/acf-helper-functions.php');
// Include core functions.
acf_include('includes/acf-data-functions.php');
acf_include('includes/acf-form-functions.php');
acf_include('includes/acf-user-functions.php');
acf_include('includes/acf-helper-functions.php');
acf_include('includes/acf-hook-functions.php');
// Include functions.
acf_include('includes/acf-deprecated-functions.php');
acf_include('includes/acf-field-functions.php');
acf_include('includes/acf-field-group-functions.php');
acf_include('includes/acf-form-functions.php');
acf_include('includes/acf-meta-functions.php');
acf_include('includes/acf-post-functions.php');
acf_include('includes/acf-user-functions.php');
acf_include('includes/acf-value-functions.php');
// fields
acf_include('includes/fields.php');
@ -152,12 +156,11 @@ class ACF {
// core
acf_include('includes/assets.php');
acf_include('includes/cache.php');
acf_include('includes/compatibility.php');
acf_include('includes/deprecated.php');
acf_include('includes/json.php');
acf_include('includes/l10n.php');
acf_include('includes/local.php');
acf_include('includes/local-fields.php');
acf_include('includes/loop.php');
acf_include('includes/media.php');
acf_include('includes/revisions.php');

View File

@ -1991,7 +1991,7 @@
// option
} else {
itemsHtml += '<option value="' + id + '"' + (item.disabled ? ' disabled="disabled"' : '') + '>' + acf.strEscape(text) + '</option>';
itemsHtml += '<option value="' + id + '"' + (item.disabled ? ' disabled="disabled"' : '') + '>' + text + '</option>';
}
});
@ -2097,7 +2097,7 @@
* @return bool
*/
acf.isGutenberg = function(){
return ( window.wp && wp.blocks );
return ( window.wp && wp.data && wp.data.select && wp.data.select( 'core/editor' ) );
};
/**
@ -5934,6 +5934,10 @@
// render
this.renderVal( val );
// action
var latLng = this.newLatLng( val.lat, val.lng );
acf.doAction('google_map_change', latLng, this.map, this);
},
renderVal: function( val ){
@ -5965,9 +5969,6 @@
// show marker
this.map.marker.setVisible( true );
// action
acf.doAction('google_map_change', latLng, this.map, this);
// center
this.center();
@ -11037,16 +11038,20 @@
copyEvents( $submitdiv.children('.hndle'), $postbox.children('.hndle') );
}
// Initalize it (modifies HTML).
postbox = acf.newPostbox( result );
// Trigger action.
acf.doAction('append', $postbox);
// Initalize it.
postbox = acf.newPostbox( result );
acf.doAction('append_postbox', postbox);
}
// show postbox
postbox.showEnable();
// Do action.
acf.doAction('show_postbox', postbox);
// append
visible.push( result.id );
});
@ -11055,6 +11060,9 @@
acf.getPostboxes().map(function( postbox ){
if( visible.indexOf( postbox.get('id') ) === -1 ) {
postbox.hideDisable();
// Do action.
acf.doAction('hide_postbox', postbox);
}
});
@ -11099,6 +11107,9 @@
acf.screen.getPostType = this.getPostType;
acf.screen.getPostFormat = this.getPostFormat;
acf.screen.getPostCoreTerms = this.getPostCoreTerms;
// Add actions.
this.addAction( 'append_postbox', acf.screen.refreshAvailableMetaBoxesPerLocation );
},
onChange: function(){
@ -11121,7 +11132,7 @@
// Filter out attributes that have not changed.
attributes = attributes.filter(this.proxy(function( attr ){
return ( edits[attr] && edits[attr] !== this.get(attr) );
return ( edits[attr] !== undefined && edits[attr] !== this.get(attr) );
}));
// Trigger change if has attributes.
@ -11175,8 +11186,62 @@
// return
return terms;
},
}
});
/**
* acf.screen.refreshAvailableMetaBoxesPerLocation
*
* Refreshes the WP data state based on metaboxes found in the DOM.
*
* @date 6/3/19
* @since 5.7.13
*
* @param void
* @return void
*/
acf.screen.refreshAvailableMetaBoxesPerLocation = function() {
// Extract vars.
var select = wp.data.select( 'core/edit-post' );
var dispatch = wp.data.dispatch( 'core/edit-post' );
// Load current metabox locations and data.
var data = {};
select.getActiveMetaBoxLocations().map(function( location ){
data[ location ] = select.getMetaBoxesPerLocation( location );
});
// Generate flat array of existing ids.
var ids = [];
for( var k in data ) {
ids = ids.concat( data[k].map(function(m){ return m.id; }) );
}
// Append ACF metaboxes.
acf.getPostboxes().map(function( postbox ){
// Ignore if already exists in data.
if( ids.indexOf( postbox.get('id') ) !== -1 ) {
return;
}
// Get metabox location looking at parent form.
var location = postbox.$el.closest('form').attr('class').replace('metabox-location-', '');
// Ensure location exists.
data[ location ] = data[ location ] || [];
// Append.
data[ location ].push({
id: postbox.get('id'),
title: postbox.get('title')
});
});
// Update state.
dispatch.setAvailableMetaBoxesPerLocation(data);
};
})(jQuery);
@ -13074,7 +13139,7 @@
'click button[type="submit"]': 'onClickSubmit',
//'click #editor .editor-post-publish-button': 'onClickSubmitGutenberg',
'click #save-post': 'onClickSave',
'mousedown #post-preview': 'onClickPreview', // use mousedown to hook in before WP click event
'submit form#post': 'onSubmitPost',
'submit form': 'onSubmit',
},
@ -13237,27 +13302,6 @@
this.set('ignore', true);
},
/**
* onClickPreview
*
* Set ignore to true when previewing a post.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object e The event object.
* @param jQuery $el The input element.
* @return void
*/
onClickPreview: function( e, $el ) {
this.set('ignore', true);
// if post has previously been published but prevented by an error, WP core has
// added a custom 'submit.edit-post' event which causes the input buttons to become disabled.
// remove this event to prevent UX issues.
$('form#post').off('submit.edit-post');
},
/**
* onClickSubmitGutenberg
*
@ -13291,6 +13335,31 @@
}
},
/**
* onSubmitPost
*
* Callback when the 'post' form is submit.
*
* @date 5/3/19
* @since 5.7.13
*
* @param object e The event object.
* @param jQuery $el The input element.
* @return void
*/
onSubmitPost: function( e, $el ) {
// Check if is preview.
if( $('input#wp-preview').val() === 'dopreview' ) {
// Ignore validation.
this.set('ignore', true);
// Unlock form to fix conflict with core "submit.edit-post" event causing all submit buttons to be disabled.
acf.unlockForm( $el )
}
},
/**
* onSubmit
*
@ -13305,27 +13374,51 @@
*/
onSubmit: function( e, $el ){
// bail early if is disabled
if( !this.active ) {
return;
// Allow form to submit if...
if(
// Validation has been disabled.
!this.active
// Or this event is to be ignored.
|| this.get('ignore')
// Or this event has already been prevented.
|| e.isDefaultPrevented()
) {
// Return early and call reset function.
return this.allowSubmit();
}
// bail early if is ignore
if( this.get('ignore') ) {
this.set('ignore', false);
return;
}
// validate
// Validate form.
var valid = acf.validateForm({
form: $el,
event: this.get('originalEvent')
});
// if not valid, stop event and allow validation to continue
// If not valid, stop event to prevent form submit.
if( !valid ) {
e.preventDefault();
}
},
/**
* allowSubmit
*
* Resets data during onSubmit when the form is allowed to submit.
*
* @date 5/3/19
* @since 5.7.13
*
* @param void
* @return void
*/
allowSubmit: function(){
// Reset "ignore" state.
this.set('ignore', false);
// Reset "originalEvent" object.
this.set('originalEvent', false)
}
});

File diff suppressed because one or more lines are too long

View File

@ -1,29 +1,11 @@
<?php
/**
* acf_instances
*
* Initialize $acf_instances if it has not been set.
*
* @date 9/1/19
* @since 5.7.10
*
* @param void
* @return ACF_Data
*/
function acf_instances() {
// Globals.
global $acf_instances;
// Initialize only once.
if( !isset($acf_instances) ) {
$acf_instances = new ACF_Data();
}
// Return.
return $acf_instances;
}
// Globals.
global $acf_stores, $acf_instances;
// Initialize plaeholders.
$acf_stores = array();
$acf_instances = array();
/**
* acf_new_instance
@ -37,15 +19,8 @@ function acf_instances() {
* @return object The instance.
*/
function acf_new_instance( $class = '' ) {
// Create instance.
$instance = new $class();
// Register instance.
acf_instances()->set( $class, $instance );
// Return instance.
return $instance;
global $acf_instances;
return $acf_instances[ $class ] = new $class();
}
/**
@ -60,7 +35,11 @@ function acf_new_instance( $class = '' ) {
* @return object The instance.
*/
function acf_get_instance( $class = '' ) {
return acf_instances()->get( $class );
global $acf_instances;
if( !isset($acf_instances[ $class ]) ) {
$acf_instances[ $class ] = new $class();
}
return $acf_instances[ $class ];
}
/**
@ -75,16 +54,17 @@ function acf_get_instance( $class = '' ) {
* @param array $data Array of data to start the store with.
* @return ACF_Data
*/
function acf_register_store( $name = '', $data = false ) {
function acf_register_store( $name = '', $data = false ) {
// Create store.
$store = new ACF_Data( $data );
// Register store.
acf_instances()->set( "ACF_Store_$name", $store );
// Return store.
return $store;
// Create store.
$store = new ACF_Data( $data );
// Register store.
global $acf_stores;
$acf_stores[ $name ] = $store;
// Return store.
return $store;
}
/**
@ -99,6 +79,28 @@ function acf_get_instance( $class = '' ) {
* @return ACF_Data
*/
function acf_get_store( $name = '' ) {
return acf_instances()->get( "ACF_Store_$name" );
global $acf_stores;
return isset( $acf_stores[ $name ] ) ? $acf_stores[ $name ] : false;
}
/**
* acf_switch_stores
*
* Triggered when switching between sites on a multisite installation.
*
* @date 13/2/19
* @since 5.7.11
*
* @param int $site_id New blog ID.
* @param int prev_blog_id Prev blog ID.
* @return void
*/
function acf_switch_stores( $site_id, $prev_site_id ) {
// Loop over stores and call switch_site().
global $acf_stores;
foreach( $acf_stores as $store ) {
$store->switch_site( $site_id, $prev_site_id );
}
}
add_action( 'switch_blog', 'acf_switch_stores', 10, 2 );

View File

@ -0,0 +1,116 @@
<?php
/**
* acf_render_field_wrap_label
*
* Renders the field's label.
*
* @date 19/9/17
* @since 5.6.3
* @deprecated 5.6.5
*
* @param array $field The field array.
* @return void
*/
function acf_render_field_wrap_label( $field ) {
// Warning.
_deprecated_function( __FUNCTION__, '5.7.11', 'acf_render_field_label()' );
// Render.
acf_render_field_label( $field );
}
/**
* acf_render_field_wrap_description
*
* Renders the field's instructions.
*
* @date 19/9/17
* @since 5.6.3
* @deprecated 5.6.5
*
* @param array $field The field array.
* @return void
*/
function acf_render_field_wrap_description( $field ) {
// Warning.
_deprecated_function( __FUNCTION__, '5.7.11', 'acf_render_field_instructions()' );
// Render.
acf_render_field_instructions( $field );
}
/*
* acf_get_fields_by_id
*
* Returns and array of fields for the given $parent_id.
*
* @date 27/02/2014
* @since 5.0.0.
* @deprecated 5.7.11
*
* @param int $parent_id The parent ID.
* @return array
*/
function acf_get_fields_by_id( $parent_id = 0 ) {
// Warning.
_deprecated_function( __FUNCTION__, '5.7.11', 'acf_get_fields()' );
// Return fields.
return acf_get_fields(array( 'ID' => $parent_id, 'key' => "group_$parent_id" ));
}
/**
* acf_update_option
*
* A wrapper for the WP update_option but provides logic for a 'no' autoload
*
* @date 4/01/2014
* @since 5.0.0
* @deprecated 5.7.11
*
* @param string $option The option name.
* @param string $value The option value.
* @param string $autoload An optional autoload value.
* @return bool
*/
function acf_update_option( $option = '', $value = '', $autoload = null ) {
// Warning.
_deprecated_function( __FUNCTION__, '5.7.11', 'update_option()' );
// Update.
if( $autoload === null ) {
$autoload = (bool) acf_get_setting('autoload');
}
return update_option( $option, $value, $autoload );
}
/**
* acf_get_field_reference
*
* Finds the field key for a given field name and post_id.
*
* @date 26/1/18
* @since 5.6.5
* @deprecated 5.6.8
*
* @param string $field_name The name of the field. eg 'sub_heading'
* @param mixed $post_id The post_id of which the value is saved against
* @return string $reference The field key
*/
function acf_get_field_reference( $field_name, $post_id ) {
// Warning.
_deprecated_function( __FUNCTION__, '5.6.8', 'acf_get_reference()' );
// Return reference.
return acf_get_reference( $field_name, $post_id );
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -153,20 +153,9 @@ function acf_save_post( $post_id = 0, $values = null ) {
*/
function _acf_do_save_post( $post_id = 0 ) {
// Check $_POST data.
// Check and update $_POST data.
if( $_POST['acf'] ) {
// Loop over posted values.
foreach( $_POST['acf'] as $key => $value ) {
// Get field.
$field = acf_get_field( $key );
// Update value.
if( $field ) {
acf_update_value( $value, $post_id, $field );
}
}
acf_update_values( $_POST['acf'], $post_id );
}
}

View File

@ -22,3 +22,204 @@ function acf_uniqid( $prefix = 'acf' ) {
// Return id.
return $prefix . '-' . $acf_uniqid++;
}
/**
* acf_merge_attributes
*
* Merges together two arrays but with extra functionality to append class names.
*
* @date 22/1/19
* @since 5.7.10
*
* @param array $array1 An array of attributes.
* @param array $array2 An array of attributes.
* @return array
*/
function acf_merge_attributes( $array1, $array2 ) {
// Merge together attributes.
$array3 = array_merge( $array1, $array2 );
// Append together special attributes.
foreach( array('class', 'style') as $key ) {
if( isset($array1[$key]) && isset($array2[$key]) ) {
$array3[$key] = trim($array1[$key]) . ' ' . trim($array2[$key]);
}
}
// Return
return $array3;
}
/**
* acf_cache_key
*
* Returns a filtered cache key.
*
* @date 25/1/19
* @since 5.7.11
*
* @param string $key The cache key.
* @return string
*/
function acf_cache_key( $key = '' ) {
/**
* Filters the cache key.
*
* @date 25/1/19
* @since 5.7.11
*
* @param string $key The cache key.
* @param string $original_key The original cache key.
*/
return apply_filters( "acf/get_cache_key", $key, $key );
}
/**
* acf_request_args
*
* Returns an array of $_REQUEST values using the provided defaults.
*
* @date 28/2/19
* @since 5.7.13
*
* @param array $args An array of args.
* @return array
*/
function acf_request_args( $args = array() ) {
foreach( $args as $k => $v ) {
$args[ $k ] = isset($_REQUEST[ $k ]) ? $_REQUEST[ $k ] : $args[ $k ];
}
return $args;
}
// Register store.
acf_register_store( 'filters' );
/**
* acf_enable_filter
*
* Enables a filter with the given name.
*
* @date 14/7/16
* @since 5.4.0
*
* @param string name The modifer name.
* @return void
*/
function acf_enable_filter( $name = '' ) {
acf_get_store( 'filters' )->set( $name, true );
}
/**
* acf_disable_filter
*
* Disables a filter with the given name.
*
* @date 14/7/16
* @since 5.4.0
*
* @param string name The modifer name.
* @return void
*/
function acf_disable_filter( $name = '' ) {
acf_get_store( 'filters' )->set( $name, false );
}
/**
* acf_is_filter_enabled
*
* Returns the state of a filter for the given name.
*
* @date 14/7/16
* @since 5.4.0
*
* @param string name The modifer name.
* @return array
*/
function acf_is_filter_enabled( $name = '' ) {
return acf_get_store( 'filters' )->get( $name );
}
/**
* acf_get_filters
*
* Returns an array of filters in their current state.
*
* @date 14/7/16
* @since 5.4.0
*
* @param void
* @return array
*/
function acf_get_filters() {
return acf_get_store( 'filters' )->get();
}
/**
* acf_set_filters
*
* Sets an array of filter states.
*
* @date 14/7/16
* @since 5.4.0
*
* @param array $filters An Array of modifers
* @return array
*/
function acf_set_filters( $filters = array() ) {
acf_get_store( 'filters' )->set( $filters );
}
/**
* acf_disable_filters
*
* Disables all filters and returns the previous state.
*
* @date 14/7/16
* @since 5.4.0
*
* @param void
* @return array
*/
function acf_disable_filters() {
// Get state.
$prev_state = acf_get_filters();
// Set all modifers as false.
acf_set_filters( array_map('__return_false', $prev_state) );
// Return prev state.
return $prev_state;
}
/**
* acf_enable_filters
*
* Enables all or an array of specific filters and returns the previous state.
*
* @date 14/7/16
* @since 5.4.0
*
* @param array $filters An Array of modifers
* @return array
*/
function acf_enable_filters( $filters = array() ) {
// Get state.
$prev_state = acf_get_filters();
// Allow specific filters to be enabled.
if( $filters ) {
acf_set_filters( $filters );
// Set all modifers as true.
} else {
acf_set_filters( array_map('__return_true', $prev_state) );
}
// Return prev state.
return $prev_state;
}

View File

@ -0,0 +1,220 @@
<?php
// Register store.
acf_register_store( 'hook-variations' );
/**
* acf_add_filter_variations
*
* Registers variations for the given filter.
*
* @date 26/1/19
* @since 5.7.11
*
* @param string $filter The filter name.
* @param array $variations An array variation keys.
* @param int $index The param index to find variation values.
* @return void
*/
function acf_add_filter_variations( $filter = '', $variations = array(), $index = 0 ) {
// Store replacement data.
acf_get_store('hook-variations')->set( $filter, array(
'type' => 'filter',
'variations' => $variations,
'index' => $index,
));
// Add generic handler.
// Use a priotiry of 10, and accepted args of 10 (ignored by WP).
add_filter( $filter, '_acf_apply_hook_variations', 10, 10 );
}
/**
* acf_add_action_variations
*
* Registers variations for the given action.
*
* @date 26/1/19
* @since 5.7.11
*
* @param string $action The action name.
* @param array $variations An array variation keys.
* @param int $index The param index to find variation values.
* @return void
*/
function acf_add_action_variations( $action = '', $variations = array(), $index = 0 ) {
// Store replacement data.
acf_get_store('hook-variations')->set( $action, array(
'type' => 'action',
'variations' => $variations,
'index' => $index,
));
// Add generic handler.
// Use a priotiry of 10, and accepted args of 10 (ignored by WP).
add_action( $action, '_acf_apply_hook_variations', 10, 10 );
}
/**
* _acf_apply_hook_variations
*
* Applys hook variations during apply_filters() or do_action().
*
* @date 25/1/19
* @since 5.7.11
*
* @param mixed
* @return mixed
*/
function _acf_apply_hook_variations() {
// Get current filter.
$filter = current_filter();
// Get args provided.
$args = func_get_args();
// Get variation information.
$variations = acf_get_store('hook-variations')->get( $filter );
extract( $variations );
// Find field in args using index.
$field = $args[ $index ];
// Loop over variations and apply filters.
foreach( $variations as $variation ) {
// Get value from field.
// First look for "backup" value ("_name", "_key").
if( isset($field[ "_$variation" ]) ) {
$value = $field[ "_$variation" ];
} elseif( isset($field[ $variation ]) ) {
$value = $field[ $variation ];
} else {
continue;
}
// Apply filters.
if( $type === 'filter' ) {
$args[0] = apply_filters_ref_array( "$filter/$variation=$value", $args );
// Or do action.
} else {
do_action_ref_array( "$filter/$variation=$value", $args );
}
}
// Return first arg.
return $args[0];
}
// Register store.
acf_register_store( 'deprecated-hooks' );
/**
* acf_add_deprecated_filter
*
* Registers a deprecated filter to run during the replacement.
*
* @date 25/1/19
* @since 5.7.11
*
* @param string $deprecated The deprecated hook.
* @param string $version The version this hook was deprecated.
* @param string $replacement The replacement hook.
* @return void
*/
function acf_add_deprecated_filter( $deprecated, $version, $replacement ) {
// Store replacement data.
acf_get_store('deprecated-hooks')->append(array(
'type' => 'filter',
'deprecated' => $deprecated,
'replacement' => $replacement,
'version' => $version
));
// Add generic handler.
// Use a priotiry of 10, and accepted args of 10 (ignored by WP).
add_filter( $replacement, '_acf_apply_deprecated_hook', 10, 10 );
}
/**
* acf_add_deprecated_action
*
* Registers a deprecated action to run during the replacement.
*
* @date 25/1/19
* @since 5.7.11
*
* @param string $deprecated The deprecated hook.
* @param string $version The version this hook was deprecated.
* @param string $replacement The replacement hook.
* @return void
*/
function acf_add_deprecated_action( $deprecated, $version, $replacement ) {
// Store replacement data.
acf_get_store('deprecated-hooks')->append(array(
'type' => 'action',
'deprecated' => $deprecated,
'replacement' => $replacement,
'version' => $version
));
// Add generic handler.
// Use a priotiry of 10, and accepted args of 10 (ignored by WP).
add_filter( $replacement, '_acf_apply_deprecated_hook', 10, 10 );
}
/**
* _acf_apply_deprecated_hook
*
* Applys a deprecated filter during apply_filters() or do_action().
*
* @date 25/1/19
* @since 5.7.11
*
* @param mixed
* @return mixed
*/
function _acf_apply_deprecated_hook() {
// Get current hook.
$hook = current_filter();
// Get args provided.
$args = func_get_args();
// Get deprecated items for this hook.
$items = acf_get_store('deprecated-hooks')->query(array( 'replacement' => $hook ));
// Loop over results.
foreach( $items as $item ) {
// Extract data.
extract( $item );
// Check if anyone is hooked into this deprecated hook.
if( has_filter($deprecated) ) {
// Log warning.
_deprecated_hook( $deprecated, $version, $hook );
// Apply filters.
if( $type === 'filter' ) {
$args[0] = apply_filters_ref_array( $deprecated, $args );
// Or do action.
} else {
do_action_ref_array( $deprecated, $args );
}
}
}
// Return first arg.
return $args[0];
}

View File

@ -0,0 +1,439 @@
<?php
/**
* acf_decode_post_id
*
* Returns an array containing the object type and id for the given post_id string.
*
* @date 25/1/19
* @since 5.7.11
*
* @param (int|string) $post_id The post id.
* @return array()
*/
function acf_decode_post_id( $post_id = 0 ) {
// Default data
$data = array(
'type' => 'post',
'id' => 0
);
// Check if is numeric.
if( is_numeric($post_id) ) {
$data['id'] = (int) $post_id;
// Check if is string.
} elseif( is_string($post_id) ) {
// Determine "{$type}_{$id}" from string.
$bits = explode( '_', $post_id );
$id = array_pop( $bits );
$type = implode( '_', $bits );
// Check if is meta type.
if( function_exists("get_{$type}_meta") && is_numeric($id) ) {
$data['type'] = $type;
$data['id'] = (int) $id;
// Check if is taxonomy name.
} elseif( taxonomy_exists($type) && is_numeric($id) ) {
$data['type'] = 'term';
$data['id'] = (int) $id;
// Otherwise, default to option.
} else {
$data['type'] = 'option';
$data['id'] = $post_id;
}
}
/**
* Filters the $data array after it has been decoded.
*
* @date 12/02/2014
* @since 5.0.0
*
* @param array $data The type and id array.
*/
return apply_filters( "acf/decode_post_id", $data, $post_id );
}
/**
* acf_get_meta
*
* Returns an array of "ACF only" meta for the given post_id.
*
* @date 9/10/18
* @since 5.8.0
*
* @param mixed $post_id The post_id for this data.
* @return array
*/
function acf_get_meta( $post_id = 0 ) {
// Allow filter to short-circuit load_value logic.
$pre = apply_filters( "acf/pre_load_meta", null, $post_id );
if( $pre !== null ) {
return $pre;
}
// Decode $post_id for $type and $id.
extract( acf_decode_post_id($post_id) );
// Use get_$type_meta() function when possible.
if( function_exists("get_{$type}_meta") ) {
$allmeta = call_user_func("get_{$type}_meta", $id, '');
// Default to wp_options.
} else {
$allmeta = acf_get_option_meta( $id );
}
// Loop over meta and check that a reference exists for each value.
$meta = array();
foreach( $allmeta as $key => $value ) {
// If a reference exists for this value, add it to the meta array.
if( isset($allmeta["_$key"]) ) {
$meta[ $key ] = $allmeta[ $key ][0];
$meta[ "_$key" ] = $allmeta[ "_$key" ][0];
}
}
// Unserialized results (get_metadata does not unserialize if $key is empty).
$meta = array_map('maybe_unserialize', $meta);
/**
* Filters the $meta array after it has been loaded.
*
* @date 25/1/19
* @since 5.7.11
*
* @param array $meta The arary of loaded meta.
* @param string $post_id The $post_id for this meta.
*/
return apply_filters( "acf/load_meta", $meta, $post_id );
}
/**
* acf_get_option_meta
*
* Returns an array of meta for the given wp_option name prefix in the same format as get_post_meta().
*
* @date 9/10/18
* @since 5.8.0
*
* @param string $prefix The wp_option name prefix.
* @return array
*/
function acf_get_option_meta( $prefix = '' ) {
// Globals.
global $wpdb;
// Vars.
$meta = array();
$search = "{$prefix}_%";
$_search = "_{$prefix}_%";
// Escape underscores for LIKE.
$search = str_replace('_', '\_', $search);
$_search = str_replace('_', '\_', $_search);
// Query database for results.
$rows = $wpdb->get_results($wpdb->prepare(
"SELECT *
FROM $wpdb->options
WHERE option_name LIKE %s
OR option_name LIKE %s",
$search,
$_search
), ARRAY_A);
// Loop over results and append meta (removing the $prefix from the option name).
$len = strlen("{$prefix}_");
foreach( $rows as $row ) {
$meta[ substr($row['option_name'], $len) ][] = $row['option_value'];
}
// Return results.
return $meta;
}
/**
* acf_get_metadata
*
* Retrieves specific metadata from the database.
*
* @date 16/10/2015
* @since 5.2.3
*
* @param (int|string) $post_id The post id.
* @param string $name The meta name.
* @param bool $hidden If the meta is hidden (starts with an underscore).
* @return mixed
*/
function acf_get_metadata( $post_id = 0, $name = '', $hidden = false ) {
// Allow filter to short-circuit logic.
$pre = apply_filters( "acf/pre_load_metadata", null, $post_id, $name, $hidden );
if( $pre !== null ) {
return $pre;
}
// Decode $post_id for $type and $id.
extract( acf_decode_post_id($post_id) );
// Hidden meta uses an underscore prefix.
$prefix = $hidden ? '_' : '';
// Bail early if no $id (possible during new acf_form).
if( !$id ) {
return null;
}
// Check option.
if( $type === 'option' ) {
return get_option( "{$prefix}{$id}_{$name}", null );
// Check meta.
} else {
$meta = get_metadata( $type, $id, "{$prefix}{$name}", false );
return isset($meta[0]) ? $meta[0] : null;
}
}
/**
* acf_update_metadata
*
* Updates metadata in the database.
*
* @date 16/10/2015
* @since 5.2.3
*
* @param (int|string) $post_id The post id.
* @param string $name The meta name.
* @param mixed $value The meta value.
* @param bool $hidden If the meta is hidden (starts with an underscore).
* @return (int|bool) Meta ID if the key didn't exist, true on successful update, false on failure.
*/
function acf_update_metadata( $post_id = 0, $name = '', $value = '', $hidden = false ) {
// Allow filter to short-circuit logic.
$pre = apply_filters( "acf/pre_update_metadata", null, $post_id, $name, $value, $hidden );
if( $pre !== null ) {
return $pre;
}
// Decode $post_id for $type and $id.
extract( acf_decode_post_id($post_id) );
// Hidden meta uses an underscore prefix.
$prefix = $hidden ? '_' : '';
// Bail early if no $id (possible during new acf_form).
if( !$id ) {
return false;
}
// Update option.
if( $type === 'option' ) {
// Unslash value to match update_metadata() functionality.
$value = wp_unslash( $value );
$autoload = (bool) acf_get_setting('autoload');
return update_option( "{$prefix}{$id}_{$name}", $value, $autoload );
// Update meta.
} else {
return update_metadata( $type, $id, "{$prefix}{$name}", $value );
}
}
/**
* acf_delete_metadata
*
* Deletes metadata from the database.
*
* @date 16/10/2015
* @since 5.2.3
*
* @param (int|string) $post_id The post id.
* @param string $name The meta name.
* @param bool $hidden If the meta is hidden (starts with an underscore).
* @return bool
*/
function acf_delete_metadata( $post_id = 0, $name = '', $hidden = false ) {
// Allow filter to short-circuit logic.
$pre = apply_filters( "acf/pre_delete_metadata", null, $post_id, $name, $hidden );
if( $pre !== null ) {
return $pre;
}
// Decode $post_id for $type and $id.
extract( acf_decode_post_id($post_id) );
// Hidden meta uses an underscore prefix.
$prefix = $hidden ? '_' : '';
// Bail early if no $id (possible during new acf_form).
if( !$id ) {
return false;
}
// Update option.
if( $type === 'option' ) {
$autoload = (bool) acf_get_setting('autoload');
return delete_option( "{$prefix}{$id}_{$name}" );
// Update meta.
} else {
return delete_metadata( $type, $id, "{$prefix}{$name}" );
}
}
/**
* acf_copy_postmeta
*
* Copies meta from one post to another. Useful for saving and restoring revisions.
*
* @date 25/06/2016
* @since 5.3.8
*
* @param (int|string) $from_post_id The post id to copy from.
* @param (int|string) $to_post_id The post id to paste to.
* @return void
*/
function acf_copy_metadata( $from_post_id = 0, $to_post_id = 0 ) {
// Get all postmeta.
$meta = acf_get_meta( $from_post_id );
// Check meta.
if( $meta ) {
// Slash data. WP expects all data to be slashed and will unslash it (fixes '\' character issues).
$meta = wp_slash( $meta );
// Loop over meta.
foreach( $meta as $name => $value ) {
acf_update_metadata( $to_post_id, $name, $value );
}
}
}
/**
* acf_copy_postmeta
*
* Copies meta from one post to another. Useful for saving and restoring revisions.
*
* @date 25/06/2016
* @since 5.3.8
* @deprecated 5.7.11
*
* @param int $from_post_id The post id to copy from.
* @param int $to_post_id The post id to paste to.
* @return void
*/
function acf_copy_postmeta( $from_post_id = 0, $to_post_id = 0 ) {
return acf_copy_metadata( $from_post_id, $to_post_id );
}
/**
* acf_get_meta_field
*
* Returns a field using the provided $id and $post_id parameters.
* Looks for a reference to help loading the correct field via name.
*
* @date 21/1/19
* @since 5.7.10
*
* @param string $key The meta name (field name).
* @param (int|string) $post_id The post_id where this field's value is saved.
* @return (array|false) The field array.
*/
function acf_get_meta_field( $key = 0, $post_id = 0 ) {
// Try reference.
$field_key = acf_get_reference( $key, $post_id );
if( $field_key ) {
$field = acf_get_field( $field_key );
if( $field ) {
$field['name'] = $key;
return $field;
}
}
// Return false.
return false;
}
/**
* acf_get_metaref
*
* Retrieves reference metadata from the database.
*
* @date 16/10/2015
* @since 5.2.3
*
* @param (int|string) $post_id The post id.
* @param string type The reference type (fields|groups).
* @param string $name An optional specific name
* @return mixed
*/
function acf_get_metaref( $post_id = 0, $type = 'fields', $name = '' ) {
// Load existing meta.
$meta = acf_get_metadata( $post_id, "_acf_$type" );
// Handle no meta.
if( !$meta ) {
return $name ? '' : array();
}
// Return specific reference.
if( $name ) {
return isset($meta[ $name ]) ? $meta[ $name ] : '';
// Or return all references.
} else {
return $meta;
}
}
/**
* acf_update_metaref
*
* Updates reference metadata in the database.
*
* @date 16/10/2015
* @since 5.2.3
*
* @param (int|string) $post_id The post id.
* @param string type The reference type (fields|groups).
* @param array $references An array of references.
* @return (int|bool) Meta ID if the key didn't exist, true on successful update, false on failure.
*/
function acf_update_metaref( $post_id = 0, $type = 'fields', $references = array() ) {
// Get current references.
$current = acf_get_metaref( $post_id, $type );
// Merge in new references.
$references = array_merge( $current, $references );
// Simplify groups
if( $type === 'groups' ) {
$references = array_values($references);
}
// Remove duplicate references.
$references = array_unique($references);
// Update metadata.
return acf_update_metadata( $post_id, "_acf_$type", $references );
}

View File

@ -0,0 +1,34 @@
<?php
/**
* acf_get_post_templates
*
* Returns an array of post_type => templates data.
*
* @date 29/8/17
* @since 5.6.2
*
* @param void
* @return array
*/
function acf_get_post_templates() {
// Defaults.
$post_templates = array(
'page' => array()
);
// Loop over post types and append their templates.
if( method_exists('WP_Theme', 'get_page_templates') ) {
$post_types = acf_get_post_types();
foreach( $post_types as $post_type ) {
$templates = wp_get_theme()->get_page_templates( null, $post_type );
if( $templates ) {
$post_templates[ $post_type ] = $templates;
}
}
}
// Return.
return $post_templates;
}

View File

@ -0,0 +1,329 @@
<?php
// Register store.
acf_register_store( 'values' )->prop( 'multisite', true );
/**
* acf_get_reference
*
* Retrieves the field key for a given field name and post_id.
*
* @date 26/1/18
* @since 5.6.5
*
* @param string $field_name The name of the field. eg 'sub_heading'.
* @param mixed $post_id The post_id of which the value is saved against.
* @return string The field key.
*/
function acf_get_reference( $field_name, $post_id ) {
// Allow filter to short-circuit load_value logic.
$reference = apply_filters( "acf/pre_load_reference", null, $field_name, $post_id );
if( $reference !== null ) {
return $reference;
}
// Get hidden meta for this field name.
$reference = acf_get_metadata( $post_id, $field_name, true );
/**
* Filters the reference value.
*
* @date 25/1/19
* @since 5.7.11
*
* @param string $reference The reference value.
* @param string $field_name The field name.
* @param (int|string) $post_id The post ID where meta is stored.
*/
return apply_filters( "acf/load_reference", $reference, $field_name, $post_id );
}
// Register deprecated.
acf_add_deprecated_filter( 'acf/get_field_reference', '5.6.5', 'acf/load_reference' );
/**
* acf_get_value
*
* Retrieves the value for a given field and post_id.
*
* @date 28/09/13
* @since 5.0.0
*
* @param (int|string) $post_id The post id.
* @param array $field The field array.
* @return mixed.
*/
function acf_get_value( $post_id = 0, $field ) {
// Allow filter to short-circuit load_value logic.
$value = apply_filters( "acf/pre_load_value", null, $post_id, $field );
if( $value !== null ) {
return $value;
}
// Get field name.
$field_name = $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'];
}
/**
* Filters the $value after it has been loaded.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The value to preview.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
*/
$value = apply_filters( "acf/load_value", $value, $post_id, $field );
// Update store.
$store->set( "$post_id:$field_name", $value );
// Return value.
return $value;
}
// Register variation.
acf_add_filter_variations( 'acf/load_value', array('type', 'name', 'key'), 2 );
/**
* acf_format_value
*
* Returns a formatted version of the provided value.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The field value.
* @param (int|string) $post_id The post id.
* @param array $field The field array.
* @return mixed.
*/
function acf_format_value( $value, $post_id, $field ) {
// Allow filter to short-circuit load_value logic.
$check = apply_filters( "acf/pre_format_value", null, $post_id, $field );
if( $check !== null ) {
return $check;
}
// Get field name.
$field_name = $field['name'];
// Check store.
$store = acf_get_store( 'values' );
if( $store->has( "$post_id:$field_name:formatted" ) ) {
return $store->get( "$post_id:$field_name:formatted" );
}
/**
* Filters the $value for use in a template function.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The value to preview.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
*/
$value = apply_filters( "acf/format_value", $value, $post_id, $field );
// Update store.
$store->set( "$post_id:$field_name:formatted", $value );
// Return value.
return $value;
}
// Register variation.
acf_add_filter_variations( 'acf/format_value', array('type', 'name', 'key'), 2 );
/**
* acf_update_value
*
* Updates the value for a given field and post_id.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The new value.
* @param (int|string) $post_id The post id.
* @param array $field The field array.
* @return bool.
*/
function acf_update_value( $value = null, $post_id = 0, $field ) {
// Allow filter to short-circuit update_value logic.
$check = apply_filters( "acf/pre_update_value", null, $value, $post_id, $field );
if( $check !== null ) {
return $check;
}
/**
* Filters the $value before it is updated.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The value to update.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
* @param mixed $original The original value before modification.
*/
$value = apply_filters( "acf/update_value", $value, $post_id, $field, $value );
// Allow null to delete value.
if( $value === null ) {
return acf_delete_value( $post_id, $field );
}
// Update meta.
$return = acf_update_metadata( $post_id, $field['name'], $value );
// Update reference.
acf_update_metadata( $post_id, $field['name'], $field['key'], true );
// Delete stored data.
acf_flush_value_cache( $post_id, $field['name'] );
// Return update status.
return $return;
}
// Register variation.
acf_add_filter_variations( 'acf/update_value', array('type', 'name', 'key'), 2 );
/**
* acf_update_values
*
* Updates an array of values.
*
* @date 26/2/19
* @since 5.7.13
*
* @param array values The array of values.
* @param (int|string) $post_id The post id.
* @return void
*/
function acf_update_values( $values = array(), $post_id = 0 ) {
// Loop over values.
foreach( $values as $key => $value ) {
// Get field.
$field = acf_get_field( $key );
// Update value.
if( $field ) {
acf_update_value( $value, $post_id, $field );
}
}
}
/**
* acf_flush_value_cache
*
* Deletes all cached data for this value.
*
* @date 22/1/19
* @since 5.7.10
*
* @param (int|string) $post_id The post id.
* @param string $field_name The field name.
* @return void
*/
function acf_flush_value_cache( $post_id = 0, $field_name = '' ) {
// Delete stored data.
acf_get_store( 'values' )
->remove( "$post_id:$field_name" )
->remove( "$post_id:$field_name:formatted" );
}
/**
* acf_delete_value
*
* Deletes the value for a given field and post_id.
*
* @date 28/09/13
* @since 5.0.0
*
* @param (int|string) $post_id The post id.
* @param array $field The field array.
* @return bool.
*/
function acf_delete_value( $post_id, $field ) {
/**
* Fires before a value is deleted.
*
* @date 28/09/13
* @since 5.0.0
*
* @param string $post_id The post ID for this value.
* @param mixed $name The meta name.
* @param array $field The field array.
*/
do_action( "acf/delete_value", $post_id, $field['name'], $field );
// Delete meta.
$return = acf_delete_metadata( $post_id, $field['name'] );
// Delete reference.
acf_delete_metadata( $post_id, $field['name'], true );
// Delete stored data.
acf_flush_value_cache( $post_id, $field['name'] );
// Return delete status.
return $return;
}
// Register variation.
acf_add_filter_variations( 'acf/delete_value', array('type', 'name', 'key'), 2 );
/**
* acf_preview_value
*
* Return a human friendly 'preview' for a given field value.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The new value.
* @param (int|string) $post_id The post id.
* @param array $field The field array.
* @return bool.
*/
function acf_preview_value( $value, $post_id, $field ) {
/**
* Filters the $value before used in HTML.
*
* @date 24/10/16
* @since 5.5.0
*
* @param mixed $value The value to preview.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
*/
return apply_filters( "acf/preview_value", $value, $post_id, $field );
}
// Register variation.
acf_add_filter_variations( 'acf/preview_value', array('type', 'name', 'key'), 2 );

View File

@ -213,7 +213,7 @@ class acf_admin_field_group {
// set global var
$field_group = acf_get_field_group( $post );
$field_group = acf_get_field_group( $post->ID );
// metaboxes
@ -557,7 +557,7 @@ class acf_admin_field_group {
// get fields
$view = array(
'fields' => acf_get_fields_by_id( $field_group['ID'] ),
'fields' => acf_get_fields( $field_group ),
'parent' => 0
);

View File

@ -270,22 +270,22 @@ class acf_admin_field_groups {
$modified = acf_maybe_get($group, 'modified', 0);
$private = acf_maybe_get($group, 'private', false);
// Ignore if is private.
if( $private ) {
continue;
// ignore DB / PHP / private field groups
if( $local !== 'json' || $private ) {
// do nothing
// Ignore not local "json".
} elseif( $local !== 'json' ) {
continue;
// Append to sync if not yet in database.
} elseif( !$group['ID'] ) {
$this->sync[ $group['key'] ] = $group;
// Append to sync if "json" modified time is newer than database.
} elseif( $modified && $modified > get_post_modified_time('U', true, $group['ID'], true) ) {
$this->sync[ $group['key'] ] = $group;
}
}
@ -334,21 +334,22 @@ class acf_admin_field_groups {
// loop
foreach( $sync_keys as $key ) {
// append fields
if( acf_have_local_fields($key) ) {
$this->sync[ $key ]['fields'] = acf_get_local_fields( $key );
// Bail early if not found.
if( !isset($this->sync[ $key ]) ) {
continue;
}
// Get field group.
$field_group = $this->sync[ $key ];
// import
$field_group = acf_import_field_group( $this->sync[ $key ] );
// Append fields.
$field_group['fields'] = acf_get_fields( $field_group );
// Import field group.
$field_group = acf_import_field_group( $field_group );
// append
// Append imported ID.
$new_ids[] = $field_group['ID'];
}
@ -614,7 +615,6 @@ class acf_admin_field_groups {
// vars
$url_home = 'https://www.advancedcustomfields.com';
$url_support = 'https://support.advancedcustomfields.com';
$icon = '<i aria-hidden="true" class="dashicons dashicons-external"></i>';
?>
@ -637,7 +637,7 @@ class acf_admin_field_groups {
<ul>
<li><a href="<?php echo esc_url( $url_home ); ?>" target="_blank"><?php echo $icon; ?> <?php _e("Website",'acf'); ?></a></li>
<li><a href="<?php echo esc_url( $url_home . '/resources/' ); ?>" target="_blank"><?php echo $icon; ?> <?php _e("Documentation",'acf'); ?></a></li>
<li><a href="<?php echo esc_url( $url_support ); ?>" target="_blank"><?php echo $icon; ?> <?php _e("Support",'acf'); ?></a></li>
<li><a href="<?php echo esc_url( $url_home . '/support/' ); ?>" target="_blank"><?php echo $icon; ?> <?php _e("Support",'acf'); ?></a></li>
<?php if( !acf_get_setting('pro') ): ?>
<li><a href="<?php echo esc_url( $url_home . '/pro/' ); ?>" target="_blank"><?php echo $icon; ?> <?php _e("Pro",'acf'); ?></a></li>
<?php endif; ?>

View File

@ -43,20 +43,6 @@ class ACF_Admin_Tool_Import extends ACF_Admin_Tool {
function html() {
// vars
$choices = array();
$field_groups = acf_get_field_groups();
// loop
if( $field_groups ) {
foreach( $field_groups as $field_group ) {
$choices[ $field_group['key'] ] = esc_html( $field_group['title'] );
}
}
// html
?>
<p><?php _e('Select the Advanced Custom Fields JSON file you would like to import. When you click the import button below, ACF will import the field groups.', 'acf'); ?></p>
<div class="acf-fields">
@ -94,166 +80,73 @@ class ACF_Admin_Tool_Import extends ACF_Admin_Tool {
function submit() {
// validate
// Check file size.
if( empty($_FILES['acf_import_file']['size']) ) {
return acf_add_admin_notice( __("No file selected", 'acf'), 'warning' );
}
// vars
// Get file data.
$file = $_FILES['acf_import_file'];
// validate error
// Check errors.
if( $file['error'] ) {
return acf_add_admin_notice( __("Error uploading file. Please try again", 'acf'), 'warning' );
}
// validate type
// Check file type.
if( pathinfo($file['name'], PATHINFO_EXTENSION) !== 'json' ) {
return acf_add_admin_notice( __("Incorrect file type", 'acf'), 'warning' );
}
// read file
// Read JSON.
$json = file_get_contents( $file['tmp_name'] );
// decode json
$json = json_decode($json, true);
// validate json
if( empty($json) ) {
// Check if empty.
if( !$json || !is_array($json) ) {
return acf_add_admin_notice( __("Import file empty", 'acf'), 'warning' );
}
// if importing an auto-json, wrap field group in array
// Ensure $json is an array of groups.
if( isset($json['key']) ) {
$json = array( $json );
$json = array( $json );
}
// vars
// Remeber imported field group ids.
$ids = array();
$keys = array();
$imported = array();
// populate keys
// Loop over json
foreach( $json as $field_group ) {
// append key
$keys[] = $field_group['key'];
}
// look for existing ids
foreach( $keys as $key ) {
// attempt find ID
$field_group = _acf_get_field_group_by_key( $key );
// bail early if no field group
if( !$field_group ) continue;
// append
$ids[ $key ] = $field_group['ID'];
}
// enable local
acf_enable_local();
// reset local (JSON class has already included .json field groups which may conflict)
acf_reset_local();
// add local field groups
foreach( $json as $field_group ) {
// add field group
acf_add_local_field_group( $field_group );
}
// loop over keys
foreach( $keys as $key ) {
// vars
$field_group = acf_get_local_field_group( $key );
// attempt get id
$id = acf_maybe_get( $ids, $key );
if( $id ) {
$field_group['ID'] = $id;
// Search database for existing field group.
$post = acf_get_field_group_post( $field_group['key'] );
if( $post ) {
$field_group['ID'] = $post->ID;
}
// Import field group.
$field_group = acf_import_field_group( $field_group );
// append fields
if( acf_have_local_fields($key) ) {
$field_group['fields'] = acf_get_local_fields( $key );
}
// import
$field_group = acf_import_field_group( $field_group );
// append message
$imported[] = array(
'ID' => $field_group['ID'],
'title' => $field_group['title'],
'updated' => $id ? 1 : 0
);
// append message
$ids[] = $field_group['ID'];
}
// messages
if( !empty($imported) ) {
// vars
$links = array();
$count = count($imported);
$message = sprintf(_n( 'Imported 1 field group', 'Imported %s field groups', $count, 'acf' ), $count) . '.';
// populate links
foreach( $imported as $import ) {
$links[] = '<a href="' . admin_url("post.php?post={$import['ID']}&action=edit") . '" target="_blank">' . $import['title'] . '</a>';
}
// append links
$message .= ' ' . implode(', ', $links);
// add notice
acf_add_admin_notice( $message, 'success' );
}
// Count number of imported field groups.
$total = count($ids);
// Generate text.
$text = sprintf( _n( 'Imported 1 field group', 'Imported %s field groups', $total, 'acf' ), $total );
// Add links to text.
$links = array();
foreach( $ids as $id ) {
$links[] = '<a href="' . get_edit_post_link( $id ) . '">' . get_the_title( $id ) . '</a>';
}
$text .= ' ' . implode( ', ', $links );
// Add notice
acf_add_admin_notice( $text, 'success' );
}
}
// initialize

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -546,10 +546,7 @@ function acf_parse_args( $args, $defaults = array() ) {
*/
function acf_parse_types( $array ) {
// return
return array_map( 'acf_parse_type', $array );
}
@ -567,26 +564,21 @@ function acf_parse_types( $array ) {
*/
function acf_parse_type( $v ) {
// Check if is string.
if( is_string($v) ) {
// bail early if not string
if( !is_string($v) ) return $v;
// trim
$v = trim($v);
// convert int (string) to int
if( is_numeric($v) && strval((int)$v) === $v ) {
$v = intval( $v );
// Trim ("Word " = "Word").
$v = trim( $v );
// Convert int strings to int ("123" = 123).
if( is_numeric($v) && strpos($v, '.') === false ) {
$v = intval( $v );
}
}
// return
// return.
return $v;
}
@ -3607,14 +3599,6 @@ function acf_str_join( $s1 = '', $s2 = '' ) {
return $s1 . $s2;
}
// Tests.
//acf_test( acf_str_join('http://multisite.local/sub1/', '/sample-page/'), 'http://multisite.local/sub1/sample-page/' );
//acf_test( acf_str_join('http://multisite.local/sub1/', 'sample-page/'), 'http://multisite.local/sub1/sample-page/' );
//acf_test( acf_str_join('http://multisite.local/sub1/', '/sub1'), 'http://multisite.local/sub1/sub1' );
//acf_test( acf_str_join('http://multisite.local/sub1/', '/sub1/sample-page/'), 'http://multisite.local/sub1/sample-page/' );
//acf_test( acf_str_join('http://multisite.local/', '/sub1/sample-page/'), 'http://multisite.local/sub1/sample-page/' );
/*
* acf_current_user_can_admin
*
@ -4474,6 +4458,20 @@ function acf_format_date( $value, $format ) {
}
/**
* acf_clear_log
*
* Deletes the debug.log file.
*
* @date 21/1/19
* @since 5.7.10
*
* @param type $var Description. Default.
* @return type Description.
*/
function acf_clear_log() {
unlink( WP_CONTENT_DIR . '/debug.log' );
}
/*
* acf_log
@ -4530,23 +4528,6 @@ function acf_dev_log() {
}
}
/**
* acf_test
*
* Tests a function against an expected result and logs the pass/fail.
*
* @date 19/11/18
* @since 5.8.0
*
* @param type $var Description. Default.
* @return type Description.
*/
function acf_test( $result, $expected_result ) {
$success = ($result === $expected_result);
acf_log('ACF Test', $success ? '(Pass)' : '(Fail)', $result, $expected_result);
}
/*
* acf_doing
*
@ -4645,183 +4626,6 @@ function acf_is_plugin_active() {
}
/**
* acf_get_filters
*
* Returns the registered filters
*
* @date 2/2/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
function acf_get_filters() {
// get
$filters = acf_raw_setting('filters');
// array
$filters = is_array($filters) ? $filters : array();
// return
return $filters;
}
/**
* acf_update_filters
*
* Updates the registered filters
*
* @date 2/2/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
function acf_update_filters( $filters ) {
return acf_update_setting('filters', $filters);
}
/*
* acf_enable_filter
*
* This function will enable a filter
*
* @type function
* @date 15/07/2016
* @since 5.4.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function acf_enable_filter( $filter = '' ) {
// get
$filters = acf_get_filters();
// append
$filters[ $filter ] = true;
// update
acf_update_filters( $filters );
}
/*
* acf_disable_filter
*
* This function will disable a filter
*
* @type function
* @date 15/07/2016
* @since 5.4.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function acf_disable_filter( $filter = '' ) {
// get
$filters = acf_get_filters();
// append
$filters[ $filter ] = false;
// update
acf_update_filters( $filters );
}
/*
* acf_enable_filters
*
* ACF uses filters to modify field group and field data
* This function will enable them allowing ACF to interact with all data
*
* @type function
* @date 14/07/2016
* @since 5.4.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function acf_enable_filters() {
// get
$filters = acf_get_filters();
// loop
foreach( array_keys($filters) as $k ) {
$filters[ $k ] = true;
}
// update
acf_update_filters( $filters );
}
/*
* acf_disable_filters
*
* ACF uses filters to modify field group and field data
* This function will disable them allowing ACF to interact only with raw DB data
*
* @type function
* @date 14/07/2016
* @since 5.4.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function acf_disable_filters() {
// get
$filters = acf_get_filters();
// loop
foreach( array_keys($filters) as $k ) {
$filters[ $k ] = false;
}
// update
acf_update_filters( $filters );
}
/*
* acf_is_filter_enabled
*
* ACF uses filters to modify field group and field data
* This function will return true if they are enabled
*
* @type function
* @date 14/07/2016
* @since 5.4.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function acf_is_filter_enabled( $filter = '' ) {
// get
$filters = acf_get_filters();
// return
return !empty($filters[ $filter ]);
}
/*
* acf_send_ajax_results
*
@ -5180,42 +4984,6 @@ function acf_decrypt( $data = '' ) {
}
/*
* acf_get_post_templates
*
* This function will return an array of all post templates (including parent theme templates)
*
* @type function
* @date 29/8/17
* @since 5.6.2
*
* @param n/a
* @return (array)
*/
function acf_get_post_templates() {
// vars
$post_types = acf_get_post_types();
$post_templates = array();
// loop
foreach( $post_types as $post_type ) {
$post_templates[ $post_type ] = wp_get_theme()->get_page_templates(null, $post_type);
}
// remove empty templates
$post_templates = array_filter( $post_templates );
// return
return $post_templates;
}
/**
* acf_parse_markdown
*

View File

@ -147,6 +147,106 @@ function get_field_object( $selector, $post_id = false, $format_value = true, $l
}
/*
* acf_get_object_field
*
* This function will return a field for the given selector.
* It will also review the field_reference to ensure the correct field is returned which makes it useful for the template API
*
* @type function
* @date 4/08/2015
* @since 5.2.3
*
* @param $selector (mixed) identifyer of field. Can be an ID, key, name or post object
* @param $post_id (mixed) the post_id of which the value is saved against
* @param $strict (boolean) if true, return a field only when a field key is found.
* @return $field (array)
*/
function acf_maybe_get_field( $selector, $post_id = false, $strict = true ) {
// init
acf_init();
// Check if field key was given.
if( acf_is_field_key($selector) ) {
return acf_get_field( $selector );
}
// Lookup field via reference.
$post_id = acf_get_valid_post_id( $post_id );
$field = acf_get_meta_field( $selector, $post_id );
if( $field ) {
return $field;
}
// Lookup field loosely via name.
if( !$strict ) {
return acf_get_field( $selector );
}
// Return no result.
return false;
}
/*
* acf_maybe_get_sub_field
*
* This function will attempt to find a sub field
*
* @type function
* @date 3/10/2016
* @since 5.4.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function acf_maybe_get_sub_field( $selectors, $post_id = false, $strict = true ) {
// bail ealry if not enough selectors
if( !is_array($selectors) || count($selectors) < 3 ) return false;
// vars
$offset = acf_get_setting('row_index_offset');
$selector = acf_extract_var( $selectors, 0 );
$selectors = array_values( $selectors ); // reset keys
// attempt get field
$field = acf_maybe_get_field( $selector, $post_id, $strict );
// bail early if no field
if( !$field ) return false;
// loop
for( $j = 0; $j < count($selectors); $j+=2 ) {
// vars
$sub_i = $selectors[ $j ];
$sub_s = $selectors[ $j+1 ];
$field_name = $field['name'];
// find sub field
$field = acf_get_sub_field( $sub_s, $field );
// bail early if no sub field
if( !$field ) return false;
// add to name
$field['name'] = $field_name . '_' . ($sub_i-$offset) . '_' . $field['name'];
}
// return
return $field;
}
/*
* get_fields()
@ -206,6 +306,9 @@ function get_fields( $post_id = false, $format_value = true ) {
function get_field_objects( $post_id = false, $format_value = true, $load_value = true ) {
// init
acf_init();
// validate post_id
$post_id = acf_get_valid_post_id( $post_id );

View File

@ -1,715 +0,0 @@
<?php
/*
* acf_get_metadata
*
* This function will get a value from the DB
*
* @type function
* @date 16/10/2015
* @since 5.2.3
*
* @param $post_id (mixed)
* @param $name (string)
* @param $hidden (boolean)
* @return $return (mixed)
*/
function acf_get_metadata( $post_id = 0, $name = '', $hidden = false ) {
// vars
$value = null;
$prefix = $hidden ? '_' : '';
// get post_id info
$info = acf_get_post_id_info($post_id);
// bail early if no $post_id (acf_form - new_post)
if( !$info['id'] ) return $value;
// option
if( $info['type'] === 'option' ) {
$name = $prefix . $post_id . '_' . $name;
$value = get_option( $name, null );
// meta
} else {
$name = $prefix . $name;
$meta = get_metadata( $info['type'], $info['id'], $name, false );
if( isset($meta[0]) ) {
$value = $meta[0];
}
}
// return
return $value;
}
/*
* acf_update_metadata
*
* This function will update a value from the DB
*
* @type function
* @date 16/10/2015
* @since 5.2.3
*
* @param $post_id (mixed)
* @param $name (string)
* @param $value (mixed)
* @param $hidden (boolean)
* @return $return (boolean)
*/
function acf_update_metadata( $post_id = 0, $name = '', $value = '', $hidden = false ) {
// vars
$return = false;
$prefix = $hidden ? '_' : '';
// get post_id info
$info = acf_get_post_id_info($post_id);
// bail early if no $post_id (acf_form - new_post)
if( !$info['id'] ) return $return;
// option
if( $info['type'] === 'option' ) {
$name = $prefix . $post_id . '_' . $name;
$return = acf_update_option( $name, $value );
// meta
} else {
$name = $prefix . $name;
$return = update_metadata( $info['type'], $info['id'], $name, $value );
}
// return
return $return;
}
/*
* acf_delete_metadata
*
* This function will delete a value from the DB
*
* @type function
* @date 16/10/2015
* @since 5.2.3
*
* @param $post_id (mixed)
* @param $name (string)
* @param $hidden (boolean)
* @return $return (boolean)
*/
function acf_delete_metadata( $post_id = 0, $name = '', $hidden = false ) {
// vars
$return = false;
$prefix = $hidden ? '_' : '';
// get post_id info
$info = acf_get_post_id_info($post_id);
// bail early if no $post_id (acf_form - new_post)
if( !$info['id'] ) return $return;
// option
if( $info['type'] === 'option' ) {
$name = $prefix . $post_id . '_' . $name;
$return = delete_option( $name );
// meta
} else {
$name = $prefix . $name;
$return = delete_metadata( $info['type'], $info['id'], $name );
}
// return
return $return;
}
/*
* acf_update_option
*
* This function is a wrapper for the WP update_option but provides logic for a 'no' autoload
*
* @type function
* @date 4/01/2014
* @since 5.0.0
*
* @param $option (string)
* @param $value (mixed)
* @param autoload (mixed)
* @return (boolean)
*/
function acf_update_option( $option = '', $value = '', $autoload = null ) {
// vars
$deprecated = '';
$return = false;
// autoload
if( $autoload === null ){
$autoload = acf_get_setting('autoload') ? 'yes' : 'no';
}
// for some reason, update_option does not use stripslashes_deep.
// update_metadata -> https://core.trac.wordpress.org/browser/tags/3.4.2/wp-includes/meta.php#L82: line 101 (does use stripslashes_deep)
// update_option -> https://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/option.php#L0: line 215 (does not use stripslashes_deep)
$value = stripslashes_deep($value);
// add or update
if( get_option($option) !== false ) {
$return = update_option( $option, $value );
} else {
$return = add_option( $option, $value, $deprecated, $autoload );
}
// return
return $return;
}
/**
* acf_get_reference
*
* Finds the field key for a given field name and post_id.
*
* @date 26/1/18
* @since 5.6.5
*
* @param string $field_name The name of the field. eg 'sub_heading'
* @param mixed $post_id The post_id of which the value is saved against
* @return string $reference The field key
*/
function acf_get_reference( $field_name, $post_id ) {
// allow filter to short-circuit load_value logic
$reference = apply_filters( "acf/pre_load_reference", null, $field_name, $post_id );
if( $reference !== null ) {
return $reference;
}
// get hidden meta for this field name
$reference = acf_get_metadata( $post_id, $field_name, true );
// filter
$reference = apply_filters('acf/load_reference', $reference, $field_name, $post_id);
$reference = apply_filters('acf/get_field_reference', $reference, $field_name, $post_id);
// return
return $reference;
}
// deprecated in 5.6.8
function acf_get_field_reference( $field_name, $post_id ) {
return acf_get_reference( $field_name, $post_id );
}
/*
* acf_get_value
*
* This function will load in a field's value
*
* @type function
* @date 28/09/13
* @since 5.0.0
*
* @param $post_id (int)
* @param $field (array)
* @return (mixed)
*/
function acf_get_value( $post_id = 0, $field ) {
// allow filter to short-circuit load_value logic
$value = apply_filters( "acf/pre_load_value", null, $post_id, $field );
if( $value !== null ) {
return $value;
}
// vars
$cache_key = "get_value/post_id={$post_id}/name={$field['name']}";
// return early if cache is found
if( acf_isset_cache($cache_key) ) {
return acf_get_cache($cache_key);
}
// load value
$value = acf_get_metadata( $post_id, $field['name'] );
// if value was duplicated, it may now be a serialized string!
$value = maybe_unserialize( $value );
// no value? try default_value
if( $value === null && isset($field['default_value']) ) {
$value = $field['default_value'];
}
/**
* Filters the $value after it has been loaded.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The value to preview.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
*/
$value = apply_filters( "acf/load_value/type={$field['type']}", $value, $post_id, $field );
$value = apply_filters( "acf/load_value/name={$field['_name']}", $value, $post_id, $field );
$value = apply_filters( "acf/load_value/key={$field['key']}", $value, $post_id, $field );
$value = apply_filters( "acf/load_value", $value, $post_id, $field );
// update cache
acf_set_cache($cache_key, $value);
// return
return $value;
}
/*
* acf_format_value
*
* This function will format the value for front end use
*
* @type function
* @date 3/07/2014
* @since 5.0.0
*
* @param $value (mixed)
* @param $post_id (mixed)
* @param $field (array)
* @return $value
*/
function acf_format_value( $value, $post_id, $field ) {
// vars
$cache_key = "format_value/post_id={$post_id}/name={$field['name']}";
// return early if cache is found
if( acf_isset_cache($cache_key) ) {
return acf_get_cache($cache_key);
}
/**
* Filters the $value for use in a template function.
*
* @date 28/09/13
* @since 5.0.0
*
* @param mixed $value The value to preview.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
*/
$value = apply_filters( "acf/format_value/type={$field['type']}", $value, $post_id, $field );
$value = apply_filters( "acf/format_value/name={$field['_name']}", $value, $post_id, $field );
$value = apply_filters( "acf/format_value/key={$field['key']}", $value, $post_id, $field );
$value = apply_filters( "acf/format_value", $value, $post_id, $field );
// update cache
acf_set_cache($cache_key, $value);
// return
return $value;
}
/*
* acf_update_value
*
* updates a value into the db
*
* @type action
* @date 23/01/13
*
* @param $value (mixed)
* @param $post_id (mixed)
* @param $field (array)
* @return (boolean)
*/
function acf_update_value( $value = null, $post_id = 0, $field ) {
// strip slashes
if( acf_get_setting('stripslashes') ) {
$value = stripslashes_deep($value);
}
/**
* Allows developers to run a custom update function.
*
* @date 28/09/13
* @since 5.0.0
*
* @param null $check Return a non null value to prevent default.
* @param mixed $value The value to update.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
*/
$check = apply_filters( "acf/pre_update_value", null, $value, $post_id, $field );
if( $check !== null ) {
return $check;
}
/**
* Filters the $value before it is saved.
*
* @date 28/09/13
* @since 5.0.0
* @since 5.7.6 Added $_value parameter.
*
* @param mixed $value The value to update.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
* @param mixed $_value The original value before modification.
*/
$_value = $value;
$value = apply_filters( "acf/update_value/type={$field['type']}", $value, $post_id, $field, $_value );
$value = apply_filters( "acf/update_value/name={$field['_name']}", $value, $post_id, $field, $_value );
$value = apply_filters( "acf/update_value/key={$field['key']}", $value, $post_id, $field, $_value );
$value = apply_filters( "acf/update_value", $value, $post_id, $field, $_value );
// allow null to delete
if( $value === null ) {
return acf_delete_value( $post_id, $field );
}
// update value
$return = acf_update_metadata( $post_id, $field['name'], $value );
// update reference
acf_update_metadata( $post_id, $field['name'], $field['key'], true );
// clear cache
acf_delete_cache("get_value/post_id={$post_id}/name={$field['name']}");
acf_delete_cache("format_value/post_id={$post_id}/name={$field['name']}");
// return
return $return;
}
/*
* acf_delete_value
*
* This function will delete a value from the database
*
* @type function
* @date 28/09/13
* @since 5.0.0
*
* @param $post_id (mixed)
* @param $field (array)
* @return (boolean)
*/
function acf_delete_value( $post_id = 0, $field ) {
/**
* Fires before a value is deleted.
*
* @date 28/09/13
* @since 5.0.0
*
* @param string $post_id The post ID for this value.
* @param mixed $name The meta name.
* @param array $field The field array.
*/
do_action( "acf/delete_value/type={$field['type']}", $post_id, $field['name'], $field );
do_action( "acf/delete_value/name={$field['_name']}", $post_id, $field['name'], $field );
do_action( "acf/delete_value/key={$field['key']}", $post_id, $field['name'], $field );
do_action( "acf/delete_value", $post_id, $field['name'], $field );
// delete value
$return = acf_delete_metadata( $post_id, $field['name'] );
// delete reference
acf_delete_metadata( $post_id, $field['name'], true );
// clear cache
acf_delete_cache("get_value/post_id={$post_id}/name={$field['name']}");
acf_delete_cache("format_value/post_id={$post_id}/name={$field['name']}");
// return
return $return;
}
/*
* acf_copy_postmeta
*
* This function will copy postmeta from one post to another.
* Very useful for saving and restoring revisions
*
* @type function
* @date 25/06/2016
* @since 5.3.8
*
* @param $from_post_id (int)
* @param $to_post_id (int)
* @return n/a
*/
function acf_copy_postmeta( $from_post_id, $to_post_id ) {
// get all postmeta
$meta = get_post_meta( $from_post_id );
// bail early if no meta
if( !$meta ) return;
// loop
foreach( $meta as $name => $value ) {
// attempt to find key value
$key = acf_maybe_get( $meta, '_'.$name );
// bail ealry if no key
if( !$key ) continue;
// update vars
$value = $value[0];
$key = $key[0];
// bail early if $key is a not a field_key
if( !acf_is_field_key($key) ) continue;
// get_post_meta will return array before running maybe_unserialize
$value = maybe_unserialize( $value );
// add in slashes
// - update_post_meta will unslash the value, so we must first slash it to avoid losing backslashes
// - https://codex.wordpress.org/Function_Reference/update_post_meta#Character_Escaping
if( is_string($value) ) {
$value = wp_slash($value);
}
// update value
acf_update_metadata( $to_post_id, $name, $value );
acf_update_metadata( $to_post_id, $name, $key, true );
}
}
/*
* acf_preview_value
*
* This function will return a human freindly 'preview' for a given field value
*
* @type function
* @date 24/10/16
* @since 5.5.0
*
* @param $value (mixed)
* @param $post_id (mixed)
* @param $field (array)
* @return (string)
*/
function acf_preview_value( $value, $post_id, $field ) {
/**
* Filters the $value before used in HTML.
*
* @date 24/10/16
* @since 5.5.0
*
* @param mixed $value The value to preview.
* @param string $post_id The post ID for this value.
* @param array $field The field array.
*/
$value = apply_filters( "acf/preview_value/type={$field['type']}", $value, $post_id, $field );
$value = apply_filters( "acf/preview_value/name={$field['_name']}", $value, $post_id, $field );
$value = apply_filters( "acf/preview_value/key={$field['key']}", $value, $post_id, $field );
$value = apply_filters( "acf/preview_value", $value, $post_id, $field );
// return
return $value;
}
/**
* acf_get_option_meta
*
* Returns an array of meta for the given wp_option name prefix.
*
* @date 9/10/18
* @since 5.8.0
*
* @param string $prefix The wp_option name prefix.
* @return array
*/
function acf_get_option_meta( $prefix = '' ) {
// global
global $wpdb;
// vars
$meta = array();
$search = "{$prefix}_%";
$_search = "_{$prefix}_%";
// escape underscores
$search = str_replace('_', '\_', $search);
$_search = str_replace('_', '\_', $_search);
// query
$rows = $wpdb->get_results($wpdb->prepare(
"SELECT *
FROM $wpdb->options
WHERE option_name LIKE %s
OR option_name LIKE %s",
$search,
$_search
), ARRAY_A);
// loop
$len = strlen("{$prefix}_");
foreach( $rows as $row ) {
$meta[ substr($row['option_name'], $len) ][] = $row['option_value'];
}
// return unserialized
return array_map('maybe_unserialize', $meta);
}
/**
* acf_get_meta
*
* Returns an array of "ACF only" meta for the given post_id.
*
* @date 9/10/18
* @since 5.8.0
*
* @param mixed $post_id The post_id for this data.
* @return array
*/
function acf_get_meta( $post_id = 0 ) {
// allow filter to short-circuit load_value logic
$pre = apply_filters( "acf/pre_load_meta", null, $post_id );
if( $pre !== null ) {
return $pre;
}
// get post_id info
extract( acf_get_post_id_info($post_id) );
// use get_$type_meta() function when possible
if( function_exists("get_{$type}_meta") ) {
$allmeta = call_user_func("get_{$type}_meta", $id, '', true);
// default to wp_options
} else {
$allmeta = acf_get_option_meta( $id );
}
// loop
$meta = array();
foreach( $allmeta as $key => $value ) {
// if is value
if( isset($allmeta["_$key"]) ) {
$meta[ $key ] = $allmeta[ $key ][0];
$meta[ "_$key" ] = $allmeta[ "_$key" ][0];
}
}
// return
return $meta;
}
?>

View File

@ -1,445 +0,0 @@
<?php
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if( ! class_exists('acf_cache') ) :
class acf_cache {
// vars
var $reference = array(),
$active = true;
/*
* __construct
*
* This function will setup the class functionality
*
* @type function
* @date 5/03/2014
* @since 5.4.0
*
* @param n/a
* @return n/a
*/
function __construct() {
// prevent ACF from persistent cache
wp_cache_add_non_persistent_groups('acf');
}
/*
* is_active
*
* This function will return true if caching is enabled
*
* @type function
* @date 26/6/17
* @since 5.6.0
*
* @param n/a
* @return (bool)
*/
function is_active() {
return $this->active;
}
/*
* enable
*
* This function will enable ACF caching
*
* @type function
* @date 26/6/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function enable() {
$this->active = true;
}
/*
* disable
*
* This function will disable ACF caching
*
* @type function
* @date 26/6/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function disable() {
$this->active = false;
}
/*
* get_key
*
* This function will check for references and modify the key
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param $key (string)
* @return $key
*/
function get_key( $key = '' ) {
// check for reference
if( isset($this->reference[ $key ]) ) {
$key = $this->reference[ $key ];
}
// return
return $key;
}
/*
* isset_cache
*
* This function will return true if a cached data exists for the given key
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param $key (string)
* @return (boolean)
*/
function isset_cache( $key = '' ) {
// bail early if not active
if( !$this->is_active() ) return false;
// vars
$key = $this->get_key($key);
$found = false;
// get cache
$cache = wp_cache_get($key, 'acf', false, $found);
// return
return $found;
}
/*
* get_cache
*
* This function will return cached data for a given key
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param $key (string)
* @return (mixed)
*/
function get_cache( $key = '' ) {
// bail early if not active
if( !$this->is_active() ) return false;
// vars
$key = $this->get_key($key);
$found = false;
// get cache
$cache = wp_cache_get($key, 'acf', false, $found);
// return
return $cache;
}
/*
* set_cache
*
* This function will set cached data for a given key
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param $key (string)
* @param $data (mixed)
* @return n/a
*/
function set_cache( $key = '', $data = '' ) {
// bail early if not active
if( !$this->is_active() ) return false;
// set
wp_cache_set($key, $data, 'acf');
// return
return $key;
}
/*
* set_cache_reference
*
* This function will set a reference to cached data for a given key
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param $key (string)
* @param $reference (string)
* @return n/a
*/
function set_cache_reference( $key = '', $reference = '' ) {
// bail early if not active
if( !$this->is_active() ) return false;
// add
$this->reference[ $key ] = $reference;
// resturn
return $key;
}
/*
* delete_cache
*
* This function will delete cached data for a given key
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param $key (string)
* @return n/a
*/
function delete_cache( $key = '' ) {
// bail early if not active
if( !$this->is_active() ) return false;
// delete
return wp_cache_delete( $key, 'acf' );
}
}
// initialize
acf()->cache = new acf_cache();
endif; // class_exists check
/*
* acf_is_cache_active
*
* alias of acf()->cache->is_active()
*
* @type function
* @date 26/6/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function acf_is_cache_active() {
return acf()->cache->is_active();
}
/*
* acf_disable_cache
*
* alias of acf()->cache->disable()
*
* @type function
* @date 26/6/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function acf_disable_cache() {
return acf()->cache->disable();
}
/*
* acf_enable_cache
*
* alias of acf()->cache->enable()
*
* @type function
* @date 26/6/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function acf_enable_cache() {
return acf()->cache->enable();
}
/*
* acf_isset_cache
*
* alias of acf()->cache->isset_cache()
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param n/a
* @return n/a
*/
function acf_isset_cache( $key = '' ) {
return acf()->cache->isset_cache( $key );
}
/*
* acf_get_cache
*
* alias of acf()->cache->get_cache()
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param n/a
* @return n/a
*/
function acf_get_cache( $key = '' ) {
return acf()->cache->get_cache( $key );
}
/*
* acf_set_cache
*
* alias of acf()->cache->set_cache()
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param n/a
* @return n/a
*/
function acf_set_cache( $key = '', $data ) {
return acf()->cache->set_cache( $key, $data );
}
/*
* acf_set_cache_reference
*
* alias of acf()->cache->set_cache_reference()
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param n/a
* @return n/a
*/
function acf_set_cache_reference( $key = '', $reference = '' ) {
return acf()->cache->set_cache_reference( $key, $reference );
}
/*
* acf_delete_cache
*
* alias of acf()->cache->delete_cache()
*
* @type function
* @date 30/06/2016
* @since 5.4.0
*
* @param n/a
* @return n/a
*/
function acf_delete_cache( $key = '' ) {
return acf()->cache->delete_cache( $key );
}
?>

View File

@ -12,6 +12,12 @@ class ACF_Data {
/** @var array Storage for data. */
var $data = array();
/** @var array Storage for data aliases. */
var $aliases = array();
/** @var bool Enables unique data per site. */
var $multisite = false;
/**
* __construct
*
@ -29,8 +35,8 @@ class ACF_Data {
$this->cid = acf_uniqid();
// Set data.
if( $data && is_array($data) ) {
$this->data = array_merge($this->data, $data);
if( $data ) {
$this->set( $data );
}
// Initialize.
@ -49,7 +55,43 @@ class ACF_Data {
* @return void
*/
function initialize() {
// Do nothing.
}
/**
* prop
*
* Sets a property for the given name and returns $this for chaining.
*
* @date 9/1/19
* @since 5.7.10
*
* @param (string|array) $name The data name or an array of data.
* @param mixed $value The data value.
* @return ACF_Data
*/
function prop( $name = '', $value = null ) {
// Update property.
$this->{$name} = $value;
// Return this for chaining.
return $this;
}
/**
* _key
*
* Returns a key for the given name allowing aliasses to work.
*
* @date 18/1/19
* @since 5.7.10
*
* @param type $var Description. Default.
* @return type Description.
*/
function _key( $name = '' ) {
return isset($this->aliases[ $name ]) ? $this->aliases[ $name ] : $name;
}
/**
@ -64,7 +106,23 @@ class ACF_Data {
* @return boolean
*/
function has( $name = '' ) {
return isset($this->data[ $name ]);
$key = $this->_key($name);
return isset($this->data[ $key ]);
}
/**
* is
*
* Similar to has() but does not check aliases.
*
* @date 7/2/19
* @since 5.7.11
*
* @param type $var Description. Default.
* @return type Description.
*/
function is( $key = '' ) {
return isset($this->data[ $key ]);
}
/**
@ -78,8 +136,17 @@ class ACF_Data {
* @param string $name The data name.
* @return mixed
*/
function get( $name = '' ) {
return isset($this->data[ $name ]) ? $this->data[ $name ] : null;
function get( $name = false ) {
// Get all.
if( $name === false ) {
return $this->data;
// Get specific.
} else {
$key = $this->_key($name);
return isset($this->data[ $key ]) ? $this->data[ $key ] : null;
}
}
/**
@ -109,7 +176,7 @@ class ACF_Data {
* @param mixed $value The data value.
* @return ACF_Data
*/
function set( $name = '', $value ) {
function set( $name = '', $value = null ) {
// Set multiple.
if( is_array($name) ) {
@ -124,6 +191,26 @@ class ACF_Data {
return $this;
}
/**
* append
*
* Appends data for the given name and returns $this for chaining.
*
* @date 9/1/19
* @since 5.7.10
*
* @param mixed $value The data value.
* @return ACF_Data
*/
function append( $value = null ) {
// Append.
$this->data[] = $value;
// Return this for chaining.
return $this;
}
/**
* remove
*
@ -143,6 +230,125 @@ class ACF_Data {
// Return this for chaining.
return $this;
}
/**
* reset
*
* Resets the data.
*
* @date 22/1/19
* @since 5.7.10
*
* @param void
* @return void
*/
function reset() {
$this->data = array();
$this->aliases = array();
}
/**
* count
*
* Returns the data count.
*
* @date 23/1/19
* @since 5.7.10
*
* @param void
* @return int
*/
function count() {
return count( $this->data );
}
/**
* query
*
* Returns a filtered array of data based on the set of key => value arguments.
*
* @date 23/1/19
* @since 5.7.10
*
* @param void
* @return int
*/
function query( $args, $operator = 'AND' ) {
return wp_list_filter( $this->data, $args, $operator );
}
/**
* alias
*
* Sets an alias for the given name allowing data to be found via multiple identifiers.
*
* @date 18/1/19
* @since 5.7.10
*
* @param type $var Description. Default.
* @return type Description.
*/
function alias( $name = '' /*, $alias, $alias2, etc */ ) {
// Get all aliases.
$args = func_get_args();
array_shift( $args );
// Loop over aliases and add to data.
foreach( $args as $alias ) {
$this->aliases[ $alias ] = $name;
}
// Return this for chaining.
return $this;
}
/**
* switch_site
*
* Triggered when switching between sites on a multisite installation.
*
* @date 13/2/19
* @since 5.7.11
*
* @param int $site_id New blog ID.
* @param int prev_blog_id Prev blog ID.
* @return void
*/
function switch_site( $site_id, $prev_site_id ) {
// Bail early if not multisite compatible.
if( !$this->multisite ) {
return;
}
// Bail early if no change in blog ID.
if( $site_id === $prev_site_id ) {
return;
}
// Create storage.
if( !isset($this->site_data) ) {
$this->site_data = array();
$this->site_aliases = array();
}
// Save state.
$this->site_data[ $prev_site_id ] = $this->data;
$this->site_aliases[ $prev_site_id ] = $this->aliases;
// Reset state.
$this->data = array();
$this->aliases = array();
// Load state.
if( isset($this->site_data[ $site_id ]) ) {
$this->data = $this->site_data[ $site_id ];
$this->aliases = $this->site_aliases[ $site_id ];
unset( $this->site_data[ $site_id ] );
unset( $this->site_aliases[ $site_id ] );
}
}
}
endif; // class_exists check

View File

@ -34,11 +34,39 @@ class ACF_Compatibility {
add_filter('acf/validate_field/type=user', array($this, 'validate_user_field'), 20, 1);
add_filter('acf/validate_field_group', array($this, 'validate_field_group'), 20, 1);
// Modify field wrapper attributes
add_filter('acf/field_wrapper_attributes', array($this, 'field_wrapper_attributes'), 20, 2);
// location
add_filter('acf/location/validate_rule/type=post_taxonomy', array($this, 'validate_post_taxonomy_location_rule'), 20, 1);
add_filter('acf/location/validate_rule/type=post_category', array($this, 'validate_post_taxonomy_location_rule'), 20, 1);
}
/**
* field_wrapper_attributes
*
* Adds compatibility with deprecated field wrap attributes.
*
* @date 21/1/19
* @since 5.7.10
*
* @param array $wrapper The wrapper attributes array.
* @param array $field The field array.
*/
function field_wrapper_attributes( $wrapper, $field ) {
// Check compatibility setting.
if( acf_get_compatibility('field_wrapper_class') ) {
$wrapper['class'] .= " field_type-{$field['type']}";
if( $field['key'] ) {
$wrapper['class'] .= " field_key-{$field['key']}";
}
}
// Return wrapper.
return $wrapper;
}
/**
* validate_field
*
@ -326,7 +354,7 @@ class ACF_Compatibility {
// detect ACF4 data and generate key
if( !$field_group['key'] ) {
$version = 4;
$field_group['key'] = uniqid('group_');
$field_group['key'] = isset($field_group['id']) ? "group_{$field_group['id']}" : uniqid('group_');
}
// prior to version 5.0.0, settings were saved in an 'options' array

View File

@ -160,6 +160,30 @@ class acf_field_text extends acf_field {
}
/**
* validate_value
*
* Validates a field's value.
*
* @date 29/1/19
* @since 5.7.11
*
* @param (bool|string) Whether the value is vaid or not.
* @param mixed $value The field value.
* @param array $field The field array.
* @param string $input The HTML input name.
* @return (bool|string)
*/
function validate_value( $valid, $value, $field, $input ){
// Check maxlength
if( $field['maxlength'] && mb_strlen(wp_unslash($value)) > $field['maxlength'] ) {
return sprintf( __('Value must not exceed %d characters', 'acf'), $field['maxlength'] );
}
// Return.
return $valid;
}
}

View File

@ -192,6 +192,30 @@ class acf_field_textarea extends acf_field {
return $value;
}
/**
* validate_value
*
* Validates a field's value.
*
* @date 29/1/19
* @since 5.7.11
*
* @param (bool|string) Whether the value is vaid or not.
* @param mixed $value The field value.
* @param array $field The field array.
* @param string $input The HTML input name.
* @return (bool|string)
*/
function validate_value( $valid, $value, $field, $input ){
// Check maxlength
if( $field['maxlength'] && mb_strlen(wp_unslash($value)) > $field['maxlength'] ) {
return sprintf( __('Value must not exceed %d characters', 'acf'), $field['maxlength'] );
}
// Return.
return $valid;
}
}

View File

@ -85,9 +85,20 @@ class ACF_Form_Gutenberg {
<script type="text/javascript">
(function($) {
// Move elements around screen.
// Wait until prepare.
acf.addAction('prepare', function(){
// Append custom sortables before normal sortables (within the normal metabox)
$('#normal-sortables').before( $('#acf_after_title-sortables') );
}, 1);
// Wait until load.
acf.addAction('load', function(){
// Refresh metaboxes to show 'acf_after_title' area.
acf.screen.refreshAvailableMetaBoxesPerLocation();
}, 1);
// Disable unload

View File

@ -246,27 +246,27 @@ class acf_form_taxonomy {
*/
function admin_footer() {
?>
<script type="text/javascript">
(function($) {
// vars
// Define vars.
var view = '<?php echo $this->view; ?>';
var $form = $('#' + view + 'tag');
var $submit = $('#' + view + 'tag input[type="submit"]:last');
// add missing spinners
var $submit = $('input.button-primary');
// Add missing spinner.
if( !$submit.next('.spinner').length ) {
$submit.after('<span class="spinner"></span>');
}
<?php
// add view
// View: Add.
if( $this->view == 'add' ): ?>
// vars
var $form = $('#addtag');
var $fields = $('#acf-term-fields');
var html = '';

View File

@ -15,7 +15,6 @@ class acf_json {
// actions
add_action('acf/update_field_group', array($this, 'update_field_group'), 10, 1);
add_action('acf/duplicate_field_group', array($this, 'update_field_group'), 10, 1);
add_action('acf/untrash_field_group', array($this, 'update_field_group'), 10, 1);
add_action('acf/trash_field_group', array($this, 'delete_field_group'), 10, 1);
add_action('acf/delete_field_group', array($this, 'delete_field_group'), 10, 1);

View File

@ -27,11 +27,11 @@ function determine_locale() {
$determined_locale = get_locale();
if ( is_admin() ) {
if ( function_exists('get_user_locale') && is_admin() ) {
$determined_locale = get_user_locale();
}
if ( isset( $_GET['_locale'] ) && 'user' === $_GET['_locale'] && wp_is_json_request() ) {
if ( function_exists('get_user_locale') && isset( $_GET['_locale'] ) && 'user' === $_GET['_locale'] ) {
$determined_locale = get_user_locale();
}
@ -71,7 +71,7 @@ function acf_get_locale() {
$langs = array(
'az_TR' => 'az', // Azerbaijani (Turkey)
'zh_HK' => 'zh_CN', // Chinese (Hong Kong)
'zh_TW' => 'zh_CN', // Chinese (Taiwan)
//'zh_TW' => 'zh_CN', // Chinese (Taiwan)
'nl_BE' => 'nl_NL', // Dutch (Belgium)
'fr_BE' => 'fr_FR', // French (Belgium)
'nn_NO' => 'nb_NO', // Norwegian (Nynorsk)
@ -126,3 +126,32 @@ function acf_load_textdomain( $domain = 'acf' ) {
// Load from plugin lang folder.
return load_textdomain( $domain, acf_get_path( 'lang/' . $mofile ) );
}
/**
* _acf_apply_language_cache_key
*
* Applies the current language to the cache key.
*
* @date 23/1/19
* @since 5.7.11
*
* @param string $key The cache key.
* @return string
*/
function _acf_apply_language_cache_key( $key ) {
// Get current language.
$current_language = acf_get_setting('current_language');
if( $current_language ) {
$key = "{$key}:{$current_language}";
}
// Return key.
return $key;
}
// Hook into filter.
add_filter( 'acf/get_cache_key', '_acf_apply_language_cache_key' );

574
includes/local-fields.php Normal file
View File

@ -0,0 +1,574 @@
<?php
// Register notices stores.
acf_register_store( 'local-fields' );
acf_register_store( 'local-groups' );
acf_register_store( 'local-empty' );
// Register filter.
acf_enable_filter( 'local' );
/**
* acf_enable_local
*
* Enables the local filter.
*
* @date 22/1/19
* @since 5.7.10
*
* @param void
* @return void
*/
function acf_enable_local() {
acf_enable_filter('local');
}
/**
* acf_disable_local
*
* Disables the local filter.
*
* @date 22/1/19
* @since 5.7.10
*
* @param void
* @return void
*/
function acf_disable_local() {
acf_disable_filter('local');
}
/**
* acf_is_local_enabled
*
* Returns true if local fields are enabled.
*
* @date 23/1/19
* @since 5.7.10
*
* @param void
* @return bool
*/
function acf_is_local_enabled() {
return ( acf_is_filter_enabled('local') && acf_get_setting('local') );
}
/**
* acf_get_local_store
*
* Returns either local store or a dummy store for the given name.
*
* @date 23/1/19
* @since 5.7.10
*
* @param string $name The store name (fields|groups).
* @return ACF_Data
*/
function acf_get_local_store( $name = '' ) {
// Check if enabled.
if( acf_is_local_enabled() ) {
return acf_get_store( "local-$name" );
// Return dummy store if not enabled.
} else {
return acf_get_store( "local-empty" );
}
}
/**
* acf_reset_local
*
* Resets the local data.
*
* @date 22/1/19
* @since 5.7.10
*
* @param void
* @return void
*/
function acf_reset_local() {
acf_get_local_store( 'fields' )->reset();
acf_get_local_store( 'groups' )->reset();
}
/**
* acf_get_local_field_groups
*
* Returns all local field groups.
*
* @date 22/1/19
* @since 5.7.10
*
* @param void
* @return array
*/
function acf_get_local_field_groups() {
return acf_get_local_store( 'groups' )->get();
}
/**
* acf_have_local_field_groups
*
* description
*
* @date 22/1/19
* @since 5.7.10
*
* @param type $var Description. Default.
* @return type Description.
*/
function acf_have_local_field_groups() {
return acf_get_local_store( 'groups' )->count() ? true : false;
}
/**
* acf_count_local_field_groups
*
* description
*
* @date 22/1/19
* @since 5.7.10
*
* @param type $var Description. Default.
* @return type Description.
*/
function acf_count_local_field_groups() {
return acf_get_local_store( 'groups' )->count();
}
/**
* acf_add_local_field_group
*
* Adds a local field group.
*
* @date 22/1/19
* @since 5.7.10
*
* @param array $field_group The field group array.
* @return void
*/
function acf_add_local_field_group( $field_group ) {
// Validate field group.
$field_group = acf_get_valid_field_group( $field_group );
// Bail early if field group already exists.
if( acf_is_local_field_group($field_group['key']) ) {
return;
}
// Extract fields from group.
$fields = acf_extract_var( $field_group, 'fields' );
// Add local reference (may be set to "json").
if( empty($field_group['local']) ) {
$field_group['local'] = 'php';
}
// Add to store
acf_get_local_store( 'groups' )->set( $field_group['key'], $field_group );
// Add fields
if( $fields ) {
// Add parent reference
foreach( $fields as $i => $field ) {
$fields[ $i ]['parent'] = $field_group['key'];
}
// Add fields.
acf_add_local_fields( $fields );
}
}
/**
* register_field_group
*
* See acf_add_local_field_group().
*
* @date 22/1/19
* @since 5.7.10
*
* @param array $field_group The field group array.
* @return void
*/
function register_field_group( $field_group ) {
acf_add_local_field_group( $field_group );
}
/**
* acf_remove_local_field_group
*
* Removes a field group for the given key.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field group key.
* @return bool
*/
function acf_remove_local_field_group( $key = '' ) {
return acf_get_local_store( 'groups' )->remove( $key );
}
/**
* acf_is_local_field_group
*
* Returns true if a field group exists for the given key.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field group key.
* @return bool
*/
function acf_is_local_field_group( $key = '' ) {
return acf_get_local_store( 'groups' )->has( $key );
}
/**
* acf_is_local_field_group_key
*
* Returns true if a field group exists for the given key.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field group group key.
* @return bool
*/
function acf_is_local_field_group_key( $key = '' ) {
return acf_get_local_store( 'groups' )->is( $key );
}
/**
* acf_get_local_field_group
*
* Returns a field group for the given key.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field group key.
* @return (array|null)
*/
function acf_get_local_field_group( $key = '' ) {
return acf_get_local_store( 'groups' )->get( $key );
}
/**
* acf_add_local_fields
*
* Adds an array of local fields.
*
* @date 22/1/19
* @since 5.7.10
*
* @param array $fields An array of un prepared fields.
* @return array
*/
function acf_add_local_fields( $fields = array() ) {
// Prepare for import (allows parent fields to offer up children).
$fields = acf_prepare_fields_for_import( $fields );
// Add each field.
foreach( $fields as $field ) {
acf_add_local_field( $field, true );
}
}
/**
* acf_get_local_fields
*
* Returns all local fields for the given parent.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $parent The parent key.
* @return array
*/
function acf_get_local_fields( $parent = '' ) {
// Return children
if( $parent ) {
return acf_get_local_store( 'fields' )->query(array(
'parent' => $parent
));
// Return all.
} else {
return acf_get_local_store( 'fields' )->get();
}
}
/**
* acf_have_local_fields
*
* Returns true if local fields exist.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $parent The parent key.
* @return bool
*/
function acf_have_local_fields( $parent = '' ) {
return acf_get_local_fields($parent) ? true : false;
}
/**
* acf_count_local_fields
*
* Returns the number of local fields for the given parent.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $parent The parent key.
* @return int
*/
function acf_count_local_fields( $parent = '' ) {
return count( acf_get_local_fields($parent) );
}
/**
* acf_add_local_field
*
* Adds a local field.
*
* @date 22/1/19
* @since 5.7.10
*
* @param array $field The field array.
* @param bool $prepared Whether or not the field has already been prepared for import.
* @return void
*/
function acf_add_local_field( $field, $prepared = false ) {
// Apply default args needed for import.
$field = wp_parse_args($field, array(
'key' => '',
'name' => '',
'type' => '',
'parent' => ''
));
// Ensure field has a key.
if( !$field['key'] ) {
$field['key'] = "field_{$field['name']}";
}
// If called directly, allow sub fields to be correctly prepared.
if( !$prepared ) {
return acf_add_local_fields( array( $field ) );
}
// Extract attributes.
$key = $field['key'];
$name = $field['name'];
// Allow sub field to be added multipel times to different parents.
$store = acf_get_local_store( 'fields' );
if( $store->is($key) ) {
$old_key = _acf_generate_local_key( $store->get($key) );
$new_key = _acf_generate_local_key( $field );
if( $old_key !== $new_key ) {
$key = $new_key;
}
}
// Add field.
$store->set( $key, $field )->alias( $key, $name );
}
/**
* _acf_generate_local_key
*
* Generates a unique key based on the field's parent.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field key.
* @return bool
*/
function _acf_generate_local_key( $field ) {
return "{$field['key']}:{$field['parent']}";
}
/**
* acf_remove_local_field
*
* Removes a field for the given key.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field key.
* @return bool
*/
function acf_remove_local_field( $key = '' ) {
return acf_get_local_store( 'fields' )->remove( $key );
}
/**
* acf_is_local_field
*
* Returns true if a field exists for the given key or name.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field group key.
* @return bool
*/
function acf_is_local_field( $key = '' ) {
return acf_get_local_store( 'fields' )->has( $key );
}
/**
* acf_is_local_field_key
*
* Returns true if a field exists for the given key.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field group key.
* @return bool
*/
function acf_is_local_field_key( $key = '' ) {
return acf_get_local_store( 'fields' )->is( $key );
}
/**
* acf_get_local_field
*
* Returns a field for the given key.
*
* @date 22/1/19
* @since 5.7.10
*
* @param string $key The field group key.
* @return (array|null)
*/
function acf_get_local_field( $key = '' ) {
return acf_get_local_store( 'fields' )->get( $key );
}
/**
* _acf_apply_get_local_field_groups
*
* Appends local field groups to the provided array.
*
* @date 23/1/19
* @since 5.7.10
*
* @param array $field_groups An array of field groups.
* @return array
*/
function _acf_apply_get_local_field_groups( $groups = array() ) {
// Get local groups
$local = acf_get_local_field_groups();
if( $local ) {
// Generate map of "index" => "key" data.
$map = wp_list_pluck($groups, 'key');
// Loop over groups and update/append local.
foreach( $local as $group ) {
// Get group allowing cache and filters to run.
//$group = acf_get_field_group( $group['key'] );
// Update.
$i = array_search($group['key'], $map);
if( $i !== false ) {
unset($group['ID']);
$groups[ $i ] = array_merge($groups[ $i ], $group);
// Append
} else {
$groups[] = acf_get_field_group( $group['key'] );
}
}
// Sort list via menu_order and title.
$groups = wp_list_sort( $groups, array('menu_order' => 'ASC', 'title' => 'ASC') );
}
// Return groups.
return $groups;
}
// Hook into filter.
add_filter( 'acf/get_field_groups', '_acf_apply_get_local_field_groups', 20, 1 );
/**
* _acf_apply_is_local_field_key
*
* Returns true if is a local key.
*
* @date 23/1/19
* @since 5.7.10
*
* @param bool $bool The result.
* @param string $id The identifier.
* @return bool
*/
function _acf_apply_is_local_field_key( $bool, $id ) {
return acf_is_local_field_key( $id );
}
// Hook into filter.
add_filter( 'acf/is_field_key', '_acf_apply_is_local_field_key', 20, 2 );
/**
* _acf_apply_is_local_field_group_key
*
* Returns true if is a local key.
*
* @date 23/1/19
* @since 5.7.10
*
* @param bool $bool The result.
* @param string $id The identifier.
* @return bool
*/
function _acf_apply_is_local_field_group_key( $bool, $id ) {
return acf_is_local_field_group_key( $id );
}
// Hook into filter.
add_filter( 'acf/is_field_group_key', '_acf_apply_is_local_field_group_key', 20, 2 );
/**
* _acf_do_prepare_local_fields
*
* Local fields that are added too early will not be correctly prepared by the field type class.
*
* @date 23/1/19
* @since 5.7.10
*
* @param void
* @return void
*/
function _acf_do_prepare_local_fields() {
// Get fields.
$fields = acf_get_local_fields();
// If fields have been registered early, re-add to correctly prepare them.
if( $fields ) {
acf_add_local_fields( $fields );
}
}
// Hook into action.
add_action( 'acf/include_fields', '_acf_do_prepare_local_fields', 0, 1 );
?>

File diff suppressed because it is too large Load Diff

View File

@ -335,7 +335,7 @@ function acf_match_location_rule( $rule, $screen ) {
* @return (array)
*/
function acf_get_location_screen( $screen, $field_group ) {
function acf_get_location_screen( $screen = array(), $field_group = false ) {
// vars
$screen = wp_parse_args($screen, array(

View File

@ -46,35 +46,24 @@ class acf_location_page_template extends acf_location {
function rule_match( $result, $rule, $screen ) {
// vars
$post_type = acf_maybe_get( $screen, 'post_type' );
// lookup post_type
if( !$post_type ) {
$post_id = acf_maybe_get( $screen, 'post_id' );
if( !$post_id ) return false;
$post_type = get_post_type( $post_id );
// Check if this rule is relevant to the current screen.
// Find $post_id in the process.
if( isset($screen['post_type']) ) {
$post_type = $screen['post_type'];
} elseif( isset($screen['post_id']) ) {
$post_type = get_post_type( $screen['post_id'] );
} else {
return false;
}
// page template 'default' rule is only for 'page' post type
// prevents 'Default Template' field groups appearing on all post types that allow for post templates (WP 4.7)
if( $rule['value'] === 'default' ) {
// bail ealry if not page
if( $post_type !== 'page' ) return false;
// If this rule is set to "default" template, avoid matching on non "page" post types.
// Fixes issue where post templates were added in WP 4.7 and field groups appeared on all post type edit screens.
if( $rule['value'] === 'default' && $post_type !== 'page' ) {
return false;
}
// return
// Return.
return acf_get_location_rule('post_template')->rule_match( $result, $rule, $screen );
}
@ -93,20 +82,19 @@ class acf_location_page_template extends acf_location {
function rule_values( $choices, $rule ) {
// vars
// Default choices.
$choices = array(
'default' => apply_filters( 'default_page_template_title', __('Default Template', 'acf') )
);
// Load all templates, and merge in 'page' templates.
$post_templates = acf_get_post_templates();
if( isset($post_templates['page']) ) {
$choices = array_merge($choices, $post_templates['page']);
}
// get templates and merge them in
$templates = wp_get_theme()->get_page_templates();
$choices = array_merge($choices, $templates);
// return choices
// Return choices.
return $choices;
}
}

View File

@ -81,53 +81,36 @@ class acf_location_post_template extends acf_location {
function rule_match( $result, $rule, $screen ) {
// vars
$templates = array();
$post_id = acf_maybe_get( $screen, 'post_id' );
// Check if this rule is relevant to the current screen.
// Find $post_id in the process.
if( isset($screen['post_type']) ) {
$post_type = $screen['post_type'];
} elseif( isset($screen['post_id']) ) {
$post_type = get_post_type( $screen['post_id'] );
} else {
return false;
}
// Check if this post type has templates.
$post_templates = acf_get_post_templates();
if( !isset($post_templates[ $post_type ]) ) {
return false;
}
// get page template allowing for screen or database value.
$page_template = acf_maybe_get( $screen, 'page_template' );
$post_type = $this->get_post_type( $screen );
// bail early if no post_type found (not a post)
if( !$post_type ) return false;
// get templates (WP 4.7)
if( acf_version_compare('wp', '>=', '4.7') ) {
$templates = acf_get_post_templates();
}
// 'page' is always a valid pt even if no templates exist in the theme
// allows scenario where page_template = 'default' and no templates exist
if( !isset($templates['page']) ) {
$templates['page'] = array();
}
// bail early if this post type does not allow for templates
if( !isset($templates[ $post_type ]) ) return false;
// get page template
if( !$page_template ) {
$post_id = acf_maybe_get( $screen, 'post_id' );
if( $page_template === null ) {
$page_template = get_post_meta( $post_id, '_wp_page_template', true );
}
// Treat empty value as default template.
if( $page_template === '' ) {
$page_template = 'default';
}
// new post - no page template
if( !$page_template ) $page_template = "default";
// match
// Compare.
return $this->compare( $page_template, $rule );
}
@ -146,24 +129,17 @@ class acf_location_post_template extends acf_location {
function rule_values( $choices, $rule ) {
// vars
// Default choices.
$choices = array(
'default' => apply_filters( 'default_page_template_title', __('Default Template', 'acf') )
);
// get templates (WP 4.7)
if( acf_version_compare('wp', '>=', '4.7') ) {
$templates = acf_get_post_templates();
$choices = array_merge($choices, $templates);
}
// return choices
// Merge in all post templates.
$post_templates = acf_get_post_templates();
$choices = array_merge($choices, $post_templates);
// Return choices.
return $choices;
}
}

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

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

View File

@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Advanced Custom Fields\n"
"Report-Msgid-Bugs-To: http://support.advancedcustomfields.com\n"
"POT-Creation-Date: 2019-01-15 11:15+1000\n"
"POT-Creation-Date: 2019-01-31 12:36+0100\n"
"PO-Revision-Date: 2015-06-11 13:00+1000\n"
"Last-Translator: Elliot Condon <e@elliotcondon.com>\n"
"Language-Team: Elliot Condon <e@elliotcondon.com>\n"
@ -11,7 +11,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.1\n"
"X-Generator: Poedit 2.2.1\n"
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
@ -26,97 +26,107 @@ msgstr ""
msgid "Advanced Custom Fields"
msgstr ""
#: acf.php:362 includes/admin/admin.php:58
#: acf.php:363 includes/admin/admin.php:58
msgid "Field Groups"
msgstr ""
#: acf.php:363
#: acf.php:364
msgid "Field Group"
msgstr ""
#: acf.php:364 acf.php:396 includes/admin/admin.php:59
#: acf.php:365 acf.php:397 includes/admin/admin.php:59
#: pro/fields/class-acf-field-flexible-content.php:572
msgid "Add New"
msgstr ""
#: acf.php:365
#: acf.php:366
msgid "Add New Field Group"
msgstr ""
#: acf.php:366
#: acf.php:367
msgid "Edit Field Group"
msgstr ""
#: acf.php:367
#: acf.php:368
msgid "New Field Group"
msgstr ""
#: acf.php:368
#: acf.php:369
msgid "View Field Group"
msgstr ""
#: acf.php:369
#: acf.php:370
msgid "Search Field Groups"
msgstr ""
#: acf.php:370
#: acf.php:371
msgid "No Field Groups found"
msgstr ""
#: acf.php:371
#: acf.php:372
msgid "No Field Groups found in Trash"
msgstr ""
#: acf.php:394 includes/admin/admin-field-group.php:220
#: acf.php:395 includes/admin/admin-field-group.php:220
#: includes/admin/admin-field-groups.php:529
#: pro/fields/class-acf-field-clone.php:811
msgid "Fields"
msgstr ""
#: acf.php:395
#: acf.php:396
msgid "Field"
msgstr ""
#: acf.php:397
#: acf.php:398
msgid "Add New Field"
msgstr ""
#: acf.php:398
#: acf.php:399
msgid "Edit Field"
msgstr ""
#: acf.php:399 includes/admin/views/field-group-fields.php:41
#: acf.php:400 includes/admin/views/field-group-fields.php:41
msgid "New Field"
msgstr ""
#: acf.php:400
#: acf.php:401
msgid "View Field"
msgstr ""
#: acf.php:401
#: acf.php:402
msgid "Search Fields"
msgstr ""
#: acf.php:402
#: acf.php:403
msgid "No Fields found"
msgstr ""
#: acf.php:403
#: acf.php:404
msgid "No Fields found in Trash"
msgstr ""
#: acf.php:442 includes/admin/admin-field-group.php:402
#: acf.php:443 includes/admin/admin-field-group.php:402
#: includes/admin/admin-field-groups.php:586
msgid "Inactive"
msgstr ""
#: acf.php:447
#: acf.php:448
#, php-format
msgid "Inactive <span class=\"count\">(%s)</span>"
msgid_plural "Inactive <span class=\"count\">(%s)</span>"
msgstr[0] ""
msgstr[1] ""
#: includes/acf-field-functions.php:823
#: includes/admin/admin-field-group.php:178
msgid "(no label)"
msgstr ""
#: includes/acf-field-group-functions.php:816
#: includes/admin/admin-field-group.php:180
msgid "copy"
msgstr ""
#: includes/admin/admin-field-group.php:86
#: includes/admin/admin-field-group.php:87
#: includes/admin/admin-field-group.php:89
@ -175,25 +185,16 @@ msgstr ""
msgid "Checked"
msgstr ""
#: includes/admin/admin-field-group.php:178 includes/api/api-field.php:320
msgid "(no label)"
msgstr ""
#: includes/admin/admin-field-group.php:179
msgid "(this field)"
msgstr ""
#: includes/admin/admin-field-group.php:180
#: includes/api/api-field-group.php:751
msgid "copy"
msgstr ""
#: includes/admin/admin-field-group.php:181
#: includes/admin/views/field-group-field-conditional-logic.php:51
#: includes/admin/views/field-group-field-conditional-logic.php:151
#: includes/admin/views/field-group-locations.php:29
#: includes/admin/views/html-location-group.php:3
#: includes/api/api-helpers.php:3998
#: includes/api/api-helpers.php:3990
msgid "or"
msgstr ""
@ -380,8 +381,7 @@ msgstr ""
msgid "Review sites & upgrade"
msgstr ""
#: includes/admin/admin.php:54
#: includes/admin/views/field-group-options.php:110
#: includes/admin/admin.php:54 includes/admin/views/field-group-options.php:110
msgid "Custom Fields"
msgstr ""
@ -453,39 +453,39 @@ msgstr ""
msgid "Import Field Groups"
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:61
#: includes/admin/tools/class-acf-admin-tool-import.php:47
msgid ""
"Select the Advanced Custom Fields JSON file you would like to import. When "
"you click the import button below, ACF will import the field groups."
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:66
#: includes/admin/tools/class-acf-admin-tool-import.php:52
#: includes/fields/class-acf-field-file.php:57
msgid "Select File"
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:76
#: includes/admin/tools/class-acf-admin-tool-import.php:62
msgid "Import File"
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:99
#: includes/admin/tools/class-acf-admin-tool-import.php:85
#: includes/fields/class-acf-field-file.php:170
msgid "No file selected"
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:109
#: includes/admin/tools/class-acf-admin-tool-import.php:93
msgid "Error uploading file. Please try again"
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:115
#: includes/admin/tools/class-acf-admin-tool-import.php:98
msgid "Incorrect file type"
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:129
#: includes/admin/tools/class-acf-admin-tool-import.php:107
msgid "Import file empty"
msgstr ""
#: includes/admin/tools/class-acf-admin-tool-import.php:235
#: includes/admin/tools/class-acf-admin-tool-import.php:138
#, php-format
msgid "Imported 1 field group"
msgid_plural "Imported %s field groups"
@ -1182,37 +1182,37 @@ msgstr ""
msgid "(no title)"
msgstr ""
#: includes/api/api-helpers.php:3919
#: includes/api/api-helpers.php:3911
#, php-format
msgid "Image width must be at least %dpx."
msgstr ""
#: includes/api/api-helpers.php:3924
#: includes/api/api-helpers.php:3916
#, php-format
msgid "Image width must not exceed %dpx."
msgstr ""
#: includes/api/api-helpers.php:3940
#: includes/api/api-helpers.php:3932
#, php-format
msgid "Image height must be at least %dpx."
msgstr ""
#: includes/api/api-helpers.php:3945
#: includes/api/api-helpers.php:3937
#, php-format
msgid "Image height must not exceed %dpx."
msgstr ""
#: includes/api/api-helpers.php:3963
#: includes/api/api-helpers.php:3955
#, php-format
msgid "File size must be at least %s."
msgstr ""
#: includes/api/api-helpers.php:3968
#: includes/api/api-helpers.php:3960
#, php-format
msgid "File size must must not exceed %s."
msgstr ""
#: includes/api/api-helpers.php:4002
#: includes/api/api-helpers.php:3994
#, php-format
msgid "File type must be %s."
msgstr ""
@ -1375,8 +1375,7 @@ msgstr ""
msgid "jQuery"
msgstr ""
#: includes/fields.php:354
#: includes/fields/class-acf-field-button-group.php:177
#: includes/fields.php:354 includes/fields/class-acf-field-button-group.php:177
#: includes/fields/class-acf-field-checkbox.php:389
#: includes/fields/class-acf-field-group.php:474
#: includes/fields/class-acf-field-radio.php:290
@ -2515,6 +2514,12 @@ msgstr ""
msgid "Leave blank for no limit"
msgstr ""
#: includes/fields/class-acf-field-text.php:181
#: includes/fields/class-acf-field-textarea.php:213
#, php-format
msgid "Value must not exceed %d characters"
msgstr ""
#: includes/fields/class-acf-field-textarea.php:25
msgid "Text Area"
msgstr ""
@ -2640,8 +2645,8 @@ msgstr ""
msgid "Validate Email"
msgstr ""
#: includes/forms/form-front.php:103
#: pro/fields/class-acf-field-gallery.php:591 pro/options-page.php:81
#: includes/forms/form-front.php:103 pro/fields/class-acf-field-gallery.php:591
#: pro/options-page.php:81
msgid "Update"
msgstr ""
@ -2734,8 +2739,8 @@ msgstr ""
msgid "Page Template"
msgstr ""
#: includes/locations/class-acf-location-page-template.php:98
#: includes/locations/class-acf-location-post-template.php:151
#: includes/locations/class-acf-location-page-template.php:87
#: includes/locations/class-acf-location-post-template.php:134
msgid "Default Template"
msgstr ""
@ -2828,8 +2833,7 @@ msgstr ""
msgid "<b>Error</b>. Could not connect to update server"
msgstr ""
#: pro/admin/admin-updates.php:118
#: pro/admin/views/html-settings-updates.php:13
#: pro/admin/admin-updates.php:118 pro/admin/views/html-settings-updates.php:13
msgid "Updates"
msgstr ""

View File

@ -1187,7 +1187,10 @@
start: function (event, ui) {
ui.placeholder.html( ui.item.html() );
ui.placeholder.removeAttr('style');
}
},
update: function(event, ui) {
self.$input().trigger('change');
}
});
// resizable

File diff suppressed because one or more lines are too long

View File

@ -104,7 +104,7 @@ class acf_field_flexible_content extends acf_field {
// parse
$layout = wp_parse_args($layout, array(
'key' => uniqid(),
'key' => uniqid('layout_'),
'name' => '',
'label' => '',
'display' => 'block',
@ -209,47 +209,32 @@ class acf_field_flexible_content extends acf_field {
* @param $field (array)
* @return $post_id (int)
*/
function get_sub_field( $sub_field, $selector, $field ) {
function get_sub_field( $sub_field, $id, $field ) {
// bail early if no layouts
if( empty($field['layouts']) ) return false;
// vars
// Get active layout.
$active = get_row_layout();
// loop
foreach( $field['layouts'] as $layout ) {
// bail early if active layout does not match
if( $active && $active !== $layout['name'] ) continue;
// bail early if no sub fields
if( empty($layout['sub_fields']) ) continue;
// loop
foreach( $layout['sub_fields'] as $sub_field ) {
// Loop over layouts.
if( $field['layouts'] ) {
foreach( $field['layouts'] as $layout ) {
// check name and key
if( $sub_field['name'] == $selector || $sub_field['key'] == $selector ) {
// return
return $sub_field;
// Restict to active layout if within a have_rows() loop.
if( $active && $active !== $layout['name'] ) {
continue;
}
// Check sub fields.
if( $layout['sub_fields'] ) {
$sub_field = acf_search_fields( $id, $layout['sub_fields'] );
if( $sub_field ) {
break;
}
}
}
}
// return
return false;
return $sub_field;
}
@ -1639,71 +1624,46 @@ class acf_field_flexible_content extends acf_field {
function prepare_field_for_import( $field ) {
// bail early if no layouts
if( empty($field['layouts']) ) return $field;
// Bail early if no layouts
if( empty($field['layouts']) ) {
return $field;
}
// var
// Storage for extracted fields.
$extra = array();
// loop
foreach( array_keys($field['layouts']) as $i ) {
// Loop over layouts.
foreach( $field['layouts'] as &$layout ) {
// extract layout
$layout = acf_extract_var( $field['layouts'], $i );
// Ensure layout is valid.
$layout = $this->get_valid_layout( $layout );
// Extract sub fields.
$sub_fields = acf_extract_var( $layout, 'sub_fields' );
// get valid layout (fixes ACF4 export code bug undefined index 'key')
if( empty($layout['key']) ) $layout['key'] = uniqid();
// extract sub fields
$sub_fields = acf_extract_var( $layout, 'sub_fields');
// validate sub fields
if( !empty($sub_fields) ) {
// loop over sub fields
foreach( array_keys($sub_fields) as $j ) {
// Modify and append sub fields to $extra.
if( $sub_fields ) {
foreach( $sub_fields as $i => $sub_field ) {
// extract sub field
$sub_field = acf_extract_var( $sub_fields, $j );
// attributes
// Update atttibutes
$sub_field['parent'] = $field['key'];
$sub_field['parent_layout'] = $layout['key'];
$sub_field['menu_order'] = $i;
// append to extra
// Append to extra.
$extra[] = $sub_field;
}
}
// append to layout
$field['layouts'][ $i ] = $layout;
}
// extra
if( !empty($extra) ) {
// Merge extra sub fields.
if( $extra ) {
array_unshift($extra, $field);
return $extra;
}
// return
// Return field.
return $field;
}

View File

@ -66,6 +66,49 @@ From your WordPress dashboard
== Changelog ==
= 5.7.13 =
*Release Date - 6 March 2019*
* Fix - Fixed bug causing issues with registered fields during `switch_to_blog()`.
* Fix - Fixed bug preventing sub fields from being reused across multiple parents.
* Fix - Fixed bug causing the `get_sub_field()` function to fail if a tab field exists with the same name as the selected field.
* Fix - Fixed bug corrupting field settings since WP 5.1 when instructions contain `< a target="" >`.
* Fix - Fixed bug in Gutenberg where custom metabox location (acf_after_title) did not show on initial page load.
* Fix - Fixed bug causing issues when importing/syncing multiple field groups which contain a clone field.
* Fix - Fixed bug preventing the AMP plugin preview from working.
* Dev - Added new 'pre' filters to get, update and delete meta functions.
* i18n - Update Turkish translation thanks to Emre Erkan.
= 5.7.12 =
*Release Date - 15 February 2019*
* Fix - Added missing function `register_field_group()`.
* Fix - Fixed PHP 5.4 error "Can't use function return value in write context".
* Fix - Fixed bug causing wp_options values to be slashed incorrectly.
* Fix - Fixed bug where "sync" feature imported field groups without fields.
* Fix - Fixed bug preventing `get_field_object()` working with a field key.
* Fix - Fixed bug causing incorrect results in `get_sub_field()`.
* Fix - Fixed bug causing draft and preview issues with serialized values.
* Fix - Fixed bug causing reversed field group metabox order.
* Fix - Fixed bug causing incorrect character count when validating values.
* Fix - Fixed bug showing incorrect choices for post_template location rule.
* Fix - Fixed bug causing incorrect value retrieval after `switch_to_blog()`.
* i18n - Updated Persian translation thanks to Majix.
= 5.7.11 =
*Release Date - 11 February 2019*
* New - Added support for persistent object caching.
* Fix - Fixed PHP error in `determine_locale()` affecting AJAX requests.
* Fix - Fixed bug affecting dynamic metabox check when selecting "default" page template.
* Fix - Fixed bug where tab fields did not render correctly within a dynamic metabox.
* Tweak - Removed language fallback from "zh_TW" to "zh_CN".
* Dev - Refactored various core functions.
* Dev - Added new hook variation functions `acf_add_filter_variations()` and `acf_add_action_variations()`.
* i18n - Updated Portuguese language thanks to Pedro Mendonça.
* i18n - Updated German translation thanks to Ralf Koller.
* i18n - Updated Swiss German translation thanks to Raphael Hüni.
= 5.7.10 =
*Release Date - 16 January 2019*