PluginProbe
WP EXtra – One Click Optimize / trunk
WP EXtra – One Click Optimize vtrunk
8.7.1 8.6.8 8.7.0 trunk 5.9 8.0 8.5.0 8.5.4 8.5.5 8.6.0 8.6.1 8.6.2 8.6.3 8.6.5
wp-extra / src / Modules / Common / Posts.php

Posts.php in WP EXtra – One Click Optimize trunk, at src/Modules/Common/Posts.php

780 lines 28.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WPEXtra\Modules\Common;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 use WPEXtra\Settings;
9 use WPEXtra\Helper;
10 use WPEXtra\Base;
11
12 class Posts extends Base {
13
14 public function __construct() {
15 parent::__construct();
16 }
17
18 protected $features = [
19 'mce_classic',
20 'mce_plugins',
21 'signature',
22 'classic_widget',
23 'disable_widget',
24 'publish_btn',
25 'post_revisions',
26 'delete_attached',
27 'lock_modified',
28 'show_modified',
29 'img_column',
30 'disable_tags',
31 ];
32
33 public function disable_widget() {
34 add_action('widgets_init', [$this, 'disable_sidebar_widgets'], 100);
35 }
36
37 public function disable_sidebar_widgets() {
38 if (!is_admin() || (isset($_GET['page']) && $_GET['page'] === 'wp-extra')) {
39 return;
40 }
41 $widgets = (array) Helper::get_option('disable_widget', []);
42 if (!empty($widgets)) {
43 foreach ($widgets as $widget_class) {
44 if (class_exists($widget_class)) {
45 unregister_widget($widget_class);
46 }
47 }
48 }
49 }
50
51 public function mce_classic() {
52 add_action( 'current_screen', [$this, 'remove_gutenberg'] );
53 add_filter( 'page_row_actions', [$this, 'classic_editor_add_edit_links'], 15, 2 );
54 add_filter( 'post_row_actions', [$this, 'classic_editor_add_edit_links'], 15, 2 );
55 if ( isset( $_GET['classic-editor'] )) {
56 add_filter( 'use_block_editor_for_post_type', '__return_false', 100 );
57 add_filter( 'tiny_mce_before_init', [$this, 'disable_wpautop_for_page_classic'] );
58 add_action( 'edit_form_top', [$this, 'render_block_editor_switch_button'] );
59 } else {
60 add_action( 'enqueue_block_editor_assets', [$this, 'register_classic_editor_gutenberg_plugin'] );
61 }
62 add_filter( 'redirect_post_location', [$this, 'classic_editor_redirect' ]);
63 add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
64 add_action('wp_ajax_getimage_image', [$this, 'ajax_download_image']);
65
66 }
67
68 public function enqueue_scripts($hook) {
69 if ($hook === 'post.php' || $hook === 'post-new.php') {
70 wp_localize_script('jquery', 'EXTRA_DL', [
71 'ajax_url' => admin_url('admin-ajax.php'),
72 'nonce' => wp_create_nonce('extra_dl_nonce'),
73 'i18n' => [
74 'no_image' => __('Please select an image in the editor.', 'wp-extra'),
75 'already_local' => __('This image is already in your Media Library.', 'wp-extra'),
76 'success' => __('�
77 Image successfully downloaded and replaced.', 'wp-extra'),
78 'error' => __(' Failed to download the image.', 'wp-extra'),
79 'connection' => __(' Connection error.', 'wp-extra'),
80 ],
81 ]);
82 }
83 }
84
85 public function ajax_download_image() {
86 check_ajax_referer('extra_dl_nonce', 'nonce');
87
88 $url = esc_url_raw($_POST['url'] ?? '');
89 $post_id = intval($_POST['post_id'] ?? 0);
90 $alt = sanitize_text_field($_POST['alt'] ?? '');
91 $title = sanitize_text_field($_POST['title'] ?? '');
92
93 if (empty($url) || !$post_id || !wp_http_validate_url($url)) {
94 wp_send_json_error(['message' => __('Missing or invalid data.', 'wp-extra')]);
95 }
96
97 if (!current_user_can('edit_post', $post_id)) {
98 wp_send_json_error(['message' => __('You do not have permission to edit this post.', 'wp-extra')]);
99 }
100
101 $post = get_post($post_id);
102 if (!$post) {
103 wp_send_json_error(['message' => __('Post not found.', 'wp-extra')]);
104 }
105
106 require_once(ABSPATH . 'wp-admin/includes/file.php');
107 require_once(ABSPATH . 'wp-admin/includes/media.php');
108 require_once(ABSPATH . 'wp-admin/includes/image.php');
109
110 $tmp = download_url($url);
111 if (is_wp_error($tmp)) {
112 wp_send_json_error(['message' => sprintf(__('Download failed: %s', 'wp-extra'), $tmp->get_error_message())]);
113 }
114
115 $slug = sanitize_title($post->post_name ?: $post->post_title);
116 $ext = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg';
117
118 if (empty($slug)) {
119 $filename = basename(parse_url($url, PHP_URL_PATH));
120 } else {
121 $filename = "{$slug}.{$ext}";
122 }
123
124 $file = [
125 'name' => $filename,
126 'type' => mime_content_type($tmp),
127 'tmp_name' => $tmp,
128 'size' => filesize($tmp),
129 ];
130
131 $attachment_id = media_handle_sideload($file, $post_id);
132
133 if (is_wp_error($attachment_id)) {
134 @unlink($tmp);
135 wp_send_json_error(['message' => __('Could not import image.', 'wp-extra')]);
136 }
137
138 if ($alt) update_post_meta($attachment_id, '_wp_attachment_image_alt', $alt);
139 if ($title) wp_update_post(['ID' => $attachment_id, 'post_title' => $title]);
140
141 $new_url = wp_get_attachment_url($attachment_id);
142
143 wp_send_json_success(['new_url' => $new_url]);
144 }
145
146 public function remove_gutenberg() {
147 $current_screen = get_current_screen();
148 if($current_screen->id !== 'page' ) {
149 add_filter('use_block_editor_for_post_type', '__return_false', 100);
150 }
151 }
152
153 public function classic_editor_add_edit_links ( $actions, $post ) {
154 if ( 'trash' === $post->post_status || ! post_type_supports( $post->post_type, 'editor' ) ) {
155 return $actions;
156 }
157 $edit_url = get_edit_post_link( $post->ID, 'raw' );
158 if ( ! $edit_url ) {
159 return $actions;
160 }
161 if ( $post->post_type == 'page' ) {
162 $edit_url = add_query_arg( 'classic-editor', '', $edit_url );
163 $title = _draft_or_post_title( $post->ID );
164 $edit_action = array(
165 'classic' => sprintf(
166 '<a href="%s" aria-label="%s">%s</a>',
167 esc_url( $edit_url ),
168 esc_attr( sprintf(
169 __( 'Classic Block Keyboard Shortcuts' ),
170 $title
171 ) ),
172 __('Edit Classic')
173 ),
174 );
175 $edit_offset = array_search( 'edit', array_keys( $actions ), true );
176 array_splice( $actions, $edit_offset, 0, $edit_action );
177 }
178 return $actions;
179 }
180
181 public function disable_wpautop_for_page_classic( $init ) {
182 if ( ! is_admin() ) {
183 return $init;
184 }
185 if ( ! function_exists( 'get_current_screen' ) ) {
186 return $init;
187 }
188 $screen = get_current_screen();
189 if ( $screen->post_type !== 'page' ) {
190 return $init;
191 }
192 $init['wpautop'] = false;
193 $init['forced_root_block'] = false;
194 return $init;
195 }
196
197 public function classic_editor_redirect ( $location ) {
198 if ( isset( $_REQUEST['classic-editor'] ) || ( isset( $_POST['_wp_http_referer'] ) && strpos( $_POST['_wp_http_referer'], '&classic-editor' ) !== false ) ) {
199 $location = add_query_arg( 'classic-editor', '', $location );
200 }
201 return $location;
202 }
203
204 public function register_classic_editor_gutenberg_plugin() {
205 $screen = get_current_screen();
206 if ( ! $screen || $screen->post_type !== 'page' || isset( $_GET['classic-editor'] ) ) {
207 return;
208 }
209 global $post;
210 $post_id = $post->ID ?? 0;
211 if ( $post_id ) {
212 $classic_url = add_query_arg( [ 'post' => $post_id, 'action' => 'edit', 'classic-editor' => '' ], admin_url( 'post.php' ) );
213 } else {
214 $classic_url = add_query_arg( [ 'post_type' => 'page', 'classic-editor' => '' ], admin_url( 'post-new.php' ) );
215 }
216
217 $script = sprintf(
218 "(function(wp) {
219 'use strict';
220 if (!wp || !wp.domReady || !wp.data) return;
221
222 var ClassicSwitch = {
223 headerToolbar: null,
224 btn: null,
225 editUrl: %s,
226 btnText: %s,
227 icon: '<span class=\"dashicons dashicons-edit\" style=\"font-size:16px;width:16px;height:16px;line-height:16px;margin-right:4px;\"></span>',
228
229 init: function() {
230 if (document.getElementById('wpex-classic-edit-btn')) return;
231
232 this.headerToolbar = document.querySelector('.block-editor .edit-post-header__toolbar') || document.querySelector('.block-editor .editor-header__toolbar');
233 if (!this.headerToolbar) return;
234
235 var btn = document.createElement('a');
236 btn.id = 'wpex-classic-edit-btn';
237 btn.className = 'components-button is-button is-secondary is-large';
238 btn.href = this.editUrl;
239 btn.title = this.btnText;
240 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;';
241 btn.innerHTML = this.icon + this.btnText;
242
243 var uxBtn = this.headerToolbar.querySelector('#uxbuilder-edit-button, a[href*=\"uxbuilder\"], .uxbuilder-button');
244 if (uxBtn && uxBtn.parentNode) {
245 uxBtn.parentNode.insertBefore(btn, uxBtn.nextSibling);
246 } else {
247 this.headerToolbar.appendChild(btn);
248 }
249
250 this.btn = btn;
251 }
252 };
253
254 wp.domReady(function() {
255 wp.data.subscribe(function() {
256 ClassicSwitch.init();
257 });
258 });
259 })(window.wp);",
260 wp_json_encode( esc_url_raw( $classic_url ) ),
261 wp_json_encode( __( 'Classic Editor', 'wp-extra' ) )
262 );
263
264 wp_add_inline_script( 'wp-edit-post', $script );
265 }
266
267 public function render_block_editor_switch_button( $post ) {
268 if ( ! $post || $post->post_type !== 'page' || ! isset( $_GET['classic-editor'] ) ) {
269 return;
270 }
271 $block_url = remove_query_arg( 'classic-editor' );
272 $block_text = __( 'Block Editor', 'wp-extra' );
273 ?>
274 <script type="text/javascript">
275 (function() {
276 function attachBlockEditorTab() {
277 var uxWrapper = document.getElementById('uxbuilder-enable-disable');
278 if (!uxWrapper || document.getElementById('wpex-block-editor-tab')) return;
279
280 var tab = document.createElement('a');
281 tab.id = 'wpex-block-editor-tab';
282 tab.href = <?php echo json_encode( esc_url_raw( $block_url ) ); ?>;
283 tab.className = 'nav-tab';
284 tab.innerHTML = '<span class="dashicons dashicons-block-default" style="font-size:16px;width:16px;height:16px;margin-right:4px;vertical-align:text-bottom;"></span>' + <?php echo json_encode( $block_text ); ?>;
285
286 var uxBtn = uxWrapper.querySelector('a[href*="uxbuilder"], a[href*="app=uxbuilder"]');
287 if (uxBtn) {
288 uxBtn.parentNode.insertBefore(tab, uxBtn);
289 } else {
290 uxWrapper.appendChild(tab);
291 }
292 }
293
294 if (document.readyState === 'loading') {
295 document.addEventListener('DOMContentLoaded', attachBlockEditorTab);
296 } else {
297 attachBlockEditorTab();
298 }
299 setTimeout(attachBlockEditorTab, 200);
300 setTimeout(attachBlockEditorTab, 800);
301 })();
302 </script>
303 <?php
304 }
305
306 public function mce_plugins() {
307 if ( 'flatsome' === wp_get_theme()->template ) {
308 add_action( 'admin_head', [$this, 'remove_ux_mce'], 1 );
309 }
310 add_filter( 'mce_external_plugins', [$this, 'mce_plugin' ]);
311 add_filter( 'mce_buttons', [$this, 'mce_buttons' ]);
312 add_filter( 'mce_buttons_2', [$this, 'mce_buttons_2']);
313 add_action( 'wp_enqueue_scripts', [$this, 'enqueue_frontend_styles'] );
314 add_filter( 'mce_css', [$this, 'add_editor_styles'] );
315 if(Settings::get_option('signature')) {
316 add_shortcode('signature', [$this, 'shortcode_signature']);
317 if(Settings::get_option('signature_pos') == 'top') {
318 add_filter('the_content', [$this, 'add_signature_top']);
319 }
320 if(Settings::get_option('signature_pos') == 'bottom') {
321 add_filter('the_content', [$this, 'add_signature_bottom']);
322 }
323 }
324 if (Settings::get_option('mce_plugins') && !class_exists( 'RankMath' )) {
325 add_action( 'admin_enqueue_scripts', [$this, 'overwrite_wplink'], 999 );
326 }
327 }
328
329 public function enqueue_frontend_styles() {
330 wp_enqueue_style( 'wpex-checklist', plugins_url('/assets/css/checklist.min.css', WPEX_FILE), [], defined('WPEX_VERSION') ? WPEX_VERSION : null );
331 }
332
333 public function add_editor_styles( $mce_css ) {
334 $checklist_css = plugins_url('/assets/css/checklist.min.css', WPEX_FILE);
335 if ( ! empty( $mce_css ) ) {
336 $mce_css .= ',' . $checklist_css;
337 } else {
338 $mce_css = $checklist_css;
339 }
340 return $mce_css;
341 }
342
343 public function mce_plugin( $init ) {
344 $plugins = [];
345 if ( Settings::get_option( 'mce_plugins' ) ) {
346 $plugins = [
347 'table',
348 'visualblocks',
349 'searchreplace',
350 'letterspacing',
351 'changecase',
352 'cleanhtml',
353 'ultable',
354 'getimage',
355 'checklist',
356 ];
357 }
358 if ( Settings::get_option( 'signature' ) ) {
359 $plugins[] = 'signature';
360 }
361 foreach ($plugins as $item) {
362 $init[$item] = plugins_url('/assets/tinymce/' . $item . '/plugin.min.js', WPEX_FILE);
363 }
364 return $init;
365 }
366
367 public function remove_ux_mce() {
368 remove_filter('mce_buttons', 'flatsome_mce_buttons_2');
369 remove_filter('mce_buttons_2', 'flatsome_font_buttons');
370 }
371
372 public function mce_buttons( $buttons ) {
373 array_splice( $buttons, 3, 0, 'underline' );
374 array_splice( $buttons, 4, 0, 'strikethrough' );
375 //array_splice( $buttons, 5, 0, 'hr' );
376 array_splice( $buttons, 11, 0, 'alignjustify' );
377 array_splice( $buttons, 13, 0, 'unlink' );
378 array_splice( $buttons, 14, 0, 'visualblocks' );
379 array_splice( $buttons, 15, 0, 'searchreplace' );
380 array_splice( $buttons, 16, 0, 'wp_code' );
381
382 // Place checklist dropdown right next to list buttons (numlist / bullist)
383 $pos = array_search( 'numlist', $buttons, true );
384 if ( false !== $pos ) {
385 array_splice( $buttons, $pos + 1, 0, 'checklist' );
386 } else {
387 $pos = array_search( 'bullist', $buttons, true );
388 if ( false !== $pos ) {
389 array_splice( $buttons, $pos + 1, 0, 'checklist' );
390 } else {
391 $buttons[] = 'checklist';
392 }
393 }
394
395 return $buttons;
396 }
397
398 public function mce_buttons_2( $buttons ) {
399 if(Settings::get_option('signature')) {
400 array_splice( $buttons, 6, 0, 'signature' );
401 }
402 array_splice( $buttons, 1, 0, 'fontselect' );
403 array_splice( $buttons, 2, 0, 'fontsizeselect' );
404 array_splice( $buttons, 3, 0, 'letterspacing' );
405 array_splice( $buttons, 4, 0, 'changecase' );
406 array_splice( $buttons, 7, 0, 'backcolor' );
407 array_splice( $buttons, 9, 0, 'table' );
408 array_splice( $buttons, 10, 0, 'cleanhtml' );
409 array_splice( $buttons, 12, 0, 'getimage' );
410 array_splice( $buttons, 20, 0, 'ultable' );
411 return $buttons;
412 }
413
414 public function remove_mce_buttons_2( $buttons ) {
415 $remove = array( 'hr', 'charmap', 'strikethrough', 'wp_help' );
416 return array_diff( $buttons, $remove );
417 }
418
419 public function overwrite_wplink() {
420 wp_deregister_script( 'wplink' );
421 wp_register_script( 'wplink', plugins_url('/assets/js/wplink.min.js', WPEX_FILE ), [ 'jquery', 'wp-a11y' ], '1.0', true );
422 wp_localize_script(
423 'wplink',
424 'wpLinkL10n',
425 [
426 'title' => esc_html__( 'Insert/edit link' ),
427 'update' => esc_html__( 'Update' ),
428 'save' => esc_html__( 'Add Link' ),
429 'noTitle' => esc_html__( '(no title)' ),
430 'noMatchesFound' => esc_html__( 'No matches found.' ),
431 'linkSelected' => esc_html__( 'Link selected.' ),
432 'linkInserted' => esc_html__( 'Link inserted.' ),
433 'relCheckbox' => __( 'Add <code>rel="nofollow"</code>' ),
434 'sponsoredCheckbox' => __( 'Add <code>rel="sponsored"</code>' ),
435 'linkTitle' => esc_html__( 'Link Title' ),
436 ]
437 );
438 }
439
440 public function shortcode_signature() {
441 return do_shortcode(Settings::get_option('signature_content'));
442 }
443
444 public function add_signature_top($content) {
445 if ( ! is_singular( 'post' ) && ! is_singular( 'product' ) ) {
446 return $content;
447 }
448
449 $signature = do_shortcode('[signature]');
450 $content_with_signature_top = $signature . $content;
451 return $content_with_signature_top;
452 }
453
454 public function add_signature_bottom($content) {
455 if ( ! is_singular( 'post' ) && ! is_singular( 'product' ) ) {
456 return $content;
457 }
458
459 $signature = do_shortcode('[signature]');
460 $content_with_signature_bottom = $content . $signature;
461 return $content_with_signature_bottom;
462 }
463
464 public function signature() {
465 add_action('wp_ajax_get_signature_content', [$this, 'get_signature_content_callback']);
466 add_action('wp_ajax_nopriv_get_signature_content', [$this, 'get_signature_content_callback']);
467 }
468
469 public function get_signature_content_callback() {
470 wp_send_json_success(do_shortcode('[signature]'));
471 }
472
473 public function classic_widget() {
474 add_filter('gutenberg_use_widgets_block_editor', '__return_false');
475 add_filter('use_widgets_block_editor', '__return_false');
476 }
477
478 public function publish_btn() {
479 add_action( 'admin_enqueue_scripts', [$this, 'publish_button_enqueue'], 20 );
480 }
481
482 public function publish_button_enqueue() {
483 global $pagenow;
484 if ( is_admin() && ($pagenow == 'post.php' || $pagenow == 'post-new.php') ) {
485 wp_enqueue_script('publish-button', plugins_url('/assets/js/publish-button.min.js', WPEX_FILE ), array('jquery'), '1.0', true );
486 }
487 }
488
489 public function post_revisions() {
490 add_filter('wp_revisions_to_keep', [$this, 'limit_revisions'], 10, 2);
491 }
492
493 public function limit_revisions($num, $post) {
494 $limit = Settings::get_option('post_revisions');
495 if ($limit === '' || $limit === null || !is_numeric($limit)) {
496 return $num;
497 }
498 return max(0, (int) $limit);
499 }
500
501 public function delete_attached() {
502 add_action('before_delete_post', [$this, 'delete_attachments']);
503 }
504
505 public function delete_attachments($post_id) {
506 if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
507 return;
508 }
509 $attachments = get_attached_media('', $post_id);
510 if (empty($attachments)) {
511 return;
512 }
513 global $wpdb;
514 foreach ($attachments as $attachment) {
515 if ($attachment->post_parent !== (int)$post_id) {
516 continue;
517 }
518 $other_thumb = $wpdb->get_var($wpdb->prepare(
519 "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id' AND meta_value = %d AND post_id != %d LIMIT 1",
520 $attachment->ID,
521 $post_id
522 ));
523
524 if ($other_thumb) {
525 wp_update_post([
526 'ID' => $attachment->ID,
527 'post_parent' => (int)$other_thumb,
528 ]);
529 } else {
530 wp_delete_attachment($attachment->ID, true);
531 }
532 }
533 }
534
535 public function show_modified() {
536 add_filter('manage_post_posts_columns', [$this, 'modified_column_register']);
537 add_action('manage_post_posts_custom_column', [$this, 'modified_column_display'], 10, 2);
538 add_filter('manage_edit-post_sortable_columns', [$this, 'modified_column_register_sortable']);
539
540 add_action('admin_footer', [$this, 'script_modified']);
541 add_action('wp_ajax_convert_post_date', [$this, 'convert_post_date']);
542 }
543
544 public function modified_column_register($columns) {
545 $columns['modified'] = __('Last Modified');
546 return $columns;
547 }
548
549 public function modified_column_display($column_name, $post_id) {
550 if ($column_name !== 'modified') return;
551
552 $author_id = get_post_field('post_modified_by', $post_id);
553 if ($author_id) {
554 echo '<small>' . esc_html(get_the_author_meta('display_name', $author_id)) . '</small><br>';
555 }
556
557 echo '<button class="button-link convert-date-btn" data-id="' . esc_attr($post_id) . '">
558 <span class="dashicons dashicons-backup"></span>
559 </button> ';
560
561 echo sprintf(
562 esc_html__('%1$s at %2$s'),
563 esc_html(get_the_modified_date('d/m/Y', $post_id)),
564 esc_html(get_the_modified_time('', $post_id))
565 );
566 }
567
568 public function modified_column_register_sortable($columns) {
569 $columns['modified'] = 'modified';
570 return $columns;
571 }
572
573 public function script_modified() {
574 $screen = get_current_screen();
575
576 if (!$screen || $screen->base !== 'edit' || $screen->post_type !== 'post') return;
577
578 $nonce = wp_create_nonce('convert_post_date_nonce');
579 ?>
580 <script>
581 jQuery(function($){
582
583 const confirmText = "<?php echo esc_js(sprintf('%s → %s?', __('Last Modified'), __('Published'))); ?>";
584 const done = "<?php echo esc_js(__('Done')); ?>";
585 const error = "<?php echo esc_js(__('An error occurred.')); ?>";
586
587 $(document).on('click', '.convert-date-btn', function(){
588 if (!confirm(confirmText)) return;
589
590 $.post(ajaxurl, {
591 action: 'convert_post_date',
592 post_id: $(this).data('id'),
593 nonce: '<?php echo $nonce; ?>'
594 }, function(res){
595 if(res.success){
596 alert(done);
597 location.reload();
598 } else {
599 alert(error);
600 }
601 });
602 });
603
604 });
605 </script>
606 <?php
607 }
608
609 public function convert_post_date() {
610 if (
611 !isset($_POST['nonce']) ||
612 !wp_verify_nonce($_POST['nonce'], 'convert_post_date_nonce')
613 ) {
614 wp_send_json_error();
615 }
616
617 $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
618 if (!$post_id) {
619 wp_send_json_error();
620 }
621
622 if (!current_user_can('edit_post', $post_id)) {
623 wp_send_json_error();
624 }
625
626 $post = get_post($post_id);
627 if (!$post || $post->post_type !== 'post') {
628 wp_send_json_error();
629 }
630
631 global $wpdb;
632
633 $publish_date = $post->post_date;
634 $gmt = get_gmt_from_date($publish_date);
635
636 $result = $wpdb->update(
637 $wpdb->posts,
638 [
639 'post_modified' => $publish_date,
640 'post_modified_gmt' => $gmt
641 ],
642 ['ID' => $post_id],
643 ['%s', '%s'],
644 ['%d']
645 );
646
647 if ($result === false) {
648 wp_send_json_error();
649 }
650
651 clean_post_cache($post_id);
652
653 wp_send_json_success();
654 }
655
656 public function lock_modified() {
657 add_filter('wp_insert_post_data', [$this, 'disable_post_modified'], 99, 2);
658 }
659
660 public function disable_post_modified($data, $postarr) {
661 if (empty($postarr['ID'])) return $data;
662
663 $post = get_post($postarr['ID']);
664 if (!$post || $post->post_type !== 'post') return $data;
665
666 if ($post->post_status !== 'publish') return $data;
667
668 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $data;
669
670 $data['post_modified'] = $post->post_modified;
671 $data['post_modified_gmt'] = $post->post_modified_gmt;
672
673 return $data;
674 }
675
676 public function img_column() {
677 add_filter('manage_post_posts_columns', [$this, 'add_img_column']);
678 add_action('manage_post_posts_custom_column', [$this, 'manage_img_column'], 10, 2);
679 add_action('admin_head-edit.php', [$this, 'img_column_css']);
680 }
681
682 public function img_column_css() {
683 $screen = get_current_screen();
684 if (!$screen || $screen->post_type !== 'post') {
685 return;
686 }
687
688 echo '<style>
689 .wp-list-table th.column-thumbnail,.wp-list-table td.column-thumbnail{width:52px!important;text-align:center!important;vertical-align:top!important;padding:10px 4px!important;box-sizing:border-box!important}
690 .wp-list-table th.check-column,.wp-list-table td.check-column{vertical-align:top!important;padding-top:14px!important}
691 .wp-list-table td.column-title{vertical-align:top!important}
692 .wpex-thumb-box{width:40px;height:40px;margin:0 auto;display:flex;align-items:center;justify-content:center;background:#f8fafc;border:1px solid #e2e8f0;border-radius:4px;overflow:hidden;box-sizing:border-box}
693 .wpex-thumb-box a{display:flex;align-items:center;justify-content:center;width:100%;height:100%;text-decoration:none}
694 .wpex-thumb-box img{width:100%!important;height:100%!important;object-fit:cover!important;display:block!important}
695 .wpex-thumb-box .dashicons{color:#94a3b8;font-size:18px;width:18px;height:18px;line-height:18px;display:block}
696 </style>';
697 }
698
699 public function add_img_column($columns) {
700 $new_columns = [];
701 foreach ($columns as $key => $title) {
702 if ($key === 'title') {
703 $new_columns['thumbnail'] = '<span class="screen-reader-text">' . esc_html__('Thumbnail', 'wp-extra') . '</span>';
704 }
705 $new_columns[$key] = $title;
706 }
707 return $new_columns;
708 }
709
710 public function manage_img_column($column_name, $post_id) {
711 if ('thumbnail' === $column_name) {
712 $edit_link = get_edit_post_link($post_id);
713 echo '<div class="wpex-thumb-box">';
714 if (has_post_thumbnail($post_id)) {
715 $img_html = get_the_post_thumbnail($post_id, [80, 80], ['loading' => 'lazy']);
716 echo $edit_link ? '<a href="' . esc_url($edit_link) . '">' . $img_html . '</a>' : $img_html;
717 } else {
718 $placeholder = '<span class="dashicons dashicons-format-image"></span>';
719 echo $edit_link ? '<a href="' . esc_url($edit_link) . '">' . $placeholder . '</a>' : $placeholder;
720 }
721 echo '</div>';
722 }
723 }
724
725 public function disable_tags() {
726 $mode = Helper::get_option('disable_tags', '');
727 if ($mode === 'disable_link') {
728 add_filter('term_links-post_tag', [$this, 'remove_tag_links']);
729 add_filter('the_tags', [$this, 'filter_the_tags']);
730 add_filter('term_link', [$this, 'filter_tag_term_link'], 10, 3);
731 add_action('template_redirect', [$this, 'block_tag_archives']);
732 } elseif ($mode === 'disable_tag' || $mode === '1' || $mode === true) {
733 add_action('init', [$this, 'unregister_post_tags']);
734 add_action('admin_menu', [$this, 'remove_tags_admin_menu']);
735 add_action('template_redirect', [$this, 'block_tag_archives']);
736 }
737 }
738
739 public function remove_tag_links($links) {
740 if (is_array($links)) {
741 return array_map(function($link) {
742 return preg_replace('/<a\b[^>]*>(.*?)<\/a>/i', '<span class="tag-no-link">$1</span>', $link);
743 }, $links);
744 }
745 return $links;
746 }
747
748 public function filter_the_tags($tag_list) {
749 if (!empty($tag_list)) {
750 return preg_replace('/<a\b[^>]*>(.*?)<\/a>/i', '<span class="tag-no-link">$1</span>', $tag_list);
751 }
752 return $tag_list;
753 }
754
755 public function filter_tag_term_link($termlink, $term, $taxonomy) {
756 if ($taxonomy === 'post_tag') {
757 return 'javascript:void(0);';
758 }
759 return $termlink;
760 }
761
762 public function unregister_post_tags() {
763 unregister_taxonomy_for_object_type('post_tag', 'post');
764 }
765
766 public function remove_tags_admin_menu() {
767 remove_submenu_page('edit.php', 'edit-tags.php?taxonomy=post_tag');
768 }
769
770 public function block_tag_archives() {
771 if (is_tag()) {
772 global $wp_query;
773 $wp_query->set_404();
774 status_header(404);
775 nocache_headers();
776 }
777 }
778
779 }
780