Código
Puede usar o descargar la carpeta en GitHub
Archivo "arp-admin.js"
jQuery(document).ready(function($){
// Al pulsar Quick Edit: rellenar campos con los datos actuales
var wp_inline_edit = inlineEditPost.edit;
inlineEditPost.edit = function( post_id ) {
wp_inline_edit.apply(this, arguments);
var id = 0;
if (typeof(post_id) == 'object') {
id = parseInt(this.getId(post_id));
}
if (id > 0) {
var row = $('#post-' + id);
var prefijo = row.find('td.column-arp_ubicacion').data('arp-prefijo') || '';
// Pero podemos obtener el texto mostrado y tratarlo:
var text = row.find('td.column-arp_ubicacion').text().trim();
// Rellenar los campos del quick edit
var $edit_row = $('#edit-' + id);
// Si no encontramos el zone, rellenamos el area del quick edit global
$('#edit-' + id).find('select[name="arp_ubicacion_prefijo_qe"]').val('');
$('#edit-' + id).find('input[name="arp_ubicacion_lugar_qe"]').val('');
// Alternativa simple: si text tiene espacio, separar primer palabra como prefijo y resto lugar
if (text && text !== '—') {
var parts = text.split(' ');
// Buscamos si el primer token coincide con una de las opciones
var opciones = ['Reportando','Reportó','Reportaron','En','Desde'];
var first = parts[0];
var pref = '';
var lugar = text;
// Buscar coincidencia prefijo exacta o "En vivo desde"
var known = ['Reportando','Reportó','Reportaron','En vivo desde','Desde'];
for (var i=0;i<known.length;i++){
if (text.indexOf(known[i]) === 0) {
pref = known[i];
lugar = text.replace(known[i],'').trim();
break;
}
}
if (pref) {
$('#edit-' + id).find('select[name="arp_ubicacion_prefijo_qe"]').val(pref);
$('#edit-' + id).find('input[name="arp_ubicacion_lugar_qe"]').val(lugar);
} else {
$('#edit-' + id).find('input[name="arp_ubicacion_lugar_qe"]').val(text);
}
}
}
};
// Cuando se abre quick edit en la lista desde el botón "Quick Edit" estándar,
// WordPress clona la fila .inline-edit-row; por eso usamos evento click
$(document).on('click', '.editinline', function(){
var row = $(this).closest('tr');
var post_id = row.attr('id').replace('post-','');
var text = row.find('td.column-arp_ubicacion').text().trim();
var $inline = $('#edit-'+post_id);
if (!$inline.length) {
// quick edit global
var $qe = $('#the-list').find('tr.inline-edit-row');
$qe.find('select[name="arp_ubicacion_prefijo_qe"]').val('');
$qe.find('input[name="arp_ubicacion_lugar_qe"]').val('');
if (text && text !== '—') {
// intentar separar
var known = ['Reportando','Reportó','Reportaron','En vivo desde','Desde'];
var pref = '';
var lugar = text;
for (var i=0;i<known.length;i++){
if (text.indexOf(known[i]) === 0) {
pref = known[i];
lugar = text.replace(known[i],'').trim();
break;
}
}
if (pref) {
$qe.find('select[name="arp_ubicacion_prefijo_qe"]').val(pref);
$qe.find('input[name="arp_ubicacion_lugar_qe"]').val(lugar);
} else {
$qe.find('input[name="arp_ubicacion_lugar_qe"]').val(text);
}
}
}
});
});Archivo "autor-ubicacion-elementor.php"
<?php
/*
Plugin Name: Información de Autor y Ubicación para Elementor
Description: Widget de Elementor para mostrar autor, foto, cargo, ubicación (prefijo + lugar) y fecha en reportajes. Incluye metabox, quick-edit y compatibilidad con Elementor.
Version: 3.0
Author: Marcos para El Ambientalista Post
*/
if (!defined('ABSPATH')) exit;
// -------------------------
// Encolar estilos frontend
// -------------------------
add_action('wp_enqueue_scripts', function() {
wp_enqueue_style('arp-elementor-style', plugin_dir_url(__FILE__) . 'style.css');
});
// -------------------------
// Registrar el widget en Elementor
// -------------------------
add_action('elementor/widgets/register', function($widgets_manager) {
require_once(__DIR__ . '/widget-autor.php');
$widgets_manager->register(new \ARP\Widgets\Autor_Ubicacion_Widget());
});
// -------------------------
// Añadir categoría de Elementor
// -------------------------
add_action('elementor/elements/categories_registered', function($elements_manager) {
$elements_manager->add_category(
'elambientalista',
[
'title' => esc_html__('El Ambientalista', 'arp-elementor'),
'icon' => 'fa fa-leaf',
]
);
});
// -------------------------
// Metabox: Solo UN campo: prefijo + lugar
// -------------------------
add_action('add_meta_boxes', function() {
add_meta_box(
'arp_autor_ubicacion',
'Agregar ubicación del autor',
'arp_autor_ubicacion_metabox',
['post'],
'side',
'default'
);
});
function arp_autor_ubicacion_metabox($post) {
// Prefijo guardado y lugar
$prefijo = get_post_meta($post->ID, '_arp_ubicacion_prefijo', true);
$lugar = get_post_meta($post->ID, '_arp_ubicacion_lugar', true);
// Opciones sugeridas
$opciones = [
'' => '-- Ninguno --',
'Reportando' => 'Reportando',
'Reportó' => 'Reportó',
'Reportaron' => 'Reportaron',
'En vivo desde' => 'En vivo desde',
'Desde' => 'Desde'
];
?>
<p>
<label for="arp_ubicacion_prefijo"><strong>Tipo</strong></label>
<select name="arp_ubicacion_prefijo" id="arp_ubicacion_prefijo" class="widefat">
<?php foreach ($opciones as $k => $v): ?>
<option value="<?php echo esc_attr($k); ?>" <?php selected($prefijo, $k); ?>><?php echo esc_html($v); ?></option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="arp_ubicacion_lugar"><strong>Ciudad / País</strong></label>
<input type="text" name="arp_ubicacion_lugar" id="arp_ubicacion_lugar" class="widefat"
placeholder="Ej: Ciudad de México, México" value="<?php echo esc_attr($lugar); ?>">
</p>
<p style="font-size:12px;color:#666;margin-top:6px;">Si dejas ambos en blanco, no se mostrará la ubicación en el widget.</p>
<?php
}
// -------------------------
// Guardar metadatos
// -------------------------
add_action('save_post', function($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
// Prefijo y lugar
if (isset($_POST['arp_ubicacion_prefijo'])) {
update_post_meta($post_id, '_arp_ubicacion_prefijo', sanitize_text_field($_POST['arp_ubicacion_prefijo']));
}
if (isset($_POST['arp_ubicacion_lugar'])) {
update_post_meta($post_id, '_arp_ubicacion_lugar', sanitize_text_field($_POST['arp_ubicacion_lugar']));
}
});
// -------------------------
// Helper: obtener ubicación completa (prefijo + lugar)
// -------------------------
function arp_get_post_ubicacion($post_id = null) {
if (!$post_id) $post_id = get_the_ID();
$prefijo = get_post_meta($post_id, '_arp_ubicacion_prefijo', true);
$lugar = get_post_meta($post_id, '_arp_ubicacion_lugar', true);
if (empty($prefijo) && empty($lugar)) return '';
$parts = [];
if (!empty($prefijo)) $parts[] = $prefijo;
if (!empty($lugar)) $parts[] = $lugar;
return implode(' ', $parts); // ej: "Reportando Ciudad de México"
}
// -------------------------
// Quick Edit: agregar columna y quick edit para ubicación
// -------------------------
add_filter('manage_posts_columns', function($columns) {
$columns['arp_ubicacion'] = __('Ubicación', 'arp-elementor');
return $columns;
});
add_action('manage_posts_custom_column', function($column, $post_id) {
if ($column === 'arp_ubicacion') {
$prefijo = get_post_meta($post_id, '_arp_ubicacion_prefijo', true);
$lugar = get_post_meta($post_id, '_arp_ubicacion_lugar', true);
if ($prefijo || $lugar) {
echo esc_html(trim($prefijo . ' ' . $lugar));
} else {
echo '—';
}
}
}, 10, 2);
// Añadir contenido al quick edit (caja invisible, estilo admin)
add_action('quick_edit_custom_box', function($column_name, $post_type) {
if ($column_name !== 'arp_ubicacion') return;
?>
<fieldset class="inline-edit-col-left">
<div class="inline-edit-col">
<label>
<span class="title">Tipo</span>
<select name="arp_ubicacion_prefijo_qe" class="arp-quick-prefijo">
<option value="">-- Ninguno --</option>
<option value="Reportando">Reportando</option>
<option value="Reportó">Reportó</option>
<option value="Reportaron">Reportaron</option>
<option value="En vivo desde">En vivo desde</option>
<option value="Desde">Desde</option>
</select>
</label>
<label>
<span class="title">Ciudad / País</span>
<input type="text" name="arp_ubicacion_lugar_qe" class="arp-quick-lugar" value="">
</label>
</div>
</fieldset>
<?php
}, 10, 2);
// Guardar Quick Edit (hook en save_post ya captura cambios de quick edit si hay datos)
// Para interceptar desde la lista necesitamos usar 'save_post' y valores que vienen por POST con names del quick edit.
add_action('save_post', function($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['arp_ubicacion_prefijo_qe'])) {
update_post_meta($post_id, '_arp_ubicacion_prefijo', sanitize_text_field($_POST['arp_ubicacion_prefijo_qe']));
}
if (isset($_POST['arp_ubicacion_lugar_qe'])) {
update_post_meta($post_id, '_arp_ubicacion_lugar', sanitize_text_field($_POST['arp_ubicacion_lugar_qe']));
}
}, 20, 1);
// -------------------------
// Encolar scripts admin para Quick Edit y media uploader (si quieres editar/avatar desde admin)
// -------------------------
add_action('admin_enqueue_scripts', function($hook) {
// Solo en listado de posts y editor
wp_enqueue_script('arp-admin-js', plugin_dir_url(__FILE__) . 'arp-admin.js', ['jquery'], false, true);
// Localizar texto y nonce si se requiere
wp_localize_script('arp-admin-js', 'arpAdmin', [
'ajax_url' => admin_url('admin-ajax.php'),
]);
});Archivo "style.css"
/* Estilos para el widget Autor y Ubicación - responsive y alineación */
/* contenedor */
.arp-autor-widget { font-family: Georgia, 'Times New Roman', serif; color: #111; }
/* layout: foto izquierda, texto derecha */
.arp-autor-inner { display:flex; align-items:flex-start; gap:14px; }
.arp-autor-left { flex: 0 0 auto; }
.arp-autor-right { display:flex; flex-direction:column; justify-content:center; }
/* Ubicación arriba del nombre — alineada con el texto principal */
.arp-ubicacion { font-size:13px; color:#666; margin-bottom:2px; line-height:1.1; }
/* Línea del nombre */
.arp-por-nombre { font-size:15px; color:#111; }
/* Fecha debajo del nombre, con transición */
.arp-fecha { font-size:13px; color:#666; margin-top:6px; height:auto; transition: transform .45s ease, opacity .45s ease; }
/* Responsive */
@media (max-width:768px) {
.arp-autor-inner { gap:10px; align-items:center; }
.arp-ubicacion { font-size:12px; }
.arp-por-nombre { font-size:14px; }
.arp-fecha { font-size:12px; margin-top:4px; }
}
/* Móvil estrecho: apilar */
@media (max-width:420px) {
.arp-autor-inner { flex-direction:row; align-items:center; gap:8px; }
.arp-autor-right { min-width:0; }
.arp-por-nombre { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
}Archivo "widget-autor.php"
<?php
namespace ARP\Widgets;
use Elementor\Widget_Base;
use Elementor\Controls_Manager;
if (!defined('ABSPATH')) exit;
class Autor_Ubicacion_Widget extends Widget_Base {
public function get_name() {
return 'autor_ubicacion_widget';
}
public function get_title() {
return __('Autor y Ubicación', 'arp-elementor');
}
public function get_icon() {
return 'eicon-person';
}
public function get_categories() {
return ['elambientalista'];
}
protected function register_controls() {
$this->start_controls_section('content_section', [
'label' => __('Contenido (override opcional)', 'arp-elementor'),
'tab' => Controls_Manager::TAB_CONTENT,
]);
// Foto independiente
$this->add_control('foto', [
'label' => __('Foto del autor (opcional)', 'arp-elementor'),
'type' => Controls_Manager::MEDIA,
'default' => ['url' => ''],
]);
// Nombre independiente (si quieres forzar otro nombre)
$this->add_control('nombre_forzado', [
'label' => __('Nombre del autor (opcional)', 'arp-elementor'),
'type' => Controls_Manager::TEXT,
'placeholder' => __('Ej: María López'),
]);
// Ubicación independiente (override)
$this->add_control('ubicacion_forzada', [
'label' => __('Ubicación (opcional - override)', 'arp-elementor'),
'type' => Controls_Manager::TEXT,
'placeholder' => __('Ej: Reportando desde Ciudad de México'),
]);
// Fecha independiente
$this->add_control('fecha_forzada', [
'label' => __('Texto de fecha (opcional)', 'arp-elementor'),
'type' => Controls_Manager::TEXT,
'placeholder' => __('Ej: Publicado el 25 de enero de 2025 a las 12:45 am'),
]);
// Ajustes responsivos: imagen tamaño
$this->add_control('foto_size', [
'label' => __('Tamaño de la foto (px)', 'arp-elementor'),
'type' => Controls_Manager::NUMBER,
'default' => 55,
]);
$this->end_controls_section();
}
protected function render() {
global $post;
if (!$post) return;
$settings = $this->get_settings_for_display();
// Datos base: autor WP
$author_id = $post->post_author;
$author_name_wp = get_the_author_meta('display_name', $author_id);
$author_avatar_wp = get_avatar_url($author_id, ['size' => 120]);
// Ubicación desde metadatos (prefijo + lugar)
$ubicacion_meta = function_exists('arp_get_post_ubicacion') ? arp_get_post_ubicacion($post->ID) : '';
// Valores finales (prioridad: Elementor override > WP post data)
$foto = !empty($settings['foto']['url']) ? $settings['foto']['url'] : $author_avatar_wp;
$author_name = !empty($settings['nombre_forzado']) ? $settings['nombre_forzado'] : $author_name_wp;
$ubicacion = !empty($settings['ubicacion_forzada']) ? $settings['ubicacion_forzada'] : $ubicacion_meta;
$fecha_override = !empty($settings['fecha_forzada']) ? $settings['fecha_forzada'] : '';
// --- INICIO DE LA LÓGICA DE FECHA MODIFICADA ---
if ($fecha_override) {
$texto_fecha = $fecha_override;
} else {
// Usamos timestamps (formato 'U') para cálculos precisos.
$pub_ts = get_the_time('U', $post->ID);
$mod_ts = get_the_modified_time('U', $post->ID);
$current_ts = current_time('U');
// Se considera 'modificado' si hay más de 60 segundos de diferencia.
if ($mod_ts - $pub_ts > 60) {
$diff_seconds = $current_ts - $mod_ts;
if ($diff_seconds < HOUR_IN_SECONDS) {
// 1. Actualización menor a 1 hora
$texto_fecha = sprintf(__('Actualizado hace %s'), human_time_diff($mod_ts, $current_ts));
} elseif (date('Ymd', $mod_ts) === date('Ymd', $current_ts)) {
// 2. Actualización hoy (hace más de una hora)
$texto_fecha = "Actualizado hoy a las " . get_the_modified_time('g:i a', $post);
} elseif (date('Ymd', $mod_ts) === date('Ymd', $current_ts - DAY_IN_SECONDS)) {
// 3. Actualización ayer
$texto_fecha = "Actualizado ayer a las " . get_the_modified_time('g:i a', $post);
} else {
// 4. Actualización hace más de un día (y no fue ayer)
$texto_fecha = "Actualizado el " . get_the_modified_date('j \d\e F \a \l\a\s g:i a', $post);
}
} else {
// No hay modificación real, mostrar fecha de publicación.
$texto_fecha = "Publicado el " . get_the_date('j \d\e F \d\e Y \a \l\a\s g:i a', $post);
}
}
// --- FIN DE LA LÓGICA DE FECHA MODIFICADA ---
// Tamaño foto responsive
$foto_size = intval($settings['foto_size']) ?: 55;
$foto_size_style = esc_attr($foto_size);
// Si no hay nada para mostrar, salir
if (empty($author_name)) return;
?>
<div class="arp-autor-widget" style="margin-top:20px;">
<div class="arp-autor-inner">
<div class="arp-autor-left">
<img src="<?php echo esc_url($foto); ?>"
alt="<?php echo esc_attr($author_name); ?>"
style="width:<?php echo $foto_size_style; ?>px;height:<?php echo $foto_size_style; ?>px;object-fit:cover;border-radius:50%;border:1px solid #ddd;">
</div>
<div class="arp-autor-right">
<?php if ($ubicacion): ?>
<div class="arp-ubicacion" aria-hidden="true"><?php echo esc_html($ubicacion); ?></div>
<?php endif; ?>
<div class="arp-por-nombre">Por <strong><?php echo esc_html($author_name); ?></strong></div>
<?php if ($texto_fecha): ?>
<div class="arp-fecha" aria-live="polite"><?php echo esc_html($texto_fecha); ?></div>
<?php endif; ?>
</div>
</div>
</div>
<?php
}
}Última actualización
¿Te fue útil?