<?php
/**
 * Plugin Name:       Simple SEO Meta by ConvertAtlas
 * Plugin URI:        https://convertatlas.org/en/wordpress/simple-seo-meta
 * Description:       Lightweight SEO meta tags: custom titles & descriptions per post/page, plus Open Graph and Twitter Card output. No bloat, no account.
 * Version:           1.0.0
 * Requires at least: 5.5
 * Requires PHP:      7.4
 * Author:            ConvertAtlas
 * Author URI:        https://convertatlas.org
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       ca-simple-seo-meta
 *
 * Built with convertatlas.org — free developer tools & templates.
 */

if (!defined('ABSPATH')) { exit; }

final class CA_Simple_SEO_Meta {

    const META_TITLE = '_ca_seo_title';
    const META_DESC  = '_ca_seo_desc';
    const META_NOINDEX = '_ca_seo_noindex';

    public static function init() {
        $self = new self();
        add_action('add_meta_boxes', array($self, 'add_box'));
        add_action('save_post', array($self, 'save'), 10, 2);
        // Output as early as possible in <head>.
        add_action('wp_head', array($self, 'output_head'), 1);
        // Let WordPress use our custom title when set.
        add_filter('pre_get_document_title', array($self, 'filter_title'), 20);
        add_filter('document_title_parts', array($self, 'filter_title_parts'), 20);
    }

    /** Meta box on posts and pages. */
    public function add_box() {
        foreach (array('post', 'page') as $type) {
            add_meta_box(
                'ca_seo_meta_box',
                'SEO — ConvertAtlas',
                array($this, 'render_box'),
                $type,
                'normal',
                'high'
            );
        }
    }

    public function render_box($post) {
        wp_nonce_field('ca_seo_save', 'ca_seo_nonce');
        $title = get_post_meta($post->ID, self::META_TITLE, true);
        $desc  = get_post_meta($post->ID, self::META_DESC, true);
        $noindex = get_post_meta($post->ID, self::META_NOINDEX, true);
        ?>
        <p>
            <label for="ca_seo_title"><strong>SEO title</strong> (leave blank to use the default)</label><br>
            <input type="text" id="ca_seo_title" name="ca_seo_title" value="<?php echo esc_attr($title); ?>" style="width:100%" maxlength="70">
            <span style="color:#666;font-size:12px">Recommended: under 60 characters.</span>
        </p>
        <p>
            <label for="ca_seo_desc"><strong>Meta description</strong></label><br>
            <textarea id="ca_seo_desc" name="ca_seo_desc" rows="3" style="width:100%" maxlength="200"><?php echo esc_textarea($desc); ?></textarea>
            <span style="color:#666;font-size:12px">Recommended: 120–158 characters.</span>
        </p>
        <p>
            <label><input type="checkbox" name="ca_seo_noindex" value="1" <?php checked($noindex, '1'); ?>> Tell search engines <strong>not</strong> to index this content (noindex)</label>
        </p>
        <?php
    }

    public function save($post_id, $post) {
        if (!isset($_POST['ca_seo_nonce']) || !wp_verify_nonce($_POST['ca_seo_nonce'], 'ca_seo_save')) return;
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
        if (!current_user_can('edit_post', $post_id)) return;

        $title = isset($_POST['ca_seo_title']) ? sanitize_text_field($_POST['ca_seo_title']) : '';
        $desc  = isset($_POST['ca_seo_desc']) ? sanitize_textarea_field($_POST['ca_seo_desc']) : '';
        $noindex = isset($_POST['ca_seo_noindex']) ? '1' : '';

        update_post_meta($post_id, self::META_TITLE, $title);
        update_post_meta($post_id, self::META_DESC, $desc);
        update_post_meta($post_id, self::META_NOINDEX, $noindex);
    }

    private function current_title() {
        if (is_singular()) {
            $t = get_post_meta(get_queried_object_id(), self::META_TITLE, true);
            if ($t) return $t;
        }
        return wp_get_document_title();
    }

    private function current_desc() {
        if (is_singular()) {
            $d = get_post_meta(get_queried_object_id(), self::META_DESC, true);
            if ($d) return $d;
            $post = get_queried_object();
            if ($post && !empty($post->post_excerpt)) return wp_trim_words(wp_strip_all_tags($post->post_excerpt), 30, '');
            if ($post && !empty($post->post_content)) return wp_trim_words(wp_strip_all_tags($post->post_content), 30, '');
        }
        $tagline = get_bloginfo('description');
        return $tagline ? $tagline : '';
    }

    public function filter_title($title) {
        if (is_singular()) {
            $t = get_post_meta(get_queried_object_id(), self::META_TITLE, true);
            if ($t) return $t;
        }
        return $title;
    }

    public function filter_title_parts($parts) {
        if (is_singular()) {
            $t = get_post_meta(get_queried_object_id(), self::META_TITLE, true);
            if ($t) { $parts['title'] = $t; }
        }
        return $parts;
    }

    public function output_head() {
        $desc = $this->current_desc();
        $title = $this->current_title();
        $url = home_url(add_query_arg(array(), $GLOBALS['wp']->request ?? ''));
        if (is_singular()) { $url = get_permalink(get_queried_object_id()); }
        $site = get_bloginfo('name');
        $noindex = is_singular() ? get_post_meta(get_queried_object_id(), self::META_NOINDEX, true) : '';

        echo "\n<!-- Simple SEO Meta by ConvertAtlas (convertatlas.org) -->\n";

        if ($noindex === '1') {
            echo '<meta name="robots" content="noindex,follow">' . "\n";
        }
        if ($desc) {
            echo '<meta name="description" content="' . esc_attr($desc) . '">' . "\n";
        }
        // Canonical
        if ($url) {
            echo '<link rel="canonical" href="' . esc_url($url) . '">' . "\n";
        }
        // Open Graph
        echo '<meta property="og:type" content="' . (is_singular() ? 'article' : 'website') . '">' . "\n";
        echo '<meta property="og:title" content="' . esc_attr($title) . '">' . "\n";
        if ($desc) echo '<meta property="og:description" content="' . esc_attr($desc) . '">' . "\n";
        if ($url)  echo '<meta property="og:url" content="' . esc_url($url) . '">' . "\n";
        if ($site) echo '<meta property="og:site_name" content="' . esc_attr($site) . '">' . "\n";
        if (is_singular() && has_post_thumbnail()) {
            $img = get_the_post_thumbnail_url(get_queried_object_id(), 'full');
            if ($img) echo '<meta property="og:image" content="' . esc_url($img) . '">' . "\n";
        }
        // Twitter Card
        echo '<meta name="twitter:card" content="summary_large_image">' . "\n";
        echo '<meta name="twitter:title" content="' . esc_attr($title) . '">' . "\n";
        if ($desc) echo '<meta name="twitter:description" content="' . esc_attr($desc) . '">' . "\n";
        echo "<!-- /Simple SEO Meta -->\n";
    }
}

add_action('init', array('CA_Simple_SEO_Meta', 'init'));