Content Audit): counts per check, filterable issue list,
* per-row quick fixes. Stock WordPress UI, everything escaped.
*/
defined('ABSPATH') || exit;
class Postlint_Report {
public static function init() {
add_action('admin_menu', [__CLASS__, 'menu']);
add_action('admin_post_postlint_fix', ['Postlint_Fixes', 'handle']);
add_action('admin_post_postlint_scan', [__CLASS__, 'handle_scan']);
add_action('admin_post_postlint_save_settings', [__CLASS__, 'handle_settings']);
add_action('admin_enqueue_scripts', [__CLASS__, 'assets']);
}
/** The media library picker for the default featured image, on this screen only. */
public static function assets($hook) {
if ($hook !== 'tools_page_postlint-report') {
return;
}
wp_enqueue_media();
wp_add_inline_script('media-editor', "jQuery(function($){var f;$('#postlint-img-pick').on('click',function(e){e.preventDefault();f=f||wp.media({title:$(this).data('title'),library:{type:'image'},multiple:false});f.off('select').on('select',function(){var a=f.state().get('selection').first().toJSON(),u=(a.sizes&&a.sizes.thumbnail?a.sizes.thumbnail.url:a.url);$('#postlint-img').val(a.id);$('#postlint-img-preview').html($('',{src:u,alt:'',width:80,height:80,style:'object-fit:cover;border-radius:4px'}));$('#postlint-img-clear').show();});f.open();});$('#postlint-img-clear').on('click',function(e){e.preventDefault();$('#postlint-img').val(0);$('#postlint-img-preview').empty();$(this).hide();});});");
}
public static function menu() {
add_management_page('Content Audit', 'Content Audit', 'manage_options', 'postlint-report', [__CLASS__, 'render']);
}
private static function guard() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('You are not allowed to do that.', 'postlint-content-audit'));
}
}
public static function handle_scan() {
self::guard();
check_admin_referer('postlint_scan');
$settings = Postlint_Settings::get();
$offset = isset($_POST['offset']) ? absint($_POST['offset']) : 0;
$scanned = Postlint_Scanner::scan_batch($settings, $offset);
$next = $scanned > 0 ? $offset + $scanned : 0;
wp_safe_redirect(admin_url('tools.php?page=postlint-report&scanned=' . (int) $scanned . '&next=' . (int) $next));
exit;
}
public static function handle_settings() {
self::guard();
check_admin_referer('postlint_scan');
$raw = isset($_POST['postlint']) && is_array($_POST['postlint']) ? wp_unslash($_POST['postlint']) : [];
update_option(POSTLINT_OPTION_SETTINGS, Postlint_Settings::sanitize($raw), false);
Postlint_Scheduler::sync((bool) Postlint_Settings::get()['weekly_rescan']);
wp_safe_redirect(admin_url('tools.php?page=postlint-report&saved=1'));
exit;
}
/** The issues a view lists: all of them, or only those carrying one check. */
public static function filtered_issues(array $issues, string $filter): array {
if ($filter === '') {
return $issues;
}
return array_values(array_filter($issues, static function ($issue) use ($filter) {
return in_array($filter, $issue['checks'], true);
}));
}
public static function render() {
self::guard();
$settings = Postlint_Settings::get();
$report = Postlint_Scanner::get_report();
$filter = isset($_GET['check']) ? sanitize_key($_GET['check']) : '';
?>
0) { echo esc_html(sprintf('%1$d posts scanned, last scan %2$s (UTC).', (int) $report['scanned'], $report['scanned_at'])); } else { esc_html_e('No scan yet. Run your first scan below.', 'postlint-content-audit'); } ?>
| 0; $can_excerpt = in_array('excerpt', $issue['checks'], true); if (!$can_image && !$can_excerpt) : ?> |