initial commit

This commit is contained in:
2024-04-29 13:12:44 +05:45
commit 34887303c5
19300 changed files with 5268802 additions and 0 deletions

View File

@ -0,0 +1,820 @@
<?php
/*
* ACF Admin Field Group Class
*
* All the logic for editing a field group
*
* @class acf_admin_field_group
* @package ACF
* @subpackage Admin
*/
if ( ! class_exists( 'acf_admin_field_group' ) ) :
class acf_admin_field_group {
/*
* __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() {
// actions
add_action( 'current_screen', array( $this, 'current_screen' ) );
add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
// ajax
add_action( 'wp_ajax_acf/field_group/render_field_settings', array( $this, 'ajax_render_field_settings' ) );
add_action( 'wp_ajax_acf/field_group/render_location_rule', array( $this, 'ajax_render_location_rule' ) );
add_action( 'wp_ajax_acf/field_group/move_field', array( $this, 'ajax_move_field' ) );
// filters
add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) );
add_filter( 'use_block_editor_for_post_type', array( $this, 'use_block_editor_for_post_type' ), 10, 2 );
}
/**
* use_block_editor_for_post_type
*
* Prevents the block editor from loading when editing an ACF field group.
*
* @date 7/12/18
* @since 5.8.0
*
* @param bool $use_block_editor Whether the post type can be edited or not. Default true.
* @param string $post_type The post type being checked.
* @return bool
*/
function use_block_editor_for_post_type( $use_block_editor, $post_type ) {
if ( $post_type === 'acf-field-group' ) {
return false;
}
return $use_block_editor;
}
/*
* post_updated_messages
*
* This function will customize the message shown when editing a field group
*
* @type action (post_updated_messages)
* @date 30/04/2014
* @since 5.0.0
*
* @param $messages (array)
* @return $messages
*/
function post_updated_messages( $messages ) {
// append to messages
$messages['acf-field-group'] = array(
0 => '', // Unused. Messages start at index 1.
1 => __( 'Field group updated.', 'acf' ),
2 => __( 'Field group updated.', 'acf' ),
3 => __( 'Field group deleted.', 'acf' ),
4 => __( 'Field group updated.', 'acf' ),
5 => false, // field group does not support revisions
6 => __( 'Field group published.', 'acf' ),
7 => __( 'Field group saved.', 'acf' ),
8 => __( 'Field group submitted.', 'acf' ),
9 => __( 'Field group scheduled for.', 'acf' ),
10 => __( 'Field group draft updated.', 'acf' ),
);
// return
return $messages;
}
/*
* current_screen
*
* This function is fired when loading the admin page before HTML has been rendered.
*
* @type action (current_screen)
* @date 21/07/2014
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
function current_screen() {
// validate screen
if ( ! acf_is_screen( 'acf-field-group' ) ) {
return;
}
// disable filters to ensure ACF loads raw data from DB
acf_disable_filters();
// enqueue scripts
acf_enqueue_scripts();
// actions
add_action( 'acf/input/admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
add_action( 'acf/input/admin_head', array( $this, 'admin_head' ) );
add_action( 'acf/input/form_data', array( $this, 'form_data' ) );
add_action( 'acf/input/admin_footer', array( $this, 'admin_footer' ) );
// filters
add_filter( 'acf/input/admin_l10n', array( $this, 'admin_l10n' ) );
}
/*
* admin_enqueue_scripts
*
* This action is run after post query but before any admin script / head actions.
* It is a good place to register all actions.
*
* @type action (admin_enqueue_scripts)
* @date 30/06/2014
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
function admin_enqueue_scripts() {
// no autosave
wp_dequeue_script( 'autosave' );
// custom scripts
wp_enqueue_style( 'acf-field-group' );
wp_enqueue_script( 'acf-field-group' );
// localize text
acf_localize_text(
array(
'The string "field_" may not be used at the start of a field name' => __( 'The string "field_" may not be used at the start of a field name', 'acf' ),
'This field cannot be moved until its changes have been saved' => __( 'This field cannot be moved until its changes have been saved', 'acf' ),
'Field group title is required' => __( 'Field group title is required', 'acf' ),
'Move to trash. Are you sure?' => __( 'Move to trash. Are you sure?', 'acf' ),
'No toggle fields available' => __( 'No toggle fields available', 'acf' ),
'Move Custom Field' => __( 'Move Custom Field', 'acf' ),
'Checked' => __( 'Checked', 'acf' ),
'(no label)' => __( '(no label)', 'acf' ),
'(this field)' => __( '(this field)', 'acf' ),
'copy' => __( 'copy', 'acf' ),
'or' => __( 'or', 'acf' ),
'Show this field group if' => __( 'Show this field group if', 'acf' ),
'Null' => __( 'Null', 'acf' ),
// Conditions
'Has any value' => __( 'Has any value', 'acf' ),
'Has no value' => __( 'Has no value', 'acf' ),
'Value is equal to' => __( 'Value is equal to', 'acf' ),
'Value is not equal to' => __( 'Value is not equal to', 'acf' ),
'Value matches pattern' => __( 'Value matches pattern', 'acf' ),
'Value contains' => __( 'Value contains', 'acf' ),
'Value is greater than' => __( 'Value is greater than', 'acf' ),
'Value is less than' => __( 'Value is less than', 'acf' ),
'Selection is greater than' => __( 'Selection is greater than', 'acf' ),
'Selection is less than' => __( 'Selection is less than', 'acf' ),
// Pro-only fields
'Repeater (Pro only)' => __( 'Repeater (Pro only)', 'acf' ),
'Flexibly Content (Pro only)' => __( 'Flexible Content (Pro only)', 'acf' ),
'Clone (Pro only)' => __( 'Clone (Pro only)', 'acf' ),
'Gallery (Pro only)' => __( 'Gallery (Pro only)', 'acf' ),
)
);
// localize data
acf_localize_data(
array(
'fieldTypes' => acf_get_field_types_info(),
)
);
// 3rd party hook
do_action( 'acf/field_group/admin_enqueue_scripts' );
}
/*
* admin_head
*
* This function will setup all functionality for the field group edit page to work
*
* @type action (admin_head)
* @date 23/06/12
* @since 3.1.8
*
* @param $post_id (int)
* @return $post_id (int)
*/
function admin_head() {
// global
global $post, $field_group;
// set global var
$field_group = acf_get_field_group( $post->ID );
// metaboxes
add_meta_box( 'acf-field-group-fields', __( 'Fields', 'acf' ), array( $this, 'mb_fields' ), 'acf-field-group', 'normal', 'high' );
add_meta_box( 'acf-field-group-locations', __( 'Location', 'acf' ), array( $this, 'mb_locations' ), 'acf-field-group', 'normal', 'high' );
add_meta_box( 'acf-field-group-options', __( 'Settings', 'acf' ), array( $this, 'mb_options' ), 'acf-field-group', 'normal', 'high' );
// actions
add_action( 'post_submitbox_misc_actions', array( $this, 'post_submitbox_misc_actions' ), 10, 0 );
add_action( 'edit_form_after_title', array( $this, 'edit_form_after_title' ), 10, 0 );
// filters
add_filter( 'screen_settings', array( $this, 'screen_settings' ), 10, 1 );
// 3rd party hook
do_action( 'acf/field_group/admin_head' );
}
/*
* edit_form_after_title
*
* This action will allow ACF to render metaboxes after the title
*
* @type action
* @date 17/08/13
*
* @param n/a
* @return n/a
*/
function edit_form_after_title() {
// globals
global $post;
// render post data
acf_form_data(
array(
'screen' => 'field_group',
'post_id' => $post->ID,
'delete_fields' => 0,
'validation' => 0,
)
);
}
/*
* form_data
*
* This function will add extra HTML to the acf form data element
*
* @type function
* @date 31/05/2016
* @since 5.3.8
*
* @param n/a
* @return n/a
*/
function form_data( $args ) {
// do action
do_action( 'acf/field_group/form_data', $args );
}
/*
* admin_l10n
*
* This function will append extra l10n strings to the acf JS object
*
* @type function
* @date 31/05/2016
* @since 5.3.8
*
* @param $l10n (array)
* @return $l10n
*/
function admin_l10n( $l10n ) {
return apply_filters( 'acf/field_group/admin_l10n', $l10n );
}
/*
* admin_footer
*
* description
*
* @type function
* @date 11/01/2016
* @since 5.3.2
*
* @param $post_id (int)
* @return $post_id (int)
*/
function admin_footer() {
// 3rd party hook
do_action( 'acf/field_group/admin_footer' );
}
/*
* screen_settings
*
* description
*
* @type function
* @date 26/01/13
* @since 3.6.0
*
* @param $current (string)
* @return $current
*/
function screen_settings( $html ) {
// vars
$checked = acf_get_user_setting( 'show_field_keys' ) ? 'checked="checked"' : '';
// append
$html .= '<div id="acf-append-show-on-screen" class="acf-hidden">';
$html .= '<label for="acf-field-key-hide"><input id="acf-field-key-hide" type="checkbox" value="1" name="show_field_keys" ' . $checked . ' /> ' . __( 'Field Keys', 'acf' ) . '</label>';
$html .= '</div>';
// return
return $html;
}
/*
* post_submitbox_misc_actions
*
* This function will customize the publish metabox
*
* @type function
* @date 17/07/2015
* @since 5.2.9
*
* @param n/a
* @return n/a
*/
function post_submitbox_misc_actions() {
global $field_group;
$status_label = $field_group['active'] ? _x( 'Active', 'post status', 'acf' ) : _x( 'Disabled', 'post status', 'acf' );
?>
<script type="text/javascript">
(function($) {
$('#post-status-display').html( '<?php echo esc_html( $status_label ); ?>' );
})(jQuery);
</script>
<?php
}
/*
* save_post
*
* This function will save all the field group data
*
* @type function
* @date 23/06/12
* @since 1.0.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function save_post( $post_id, $post ) {
// do not save if this is an auto save routine
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// bail early if not acf-field-group
if ( $post->post_type !== 'acf-field-group' ) {
return $post_id;
}
// only save once! WordPress save's a revision as well.
if ( wp_is_post_revision( $post_id ) ) {
return $post_id;
}
// verify nonce
if ( ! acf_verify_nonce( 'field_group' ) ) {
return $post_id;
}
// Bail early if request came from an unauthorised user.
if ( ! current_user_can( acf_get_setting( 'capability' ) ) ) {
return $post_id;
}
// disable filters to ensure ACF loads raw data from DB
acf_disable_filters();
// save fields
if ( ! empty( $_POST['acf_fields'] ) ) {
// loop
foreach ( $_POST['acf_fields'] as $field ) {
// vars
$specific = false;
$save = acf_extract_var( $field, 'save' );
// only saved field if has changed
if ( $save == 'meta' ) {
$specific = array(
'menu_order',
'post_parent',
);
}
// set parent
if ( ! $field['parent'] ) {
$field['parent'] = $post_id;
}
// save field
acf_update_field( $field, $specific );
}
}
// delete fields
if ( $_POST['_acf_delete_fields'] ) {
// clean
$ids = explode( '|', $_POST['_acf_delete_fields'] );
$ids = array_map( 'intval', $ids );
// loop
foreach ( $ids as $id ) {
// bai early if no id
if ( ! $id ) {
continue;
}
// delete
acf_delete_field( $id );
}
}
// add args
$_POST['acf_field_group']['ID'] = $post_id;
$_POST['acf_field_group']['title'] = $_POST['post_title'];
// save field group
acf_update_field_group( $_POST['acf_field_group'] );
// return
return $post_id;
}
/*
* mb_fields
*
* This function will render the HTML for the medtabox 'acf-field-group-fields'
*
* @type function
* @date 28/09/13
* @since 5.0.0
*
* @param N/A
* @return N/A
*/
function mb_fields() {
// global
global $field_group;
// get fields
$view = array(
'fields' => acf_get_fields( $field_group ),
'parent' => 0,
);
// load view
acf_get_view( 'field-group-fields', $view );
}
/*
* mb_options
*
* This function will render the HTML for the medtabox 'acf-field-group-options'
*
* @type function
* @date 28/09/13
* @since 5.0.0
*
* @param N/A
* @return N/A
*/
function mb_options() {
// global
global $field_group;
// field key (leave in for compatibility)
if ( ! acf_is_field_group_key( $field_group['key'] ) ) {
$field_group['key'] = uniqid( 'group_' );
}
// view
acf_get_view( 'field-group-options' );
}
/*
* mb_locations
*
* This function will render the HTML for the medtabox 'acf-field-group-locations'
*
* @type function
* @date 28/09/13
* @since 5.0.0
*
* @param N/A
* @return N/A
*/
function mb_locations() {
// global
global $field_group;
// UI needs at lease 1 location rule
if ( empty( $field_group['location'] ) ) {
$field_group['location'] = array(
// group 0
array(
// rule 0
array(
'param' => 'post_type',
'operator' => '==',
'value' => 'post',
),
),
);
}
// view
acf_get_view( 'field-group-locations' );
}
/*
* ajax_render_location_rule
*
* This function can be accessed via an AJAX action and will return the result from the render_location_value function
*
* @type function (ajax)
* @date 30/09/13
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
function ajax_render_location_rule() {
// validate
if ( ! acf_verify_ajax() ) {
die();
}
// verify user capability
if ( ! acf_current_user_can_admin() ) {
die();
}
// validate rule
$rule = acf_validate_location_rule( $_POST['rule'] );
// view
acf_get_view(
'html-location-rule',
array(
'rule' => $rule,
)
);
// die
die();
}
/*
* ajax_render_field_settings
*
* This function will return HTML containing the field's settings based on it's new type
*
* @type function (ajax)
* @date 30/09/13
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
function ajax_render_field_settings() {
// validate
if ( ! acf_verify_ajax() ) {
die();
}
// verify user capability
if ( ! acf_current_user_can_admin() ) {
die();
}
// vars
$field = acf_maybe_get_POST( 'field' );
// check
if ( ! $field ) {
die();
}
// set prefix
$field['prefix'] = acf_maybe_get_POST( 'prefix' );
// validate
$field = acf_get_valid_field( $field );
// render
do_action( "acf/render_field_settings/type={$field['type']}", $field );
// return
die();
}
/*
* ajax_move_field
*
* description
*
* @type function
* @date 20/01/2014
* @since 5.0.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
function ajax_move_field() {
// disable filters to ensure ACF loads raw data from DB
acf_disable_filters();
$args = acf_parse_args(
$_POST,
array(
'nonce' => '',
'post_id' => 0,
'field_id' => 0,
'field_group_id' => 0,
)
);
// verify nonce
if ( ! wp_verify_nonce( $args['nonce'], 'acf_nonce' ) ) {
die();
}
// verify user capability
if ( ! acf_current_user_can_admin() ) {
die();
}
// confirm?
if ( $args['field_id'] && $args['field_group_id'] ) {
// vars
$field = acf_get_field( $args['field_id'] );
$field_group = acf_get_field_group( $args['field_group_id'] );
// update parent
$field['parent'] = $field_group['ID'];
// remove conditional logic
$field['conditional_logic'] = 0;
// update field
acf_update_field( $field );
// Output HTML.
$link = '<a href="' . admin_url( 'post.php?post=' . $field_group['ID'] . '&action=edit' ) . '" target="_blank">' . esc_html( $field_group['title'] ) . '</a>';
echo '' .
'<p><strong>' . __( 'Move Complete.', 'acf' ) . '</strong></p>' .
'<p>' . sprintf(
acf_punctify( __( 'The %1$s field can now be found in the %2$s field group', 'acf' ) ),
esc_html( $field['label'] ),
$link
) . '</p>' .
'<a href="#" class="button button-primary acf-close-popup">' . __( 'Close Window', 'acf' ) . '</a>';
die();
}
// get all field groups
$field_groups = acf_get_field_groups();
$choices = array();
// check
if ( ! empty( $field_groups ) ) {
// loop
foreach ( $field_groups as $field_group ) {
// bail early if no ID
if ( ! $field_group['ID'] ) {
continue;
}
// bail ealry if is current
if ( $field_group['ID'] == $args['post_id'] ) {
continue;
}
// append
$choices[ $field_group['ID'] ] = $field_group['title'];
}
}
// render options
$field = acf_get_valid_field(
array(
'type' => 'select',
'name' => 'acf_field_group',
'choices' => $choices,
)
);
echo '<p>' . __( 'Please select the destination for this field', 'acf' ) . '</p>';
echo '<form id="acf-move-field-form">';
// render
acf_render_field_wrap( $field );
echo '<button type="submit" class="button button-primary">' . __( 'Move Field', 'acf' ) . '</button>';
echo '</form>';
// die
die();
}
}
// initialize
new acf_admin_field_group();
endif;
?>

View File

@ -0,0 +1,885 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'ACF_Admin_Field_Groups' ) ) :
class ACF_Admin_Field_Groups {
/**
* Array of field groups availbale for sync.
*
* @since 5.9.0
* @var array
*/
public $sync = array();
/**
* The current view (post_status).
*
* @since 5.9.0
* @var string
*/
public $view = '';
/**
* Constructor.
*
* @date 5/03/2014
* @since 5.0.0
*
* @param void
* @return void
*/
public function __construct() {
// Add hooks.
add_action( 'load-edit.php', array( $this, 'handle_redirection' ) );
add_action( 'current_screen', array( $this, 'current_screen' ) );
// Handle post status change events.
add_action( 'trashed_post', array( $this, 'trashed_post' ) );
add_action( 'untrashed_post', array( $this, 'untrashed_post' ) );
add_action( 'deleted_post', array( $this, 'deleted_post' ) );
}
/**
* Returns the Field Groups admin URL.
*
* @date 27/3/20
* @since 5.9.0
*
* @param string $params Extra URL params.
* @return string
*/
public function get_admin_url( $params = '' ) {
return admin_url( "edit.php?post_type=acf-field-group{$params}" );
}
/**
* Returns the Field Groups admin URL taking into account the current view.
*
* @date 27/3/20
* @since 5.9.0
*
* @param string $params Extra URL params.
* @return string
*/
public function get_current_admin_url( $params = '' ) {
return $this->get_admin_url( ( $this->view ? '&post_status=' . $this->view : '' ) . $params );
}
/**
* Redirects users from ACF 4.0 admin page.
*
* @date 17/9/18
* @since 5.7.6
*
* @param void
* @return void
*/
public function handle_redirection() {
if ( isset( $_GET['post_type'] ) && $_GET['post_type'] === 'acf' ) {
wp_redirect( $this->get_admin_url() );
exit;
}
}
/**
* Constructor for the Field Groups admin page.
*
* @date 21/07/2014
* @since 5.0.0
*
* @param void
* @return void
*/
public function current_screen() {
// Bail early if not Field Groups admin page.
if ( ! acf_is_screen( 'edit-acf-field-group' ) ) {
return;
}
// Get the current view.
$this->view = isset( $_GET['post_status'] ) ? sanitize_text_field( $_GET['post_status'] ) : '';
// Setup and check for custom actions..
$this->setup_sync();
$this->check_sync();
$this->check_duplicate();
// Modify publish post status text and order.
global $wp_post_statuses;
$wp_post_statuses['publish']->label_count = _n_noop( 'Active <span class="count">(%s)</span>', 'Active <span class="count">(%s)</span>', 'acf' );
$wp_post_statuses['trash'] = acf_extract_var( $wp_post_statuses, 'trash' );
// Add hooks.
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
add_action( 'admin_body_class', array( $this, 'admin_body_class' ) );
add_filter( 'views_edit-acf-field-group', array( $this, 'admin_table_views' ), 10, 1 );
add_filter( 'manage_acf-field-group_posts_columns', array( $this, 'admin_table_columns' ), 10, 1 );
add_action( 'manage_acf-field-group_posts_custom_column', array( $this, 'admin_table_columns_html' ), 10, 2 );
add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 );
add_filter( 'bulk_actions-edit-acf-field-group', array( $this, 'admin_table_bulk_actions' ), 10, 1 );
add_action( 'admin_footer', array( $this, 'admin_footer' ), 1 );
if ( $this->view !== 'trash' ) {
add_filter( 'page_row_actions', array( $this, 'page_row_actions' ), 10, 2 );
}
// Add hooks for "sync" view.
if ( $this->view === 'sync' ) {
add_action( 'admin_footer', array( $this, 'admin_footer__sync' ), 1 );
}
}
/**
* Sets up the field groups ready for sync.
*
* @date 17/4/20
* @since 5.9.0
*
* @param void
* @return void
*/
public function setup_sync() {
// Review local json field groups.
if ( acf_get_local_json_files() ) {
// Get all groups in a single cached query to check if sync is available.
$all_field_groups = acf_get_field_groups();
foreach ( $all_field_groups as $field_group ) {
// Extract vars.
$local = acf_maybe_get( $field_group, 'local' );
$modified = acf_maybe_get( $field_group, 'modified' );
$private = acf_maybe_get( $field_group, 'private' );
// Ignore if is private.
if ( $private ) {
continue;
// Ignore not local "json".
} elseif ( $local !== 'json' ) {
continue;
// Append to sync if not yet in database.
} elseif ( ! $field_group['ID'] ) {
$this->sync[ $field_group['key'] ] = $field_group;
// Append to sync if "json" modified time is newer than database.
} elseif ( $modified && $modified > get_post_modified_time( 'U', true, $field_group['ID'] ) ) {
$this->sync[ $field_group['key'] ] = $field_group;
}
}
}
}
/**
* Enqueues admin scripts.
*
* @date 18/4/20
* @since 5.9.0
*
* @param void
* @return void
*/
public function admin_enqueue_scripts() {
acf_enqueue_script( 'acf' );
// Localize text.
acf_localize_text(
array(
'Review local JSON changes' => __( 'Review local JSON changes', 'acf' ),
'Loading diff' => __( 'Loading diff', 'acf' ),
'Sync changes' => __( 'Sync changes', 'acf' ),
)
);
}
/**
* Modifies the admin body class.
*
* @date 18/4/20
* @since 5.9.0
*
* @param string $classes Space-separated list of CSS classes.
* @return string
*/
public function admin_body_class( $classes ) {
$classes .= ' acf-admin-field-groups';
if ( $this->view ) {
$classes .= " view-{$this->view}";
}
return $classes;
}
/**
* returns the disabled post state HTML.
*
* @date 17/4/20
* @since 5.9.0
*
* @param void
* @return string
*/
public function get_disabled_post_state() {
return '<span class="dashicons dashicons-hidden"></span> ' . _x( 'Disabled', 'post status', 'acf' );
}
/**
* Adds the "disabled" post state for the admin table title.
*
* @date 1/4/20
* @since 5.9.0
*
* @param array $post_states An array of post display states.
* @param WP_Post $post The current post object.
* @return array
*/
public function display_post_states( $post_states, $post ) {
if ( $post->post_status === 'acf-disabled' ) {
$post_states['acf-disabled'] = $this->get_disabled_post_state();
}
return $post_states;
}
/**
* Customizes the admin table columns.
*
* @date 1/4/20
* @since 5.9.0
*
* @param array $columns The columns array.
* @return array
*/
public function admin_table_columns( $_columns ) {
$columns = array(
'cb' => $_columns['cb'],
'title' => $_columns['title'],
'acf-description' => __( 'Description', 'acf' ),
'acf-key' => __( 'Key', 'acf' ),
'acf-location' => __( 'Location', 'acf' ),
'acf-count' => __( 'Fields', 'acf' ),
);
if ( acf_get_local_json_files() ) {
$columns['acf-json'] = __( 'Local JSON', 'acf' );
}
return $columns;
}
/**
* Renders the admin table column HTML
*
* @date 1/4/20
* @since 5.9.0
*
* @param string $column_name The name of the column to display.
* @param int $post_id The current post ID.
* @return void
*/
public function admin_table_columns_html( $column_name, $post_id ) {
$field_group = acf_get_field_group( $post_id );
if ( $field_group ) {
$this->render_admin_table_column( $column_name, $field_group );
}
}
/**
* Renders a specific admin table column.
*
* @date 17/4/20
* @since 5.9.0
*
* @param string $column_name The name of the column to display.
* @param array $field_group The field group.
* @return void
*/
public function render_admin_table_column( $column_name, $field_group ) {
switch ( $column_name ) {
// Key.
case 'acf-key':
echo esc_html( $field_group['key'] );
break;
// Description.
case 'acf-description':
if ( $field_group['description'] ) {
echo '<span class="acf-description">' . acf_esc_html( $field_group['description'] ) . '</span>';
}
break;
// Location.
case 'acf-location':
$this->render_admin_table_column_locations( $field_group );
break;
// Count.
case 'acf-count':
echo esc_html( acf_get_field_count( $field_group ) );
break;
// Local JSON.
case 'acf-json':
$this->render_admin_table_column_local_status( $field_group );
break;
}
}
/**
* Displays a visual representation of the field group's locations.
*
* @date 1/4/20
* @since 5.9.0
*
* @param array $field_group The field group.
* @return void
*/
public function render_admin_table_column_locations( $field_group ) {
$objects = array();
// Loop over location rules and determine connected object types.
if ( $field_group['location'] ) {
foreach ( $field_group['location'] as $i => $rules ) {
// Determine object types for each rule.
foreach ( $rules as $j => $rule ) {
// Get location type and subtype for the current rule.
$location = acf_get_location_rule( $rule['param'] );
$location_object_type = '';
$location_object_subtype = '';
if ( $location ) {
$location_object_type = $location->get_object_type( $rule );
$location_object_subtype = $location->get_object_subtype( $rule );
}
$rules[ $j ]['object_type'] = $location_object_type;
$rules[ $j ]['object_subtype'] = $location_object_subtype;
}
// Now that each $rule conains object type data...
$object_types = array_column( $rules, 'object_type' );
$object_types = array_filter( $object_types );
$object_types = array_values( $object_types );
if ( $object_types ) {
$object_type = $object_types[0];
} else {
continue;
}
$object_subtypes = array_column( $rules, 'object_subtype' );
$object_subtypes = array_filter( $object_subtypes );
$object_subtypes = array_values( $object_subtypes );
$object_subtypes = array_map( 'acf_array', $object_subtypes );
if ( count( $object_subtypes ) > 1 ) {
$object_subtypes = call_user_func_array( 'array_intersect', $object_subtypes );
$object_subtypes = array_values( $object_subtypes );
} elseif ( $object_subtypes ) {
$object_subtypes = $object_subtypes[0];
} else {
$object_subtypes = array( '' );
}
// Append to objects.
foreach ( $object_subtypes as $object_subtype ) {
$object = acf_get_object_type( $object_type, $object_subtype );
if ( $object ) {
$objects[ $object->name ] = $object;
}
}
}
}
// Reset keys.
$objects = array_values( $objects );
// Display.
$html = '';
if ( $objects ) {
$limit = 3;
$total = count( $objects );
// Icon.
$html .= '<span class="dashicons ' . $objects[0]->icon . ( $total > 1 ? ' acf-multi-dashicon' : '' ) . '"></span> ';
// Labels.
$labels = array_column( $objects, 'label' );
$labels = array_slice( $labels, 0, 3 );
$html .= implode( ', ', $labels );
// More.
if ( $total > $limit ) {
$html .= ', ...';
}
} else {
$html = '<span class="dashicons dashicons-businesswoman"></span> ' . __( 'Various', 'acf' );
}
// Filter.
echo acf_esc_html( $html );
}
/**
* Returns a human readable file location.
*
* @date 17/4/20
* @since 5.9.0
*
* @param string $file The full file path.
* @return string
*/
public function get_human_readable_file_location( $file ) {
// Generate friendly file path.
$theme_path = get_stylesheet_directory();
if ( strpos( $file, $theme_path ) !== false ) {
$rel_file = str_replace( $theme_path, '', $file );
$located = sprintf( __( 'Located in theme: %s', 'acf' ), $rel_file );
} elseif ( strpos( $file, WP_PLUGIN_DIR ) !== false ) {
$rel_file = str_replace( WP_PLUGIN_DIR, '', $file );
$located = sprintf( __( 'Located in plugin: %s', 'acf' ), $rel_file );
} else {
$rel_file = str_replace( ABSPATH, '', $file );
$located = sprintf( __( 'Located in: %s', 'acf' ), $rel_file );
}
return $located;
}
/**
* Displays the local JSON status of a field group.
*
* @date 14/4/20
* @since 5.9.0
*
* @param type $var Description. Default.
* @return type Description.
*/
public function render_admin_table_column_local_status( $field_group ) {
$json = acf_get_local_json_files();
if ( isset( $json[ $field_group['key'] ] ) ) {
$file = $json[ $field_group['key'] ];
if ( isset( $this->sync[ $field_group['key'] ] ) ) {
$url = $this->get_admin_url( '&acfsync=' . $field_group['key'] . '&_wpnonce=' . wp_create_nonce( 'bulk-posts' ) );
echo '<strong>' . __( 'Sync available', 'acf' ) . '</strong>';
if ( $field_group['ID'] ) {
echo '<div class="row-actions">
<span class="sync"><a href="' . esc_url( $url ) . '">' . __( 'Sync', 'acf' ) . '</a> | </span>
<span class="review"><a href="#" data-event="review-sync" data-id="' . esc_attr( $field_group['ID'] ) . '" data-href="' . esc_url( $url ) . '">' . __( 'Review changes', 'acf' ) . '</a></span>
</div>';
} else {
echo '<div class="row-actions">
<span class="sync"><a href="' . esc_url( $url ) . '">' . __( 'Import', 'acf' ) . '</a></span>
</div>';
}
} else {
echo __( 'Saved', 'acf' );
}
} else {
echo '<span class="acf-secondary-text">' . __( 'Awaiting save', 'acf' ) . '</span>';
}
}
/**
* Customizes the page row actions visible on hover.
*
* @date 14/4/20
* @since 5.9.0
*
* @param array $actions The array of actions HTML.
* @param WP_Post $post The post.
* @return array
*/
public function page_row_actions( $actions, $post ) {
// Remove "Quick Edit" action.
unset( $actions['inline'], $actions['inline hide-if-no-js'] );
// Append "Duplicate" action.
$duplicate_action_url = $this->get_admin_url( '&acfduplicate=' . $post->ID . '&_wpnonce=' . wp_create_nonce( 'bulk-posts' ) );
$actions['acfduplicate'] = '<a href="' . esc_url( $duplicate_action_url ) . '" aria-label="' . esc_attr__( 'Duplicate this item', 'acf' ) . '">' . __( 'Duplicate', 'acf' ) . '</a>';
// Return actions in custom order.
$order = array( 'edit', 'acfduplicate', 'trash' );
return array_merge( array_flip( $order ), $actions );
}
/**
* Modifies the admin table bulk actions dropdown.
*
* @date 15/4/20
* @since 5.9.0
*
* @param array $actions The actions array.
* @return array
*/
public function admin_table_bulk_actions( $actions ) {
// Add "duplicate" action.
if ( $this->view !== 'sync' ) {
$actions['acfduplicate'] = __( 'Duplicate', 'acf' );
}
// Add "Sync" action.
if ( $this->sync ) {
if ( $this->view === 'sync' ) {
$actions = array();
}
$actions['acfsync'] = __( 'Sync changes', 'acf' );
}
return $actions;
}
/**
* Checks for the custom "duplicate" action.
*
* @date 15/4/20
* @since 5.9.0
*
* @param void
* @return void
*/
public function check_duplicate() {
// Display notice on success redirect.
if ( isset( $_GET['acfduplicatecomplete'] ) ) {
$ids = array_map( 'intval', explode( ',', $_GET['acfduplicatecomplete'] ) );
// Generate text.
$text = sprintf(
_n( 'Field group duplicated.', '%s field groups duplicated.', count( $ids ), 'acf' ),
count( $ids )
);
// Append 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' );
return;
}
// Find items to duplicate.
$ids = array();
if ( isset( $_GET['acfduplicate'] ) ) {
$ids[] = intval( $_GET['acfduplicate'] );
} elseif ( isset( $_GET['post'], $_GET['action2'] ) && $_GET['action2'] === 'acfduplicate' ) {
$ids = array_map( 'intval', $_GET['post'] );
}
if ( $ids ) {
check_admin_referer( 'bulk-posts' );
// Duplicate field groups and generate array of new IDs.
$new_ids = array();
foreach ( $ids as $id ) {
$field_group = acf_duplicate_field_group( $id );
$new_ids[] = $field_group['ID'];
}
// Redirect.
wp_redirect( $this->get_admin_url( '&acfduplicatecomplete=' . implode( ',', $new_ids ) ) );
exit;
}
}
/**
* Checks for the custom "acfsync" action.
*
* @date 15/4/20
* @since 5.9.0
*
* @param void
* @return void
*/
public function check_sync() {
// Display notice on success redirect.
if ( isset( $_GET['acfsynccomplete'] ) ) {
$ids = array_map( 'intval', explode( ',', $_GET['acfsynccomplete'] ) );
// Generate text.
$text = sprintf(
_n( 'Field group synchronised.', '%s field groups synchronised.', count( $ids ), 'acf' ),
count( $ids )
);
// Append 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' );
return;
}
// Find items to sync.
$keys = array();
if ( isset( $_GET['acfsync'] ) ) {
$keys[] = sanitize_text_field( $_GET['acfsync'] );
} elseif ( isset( $_GET['post'], $_GET['action2'] ) && $_GET['action2'] === 'acfsync' ) {
$keys = array_map( 'sanitize_text_field', $_GET['post'] );
}
if ( $keys && $this->sync ) {
check_admin_referer( 'bulk-posts' );
// Disabled "Local JSON" controller to prevent the .json file from being modified during import.
acf_update_setting( 'json', false );
// Sync field groups and generate array of new IDs.
$files = acf_get_local_json_files();
$new_ids = array();
foreach ( $this->sync as $key => $field_group ) {
if ( $field_group['key'] && in_array( $field_group['key'], $keys ) ) {
// Import.
} elseif ( $field_group['ID'] && in_array( $field_group['ID'], $keys ) ) {
// Import.
} else {
// Ignore.
continue;
}
$local_field_group = json_decode( file_get_contents( $files[ $key ] ), true );
$local_field_group['ID'] = $field_group['ID'];
$result = acf_import_field_group( $local_field_group );
$new_ids[] = $result['ID'];
}
// Redirect.
wp_redirect( $this->get_current_admin_url( '&acfsynccomplete=' . implode( ',', $new_ids ) ) );
exit;
}
}
/**
* Customizes the admin table subnav.
*
* @date 17/4/20
* @since 5.9.0
*
* @param array $views The available views.
* @return array
*/
public function admin_table_views( $views ) {
global $wp_list_table, $wp_query;
// Count items.
$count = count( $this->sync );
// Append "sync" link to subnav.
if ( $count ) {
$views['sync'] = sprintf(
'<a %s href="%s">%s <span class="count">(%s)</span></a>',
( $this->view === 'sync' ? 'class="current"' : '' ),
esc_url( $this->get_admin_url( '&post_status=sync' ) ),
esc_html( __( 'Sync available', 'acf' ) ),
$count
);
}
// Modify table pagination args to match JSON data.
if ( $this->view === 'sync' ) {
$wp_list_table->set_pagination_args(
array(
'total_items' => $count,
'total_pages' => 1,
'per_page' => $count,
)
);
$wp_query->post_count = 1; // At least one post is needed to render bulk drop-down.
}
return $views;
}
/**
* Prints scripts into the admin footer.
*
* @date 20/4/20
* @since 5.9.0
*
* @param void
* @return void
*/
function admin_footer() {
?>
<script type="text/javascript">
(function($){
// Displays a modal comparing local changes.
function reviewSync( props ) {
var modal = acf.newModal({
title: acf.__('Review local JSON changes'),
content: '<p class="acf-modal-feedback"><i class="acf-loading"></i> ' + acf.__('Loading diff') + '</p>',
toolbar: '<a href="' + props.href + '" class="button button-primary button-sync-changes disabled">' + acf.__('Sync changes') + '</a>',
});
// Call AJAX.
var xhr = $.ajax({
url: acf.get('ajaxurl'),
method: 'POST',
dataType: 'json',
data: acf.prepareForAjax({
action: 'acf/ajax/local_json_diff',
id: props.id
})
})
.done(function( data, textStatus, jqXHR ) {
modal.content( data.html );
modal.$('.button-sync-changes').removeClass('disabled');
})
.fail(function( jqXHR, textStatus, errorThrown ) {
if( error = acf.getXhrError(jqXHR) ) {
modal.content( '<p class="acf-modal-feedback error">' + error + '</p>' );
}
});
}
// Add event listener.
$(document).on('click', 'a[data-event="review-sync"]', function( e ){
e.preventDefault();
reviewSync( $(this).data() );
});
})(jQuery);
</script>
<?php
}
/**
* Customizes the admin table HTML when viewing "sync" post_status.
*
* @date 17/4/20
* @since 5.9.0
*
* @param array $views The available views.
* @return array
*/
public function admin_footer__sync() {
global $wp_list_table;
// Get table columns.
$columns = $wp_list_table->get_columns();
$hidden = get_hidden_columns( $wp_list_table->screen );
?>
<div style="display: none;">
<table>
<tbody id="acf-the-list">
<?php
foreach ( $this->sync as $k => $field_group ) {
echo '<tr>';
foreach ( $columns as $column_name => $column_label ) {
$el = 'td';
if ( $column_name === 'cb' ) {
$el = 'th';
$classes = 'check-column';
$column_label = '';
} elseif ( $column_name === 'title' ) {
$classes = "$column_name column-$column_name column-primary";
} else {
$classes = "$column_name column-$column_name";
}
if ( in_array( $column_name, $hidden, true ) ) {
$classes .= ' hidden';
}
echo "<$el class=\"$classes\" data-colname=\"$column_label\">";
switch ( $column_name ) {
// Checkbox.
case 'cb':
echo '<label for="cb-select-' . esc_attr( $k ) . '" class="screen-reader-text">' . esc_html( sprintf( __( 'Select %s', 'acf' ), $field_group['title'] ) ) . '</label>';
echo '<input id="cb-select-' . esc_attr( $k ) . '" type="checkbox" value="' . esc_attr( $k ) . '" name="post[]">';
break;
// Title.
case 'title':
$post_state = '';
if ( ! $field_group['active'] ) {
$post_state = ' — <span class="post-state">' . $this->get_disabled_post_state() . '</span>';
}
echo '<strong><span class="row-title">' . esc_html( $field_group['title'] ) . '</span>' . $post_state . '</strong>';
echo '<div class="row-actions"><span class="file acf-secondary-text">' . $this->get_human_readable_file_location( $field_group['local_file'] ) . '</span></div>';
echo '<button type="button" class="toggle-row"><span class="screen-reader-text">Show more details</span></button>';
break;
// All other columns.
default:
$this->render_admin_table_column( $column_name, $field_group );
break;
}
echo "</$el>";
}
echo '</tr>';
}
?>
</tbody>
</table>
</div>
<script type="text/javascript">
(function($){
$('#the-list').html( $('#acf-the-list').children() );
})(jQuery);
</script>
<?php
}
/**
* Fires when trashing a field group post.
*
* @date 8/01/2014
* @since 5.0.0
*
* @param int $post_id The post ID.
* @return void
*/
public function trashed_post( $post_id ) {
if ( get_post_type( $post_id ) === 'acf-field-group' ) {
acf_trash_field_group( $post_id );
}
}
/**
* Fires when untrashing a field group post.
*
* @date 8/01/2014
* @since 5.0.0
*
* @param int $post_id The post ID.
* @return void
*/
public function untrashed_post( $post_id ) {
if ( get_post_type( $post_id ) === 'acf-field-group' ) {
acf_untrash_field_group( $post_id );
}
}
/**
* Fires when deleting a field group post.
*
* @date 8/01/2014
* @since 5.0.0
*
* @param int $post_id The post ID.
* @return void
*/
public function deleted_post( $post_id ) {
if ( get_post_type( $post_id ) === 'acf-field-group' ) {
acf_delete_field_group( $post_id );
}
}
}
// Instantiate.
acf_new_instance( 'ACF_Admin_Field_Groups' );
endif; // class_exists check

