and meta).
return citami_active_seo_plugin() === null;
}
/* ---------------------------------------------------------------- */
/* Templates */
/* ---------------------------------------------------------------- */
/** Variables available to templates for the given context. */
function citami_seo_vars($ctx) {
$settings = citami_seo_settings();
$vars = array(
'sitename' => get_bloginfo('name'),
'tagline' => get_bloginfo('description'),
'sep' => $settings['separator'],
'title' => '',
'excerpt' => '',
'category' => '',
'author' => '',
'date' => '',
'term' => '',
'page' => '',
'search' => '',
);
if (!empty($ctx['post']) && is_object($ctx['post'])) {
$post = $ctx['post'];
$vars['title'] = isset($post->post_title) ? (string) $post->post_title : '';
$vars['excerpt'] = citami_seo_post_excerpt($post);
if (function_exists('get_the_author_meta') && !empty($post->post_author)) {
$vars['author'] = (string) get_the_author_meta('display_name', (int) $post->post_author);
}
if (!empty($post->post_date)) {
$vars['date'] = date_i18n(get_option('date_format', 'Y-m-d'), strtotime((string) $post->post_date));
}
if (function_exists('get_the_category')) {
$cats = get_the_category($post->ID);
if (is_array($cats) && !empty($cats) && isset($cats[0]->name)) {
$vars['category'] = (string) $cats[0]->name;
}
}
}
if (!empty($ctx['term'])) {
$vars['term'] = (string) $ctx['term'];
}
if (!empty($ctx['page']) && (int) $ctx['page'] > 1) {
$vars['page'] = sprintf(citami_t('Pagina %d', 'Page %d'), (int) $ctx['page']);
}
if (!empty($ctx['search'])) {
$vars['search'] = (string) $ctx['search'];
}
return $vars;
}
/** First ~155 chars of the excerpt or the content, tags stripped. */
function citami_seo_post_excerpt($post) {
$text = '';
if (!empty($post->post_excerpt)) {
$text = (string) $post->post_excerpt;
} else {
// 2.31.1 — builder-aware: Elementor pages have an empty post_content.
$text = citami_post_content_html($post);
}
// 2.29.1 — seen on a real site: "…cosciente.Quanto costa" — block
// comments dropped, block boundaries become spaces, entities decoded,
// the cut lands on a word boundary.
$text = preg_replace('//s', ' ', citami_strip_shortcodes_safe($text));
$text = preg_replace('#?(p|h[1-6]|li|ul|ol|div|br|tr|td|th|table|blockquote|figure|figcaption|section|article|details|summary|pre)\b[^>]*>#i', ' ', $text);
$text = html_entity_decode(wp_strip_all_tags($text), ENT_QUOTES | ENT_HTML5, 'UTF-8');
$text = preg_replace('/\s+/u', ' ', $text);
$text = trim($text);
if (mb_strlen($text) > 155) {
$cut = mb_substr($text, 0, 152);
$sp = mb_strrpos($cut, ' ');
if ($sp !== false && $sp > 100) {
$cut = mb_substr($cut, 0, $sp);
}
$text = rtrim($cut, " ,;:") . '…';
}
return $text;
}
/** strip_shortcodes() when WP is loaded; a regex fallback in the harness. */
function citami_strip_shortcodes_safe($text) {
if (function_exists('strip_shortcodes')) {
return strip_shortcodes($text);
}
return preg_replace('/\[[^\]]+\]/', '', $text);
}
/**
* Renders "%title% %sep% %sitename%" with the vars. Empty vars collapse
* cleanly: dangling separators and double spaces are removed.
*/
function citami_seo_render_template($tpl, array $vars) {
$out = (string) $tpl;
foreach ($vars as $k => $v) {
$out = str_replace('%' . $k . '%', (string) $v, $out);
}
$out = preg_replace('/%[a-z_]+%/', '', $out); // unknown vars
$sep = isset($vars['sep']) ? preg_quote((string) $vars['sep'], '/') : '';
if ($sep !== '') {
$out = preg_replace('/(\s*' . $sep . '\s*){2,}/u', ' ' . $vars['sep'] . ' ', $out);
$out = preg_replace('/^\s*' . $sep . '\s*|\s*' . $sep . '\s*$/u', '', $out);
}
$out = preg_replace('/\s+/u', ' ', $out);
return trim(wp_strip_all_tags($out));
}
/* ---------------------------------------------------------------- */
/* Context + resolution */
/* ---------------------------------------------------------------- */
/** What is being rendered: singular post, home, archive, search, 404. */
function citami_seo_context() {
$ctx = array('kind' => 'other', 'post' => null, 'type' => '', 'term' => '', 'page' => 1, 'search' => '');
if (function_exists('get_query_var')) {
$paged = (int) get_query_var('paged');
$ctx['page'] = $paged > 1 ? $paged : 1;
}
if (is_front_page() || is_home()) {
$ctx['kind'] = 'home';
if (is_front_page() && is_singular()) {
$ctx['post'] = get_post();
}
return $ctx;
}
if (is_search()) {
$ctx['kind'] = 'search';
$ctx['search'] = function_exists('get_search_query') ? (string) get_search_query() : '';
return $ctx;
}
if (is_404()) {
$ctx['kind'] = '404';
return $ctx;
}
if (is_singular()) {
$post = get_post();
if ($post) {
$ctx['kind'] = 'singular';
$ctx['post'] = $post;
$ctx['type'] = isset($post->post_type) ? (string) $post->post_type : 'post';
return $ctx;
}
}
if (is_archive()) {
$ctx['kind'] = 'archive';
$obj = get_queried_object();
if (is_object($obj) && isset($obj->name)) {
$ctx['term'] = (string) $obj->name;
} elseif (is_object($obj) && isset($obj->display_name)) {
$ctx['term'] = (string) $obj->display_name;
}
return $ctx;
}
return $ctx;
}
/** Resolved for the current request (null = leave WordPress'). */
function citami_seo_title($ctx = null) {
$ctx = $ctx === null ? citami_seo_context() : $ctx;
$settings = citami_seo_settings();
$vars = citami_seo_vars($ctx);
if ($ctx['kind'] === 'singular' && $ctx['post']) {
$custom = (string) get_post_meta($ctx['post']->ID, CITAMI_META_TITLE, true);
if (trim($custom) !== '') {
return citami_seo_render_template($custom, $vars);
}
$tpl = isset($settings['templates'][$ctx['type']]['title']) ? $settings['templates'][$ctx['type']]['title'] : '%title% %sep% %sitename%';
return citami_seo_render_template($tpl, $vars);
}
if ($ctx['kind'] === 'home') {
if ($ctx['post']) {
$custom = (string) get_post_meta($ctx['post']->ID, CITAMI_META_TITLE, true);
if (trim($custom) !== '') {
return citami_seo_render_template($custom, $vars);
}
}
return citami_seo_render_template($settings['home']['title'], $vars);
}
if ($ctx['kind'] === 'archive' && $ctx['term'] !== '') {
return citami_seo_render_template($settings['archive']['title'], $vars);
}
if ($ctx['kind'] === 'search') {
return citami_seo_render_template('%search% %sep% %sitename%', $vars);
}
return null;
}
/** Resolved meta description (empty = print nothing). */
function citami_seo_description($ctx = null) {
$ctx = $ctx === null ? citami_seo_context() : $ctx;
$settings = citami_seo_settings();
$vars = citami_seo_vars($ctx);
if (($ctx['kind'] === 'singular' || $ctx['kind'] === 'home') && $ctx['post']) {
$custom = (string) get_post_meta($ctx['post']->ID, CITAMI_META_DESC, true);
if (trim($custom) !== '') {
return citami_seo_render_template($custom, $vars);
}
}
if ($ctx['kind'] === 'singular') {
$tpl = isset($settings['templates'][$ctx['type']]['description']) ? $settings['templates'][$ctx['type']]['description'] : '%excerpt%';
return citami_seo_render_template($tpl, $vars);
}
if ($ctx['kind'] === 'home') {
return citami_seo_render_template($settings['home']['description'], $vars);
}
if ($ctx['kind'] === 'archive') {
return citami_seo_render_template($settings['archive']['description'], $vars);
}
return '';
}
/** Canonical URL: custom meta wins, else the permalink (singular only). */
function citami_seo_canonical($ctx = null) {
$ctx = $ctx === null ? citami_seo_context() : $ctx;
if (($ctx['kind'] === 'singular' || $ctx['kind'] === 'home') && $ctx['post']) {
$custom = trim((string) get_post_meta($ctx['post']->ID, CITAMI_META_CANONICAL, true));
if ($custom !== '' && preg_match('#^https?://#i', $custom)) {
return $custom;
}
return $ctx['kind'] === 'home' ? home_url('/') : get_permalink($ctx['post']);
}
if ($ctx['kind'] === 'home') {
return home_url('/');
}
return '';
}
/** Robots directives as the wp_robots filter expects (name => true). */
function citami_seo_robots(array $robots, $ctx = null) {
$ctx = $ctx === null ? citami_seo_context() : $ctx;
$settings = citami_seo_settings();
$noindex = false;
$nofollow = false;
$advanced = array();
if ($ctx['kind'] === 'search' && $settings['noindex']['search']) {
$noindex = true;
}
if ($ctx['kind'] === 'archive' && $settings['noindex']['date'] && function_exists('is_date') && is_date()) {
$noindex = true;
}
if ($ctx['kind'] === 'archive' && $settings['noindex']['author'] && function_exists('is_author') && is_author()) {
$noindex = true;
}
if ($ctx['page'] > 1 && $settings['noindex']['paginated']) {
$noindex = true;
}
if ($ctx['post']) {
if ($settings['noindex']['attachment'] && isset($ctx['post']->post_type) && $ctx['post']->post_type === 'attachment') {
$noindex = true;
}
$idx = (string) get_post_meta($ctx['post']->ID, CITAMI_META_ROBOTS_INDEX, true);
if ($idx === 'noindex') {
$noindex = true;
} elseif ($idx === 'index') {
$noindex = false;
}
$fol = (string) get_post_meta($ctx['post']->ID, CITAMI_META_ROBOTS_FOLLOW, true);
if ($fol === 'nofollow') {
$nofollow = true;
}
$adv = (string) get_post_meta($ctx['post']->ID, CITAMI_META_ROBOTS_ADV, true);
foreach (array_filter(array_map('trim', explode(',', $adv))) as $d) {
if (in_array($d, array('noarchive', 'nosnippet', 'noimageindex', 'notranslate'), true)) {
$advanced[] = $d;
}
}
}
if ($noindex) {
unset($robots['index']);
$robots['noindex'] = true;
}
if ($nofollow) {
unset($robots['follow']);
$robots['nofollow'] = true;
}
foreach ($advanced as $d) {
$robots[$d] = true;
}
if (!$noindex && !isset($robots['noindex']) && !isset($robots['index'])) {
// WordPress' default "max-image-preview:large" stays; be explicit.
$robots['index'] = true;
}
if (!$nofollow && !isset($robots['nofollow']) && !isset($robots['follow'])) {
$robots['follow'] = true;
}
return $robots;
}
/* ---------------------------------------------------------------- */
/* Front-end output */
/* ---------------------------------------------------------------- */
add_filter('pre_get_document_title', function ($title) {
if (!citami_seo_enabled()) {
return $title;
}
$ours = citami_seo_title();
return ($ours !== null && $ours !== '') ? $ours : $title;
}, 15);
add_filter('wp_robots', function ($robots) {
if (!citami_seo_enabled()) {
return $robots;
}
return citami_seo_robots(is_array($robots) ? $robots : array());
}, 15);
/** Prints description + canonical. Runs early so it sits at the top of . */
function citami_seo_print_head() {
if (!citami_seo_enabled()) {
return;
}
$ctx = citami_seo_context();
$desc = citami_seo_description($ctx);
if ($desc !== '') {
echo '' . "\n";
}
$canonical = citami_seo_canonical($ctx);
if ($canonical !== '') {
echo '' . "\n";
}
}
add_action('wp_head', 'citami_seo_print_head', 1);
// WordPress prints its own rel=canonical on singular pages: ours replaces it.
add_action('wp', function () {
if (citami_seo_enabled() && function_exists('remove_action')) {
remove_action('wp_head', 'rel_canonical');
}
});
/* ---------------------------------------------------------------- */
/* Editor: meta box + save */
/* ---------------------------------------------------------------- */
function citami_seo_post_types() {
$types = get_post_types(array('public' => true), 'names');
if (!is_array($types)) {
return array('post', 'page');
}
unset($types['attachment']);
return array_values($types);
}
add_action('add_meta_boxes', function () {
foreach (citami_seo_post_types() as $type) {
add_meta_box('citami_seo', citami_brand_name() . ' · SEO', 'citami_seo_render_meta_box', $type, 'normal', 'high');
}
});
add_action('init', function () {
foreach (array(CITAMI_META_TITLE, CITAMI_META_DESC, CITAMI_META_CANONICAL, CITAMI_META_ROBOTS_INDEX, CITAMI_META_ROBOTS_FOLLOW, CITAMI_META_ROBOTS_ADV) as $key) {
register_post_meta('', $key, array(
'type' => 'string',
'single' => true,
'show_in_rest' => true,
'auth_callback' => function () {
return current_user_can('edit_posts');
},
));
}
});
/** Values as stored (all strings). */
function citami_seo_get_post_fields($post_id) {
return array(
'title' => (string) get_post_meta($post_id, CITAMI_META_TITLE, true),
'description' => (string) get_post_meta($post_id, CITAMI_META_DESC, true),
'canonical' => (string) get_post_meta($post_id, CITAMI_META_CANONICAL, true),
'robots_index' => (string) get_post_meta($post_id, CITAMI_META_ROBOTS_INDEX, true),
'robots_follow' => (string) get_post_meta($post_id, CITAMI_META_ROBOTS_FOLLOW, true),
'robots_advanced' => (string) get_post_meta($post_id, CITAMI_META_ROBOTS_ADV, true),
);
}
/** Validates + stores a partial set of fields. Returns the stored values. */
function citami_seo_save_post_fields($post_id, array $fields) {
$post_id = (int) $post_id;
if (array_key_exists('title', $fields)) {
update_post_meta($post_id, CITAMI_META_TITLE, mb_substr(citami_seo_sanitize_template($fields['title']), 0, 200));
}
if (array_key_exists('description', $fields)) {
update_post_meta($post_id, CITAMI_META_DESC, mb_substr(citami_seo_sanitize_template($fields['description']), 0, 320));
}
if (array_key_exists('canonical', $fields)) {
$c = trim((string) $fields['canonical']);
update_post_meta($post_id, CITAMI_META_CANONICAL, preg_match('#^https?://#i', $c) ? esc_url_raw($c) : '');
}
if (array_key_exists('robots_index', $fields)) {
$v = (string) $fields['robots_index'];
update_post_meta($post_id, CITAMI_META_ROBOTS_INDEX, in_array($v, array('index', 'noindex'), true) ? $v : '');
}
if (array_key_exists('robots_follow', $fields)) {
$v = (string) $fields['robots_follow'];
update_post_meta($post_id, CITAMI_META_ROBOTS_FOLLOW, in_array($v, array('follow', 'nofollow'), true) ? $v : '');
}
if (array_key_exists('robots_advanced', $fields)) {
$raw = is_array($fields['robots_advanced']) ? $fields['robots_advanced'] : explode(',', (string) $fields['robots_advanced']);
$keep = array();
foreach ($raw as $d) {
$d = sanitize_key((string) $d);
if (in_array($d, array('noarchive', 'nosnippet', 'noimageindex', 'notranslate'), true)) {
$keep[] = $d;
}
}
update_post_meta($post_id, CITAMI_META_ROBOTS_ADV, implode(',', array_unique($keep)));
}
// 2.31.1 — a cache plugin does not see a meta change: purge the page.
if (function_exists('citami_purge_cache')) {
citami_purge_cache($post_id);
}
return citami_seo_get_post_fields($post_id);
}
// 2.40 — per-page meta coverage travels with the content-health snapshot:
// how many published pages have a custom title / description, how many are
// noindex (and which, as page refs). Counts and refs only: no meta text travels.
add_filter('citami_health_extra', function ($extra) {
$extra = is_array($extra) ? $extra : array();
$ids = get_posts(array(
'post_type' => citami_seo_post_types(),
'post_status' => 'publish',
'numberposts' => defined('CITAMI_HEALTH_SCAN') ? CITAMI_HEALTH_SCAN : 500,
'orderby' => 'modified',
'order' => 'DESC',
'fields' => 'ids',
));
$out = array('checked' => 0, 'custom_title' => 0, 'custom_description' => 0, 'noindex' => 0, 'noindex_pages' => array());
$limit = defined('CITAMI_HEALTH_LIST') ? CITAMI_HEALTH_LIST : 5;
foreach ((array) $ids as $id) {
$id = (int) $id;
$out['checked']++;
if ((string) get_post_meta($id, CITAMI_META_TITLE, true) !== '') {
$out['custom_title']++;
}
if ((string) get_post_meta($id, CITAMI_META_DESC, true) !== '') {
$out['custom_description']++;
}
if ((string) get_post_meta($id, CITAMI_META_ROBOTS_INDEX, true) === 'noindex') {
$out['noindex']++;
if (count($out['noindex_pages']) < $limit && function_exists('citami_health_page_ref')) {
$out['noindex_pages'][] = citami_health_page_ref($id);
}
}
}
$extra['meta'] = $out;
return $extra;
});
function citami_seo_render_meta_box($post) {
$f = citami_seo_get_post_fields($post->ID);
$settings = citami_seo_settings();
$type = isset($post->post_type) ? (string) $post->post_type : 'post';
$tpl = isset($settings['templates'][$type]['title']) ? $settings['templates'][$type]['title'] : '%title% %sep% %sitename%';
// 2.49 — the placeholder is what the page gets when the field is empty, rendered, not the template variables.
$default_title = citami_seo_render_template($tpl, citami_seo_vars(array('post' => $post)));
$enabled = citami_seo_enabled();
wp_nonce_field('citami_seo_save_' . $post->ID, CITAMI_SEO_NONCE);
?>
Robots
isset($in['title']) ? $in['title'] : '',
'description' => isset($in['description']) ? $in['description'] : '',
'canonical' => isset($in['canonical']) ? $in['canonical'] : '',
'robots_index' => isset($in['robots_index']) ? $in['robots_index'] : '',
'robots_follow' => isset($in['robots_follow']) ? $in['robots_follow'] : '',
'robots_advanced' => isset($in['robots_advanced']) ? $in['robots_advanced'] : array(),
);
citami_seo_save_post_fields($post_id, $fields);
do_action('citami_seo_save_extra', $post_id, $in);
return;
}
// Quick edit / bulk edit: only the fields that were sent, "-1" = unchanged.
$fields = array();
foreach (array('title', 'description', 'robots_index', 'robots_follow') as $k) {
$name = 'citami_qe_' . $k;
if (!isset($_REQUEST[$name])) {
continue;
}
$v = sanitize_text_field(wp_unslash((string) $_REQUEST[$name]));
if ($v === '-1') {
continue;
}
$fields[$k] = $v;
}
if (!empty($fields)) {
if (!empty($_REQUEST['citami_qe_nonce']) && !wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['citami_qe_nonce'])), 'citami_qe')) {
return;
}
citami_seo_save_post_fields($post_id, $fields);
}
}
add_action('save_post', 'citami_seo_handle_save', 10, 1);
/* ---------------------------------------------------------------- */
/* Posts list: column + quick edit + bulk edit */
/* ---------------------------------------------------------------- */
add_filter('manage_posts_columns', 'citami_seo_add_column');
add_filter('manage_pages_columns', 'citami_seo_add_column');
function citami_seo_add_column($columns) {
if (is_array($columns)) {
$columns['citami_seo'] = 'SEO';
}
return $columns;
}
function citami_seo_render_column($column, $post_id) {
if ($column !== 'citami_seo') {
return;
}
$f = citami_seo_get_post_fields($post_id);
$bits = array();
// 2.52 — the tooltip says what the letters mean; the cell stays short.
$bits[] = $f['title'] !== ''
? 'T ✓'
: 'T –';
$bits[] = $f['description'] !== ''
? 'D ✓'
: 'D –';
if ($f['robots_index'] === 'noindex') {
$bits[] = 'noindex';
}
echo wp_kses(implode(' · ', $bits), citami_kses_allowed());
// Hidden values the quick-edit JS copies into the inline form.
echo '';
}
add_action('manage_posts_custom_column', 'citami_seo_render_column', 10, 2);
add_action('manage_pages_custom_column', 'citami_seo_render_column', 10, 2);
function citami_seo_quick_edit_box($column_name, $post_type) {
if ($column_name !== 'citami_seo') {
return;
}
wp_nonce_field('citami_qe', 'citami_qe_nonce', false);
?>
get_json_params();
if (!is_array($body)) {
$body = array();
}
$post_id = isset($body['post_id']) ? (int) $body['post_id'] : 0;
if ($post_id <= 0 && !empty($body['url']) && function_exists('url_to_postid')) {
$post_id = (int) url_to_postid((string) $body['url']);
}
if ($post_id <= 0 || !get_post($post_id)) {
return new WP_Error('citami_post_not_found', 'post_id o url non risolvibile.', array('status' => 404));
}
$fields = array_intersect_key($body, array_flip(array('title', 'description', 'canonical', 'robots_index', 'robots_follow', 'robots_advanced')));
if (empty($fields)) {
return new WP_Error('citami_bad_payload', 'Nessun campo da salvare.', array('status' => 400));
}
$stored = citami_seo_save_post_fields($post_id, $fields);
// WP10 — IndexNow hears about platform-driven changes too.
do_action('citami_page_meta_saved', $post_id);
return rest_ensure_response(array(
'success' => true,
'post_id' => $post_id,
'fields' => $stored,
'seo_enabled' => citami_seo_enabled(),
));
}
/** GET /wp-json/citami/v1/page-meta?post_id= */
function citami_rest_page_meta_get(WP_REST_Request $request) {
$post_id = (int) $request->get_param('post_id');
if ($post_id <= 0 || !get_post($post_id)) {
return new WP_Error('citami_post_not_found', 'post_id non valido.', array('status' => 404));
}
return rest_ensure_response(array(
'post_id' => $post_id,
'fields' => citami_seo_get_post_fields($post_id),
'seo_enabled' => citami_seo_enabled(),
));
}
add_action('rest_api_init', function () {
register_rest_route('citami/v1', '/page-meta', array(
array(
'methods' => 'POST',
'callback' => 'citami_rest_page_meta',
'permission_callback' => 'citami_check_permission',
),
array(
'methods' => 'GET',
'callback' => 'citami_rest_page_meta_get',
'permission_callback' => 'citami_check_permission',
),
));
});
/* ---------------------------------------------------------------- */
/* Settings tab (rendered by admin.php under ?tab=seo) */
/* ---------------------------------------------------------------- */
add_action('admin_init', function () {
register_setting('citami_seo', CITAMI_SEO_SETTINGS_OPT, array(
'type' => 'array',
'sanitize_callback' => 'citami_sanitize_seo_settings',
'default' => array(),
));
});
/**
* 2.42 — what is on, off or left to another plugin, one line each. The
* SEO tab opens with this instead of forty fields.
*/
function citami_seo_status_items() {
$other = citami_active_seo_plugin();
$items = array();
$meta_on = citami_seo_enabled();
$items[] = array('id' => 'meta', 'label' => citami_t('Title, description, canonical, robots', 'Title, description, canonical, robots'), 'state' => $meta_on ? 'good' : ($other !== null ? 'muted' : 'warn'), 'detail' => $meta_on ? citami_t('gestiti da Citami su ogni pagina', 'managed by Citami on every page') : ($other !== null ? sprintf(citami_t('lasciati a %s', 'left to %s'), $other) : citami_t('disattivati', 'off')));
$schema_on = function_exists('citami_schema_enabled') ? citami_schema_enabled() : false;
$items[] = array('id' => 'schema', 'label' => citami_t('Schema (Organization, WebPage, Article, FAQ)', 'Schema (Organization, WebPage, Article, FAQ)'), 'state' => $schema_on ? 'good' : ($other !== null ? 'muted' : 'warn'), 'detail' => $schema_on ? citami_t('stampato in ogni pagina', 'printed on every page') : ($other !== null ? sprintf(citami_t('lasciato a %s', 'left to %s'), $other) : citami_t('disattivato', 'off')));
$sitemap_on = function_exists('citami_sitemap_enabled') ? citami_sitemap_enabled() : false;
$items[] = array('id' => 'sitemap', 'label' => 'Sitemap XML', 'state' => $sitemap_on ? 'good' : 'muted', 'detail' => $sitemap_on ? home_url('/sitemap.xml') : citami_t('servita da un altro plugin o disattivata', 'served by another plugin or off'));
$llms_on = function_exists('citami_llms_settings') ? citami_llms_settings()['enabled'] === 'on' : false;
$items[] = array('id' => 'llms', 'label' => 'llms.txt', 'state' => $llms_on ? 'good' : 'warn', 'detail' => $llms_on ? home_url('/llms.txt') : citami_t('disattivato: i crawler AI non hanno un indice del sito', 'off: AI crawlers have no index of the site'));
$in_on = function_exists('citami_indexnow_enabled') ? citami_indexnow_enabled() : false;
$in_log = get_option('citami_indexnow_log', array());
$in_last = is_array($in_log) && !empty($in_log) && is_array($in_log[0]) ? $in_log[0] : null;
$in_state = !$in_on ? 'warn' : ($in_last === null ? 'good' : ((string) $in_last['status'] === 'ok' ? 'good' : 'bad'));
$items[] = array('id' => 'indexnow', 'label' => 'IndexNow', 'state' => $in_state, 'detail' => !$in_on ? citami_t('disattivato: Bing e gli altri motori non sanno delle modifiche', 'off: Bing and the other engines do not hear about changes') : ($in_last === null ? citami_t('attivo, nessun invio ancora', 'on, nothing sent yet') : ((string) $in_last['status'] === 'ok' ? sprintf(citami_t('attivo, ultimo invio riuscito il %s', 'on, last submission succeeded on %s'), wp_date('d/m', (int) $in_last['ts'])) : sprintf(citami_t('ultimo invio fallito (HTTP %d)', 'last submission failed (HTTP %d)'), (int) $in_last['code']))));
$ml = function_exists('citami_multilingual_plugin') ? citami_multilingual_plugin() : null;
$hl_on = function_exists('citami_hreflang_enabled') ? citami_hreflang_enabled() : false;
$items[] = array('id' => 'hreflang', 'label' => 'hreflang', 'state' => $ml !== null ? 'muted' : ($hl_on ? 'good' : 'muted'), 'detail' => $ml !== null ? sprintf(citami_t('gestito da %s', 'handled by %s'), $ml) : ($hl_on ? citami_t('attivo per le pagine con alternative', 'on for pages with alternates') : citami_t('disattivato', 'off')));
$alt_fill = function_exists('citami_alt_fill_enabled') ? citami_alt_fill_enabled() : false;
$alt_ai = function_exists('citami_alt_ai_enabled') ? citami_alt_ai_enabled() : false;
$items[] = array('id' => 'alt', 'label' => citami_t('Alt delle immagini', 'Image alt text'), 'state' => $alt_fill ? 'good' : 'warn', 'detail' => $alt_fill ? ($alt_ai ? citami_t('riempiti in uscita e generati in libreria', 'filled at output and generated in the library') : citami_t('riempiti in uscita; descrizione automatica spenta', 'filled at output; automatic description off')) : citami_t('le immagini senza alt restano senza alt', 'images without alt stay without alt'));
$aeo_on = function_exists('citami_aeo_settings') ? citami_aeo_settings()['enabled'] === 'on' : false;
$items[] = array('id' => 'aeo', 'label' => citami_t('Punteggio AEO nell\'editor', 'AEO score in the editor'), 'state' => $aeo_on ? 'good' : 'muted', 'detail' => $aeo_on ? citami_t('pannello e colonna attivi', 'panel and column on') : citami_t('disattivato', 'off'));
$soc_on = function_exists('citami_social_settings') ? citami_social_settings()['enabled'] === 'on' : false;
$items[] = array('id' => 'social', 'label' => 'Open Graph / X', 'state' => $soc_on ? 'good' : 'muted', 'detail' => $soc_on ? citami_t('anteprime social attive', 'social previews on') : citami_t('disattivate', 'off'));
return $items;
}
function citami_render_seo_status_card() {
$items = citami_seo_status_items();
$good = count(array_filter($items, function ($i) { return $i['state'] === 'good'; }));
?>
and its header; the caller prints the rows (a
* form-table) and closes the . The id is the anchor the
* status card and the action handlers link to (#citami-seo-).
*/
function citami_seo_card_head($id, $title, $purpose, $extra_class = '') {
$cls = 'citami-card citami-seo-card' . ($extra_class !== '' ? ' ' . $extra_class : '');
echo ''
. '
citami_t('Risultati di ricerca', 'Search results'), 'attachment' => citami_t('Pagine allegato', 'Attachment pages'), 'author' => citami_t('Archivi autore', 'Author archives'), 'date' => citami_t('Archivi per data', 'Date archives'), 'paginated' => citami_t('Pagine 2+ degli archivi', 'Paginated archive pages')) as $k => $label): ?>
nested in it was dropped by the browser and
// its hidden "action" field hijacked Save. Their buttons point here via form="…".
do_action('citami_seo_settings_after_form');
?>