Why we nee d d water (Copy) (Copy)

blah blah

internal link

external link

magic test<?php
/*
Plugin Name: PostFlux
Plugin URI: https://yourdomain.com/postflux
Description: A lightweight WordPress plugin to supercharge your editorial workflow. Includes post notes, filters, quick actions, and productivity shortcuts.
Version: 1.0.0
Author: Your Name
Author URI: https://yourdomain.com
License: GPL2
Text Domain: postflux
*/

// ==============================
// Feature: Last Edited Post Widget
// ==============================

add_action(‘wp_dashboard_setup’, ‘postflux_add_dashboard_widget’);

function postflux_add_dashboard_widget() {
wp_add_dashboard_widget(
‘postflux_last_edited’,
‘📄 Last Edited Post’,
‘postflux_last_edited_widget’
);
}

function postflux_last_edited_widget() {
$current_user_id = get_current_user_id();
$args = array(
‘numberposts’ => 1,
‘orderby’ => ‘modified’,
‘order’ => ‘DESC’,
‘post_status’ => array(‘draft’, ‘publish’, ‘pending’, ‘future’),
‘post_type’ => get_post_types(array(‘public’ => true)), // handles posts, pages, custom types
‘author’ => $current_user_id,
);

$recent_posts = get_posts($args);

if (!empty($recent_posts)) {
    $post = $recent_posts[0];
    $title = get_the_title($post->ID);
    $edit_link = get_edit_post_link($post->ID);
    $title = $title ? $title : '(no title)';
    echo '<p><strong>' . esc_html($title) . '</strong><br>';
    echo '<a href="' . esc_url($edit_link) . '" class="button button-primary">Edit This Post</a></p>';
} else {
    echo '<p>No recently edited posts found.</p>';
}

}

// ==============================
// Feature: One-Click Duplicate Post
// ==============================

// Add “Duplicate” link to post/page rows
add_filter(‘post_row_actions’, ‘postflux_add_duplicate_link’, 10, 2);
add_filter(‘page_row_actions’, ‘postflux_add_duplicate_link’, 10, 2);

function postflux_add_duplicate_link($actions, $post) {
if (current_user_can(‘edit_posts’)) {
$url = wp_nonce_url(
admin_url(‘admin.php?action=postflux_duplicate_post&post=’ . $post->ID),
‘postflux_duplicate_post_’ . $post->ID
);
$actions[‘postflux_duplicate’] = ‘Duplicate‘;
}
return $actions;
}

// Handle duplication action
add_action(‘admin_action_postflux_duplicate_post’, ‘postflux_duplicate_post’);

function postflux_duplicate_post() {
if (
!isset($_GET[‘post’]) ||
!isset($_GET[‘wpnonce’]) || !wp_verify_nonce($_GET[‘_wpnonce’], ‘postflux_duplicate_post‘ . intval($_GET[‘post’]))
) {
wp_die(‘Invalid request.’);
}

$post_id = intval($_GET['post']);
$post = get_post($post_id);

if (!$post) {
    wp_die('Post not found.');
}

$new_post = array(
    'post_title'    => $post->post_title . ' (Copy)',
    'post_content'  => $post->post_content,
    'post_status'   => 'draft',
    'post_type'     => $post->post_type,
    'post_author'   => get_current_user_id(),


);

$new_post_id = wp_insert_post($new_post);

// Copy taxonomies (categories, tags, etc.)
$taxonomies = get_object_taxonomies($post->post_type);
foreach ($taxonomies as $taxonomy) {
    $terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'ids'));
    wp_set_object_terms($new_post_id, $terms, $taxonomy);
}

// Redirect to edit screen of the duplicated post
wp_redirect(admin_url('post.php?action=edit&post=' . $new_post_id));
exit;

}

// ==============================
// Feature: Word Count Column in Post List
// ==============================

add_filter(‘manage_post_posts_columns’, ‘postflux_add_wordcount_column’);
add_action(‘manage_post_posts_custom_column’, ‘postflux_show_wordcount_column’, 10, 2);

function postflux_add_wordcount_column($columns) {
$columns[‘postflux_wordcount’] = ‘Words’;
return $columns;
}

function postflux_show_wordcount_column($column, $post_id) {
if ($column === ‘postflux_wordcount’) {
$content = get_post_field(‘post_content’, $post_id);
$word_count = str_word_count(strip_tags($content));
echo esc_html($word_count);
}
}

// ==============================
// Rename “Categories” & Remove “Tags”
// ==============================