View File

@ -0,0 +1,140 @@
<?php
/**
* ACF Admin Notices
*
* Functions and classes to manage admin notices.
*
* @date 10/1/19
* @since 5.7.10
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Register notices store.
acf_register_store( 'notices' );
/**
* ACF_Admin_Notice
*
* Class used to create an admin notice.
*
* @date 10/1/19
* @since 5.7.10
*/
if ( ! class_exists( 'ACF_Admin_Notice' ) ) :
class ACF_Admin_Notice extends ACF_Data {
/** @var array Storage for data. */
var $data = array(
/** @type string Text displayed in notice. */
'text' => '',
/** @type string The type of notice (warning, error, success, info). */
'type' => 'info',
/** @type bool If the notice can be dismissed. */
'dismissible' => true,
);
/**
* render
*
* Renders the notice HTML.
*
* @date 27/12/18
* @since 5.8.0
*
* @param void
* @return void
*/
function render() {
$notice_text = $this->get( 'text' );
$notice_type = $this->get( 'type' );
$is_dismissible = $this->get( 'dismissible' );
printf(
'<div class="acf-admin-notice notice notice-%s %s">%s</div>',
esc_attr( $notice_type ),
$is_dismissible ? 'is-dismissible' : '',
acf_esc_html( wpautop( acf_punctify( $notice_text ) ) )
);
}
}
endif; // class_exists check
/**
* acf_new_admin_notice
*
* Instantiates and returns a new model.
*
* @date 23/12/18
* @since 5.8.0
*
* @param array $data Optional data to set.
* @return ACF_Admin_Notice
*/
function acf_new_admin_notice( $data = false ) {
// Create notice.
$instance = new ACF_Admin_Notice( $data );
// Register notice.
acf_get_store( 'notices' )->set( $instance->cid, $instance );
// Return notice.
return $instance;
}
/**
* acf_render_admin_notices
*
* Renders all admin notices HTML.
*
* @date 10/1/19
* @since 5.7.10
*
* @param void
* @return void
*/
function acf_render_admin_notices() {
// Get notices.
$notices = acf_get_store( 'notices' )->get_data();
// Loop over notices and render.
if ( $notices ) {
foreach ( $notices as $notice ) {
$notice->render();
}
}
}
// Render notices during admin action.
add_action( 'admin_notices', 'acf_render_admin_notices', 99 );
/**
* acf_add_admin_notice
*
* Creates and returns a new notice.
*
* @date 17/10/13
* @since 5.0.0
*
* @param string $text The admin notice text.
* @param string $class The type of notice (warning, error, success, info).
* @return ACF_Admin_Notice
*/
function acf_add_admin_notice( $text = '', $type = 'info' ) {
return acf_new_admin_notice(
array(
'text' => $text,
'type' => $type,
)
);
}

