327 lines
12 KiB
PHP
327 lines
12 KiB
PHP
<?php
|
|
if (!defined('ABSPATH')) exit;
|
|
|
|
class Simply_Code_Admin {
|
|
const OPTION_SAFE_MODE = 'simply_code_safe_mode';
|
|
|
|
/**
|
|
* Initialize admin hooks
|
|
*/
|
|
public static function init() {
|
|
add_action('admin_menu', [self::class, 'register_menu']);
|
|
add_action('admin_enqueue_scripts', [self::class, 'enqueue_admin_scripts']);
|
|
|
|
// CRÍTICO: Registrar handler AJAX para detección de hooks
|
|
add_action('wp_ajax_simply_code_detect_hooks', [Simply_Snippet_Editor::class, 'ajax_detect_hooks']);
|
|
}
|
|
|
|
/**
|
|
* Register admin menu and submenus
|
|
*/
|
|
public static function register_menu() {
|
|
add_menu_page(
|
|
'Simply Code',
|
|
'Simply Code',
|
|
'manage_options',
|
|
'simply-code',
|
|
[self::class, 'main_page'],
|
|
'dashicons-editor-code'
|
|
);
|
|
|
|
add_submenu_page(
|
|
'simply-code',
|
|
'Nuevo Snippet',
|
|
'Nuevo Snippet',
|
|
'manage_options',
|
|
'simply-code-new',
|
|
[Simply_Snippet_Editor::class, 'new_snippet']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Enqueue admin scripts and styles
|
|
*/
|
|
public static function enqueue_admin_scripts($hook) {
|
|
// Solo cargar en nuestras páginas
|
|
if (strpos($hook, 'simply-code') === false) {
|
|
return;
|
|
}
|
|
|
|
wp_enqueue_script(
|
|
'simply-code-editor',
|
|
plugins_url('assets/js/editor.js', SC_PATH . 'simply-code.php'),
|
|
['jquery'],
|
|
'1.0.0',
|
|
true
|
|
);
|
|
|
|
wp_enqueue_style(
|
|
'simply-code-editor',
|
|
plugins_url('assets/css/editor.css', SC_PATH . 'simply-code.php'),
|
|
[],
|
|
'1.0.0'
|
|
);
|
|
|
|
// Localizar script con ajaxurl
|
|
wp_localize_script('simply-code-editor', 'simply_code_ajax', [
|
|
'ajax_url' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('simply_code_detect_hooks')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Handle admin notices - VERSIÓN MEJORADA CON TRANSIENTS
|
|
*/
|
|
private static function handle_admin_notices() {
|
|
$notice = '';
|
|
|
|
// Manejar mensajes de éxito desde transients
|
|
$success_message = get_transient('simply_code_success');
|
|
if ($success_message) {
|
|
$notice .= '<div class="notice notice-success is-dismissible"><p>' . esc_html($success_message) . '</p></div>';
|
|
delete_transient('simply_code_success');
|
|
}
|
|
|
|
// Manejar mensajes de error desde transients
|
|
$error_message = get_transient('simply_code_error');
|
|
if ($error_message) {
|
|
$notice .= '<div class="notice notice-error is-dismissible"><p>' . esc_html($error_message) . '</p></div>';
|
|
delete_transient('simply_code_error');
|
|
}
|
|
|
|
// Mantener compatibilidad con parámetros GET existentes
|
|
if (isset($_GET['created']) && isset($_GET['snippet'])) {
|
|
$snippet_name = sanitize_text_field(urldecode($_GET['snippet']));
|
|
$notice .= sprintf(
|
|
'<div class="notice notice-success is-dismissible"><p>Snippet "%s" creado correctamente.</p></div>',
|
|
esc_html($snippet_name)
|
|
);
|
|
}
|
|
|
|
if (isset($_GET['updated']) && isset($_GET['snippet'])) {
|
|
$snippet_name = sanitize_text_field(urldecode($_GET['snippet']));
|
|
$notice .= sprintf(
|
|
'<div class="notice notice-success is-dismissible"><p>Snippet "%s" actualizado correctamente.</p></div>',
|
|
esc_html($snippet_name)
|
|
);
|
|
}
|
|
|
|
if (isset($_GET['deleted']) && isset($_GET['snippet'])) {
|
|
$snippet_name = sanitize_text_field(urldecode($_GET['snippet']));
|
|
$notice .= sprintf(
|
|
'<div class="notice notice-success is-dismissible"><p>Snippet "%s" eliminado correctamente.</p></div>',
|
|
esc_html($snippet_name)
|
|
);
|
|
}
|
|
|
|
if (isset($_GET['saved'])) {
|
|
$message = 'Snippet guardado correctamente.';
|
|
if (isset($_GET['snippet_name'])) {
|
|
$snippet_name = sanitize_text_field(urldecode($_GET['snippet_name']));
|
|
$message = sprintf('Snippet "%s" guardado correctamente.', esc_html($snippet_name));
|
|
}
|
|
$notice .= sprintf(
|
|
'<div class="notice notice-success is-dismissible"><p>%s</p></div>',
|
|
$message
|
|
);
|
|
}
|
|
|
|
if (isset($_GET['status_changed']) && isset($_GET['snippet']) && isset($_GET['status'])) {
|
|
$snippet_name = sanitize_text_field(urldecode($_GET['snippet']));
|
|
$status = $_GET['status'] === 'activated' ? 'activado' : 'desactivado';
|
|
$notice .= sprintf(
|
|
'<div class="notice notice-success is-dismissible"><p>Snippet "%s" %s correctamente.</p></div>',
|
|
esc_html($snippet_name),
|
|
$status
|
|
);
|
|
}
|
|
|
|
if (isset($_GET['reordered'])) {
|
|
$notice .= '<div class="notice notice-success is-dismissible"><p>Orden de snippets actualizado correctamente.</p></div>';
|
|
}
|
|
|
|
if (isset($_GET['safe_mode_updated'])) {
|
|
$notice .= '<div class="notice notice-success is-dismissible"><p>Configuración de modo seguro actualizada correctamente.</p></div>';
|
|
}
|
|
|
|
return $notice;
|
|
}
|
|
|
|
/**
|
|
* Safe redirect with proper buffer cleanup
|
|
*/
|
|
private static function safe_redirect($url) {
|
|
// Solo limpiar si hay buffers de usuario con contenido
|
|
if (ob_get_level() > 0 && ob_get_contents() !== false) {
|
|
$buffer_content = ob_get_contents();
|
|
if (!empty(trim($buffer_content))) {
|
|
@ob_end_clean();
|
|
}
|
|
}
|
|
|
|
// Verificar que no se hayan enviado headers
|
|
if (headers_sent($file, $line)) {
|
|
error_log("Simply Code: Headers already sent in {$file} at line {$line}, cannot redirect to: {$url}");
|
|
echo '<script>setTimeout(function(){ window.location.href = "' . esc_js($url) . '"; }, 100);</script>';
|
|
echo '<noscript><meta http-equiv="refresh" content="0;url=' . esc_attr($url) . '" /></noscript>';
|
|
exit;
|
|
}
|
|
|
|
// Usar wp_safe_redirect que es más robusto
|
|
$result = wp_safe_redirect($url);
|
|
if (!$result) {
|
|
error_log("Simply Code: wp_safe_redirect failed for URL: {$url}");
|
|
echo '<script>window.location.href = "' . esc_js($url) . '";</script>';
|
|
}
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Main admin page handler
|
|
*/
|
|
public static function main_page() {
|
|
$action_message = '';
|
|
|
|
// Verificar permisos
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('No tienes permisos suficientes para acceder a esta página.'));
|
|
}
|
|
|
|
// CRÍTICO: Manejar POST antes de cualquier output
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
if (empty($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'simply_code_actions')) {
|
|
wp_die('Error de seguridad');
|
|
}
|
|
|
|
// Solo delete requiere redirect (para evitar resubmisión accidental)
|
|
if (isset($_POST['delete_snippet'])) {
|
|
self::handle_deletion(); // Hace redirect y exit
|
|
}
|
|
|
|
// Otras acciones sin redirect para evitar el efecto "doble carga"
|
|
if (isset($_POST['toggle_snippet_status'])) {
|
|
$action_message = self::handle_status_toggle_inline();
|
|
}
|
|
elseif (isset($_POST['move_up']) || isset($_POST['move_down'])) {
|
|
$action_message = self::handle_reordering_inline();
|
|
}
|
|
elseif (isset($_POST['safe_mode_toggle'])) {
|
|
$action_message = self::handle_safe_mode_inline();
|
|
}
|
|
else {
|
|
// Si no coincide con ninguna acción conocida
|
|
$action_message = 'Acción POST no reconocida';
|
|
}
|
|
}
|
|
|
|
// Mostrar notices de URL parameters
|
|
$notice = self::handle_admin_notices();
|
|
|
|
// Agregar mensaje de acción inline si existe
|
|
if ($action_message) {
|
|
$notice .= '<div class="notice notice-success is-dismissible"><p>' . esc_html($action_message) . '</p></div>';
|
|
}
|
|
|
|
// Obtener snippets
|
|
$snippets = Simply_Snippet_Manager::list_snippets(true, true);
|
|
|
|
// Mostrar notices
|
|
if ($notice) {
|
|
echo wp_kses_post($notice);
|
|
}
|
|
|
|
// Renderizar vista
|
|
include SC_PATH . 'admin/views/snippets-list.php';
|
|
}
|
|
|
|
/**
|
|
* Handle status toggle without redirect
|
|
*/
|
|
private static function handle_status_toggle_inline() {
|
|
if (!isset($_POST['toggle_snippet_status'], $_POST['snippet_name'])) {
|
|
return 'Error: Datos de formulario incompletos para cambio de estado.';
|
|
}
|
|
|
|
$snippet_name = sanitize_text_field($_POST['snippet_name']);
|
|
$new_status = isset($_POST['snippet_active']);
|
|
|
|
if (Simply_Snippet_Manager::toggle_snippet_status($snippet_name, $new_status)) {
|
|
$status_text = $new_status ? 'activado' : 'desactivado';
|
|
return sprintf('Snippet "%s" %s correctamente.', esc_html($snippet_name), $status_text);
|
|
}
|
|
|
|
return sprintf('Error al cambiar el estado del snippet "%s".', esc_html($snippet_name));
|
|
}
|
|
|
|
/**
|
|
* Handle reordering without redirect
|
|
*/
|
|
private static function handle_reordering_inline() {
|
|
if (!isset($_POST['move_up']) && !isset($_POST['move_down'])) {
|
|
return 'Error: Acción de reordenamiento no especificada.';
|
|
}
|
|
|
|
$snippets = Simply_Snippet_Manager::list_snippets(true);
|
|
$i = isset($_POST['move_up']) ? (int)$_POST['move_up'] : (int)$_POST['move_down'];
|
|
$names = array_map(function($s) { return $s['name']; }, $snippets);
|
|
$changed = false;
|
|
|
|
if (isset($_POST['move_up']) && $i > 0 && $i < count($names)) {
|
|
$tmp = $names[$i-1];
|
|
$names[$i-1] = $names[$i];
|
|
$names[$i] = $tmp;
|
|
$changed = true;
|
|
}
|
|
elseif (isset($_POST['move_down']) && $i >= 0 && $i < count($names) - 1) {
|
|
$tmp = $names[$i+1];
|
|
$names[$i+1] = $names[$i];
|
|
$names[$i] = $tmp;
|
|
$changed = true;
|
|
}
|
|
|
|
if ($changed && Simply_Snippet_Manager::update_snippets_order($names)) {
|
|
return 'Orden de snippets actualizado correctamente.';
|
|
}
|
|
|
|
return 'Error al actualizar el orden de los snippets.';
|
|
}
|
|
|
|
/**
|
|
* Handle safe mode without redirect
|
|
*/
|
|
private static function handle_safe_mode_inline() {
|
|
if (!isset($_POST['safe_mode_toggle'])) {
|
|
return 'Error: Configuración de modo seguro no especificada.';
|
|
}
|
|
|
|
update_option(
|
|
self::OPTION_SAFE_MODE,
|
|
isset($_POST['safe_mode']) && $_POST['safe_mode'] === 'on' ? 'on' : 'off'
|
|
);
|
|
|
|
return 'Configuración de modo seguro actualizada correctamente.';
|
|
}
|
|
|
|
/**
|
|
* Handle deletion with redirect
|
|
*/
|
|
private static function handle_deletion() {
|
|
if (!isset($_POST['delete_snippet'], $_POST['snippet_name'])) {
|
|
wp_die('Error: Datos de eliminación incompletos.');
|
|
}
|
|
|
|
$snippet_name = sanitize_text_field($_POST['snippet_name']);
|
|
|
|
if (Simply_Snippet_Manager::delete_snippet($snippet_name)) {
|
|
$success_message = sprintf('Snippet "%s" eliminado correctamente.', esc_html($snippet_name));
|
|
set_transient('simply_code_success', $success_message, 45);
|
|
|
|
$redirect_url = admin_url('admin.php?page=simply-code');
|
|
self::safe_redirect($redirect_url);
|
|
return; // Never reached
|
|
}
|
|
|
|
wp_die('Error al eliminar el snippet "' . esc_html($snippet_name) . '".');
|
|
}
|
|
}
|