add_filter(‘manage_post_posts_columns’, ‘postflux_adjust_post_columns’);
function postflux_adjust_post_columns($columns) {
if (isset($columns[‘categories’])) {
$columns[‘categories’] = ‘📂’; // or ‘Cats’
}

if (isset($columns['tags'])) {
    unset($columns['tags']);
}

return $columns;

}

// ==============================
// Feature: Post Status Icons Inline with Title
// ==============================

// 1. Filter the post title display in the list
add_filter(‘the_title’, ‘postflux_add_status_icon_to_title’, 10, 2);

function postflux_add_status_icon_to_title($title, $post_id) {
if (!is_admin()) return $title;

global $pagenow;
if ($pagenow !== 'edit.php') return $title;

$status = get_post_status($post_id);
$icon = '';

switch ($status) {
    case 'publish':
        $icon = '✅';
        break;
    case 'draft':
        $icon = '📝';
        break;
    case 'pending':
        $icon = '⏳';
        break;
    case 'future':
        $icon = '🕒';
        break;
    default:
        $icon = '';
        break;
}

return $icon ? $icon . ' ' . $title : $title;

}

// ==============================
// Feature: Append Age to the Date Column
// ==============================

add_filter(‘post_date_column_time’, ‘postflux_append_age_to_date_column’, 10, 3);

function postflux_append_age_to_date_column($t_time, $post, $column_name) {
if ($column_name !== ‘date’) return $t_time;

$post_time = get_the_time('U', $post);
$current_time = current_time('timestamp');
$diff = $current_time - $post_time;

if ($diff < HOUR_IN_SECONDS) {
    $age = round($diff / MINUTE_IN_SECONDS) . ' mins ago';
} elseif ($diff < DAY_IN_SECONDS) {
    $age = round($diff / HOUR_IN_SECONDS) . ' hrs ago';
} elseif ($diff < WEEK_IN_SECONDS) {
    $age = round($diff / DAY_IN_SECONDS) . ' days ago';
} elseif ($diff < MONTH_IN_SECONDS) {
    $age = round($diff / WEEK_IN_SECONDS) . ' wks ago';
} else {
    $age = round($diff / MONTH_IN_SECONDS) . ' mos ago';
}

return $t_time . '<br><small style="opacity:0.7;">🕓 ' . $age . '</small>';

}

// ==============================
// Feature: Star Column with Toggle (Clean Version)
// ==============================

// 1. Add ⭐ column to the end of the post list
add_filter(‘manage_post_posts_columns’, ‘postflux_add_star_column’);
function postflux_add_star_column($columns) {
$columns[‘postflux_starred’] = ‘⭐’; // adds it at the end
return $columns;
}

// 2. Show clickable star icon per post
add_action(‘manage_post_posts_custom_column’, ‘postflux_show_star_column’, 10, 2);
function postflux_show_star_column($column, $post_id) {
if ($column !== ‘postflux_starred’) return;

$starred = get_post_meta($post_id, '_postflux_starred', true);
$icon = $starred ? '⭐' : '☆';
$nonce = wp_create_nonce('postflux_toggle_star_' . $post_id);

$url = add_query_arg([
    'action'   => 'postflux_toggle_star',
    'post_id'  => $post_id,
    '_wpnonce' => $nonce
], admin_url());

echo '<a href="' . esc_url($url) . '" title="Toggle Star" style="text-decoration:none; font-size:1.1em;">' . $icon . '</a>';

}

// 3. Handle star toggle with redirect to Posts list
add_action(‘admin_init’, ‘postflux_handle_toggle_star’);
function postflux_handle_toggle_star() {
if (
isset($_GET[‘action’]) &&
$_GET[‘action’] === ‘postflux_toggle_star’ &&
isset($_GET[‘post_id’]) &&
current_user_can(‘edit_posts’) &&
wp_verify_nonce($_GET[‘wpnonce’], ‘postflux_toggle_star‘ . intval($_GET[‘post_id’]))
) {
$post_id = intval($_GET[‘post_id’]);
$current = get_post_meta($post_id, ‘_postflux_starred’, true);

    if ($current) {
        delete_post_meta($post_id, '_postflux_starred');
    } else {
        update_post_meta($post_id, '_postflux_starred', 1);
    }

    $referer = wp_get_referer();
    $redirect_to = ($referer && strpos($referer, 'edit.php') !== false)
        ? remove_query_arg(['action', 'post_id', '_wpnonce'], $referer)
        : admin_url('edit.php?post_type=post');

    wp_safe_redirect($redirect_to);
    exit;
}

}

// ==============================
// Rename “Categories” to “Cat” + Show “Uncat” Instead of “Uncategorized”
// ==============================