View File

@ -0,0 +1,347 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'acf_admin_tools' ) ) :
class acf_admin_tools {
/** @var array Contains an array of admin tool instances */
var $tools = array();
/** @var string The active tool */
var $active = '';
/**
* __construct
*
* This function will setup the class functionality
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function __construct() {
// actions
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
}
/**
* register_tool
*
* This function will store a tool tool class
*
* @date 10/10/17
* @since 5.6.3
*
* @param string $class
* @return n/a
*/
function register_tool( $class ) {
$instance = new $class();
$this->tools[ $instance->name ] = $instance;
}
/**
* get_tool
*
* This function will return a tool tool class
*
* @date 10/10/17
* @since 5.6.3
*
* @param string $name
* @return n/a
*/
function get_tool( $name ) {
return isset( $this->tools[ $name ] ) ? $this->tools[ $name ] : null;
}
/**
* get_tools
*
* This function will return an array of all tools
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return array
*/
function get_tools() {
return $this->tools;
}
/*
* admin_menu
*
* This function will add the ACF menu item to the WP admin
*
* @type action (admin_menu)
* @date 28/09/13
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
function admin_menu() {
// bail early if no show_admin
if ( ! acf_get_setting( 'show_admin' ) ) {
return;
}
// add page
$page = add_submenu_page( 'edit.php?post_type=acf-field-group', __( 'Tools', 'acf' ), __( 'Tools', 'acf' ), acf_get_setting( 'capability' ), 'acf-tools', array( $this, 'html' ) );
// actions
add_action( 'load-' . $page, array( $this, 'load' ) );
}
/**
* load
*
* description
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function load() {
// disable filters (default to raw data)
acf_disable_filters();
// include tools
$this->include_tools();
// check submit
$this->check_submit();
// load acf scripts
acf_enqueue_scripts();
}
/**
* include_tools
*
* description
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function include_tools() {
// include
acf_include( 'includes/admin/tools/class-acf-admin-tool.php' );
acf_include( 'includes/admin/tools/class-acf-admin-tool-export.php' );
acf_include( 'includes/admin/tools/class-acf-admin-tool-import.php' );
// action
do_action( 'acf/include_admin_tools' );
}
/**
* check_submit
*
* description
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function check_submit() {
// loop
foreach ( $this->get_tools() as $tool ) {
// load
$tool->load();
// submit
if ( acf_verify_nonce( $tool->name ) ) {
$tool->submit();
}
}
}
/**
* html
*
* description
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html() {
// vars
$screen = get_current_screen();
$active = acf_maybe_get_GET( 'tool' );
// view
$view = array(
'screen_id' => $screen->id,
'active' => $active,
);
// register metaboxes
foreach ( $this->get_tools() as $tool ) {
// check active
if ( $active && $active !== $tool->name ) {
continue;
}
// add metabox
add_meta_box( 'acf-admin-tool-' . $tool->name, acf_esc_html( $tool->title ), array( $this, 'metabox_html' ), $screen->id, 'normal', 'default', array( 'tool' => $tool->name ) );
}
// view
acf_get_view( 'html-admin-tools', $view );
}
/**
* meta_box_html
*
* description
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function metabox_html( $post, $metabox ) {
// vars
$tool = $this->get_tool( $metabox['args']['tool'] );
?>
<form method="post">
<?php $tool->html(); ?>
<?php acf_nonce_input( $tool->name ); ?>
</form>
<?php
}
}
// initialize
acf()->admin_tools = new acf_admin_tools();
endif; // class_exists check
/*
* acf_register_admin_tool
*
* alias of acf()->admin_tools->register_tool()
*
* @type function
* @date 31/5/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function acf_register_admin_tool( $class ) {
return acf()->admin_tools->register_tool( $class );
}
/*
* acf_get_admin_tools_url
*
* This function will return the admin URL to the tools page
*
* @type function
* @date 31/5/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function acf_get_admin_tools_url() {
return admin_url( 'edit.php?post_type=acf-field-group&page=acf-tools' );
}
/*
* acf_get_admin_tool_url
*
* This function will return the admin URL to the tools page
*
* @type function
* @date 31/5/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function acf_get_admin_tool_url( $tool = '' ) {
return acf_get_admin_tools_url() . '&tool=' . $tool;
}
?>

View File

@ -0,0 +1,246 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'ACF_Admin_Upgrade' ) ) :
class ACF_Admin_Upgrade {
/**
* __construct
*
* Sets up the class functionality.
*
* @date 31/7/18
* @since 5.7.2
*
* @param void
* @return void
*/
function __construct() {
// actions
add_action( 'admin_menu', array( $this, 'admin_menu' ), 20 );
if ( is_multisite() ) {
add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ), 20 );
}
}
/**
* admin_menu
*
* Setus up logic if DB Upgrade is needed on a single site.
*
* @date 24/8/18
* @since 5.7.4
*
* @param void
* @return void
*/
function admin_menu() {
// check if upgrade is avaialble
if ( acf_has_upgrade() ) {
// add notice
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
// add page
$page = add_submenu_page( 'index.php', __( 'Upgrade Database', 'acf' ), __( 'Upgrade Database', 'acf' ), acf_get_setting( 'capability' ), 'acf-upgrade', array( $this, 'admin_html' ) );
// actions
add_action( 'load-' . $page, array( $this, 'admin_load' ) );
}
}
/**
* network_admin_menu
*
* Sets up admin logic if DB Upgrade is required on a multi site.
*
* @date 24/8/18
* @since 5.7.4
*
* @param void
* @return void
*/
function network_admin_menu() {
// Vars.
$upgrade = false;
// Loop over sites and check for upgrades.
$sites = get_sites( array( 'number' => 0 ) );
if ( $sites ) {
// Unhook action to avoid memory issue (as seen in wp-includes/ms-site.php).
remove_action( 'switch_blog', 'wp_switch_roles_and_user', 1 );
foreach ( $sites as $site ) {
// Switch site.
switch_to_blog( $site->blog_id );
// Check for upgrade.
$site_upgrade = acf_has_upgrade();
// Restore site.
// Ideally, we would switch back to the original site at after looping, however,
// the restore_current_blog() is needed to modify global vars.
restore_current_blog();
// Check if upgrade was found.
if ( $site_upgrade ) {
$upgrade = true;
break;
}
}
add_action( 'switch_blog', 'wp_switch_roles_and_user', 1, 2 );
}
// Bail early if no upgrade is needed.
if ( ! $upgrade ) {
return;
}
// Add notice.
add_action( 'network_admin_notices', array( $this, 'network_admin_notices' ) );
// Add page.
$page = add_submenu_page(
'index.php',
__( 'Upgrade Database', 'acf' ),
__( 'Upgrade Database', 'acf' ),
acf_get_setting( 'capability' ),
'acf-upgrade-network',
array( $this, 'network_admin_html' )
);
add_action( "load-$page", array( $this, 'network_admin_load' ) );
}
/**
* admin_load
*
* Runs during the loading of the admin page.
*
* @date 24/8/18
* @since 5.7.4
*
* @param type $var Description. Default.
* @return type Description.
*/
function admin_load() {
// remove prompt
remove_action( 'admin_notices', array( $this, 'admin_notices' ) );
// Enqueue core script.
acf_enqueue_script( 'acf' );
}
/**
* network_admin_load
*
* Runs during the loading of the network admin page.
*
* @date 24/8/18
* @since 5.7.4
*
* @param type $var Description. Default.
* @return type Description.
*/
function network_admin_load() {
// remove prompt
remove_action( 'network_admin_notices', array( $this, 'network_admin_notices' ) );
// Enqueue core script.
acf_enqueue_script( 'acf' );
}
/**
* admin_notices
*
* Displays the DB Upgrade prompt.
*
* @date 23/8/18
* @since 5.7.3
*
* @param void
* @return void
*/
function admin_notices() {
// vars
$view = array(
'button_text' => __( 'Upgrade Database', 'acf' ),
'button_url' => admin_url( 'index.php?page=acf-upgrade' ),
'confirm' => true,
);
// view
acf_get_view( 'html-notice-upgrade', $view );
}
/**
* network_admin_notices
*
* Displays the DB Upgrade prompt on a multi site.
*
* @date 23/8/18
* @since 5.7.3
*
* @param void
* @return void
*/
function network_admin_notices() {
// vars
$view = array(
'button_text' => __( 'Review sites & upgrade', 'acf' ),
'button_url' => network_admin_url( 'index.php?page=acf-upgrade-network' ),
'confirm' => false,
);
// view
acf_get_view( 'html-notice-upgrade', $view );
}
/**
* admin_html
*
* Displays the HTML for the admin page.
*
* @date 24/8/18
* @since 5.7.4
*
* @param void
* @return void
*/
function admin_html() {
acf_get_view( 'html-admin-page-upgrade' );
}
/**
* network_admin_html
*
* Displays the HTML for the network upgrade admin page.
*
* @date 24/8/18
* @since 5.7.4
*
* @param void
* @return void
*/
function network_admin_html() {
acf_get_view( 'html-admin-page-upgrade-network' );
}
}
// instantiate
acf_new_instance( 'ACF_Admin_Upgrade' );
endif; // class_exists check

