'Bearer ' . citami_get_api_key(),
'Accept' => 'application/json',
'User-Agent' => 'CitamiConnector/' . CITAMI_PLUGIN_VERSION . '; ' . home_url('/'),
);
}
/** GET on the platform; array('ok' => bool, 'data' => array|null, 'error' => string). */
function citami_articles_get($path) {
if (citami_get_api_key() === '') {
return array('ok' => false, 'data' => null, 'error' => 'no_key');
}
$res = wp_remote_get(citami_get_endpoint() . $path, array('timeout' => 30, 'headers' => citami_articles_headers()));
if (is_wp_error($res)) {
return array('ok' => false, 'data' => null, 'error' => $res->get_error_message());
}
$code = (int) wp_remote_retrieve_response_code($res);
$data = json_decode((string) wp_remote_retrieve_body($res), true);
if ($code < 200 || $code >= 300 || !is_array($data)) {
return array('ok' => false, 'data' => null, 'error' => 'HTTP ' . $code);
}
return array('ok' => true, 'data' => $data, 'error' => '');
}
/** The site's articles on the platform (ready, to review, published), cached 10 minutes. */
function citami_articles_list($force = false) {
$cached = get_transient(CITAMI_ARTICLES_TRANSIENT);
if (!$force && is_array($cached)) {
return $cached;
}
$r = citami_articles_get('/api/plugin/articles');
$out = array('ok' => !empty($r['ok']), 'articles' => array(), 'error' => $r['error'], 'fetched_at' => time());
if (!empty($r['ok']) && isset($r['data']['articles']) && is_array($r['data']['articles'])) {
foreach ($r['data']['articles'] as $a) {
if (!is_array($a) || empty($a['id'])) {
continue;
}
$out['articles'][] = array(
'id' => (string) $a['id'],
'title' => (string) (isset($a['title']) ? $a['title'] : ''),
'status' => (string) (isset($a['status']) ? $a['status'] : ''),
'keywords' => isset($a['keywords']) && is_array($a['keywords']) ? array_map('strval', $a['keywords']) : array(),
'word_count' => isset($a['word_count']) ? (int) $a['word_count'] : null,
'quality_score' => isset($a['quality_score']) ? (int) $a['quality_score'] : null,
'created_at' => (string) (isset($a['created_at']) ? $a['created_at'] : ''),
'published_url' => (string) (isset($a['published_url']) ? $a['published_url'] : ''),
'wp_post_id' => isset($a['wp_post_id']) ? (int) $a['wp_post_id'] : 0,
);
}
set_transient(CITAMI_ARTICLES_TRANSIENT, $out, CITAMI_ARTICLES_TTL);
} elseif (is_array($cached)) {
$cached['stale_error'] = $r['error'];
return $cached;
}
return $out;
}
/** Ready-to-publish count for the Overview (cache only when fresh, one fetch per 10 minutes otherwise). */
function citami_articles_ready_count() {
if (citami_get_api_key() === '') {
return 0;
}
$l = citami_articles_list();
$n = 0;
foreach ($l['articles'] as $a) {
if ($a['status'] === 'ready' || $a['status'] === 'needs_review') {
$n++;
}
}
return $n;
}
/**
* Creates the post from a platform payload (title, content, status,
* excerpt, slug, categories, author, schema_jsonld). Shared with the REST
* route the dashboard calls, so both publish paths produce the same post.
* Returns array('id' => int, 'link' => string) or WP_Error.
*/
function citami_publish_article_payload(array $data) {
$title = (string) (isset($data['title']) ? $data['title'] : '');
$content = (string) (isset($data['content']) ? $data['content'] : '');
if (trim($title) === '' || trim($content) === '') {
return new WP_Error('citami_publish_missing_fields', 'title e content sono obbligatori.', array('status' => 400));
}
$status = (string) (isset($data['status']) ? $data['status'] : 'draft');
if (!in_array($status, array('draft', 'publish', 'pending'), true)) {
$status = 'draft';
}
// Autore: quello richiesto se esiste, altrimenti il primo amministratore.
$author = absint(isset($data['author']) ? $data['author'] : 0);
if ($author === 0 || !get_user_by('id', $author)) {
$admins = get_users(array('role' => 'administrator', 'number' => 1, 'orderby' => 'ID', 'order' => 'ASC', 'fields' => 'ID'));
$first = !empty($admins) ? $admins[0] : 0;
$author = is_object($first) ? (int) $first->ID : (int) $first;
}
$postarr = array(
'post_title' => sanitize_text_field($title),
'post_content' => wp_kses_post($content),
'post_status' => $status,
'post_type' => 'post',
'post_excerpt' => sanitize_text_field((string) (isset($data['excerpt']) ? $data['excerpt'] : '')),
);
if ($author > 0) {
$postarr['post_author'] = $author;
}
$slug = sanitize_title((string) (isset($data['slug']) ? $data['slug'] : ''));
if ($slug !== '') {
$postarr['post_name'] = $slug;
}
if (isset($data['categories']) && is_array($data['categories'])) {
$cat_ids = array_values(array_filter(array_map('absint', $data['categories'])));
if (!empty($cat_ids)) {
$postarr['post_category'] = $cat_ids;
}
}
$post_id = wp_insert_post($postarr, true);
if (is_wp_error($post_id)) {
return new WP_Error('citami_publish_failed', $post_id->get_error_message(), array('status' => 500));
}
$schema = isset($data['schema_jsonld']) ? $data['schema_jsonld'] : '';
if (is_string($schema) && $schema !== '') {
update_post_meta($post_id, '_citami_schema_jsonld', wp_slash($schema));
}
if (function_exists('citami_sideload_post_images')) {
$imported = citami_sideload_post_images((int) $post_id, $postarr['post_content']);
if (is_string($imported) && $imported !== $postarr['post_content']) {
wp_update_post(array('ID' => (int) $post_id, 'post_content' => $imported));
}
}
return array('id' => (int) $post_id, 'link' => get_permalink($post_id));
}
/** The plugin-side publish: pull the article, create the post, report back. */
function citami_articles_publish($article_id, $status = 'draft') {
$article_id = preg_replace('/[^a-f0-9-]/i', '', (string) $article_id);
if ($article_id === '') {
return array('ok' => false, 'message' => citami_t('Articolo non valido.', 'Invalid article.'));
}
$map = get_option(CITAMI_ARTICLES_MAP_OPT, array());
if (is_array($map) && !empty($map[$article_id]) && get_post((int) $map[$article_id])) {
return array('ok' => false, 'message' => citami_t('Questo articolo è già stato pubblicato da qui.', 'This article was already published from here.'), 'post_id' => (int) $map[$article_id]);
}
$r = citami_articles_get('/api/plugin/articles/' . rawurlencode($article_id));
if (empty($r['ok']) || empty($r['data']['article']) || !is_array($r['data']['article'])) {
return array('ok' => false, 'message' => sprintf(citami_t('Articolo non scaricato dalla piattaforma (%s).', 'Could not fetch the article from the platform (%s).'), $r['error'] !== '' ? $r['error'] : '?'));
}
$a = $r['data']['article'];
if (!empty($a['wp_post_id'])) {
return array('ok' => false, 'message' => citami_t('La piattaforma lo segna già come pubblicato.', 'The platform already marks it as published.'));
}
$status = in_array($status, array('draft', 'publish', 'pending'), true) ? $status : 'draft';
$data = array(
'title' => isset($a['title']) ? $a['title'] : '',
'content' => isset($a['content']) ? $a['content'] : '',
'excerpt' => isset($a['excerpt']) ? $a['excerpt'] : '',
'slug' => isset($a['slug']) ? $a['slug'] : '',
'schema_jsonld' => isset($a['schema_jsonld']) ? $a['schema_jsonld'] : '',
'status' => $status,
'author' => get_current_user_id(),
);
$post = citami_publish_article_payload($data);
if (is_wp_error($post)) {
return array('ok' => false, 'message' => $post->get_error_message());
}
update_post_meta($post['id'], '_citami_article_id', $article_id);
$map = is_array($map) ? $map : array();
$map[$article_id] = (int) $post['id'];
update_option(CITAMI_ARTICLES_MAP_OPT, $map, false);
// Report: the platform marks it published and starts the keyword tracking.
$reported = false;
$res = wp_remote_post(citami_get_endpoint() . '/api/plugin/articles/' . rawurlencode($article_id) . '/published', array(
'timeout' => 30,
'headers' => citami_articles_headers() + array('Content-Type' => 'application/json'),
'body' => wp_json_encode(array('post_id' => (int) $post['id'], 'url' => (string) $post['link'], 'status' => $status)),
));
if (!is_wp_error($res)) {
$code = (int) wp_remote_retrieve_response_code($res);
$reported = $code >= 200 && $code < 300;
}
delete_transient(CITAMI_ARTICLES_TRANSIENT);
if (function_exists('citami_activity_log')) {
citami_activity_log('article', sprintf(citami_t('Articolo pubblicato dalla piattaforma: "%s" (%s)', 'Article published from the platform: "%s" (%s)'), $data['title'], $status === 'publish' ? citami_t('online', 'live') : citami_t('bozza', 'draft')), 1, array('post' => (int) $post['id'], 'article' => $article_id));
}
$message = $status === 'publish'
? sprintf(citami_t('"%s" è online.', '"%s" is live.'), $data['title'])
: sprintf(citami_t('"%s" è in bozza: rivedila e pubblica dall\'editor.', '"%s" is a draft: review it and publish from the editor.'), $data['title']);
if (!$reported) {
$message .= ' ' . citami_t('La piattaforma non ha ricevuto la conferma: il rendimento dell\'articolo partirà al prossimo sync.', 'The platform did not get the confirmation: the article\'s performance tracking starts with the next sync.');
}
return array('ok' => true, 'message' => $message, 'post_id' => (int) $post['id'], 'link' => (string) $post['link'], 'reported' => $reported);
}
/** 2.59 — the full article for the preview row, cached an hour; null on failure. */
function citami_articles_preview_fetch($article_id) {
$r = citami_articles_get('/api/plugin/articles/' . rawurlencode($article_id));
if (empty($r['ok']) || empty($r['data']['article']) || !is_array($r['data']['article'])) {
return null;
}
$a = $r['data']['article'];
$content = (string) (isset($a['content']) ? $a['content'] : '');
$pv = array(
'title' => (string) (isset($a['title']) ? $a['title'] : ''),
'slug' => (string) (isset($a['slug']) ? $a['slug'] : ''),
'excerpt' => (string) (isset($a['excerpt']) ? $a['excerpt'] : ''),
'content' => wp_kses_post($content),
'words' => str_word_count(wp_strip_all_tags($content)),
'images' => preg_match_all('/
!empty($a['schema_jsonld']),
);
set_transient('citami_article_preview_' . md5($article_id), $pv, HOUR_IN_SECONDS);
return $pv;
}
/* ---------------------------------------------------------------- */
/* Admin: action handler + tab */
/* ---------------------------------------------------------------- */
function citami_articles_form_open($do, $extra = '', $id = '', $class = 'citami-inline-form') {
return '
| | | |
>
|
|
|
', $fid . '-d'), citami_kses_allowed()); ?>
', $fid . '-p'), citami_kses_allowed()); ?>
', $fid . '-v'), citami_kses_allowed()); ?>
|
|
|
| | | |
0 ? get_post_status($pid) : false; ?>
>
|
— |
— |
0 && $st): ?> |