File: /www/wwwroot/ahmsolaiman.com/wp-content/plugins/types/application/controllers/ajax.php
<?php
/**
* Main AJAX call controller for Types.
*
* This class can be used in any way only after the Common Library is loaded.
*
* Please read the important usage instructions for the superclass:
*
* @inheritdoc
*
* @since 2.0
*/
class Types_Ajax extends Toolset_Ajax {
const HANDLER_CLASS_PREFIX = 'Types_Ajax_Handler_';
// Action names
const CALLBACK_FIELD_CONTROL_ACTION = 'field_control_action';
const CALLBACK_CHECK_SLUG_CONFLICTS = 'check_slug_conflicts';
const CALLBACK_SETTINGS_ACTION = 'settings_action';
const CALLBACK_M2M_MIGRATION_PREVIEW_RELATIONSHIPS = 'm2m_migration_preview_relationships';
const CALLBACK_M2M_MIGRATION_PREVIEW_ASSOCIATIONS = 'm2m_migration_preview_associations';
const CALLBACK_M2M_SCAN_LEGACY_CUSTOM_CODE = 'm2m_scan_legacy_custom_code';
const CALLBACK_CUSTOM_FIELDS_ACTION = 'custom_fields_action';
const CALLBACK_RELATIONSHIPS_ACTION = 'relationships_action';
const CALLBACK_DELETE_INTERMEDIARY_POST_TYPE_ACTION = 'delete_intermediary_post_type';
const CALLBACK_RELATED_CONTENT_ACTION = 'related_content_action';
const CALLBACK_FIELD_GROUP_EDIT_ACTION = 'field_group_edit_action';
const CALLBACK_REPEATABLE_GROUP = 'repeatable_group';
const CALLBACK_POST_REFERENCE_FIELD = 'post_reference_field';
const CALLBACK_INTERMEDIARY_PARENT_CHILD = 'intermediary_parent_child';
const CALLBACK_ASSOCIATIONS_IMPORT = 'associations_import';
const CALLBACK_MERGE_RELATIONSHIPS = 'merge_relationships';
const CALLBACK_SET_EDITOR_MODE = 'set_editor_mode';
const CALLBACK_REEVALUATE_DISPLAYED_FIELD_GROUPS = 'reevaluate_displayed_field_groups';
private static $callbacks = array(
self::CALLBACK_FIELD_CONTROL_ACTION,
self::CALLBACK_CHECK_SLUG_CONFLICTS,
self::CALLBACK_SETTINGS_ACTION,
self::CALLBACK_M2M_MIGRATION_PREVIEW_RELATIONSHIPS,
self::CALLBACK_M2M_MIGRATION_PREVIEW_ASSOCIATIONS,
self::CALLBACK_CUSTOM_FIELDS_ACTION,
self::CALLBACK_RELATIONSHIPS_ACTION,
self::CALLBACK_RELATED_CONTENT_ACTION,
self::CALLBACK_FIELD_GROUP_EDIT_ACTION,
self::CALLBACK_REPEATABLE_GROUP,
self::CALLBACK_POST_REFERENCE_FIELD,
self::CALLBACK_M2M_SCAN_LEGACY_CUSTOM_CODE,
self::CALLBACK_DELETE_INTERMEDIARY_POST_TYPE_ACTION,
self::CALLBACK_INTERMEDIARY_PARENT_CHILD,
self::CALLBACK_ASSOCIATIONS_IMPORT,
self::CALLBACK_MERGE_RELATIONSHIPS,
self::CALLBACK_SET_EDITOR_MODE,
self::CALLBACK_REEVALUATE_DISPLAYED_FIELD_GROUPS,
);
private static $types_instance;
public static function get_instance() {
if ( null === self::$types_instance ) {
self::$types_instance = new self();
}
return self::$types_instance;
}
/**
* @inheritDoc
* @return Types_Ajax
* @since 3.4 In Types, we also allow namespaced AJAX handler classes now.
*/
public static function initialize() {
/** @var Types_Ajax $instance */
$instance = parent::initialize();
// Dynamically register a namespaced AJAX call handler for actions with the plugin prefix.
//
// This allows us to abandon the endless updates to self::$callbacks.
//
// Note that this is safe because the callbacks will only work when there is a dedicated handler class
// implemented.
add_action( 'admin_init', function () use ( $instance ) {
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX || ! array_key_exists( 'action', $_POST ) ) {
// This should never happen, due to how this class is initialized, but we can never be too sure.
return;
}
$action_name = esc_attr( $_POST['action'] );
$prefix = $instance->get_plugin_slug( false ) . self::DELIMITER;
if ( substr( $action_name, 0, strlen( $prefix ) ) !== $prefix ) {
return;
}
add_action(
'wp_ajax_' . $action_name,
[ $instance, self::CALLBACK_PREFIX . substr( $action_name, strlen( $prefix ) ) ]
);
} );
return $instance;
}
/**
* @inheritDoc
* @since 3.4 Added support for namespaced AJAX handler classes.
*/
protected function name_parts_to_callback_name( $name_parts ) {
$default_class_name = parent::name_parts_to_callback_name( $name_parts );
if ( class_exists( $default_class_name ) ) {
return $default_class_name;
}
// No class handler by the legacy naming conventions, let's try with a namespace.
// Yes, PHP is not case-sensitive. But our classmap-based autoloader is.
$namespaced_class_name = '\OTGS\Toolset\Types\Ajax\Handler\\' . implode( '', array_map( function ( $part ) {
return ucfirst( $part );
}, $name_parts ) );
if ( ! class_exists( $namespaced_class_name ) ) {
return '';
}
return $namespaced_class_name;
}
/**
* @inheritdoc
*
* @param bool $capitalized
*
* @return string
* @since m2m
*/
protected function get_plugin_slug( $capitalized = false ) {
return ( $capitalized ? 'Types' : 'types' );
}
/**
* @inheritdoc
* @return array
* @since m2m
*/
protected function get_callback_names() {
return self::$callbacks;
}
/**
* Handles all initialization of everything except AJAX callbacks itself that is needed when
* we're DOING_AJAX.
*
* Since this is executed on every AJAX call, make sure it's as lightweight as possible.
*
* @since 2.1
*/
protected function additional_ajax_init() {
// On the Add Term page, we need to initialize the page controller WPCF_GUI_Term_Field_Editing
// so that it saves term fields (if there are any).
add_action( 'create_term', array( $this, 'prepare_for_term_creation' ) );
add_action( 'updated_user_meta', array( $this, 'capture_columnshidden_update' ), 10, 4 );
// Handle partially refactored AJAX callbacks coming from wpcf_ajax_embedded()
// or from wpcf_ajax(). The wp_ajax_wpcf_ajax action will be reached only if the $fallthrough variables
// in those functions are set to true (which means that the call was not handled).
add_action( 'wp_ajax_wpcf_ajax', array( $this, 'do_legacy_wpcf_ajax' ) );
}
/**
* On the Add Term page, we need to initialize the page controller WPCF_GUI_Term_Field_Editing
* so that it saves term fields (if there are any).
*
* @since 2.1
* @codeCoverageIgnore Interacts with legacy code.
*/
public function prepare_for_term_creation() {
// Takes care of the rest, mainly we're interested about the create_{$taxonomy} action which follows
// immediately after create_term.
//
// On actions fired on the Add Term page, the action POST variable is allways add-tag and the screen is set
// to edit-{$taxonomy}. When creating the term on the post edit page, for example, the screen is not set. We use
// this to further limit the resource wasting. However, initializing the controller even if it's not supposed to
// will not lead to any errors - it gives up gracefully.
$action = toolset_getpost( 'action' );
$screen = toolset_getpost( 'screen', null );
if ( 'add-tag' === $action && null !== $screen ) {
WPCF_GUI_Term_Field_Editing::initialize();
}
}
/**
* When updating screen options with hidden listing columns, we may need to store additional data.
*
* See WPCF_GUI_Term_Field_Editing::maybe_disable_column_autohiding() for details.
*
* @param mixed $meta_id Ignored.
* @param mixed $object_id Ignored.
* @param string $meta_key Meta key.
* @param mixed $_meta_value Meta value. We expect it to be an array.
*
* @since 2.1
* @codeCoverageIgnore Interacts with legacy code.
*/
public function capture_columnshidden_update(
/** @noinspection PhpUnusedParameterInspection */ $meta_id, $object_id, $meta_key, $_meta_value
) {
// We're looking for a meta_key that looks like "manage{$page_name}columnshidden".
$txt_columnshidden = 'columnshidden';
$is_columnshidden_option = (
0 === strcmp(
$txt_columnshidden, substr( $meta_key, strlen( $txt_columnshidden ) * - 1 )
) );
if ( $is_columnshidden_option ) {
// Extract the page name from the meta_key
$strip_begin = strlen( 'manage' );
$strip_end = strlen( $txt_columnshidden );
$page_name = substr( $meta_key, $strip_begin, strlen( $meta_key ) - ( $strip_begin + $strip_end ) );
// Determine if we're editing a taxonomy
$txt_edit = 'edit-';
$txt_edit_len = strlen( $txt_edit );
$is_tax_edit_page = ( 0 === strcmp( $txt_edit, substr( $page_name, 0, $txt_edit_len ) ) );
// This is not 100% certain but attempting to handle a taxonomy that doesn't exist does no harm.
if ( $is_tax_edit_page ) {
// Now we know that we need to perform the extra action.
$taxonomy_name = substr( $page_name, $txt_edit_len );
$edit_term_page_extension = WPCF_GUI_Term_Field_Editing::get_instance();
$edit_term_page_extension->maybe_disable_column_autohiding( $taxonomy_name, $_meta_value, $page_name );
}
}
}
/**
* This offers a possibility to handle legacy AJAX wp_ajax_wpcf_ajax calls
* if they're not handled in the legacy code anymore.
*
* Note that the method needs to always finish with die() to keep consistency with the legacy code.
*
* @since 2.2.16
*/
public function do_legacy_wpcf_ajax() {
die();
}
}