View File

@ -0,0 +1,209 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'ACF_Admin' ) ) :
class ACF_Admin {
/**
* Constructor.
*
* @date 23/06/12
* @since 5.0.0
*
* @param void
* @return void
*/
function __construct() {
// Add actions.
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
add_action( 'admin_body_class', array( $this, 'admin_body_class' ) );
add_action( 'current_screen', array( $this, 'current_screen' ) );
}
/**
* Adds the ACF menu item.
*
* @date 28/09/13
* @since 5.0.0
*
* @param void
* @return void
*/
function admin_menu() {
// Bail early if ACF is hidden.
if ( ! acf_get_setting( 'show_admin' ) ) {
return;
}
// Vars.
$slug = 'edit.php?post_type=acf-field-group';
$cap = acf_get_setting( 'capability' );
// Add menu items.
add_menu_page( __( 'Custom Fields', 'acf' ), __( 'Custom Fields', 'acf' ), $cap, $slug, false, 'dashicons-welcome-widgets-menus', 80 );
add_submenu_page( $slug, __( 'Field Groups', 'acf' ), __( 'Field Groups', 'acf' ), $cap, $slug );
add_submenu_page( $slug, __( 'Add New', 'acf' ), __( 'Add New', 'acf' ), $cap, 'post-new.php?post_type=acf-field-group' );
}
/**
* Enqueues global admin styling.
*
* @date 28/09/13
* @since 5.0.0
*
* @param void
* @return void
*/
function admin_enqueue_scripts() {
wp_enqueue_style( 'acf-global' );
}
/**
* Appends custom admin body classes.
*
* @date 5/11/19
* @since 5.8.7
*
* @param string $classes Space-separated list of CSS classes.
* @return string
*/
function admin_body_class( $classes ) {
global $wp_version;
// Determine body class version.
$wp_minor_version = floatval( $wp_version );
if ( $wp_minor_version >= 5.3 ) {
$classes .= ' acf-admin-5-3';
} else {
$classes .= ' acf-admin-3-8';
}
// Add browser for specific CSS.
$classes .= ' acf-browser-' . acf_get_browser();
// Return classes.
return $classes;
}
/**
* Adds custom functionality to "ACF" admin pages.
*
* @date 7/4/20
* @since 5.9.0
*
* @param void
* @return void
*/
function current_screen( $screen ) {
// Determine if the current page being viewed is "ACF" related.
if ( isset( $screen->post_type ) && $screen->post_type === 'acf-field-group' ) {
add_action( 'in_admin_header', array( $this, 'in_admin_header' ) );
add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ) );
$this->setup_help_tab();
}
}
/**
* Sets up the admin help tab.
*
* @date 20/4/20
* @since 5.9.0
*
* @param void
* @return void
*/
public function setup_help_tab() {
$screen = get_current_screen();
// Overview tab.
$screen->add_help_tab(
array(
'id' => 'overview',
'title' => __( 'Overview', 'acf' ),
'content' =>
'<p><strong>' . __( 'Overview', 'acf' ) . '</strong></p>' .
'<p>' . __( 'The Advanced Custom Fields plugin provides a visual form builder to customize WordPress edit screens with extra fields, and an intuitive API to display custom field values in any theme template file.', 'acf' ) . '</p>' .
'<p>' . sprintf(
__( 'Before creating your first Field Group, we recommend first reading our <a href="%s" target="_blank">Getting started</a> guide to familiarize yourself with the plugin\'s philosophy and best practises.', 'acf' ),
'https://www.advancedcustomfields.com/resources/getting-started-with-acf/'
) . '</p>' .
'<p>' . __( 'Please use the Help & Support tab to get in touch should you find yourself requiring assistance.', 'acf' ) . '</p>' .
'',
)
);
// Help tab.
$screen->add_help_tab(
array(
'id' => 'help',
'title' => __( 'Help & Support', 'acf' ),
'content' =>
'<p><strong>' . __( 'Help & Support', 'acf' ) . '</strong></p>' .
'<p>' . __( 'We are fanatical about support, and want you to get the best out of your website with ACF. If you run into any difficulties, there are several places you can find help:', 'acf' ) . '</p>' .
'<ul>' .
'<li>' . sprintf(
__( '<a href="%s" target="_blank">Documentation</a>. Our extensive documentation contains references and guides for most situations you may encounter.', 'acf' ),
'https://www.advancedcustomfields.com/resources/'
) . '</li>' .
'<li>' . sprintf(
__( '<a href="%s" target="_blank">Discussions</a>. We have an active and friendly community on our Community Forums who may be able to help you figure out the how-tos of the ACF world.', 'acf' ),
'https://support.advancedcustomfields.com/'
) . '</li>' .
'<li>' . sprintf(
__( '<a href="%s" target="_blank">Help Desk</a>. The support professionals on our Help Desk will assist with your more in depth, technical challenges.', 'acf' ),
'https://www.advancedcustomfields.com/support/'
) . '</li>' .
'</ul>',
)
);
// Sidebar.
$screen->set_help_sidebar(
'<p><strong>' . __( 'Information', 'acf' ) . '</strong></p>' .
'<p><span class="dashicons dashicons-admin-plugins"></span> ' . sprintf( __( 'Version %s', 'acf' ), ACF_VERSION ) . '</p>' .
'<p><span class="dashicons dashicons-wordpress"></span> <a href="https://wordpress.org/plugins/advanced-custom-fields/" target="_blank">' . __( 'View details', 'acf' ) . '</a></p>' .
'<p><span class="dashicons dashicons-admin-home"></span> <a href="https://www.advancedcustomfields.com/" target="_blank" target="_blank">' . __( 'Visit website', 'acf' ) . '</a></p>' .
''
);
}
/**
* Renders the admin navigation element.
*
* @date 27/3/20
* @since 5.9.0
*
* @param void
* @return void
*/
function in_admin_header() {
acf_get_view( 'html-admin-navigation' );
}
/**
* Modifies the admin footer text.
*
* @date 7/4/20
* @since 5.9.0
*
* @param string $text The admin footer text.
* @return string
*/
function admin_footer_text( $text ) {
// Use RegExp to append "ACF" after the <a> element allowing translations to read correctly.
return preg_replace( '/(<a[\S\s]+?\/a>)/', '$1 ' . __( 'and', 'acf' ) . ' <a href="https://www.advancedcustomfields.com" target="_blank">ACF</a>', $text, 1 );
}
}
// Instantiate.
acf_new_instance( 'ACF_Admin' );
endif; // class_exists check

