This commit is contained in:
Elliot Condon 2018-08-14 10:14:07 +02:00 committed by Remco Tolsma
parent 7eb289e3cb
commit a590a680f8
36 changed files with 2827 additions and 2134 deletions

12
acf.php
View File

@ -3,7 +3,7 @@
Plugin Name: Advanced Custom Fields PRO
Plugin URI: https://www.advancedcustomfields.com/
Description: Customise WordPress with powerful, professional and intuitive fields.
Version: 5.7.0
Version: 5.7.2
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.0';
var $version = '5.7.2';
/** @var array The plugin settings array */
var $settings = array();
@ -127,7 +127,7 @@ class ACF {
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');
// fields
acf_include('includes/fields.php');
@ -141,7 +141,6 @@ class ACF {
// core
acf_include('includes/assets.php');
acf_include('includes/ajax.php');
acf_include('includes/cache.php');
acf_include('includes/compatibility.php');
acf_include('includes/deprecated.php');
@ -154,6 +153,11 @@ class ACF {
acf_include('includes/updates.php');
acf_include('includes/validation.php');
// ajax
acf_include('includes/ajax/class-acf-ajax.php');
acf_include('includes/ajax/class-acf-ajax-user-setting.php');
acf_include('includes/ajax/class-acf-ajax-query.php');
acf_include('includes/ajax/class-acf-ajax-query-terms.php');
// forms
acf_include('includes/forms/form-attachment.php');

View File

@ -102,7 +102,6 @@
// initialize
this.$el = $('#acf-field-key-hide');
this.addEvents();
// render
this.render();
@ -247,8 +246,16 @@
return $('#' + this.getInputId() + '-' + name);
},
$meta: function(){
return this.$('.meta:first');
},
$handle: function(){
return this.$('.handle:first');
},
$settings: function(){
return this.$('.acf-field-settings:first > .acf-field');
return this.$('.settings:first');
},
$setting: function( name ){
@ -540,15 +547,16 @@
acf.doAction('submit_field_object', this);
},
onChange: function(){
//console.log('onChange');
onChange: function( e, $el ){
// save settings
this.save();
// action for 3rd party customization
acf.doAction('change_field_object', this);
},
onChanged: function( e, name, value ){
onChanged: function( e, $el, name, value ){
// ignore 'save'
if( name == 'save' ) {
@ -1966,7 +1974,7 @@
$el.sortable({
handle: '.acf-sortable-handle',
connectWith: '.acf-field-list',
start: function(e, ui){
start: function( e, ui ){
var field = acf.getFieldObject( ui.item );
ui.placeholder.height( ui.item.height() );
acf.doAction('sortstart_field_object', field, $el);

File diff suppressed because one or more lines are too long

View File

@ -52,7 +52,7 @@
*/
acf.has = function( name ){
return this.get(data) !== null;
return this.get(name) !== null;
};
@ -983,10 +983,13 @@
};
*/
// Preferences
var preferences = localStorage.getItem('acf');
preferences = preferences ? JSON.parse(preferences) : {};
// - use try/catch to avoid JS error if cookies are disabled on front-end form
try {
var preferences = JSON.parse(localStorage.getItem('acf')) || {};
} catch(e) {
var preferences = {};
}
/**
@ -1485,14 +1488,15 @@
return false
}
// bail if select option does not exist
if( $input.is('select') && !$input.find('option[value="'+value+'"]').length ) {
return false;
}
// update value
$input.val( value );
// prevent select elements displaying blank value if option doesn't exist
if( $input.is('select') && $input.val() === null ) {
$input.val( prevValue );
return false;
}
// update with trigger
if( silent !== true ) {
$input.trigger('change');
@ -2092,7 +2096,7 @@
acf.doAction('load');
});
$(window).on('unload', function(){
$(window).on('beforeunload', function(){
acf.doAction('unload');
});
@ -2762,12 +2766,19 @@
proxyEvent: function( callback ){
return this.proxy(function(e){
// validate
if( !this.validateEvent(e) ) {
return;
}
var args = acf.arrayArgs(arguments);
args.push( $(e.currentTarget) );
callback.apply(this, args);
// construct args
var args = acf.arrayArgs( arguments );
var extraArgs = args.slice(1);
var eventArgs = [ e, $(e.currentTarget) ].concat( extraArgs );
// callback
callback.apply(this, eventArgs);
});
},
@ -4892,10 +4903,18 @@
var fieldsEventManager = new acf.Model({
id: 'fieldsEventManager',
events: {
'click .acf-field a[href="#"]': 'onClick'
'click .acf-field a[href="#"]': 'onClick',
'change .acf-field': 'onChange'
},
onClick: function( e ){
// prevent default of any link with an href of #
e.preventDefault();
},
onChange: function(){
// preview hack allows post to save with no title or content
$('#_acf_changed').val(1);
}
});
@ -5612,6 +5631,10 @@
return this.$('.search');
},
$canvas: function(){
return this.$('.canvas');
},
addClass: function( name ){
this.$control().addClass( name );
},
@ -5729,10 +5752,6 @@
return this.$search().val();
},
getCanvas: function(){
return this.$('.canvas');
},
initialize: function(){
// bail early if too early
@ -5770,7 +5789,7 @@
autocomplete: {}
};
mapArgs = acf.applyFilters('google_map_args', mapArgs, this);
var map = new google.maps.Map( this.getCanvas()[0], mapArgs );
var map = new google.maps.Map( this.$canvas()[0], mapArgs );
this.addMapEvents( map, this );
@ -5810,15 +5829,17 @@
// bind
autocomplete.bindTo('bounds', map);
// event
// autocomplete event place_changed is triggered each time the input changes
// customize the place object with the current "search value" to allow users controll over the address text
google.maps.event.addListener(autocomplete, 'place_changed', function() {
field.setPlace( this.getPlace() );
var place = this.getPlace();
place.address = field.getSearchVal();
field.setPlace( place );
});
}
// click
google.maps.event.addListener( map, 'click', function( e ) {
// vars
var lat = e.latLng.lat();
var lng = e.latLng.lng();
@ -5832,7 +5853,6 @@
// dragend
google.maps.event.addListener( marker, 'dragend', function(){
// vars
var position = this.getPosition();
var lat = position.lat();
@ -5901,7 +5921,7 @@
// vars
var lat = place.geometry.location.lat();
var lng = place.geometry.location.lng();
var address = place.formatted_address;
var address = place.address || place.formatted_address;
// update
this.setValue({
@ -5937,7 +5957,7 @@
$wrap.addClass('-loading');
// callback
var callback = $.proxy(function( results, status ){
var callback = this.proxy(function( results, status ){
// remove class
$wrap.removeClass('-loading');
@ -5954,7 +5974,7 @@
} else {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
address = results[0].formatted_address;
//address = results[0].formatted_address;
}
// update val
@ -5966,7 +5986,7 @@
//acf.doAction('google_map_geocode_results', results, status, this.$el, this);
}, this);
});
// query
api.geocoder.geocode({ 'address' : address }, callback);
@ -6848,8 +6868,8 @@
getValue: function(){
var val = this.$input().val();
if( val === 'other' ) {
val = this.inputText().val();
if( val === 'other' && this.get('other_choice') ) {
val = this.$inputText().val();
}
return val;
},
@ -9734,7 +9754,7 @@
remove: function(){
this.frame.detach();
this.frame.dispose();
this.frame.remove();
},
getFrameOptions: function(){
@ -10105,10 +10125,16 @@
initialize: function(){
// bail early if no media views
if( !acf.isset(wp, 'media', 'view') ) {
if( !acf.isset(window, 'wp', 'media', 'view') ) {
return;
}
// fix bug where CPT without "editor" does not set post.id setting which then prevents uploadedTo from working
var postID = getPostID();
if( postID && acf.isset(wp, 'media', 'view', 'settings', 'post') ) {
wp.media.view.settings.post.id = postID;
}
// customize
this.customizeAttachmentsRouter();
this.customizeAttachmentFilters();
@ -10215,46 +10241,30 @@
// Each instance will attempt to render when a new modal is created.
// Use a property to avoid this and only render once per instance.
if( this.rendered ) {
//console.log('ignore render', this.cid);
return this;
}
this.rendered = true;
// render
//console.log('render', this.cid);
// render HTML
AttachmentCompat.prototype.render.apply( this, arguments );
// when uploading, render is called twice.
// ignore first render by checking for #acf-form-data element
if( !this.$('#acf-form-data').length ) {
return this;
}
// clear timeout
clearTimeout( timeout );
// setTimeout
timeout = setTimeout($.proxy(function(){
// check if element is visible to avoid logic on previous instances (which are hidden)
if( this.$el.is(':visible') ) {
//console.log('append', this.cid);
acf.doAction('append', this.$el);
}
this.rendered = true;
acf.doAction('append', this.$el);
}, this), 50);
// return
return this;
},
// commented out function causing JS errors when navigating through media grid
// dispose (and remove) are called after the element has been detached, so this only causes extra JS initialization
dispose: function(){
// remove
if( this.$el.is(':visible') ) {
//acf.doAction('remove', this.$el);
console.log('removed visible');
}
// dispose
return AttachmentCompat.prototype.dispose.apply( this, arguments );
}
});
},
@ -11296,6 +11306,7 @@
var locale = acf.get('locale');
var rtl = acf.get('rtl');
var l10n = acf.get('select2L10n');
var version = getVersion();
// bail ealry if no l10n
if( !l10n ) {
@ -11308,9 +11319,9 @@
}
// initialize
if( getVersion() == 4 ) {
if( version == 4 ) {
this.addTranslations4();
} else {
} else if( version == 3 ) {
this.addTranslations3();
}
},
@ -11848,10 +11859,10 @@
},
events: {
'click #publish': 'onClickPublish',
'click #submit': 'onClickPublish',
'click #save-post': 'onClickSave',
'submit form': 'onSubmit',
'click input[type="submit"]': 'onClickSubmit',
'click button[type="submit"]': 'onClickSubmit',
'click #save-post': 'onClickSave',
'submit form': 'onSubmit',
},
initialize: function(){
@ -12075,6 +12086,8 @@
// create event specific success callback
if( args.event ) {
// create new event to avoid conflicts with prevenDefault (as used in taxonomy form)
var event = $.Event(null, args.event);
args.success = function(){
$(event.target).trigger( event );
@ -12083,7 +12096,7 @@
// action for 3rd party
acf.doAction('validation_begin', $form);
// data
var data = acf.serialize( $form );
data.action = 'acf/validate_save_post';
@ -12182,7 +12195,7 @@
addInputEvents: function( $el ){
// vars
var $inputs = $('.acf-field [name]');
var $inputs = $('.acf-field [name]', $el);
// check
if( $inputs.length ) {
@ -12211,19 +12224,15 @@
$form.submit();
},
// fixes bug on User Profile edit form
// - WP prevents $form.submit() events for unknown reason
// - temp store 'click event' and use later in onSubmit
onClickPublish: function( e, $el ){
onClickSubmit: function( e, $el ){
// store the "click event" for later use in this.onSubmit()
this.set('originalEvent', e);
this.setTimeout(function(){
this.set('originalEvent', null);
}, 100);
},
onClickSave: function( e, $el ) {
// ignore errors
// ignore errors when saving
this.pass();
},
@ -12232,7 +12241,7 @@
// validate
var valid = acf.validateForm({
form: $form,
event: this.get('originalEvent') || e
event: this.get('originalEvent')
});
// if not valid, stop event and allow validation to continue
@ -12293,7 +12302,7 @@
// vars
var $wrap = this.findSubmitWrap( $form );
var $submit = $wrap.find('.button, .acf-button');
var $submit = $wrap.find('.button, [type="submit"]');
var $spinner = $wrap.find('.spinner, .acf-spinner');
// hide all spinners (hides the preview spinner)
@ -12308,7 +12317,7 @@
// vars
var $wrap = this.findSubmitWrap( $form );
var $submit = $wrap.find('.button, .acf-button');
var $submit = $wrap.find('.button, [type="submit"]');
var $spinner = $wrap.find('.spinner, .acf-spinner');
// unlock

File diff suppressed because one or more lines are too long

View File

@ -444,7 +444,7 @@ class acf_admin_field_group {
acf_disable_filters();
// save fields
if( !empty($_POST['acf_fields']) ) {
if( !empty($_POST['acf_fields']) ) {
// loop
foreach( $_POST['acf_fields'] as $field ) {

View File

@ -152,32 +152,20 @@
</div>
<?php elseif( $active == 'changelog' ): ?>
<p class="about-description"><?php printf(__("We think you'll love the changes in %s.", 'acf'), $version); ?></p>
<?php
$items = file_get_contents( acf_get_path('readme.txt') );
$items = explode('= ' . $version . ' =', $items);
$items = end( $items );
$items = current( explode("\n\n", $items) );
$items = array_filter( array_map('trim', explode("*", $items)) );
// extract changelog and parse markdown
$readme = file_get_contents( acf_get_path('readme.txt') );
$changelog = '';
if( preg_match( '/(= '.$version.' =)(.+?)(=|$)/s', $readme, $match ) && $match[2] ) {
$changelog = acf_parse_markdown( $match[2] );
}
echo acf_parse_markdown($changelog);
?>
<ul class="changelog">
<?php foreach( $items as $item ):
$item = explode('http', $item);
?>
<li><?php echo $item[0]; ?><?php if( isset($item[1]) ): ?><a href="http<?php echo $item[1]; ?>" target="_blank">[...]</a><?php endif; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
endif; ?>
</div>

View File

@ -1,86 +0,0 @@
<?php
/*
* ACF AJAX Class
*
* All the logic for misc AJAX functionality
*
* @class acf_ajax
* @package ACF
* @subpackage Core
*/
if( ! class_exists('acf_ajax') ) :
class acf_ajax {
/*
* __construct
*
* This function will setup the class functionality
*
* @type function
* @date 5/03/2014
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
function __construct() {
// acf/update_user_setting
add_action( 'wp_ajax_acf/update_user_setting', array($this, 'update_user_setting') );
add_action( 'wp_ajax_nopriv_acf/update_user_setting', array($this, 'update_user_setting') );
}
/*
* update_user_setting
*
* This function will update a user setting
*
* @type function
* @date 15/07/2014
* @since 5.0.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function update_user_setting() {
// options
$options = wp_parse_args( $_POST, array(
'name' => '',
'value' => '',
'nonce' => '',
));
// validate
if( ! wp_verify_nonce($options['nonce'], 'acf_nonce') || empty($options['name']) ) {
die('0');
}
// upadte setting
acf_update_user_setting( $options['name'], $options['value'] );
// return
die('1');
}
}
new acf_ajax();
endif;
?>

View File

@ -0,0 +1,141 @@
<?php
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if( ! class_exists('ACF_Ajax_Query_Terms') ) :
class ACF_Ajax_Query_Terms extends ACF_Ajax_Query {
/** @var string The AJAX action name */
var $action = 'acf/ajax/query_terms';
/**
* get_args
*
* description
*
* @date 31/7/18
* @since 5.7.2
*
* @param type $var Description. Default.
* @return type Description.
*/
function get_args() {
// defaults
$args = wp_parse_args($this->get('query'), array(
'taxonomy' => 'category',
'search' => $this->search,
'number' => $this->per_page,
));
// pagination
if( $this->page > 0 ) {
$args['offset'] = $this->per_page * ($this->page - 1);
}
// return
return $args;
}
/**
* get_results
*
* description
*
* @date 31/7/18
* @since 5.7.2
*
* @param type $var Description. Default.
* @return type Description.
*/
function get_results( $args ) {
// vars
$results = array();
// get terms
$groups = acf_get_grouped_terms( $args );
// loop
if( $groups ) {
foreach( $groups as $label => $terms ) {
// data
$data = array(
'text' => $label,
'children' => array()
);
// convert object to string
foreach( $terms as $id => $term ) {
$terms[ $id ] = $this->get_result( $term );
}
// order posts by search
if( $this->search && !isset($args['orderby']) ) {
$terms = acf_order_by_search( $terms, $this->search );
}
// append to $data
foreach( $terms as $id => $text ) {
$this->count++;
$data['children'][] = array(
'id' => $id,
'text' => $text
);
}
// append to $results
$results[] = $data;
}}
// extract group children for a single taxonomy
$taxonomies = acf_get_array($args['taxonomy']);
if( count($taxonomies) == 1 ) {
$results = $results[0]['children'];
}
// return
return $results;
}
/**
* get_result
*
* description
*
* @date 31/7/18
* @since 5.7.2
*
* @param type $var Description. Default.
* @return type Description.
*/
function get_result( $term ) {
// vars
$title = $term->name;
// ancestors
$ancestors = get_ancestors( $term->term_id, $term->taxonomy );
if( $ancestors ) {
$prepend = str_repeat('- ', count($ancestors));
return $prepend . $title;
}
// return
return $title;
}
}
acf_new_instance('ACF_AJAX_Query_Terms');
endif; // class_exists check
?>

View File

@ -0,0 +1,133 @@
<?php
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if( ! class_exists('ACF_Ajax_Query') ) :
class ACF_Ajax_Query extends ACF_Ajax {
/** @var array The ACF field used for querying */
var $field = false;
/** @var int The page of results to return */
var $page = 1;
/** @var int The number of results per page */
var $per_page = 20;
/** @var string The searched term */
var $search = '';
/** @var int The number of results found */
var $count = 0;
/**
* response
*
* The actual logic for this AJAX request.
*
* @date 31/7/18
* @since 5.7.2
*
* @param void
* @return void
*/
function response() {
// field
if( $this->has('field_key') ) {
$this->field = acf_get_field( $this->get('field_key') );
}
// pagination
if( $this->has('paged') ) {
$this->page = (int) $this->get('paged');
}
// search
if( $this->has('s') ) {
$this->search = $this->get('s');
}
// get response
$args = $this->get_args();
$results = $this->get_results($args);
$response = $this->get_response($results, $args);
// return
return $response;
}
/**
* get_args
*
* description
*
* @date 31/7/18
* @since 5.7.2
*
* @param type $var Description. Default.
* @return type Description.
*/
function get_args() {
return array();
}
/**
* get_results
*
* description
*
* @date 31/7/18
* @since 5.7.2
*
* @param type $var Description. Default.
* @return type Description.
*/
function get_results( $args ) {
return array();
}
/**
* get_result
*
* description
*
* @date 31/7/18
* @since 5.7.2
*
* @param type $var Description. Default.
* @return type Description.
*/
function get_result( $item ) {
return '';
}
/**
* get_response
*
* description
*
* @date 31/7/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
function get_response( $results, $args ) {
return array(
'results' => $results,
'more' => ($this->count >= $this->per_page)
);
}
}
endif; // class_exists check
?>

View File

@ -0,0 +1,44 @@
<?php
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if( ! class_exists('ACF_Ajax_User_Setting') ) :
class ACF_Ajax_User_Setting extends ACF_Ajax{
/** @var string The AJAX action name */
var $action = 'acf/update_user_setting';
/** @var bool Prevents access for non-logged in users */
var $public = true;
/**
* get_response
*
* The actual logic for this AJAX request.
*
* @date 31/7/18
* @since 5.7.2
*
* @param void
* @return mixed The response data to send back or WP_Error.
*/
function response() {
// update
if( $this->has('value') ) {
return acf_update_user_setting( $this->get('name'), $this->get('value') );
// get
} else {
return acf_get_user_setting( $this->get('name') );
}
}
}
acf_new_instance('ACF_Ajax_User_Setting');
endif; // class_exists check
?>

View File

@ -0,0 +1,195 @@
<?php
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if( ! class_exists('ACF_Ajax') ) :
class ACF_Ajax {
/** @var string The AJAX action name */
var $action = '';
/** @var array The $_REQUEST data */
var $request;
/** @var bool Prevents access for non-logged in users */
var $public = false;
/**
* __construct
*
* Sets up the class functionality.
*
* @date 31/7/18
* @since 5.7.2
*
* @param void
* @return void
*/
function __construct() {
// initialize
$this->initialize();
// add actions
$this->add_actions();
}
/**
* initialize
*
* Allows easy access to modifying properties without changing constructor.
*
* @date 31/7/18
* @since 5.7.2
*
* @param void
* @return void
*/
function initialize() {
/* do nothing */
}
/**
* has
*
* Returns true if the request has data for the given key
*
* @date 31/7/18
* @since 5.7.2
*
* @param string $key The data key
* @return boolean
*/
function has( $key = '' ) {
return isset($this->request[$key]);
}
/**
* get
*
* Returns request data for the given key
*
* @date 31/7/18
* @since 5.7.2
*
* @param string $key The data key
* @return mixed
*/
function get( $key = '' ) {
return isset($this->request[$key]) ? $this->request[$key] : null;
}
/**
* set
*
* Sets request data for the given key
*
* @date 31/7/18
* @since 5.7.2
*
* @param string $key The data key
* @return mixed
*/
function set( $key = '', $value ) {
$this->request[$key] = $value;
}
/**
* add_actions
*
* Adds the ajax actions for this response.
*
* @date 31/7/18
* @since 5.7.2
*
* @param void
* @return void
*/
function add_actions() {
// add action for logged-in users
add_action( "wp_ajax_{$this->action}", array($this, 'request') );
// add action for non logged-in users
if( $this->public ) {
add_action( "wp_ajax_nopriv_{$this->action}", array($this, 'request') );
}
}
/**
* request
*
* Callback for ajax action. Sets up properties and calls the get_response() function.
*
* @date 1/8/18
* @since 5.7.2
*
* @param void
* @return void
*/
function request() {
// verify ajax request
if( !acf_verify_ajax() ) {
wp_send_json_error();
}
// store data for has() and get() functions
$this->request = wp_unslash($_REQUEST);
// send response
$this->send( $this->response() );
}
/**
* response
*
* The actual logic for this AJAX request.
*
* @date 31/7/18
* @since 5.7.2
*
* @param void
* @return mixed The response data to send back or WP_Error.
*/
function response() {
return true;
}
/**
* send
*
* Sends back JSON based on the $response as either success or failure.
*
* @date 31/7/18
* @since 5.7.2
*
* @param mixed $response The response to send back.
* @return void
*/
function send( $response ) {
// return error
if( is_wp_error($response) ) {
wp_send_json_error(array( 'error' => $response->get_error_message() ));
// return success
} else {
wp_send_json_success($response);
}
}
}
endif; // class_exists check
?>

View File

@ -1011,93 +1011,40 @@ function acf_untrash_field_group( $selector = 0 ) {
function acf_get_field_group_style( $field_group ) {
// vars
$e = '';
$style = '';
$elements = array(
'permalink' => '#edit-slug-box',
'the_content' => '#postdivrich',
'excerpt' => '#postexcerpt',
'custom_fields' => '#postcustom',
'discussion' => '#commentstatusdiv',
'comments' => '#commentsdiv',
'slug' => '#slugdiv',
'author' => '#authordiv',
'format' => '#formatdiv',
'page_attributes' => '#pageparentdiv',
'featured_image' => '#postimagediv',
'revisions' => '#revisionsdiv',
'categories' => '#categorydiv',
'tags' => '#tagsdiv-post_tag',
'send-trackbacks' => '#trackbacksdiv'
);
// bail early if no array or is empty
if( !acf_is_array($field_group['hide_on_screen']) ) return $e;
// add style to html
if( in_array('permalink',$field_group['hide_on_screen']) )
{
$e .= '#edit-slug-box {display: none;} ';
// loop over field group settings and generate list of selectors to hide
if( is_array($field_group['hide_on_screen']) ) {
$hide = array();
foreach( $field_group['hide_on_screen'] as $k ) {
if( isset($elements[ $k ]) ) {
$id = $elements[ $k ];
$hide[] = $id;
$hide[] = '#screen-meta label[for=' . substr($id, 1) . '-hide]';
}
}
$style = implode(', ', $hide) . ' {display: none;}';
}
if( in_array('the_content',$field_group['hide_on_screen']) )
{
$e .= '#postdivrich {display: none;} ';
}
if( in_array('excerpt',$field_group['hide_on_screen']) )
{
$e .= '#postexcerpt, #screen-meta label[for=postexcerpt-hide] {display: none;} ';
}
if( in_array('custom_fields',$field_group['hide_on_screen']) )
{
$e .= '#postcustom, #screen-meta label[for=postcustom-hide] { display: none; } ';
}
if( in_array('discussion',$field_group['hide_on_screen']) )
{
$e .= '#commentstatusdiv, #screen-meta label[for=commentstatusdiv-hide] {display: none;} ';
}
if( in_array('comments',$field_group['hide_on_screen']) )
{
$e .= '#commentsdiv, #screen-meta label[for=commentsdiv-hide] {display: none;} ';
}
if( in_array('slug',$field_group['hide_on_screen']) )
{
$e .= '#slugdiv, #screen-meta label[for=slugdiv-hide] {display: none;} ';
}
if( in_array('author',$field_group['hide_on_screen']) )
{
$e .= '#authordiv, #screen-meta label[for=authordiv-hide] {display: none;} ';
}
if( in_array('format',$field_group['hide_on_screen']) )
{
$e .= '#formatdiv, #screen-meta label[for=formatdiv-hide] {display: none;} ';
}
if( in_array('page_attributes',$field_group['hide_on_screen']) )
{
$e .= '#pageparentdiv {display: none;} ';
}
if( in_array('featured_image',$field_group['hide_on_screen']) )
{
$e .= '#postimagediv, #screen-meta label[for=postimagediv-hide] {display: none;} ';
}
if( in_array('revisions',$field_group['hide_on_screen']) )
{
$e .= '#revisionsdiv, #screen-meta label[for=revisionsdiv-hide] {display: none;} ';
}
if( in_array('categories',$field_group['hide_on_screen']) )
{
$e .= '#categorydiv, #screen-meta label[for=categorydiv-hide] {display: none;} ';
}
if( in_array('tags',$field_group['hide_on_screen']) )
{
$e .= '#tagsdiv-post_tag, #screen-meta label[for=tagsdiv-post_tag-hide] {display: none;} ';
}
if( in_array('send-trackbacks',$field_group['hide_on_screen']) )
{
$e .= '#trackbacksdiv, #screen-meta label[for=trackbacksdiv-hide] {display: none;} ';
}
// return
return apply_filters('acf/get_field_group_style', $e, $field_group);
return apply_filters('acf/get_field_group_style', $style, $field_group);
}

View File

@ -993,29 +993,18 @@ function acf_verify_nonce( $value) {
function acf_verify_ajax() {
// vars
$action = acf_maybe_get_POST('action');
$nonce = acf_maybe_get_POST('nonce');
// bail early if not acf action
if( !$action || substr($action, 0, 3) !== 'acf' ) {
return false;
}
$nonce = isset($_REQUEST['nonce']) ? $_REQUEST['nonce'] : '';
// bail early if not acf nonce
if( !$nonce || !wp_verify_nonce($nonce, 'acf_nonce') ) {
return false;
}
// action for 3rd party customization
do_action('acf/verify_ajax');
// return
return true;
}
@ -1248,105 +1237,6 @@ function acf_get_terms( $args ) {
}
/*
* acf_get_taxonomies
*
* This function will return an array of available taxonomies
*
* @type function
* @date 7/10/13
* @since 5.0.0
*
* @param n/a
* @return (array)
*/
function acf_get_taxonomies() {
// get all taxonomies
$taxonomies = get_taxonomies( false, 'objects' );
$ignore = array( 'nav_menu', 'link_category' );
$r = array();
// populate $r
foreach( $taxonomies as $taxonomy )
{
if( in_array($taxonomy->name, $ignore) )
{
continue;
}
$r[ $taxonomy->name ] = $taxonomy->name; //"{$taxonomy->labels->singular_name}"; // ({$taxonomy->name})
}
// return
return $r;
}
function acf_get_pretty_taxonomies( $taxonomies = array() ) {
// get post types
if( empty($taxonomies) ) {
// get all custom post types
$taxonomies = acf_get_taxonomies();
}
// get labels
$ref = array();
$r = array();
foreach( array_keys($taxonomies) as $i ) {
// vars
$taxonomy = acf_extract_var( $taxonomies, $i);
$obj = get_taxonomy( $taxonomy );
$name = $obj->labels->singular_name;
// append to r
$r[ $taxonomy ] = $name;
// increase counter
if( !isset($ref[ $name ]) ) {
$ref[ $name ] = 0;
}
$ref[ $name ]++;
}
// get slugs
foreach( array_keys($r) as $i ) {
// vars
$taxonomy = $r[ $i ];
if( $ref[ $taxonomy ] > 1 ) {
$r[ $i ] .= ' (' . $i . ')';
}
}
// return
return $r;
}
/*
* acf_get_taxonomy_terms
*
@ -5335,4 +5225,46 @@ function acf_get_post_templates() {
}
/**
* acf_parse_markdown
*
* A very basic regex-based Markdown parser function based off [slimdown](https://gist.github.com/jbroadway/2836900).
*
* @date 6/8/18
* @since 5.7.2
*
* @param string $text The string to parse.
* @return string
*/
function acf_parse_markdown( $text = '' ) {
// trim
$text = trim($text);
// rules
$rules = array (
'/=== (.+?) ===/' => '<h2>$1</h2>', // headings
'/== (.+?) ==/' => '<h3>$1</h3>', // headings
'/= (.+?) =/' => '<h4>$1</h4>', // headings
'/\[([^\[]+)\]\(([^\)]+)\)/' => '<a href="$2">$1</a>', // links
'/(\*\*)(.*?)\1/' => '<strong>$2</strong>', // bold
'/(\*)(.*?)\1/' => '<em>$2</em>', // intalic
'/`(.*?)`/' => '<code>$1</code>', // inline code
'/\n\*(.*)/' => "\n<ul>\n\t<li>$1</li>\n</ul>", // ul lists
'/\n[0-9]+\.(.*)/' => "\n<ol>\n\t<li>$1</li>\n</ol>", // ol lists
'/<\/ul>\s?<ul>/' => '', // fix extra ul
'/<\/ol>\s?<ol>/' => '', // fix extra ol
);
foreach( $rules as $k => $v ) {
$text = preg_replace($k, $v, $text);
}
// autop
$text = wpautop($text);
// return
return $text;
}
?>

236
includes/api/api-term.php Normal file
View File

@ -0,0 +1,236 @@
<?php
/*
* acf_get_taxonomies
*
* Returns an array of taxonomy names.
*
* @date 7/10/13
* @since 5.0.0
*
* @param array $args An array of args used in the get_taxonomies() function.
* @return array An array of taxonomy names.
*/
function acf_get_taxonomies( $args = array() ) {
// vars
$taxonomies = array();
// get taxonomy objects
$objects = get_taxonomies( $args, 'objects' );
// loop
foreach( $objects as $i => $object ) {
// bail early if is builtin (WP) private post type
// - nav_menu_item, revision, customize_changeset, etc
if( $object->_builtin && !$object->public ) continue;
// append
$taxonomies[] = $i;
}
// filter
$taxonomies = apply_filters('acf/get_taxonomies', $taxonomies, $args);
// return
return $taxonomies;
}
/*
* acf_get_taxonomy_labels
*
* Returns an array of taxonomies in the format "name => label" for use in a select field.
*
* @date 3/8/18
* @since 5.7.2
*
* @param array $taxonomies Optional. An array of specific taxonomies to return.
* @return array
*/
function acf_get_taxonomy_labels( $taxonomies = array() ) {
// default
if( empty($taxonomies) ) {
$taxonomies = acf_get_taxonomies();
}
// vars
$ref = array();
$data = array();
// loop
foreach( $taxonomies as $taxonomy ) {
// vars
$object = get_taxonomy( $taxonomy );
$label = $object->labels->singular_name;
// append
$data[ $taxonomy ] = $label;
// increase counter
if( !isset($ref[ $label ]) ) {
$ref[ $label ] = 0;
}
$ref[ $label ]++;
}
// show taxonomy name next to label for shared labels
foreach( $data as $taxonomy => $label ) {
if( $ref[$label] > 1 ) {
$data[ $taxonomy ] .= ' (' . $taxonomy . ')';
}
}
// return
return $data;
}
/**
* acf_get_grouped_terms
*
* Returns an array of terms for the given query $args and groups by taxonomy name.
*
* @date 2/8/18
* @since 5.7.2
*
* @param array $args An array of args used in the get_terms() function.
* @return array
*/
function acf_get_grouped_terms( $args ) {
// vars
$data = array();
// defaults
$args = wp_parse_args($args, array(
'taxonomy' => 'category',
'hide_empty' => false,
'update_term_meta_cache' => false,
));
// vars
$taxonomies = acf_get_taxonomy_labels( acf_get_array($args['taxonomy']) );
$is_single = (count($taxonomies) == 1);
// add filter to group results by taxonomy
if( !$is_single ) {
add_filter('terms_clauses', '_acf_terms_clauses', 10, 3);
}
// get terms
$terms = get_terms( $args );
// remove this filter (only once)
if( !$is_single ) {
remove_filter('terms_clauses', '_acf_terms_clauses', 10, 3);
}
// loop
foreach( $taxonomies as $taxonomy => $label ) {
// vars
$this_terms = array();
// populate $this_terms
foreach( $terms as $term ) {
if( $term->taxonomy == $taxonomy ) {
$this_terms[] = $term;
}
}
// bail early if no $items
if( empty($this_terms) ) continue;
// sort into hierachial order
// this will fail if a search has taken place because parents wont exist
if( is_taxonomy_hierarchical($taxonomy) && empty($args['s'])) {
// get all terms from this taxonomy
$all_terms = get_terms(array_merge($args, array(
'number' => 0,
'offset' => 0,
'taxonomy' => $taxonomy
)));
// vars
$length = count($this_terms);
$offset = 0;
// find starting point (offset)
foreach( $all_terms as $i => $term ) {
if( $term->term_id == $this_terms[0]->term_id ) {
$offset = $i;
break;
}
}
// order terms
$parent = acf_maybe_get( $args, 'parent', 0 );
$parent = acf_maybe_get( $args, 'child_of', $parent );
$ordered_terms = _get_term_children( $parent, $all_terms, $taxonomy );
// compare aray lengths
// if $ordered_posts is smaller than $all_posts, WP has lost posts during the get_page_children() function
// this is possible when get_post( $args ) filter out parents (via taxonomy, meta and other search parameters)
if( count($ordered_terms) == count($all_terms) ) {
$this_terms = array_slice($ordered_terms, $offset, $length);
}
}
// populate group
$data[ $label ] = array();
foreach( $this_terms as $term ) {
$data[ $label ][ $term->term_id ] = $term;
}
}
// return
return $data;
}
/**
* _acf_terms_clauses
*
* Used in the 'terms_clauses' filter to order terms by taxonomy name.
*
* @date 2/8/18
* @since 5.7.2
*
* @param array $pieces Terms query SQL clauses.
* @param array $taxonomies An array of taxonomies.
* @param array $args An array of terms query arguments.
* @return array $pieces
*/
function _acf_terms_clauses( $pieces, $taxonomies, $args ) {
// prepend taxonomy to 'orderby' SQL
if( is_array($taxonomies) ) {
$sql = "FIELD(tt.taxonomy,'" . implode("', '", array_map('esc_sql', $taxonomies)) . "')";
$pieces['orderby'] = str_replace("ORDER BY", "ORDER BY $sql,", $pieces['orderby']);
}
// return
return $pieces;
}
/**
* acf_get_pretty_taxonomies
*
* Deprecated in favor of acf_get_taxonomy_labels() function.
*
* @date 7/10/13
* @since 5.0.0
* @deprecated 5.7.2
*/
function acf_get_pretty_taxonomies( $taxonomies = array() ) {
return acf_get_taxonomy_labels( $taxonomies );
}
?>

View File

@ -50,7 +50,7 @@ class acf_field_email extends acf_field {
// vars
$atts = array();
$keys = array( 'type', 'id', 'class', 'name', 'value', 'placeholder', 'pattern' );
$keys2 = array( 'readonly', 'disabled', 'required' );
$keys2 = array( 'readonly', 'disabled', 'required', 'multiple' );
$html = '';

View File

@ -644,6 +644,36 @@ class acf_field__group extends acf_field {
return $sub_fields;
}
/*
* delete_value
*
* Called when deleting this field's value.
*
* @date 1/07/2015
* @since 5.2.3
*
* @param mixed $post_id The post ID being saved
* @param string $meta_key The field name as seen by the DB
* @param array $field The field settings
* @return void
*/
function delete_value( $post_id, $meta_key, $field ) {
// bail ealry if no sub fields
if( empty($field['sub_fields']) ) return null;
// modify names
$field = $this->prepare_field_for_db( $field );
// loop
foreach( $field['sub_fields'] as $sub_field ) {
acf_delete_value( $post_id, $sub_field );
}
}
}

View File

@ -266,27 +266,16 @@ class acf_field_select extends acf_field {
}
// prepend empty choice for single inputs
$prepend = false;
if( !$field['multiple'] ) {
// allow null or ajax
if( $field['allow_null'] || $field['ajax'] ) {
$prepend = true;
}
}
// allow null
// prepend empty choice
// - only for single selects
// - have tried array_merge but this causes keys to re-index if is numeric (post ID's)
if( $prepend ) {
$placeholder = '- ' . $field['placeholder'] . ' -';
$choices = array( '' => $placeholder ) + $choices;
if( $field['allow_null'] && !$field['multiple'] ) {
$choices = array( '' => "- {$field['placeholder']} -" ) + $choices;
}
// clean up choices if using ajax
if( $field['ajax'] ) {
if( $field['ui'] && $field['ajax'] ) {
$minimal = array();
foreach( $value as $key ) {
if( isset($choices[ $key ]) ) {

View File

@ -755,7 +755,7 @@ class acf_field_taxonomy extends acf_field {
'instructions' => __('Select the taxonomy to be displayed','acf'),
'type' => 'select',
'name' => 'taxonomy',
'choices' => acf_get_taxonomies(),
'choices' => acf_get_taxonomy_labels(),
));
@ -856,100 +856,79 @@ class acf_field_taxonomy extends acf_field {
function ajax_add_term() {
// vars
$args = acf_parse_args($_POST, array(
$args = wp_parse_args($_POST, array(
'nonce' => '',
'field_key' => '',
'term_name' => '',
'term_parent' => ''
));
// verify nonce
if( ! wp_verify_nonce($args['nonce'], 'acf_nonce') ) {
if( !acf_verify_ajax() ) {
die();
}
}
// load field
$field = acf_get_field( $args['field_key'] );
if( !$field ) {
die();
}
// vars
$taxonomy_obj = get_taxonomy($field['taxonomy']);
$taxonomy_label = $taxonomy_obj->labels->singular_name;
// validate cap
// note: this situation should never occur due to condition of the add new button
if( !current_user_can( $taxonomy_obj->cap->manage_terms) ) {
echo '<p><strong>' . __("Error.", 'acf') . '</strong> ' . sprintf( __('User unable to add new %s', 'acf'), $taxonomy_label ) . '</p>';
die;
wp_send_json_error(array(
'error' => sprintf( __('User unable to add new %s', 'acf'), $taxonomy_label )
));
}
// save?
if( $args['term_name'] ) {
// exists
if( term_exists($args['term_name'], $field['taxonomy']) ) {
if( term_exists($args['term_name'], $field['taxonomy'], $args['term_parent']) ) {
wp_send_json_error(array(
'error' => sprintf( __('%s already exists', 'acf'), $taxonomy_label )
));
}
// vars
$extra = array();
if( $args['term_parent'] ) {
$extra['parent'] = (int) $args['term_parent'];
}
// insert
$extra = array();
if( $args['term_parent'] ) {
$extra['parent'] = $args['term_parent'];
}
$data = wp_insert_term( $args['term_name'], $field['taxonomy'], $extra );
// error?
// error
if( is_wp_error($data) ) {
wp_send_json_error(array(
'error' => $data->get_error_message()
));
}
// load term
$term = get_term($data['term_id']);
// ancestors
// prepend ancenstors count to term name
$prefix = '';
$ancestors = get_ancestors( $data['term_id'], $field['taxonomy'] );
$ancestors = get_ancestors( $term->term_id, $term->taxonomy );
if( !empty($ancestors) ) {
$prefix = str_repeat('- ', count($ancestors));
}
// success
wp_send_json_success(array(
'message' => sprintf( __('%s added', 'acf'), $taxonomy_label ),
'term_id' => $data['term_id'],
'term_name' => $args['term_name'],
'term_label' => $prefix . $args['term_name'],
'term_parent' => $args['term_parent']
'term_id' => $term->term_id,
'term_name' => $term->name,
'term_label' => $prefix . $term->name,
'term_parent' => $term->parent
));
}

View File

@ -216,24 +216,21 @@ acf.unload.active = 0;
function save_attachment( $post, $attachment ) {
// bail early if not valid nonce
if( ! acf_verify_nonce('attachment') ) {
if( !acf_verify_nonce('attachment') ) {
return $post;
}
// validate and save
if( acf_validate_save_post(true) ) {
// bypass validation for ajax
if( acf_is_ajax('save-attachment-compat') ) {
acf_save_post( $post['ID'] );
}
// validate and save
} elseif( acf_validate_save_post(true) ) {
acf_save_post( $post['ID'] );
}
// return
return $post;
return $post;
}

View File

@ -25,7 +25,7 @@ class acf_form_nav_menu {
add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
add_action('wp_update_nav_menu', array($this, 'update_nav_menu'));
add_action('acf/validate_save_post', array($this, 'acf_validate_save_post'), 5);
add_action('wp_nav_menu_item_custom_fields', array($this, 'wp_nav_menu_item_custom_fields'), 10, 5);
// filters
add_filter('wp_get_nav_menu_items', array($this, 'wp_get_nav_menu_items'), 10, 3);
@ -64,6 +64,65 @@ class acf_form_nav_menu {
}
/**
* wp_nav_menu_item_custom_fields
*
* description
*
* @date 30/7/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
function wp_nav_menu_item_custom_fields( $item_id, $item, $depth, $args, $id = '' ) {
// vars
$prefix = "menu-item-acf[$item_id]";
// get field groups
$field_groups = acf_get_field_groups(array(
'nav_menu_item' => $item->type
));
// render
if( !empty($field_groups) ) {
// open
echo '<div class="acf-menu-item-fields acf-fields -clear">';
// loop
foreach( $field_groups as $field_group ) {
// load fields
$fields = acf_get_fields( $field_group );
// bail if not fields
if( empty($fields) ) continue;
// change prefix
acf_prefix_fields( $fields, $prefix );
// render
acf_render_fields( $fields, $item_id, 'div', $field_group['instruction_placement'] );
}
// close
echo '</div>';
// Trigger append for newly created menu item (via AJAX)
if( acf_is_ajax('add-menu-item') ): ?>
<script type="text/javascript">
(function($) {
acf.doAction('append', $('#menu-item-settings-<?php echo $item_id; ?>') );
})(jQuery);
</script>
<?php endif;
}
}
/*
* update_nav_menu
*

View File

@ -157,7 +157,7 @@ class ACF_Form_User {
// render
$this->render(array(
'user_id' => 0,
'view' => 'new',
'view' => 'add',
'el' => 'tr'
));
}

View File

@ -256,7 +256,6 @@ class acf_form_widget {
*/
function admin_footer() {
?>
<script type="text/javascript">
(function($) {
@ -264,11 +263,12 @@ class acf_form_widget {
// vars
acf.set('post_id', 'widgets');
// restrict get fields
// Only initialize visible fields.
// - check for #widgets-right as this does not exist in accessibility mode
acf.addFilter('find_fields_args', function( args ){
// add parent
if( !args.parent ) {
if( !args.parent && $('#widgets-right').length ) {
args.parent = $('#widgets-right');
}

View File

@ -77,7 +77,7 @@ class acf_location_taxonomy extends acf_location {
// vars
$choices = array( 'all' => __('All', 'acf') );
$choices = array_merge( $choices, acf_get_taxonomies() );
$choices = array_merge( $choices, acf_get_taxonomy_labels() );
// return

View File

@ -2,56 +2,53 @@
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if( ! class_exists('acf_updates') ) :
if( ! class_exists('ACF_Updates') ) :
class acf_updates {
class ACF_Updates {
// vars
var $version = '2.3',
$plugins = array(),
$force_check = false,
$dev = 0;
/** @var string The ACF_Updates version */
var $version = '2.4';
/** @var array The array of registered plugins */
var $plugins = array();
/** @var boolean Dev mode */
var $dev = false;
/** @var int Counts the number of plugin update checks */
var $checked = 0;
/*
* __construct
*
* This function will setup the class functionality
* Sets up the class functionality.
*
* @type function
* @date 5/03/2014
* @since 5.0.0
*
* @param n/a
* @return n/a
* @param void
* @return void
*/
function __construct() {
// vars
$this->force_check = !empty($_GET['force-check']);
// append update information to transient
add_filter('pre_set_site_transient_update_plugins', array($this, 'modify_plugins_transient'), 10, 1);
// modify plugin data visible in the 'View details' popup
add_filter('plugins_api', array($this, 'modify_plugin_details'), 10, 3);
}
/*
* add_plugin
*
* This function will register a plugin
* Registeres a plugin for updates.
*
* @type function
* @date 8/4/17
* @since 5.5.10
*
* @param $plugin (array)
* @return n/a
* @param array $plugin The plugin array.
* @return void
*/
function add_plugin( $plugin ) {
@ -76,20 +73,40 @@ class acf_updates {
$this->plugins[ $plugin['basename'] ] = $plugin;
}
}
/**
* get_plugin_by
*
* Returns a registered plugin for the give key and value.
*
* @date 3/8/18
* @since 5.7.2
*
* @param string $key The array key to compare
* @param string $value The value to compare against
* @return array|false
*/
function get_plugin_by( $key = '', $value = null ) {
foreach( $this->plugins as $plugin ) {
if( $plugin[$key] === $value ) {
return $plugin;
}
}
return false;
}
/*
* request
*
* This function will make a request to the ACF update server
* Makes a request to the ACF connect server.
*
* @type function
* @date 8/4/17
* @since 5.5.10
*
* @param $query (string)
* @param $body (array)
* @return (mixed)
* @param string $query The api path. Defaults to 'index.php'
* @param array $body The body to post
* @return array|string|WP_Error
*/
function request( $query = 'index.php', $body = null ) {
@ -130,33 +147,30 @@ class acf_updates {
return $json;
}
/*
* get_plugin_info
*
* This function will get plugin info and save as transient
* Returns update information for the given plugin id.
*
* @type function
* @date 9/4/17
* @since 5.5.10
*
* @param $id (string)
* @return (mixed)
* @param string $id The plugin id such as 'pro'.
* @param boolean $force_check Bypasses cached result. Defaults to false.
* @return array|WP_Error
*/
function get_plugin_info( $id = '' ) {
function get_plugin_info( $id = '', $force_check = false ) {
// var
$transient_name = 'acf_plugin_info_' . $id;
// ignore cache (only once)
if( $this->force_check ) {
$this->force_check = false;
// check cache
} else {
$transient = get_transient($transient_name);
if( $transient !== false ) return $transient;
// check cache but allow for $force_check override
if( !$force_check ) {
$transient = get_transient( $transient_name );
if( $transient !== false ) {
return $transient;
}
}
// connect
@ -171,38 +185,78 @@ class acf_updates {
$expiration = $this->get_expiration($response, DAY_IN_SECONDS, MONTH_IN_SECONDS);
// update transient
set_transient($transient_name, $response, $expiration );
set_transient( $transient_name, $response, $expiration );
// return
return $response;
}
/**
* get_plugin_update
*
* Returns specific data from the 'update-check' response.
*
* @date 3/8/18
* @since 5.7.2
*
* @param string $basename The plugin basename.
* @param boolean $force_check Bypasses cached result. Defaults to false
* @return array
*/
function get_plugin_update( $basename = '', $force_check = false ) {
// get updates
$updates = $this->get_plugin_updates( $force_check );
// check for and return update
if( is_array($updates) && isset($updates['plugins'][ $basename ]) ) {
return $updates['plugins'][ $basename ];
}
return false;
}
/**
* get_plugin_updates
*
* description
* Checks for plugin updates.
*
* @date 8/7/18
* @since 5.6.9
* @since 5.7.2 Added 'checked' comparison
*
* @param type $var Description. Default.
* @return type Description.
* @param boolean $force_check Bypasses cached result. Defaults to false.
* @return array|WP_Error.
*/
function get_plugin_updates() {
function get_plugin_updates( $force_check = false ) {
// var
$transient_name = 'acf_plugin_updates';
// ignore cache (only once)
if( $this->force_check ) {
$this->force_check = false;
// check cache
} else {
// construct array of 'checked' plugins
// sort by key to avoid detecting change due to "include order"
$checked = array();
foreach( $this->plugins as $basename => $plugin ) {
$checked[ $basename ] = $plugin['version'];
}
ksort($checked);
// $force_check prevents transient lookup
if( !$force_check ) {
$transient = get_transient($transient_name);
if( $transient !== false ) return $transient;
// if cached response was found, compare $transient['checked'] against $checked and ignore if they don't match (plugins/versions have changed)
if( is_array($transient) ) {
$transient_checked = isset($transient['checked']) ? $transient['checked'] : array();
if( wp_json_encode($checked) !== wp_json_encode($transient_checked) ) {
$transient = false;
}
}
if( $transient !== false ) {
return $transient;
}
}
// vars
@ -224,6 +278,11 @@ class acf_updates {
// request
$response = $this->request('v2/plugins/update-check', $post);
// append checked reference
if( is_array($response) ) {
$response['checked'] = $checked;
}
// allow json to include expiration but force minimum and max for safety
$expiration = $this->get_expiration($response, DAY_IN_SECONDS, MONTH_IN_SECONDS);
@ -237,7 +296,7 @@ class acf_updates {
/**
* get_expiration
*
* This function safely gets the expiration value from a response
* This function safely gets the expiration value from a response.
*
* @date 8/7/18
* @since 5.6.9
@ -275,40 +334,29 @@ class acf_updates {
/*
* refresh_plugins_transient
*
* This function will refresh plugin update info to the transient
* Deletes transients and allows a fresh lookup.
*
* @type function
* @date 11/4/17
* @since 5.5.10
*
* @param n/a
* @return n/a
* @param void
* @return void
*/
function refresh_plugins_transient() {
// vars
$transient = get_site_transient('update_plugins');
// bail early if no transient
if( empty($transient) ) return;
// update (will trigger modify function)
$this->force_check = true;
set_site_transient( 'update_plugins', $transient );
delete_site_transient('update_plugins');
delete_transient('acf_plugin_updates');
}
/*
* modify_plugins_transient
*
* This function will connect to the ACF website and find update information
* Called when WP updates the 'update_plugins' site transient. Used to inject ACF plugin update info.
*
* @type function
* @date 16/01/2014
* @since 5.0.0
*
* @param $transient (object)
* @param object $transient
* @return $transient
*/
@ -319,8 +367,11 @@ class acf_updates {
return $transient;
}
// force-check (only once)
$force_check = ($this->checked == 0) ? !empty($_GET['force-check']) : false;
// fetch updates (this filter is called multiple times during a single page load)
$updates = $this->get_plugin_updates();
$updates = $this->get_plugin_updates( $force_check );
// append
if( is_array($updates) ) {
@ -329,23 +380,24 @@ class acf_updates {
}
}
// increase
$this->checked++;
// return
return $transient;
}
/*
* modify_plugin_details
*
* This function will populate the plugin data visible in the 'View details' popup
* Returns the plugin data visible in the 'View details' popup
*
* @type function
* @date 17/01/2014
* @since 5.0.0
*
* @param $result (bool|object)
* @param $action (string)
* @param $args (object)
* @param object $result
* @param string $action
* @param object $args
* @return $result
*/
@ -354,39 +406,25 @@ class acf_updates {
// vars
$plugin = false;
// only for 'plugin_information' action
if( $action !== 'plugin_information' ) return $result;
// find plugin via slug
foreach( $this->plugins as $p ) {
if( $args->slug == $p['slug'] ) $plugin = $p;
}
// bail early if plugin not found
$plugin = $this->get_plugin_by('slug', $args->slug);
if( !$plugin ) return $result;
// connect
$response = $this->get_plugin_info($plugin['id']);
// bail early if no response
if( !is_array($response) ) return $result;
// remove tags (different context)
unset($response['tags']);
// convert to object
$response = (object) $response;
// sections
$sections = array(
'description' => '',
@ -394,21 +432,14 @@ class acf_updates {
'changelog' => '',
'upgrade_notice' => ''
);
foreach( $sections as $k => $v ) {
$sections[ $k ] = $response->$k;
}
$response->sections = $sections;
// return
return $response;
}
}
}
@ -420,49 +451,39 @@ class acf_updates {
*
* Example: <?php $acf_updates = acf_updates(); ?>
*
* @type function
* @date 9/4/17
* @since 5.5.12
*
* @param n/a
* @return (object)
* @param void
* @return object
*/
function acf_updates() {
global $acf_updates;
if( !isset($acf_updates) ) {
$acf_updates = new acf_updates();
$acf_updates = new ACF_Updates();
}
return $acf_updates;
}
/*
* acf_register_plugin_update
*
* alias of acf_updates()->add_plugin()
* Alias of acf_updates()->add_plugin().
*
* @type function
* @date 12/4/17
* @since 5.5.10
*
* @param $post_id (int)
* @return $post_id (int)
* @param array $plugin
* @return void
*/
function acf_register_plugin_update( $plugin ) {
acf_updates()->add_plugin( $plugin );
acf_updates()->add_plugin( $plugin );
}
endif; // class_exists check
?>

View File

@ -5,142 +5,70 @@ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if( ! class_exists('ACF_Walker_Nav_Menu_Edit') ) :
class ACF_Walker_Nav_Menu_Edit extends Walker_Nav_Menu_Edit {
/*
* __construct
*
* This function will setup the class functionality
*
* @type function
* @date 5/03/2014
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
function __construct() {
/**
* Starts the element output.
*
* Calls the Walker_Nav_Menu_Edit start_el function and then injects the custom field HTML
*
* @since 5.0.0
* @since 5.7.2 Added preg_replace based on https://github.com/ineagu/wp-menu-item-custom-fields
*
* @param string $output Used to append additional content (passed by reference).
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $id Current item ID.
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
/* do nothing */
// vars
$item_output = '';
// call parent function
parent::start_el( $item_output, $item, $depth, $args, $id );
// inject custom field HTML
$output .= preg_replace(
// NOTE: Check this regex from time to time!
'/(?=<(fieldset|p)[^>]+class="[^"]*field-move)/',
$this->get_fields( $item, $depth, $args, $id ),
$item_output
);
}
/**
* Start the element output.
* Get custom fields HTML
*
* @see Walker_Nav_Menu::start_el()
* @since 3.0.0
* @since 5.0.0
* @since 5.7.2 Added action based on https://github.com/ineagu/wp-menu-item-custom-fields
*
* @global int $_wp_nav_menu_max_depth
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param array $args Not used.
* @param int $id Not used.
* @param array $args Menu item args.
* @param int $id Nav menu ID.
* @return string
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
// get origional html
$html = '';
parent::start_el( $html, $item, $depth, $args, $id );
// explode at <fieldset>
$search = '<fieldset class="field-move';
$pos = strpos($html, $search);
$before = substr($html, 0, $pos);
$after = substr($html, $pos);
// inject
$html = $before . $this->get_fields($item) . $after;
// append
$output .= $html;
}
/*
* get_fields
*
* description
*
* @type function
* @date 26/5/17
* @since 5.6.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function get_fields( $item ) {
// ob
function get_fields( $item, $depth, $args = array(), $id = 0 ) {
ob_start();
// vars
$prefix = 'menu-item-acf['.$item->ID.']';
$post_id = $item->ID;
// get field groups
$field_groups = acf_get_field_groups(array(
'nav_menu_item' => $item->type
));
// render
if( !empty($field_groups) ) {
echo '<div class="acf-menu-item-fields acf-fields -clear">';
// loop
foreach( $field_groups as $field_group ) {
// load fields
$fields = acf_get_fields( $field_group );
// bail if not fields
if( empty($fields) ) continue;
// change prefix
acf_prefix_fields( $fields, $prefix );
// render
acf_render_fields( $fields, $post_id, 'div', $field_group['instruction_placement'] );
}
echo '</div>';
// Trigger append for newly created menu item (via AJAX)
if( acf_is_ajax('add-menu-item') ): ?>
<script type="text/javascript">
(function($) {
acf.doAction('append', jQuery('#menu-item-settings-<?php echo $post_id; ?>') );
})(jQuery);
</script>
<?php endif;
}
// return
/**
* Get menu item custom fields from plugins/themes
*
* @since 5.7.2
*
* @param int $item_id post ID of menu
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param array $args Menu item args.
* @param int $id Nav menu ID.
*/
do_action( 'wp_nav_menu_item_custom_fields', $item->ID, $item, $depth, $args, $id );
return ob_get_clean();
}
}
}
endif;
?>
?>

Binary file not shown.

View File

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: Advanced Custom Fields Pro v5.2.9\n"
"Report-Msgid-Bugs-To: http://support.advancedcustomfields.com\n"
"POT-Creation-Date: 2018-04-16 17:11+1000\n"
"PO-Revision-Date: 2018-04-30 05:17+0200\n"
"PO-Revision-Date: 2018-07-16 09:34+1000\n"
"Last-Translator: Elliot Condon <e@elliotcondon.com>\n"
"Language-Team: Elliot Condon <e@elliotcondon.com>\n"
"Language: it_IT\n"
@ -11,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 1.8.1\n"
"X-Loco-Target-Locale: it_IT\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
@ -864,7 +864,7 @@ msgstr "Formato"
#: includes/admin/views/field-group-options.php:125
msgid "Page Attributes"
msgstr "Atrributi Pagina"
msgstr "Attributi di Pagina"
#: includes/admin/views/field-group-options.php:126
#: includes/fields/class-acf-field-relationship.php:671
@ -1497,7 +1497,8 @@ msgstr "Relazionale"
msgid "jQuery"
msgstr "jQuery"
#: includes/fields.php:149 includes/fields/class-acf-field-button-group.php:177
#: includes/fields.php:149
#: 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
@ -2787,8 +2788,8 @@ msgstr "Modifica Field Group"
msgid "Validate Email"
msgstr "Valida Email"
#: includes/forms/form-front.php:103 pro/fields/class-acf-field-gallery.php:573
#: pro/options-page.php:81
#: includes/forms/form-front.php:103
#: pro/fields/class-acf-field-gallery.php:573 pro/options-page.php:81
msgid "Update"
msgstr "Aggiorna"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: Advanced Custom Fields Pro v5.2.9\n"
"Report-Msgid-Bugs-To: http://support.advancedcustomfields.com\n"
"POT-Creation-Date: 2017-10-24 23:11+0300\n"
"PO-Revision-Date: 2018-02-06 10:06+1000\n"
"PO-Revision-Date: 2018-07-25 10:10+1000\n"
"Last-Translator: Elliot Condon <e@elliotcondon.com>\n"
"Language-Team: \n"
"Language: ru_RU\n"
@ -1384,7 +1384,7 @@ msgstr "red : Красный"
#: includes/fields/class-acf-field-taxonomy.php:793
#: includes/fields/class-acf-field-user.php:408
msgid "Allow Null?"
msgstr "Разрешить пусто значение?"
msgstr "Разрешить пустое значение?"
#: includes/fields/class-acf-field-button-group.php:168
#: includes/fields/class-acf-field-checkbox.php:375
@ -2151,7 +2151,7 @@ msgstr "Все таксономии"
#: includes/fields/class-acf-field-page_link.php:523
msgid "Allow Archives URLs"
msgstr "Рвзрешить ссылки на архивы"
msgstr "Разрешить ссылки на архивы"
#: includes/fields/class-acf-field-page_link.php:533
#: includes/fields/class-acf-field-post_object.php:422

View File

@ -185,17 +185,13 @@ class acf_admin_settings_updates {
// activate
if( acf_verify_nonce('activate_pro_licence') ) {
$this->activate_pro_licence();
// deactivate
} elseif( acf_verify_nonce('deactivate_pro_licence') ) {
$this->deactivate_pro_licence();
}
// vars
$license = acf_pro_get_license_key();
$this->view = array(
@ -208,23 +204,18 @@ class acf_admin_settings_updates {
'upgrade_notice' => ''
);
// vars
$info = acf_updates()->get_plugin_info('pro');
// get plugin updates
$force_check = !empty( $_GET['force-check'] );
$info = acf_updates()->get_plugin_info('pro', $force_check);
// error
if( is_wp_error($info) ) {
return $this->show_error( $info );
}
// add info to view
$this->view['remote_version'] = $info['version'];
// add changelog if the remote version is '>' than the current version
$version = acf_get_setting('version');
@ -236,50 +227,19 @@ class acf_admin_settings_updates {
$this->view['changelog'] = $this->get_changelog_section($info['changelog'], $info['version']);
$this->view['upgrade_notice'] = $this->get_changelog_section($info['upgrade_notice'], $info['version']);
// refresh transient
// - avoids new version not available in plugin update list
// - only request if license is active
// refresh transient if:
// a) A license is active (can get update)
// b) No update exists, or the update version is stale
$basename = acf_get_setting('basename');
$update = acf_updates()->get_plugin_update( $basename );
if( $license ) {
$this->refresh_plugins_transient();
if( !$update || $update['new_version'] !== $info['version'] ) {
acf_updates()->refresh_plugins_transient();
}
}
}
}
/**
* refresh_plugins_transient
*
* Checks the site transient 'update_plugins' and compares the cached new_version against the plugin-info version.
* If the cached version is older, a new version is available, and the transient is refreshed.
*
* @date 12/7/18
* @since 5.6.9
*
* @param void
* @return void
*/
function refresh_plugins_transient() {
// vars
$remote_version = $this->view['remote_version'];
$basename = acf_get_setting('basename');
$transient = get_site_transient('update_plugins');
$transient_version = 0;
// get transient version
if( isset($transient->response[ $basename ]->new_version) ) {
$transient_version = $transient->response[ $basename ]->new_version;
}
// return true if a newer $remote_version exists
if( acf_version_compare($remote_version, '>', $transient_version) ) {
acf_updates()->refresh_plugins_transient();
}
}
/*
* activate_pro_licence
*

View File

@ -123,7 +123,7 @@
// disable clone
acf.disable( this.$clone(), this.cid );
// render
this.render();
},
@ -200,33 +200,34 @@
return false;
}
// vars
var $clone = this.$clone();
// defaults
args = acf.parseArgs(args, {
before: $clone
before: false
});
// add row
var $el = acf.duplicate({
target: $clone,
append: function( $el, $el2 ){
target: this.$clone(),
append: this.proxy(function( $el, $el2 ){
// append
if( args.before ) {
args.before.before( $el2 );
} else {
$el.before( $el2 );
}
// remove clone class
$el2.removeClass('acf-clone');
// append
args.before.before( $el2 );
}
// enable
acf.enable( $el2, this.cid );
// render
this.render();
})
});
// enable
acf.enable_form( $el, this.cid );
// update order
this.render();
// trigger change for validation errors
this.$input().trigger('change');
@ -336,7 +337,7 @@
}
},
onShow: function( e, context ){
onShow: function( e, $el, context ){
// get sub fields
var fields = acf.getFields({
@ -670,7 +671,7 @@
}
},
onShow: function( e, context ){
onShow: function( e, $el, context ){
// get sub fields
var fields = acf.getFields({
@ -764,9 +765,6 @@
before: false
});
// append
args.append = this.$layoutsWrap();
// validate
if( !this.allowAdd() ) {
return false;
@ -775,22 +773,23 @@
// add row
var $el = acf.duplicate({
target: this.$clone( args.layout ),
append: function( $el, $el2 ){
append: this.proxy(function( $el, $el2 ){
// append
if( args.before ) {
args.before.before( $el2 );
} else {
args.append.append( $el2 );
this.$layoutsWrap().append( $el2 );
}
}
// enable
acf.enable( $el2, this.cid );
// render
this.render();
})
});
// enable
acf.enable_form( $el, this.cid );
// update order
this.render();
// trigger change for validation errors
this.$input().trigger('change');

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
=== Advanced Custom Fields Pro ===
Contributors: elliotcondon
Tags: acf, advanced, custom, field, fields, form, repeater, content
Requires at least: 3.6.0
Requires at least: 4.4.0
Tested up to: 4.9.9
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@ -66,6 +66,23 @@ From your WordPress dashboard
== Changelog ==
= 5.7.2 =
*Release Date - 6 August 2018*
* Fix - Fixed bug preventing the Google Maps Field address from being customised.
* Fix - Improved logic to request and cache plugin update information.
* Fix - Fixed bug preventing JS initialization when editing widgets in accessibility mode.
* Fix - Added missing $parent argument to term_exists() function when adding a new term via taxonomy field popup.
* Fix - Fixed bug where nested Group Fields did not delete their values.
* Fix - Fixed JS error thrown by localStorage if cookies are not enabled.
* Dev - Bumped minimum WP version requirement to 4.4.
* Dev - Added action 'wp_nav_menu_item_custom_fields' for compatibility with other plugins modifying the menu walker class.
* Dev - Added 'multiple' to the allowed attributes for an email field.
* Dev - Added new ACF_Ajax class for upcoming features.
= 5.7.1 =
* Core: Minor fixes and improvements
= 5.7.0 =
* Core: Major JavaScript updates
* Core: Improved conditional logic with new types and more supported fields