/* ========================== Admin Page Wrapper ========================== */ function rj360_admin_wrapper(){ $nonce = wp_create_nonce('rj360'); $opt = get_option(RJ360_OPT, rj360_defaults()); $cats = get_terms(['taxonomy' => 'category', 'hide_empty' => false, 'number' => 200]); rj360_output_ui($nonce, $opt, $cats); // Llama al UI puro con datos pre-fetchados } /* ========================== Enqueue CSS solo en nuestra pantalla ========================== */ add_action('admin_enqueue_scripts', function($hook){ if ($hook !== 'toplevel_page_rj360-admin') return; if (!wp_style_is('rj360-admin-style','registered')){ wp_register_style('rj360-admin-style', false, [], RJ360_VER); } wp_enqueue_style('rj360-admin-style'); $inline = '/* ===== Admin CSS (inline) ===== */ :root{ --gap:12px; --radius:12px; --border:#e3e6ea; --bg:#f6f7f9; --card:#fff; --primary:#0366d6; --primary-ink:#fff; --muted:#6b7280; --ok:#16a34a; --warn:#b45309; --danger:#dc2626; } #rj360{max-width:1400px} #rj360 h1{margin-bottom:14px} #rj360 .rj-grid{ display:grid; grid-template-columns: 1.1fr 1.8fr 1.1fr; gap: var(--gap); align-items:start; } #rj360 .card{background:var(--card); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden} #rj360 .card .inner{padding:14px 14px 18px} #rj360 .row{display:flex; gap:10px; align-items:center; margin-bottom:10px} #rj360 .row.cols-2>*, #rj360 .row.cols-3>*{flex:1} #rj360 .row.cols-3>*{min-width:0} #rj360 input[type="text"], #rj360 input[type="number"], #rj360 input[type="datetime-local"], #rj360 textarea, #rj360 select{ width:100%; padding:10px 12px; border:1px solid var(--border); border-radius:10px; background:#fff; outline:none } #rj360 textarea{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace} #rj360 .button{padding:8px 12px; border:1px solid var(--border); background:#fff; border-radius:10px; cursor:pointer} #rj360 .button:hover{background:#f3f4f6} #rj360 .button.button-primary{border-color:var(--primary); background:var(--primary); color:var(--primary-ink)} #rj360 .chips{display:flex; flex-wrap:wrap; gap:8px} #rj360 .chip{display:inline-flex; align-items:center; gap:6px; padding:6px 10px; border:1px solid var(--border); border-radius:20px; background:#fff} #rj360 .panel{display:none} #rj360 .panel.active{display:block} #rj360 .list{display:flex; flex-direction:column; gap:8px; max-height:520px; overflow:auto; border:1px dashed #e5e7eb; padding:8px; border-radius:10px} #rj360 .item a{text-decoration:none} #rj360 .preview{margin-top:12px; border:1px solid var(--border); border-radius:12px; overflow:hidden} #rj360 .preview #preview-frame{width:100%; height:540px; border:0} #rj360 .days{display:flex; gap:8px; flex-wrap:wrap} #rj360 .days-row{align-items:flex-start} @media (max-width:1280px){ #rj360 .rj-grid{ grid-template-columns: 1fr } #rj360 .preview #preview-frame{height:480px} } @media (min-width:1281px) and (max-width:1600px){ #rj360 .rj-grid{ grid-template-columns: 1fr 1.4fr 1fr } }'; if (function_exists('wp_add_inline_style')) wp_add_inline_style('rj360-admin-style', $inline); wp_enqueue_style('theme-style', get_stylesheet_uri(), [], null, 'all'); }); /* ========================== Defaults & Setup ========================== */ function rj360_defaults(){ return [ 'feeds'=>[ ['url'=>'https://prensa.jujuy.gob.ar/feed/','active'=>true], ['url'=>'https://www.argentina.gob.ar/noticias/todas-las-noticias/rss.xml','active'=>true], ], 'days'=>['mon','tue','wed','thu','fri','sat','sun'], 'safe_image_domains'=>".gob.ar\nargentina.gob.ar\njujuy.gob.ar\nwikipedia.org\nwikimedia.org\nprensa.jujuy.gob.ar" ];} function rj360_norm_feeds($fs){ $o=[]; foreach((array)$fs as $f){ if(is_array($f)&&isset($f['url'])) $o[]=['url'=>trim($f['url']),'active'=>!empty($f['active'])]; elseif(is_string($f)&&$f) $o[]=['url'=>trim($f),'active'=>true]; } return $o; } add_action('admin_init',function(){ $opt=get_option(RJ360_OPT); if(!$opt) $opt=rj360_defaults(); $opt=array_merge(rj360_defaults(),$opt); $opt['feeds']=rj360_norm_feeds($opt['feeds']); update_option(RJ360_OPT,$opt); }); /* ========================== Admin Menu ========================== */ add_action('admin_menu',function(){ add_menu_page('Reportero 360','Reportero 360','edit_posts','rj360-admin','rj360_admin_wrapper','dashicons-media-document',3); }); /* ========================== AJAX ========================== */ add_action('wp_ajax_rj360_api', function(){ if(!current_user_can('edit_posts')) wp_send_json_error('forbidden'); check_ajax_referer('rj360'); $sub = sanitize_key($_POST['sub']??''); $payload = json_decode(stripslashes($_POST['payload']??'{}'), true) ?: []; try{ switch($sub){ case 'fetch_rss': $out = rj360_ajax_fetch_rss($payload); break; case 'fetch_url': $out = rj360_ajax_fetch_url($payload); break; case 'search_posts': $out = rj360_ajax_search_posts($payload); break; case 'read_post': $out = rj360_ajax_read_post($payload); break; case 'clean_html': $out = ['html'=>rj360_clean_html($payload['html']??'')]; break; case 'publish': $out = ['id'=>rj360_publish($payload)]; break; case 'save_opt': update_option(RJ360_OPT, rj360_merge_options($payload['opt']??[])); $out=['ok'=>true]; break; default: throw new Exception('acción no soportada'); } wp_send_json_success($out); }catch(Throwable $e){ wp_send_json_error($e->getMessage()); } }); /* ========================== Helpers ========================== */ function rj360_merge_options($in){ $base = get_option(RJ360_OPT, rj360_defaults()); $in['feeds'] = rj360_norm_feeds($in['feeds']??[]); $out = array_merge($base, $in); return $out; } function rj360_host_allows($url){ $opt = get_option(RJ360_OPT, rj360_defaults()); $list = array_filter(array_map('trim', explode("\n", (string)($opt['safe_image_domains']??'')))); if(!$list) return true; $host = parse_url($url, PHP_URL_HOST); if(!$host) return false; foreach($list as $rule){ $rule = ltrim($rule); if($rule && (str_ends_with($host,$rule) || $host===$rule || (strpos($rule,'.')===0 && str_ends_with($host,$rule)))){ return true; } } return false; } function rj360_clean_html($html){ $allowed = [ 'a'=>['href'=>true,'title'=>true,'target'=>true,'rel'=>true], 'p'=>['class'=>true],'br'=>[], 'strong'=>[], 'em'=>[], 'b'=>[], 'i'=>[], 'ul'=>[],'ol'=>[],'li'=>[], 'h1'=>[],'h2'=>[],'h3'=>[],'h4'=>[],'h5'=>[],'h6'=>[], 'img'=>['src'=>true,'alt'=>true,'title'=>true,'width'=>true,'height'=>true,'loading'=>true], 'figure'=>[],'figcaption'=>[], 'blockquote'=>['cite'=>true], 'code'=>[], 'pre'=>[] ]; $html = wp_kses((string)$html, $allowed); // Quitar atributos peligrosos $html = preg_replace('/\son\w+="[^"]*"/i','',$html); // Remover iframes/embeds $html = preg_replace('#<(iframe|embed|script)[\s\S]*?#i','',$html); return $html; } /* ========================== RSS ========================== */ function rj360_ajax_fetch_rss($p){ $url = esc_url_raw($p['url']??''); $limit = max(1, min( (int)($p['limit']??12), 50 )); if(!$url) throw new Exception('feed vacío'); require_once ABSPATH.'wp-includes/feed.php'; $rss = fetch_feed($url); if(is_wp_error($rss)) throw new Exception('RSS inválido'); $max = $rss->get_item_quantity($limit); $items = []; for($i=0; $i<$max; $i++){ $it = $rss->get_item($i); $items[] = [ 'title' => (string)$it->get_title(), 'link' => (string)$it->get_link(), 'date' => (string)$it->get_date('c'), ]; } return ['items'=>$items]; } /* ========================== URL Fetch (simple) ========================== */ function rj360_ajax_fetch_url($p){ $url = esc_url_raw($p['url']??''); if(!$url) throw new Exception('URL vacía'); $res = wp_remote_get($url, ['timeout'=>12,'redirection'=>5,'user-agent'=>'RJ360/3.0']); if(is_wp_error($res)) throw new Exception('No se pudo descargar'); $html = wp_remote_retrieve_body($res); if(!$html) throw new Exception('Sin contenido'); // Title $title=''; if(preg_match('~(.*?)~is',$html,$m)) $title=wp_strip_all_tags($m[1]); // Main image (og:image) $image=''; if(preg_match('~]*>([\s\S]+?)~i',$html,$m)) $content = $m[1]; if(!$content && preg_match('~]*>([\s\S]+?)~i',$html,$m)) $content = $m[1]; $content = rj360_clean_html($content); return ['title'=>$title,'image'=>$image,'content'=>$content]; } /* ========================== Posts ========================== */ function rj360_ajax_search_posts($p){ $q = sanitize_text_field($p['q']??''); $args = ['post_type'=>'post','posts_per_page'=>20,'s'=>$q,'post_status'=>'any','orderby'=>'date','order'=>'DESC']; $posts = get_posts($args); return ['items'=>array_map(function($po){ return ['ID'=>$po->ID,'post_title'=>$po->post_title]; }, $posts)]; } function rj360_ajax_read_post($p){ $id = (int)($p['id']??0); if($id<1) throw new Exception('ID inválido'); $po = get_post($id); if(!$po) throw new Exception('No existe'); $img = get_the_post_thumbnail_url($po,'full') ?: ''; $tags = wp_get_post_tags($id, ['fields'=>'names']); $cats = wp_get_post_categories($id); return ['title'=>$po->post_title,'content'=>$po->post_content,'image'=>$img,'tags'=>$tags,'cats'=>$cats]; } /* ========================== Publicar ========================== */ function rj360_publish($p){ $title = sanitize_text_field($p['title']??''); $subtitle = sanitize_text_field($p['subtitle']??''); $content = rj360_clean_html($p['content']??''); $image = esc_url_raw($p['image']??''); $author = max(1,(int)($p['author']??1)); $status = in_array(($p['status']??'draft'), ['draft','publish','future','pending'], true) ? $p['status'] : 'draft'; $slug = sanitize_title($p['slug']??''); $excerpt = sanitize_text_field($p['excerpt']??''); $date = sanitize_text_field($p['date']??''); $cats = array_filter(array_map('intval', (array)($p['cats']??[]))); $tags = array_filter(array_map('trim', explode(',', (string)($p['tags']??'')))); $postarr = [ 'post_title' => $title, 'post_content' => ($subtitle ? '

'.esc_html($subtitle).'

' : '').$content, 'post_status' => $status, 'post_author' => $author, 'post_type' => 'post', ]; if($slug) $postarr['post_name'] = $slug; if($excerpt)$postarr['post_excerpt'] = $excerpt; if($date) $postarr['post_date'] = date('Y-m-d H:i:s', strtotime($date)); $id = wp_insert_post($postarr, true); if(is_wp_error($id)) throw new Exception($id->get_error_message()); if($cats) wp_set_post_categories($id, $cats, false); if($tags) wp_set_post_tags($id, $tags, false); // Meta JSON $meta = (array)($p['meta']??[]); foreach($meta as $k=>$v){ if(is_scalar($v) || is_null($v)) update_post_meta($id, sanitize_key($k), maybe_serialize($v)); } // Imagen if($image){ if(!rj360_host_allows($image)) throw new Exception('Dominio de imagen no permitido'); require_once ABSPATH.'wp-admin/includes/media.php'; require_once ABSPATH.'wp-admin/includes/file.php'; require_once ABSPATH.'wp-admin/includes/image.php'; $att_id = media_sideload_image($image, $id, $title, 'id'); if(!is_wp_error($att_id)) set_post_thumbnail($id, $att_id); } return $id; } /* ========================== Media helpers (fallback) ========================== */ if(!function_exists('rj360_media_sideload')){ function rj360_media_sideload($url,$post=0,$desc=''){ if(!$url) return 0; require_once ABSPATH.'wp-admin/includes/file.php'; require_once ABSPATH.'wp-admin/includes/media.php'; require_once ABSPATH.'wp-admin/includes/image.php'; $tmp=download_url($url); if(is_wp_error($tmp)) return 0; $mime=function_exists('mime_content_type')?mime_content_type($tmp):(wp_check_filetype($url)['type']??'image/jpeg'); $name=basename(parse_url($url,PHP_URL_PATH))?:'media.jpg'; $file=['name'=>$name,'type'=>$mime,'tmp_name'=>$tmp,'size'=>@filesize($tmp),'error'=>0]; $id=media_handle_sideload($file,$post,$desc); if(is_wp_error($id)){ @unlink($tmp); return 0; } @unlink($tmp); $path=get_attached_file($id); if($path&&file_exists($path)){ $meta=wp_generate_attachment_metadata($id,$path); if($meta) wp_update_attachment_metadata($id,$meta); } return $id; } } No se encontró la página | Jujuy 360
viernes, octubre 24, 2025

Ultimas Noticias

Feria del Vino Jujuy 2025: Entradas, Precios y Bodegas Imperdibles 🍷🔥

Feria del Vino Jujuy 2025: Entradas, Precios y Bodegas Imperdibles 🍷🔥Ey, jujeños y winelovers, la 10ª Feria del Vino de Jujuy 2025 llega este...

Emilia Clarke en Jujuy: Daenerys Targaryen Explora Salinas Grandes y Más en Argentina

Emilia Clarke en Jujuy: Daenerys Targaryen Explora Salinas Grandes y Más en ArgentinaEmilia Clarke, la icónica actriz británica conocida por su rol como Daenerys...

Elecciones Jujuy 2025: Dónde Votás, Candidatos y Cómo Usar la Boleta Única Sin Errores 🔥

Elecciones Jujuy 2025: Dónde Votás, Candidatos y Cómo Usar la Boleta Única Sin Errores 🔥Este domingo 26 de octubre, Jujuy define su representación en...

Ascenso Escalafonario para Empleados Públicos de Jujuy: Más de 3.000 Trabajadores Serán Beneficiados Desde Octubre

Ascenso Escalafonario para Empleados Públicos de Jujuy: Más de 3.000 Trabajadores Serán Beneficiados Desde OctubreEl Gobierno de Jujuy oficializó el Decreto Acuerdo Nº 3903,...

Enterate quién es Rodrigo Paz, el nuevo presidente de Bolivia que promete cambiar el rumbo del país

Enterate quién es Rodrigo Paz, el nuevo presidente de Bolivia que promete cambiar el rumbo del paísRodrigo Paz Pereira es el nombre que todos...

Franco Colapinto US GP 2025: drama con Gasly y clasificación difícil en Austin

Franco Colapinto US GP 2025: drama con Gasly y clasificación difícil en AustinFranco Colapinto US GP 2025 fue uno de los capítulos más intensos...

Lucas Comesaña árbitro Gimnasia de Jujuy: el juez que suspendió el partido del Lobo y su historial de polémicas

Lucas Comesaña árbitro Gimnasia de Jujuy: el juez que suspendió el partido del Lobo y su historial de polémicasEl árbitro Lucas Comesaña decidió suspender...

Gimnasia de Jujuy vs Deportivo Madryn – Ida Cuartos Reducido 2025

Gimnasia de Jujuy vs Deportivo Madryn – Ida Cuartos Reducido 2025El esperado encuentro entre Gimnasia de Jujuy y Deportivo Madryn por la ida de...