View File

@ -0,0 +1,580 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'ACF_Admin_Tool_Export' ) ) :
class ACF_Admin_Tool_Export extends ACF_Admin_Tool {
/** @var string View context */
var $view = '';
/** @var array Export data */
var $json = '';
/**
* initialize
*
* This function will initialize the admin tool
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function initialize() {
// vars
$this->name = 'export';
$this->title = __( 'Export Field Groups', 'acf' );
// active
if ( $this->is_active() ) {
$this->title .= ' - ' . __( 'Generate PHP', 'acf' );
}
}
/**
* submit
*
* This function will run when the tool's form has been submit
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function submit() {
// vars
$action = acf_maybe_get_POST( 'action' );
// download
if ( $action === 'download' ) {
$this->submit_download();
// generate
} elseif ( $action === 'generate' ) {
$this->submit_generate();
}
}
/**
* submit_download
*
* description
*
* @date 17/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function submit_download() {
// vars
$json = $this->get_selected();
// validate
if ( $json === false ) {
return acf_add_admin_notice( __( 'No field groups selected', 'acf' ), 'warning' );
}
// headers
$file_name = 'acf-export-' . date( 'Y-m-d' ) . '.json';
header( 'Content-Description: File Transfer' );
header( "Content-Disposition: attachment; filename={$file_name}" );
header( 'Content-Type: application/json; charset=utf-8' );
// return
echo acf_json_encode( $json );
die;
}
/**
* submit_generate
*
* description
*
* @date 17/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function submit_generate() {
// vars
$keys = $this->get_selected_keys();
// validate
if ( ! $keys ) {
return acf_add_admin_notice( __( 'No field groups selected', 'acf' ), 'warning' );
}
// url
$url = add_query_arg( 'keys', implode( '+', $keys ), $this->get_url() );
// redirect
wp_redirect( $url );
exit;
}
/**
* load
*
* description
*
* @date 21/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function load() {
// active
if ( $this->is_active() ) {
// get selected keys
$selected = $this->get_selected_keys();
// add notice
if ( $selected ) {
$count = count( $selected );
$text = sprintf( _n( 'Exported 1 field group.', 'Exported %s field groups.', $count, 'acf' ), $count );
acf_add_admin_notice( $text, 'success' );
}
}
}
/**
* html
*
* This function will output the metabox HTML
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html() {
// single (generate PHP)
if ( $this->is_active() ) {
$this->html_single();
// archive
} else {
$this->html_archive();
}
}
/**
* html_field_selection
*
* description
*
* @date 24/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html_field_selection() {
// vars
$choices = array();
$selected = $this->get_selected_keys();
$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'] );
}
}
// render
acf_render_field_wrap(
array(
'label' => __( 'Select Field Groups', 'acf' ),
'type' => 'checkbox',
'name' => 'keys',
'prefix' => false,
'value' => $selected,
'toggle' => true,
'choices' => $choices,
)
);
}
/**
* html_panel_selection
*
* description
*
* @date 21/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html_panel_selection() {
?>
<div class="acf-panel acf-panel-selection">
<h3 class="acf-panel-title"><?php _e( 'Select Field Groups', 'acf' ); ?> <i class="dashicons dashicons-arrow-right"></i></h3>
<div class="acf-panel-inside">
<?php $this->html_field_selection(); ?>
</div>
</div>
<?php
}
/**
* html_panel_settings
*
* description
*
* @date 21/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html_panel_settings() {
?>
<div class="acf-panel acf-panel-settings">
<h3 class="acf-panel-title"><?php _e( 'Settings', 'acf' ); ?> <i class="dashicons dashicons-arrow-right"></i></h3>
<div class="acf-panel-inside">
<?php
/*
acf_render_field_wrap(array(
'label' => __('Empty settings', 'acf'),
'type' => 'select',
'name' => 'minimal',
'prefix' => false,
'value' => '',
'choices' => array(
'all' => __('Include all settings', 'acf'),
'minimal' => __('Ignore empty settings', 'acf'),
)
));
*/
?>
</div>
</div>
<?php
}
/**
* html_archive
*
* description
*
* @date 20/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html_archive() {
?>
<p><?php _e( 'Select the field groups you would like to export and then select your export method. Use the download button to export to a .json file which you can then import to another ACF installation. Use the generate button to export to PHP code which you can place in your theme.', 'acf' ); ?></p>
<div class="acf-fields">
<?php $this->html_field_selection(); ?>
</div>
<p class="acf-submit">
<button type="submit" name="action" class="button button-primary" value="download"><?php _e( 'Export File', 'acf' ); ?></button>
<button type="submit" name="action" class="button" value="generate"><?php _e( 'Generate PHP', 'acf' ); ?></button>
</p>
<?php
}
/**
* html_single
*
* description
*
* @date 20/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html_single() {
?>
<div class="acf-postbox-columns">
<div class="acf-postbox-main">
<?php $this->html_generate(); ?>
</div>
<div class="acf-postbox-side">
<?php $this->html_panel_selection(); ?>
<p class="acf-submit">
<button type="submit" name="action" class="button button-primary" value="generate"><?php _e( 'Generate PHP', 'acf' ); ?></button>
</p>
</div>
</div>
<?php
}
/**
* html_generate
*
* description
*
* @date 17/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html_generate() {
// prevent default translation and fake __() within string
acf_update_setting( 'l10n_var_export', true );
// vars
$json = $this->get_selected();
$str_replace = array(
' ' => "\t",
"'!!__(!!\'" => "__('",
"!!\', !!\'" => "', '",
"!!\')!!'" => "')",
'array (' => 'array(',
);
$preg_replace = array(
'/([\t\r\n]+?)array/' => 'array',
'/[0-9]+ => array/' => 'array',
);
?>
<p><?php _e( "The following code can be used to register a local version of the selected field group(s). A local field group can provide many benefits such as faster load times, version control & dynamic fields/settings. Simply copy and paste the following code to your theme's functions.php file or include it within an external file.", 'acf' ); ?></p>
<textarea id="acf-export-textarea" readonly="true">
<?php
echo "if( function_exists('acf_add_local_field_group') ):" . "\r\n" . "\r\n";
foreach ( $json as $field_group ) {
// code
$code = var_export( $field_group, true );
// change double spaces to tabs
$code = str_replace( array_keys( $str_replace ), array_values( $str_replace ), $code );
// correctly formats "=> array("
$code = preg_replace( array_keys( $preg_replace ), array_values( $preg_replace ), $code );
// esc_textarea
$code = esc_textarea( $code );
// echo
echo "acf_add_local_field_group({$code});" . "\r\n" . "\r\n";
}
echo 'endif;';
?>
</textarea>
<p class="acf-submit">
<a class="button" id="acf-export-copy"><?php _e( 'Copy to clipboard', 'acf' ); ?></a>
</p>
<script type="text/javascript">
(function($){
// vars
var $a = $('#acf-export-copy');
var $textarea = $('#acf-export-textarea');
// remove $a if 'copy' is not supported
if( !document.queryCommandSupported('copy') ) {
return $a.remove();
}
// event
$a.on('click', function( e ){
// prevent default
e.preventDefault();
// select
$textarea.get(0).select();
// try
try {
// copy
var copy = document.execCommand('copy');
if( !copy ) return;
// tooltip
acf.newTooltip({
text: "<?php _e( 'Copied', 'acf' ); ?>",
timeout: 250,
target: $(this),
});
} catch (err) {
// do nothing
}
});
})(jQuery);
</script>
<?php
}
/**
* get_selected_keys
*
* This function will return an array of field group keys that have been selected
*
* @date 20/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function get_selected_keys() {
// check $_POST
if ( $keys = acf_maybe_get_POST( 'keys' ) ) {
return (array) $keys;
}
// check $_GET
if ( $keys = acf_maybe_get_GET( 'keys' ) ) {
$keys = str_replace( ' ', '+', $keys );
return explode( '+', $keys );
}
// return
return false;
}
/**
* get_selected
*
* This function will return the JSON data for given $_POST args
*
* @date 17/10/17
* @since 5.6.3
*
* @param n/a
* @return array
*/
function get_selected() {
// vars
$selected = $this->get_selected_keys();
$json = array();
// bail early if no keys
if ( ! $selected ) {
return false;
}
// construct JSON
foreach ( $selected as $key ) {
// load field group
$field_group = acf_get_field_group( $key );
// validate field group
if ( empty( $field_group ) ) {
continue;
}
// load fields
$field_group['fields'] = acf_get_fields( $field_group );
// prepare for export
$field_group = acf_prepare_field_group_for_export( $field_group );
// add to json array
$json[] = $field_group;
}
// return
return $json;
}
}
// initialize
acf_register_admin_tool( 'ACF_Admin_Tool_Export' );
endif; // class_exists check
?>