// 1. Rename the Categories column heading
add_filter(‘manage_post_posts_columns’, ‘postflux_rename_categories_column’);
function postflux_rename_categories_column($columns) {
if (isset($columns[‘categories’])) {
$columns[‘categories’] = ‘Cat’;
}
return $columns;
}

// 2. Rename the “Uncategorized” term label to “Uncat”
add_filter(‘get_the_terms’, ‘postflux_rename_uncategorized_term’, 10, 3);
function postflux_rename_uncategorized_term($terms, $post_id, $taxonomy) {
if ($taxonomy !== ‘category’ || empty($terms)) return $terms;

foreach ($terms as $term) {
    if ($term->slug === 'uncategorized') {
        $term->name = 'Uncat';
    }
}

return $terms;

}

// ==============================
// Feature: “Starred” Filter View
// ==============================

// 1. Add the Starred view link in the filter bar
add_filter(‘views_edit-post’, ‘postflux_add_starred_filter_view’);
function postflux_add_starred_filter_view($views) {
global $wpdb;

$count = $wpdb->get_var("
    SELECT COUNT(post_id)
    FROM $wpdb->postmeta
    LEFT JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->postmeta.post_id
    WHERE meta_key = '_postflux_starred'
    AND meta_value = '1'
    AND post_type = 'post'
    AND post_status NOT IN ('trash', 'auto-draft')
");

$class = (isset($_GET['postflux_starred']) && $_GET['postflux_starred'] === '1') ? 'current' : '';
$url = add_query_arg('postflux_starred', '1', admin_url('edit.php'));

$views['postflux_starred'] = '<a href="' . esc_url($url) . '" class="' . $class . '">⭐ Starred (' . intval($count) . ')</a>';

return $views;

}

// 2. Modify the query to filter for starred posts when active
add_action(‘pre_get_posts’, ‘postflux_filter_starred_posts’);
function postflux_filter_starred_posts($query) {
if (
is_admin() &&
$query->is_main_query() &&
$query->get(‘post_type’) === ‘post’ &&
isset($_GET[‘postflux_starred’]) &&
$_GET[‘postflux_starred’] === ‘1’
) {
$query->set(‘meta_key’, ‘_postflux_starred’);
$query->set(‘meta_value’, ‘1’);
}
}

// ==============================
// Feature: “Last Edited Post” Admin Menu Link (Final Version)
// ==============================

add_action(‘admin_menu’, ‘postflux_add_last_edited_nav’);

function postflux_add_last_edited_nav() {
add_submenu_page(
‘edit.php’,
‘Last Edited Post’,
‘🔁 Last Edited’,
‘edit_posts’,
‘postflux-last-edited’,
‘postflux_redirect_to_last_edited_post’
);
}

function postflux_redirect_to_last_edited_post() {
// Fetch most recently modified post
$last_post = get_posts([
‘post_type’ => ‘post’,
‘post_status’ => [‘publish’, ‘draft’, ‘pending’, ‘future’, ‘private’],
‘orderby’ => ‘modified’,
‘order’ => ‘DESC’,
‘numberposts’ => 1,
]);

if (!empty($last_post)) {
    $edit_url = get_edit_post_link($last_post[0]->ID, '');
    if ($edit_url) {
        wp_safe_redirect($edit_url);
        exit;
    }
}

// Fallback redirect
wp_safe_redirect(admin_url('edit.php?post_type=post'));
exit;

}

// ==============================
// Feature: Highlight Starred Rows in Post List
// ==============================

add_action(‘admin_head-edit.php’, ‘postflux_highlight_starred_rows’);

function postflux_highlight_starred_rows() {
global $wpdb;

$screen = get_current_screen();
if ($screen->post_type !== 'post') return;

// Get IDs of all starred posts currently visible on screen
$starred_ids = get_posts([
    'post_type'   => 'post',
    'post_status' => 'any',
    'meta_key'    => '_postflux_starred',
    'meta_value'  => '1',
    'fields'      => 'ids',
    'posts_per_page' => -1,
    'orderby' => 'modified',
    'order' => 'DESC'
]);

if (empty($starred_ids)) return;

echo '<style>';
foreach ($starred_ids as $id) {
    echo "#post-$id { background-color: #fffbe6 !important; }"; // light yellow highlight
}
echo '</style>';

}

// ==============================
// Feature: Last Modified Column (Visible + Sortable)
// ==============================

// 1. Add the column after ‘date’
add_filter(‘manage_post_posts_columns’, ‘postflux_add_last_modified_column’);
function postflux_add_last_modified_column($columns) {
$new_columns = [];

foreach ($columns as $key => $value) {
    $new_columns[$key] = $value;

    // Insert our custom column right after 'date'
    if ($key === 'date') {
        $new_columns['postflux_last_modified'] = 'Last Modified';
    }
}

return $new_columns;

}

// 2. Display the last modified value
add_action(‘manage_post_posts_custom_column’, ‘postflux_show_last_modified_column’, 10, 2);
function postflux_show_last_modified_column($column, $post_id) {
if ($column === ‘postflux_last_modified’) {
$modified = get_post_field(‘post_modified’, $post_id);
echo esc_html(date(‘Y/m/d @ H:i’, strtotime($modified)));
}
}

// 3. Make it sortable
add_filter(‘manage_edit-post_sortable_columns’, ‘postflux_make_last_modified_sortable’);
function postflux_make_last_modified_sortable($columns) {
$columns[‘postflux_last_modified’] = ‘modified’;
return $columns;
}

// ==============================
// Feature: Post Checklist (Sidebar – Smart Detection & AJAX Save + Auto Refresh)
// ==============================

// 1. Add meta box to the post editor sidebar
add_action(‘add_meta_boxes’, ‘postflux_add_checklist_sidebar’);
function postflux_add_checklist_sidebar() {
add_meta_box(
‘postflux_checklist’,
‘🧠 PostFlux Check’,
‘postflux_render_checklist_box’,
‘post’,
‘side’,
‘high’
);
}

// 2. Render checklist box
function postflux_render_checklist_box($post) {
$meta = get_post_meta($post->ID, ‘_postflux_checklist’, true);
$meta = is_array($meta) ? $meta : [];

// Manual checklist items
$manual_checks = [
    'proofread' => 'Proofread',
    'cta'       => 'Call to Action Added',
    'reviewed'  => 'Internal Link Added (confirmed)',
];

// Post content & checks
$content = $post->post_content;
$word_count = str_word_count(strip_tags($content));
$has_featured = has_post_thumbnail($post->ID);
$has_image = strpos($content, '<img') !== false;
$has_h1 = strpos($content, '<h1') !== false;

// Link detection
$has_internal = false;
$has_external = false;
$site_url = parse_url(home_url(), PHP_URL_HOST);

if (preg_match_all('/<a[^>]+href=["']([^"']+)["']/i', $content, $matches)) {
    foreach ($matches[1] as $url) {
        $parsed = parse_url(trim($url));
        $host = isset($parsed['host']) ? $parsed['host'] : '';

        // Skip empty/malformed
        if (empty($url) || strpos($url, '#') === 0 || strpos($url, 'mailto:') === 0) continue;

        if ($host === $site_url || strpos($url, '/') === 0) {
            $has_internal = true;
        } elseif (strpos($url, 'http') === 0 && $host && $host !== $site_url) {
            $has_external = true;
        }
    }
}

echo '<div style="margin-bottom: 10px;">';
echo '<strong>🔎 Auto Checks</strong><br>';
echo $word_count >= 500 ? '🟢 Word count 500+<br>' : '🔴 Too short for SEO<br>';
echo $has_featured ? '🟢 Featured image set<br>' : '🔴 No featured image<br>';
echo $has_image ? '🟢 Image added in body<br>' : '🔴 No image in content<br>';
echo $has_internal ? '🟢 Internal link present<br>' : '🔴 No internal link<br>';
echo $has_external ? '🟢 External link present<br>' : '🔴 No external link<br>';
echo $has_h1 ? '🟢 H1 heading present<br>' : '🔴 No H1 heading<br>';
echo '</div>';

echo '<div><strong>📝 Manual Checks</strong><br>';
foreach ($manual_checks as $key => $label) {
    $checked = !empty($meta[$key]) ? 'checked' : '';
    echo '<label style="display:block;margin-bottom:4px;">
            <input type="checkbox" class="postflux-manual" name="postflux_checklist[' . $key . ']" ' . $checked . '> ' . $label . '
          </label>';
}
echo '</div>';

}

// 3. Save checklist manually on post update (fallback)
add_action(‘save_post’, ‘postflux_save_checklist_data’);
function postflux_save_checklist_data($post_id) {
if (isset($_POST[‘postflux_checklist’]) && is_array($_POST[‘postflux_checklist’])) {
$cleaned = [];
foreach ($_POST[‘postflux_checklist’] as $key => $val) {
$cleaned[$key] = ‘1’;
}
update_post_meta($post_id, ‘_postflux_checklist’, $cleaned);
} else {
delete_post_meta($post_id, ‘_postflux_checklist’);
}
}

// 4. Real-time AJAX save for manual checkboxes
add_action(‘admin_footer-post.php’, ‘postflux_checklist_autosave_script’);
add_action(‘admin_footer-post-new.php’, ‘postflux_checklist_autosave_script’);
function postflux_checklist_autosave_script() {
?>

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *