getSubfeeds($feed_url);
if (is_wp_error($subfeeds)) {
wp_send_json_error($subfeeds->get_error_message());
wp_die();
}
wp_send_json_success($subfeeds);
wp_die();
}
/**
* Normaliza las URLs eliminando barras adicionales,
* convirtiendo a minúsculas y quitando la barra final.
*
* @param string $url URL a normalizar.
* @return string URL normalizada.
*/
function aife_normalize_feed_url($url) {
return rtrim(
strtolower(
preg_replace('/([^:])\/+/', '$1/', $url)
),
'/'
);
}
add_shortcode('aife_post_meta', function($atts){
global $post;
// Aseguramos que solo aceptamos una clave válida
$attribs = shortcode_atts([
'key' => '',
], $atts);
$meta_key = sanitize_key( $attribs['key'] );
// Si la clave está vacía, no se devuelve contenido
if ( empty( $meta_key ) ) {
return '';
}
// Recuperamos el valor de la meta y lo saneamos antes de mostrarlo
$value = get_post_meta( $post->ID, $meta_key, true );
if ( is_string( $value ) ) {
// Permitir solo HTML seguro. Si prefieres eliminar todo HTML usa esc_html() en su lugar.
$value = wp_kses_post( $value );
}
return $value;
});
/**
* Verifica si un campo personalizado existe en el sistema de WordPress.
*
* Evalúa si el campo:
* - Está registrado oficialmente con register_post_meta()
* - Tiene al menos una entrada guardada en postmeta
* - Está definido por ACF (si ACF está activo)
*
* @param string $meta_key
* @return bool
*/
function aife_meta_key_existe( $meta_key ) {
global $wp_meta_keys, $wpdb;
// 1. ¿Está registrado oficialmente con register_post_meta?
if ( isset( $wp_meta_keys['post']['post'] ) ) {
if ( array_key_exists( $meta_key, $wp_meta_keys['post']['post'] ) ) {
return true;
}
}
// 2. ¿Existe al menos una entrada en postmeta con esa clave?
// $meta_en_bbdd = $wpdb->get_var( $wpdb->prepare(
// "SELECT meta_id FROM {$wpdb->postmeta} WHERE meta_key = %s LIMIT 1",
//$meta_key
//) );
if ( ! empty( $meta_en_bbdd ) ) {
return true;
}
// 3. ¿Está definido por ACF?
if ( function_exists( 'get_field_object' ) ) {
$acf_field = get_field_object( $meta_key, 'post' );
if ( ! empty( $acf_field ) ) {
return true;
}
}
return false;
}
function aife_comprobar_api_rest_activa() {
$respuesta = wp_remote_get(home_url('/wp-json'), ['redirection' => 0]);
if (is_wp_error($respuesta)) {
return false;
}
$codigo_respuesta = wp_remote_retrieve_response_code($respuesta);
if ($codigo_respuesta !== 200) {
return false;
}
$cuerpo = wp_remote_retrieve_body($respuesta);
// Intentar decodificar el JSON
$json = json_decode($cuerpo, true);
// Si no es un JSON válido, la API REST no está operativa
if (json_last_error() !== JSON_ERROR_NONE) {
return false;
}
// Opcionalmente verifica un campo típico del JSON de WP REST API
if (empty($json['namespaces'])) {
return false;
}
return true;
}
function aife_get_config_feed_y_general_from_aife_original_id($aife_original_post_id){
$config = array();
// Cargar config_general, ya suele estar en el formato correcto.
$config_general = get_option( 'aife_settings', [] );
foreach ($config_general as $key => $value) {
$config['config_general'][$key] = maybe_unserialize($value);
}
$_source_feed_id = get_post_meta( $aife_original_post_id , '_source_feed_id', true );
if($_source_feed_id){
$raw_config_feed = get_post_meta( $_source_feed_id );
foreach ($raw_config_feed as $key => $value) {
if (is_array($value) && count($value) === 1) {
$unserialized = maybe_unserialize($value[0]);
$config['config_feed'][$key] = $unserialized;
} else {
// Si es un array con más de un valor, mantenerlo tal cual.
$config['config_feed'][$key] = $value;
}
}
}else{
$config['config_feed'] = $config['config_general'];
}
return $config;
}
/**
* Obtiene los datos básicos de un post para enviarlos a OpenAI.
*
* @param int $post_id
* @return array|WP_Error
*/
function aife_get_post_data($params) {
if (empty($params['post_id'])) {
return new WP_Error('falta_post_id', 'Falta post_id.');
}
$post_id = absint($params['post_id']);
$post = get_post($post_id);
if (!$post) {
return new WP_Error('post_no_encontrado', __('Post no encontrado.', 'ai-feeds'));
}
return [
'title' => $post->post_title,
'excerpt' => wp_strip_all_tags(get_the_excerpt($post)),
'content' => trim(preg_replace('/\s+/', ' ', preg_replace("/[\r\n]+/", "\n", ($post->post_content)))),
'pub_date' => get_post_meta($post_id, '_pub_date', true),
'categories' => get_post_meta($post_id, '_categories', true),
'original_url' => get_post_meta($post_id, '_original_url', true),
'config' => aife_get_config_feed_y_general_from_aife_original_id($post_id),
'user' => wp_get_current_user()->display_name,
];
}
/**
* Devuelve claramente las categorías de WP con ruta completa e ID.
*
* @param int $limit
* @return array
*/
function aife_get_categorias_con_ruta($limit = 200) {
$categories = get_categories([
'number' => $limit,
'orderby' => 'count',
'order' => 'DESC',
'hide_empty' => false,
'fields' => 'ids'
]);
$categorias_con_ruta = [];
foreach ($categories as $cat_id) {
$categoria = get_category($cat_id);
$ruta = [$categoria->name];
while ($categoria->parent) {
$categoria = get_category($categoria->parent);
array_unshift($ruta, $categoria->name);
}
$categorias_con_ruta[] = [
'id' => $cat_id,
'ruta' => implode(' > ', $ruta)
];
}
return $categorias_con_ruta;
}
if ( is_admin() ) {
add_action('transition_post_status', 'aife_gestionar_eliminacion_post_original', 10, 3);
}
function aife_gestionar_eliminacion_post_original($new_status, $old_status, $post) {
// Verificamos claramente si el post es del tipo estándar 'post'
if ($post->post_type !== 'post') {
return;
}
// Proceder claramente solo si el post pasa a la papelera o se elimina permanentemente
if (in_array($new_status, ['trash', 'delete'], true)) {
$feed_original_id = get_post_meta($post->ID, '_post_from_ai_feed', true);
if (!empty($feed_original_id) && get_post_type($feed_original_id) === 'aife_original') {
wp_delete_post($feed_original_id, true); // Elimina el original definitivamente
}
}
}
/**
* Elimina claramente enlaces HTML de un texto.
*
* @param string $content Contenido HTML original.
* @return string Contenido sin enlaces.
*/
function aife_remove_links(string $content): string {
return preg_replace('/]*>(.*?)<\/a>/is', '$1', $content);
}
function aife_add_nofollow_links($content) {
return preg_replace_callback('//i', function ($matches) {
$anchorTag = $matches[0];
// Si ya tiene un rel, lo modificamos claramente
if (stripos($anchorTag, 'rel=') !== false) {
// Añadimos nofollow a rel existente
if (preg_match('/rel=[\'"](.*?)[\'"]/i', $anchorTag, $relMatch)) {
$relValues = array_map('trim', explode(' ', $relMatch[1]));
if (!in_array('nofollow', $relValues)) {
$relValues[] = 'nofollow';
}
$newRel = 'rel="' . implode(' ', $relValues) . '"';
$anchorTag = preg_replace('/rel=[\'"].*?[\'"]/i', $newRel, $anchorTag);
}
} else {
// Si no tiene rel, se lo añadimos claramente
$anchorTag = preg_replace('/