View File

@ -0,0 +1,161 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'ACF_Admin_Tool_Import' ) ) :
class ACF_Admin_Tool_Import extends ACF_Admin_Tool {
/**
* initialize
*
* This function will initialize the admin tool
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function initialize() {
// vars
$this->name = 'import';
$this->title = __( 'Import Field Groups', 'acf' );
$this->icon = 'dashicons-upload';
}
/**
* html
*
* This function will output the metabox HTML
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function 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">
<?php
acf_render_field_wrap(
array(
'label' => __( 'Select File', 'acf' ),
'type' => 'file',
'name' => 'acf_import_file',
'value' => false,
'uploader' => 'basic',
)
);
?>
</div>
<p class="acf-submit">
<input type="submit" class="button button-primary" value="<?php _e( 'Import File', 'acf' ); ?>" />
</p>
<?php
}
/**
* submit
*
* This function will run when the tool's form has been submit
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function submit() {
// Check file size.
if ( empty( $_FILES['acf_import_file']['size'] ) ) {
return acf_add_admin_notice( __( 'No file selected', 'acf' ), 'warning' );
}
// Get file data.
$file = $_FILES['acf_import_file'];
// Check errors.
if ( $file['error'] ) {
return acf_add_admin_notice( __( 'Error uploading file. Please try again', 'acf' ), 'warning' );
}
// Check file type.
if ( pathinfo( $file['name'], PATHINFO_EXTENSION ) !== 'json' ) {
return acf_add_admin_notice( __( 'Incorrect file type', 'acf' ), 'warning' );
}
// Read JSON.
$json = file_get_contents( $file['tmp_name'] );
$json = json_decode( $json, true );
// Check if empty.
if ( ! $json || ! is_array( $json ) ) {
return acf_add_admin_notice( __( 'Import file empty', 'acf' ), 'warning' );
}
// Ensure $json is an array of groups.
if ( isset( $json['key'] ) ) {
$json = array( $json );
}
// Remeber imported field group ids.
$ids = array();
// Loop over json
foreach ( $json as $field_group ) {
// 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 message
$ids[] = $field_group['ID'];
}
// 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
acf_register_admin_tool( 'ACF_Admin_Tool_Import' );
endif; // class_exists check
?>

View File

@ -0,0 +1,194 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'ACF_Admin_Tool' ) ) :
class ACF_Admin_Tool {
/** @var string Tool name */
var $name = '';
/** @var string Tool title */
var $title = '';
/** @var string Dashicon slug */
// var $icon = '';
/** @var boolean Redirect form to single */
// var $redirect = false;
/**
* get_name
*
* This function will return the Tool's name
*
* @date 19/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function get_name() {
return $this->name;
}
/**
* get_title
*
* This function will return the Tool's title
*
* @date 19/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function get_title() {
return $this->title;
}
/**
* get_url
*
* This function will return the Tool's title
*
* @date 19/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function get_url() {
return acf_get_admin_tool_url( $this->name );
}
/**
* is_active
*
* This function will return true if the tool is active
*
* @date 19/10/17
* @since 5.6.3
*
* @param n/a
* @return bool
*/
function is_active() {
return acf_maybe_get_GET( 'tool' ) === $this->name;
}
/*
* __construct
*
* This function will setup the class functionality
*
* @type function
* @date 27/6/17
* @since 5.6.0
*
* @param n/a
* @return n/a
*/
function __construct() {
// initialize
$this->initialize();
}
/**
* initialize
*
* This function will initialize the admin tool
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function initialize() {
/* do nothing */
}
/**
* load
*
* This function is called during the admin page load
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function load() {
/* do nothing */
}
/**
* html
*
* This function will output the metabox HTML
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function html() {
}
/**
* submit
*
* This function will run when the tool's form has been submit
*
* @date 10/10/17
* @since 5.6.3
*
* @param n/a
* @return n/a
*/
function submit() {
}
}
endif; // class_exists check

View File

@ -0,0 +1,177 @@
<?php
// vars
$disabled = false;
// empty
if ( empty( $field['conditional_logic'] ) ) {
$disabled = true;
$field['conditional_logic'] = array(
// group 0
array(
// rule 0
array(),
),
);
}
?>
<tr class="acf-field acf-field-true-false acf-field-setting-conditional_logic" data-type="true_false" data-name="conditional_logic">
<td class="acf-label">
<label><?php _e( 'Conditional Logic', 'acf' ); ?></label>
</td>
<td class="acf-input">
<?php
acf_render_field(
array(
'type' => 'true_false',
'name' => 'conditional_logic',
'prefix' => $field['prefix'],
'value' => $disabled ? 0 : 1,
'ui' => 1,
'class' => 'conditions-toggle',
)
);
?>
<div class="rule-groups"
<?php
if ( $disabled ) :
?>
style="display:none;"<?php endif; ?>>
<?php
foreach ( $field['conditional_logic'] as $group_id => $group ) :
// validate
if ( empty( $group ) ) {
continue;
}
// vars
// $group_id must be completely different to $rule_id to avoid JS issues
$group_id = "group_{$group_id}";
$h4 = ( $group_id == 'group_0' ) ? __( 'Show this field if', 'acf' ) : __( 'or', 'acf' );
?>
<div class="rule-group" data-id="<?php echo $group_id; ?>">
<h4><?php echo $h4; ?></h4>
<table class="acf-table -clear">
<tbody>
<?php
foreach ( $group as $rule_id => $rule ) :
// valid rule
$rule = wp_parse_args(
$rule,
array(
'field' => '',
'operator' => '',
'value' => '',
)
);
// vars
// $group_id must be completely different to $rule_id to avoid JS issues
$rule_id = "rule_{$rule_id}";
$prefix = "{$field['prefix']}[conditional_logic][{$group_id}][{$rule_id}]";
// data attributes
$attributes = array(
'data-id' => $rule_id,
'data-field' => $rule['field'],
'data-operator' => $rule['operator'],
'data-value' => $rule['value'],
);
?>
<tr class="rule" <?php acf_esc_attr_e( $attributes ); ?>>
<td class="param">
<?php
acf_render_field(
array(
'type' => 'select',
'prefix' => $prefix,
'name' => 'field',
'class' => 'condition-rule-field',
'disabled' => $disabled,
'value' => $rule['field'],
'choices' => array(
$rule['field'] => $rule['field'],
),
)
);
?>
</td>
<td class="operator">
<?php
acf_render_field(
array(
'type' => 'select',
'prefix' => $prefix,
'name' => 'operator',
'class' => 'condition-rule-operator',
'disabled' => $disabled,
'value' => $rule['operator'],
'choices' => array(
$rule['operator'] => $rule['operator'],
),
)
);
?>
</td>
<td class="value">
<?php
// create field
acf_render_field(
array(
'type' => 'select',
'prefix' => $prefix,
'name' => 'value',
'class' => 'condition-rule-value',
'disabled' => $disabled,
'value' => $rule['value'],
'choices' => array(
$rule['value'] => $rule['value'],
),
)
);
?>
</td>
<td class="add">
<a href="#" class="button add-conditional-rule"><?php _e( 'and', 'acf' ); ?></a>
</td>
<td class="remove">
<a href="#" class="acf-icon -minus remove-conditional-rule"></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endforeach; ?>
<h4><?php _e( 'or', 'acf' ); ?></h4>
<a href="#" class="button add-conditional-group"><?php _e( 'Add rule group', 'acf' ); ?></a>
</div>
</td>
</tr>

View File

