admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('extra_dl_nonce'),
'i18n' => [
'no_image' => __('Please select an image in the editor.', 'wp-extra'),
'already_local' => __('This image is already in your Media Library.', 'wp-extra'),
'success' => __('✅ Image successfully downloaded and replaced.', 'wp-extra'),
'error' => __('❌ Failed to download the image.', 'wp-extra'),
'connection' => __('❌ Connection error.', 'wp-extra'),
],
]);
}
}
public function ajax_download_image() {
check_ajax_referer('extra_dl_nonce', 'nonce');
$url = esc_url_raw($_POST['url'] ?? '');
$post_id = intval($_POST['post_id'] ?? 0);
$alt = sanitize_text_field($_POST['alt'] ?? '');
$title = sanitize_text_field($_POST['title'] ?? '');
if (empty($url) || !$post_id || !wp_http_validate_url($url)) {
wp_send_json_error(['message' => __('Missing or invalid data.', 'wp-extra')]);
}
if (!current_user_can('edit_post', $post_id)) {
wp_send_json_error(['message' => __('You do not have permission to edit this post.', 'wp-extra')]);
}
$post = get_post($post_id);
if (!$post) {
wp_send_json_error(['message' => __('Post not found.', 'wp-extra')]);
}
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
$tmp = download_url($url);
if (is_wp_error($tmp)) {
wp_send_json_error(['message' => sprintf(__('Download failed: %s', 'wp-extra'), $tmp->get_error_message())]);
}
$slug = sanitize_title($post->post_name ?: $post->post_title);
$ext = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg';
if (empty($slug)) {
$filename = basename(parse_url($url, PHP_URL_PATH));
} else {
$filename = "{$slug}.{$ext}";
}
$file = [
'name' => $filename,
'type' => mime_content_type($tmp),
'tmp_name' => $tmp,
'size' => filesize($tmp),
];
$attachment_id = media_handle_sideload($file, $post_id);
if (is_wp_error($attachment_id)) {
@unlink($tmp);
wp_send_json_error(['message' => __('Could not import image.', 'wp-extra')]);
}
if ($alt) update_post_meta($attachment_id, '_wp_attachment_image_alt', $alt);
if ($title) wp_update_post(['ID' => $attachment_id, 'post_title' => $title]);
$new_url = wp_get_attachment_url($attachment_id);
wp_send_json_success(['new_url' => $new_url]);
}
public function remove_gutenberg() {
$current_screen = get_current_screen();
if($current_screen->id !== 'page' ) {
add_filter('use_block_editor_for_post_type', '__return_false', 100);
}
}
public function classic_editor_add_edit_links ( $actions, $post ) {
if ( 'trash' === $post->post_status || ! post_type_supports( $post->post_type, 'editor' ) ) {
return $actions;
}
$edit_url = get_edit_post_link( $post->ID, 'raw' );
if ( ! $edit_url ) {
return $actions;
}
if ( $post->post_type == 'page' ) {
$edit_url = add_query_arg( 'classic-editor', '', $edit_url );
$title = _draft_or_post_title( $post->ID );
$edit_action = array(
'classic' => sprintf(
'%s',
esc_url( $edit_url ),
esc_attr( sprintf(
__( 'Classic Block Keyboard Shortcuts' ),
$title
) ),
__('Edit Classic')
),
);
$edit_offset = array_search( 'edit', array_keys( $actions ), true );
array_splice( $actions, $edit_offset, 0, $edit_action );
}
return $actions;
}
public function disable_wpautop_for_page_classic( $init ) {
if ( ! is_admin() ) {
return $init;
}
if ( ! function_exists( 'get_current_screen' ) ) {
return $init;
}
$screen = get_current_screen();
if ( $screen->post_type !== 'page' ) {
return $init;
}
$init['wpautop'] = false;
$init['forced_root_block'] = false;
return $init;
}
public function classic_editor_redirect ( $location ) {
if ( isset( $_REQUEST['classic-editor'] ) || ( isset( $_POST['_wp_http_referer'] ) && strpos( $_POST['_wp_http_referer'], '&classic-editor' ) !== false ) ) {
$location = add_query_arg( 'classic-editor', '', $location );
}
return $location;
}
public function register_classic_editor_gutenberg_plugin() {
$screen = get_current_screen();
if ( ! $screen || $screen->post_type !== 'page' || isset( $_GET['classic-editor'] ) ) {
return;
}
global $post;
$post_id = $post->ID ?? 0;
if ( $post_id ) {
$classic_url = add_query_arg( [ 'post' => $post_id, 'action' => 'edit', 'classic-editor' => '' ], admin_url( 'post.php' ) );
} else {
$classic_url = add_query_arg( [ 'post_type' => 'page', 'classic-editor' => '' ], admin_url( 'post-new.php' ) );
}
$script = sprintf(
"(function(wp) {
'use strict';
if (!wp || !wp.domReady || !wp.data) return;
var ClassicSwitch = {
headerToolbar: null,
btn: null,
editUrl: %s,
btnText: %s,
icon: '',
init: function() {
if (document.getElementById('wpex-classic-edit-btn')) return;
this.headerToolbar = document.querySelector('.block-editor .edit-post-header__toolbar') || document.querySelector('.block-editor .editor-header__toolbar');
if (!this.headerToolbar) return;
var btn = document.createElement('a');
btn.id = 'wpex-classic-edit-btn';
btn.className = 'components-button is-button is-secondary is-large';
btn.href = this.editUrl;
btn.title = this.btnText;
btn.style.cssText = 'margin-left:6px;margin-right:6px;display:inline-flex;align-items:center;height:32px;line-height:30px;padding:0 10px;vertical-align:middle;';
btn.innerHTML = this.icon + this.btnText;
var uxBtn = this.headerToolbar.querySelector('#uxbuilder-edit-button, a[href*=\"uxbuilder\"], .uxbuilder-button');
if (uxBtn && uxBtn.parentNode) {
uxBtn.parentNode.insertBefore(btn, uxBtn.nextSibling);
} else {
this.headerToolbar.appendChild(btn);
}
this.btn = btn;
}
};
wp.domReady(function() {
wp.data.subscribe(function() {
ClassicSwitch.init();
});
});
})(window.wp);",
wp_json_encode( esc_url_raw( $classic_url ) ),
wp_json_encode( __( 'Classic Editor', 'wp-extra' ) )
);
wp_add_inline_script( 'wp-edit-post', $script );
}
public function render_block_editor_switch_button( $post ) {
if ( ! $post || $post->post_type !== 'page' || ! isset( $_GET['classic-editor'] ) ) {
return;
}
$block_url = remove_query_arg( 'classic-editor' );
$block_text = __( 'Block Editor', 'wp-extra' );
?>
template ) {
add_action( 'admin_head', [$this, 'remove_ux_mce'], 1 );
}
add_filter( 'mce_external_plugins', [$this, 'mce_plugin' ]);
add_filter( 'mce_buttons', [$this, 'mce_buttons' ]);
add_filter( 'mce_buttons_2', [$this, 'mce_buttons_2']);
add_action( 'wp_enqueue_scripts', [$this, 'enqueue_frontend_styles'] );
add_filter( 'mce_css', [$this, 'add_editor_styles'] );
if(Settings::get_option('signature')) {
add_shortcode('signature', [$this, 'shortcode_signature']);
if(Settings::get_option('signature_pos') == 'top') {
add_filter('the_content', [$this, 'add_signature_top']);
}
if(Settings::get_option('signature_pos') == 'bottom') {
add_filter('the_content', [$this, 'add_signature_bottom']);
}
}
if (Settings::get_option('mce_plugins') && !class_exists( 'RankMath' )) {
add_action( 'admin_enqueue_scripts', [$this, 'overwrite_wplink'], 999 );
}
}
public function enqueue_frontend_styles() {
wp_enqueue_style( 'wpex-checklist', plugins_url('/assets/css/checklist.min.css', WPEX_FILE), [], defined('WPEX_VERSION') ? WPEX_VERSION : null );
}
public function add_editor_styles( $mce_css ) {
$checklist_css = plugins_url('/assets/css/checklist.min.css', WPEX_FILE);
if ( ! empty( $mce_css ) ) {
$mce_css .= ',' . $checklist_css;
} else {
$mce_css = $checklist_css;
}
return $mce_css;
}
public function mce_plugin( $init ) {
$plugins = [];
if ( Settings::get_option( 'mce_plugins' ) ) {
$plugins = [
'table',
'visualblocks',
'searchreplace',
'letterspacing',
'changecase',
'cleanhtml',
'ultable',
'getimage',
'checklist',
];
}
if ( Settings::get_option( 'signature' ) ) {
$plugins[] = 'signature';
}
foreach ($plugins as $item) {
$init[$item] = plugins_url('/assets/tinymce/' . $item . '/plugin.min.js', WPEX_FILE);
}
return $init;
}
public function remove_ux_mce() {
remove_filter('mce_buttons', 'flatsome_mce_buttons_2');
remove_filter('mce_buttons_2', 'flatsome_font_buttons');
}
public function mce_buttons( $buttons ) {
array_splice( $buttons, 3, 0, 'underline' );
array_splice( $buttons, 4, 0, 'strikethrough' );
//array_splice( $buttons, 5, 0, 'hr' );
array_splice( $buttons, 11, 0, 'alignjustify' );
array_splice( $buttons, 13, 0, 'unlink' );
array_splice( $buttons, 14, 0, 'visualblocks' );
array_splice( $buttons, 15, 0, 'searchreplace' );
array_splice( $buttons, 16, 0, 'wp_code' );
// Place checklist dropdown right next to list buttons (numlist / bullist)
$pos = array_search( 'numlist', $buttons, true );
if ( false !== $pos ) {
array_splice( $buttons, $pos + 1, 0, 'checklist' );
} else {
$pos = array_search( 'bullist', $buttons, true );
if ( false !== $pos ) {
array_splice( $buttons, $pos + 1, 0, 'checklist' );
} else {
$buttons[] = 'checklist';
}
}
return $buttons;
}
public function mce_buttons_2( $buttons ) {
if(Settings::get_option('signature')) {
array_splice( $buttons, 6, 0, 'signature' );
}
array_splice( $buttons, 1, 0, 'fontselect' );
array_splice( $buttons, 2, 0, 'fontsizeselect' );
array_splice( $buttons, 3, 0, 'letterspacing' );
array_splice( $buttons, 4, 0, 'changecase' );
array_splice( $buttons, 7, 0, 'backcolor' );
array_splice( $buttons, 9, 0, 'table' );
array_splice( $buttons, 10, 0, 'cleanhtml' );
array_splice( $buttons, 12, 0, 'getimage' );
array_splice( $buttons, 20, 0, 'ultable' );
return $buttons;
}
public function remove_mce_buttons_2( $buttons ) {
$remove = array( 'hr', 'charmap', 'strikethrough', 'wp_help' );
return array_diff( $buttons, $remove );
}
public function overwrite_wplink() {
wp_deregister_script( 'wplink' );
wp_register_script( 'wplink', plugins_url('/assets/js/wplink.min.js', WPEX_FILE ), [ 'jquery', 'wp-a11y' ], '1.0', true );
wp_localize_script(
'wplink',
'wpLinkL10n',
[
'title' => esc_html__( 'Insert/edit link' ),
'update' => esc_html__( 'Update' ),
'save' => esc_html__( 'Add Link' ),
'noTitle' => esc_html__( '(no title)' ),
'noMatchesFound' => esc_html__( 'No matches found.' ),
'linkSelected' => esc_html__( 'Link selected.' ),
'linkInserted' => esc_html__( 'Link inserted.' ),
'relCheckbox' => __( 'Add rel="nofollow"' ),
'sponsoredCheckbox' => __( 'Add rel="sponsored"' ),
'linkTitle' => esc_html__( 'Link Title' ),
]
);
}
public function shortcode_signature() {
return do_shortcode(Settings::get_option('signature_content'));
}
public function add_signature_top($content) {
if ( ! is_singular( 'post' ) && ! is_singular( 'product' ) ) {
return $content;
}
$signature = do_shortcode('[signature]');
$content_with_signature_top = $signature . $content;
return $content_with_signature_top;
}
public function add_signature_bottom($content) {
if ( ! is_singular( 'post' ) && ! is_singular( 'product' ) ) {
return $content;
}
$signature = do_shortcode('[signature]');
$content_with_signature_bottom = $content . $signature;
return $content_with_signature_bottom;
}
public function signature() {
add_action('wp_ajax_get_signature_content', [$this, 'get_signature_content_callback']);
add_action('wp_ajax_nopriv_get_signature_content', [$this, 'get_signature_content_callback']);
}
public function get_signature_content_callback() {
wp_send_json_success(do_shortcode('[signature]'));
}
public function classic_widget() {
add_filter('gutenberg_use_widgets_block_editor', '__return_false');
add_filter('use_widgets_block_editor', '__return_false');
}
public function publish_btn() {
add_action( 'admin_enqueue_scripts', [$this, 'publish_button_enqueue'], 20 );
}
public function publish_button_enqueue() {
global $pagenow;
if ( is_admin() && ($pagenow == 'post.php' || $pagenow == 'post-new.php') ) {
wp_enqueue_script('publish-button', plugins_url('/assets/js/publish-button.min.js', WPEX_FILE ), array('jquery'), '1.0', true );
}
}
public function post_revisions() {
add_filter('wp_revisions_to_keep', [$this, 'limit_revisions'], 10, 2);
}
public function limit_revisions($num, $post) {
$limit = Settings::get_option('post_revisions');
if ($limit === '' || $limit === null || !is_numeric($limit)) {
return $num;
}
return max(0, (int) $limit);
}
public function delete_attached() {
add_action('before_delete_post', [$this, 'delete_attachments']);
}
public function delete_attachments($post_id) {
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
return;
}
$attachments = get_attached_media('', $post_id);
if (empty($attachments)) {
return;
}
global $wpdb;
foreach ($attachments as $attachment) {
if ($attachment->post_parent !== (int)$post_id) {
continue;
}
$other_thumb = $wpdb->get_var($wpdb->prepare(
"SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id' AND meta_value = %d AND post_id != %d LIMIT 1",
$attachment->ID,
$post_id
));
if ($other_thumb) {
wp_update_post([
'ID' => $attachment->ID,
'post_parent' => (int)$other_thumb,
]);
} else {
wp_delete_attachment($attachment->ID, true);
}
}
}
public function show_modified() {
add_filter('manage_post_posts_columns', [$this, 'modified_column_register']);
add_action('manage_post_posts_custom_column', [$this, 'modified_column_display'], 10, 2);
add_filter('manage_edit-post_sortable_columns', [$this, 'modified_column_register_sortable']);
add_action('admin_footer', [$this, 'script_modified']);
add_action('wp_ajax_convert_post_date', [$this, 'convert_post_date']);
}
public function modified_column_register($columns) {
$columns['modified'] = __('Last Modified');
return $columns;
}
public function modified_column_display($column_name, $post_id) {
if ($column_name !== 'modified') return;
$author_id = get_post_field('post_modified_by', $post_id);
if ($author_id) {
echo '' . esc_html(get_the_author_meta('display_name', $author_id)) . '
';
}
echo ' ';
echo sprintf(
esc_html__('%1$s at %2$s'),
esc_html(get_the_modified_date('d/m/Y', $post_id)),
esc_html(get_the_modified_time('', $post_id))
);
}
public function modified_column_register_sortable($columns) {
$columns['modified'] = 'modified';
return $columns;
}
public function script_modified() {
$screen = get_current_screen();
if (!$screen || $screen->base !== 'edit' || $screen->post_type !== 'post') return;
$nonce = wp_create_nonce('convert_post_date_nonce');
?>
post_type !== 'post') {
wp_send_json_error();
}
global $wpdb;
$publish_date = $post->post_date;
$gmt = get_gmt_from_date($publish_date);
$result = $wpdb->update(
$wpdb->posts,
[
'post_modified' => $publish_date,
'post_modified_gmt' => $gmt
],
['ID' => $post_id],
['%s', '%s'],
['%d']
);
if ($result === false) {
wp_send_json_error();
}
clean_post_cache($post_id);
wp_send_json_success();
}
public function lock_modified() {
add_filter('wp_insert_post_data', [$this, 'disable_post_modified'], 99, 2);
}
public function disable_post_modified($data, $postarr) {
if (empty($postarr['ID'])) return $data;
$post = get_post($postarr['ID']);
if (!$post || $post->post_type !== 'post') return $data;
if ($post->post_status !== 'publish') return $data;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $data;
$data['post_modified'] = $post->post_modified;
$data['post_modified_gmt'] = $post->post_modified_gmt;
return $data;
}
public function img_column() {
add_filter('manage_post_posts_columns', [$this, 'add_img_column']);
add_action('manage_post_posts_custom_column', [$this, 'manage_img_column'], 10, 2);
add_action('admin_head-edit.php', [$this, 'img_column_css']);
}
public function img_column_css() {
$screen = get_current_screen();
if (!$screen || $screen->post_type !== 'post') {
return;
}
echo '';
}
public function add_img_column($columns) {
$new_columns = [];
foreach ($columns as $key => $title) {
if ($key === 'title') {
$new_columns['thumbnail'] = '' . esc_html__('Thumbnail', 'wp-extra') . '';
}
$new_columns[$key] = $title;
}
return $new_columns;
}
public function manage_img_column($column_name, $post_id) {
if ('thumbnail' === $column_name) {
$edit_link = get_edit_post_link($post_id);
echo '