@ -0,0 +1,224 @@
<?php
// Define input name prefix using unique identifier.
$input_prefix = 'acf_fields[' . $field['ID'] . ']';
$input_id = acf_idify( $input_prefix );
// Update field props.
$field['prefix'] = $input_prefix;
// Elements.
$div_attrs = array(
'class' => 'acf-field-object acf-field-object-' . acf_slugify( $field['type'] ),
'data-id' => $field['ID'],
'data-key' => $field['key'],
'data-type' => $field['type'],
);
// Misc template vars.
$field_label = acf_get_field_label( $field, 'admin' );
$field_type_label = acf_get_field_type_label( $field['type'] );
?>
<div <?php echo acf_esc_attr( $div_attrs ); ?>>
<div class="meta">
<?php
$meta_inputs = array(
'ID' => $field['ID'],
'key' => $field['key'],
'parent' => $field['parent'],
'menu_order' => $i,
'save' => '',
);
foreach ( $meta_inputs as $k => $v ) :
acf_hidden_input(
array(
'name' => $input_prefix . '[' . $k . ']',
'value' => $v,
'id' => $input_id . '-' . $k,
)
);
endforeach;
?>
</div>
<div class="handle">
<ul class="acf-hl acf-tbody">
<li class="li-field-order">
<span class="acf-icon acf-sortable-handle" title="<?php _e( 'Drag to reorder', 'acf' ); ?>"><?php echo ( $i + 1 ); ?></span>
</li>
<li class="li-field-label">
<strong>
<a class="edit-field" title="<?php _e( 'Edit field', 'acf' ); ?>" href="#"><?php echo acf_esc_html( $field_label ); ?></a>
</strong>
<div class="row-options">
<a class="edit-field" title="<?php _e( 'Edit field', 'acf' ); ?>" href="#"><?php _e( 'Edit', 'acf' ); ?></a>
<a class="duplicate-field" title="<?php _e( 'Duplicate field', 'acf' ); ?>" href="#"><?php _e( 'Duplicate', 'acf' ); ?></a>
<a class="move-field" title="<?php _e( 'Move field to another group', 'acf' ); ?>" href="#"><?php _e( 'Move', 'acf' ); ?></a>
<a class="delete-field" title="<?php _e( 'Delete field', 'acf' ); ?>" href="#"><?php _e( 'Delete', 'acf' ); ?></a>
</div>
</li>
<?php // whitespace before field name looks odd but fixes chrome bug selecting all text in row ?>
<li class="li-field-name"> <?php echo esc_html( $field['name'] ); ?></li>
<li class="li-field-key"> <?php echo esc_html( $field['key'] ); ?></li>
<li class="li-field-type"> <?php echo esc_html( $field_type_label ); ?></li>
</ul>
</div>
<div class="settings">
<table class="acf-table">
<tbody class="acf-field-settings">
<?php
// label
acf_render_field_setting(
$field,
array(
'label' => __( 'Field Label', 'acf' ),
'instructions' => __( 'This is the name which will appear on the EDIT page', 'acf' ),
'name' => 'label',
'type' => 'text',
'class' => 'field-label',
),
true
);
// name
acf_render_field_setting(
$field,
array(
'label' => __( 'Field Name', 'acf' ),
'instructions' => __( 'Single word, no spaces. Underscores and dashes allowed', 'acf' ),
'name' => 'name',
'type' => 'text',
'class' => 'field-name',
),
true
);
// type
acf_render_field_setting(
$field,
array(
'label' => __( 'Field Type', 'acf' ),
'instructions' => '',
'type' => 'select',
'name' => 'type',
'choices' => acf_get_grouped_field_types(),
'class' => 'field-type',
),
true
);
// instructions
acf_render_field_setting(
$field,
array(
'label' => __( 'Instructions', 'acf' ),
'instructions' => __( 'Instructions for authors. Shown when submitting data', 'acf' ),
'type' => 'textarea',
'name' => 'instructions',
'rows' => 5,
),
true
);
// required
acf_render_field_setting(
$field,
array(
'label' => __( 'Required?', 'acf' ),
'instructions' => '',
'type' => 'true_false',
'name' => 'required',
'ui' => 1,
'class' => 'field-required',
),
true
);
// 3rd party settings
do_action( 'acf/render_field_settings', $field );
// type specific settings
do_action( "acf/render_field_settings/type={$field['type']}", $field );
// conditional logic
acf_get_view( 'field-group-field-conditional-logic', array( 'field' => $field ) );
// wrapper
acf_render_field_wrap(
array(
'label' => __( 'Wrapper Attributes', 'acf' ),
'instructions' => '',
'type' => 'number',
'name' => 'width',
'prefix' => $field['prefix'] . '[wrapper]',
'value' => $field['wrapper']['width'],
'prepend' => __( 'width', 'acf' ),
'append' => '%',
'wrapper' => array(
'data-name' => 'wrapper',
'class' => 'acf-field-setting-wrapper',
),
),
'tr'
);
acf_render_field_wrap(
array(
'label' => '',
'instructions' => '',
'type' => 'text',
'name' => 'class',
'prefix' => $field['prefix'] . '[wrapper]',
'value' => $field['wrapper']['class'],
'prepend' => __( 'class', 'acf' ),
'wrapper' => array(
'data-append' => 'wrapper',
),
),
'tr'
);
acf_render_field_wrap(
array(
'label' => '',
'instructions' => '',
'type' => 'text',
'name' => 'id',
'prefix' => $field['prefix'] . '[wrapper]',
'value' => $field['wrapper']['id'],
'prepend' => __( 'id', 'acf' ),
'wrapper' => array(
'data-append' => 'wrapper',
),
),
'tr'
);
?>
<tr class="acf-field acf-field-save">
<td class="acf-label"></td>
<td class="acf-input">
<ul class="acf-hl">
<li>
<a class="button edit-field" title="<?php _e( 'Close Field', 'acf' ); ?>" href="#"><?php _e( 'Close Field', 'acf' ); ?></a>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
</div>

View File

@ -0,0 +1,76 @@
<div class="acf-field-list-wrap">
<ul class="acf-hl acf-thead">
<li class="li-field-order"><?php _e( 'Order', 'acf' ); ?></li>
<li class="li-field-label"><?php _e( 'Label', 'acf' ); ?></li>
<li class="li-field-name"><?php _e( 'Name', 'acf' ); ?></li>
<li class="li-field-key"><?php _e( 'Key', 'acf' ); ?></li>
<li class="li-field-type"><?php _e( 'Type', 'acf' ); ?></li>
</ul>
<div class="acf-field-list
<?php
if ( ! $fields ) {
echo ' -empty'; }
?>
">
<div class="no-fields-message">
<?php _e( 'No fields. Click the <strong>+ Add Field</strong> button to create your first field.', 'acf' ); ?>
</div>
<?php
if ( $fields ) :
foreach ( $fields as $i => $field ) :
acf_get_view(
'field-group-field',
array(
'field' => $field,
'i' => $i,
)
);
endforeach;
endif;
?>
</div>
<ul class="acf-hl acf-tfoot">
<li class="acf-fr">
<a href="#" class="button button-primary button-large add-field"><?php _e( '+ Add Field', 'acf' ); ?></a>
</li>
</ul>
<?php
if ( ! $parent ) :
// get clone
$clone = acf_get_valid_field(
array(
'ID' => 'acfcloneindex',
'key' => 'acfcloneindex',
'label' => __( 'New Field', 'acf' ),
'name' => 'new_field',
'type' => 'text',
)
);
?>
<script type="text/html" id="tmpl-acf-field">
<?php
acf_get_view(
'field-group-field',
array(
'field' => $clone,
'i' => 0,
)
);
?>
</script>
<?php endif; ?>
</div>

View File

@ -0,0 +1,52 @@
<?php
// global
global $field_group;
?>
<div class="acf-field">
<div class="acf-label">
<label><?php _e( 'Rules', 'acf' ); ?></label>
<p class="description"><?php _e( 'Create a set of rules to determine which edit screens will use these advanced custom fields', 'acf' ); ?></p>
</div>
<div class="acf-input">
<div class="rule-groups">
<?php
foreach ( $field_group['location'] as $i => $group ) :
// bail ealry if no group
if ( empty( $group ) ) {
return;
}
// view
acf_get_view(
'html-location-group',
array(
'group' => $group,
'group_id' => "group_{$i}",
)
);
endforeach;
?>
<h4><?php _e( 'or', 'acf' ); ?></h4>
<a href="#" class="button add-location-group"><?php _e( 'Add rule group', 'acf' ); ?></a>
</div>
</div>
</div>
<script type="text/javascript">
if( typeof acf !== 'undefined' ) {
acf.newPostbox({
'id': 'acf-field-group-locations',
'label': 'left'
});
}
</script>

View File

@ -0,0 +1,171 @@
<?php
// global
global $field_group;
// active
acf_render_field_wrap(
array(
'label' => __( 'Active', 'acf' ),
'instructions' => '',
'type' => 'true_false',
'name' => 'active',
'prefix' => 'acf_field_group',
'value' => $field_group['active'],
'ui' => 1,
// 'ui_on_text' => __('Active', 'acf'),
// 'ui_off_text' => __('Inactive', 'acf'),
)
);
// style
acf_render_field_wrap(
array(
'label' => __( 'Style', 'acf' ),
'instructions' => '',
'type' => 'select',
'name' => 'style',
'prefix' => 'acf_field_group',
'value' => $field_group['style'],
'choices' => array(
'default' => __( 'Standard (WP metabox)', 'acf' ),
'seamless' => __( 'Seamless (no metabox)', 'acf' ),
),
)
);
// position
acf_render_field_wrap(
array(
'label' => __( 'Position', 'acf' ),
'instructions' => '',
'type' => 'select',
'name' => 'position',
'prefix' => 'acf_field_group',
'value' => $field_group['position'],
'choices' => array(
'acf_after_title' => __( 'High (after title)', 'acf' ),
'normal' => __( 'Normal (after content)', 'acf' ),
'side' => __( 'Side', 'acf' ),
),
'default_value' => 'normal',
)
);
// label_placement
acf_render_field_wrap(
array(
'label' => __( 'Label placement', 'acf' ),
'instructions' => '',
'type' => 'select',
'name' => 'label_placement',
'prefix' => 'acf_field_group',
'value' => $field_group['label_placement'],
'choices' => array(
'top' => __( 'Top aligned', 'acf' ),
'left' => __( 'Left aligned', 'acf' ),
),
)
);
// instruction_placement
acf_render_field_wrap(
array(
'label' => __( 'Instruction placement', 'acf' ),
'instructions' => '',
'type' => 'select',
'name' => 'instruction_placement',
'prefix' => 'acf_field_group',
'value' => $field_group['instruction_placement'],
'choices' => array(
'label' => __( 'Below labels', 'acf' ),
'field' => __( 'Below fields', 'acf' ),
),
)
);
// menu_order
acf_render_field_wrap(
array(
'label' => __( 'Order No.', 'acf' ),
'instructions' => __( 'Field groups with a lower order will appear first', 'acf' ),
'type' => 'number',
'name' => 'menu_order',
'prefix' => 'acf_field_group',
'value' => $field_group['menu_order'],
)
);
// description
acf_render_field_wrap(
array(
'label' => __( 'Description', 'acf' ),
'instructions' => __( 'Shown in field group list', 'acf' ),
'type' => 'text',
'name' => 'description',
'prefix' => 'acf_field_group',
'value' => $field_group['description'],
)
);
// hide on screen
$choices = array(
'permalink' => __( 'Permalink', 'acf' ),
'the_content' => __( 'Content Editor', 'acf' ),
'excerpt' => __( 'Excerpt', 'acf' ),
'custom_fields' => __( 'Custom Fields', 'acf' ),
'discussion' => __( 'Discussion', 'acf' ),
'comments' => __( 'Comments', 'acf' ),
'revisions' => __( 'Revisions', 'acf' ),
'slug' => __( 'Slug', 'acf' ),
'author' => __( 'Author', 'acf' ),
'format' => __( 'Format', 'acf' ),
'page_attributes' => __( 'Page Attributes', 'acf' ),
'featured_image' => __( 'Featured Image', 'acf' ),
'categories' => __( 'Categories', 'acf' ),
'tags' => __( 'Tags', 'acf' ),
'send-trackbacks' => __( 'Send Trackbacks', 'acf' ),
);
if ( acf_get_setting( 'remove_wp_meta_box' ) ) {
unset( $choices['custom_fields'] );
}
acf_render_field_wrap(
array(
'label' => __( 'Hide on screen', 'acf' ),
'instructions' => __( '<b>Select</b> items to <b>hide</b> them from the edit screen.', 'acf' ) . '<br /><br />' . __( "If multiple field groups appear on an edit screen, the first field group's options will be used (the one with the lowest order number)", 'acf' ),
'type' => 'checkbox',
'name' => 'hide_on_screen',
'prefix' => 'acf_field_group',
'value' => $field_group['hide_on_screen'],
'toggle' => true,
'choices' => $choices,
)
);
// 3rd party settings
do_action( 'acf/render_field_group_settings', $field_group );
?>
<div class="acf-hidden">
<input type="hidden" name="acf_field_group[key]" value="<?php echo $field_group['key']; ?>" />
</div>
<script type="text/javascript">
if( typeof acf !== 'undefined' ) {
acf.newPostbox({
'id': 'acf-field-group-options',
'label': 'left'
});
}
</script>

View File

@ -0,0 +1,93 @@
<?php
/**
* The template for displaying admin navigation.
*
* @date 27/3/20
* @since 5.9.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $submenu, $parent_file, $submenu_file, $plugin_page, $pagenow;
// Vars.
$parent_slug = 'edit.php?post_type=acf-field-group';
// Generate array of navigation items.
$tabs = array();
if ( isset( $submenu[ $parent_slug ] ) ) {
foreach ( $submenu[ $parent_slug ] as $i => $sub_item ) {
// Check user can access page.
if ( ! current_user_can( $sub_item[1] ) ) {
continue;
}
// Ignore "Add New".
if ( $i === 1 ) {
continue;
}
// Define tab.
$tab = array(
'text' => $sub_item[0],
'url' => $sub_item[2],
);
// Convert submenu slug "test" to "$parent_slug&page=test".
if ( ! strpos( $sub_item[2], '.php' ) ) {
$tab['url'] = add_query_arg( array( 'page' => $sub_item[2] ), $parent_slug );
}
// Detect active state.
if ( $submenu_file === $sub_item[2] || $plugin_page === $sub_item[2] ) {
$tab['is_active'] = true;
}
// Special case for "Add New" page.
if ( $i === 0 && $submenu_file === 'post-new.php?post_type=acf-field-group' ) {
$tab['is_active'] = true;
}
$tabs[] = $tab;
}
}
/**
* Filters the admin navigation tabs.
*
* @date 27/3/20
* @since 5.9.0
*
* @param array $tabs The array of navigation tabs.
*/
$tabs = apply_filters( 'acf/admin/toolbar', $tabs );
// Bail early if set to false.
if ( $tabs === false ) {
return;
}
?>
<div class="acf-admin-toolbar">
<h2><i class="acf-tab-icon dashicons dashicons-welcome-widgets-menus"></i> <?php echo acf_get_setting( 'name' ); ?></h2>
<?php
foreach ( $tabs as $tab ) {
printf(
'<a class="acf-tab%s" href="%s">%s</a>',
! empty( $tab['is_active'] ) ? ' is-active' : '',
esc_url( $tab['url'] ),
acf_esc_html( $tab['text'] )
);
}
?>
<?php if ( ! defined( 'ACF_PRO' ) || ! ACF_PRO ) : ?>
<a target="_blank" href="https://www.advancedcustomfields.com/pro/?utm_source=ACF%2BFree&utm_medium=insideplugin&utm_campaign=ACF%2Bupgrade" class="btn-upgrade">
<img src="<?php echo acf_get_url( 'assets/images/icon-upgrade-pro.svg' ); ?>" />
<p><?php _e( 'Upgrade to Pro', 'acf' ); ?></p>
</a>
<?php endif; ?>
</div>

View File

@ -0,0 +1,196 @@
<?php
/**
* Network Admin Database Upgrade
*
* Shows the databse upgrade process.
*
* @date 24/8/18
* @since 5.7.4
* @param void
*/
?>
<style type="text/css">
/* hide steps */
.show-on-complete {
display: none;
}
</style>
<div id="acf-upgrade-wrap" class="wrap">
<h1><?php _e( 'Upgrade Database', 'acf' ); ?></h1>
<p><?php echo sprintf( __( 'The following sites require a DB upgrade. Check the ones you want to update and then click %s.', 'acf' ), '"' . __( 'Upgrade Sites', 'acf' ) . '"' ); ?></p>
<p><input type="submit" name="upgrade" value="<?php _e( 'Upgrade Sites', 'acf' ); ?>" class="button" id="upgrade-sites"></p>
<table class="wp-list-table widefat">
<thead>
<tr>
<td class="manage-column check-column" scope="col">
<input type="checkbox" id="sites-select-all">
</td>
<th class="manage-column" scope="col" style="width:33%;">
<label for="sites-select-all"><?php _e( 'Site', 'acf' ); ?></label>
</th>
<th><?php _e( 'Description', 'acf' ); ?></th>
</tr>
</thead>
<tfoot>
<tr>
<td class="manage-column check-column" scope="col">
<input type="checkbox" id="sites-select-all-2">
</td>
<th class="manage-column" scope="col">
<label for="sites-select-all-2"><?php _e( 'Site', 'acf' ); ?></label>
</th>
<th><?php _e( 'Description', 'acf' ); ?></th>
</tr>
</tfoot>
<tbody id="the-list">
<?php
$sites = acf_get_sites();
if ( $sites ) :
foreach ( $sites as $i => $site ) :
// switch blog
switch_to_blog( $site['blog_id'] );
?>
<tr
<?php
if ( $i % 2 == 0 ) :
?>
class="alternate"<?php endif; ?>>
<th class="check-column" scope="row">
<?php if ( acf_has_upgrade() ) : ?>
<input type="checkbox" value="<?php echo $site['blog_id']; ?>" name="checked[]">
<?php endif; ?>
</th>
<td>
<strong><?php echo get_bloginfo( 'name' ); ?></strong><br /><?php echo home_url(); ?>
</td>
<td>
<?php if ( acf_has_upgrade() ) : ?>
<span class="response"><?php printf( __( 'Site requires database upgrade from %1$s to %2$s', 'acf' ), acf_get_db_version(), ACF_VERSION ); ?></span>
<?php else : ?>
<?php _e( 'Site is up to date', 'acf' ); ?>
<?php endif; ?>
</td>
</tr>
<?php
// restore
restore_current_blog();
endforeach;
endif;
?>
</tbody>
</table>
<p><input type="submit" name="upgrade" value="<?php _e( 'Upgrade Sites', 'acf' ); ?>" class="button" id="upgrade-sites-2"></p>
<p class="show-on-complete"><?php echo sprintf( __( 'Database Upgrade complete. <a href="%s">Return to network dashboard</a>', 'acf' ), network_admin_url() ); ?></p>
<script type="text/javascript">
(function($) {
var upgrader = new acf.Model({
events: {
'click #upgrade-sites': 'onClick',
'click #upgrade-sites-2': 'onClick'
},
$inputs: function(){
return $('#the-list input:checked');
},
onClick: function( e, $el ){
// prevent default
e.preventDefault();
// bail early if no selection
if( !this.$inputs().length ) {
return alert('<?php _e( 'Please select at least one site to upgrade.', 'acf' ); ?>');
}
// confirm action
if( !confirm("<?php _e( 'It is strongly recommended that you backup your database before proceeding. Are you sure you wish to run the updater now?', 'acf' ); ?>") ) {
return;
}
// upgrade
this.upgrade();
},
upgrade: function(){
// vars
var $inputs = this.$inputs();
// bail early if no sites selected
if( !$inputs.length ) {
return this.complete();
}
// disable buttons
$('.button').prop('disabled', true);
// vars
var $input = $inputs.first();
var $row = $input.closest('tr');
var text = '';
var success = false;
// show loading
$row.find('.response').html('<i class="acf-loading"></i></span> <?php printf( __( 'Upgrading data to version %s', 'acf' ), ACF_VERSION ); ?>');
// send ajax request to upgrade DB
$.ajax({
url: acf.get('ajaxurl'),
dataType: 'json',
type: 'post',
data: acf.prepareForAjax({
action: 'acf/ajax/upgrade',
blog_id: $input.val()
}),
success: function( json ){
success = true;
$input.remove();
text = '<?php _e( 'Upgrade complete.', 'acf' ); ?>';
},
error: function( jqXHR, textStatus, errorThrown ){
text = '<?php _e( 'Upgrade failed.', 'acf' ); ?>';
if( error = acf.getXhrError(jqXHR) ) {
text += ' <code>' + error + '</code>';
}
},
complete: this.proxy(function(){
// display text
$row.find('.response').html( text );
// if successful upgrade, proceed to next site. Otherwise, skip to complete.
if( success ) {
this.upgrade();
} else {
this.complete();
}
})
});
},
complete: function(){
// enable buttons
$('.button').prop('disabled', false);
// show message
$('.show-on-complete').show();
}
});
})(jQuery);
</script>
</div>

View File

@ -0,0 +1,97 @@
<?php
/**
* Admin Database Upgrade
*
* Shows the databse upgrade process.
*
* @date 24/8/18
* @since 5.7.4
* @param void
*/
?>
<style type="text/css">
/* hide steps */
.step-1,
.step-2,
.step-3 {
display: none;
}
</style>
<div id="acf-upgrade-wrap" class="wrap">
<h1><?php _e( 'Upgrade Database', 'acf' ); ?></h1>
<?php if ( acf_has_upgrade() ) : ?>
<p><?php _e( 'Reading upgrade tasks...', 'acf' ); ?></p>
<p class="step-1"><i class="acf-loading"></i> <?php printf( __( 'Upgrading data to version %s', 'acf' ), ACF_VERSION ); ?></p>
<p class="step-2"></p>
<p class="step-3"><?php echo sprintf( __( 'Database upgrade complete. <a href="%s">See what\'s new</a>', 'acf' ), admin_url( 'edit.php?post_type=acf-field-group' ) ); ?></p>
<script type="text/javascript">
(function($) {
var upgrader = new acf.Model({
initialize: function(){
// allow user to read message for 1 second
this.setTimeout( this.upgrade, 1000 );
},
upgrade: function(){
// show step 1
$('.step-1').show();
// vars
var response = '';
var success = false;
// send ajax request to upgrade DB
$.ajax({
url: acf.get('ajaxurl'),
dataType: 'json',
type: 'post',
data: acf.prepareForAjax({
action: 'acf/ajax/upgrade'
}),
success: function( json ){
success = true;
},
error: function( jqXHR, textStatus, errorThrown ){
response = '<?php _e( 'Upgrade failed.', 'acf' ); ?>';
if( error = acf.getXhrError(jqXHR) ) {
response += ' <code>' + error + '</code>';
}
},
complete: this.proxy(function(){
// remove spinner
$('.acf-loading').hide();
// display response
if( response ) {
$('.step-2').show().html( response );
}
// display success
if( success ) {
$('.step-3').show();
}
})
});
}
});
})(jQuery);
</script>
<?php else : ?>
<p><?php _e( 'No updates available.', 'acf' ); ?></p>
<?php endif; ?>
</div>

View File

@ -0,0 +1,30 @@
<?php
/**
* html-admin-tools
*
* View to output admin tools for both archive and single
*
* @date 20/10/17
* @since 5.6.3
*
* @param string $screen_id The screen ID used to display metaboxes
* @param string $active The active Tool
* @return n/a
*/
$class = $active ? 'single' : 'grid';
?>
<div class="wrap" id="acf-admin-tools">
<h1><?php _e( 'Tools', 'acf' ); ?> <?php
if ( $active ) :
?>
<a class="page-title-action" href="<?php echo acf_get_admin_tools_url(); ?>"><?php _e( 'Back to all tools', 'acf' ); ?></a><?php endif; ?></h1>
<div class="acf-meta-box-wrap -<?php echo $class; ?>">
<?php do_meta_boxes( $screen_id, 'normal', '' ); ?>
</div>
</div>

View File

@ -0,0 +1,30 @@
<div class="rule-group" data-id="<?php echo $group_id; ?>">
<h4><?php echo ( $group_id == 'group_0' ) ? __( 'Show this field group if', 'acf' ) : __( 'or', 'acf' ); ?></h4>
<table class="acf-table -clear">
<tbody>
<?php
foreach ( $group as $i => $rule ) :
// validate rule
$rule = acf_validate_location_rule( $rule );
// append id and group
$rule['id'] = "rule_{$i}";
$rule['group'] = $group_id;
// view
acf_get_view(
'html-location-rule',
array(
'rule' => $rule,
)
);
endforeach;
?>
</tbody>
</table>
</div>

View File

@ -0,0 +1,97 @@
<?php
// vars
$prefix = 'acf_field_group[location][' . $rule['group'] . '][' . $rule['id'] . ']';
?>
<tr data-id="<?php echo $rule['id']; ?>">
<td class="param">
<?php
// vars
$choices = acf_get_location_rule_types();
// array
if ( is_array( $choices ) ) {
acf_render_field(
array(
'type' => 'select',
'name' => 'param',
'prefix' => $prefix,
'value' => $rule['param'],
'choices' => $choices,
'class' => 'refresh-location-rule',
)
);
}
?>
</td>
<td class="operator">
<?php
// vars
$choices = acf_get_location_rule_operators( $rule );
// array
if ( is_array( $choices ) ) {
acf_render_field(
array(
'type' => 'select',
'name' => 'operator',
'prefix' => $prefix,
'value' => $rule['operator'],
'choices' => $choices,
)
);
// custom
} else {
echo $choices;
}
?>
</td>
<td class="value">
<?php
// vars
$choices = acf_get_location_rule_values( $rule );
// array
if ( is_array( $choices ) ) {
acf_render_field(
array(
'type' => 'select',
'name' => 'value',
'prefix' => $prefix,
'value' => $rule['value'],
'choices' => $choices,
)
);
// custom
} else {
echo $choices;
}
?>
</td>
<td class="add">
<a href="#" class="button add-location-rule"><?php _e( 'and', 'acf' ); ?></a>
</td>
<td class="remove">
<a href="#" class="acf-icon -minus remove-location-rule"></a>
</td>
</tr>

View File

@ -0,0 +1,50 @@
<?php
// calculate add-ons (non pro only)
$plugins = array();
if ( ! acf_get_setting( 'pro' ) ) {
if ( is_plugin_active( 'acf-repeater/acf-repeater.php' ) ) {
$plugins[] = __( 'Repeater', 'acf' );
}
if ( is_plugin_active( 'acf-flexible-content/acf-flexible-content.php' ) ) {
$plugins[] = __( 'Flexible Content', 'acf' );
}
if ( is_plugin_active( 'acf-gallery/acf-gallery.php' ) ) {
$plugins[] = __( 'Gallery', 'acf' );
}
if ( is_plugin_active( 'acf-options-page/acf-options-page.php' ) ) {
$plugins[] = __( 'Options Page', 'acf' );
}
}
?>
<div id="acf-upgrade-notice" class="notice">
<div class="col-content">
<img src="<?php echo acf_get_url( 'assets/images/acf-logo.png' ); ?>" />
<h2><?php _e( 'Database Upgrade Required', 'acf' ); ?></h2>
<p><?php printf( __( 'Thank you for updating to %1$s v%2$s!', 'acf' ), acf_get_setting( 'name' ), acf_get_setting( 'version' ) ); ?><br /><?php _e( 'This version contains improvements to your database and requires an upgrade.', 'acf' ); ?></p>
<?php if ( ! empty( $plugins ) ) : ?>
<p><?php printf( __( 'Please also check all premium add-ons (%s) are updated to the latest version.', 'acf' ), implode( ', ', $plugins ) ); ?></p>
<?php endif; ?>
</div>
<div class="col-actions">
<a id="acf-upgrade-button" href="<?php echo $button_url; ?>" class="button button-primary button-hero"><?php echo $button_text; ?></a>
</div>
</div>
<?php if ( $confirm ) : ?>
<script type="text/javascript">
(function($) {
$("#acf-upgrade-button").on("click", function(){
return confirm("<?php _e( 'It is strongly recommended that you backup your database before proceeding. Are you sure you wish to run the updater now?', 'acf' ); ?>");
});
})(jQuery);
</script>
<?php endif; ?>