Importador XML

<?php
/**
 * Plugin Name: Importador XML Avanzado
 * Description: Permite subir un archivo XML desde el panel de administración y genera entradas evitando duplicados.
 * Version: 1.1
 * Author: Tu Nombre
 */

if ( ! defined( 'ABSPATH' ) ) exit; // seguridad

// Menú en administración
add_action('admin_menu', 'importador_xml_menu');
function importador_xml_menu() {
    add_menu_page(
        'Importador XML',
        'Importador XML',
        'manage_options',
        'importador-xml',
        'importador_xml_page',
        'dashicons-database-import'
    );
}

// Página del plugin
function importador_xml_page() {
    ?>
    <div class="wrap">
        <h1>Importador de Entradas desde XML</h1>

        <h2>Subir XML</h2>
        <form method="post" enctype="multipart/form-data">
            <?php wp_nonce_field('importador_xml_nonce','importador_xml_nonce_field'); ?>
            <input type="file" name="archivo_xml" accept=".xml" required>
            <input type="submit" name="subir_xml" class="button button-secondary" value="Subir XML">
        </form>

        <h2>Importar entradas</h2>
        <form method="post">
            <?php wp_nonce_field('importador_xml_nonce','importador_xml_nonce_field'); ?>
            <input type="submit" name="importar_xml" class="button button-primary" value="Importar desde XML">
        </form>
    </div>
    <?php

    // Procesar subida
    if (isset($_POST['subir_xml']) && check_admin_referer('importador_xml_nonce','importador_xml_nonce_field')) {
        importador_xml_subir();
    }

    // Procesar importación
    if (isset($_POST['importar_xml']) && check_admin_referer('importador_xml_nonce','importador_xml_nonce_field')) {
        importador_xml_procesar();
    }
}

// Subir archivo XML a /uploads/importador-xml/
function importador_xml_subir() {
    if (!empty($_FILES['archivo_xml']['tmp_name'])) {
        $upload_dir = wp_upload_dir();
        $destino_dir = $upload_dir['basedir'] . '/importador-xml/';

        if (!file_exists($destino_dir)) {
            wp_mkdir_p($destino_dir);
        }

        $destino = $destino_dir . 'datos.xml';

        if (move_uploaded_file($_FILES['archivo_xml']['tmp_name'], $destino)) {
            echo "<div class='updated'><p>Archivo subido correctamente: " . esc_html($destino) . "</p></div>";
        } else {
            echo "<div class='error'><p>Error al subir el archivo.</p></div>";
        }
    }
}

// Procesar archivo XML y crear posts
function importador_xml_procesar() {
    $upload_dir = wp_upload_dir();
    $ruta = $upload_dir['basedir'] . '/importador-xml/datos.xml';

    if (!file_exists($ruta)) {
        echo "<div class='error'><p>No se encontró ningún archivo XML en: $ruta</p></div>";
        return;
    }

    $xml = simplexml_load_file($ruta);
    if (!$xml) {
        echo "<div class='error'><p>Error al leer el archivo XML.</p></div>";
        return;
    }

    $contador = 0;
    foreach ($xml->item as $item) {
        $titulo = sanitize_text_field((string) $item->title);
        $contenido = wp_kses_post((string) $item->body);

        // Comprobar si ya existe un post con este título
        $existe = get_page_by_title($titulo, OBJECT, 'post');
        if (!$existe) {
           
            $nuevo_post = array(
                'post_title'   => $titulo,
                'post_content' => $contenido,
                'post_status'  => 'publish',
                'post_author'  => get_current_user_id(),
                'post_type'    => 'post'
            );

            wp_insert_post($nuevo_post);
            $contador++;
        }
    }

    echo "<div class='updated'><p>Se importaron $contador nuevas entradas desde el XML.</p></div>";
}

Ejemplo plugin consulta datos externos

Vamos a crear un plugin que consulte datos externos de una API y los muestre vía shortcode

1.- Crear el shortcode


<?php
/*
Plugin Name: Mostrar datos de una API externa
Description: Consulta los datos de una API y los muestra donde yo ponga el shortcode
Version: 1.0
Author: Jotapeich
*/

function mostrar_datos_func( $atts ) {
  
    return "Aquí se mostrarán los datos";
}
add_shortcode( 'datos_api', 'mostrar_datos_func' );

2.- Obtener los datos de una api externa

<?php
/*
Plugin Name: Mostrar datos de una API externa
Description: Consulta los datos de una API y los muestra donde yo ponga el shortcode
Version: 1.0
Author: Jotapeich
*/
function consultar_api( $cantidad = 5 ) {
    $url = "https://jsonplaceholder.typicode.com/posts"; // API de ejemplo

    $response = wp_remote_get( $url );
    if ( is_wp_error( $response ) ) {
        return "<p>Error al consultar la API.</p>";
    }

    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );

    if ( ! is_array( $data ) ) {
        return "<p>Respuesta inválida de la API.</p>";
    } 
    
}
function mostrar_datos_func( $atts ) {
    consultar_api();
    return "Aquí se mostrarán los datos";
}
add_shortcode( 'datos_api', 'mostrar_datos_func' );

3.- Formatear los datos que me llegan:

<?php
/*
Plugin Name: Mostrar datos de una API externa
Description: Consulta los datos de una API y los muestra donde yo ponga el shortcode
Version: 1.0
Author: Jotapeich
*/
function consultar_api( $cantidad = 5 ) {
    $url = "https://jsonplaceholder.typicode.com/posts"; // API de ejemplo

    $response = wp_remote_get( $url );
    if ( is_wp_error( $response ) ) {
        return "<p>Error al consultar la API.</p>";
    }

    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );

    if ( ! is_array( $data ) ) {
        return "<p>Respuesta inválida de la API.</p>";
    } 
     $data = array_slice( $data, 0, intval($cantidad) );

    $output  = '<table style="border-collapse: collapse; width:100%; border:1px solid #ccc;">';
    $output .= '<thead><tr style="background:#f4f4f4;"><th style="padding:8px;border:1px solid #ccc;">ID</th><th style="padding:8px;border:1px solid #ccc;">Título</th><th style="padding:8px;border:1px solid #ccc;">Body</th></tr></thead><tbody>';

    foreach ( $data as $item ) {
        $output .= '<tr>';
        $output .= '<td style="padding:8px;border:1px solid #ccc;">' . esc_html($item['id']) . '</td>';
        $output .= '<td style="padding:8px;border:1px solid #ccc;">' . esc_html($item['title']) . '</td>';
        $output .= '<td style="padding:8px;border:1px solid #ccc;">' . nl2br(esc_html($item['body'])) . '</td>';
        $output .= '</tr>';
    }

    $output .= '</tbody></table>';

    return $output;
}
function mostrar_datos_func( $atts ) {
    
    return consultar_api();
}
add_shortcode( 'datos_api', 'mostrar_datos_func' );

4.- Le voy a poner un parámetro al shortcode

function mostrar_datos_func( $atts ) {
     $atts = shortcode_atts( array(
        'cantidad' => 5,
    ), $atts, 'mis_datos' );
    return consultar_api($atts['cantidad']);
}

5.- Vamos a añadir opciones

<?php
/*
Plugin Name: Mostrar datos de una API externa
Description: Consulta los datos de una API y los muestra donde yo ponga el shortcode
Version: 1.0
Author: Jotapeich
*/
function consultar_api( $cantidad = 5 ) {
    $url = "https://jsonplaceholder.typicode.com/posts"; // API de ejemplo

    $response = wp_remote_get( $url );
    if ( is_wp_error( $response ) ) {
        return "<p>Error al consultar la API.</p>";
    }

    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );

    if ( ! is_array( $data ) ) {
        return "<p>Respuesta inválida de la API.</p>";
    } 
     $data = array_slice( $data, 0, intval($cantidad) );

    $output  = '<table style="border-collapse: collapse; width:100%; border:1px solid #ccc;">';
    $output .= '<thead><tr style="background:#f4f4f4;"><th style="padding:8px;border:1px solid #ccc;">ID</th><th style="padding:8px;border:1px solid #ccc;">Título</th><th style="padding:8px;border:1px solid #ccc;">Body</th></tr></thead><tbody>';

    foreach ( $data as $item ) {
        $output .= '<tr>';
        $output .= '<td style="padding:8px;border:1px solid #ccc;">' . esc_html($item['id']) . '</td>';
        $output .= '<td style="padding:8px;border:1px solid #ccc;">' . esc_html($item['title']) . '</td>';
        $output .= '<td style="padding:8px;border:1px solid #ccc;">' . nl2br(esc_html($item['body'])) . '</td>';
        $output .= '</tr>';
    }

    $output .= '</tbody></table>';

    return $output;
}
function mostrar_datos_func( $atts ) {

    $default_cantidad = get_option( 'asp_cantidad_default', 5 );
     $atts = shortcode_atts( array(
        'cantidad' => $default_cantidad,
    ), $atts, 'mis_datos' );
    return consultar_api($atts['cantidad']);
}
add_shortcode( 'datos_api', 'mostrar_datos_func' );


// ===========================
// 3. Menú en administración
// ===========================
function asp_add_admin_menu() {
    add_menu_page(
        'Configuración API', // Título de la página
        'Configuración API',              // Texto en el menú
        'manage_options',             // Capacidad requerida
        'asp-config',                 // Slug del menú
        'asp_options_page_html',      // Callback
        'dashicons-admin-generic',    // Icono
        20                            // Posición
    );
}
add_action( 'admin_menu', 'asp_add_admin_menu' );

// ===========================
// 4. Registrar ajustes
// ===========================
function asp_settings_init() {
    register_setting( 'asp_options_group', 'asp_cantidad_default', array(
        'type' => 'integer',
        'default' => 5,
    ) );

    add_settings_section(
        'asp_section',
        'Configuración del shortcode',
        '__return_false',
        'asp_options_group'
    );

    add_settings_field(
        'asp_cantidad_default',
        'Cantidad por defecto',
        'asp_field_cantidad_render',
        'asp_options_group',
        'asp_section'
    );
}
add_action( 'admin_init', 'asp_settings_init' );

// Campo de formulario
function asp_field_cantidad_render() {
    $valor = get_option( 'asp_cantidad_default', 5 );
    echo '<input type="number" name="asp_cantidad_default" value="' . esc_attr( $valor ) . '" min="1" max="50">';
}

// ===========================
// 5. Página HTML en admin
// ===========================
function asp_options_page_html() {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }
    ?>
    <div class="wrap">
        <h1>Configuración de los datos de la api externa</h1>
        <form action="options.php" method="post">
            <?php
            settings_fields( 'asp_options_group' );
            do_settings_sections( 'asp_options_group' );
            submit_button();
            ?>
        </form>
    </div>
    <?php
}

Ejemplo opciones en WordPress

<?php
/**
 * Plugin Name: Contar palabras
 * Description: Cuenta las palabras que tiene una entrada del blog y lo pone al final
 * Version: 1.1
 * Author: Jotapé
 */


// Esta función se encarga de contar las palabras y añadirlas
function contar_palabras($content){
    $ppm=get_option( 'palabras_minuto_default', 200 );
    // usamos str_word_count para contar las palabras: se puede mejorar para no contar html o imágenes o etc...
    $num_palabras=str_word_count($content);
    // Calculo el tiempo de lectura
    $tiempo=round($num_palabras/$ppm,1);
    // Creo el texto a añadir. Como son comillas dobles puedo poner la variable dentro
    $texto="Número de palabras: <b>$num_palabras</b>. Tiempo estimado de lectura: <b>$tiempo minutos</b>";

    // Devuelvo el contenido con el texto anterior. 
    return "<p>$texto</p>$content";
}

// Añado el filtro para modificar el contenido
add_filter("the_content","contar_palabras");

function ppm_add_admin_menu() {
    add_menu_page(
        'Palabras por minuto', // Título de la página
        'Config PPM',              // Texto en el menú
        'manage_options',             // Capacidad requerida
        'ppm-config',                 // Slug del menú
        'ppm_options_page_html',      // Callback
        'dashicons-admin-generic',    // Icono
        20                            // Posición
    );
}
add_action( 'admin_menu', 'ppm_add_admin_menu' );

function ppm_settings_init() {
    register_setting( 'options_contar_palabras', 'palabras_minuto_default', array(
        'type' => 'integer',        
    'sanitize_callback' => 'absint',
        'default' => 200,
    ) );

    add_settings_section(
        'contar_palabras_section',
        'Configuración de las palabras por minuto',
        function() { echo '<p>Configura el valor de las palabras por minuto para estimar el tiempo de lectura.</p>'; },
        'options_contar_palabras'
    );

    add_settings_field(
        'palabras_minuto_default',
        'Palabras por minuto por defecto',
        'asp_field_palabras_render',
        'options_contar_palabras',
        'contar_palabras_section'
    );
}
add_action( 'admin_init', 'ppm_settings_init' );

function asp_field_palabras_render() {
    $valor = get_option( 'palabras_minuto_default', 200 );
    echo '<input type="number" name="palabras_minuto_default" value="' . esc_attr( $valor ) . '" min="50" max="500">';
}

function ppm_options_page_html() {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }
    ?>
    <div class="wrap">
        <h1>Configuración de las palabras por minuto por defecto</h1>
        <form action="options.php" method="post">
            <?php
            settings_fields( 'options_contar_palabras' );
            do_settings_sections( 'options_contar_palabras' );
            submit_button();
            ?>
        </form>
    </div>
    <?php
}

Ejercicios shortcode

1.- Crear un shortcode llamado ‘cuestionario’ que nos muestre un texto de encabezado que ponga ‘Cuestionario de wwordpress’
2.- Sobre ese shortcode añadir un array de 10 preguntas sobre wordpress. Ejemplo:
$preguntas=[«¿Qué es wp?»,»Desde donde se descarga WP»,»Como se llama el contenido de wp que tiene etiquetas?»]
3.- En el shortcode elegir una pregunta al azar y crear un formulario con la pregunta, un campo para responder y un botón de enviar
4.- Recoger la respuesta y ver si es correcta comparándola con un array de respuestas, ejemplo:
$respuestas=[«CMS»,»wordpress.org»,»Entrada»]
Si la respuesta es correcta indicarlo y si no lo es, también

5.- Nivel Pro: Añadir cuatro respuestas que una sea la correcta y que el usuario la elija.

<?php
/*
Plugin Name: Cuestionario WP
Description: Un pequeño cuestionario para poner a prueba nuestros conocimientos
Version: 1.0
Author: Tu Nombre
*/

add_shortcode("cuestionario","crear_cuestionario");

function crear_cuestionario(){
    ob_start();
    $respuestas=["CMS","wordpress.org","Entrada"];
     if ( isset($_POST['fb_submit']) ) {
        
        $respuesta=sanitize_text_field($_POST['respuesta']);
        $numero=sanitize_text_field($_POST['pregunta']);
        if ($respuesta==$respuestas[$numero]){
            echo "Respuesta correcta ¡Muy bien!";
        }else{
            echo "Incorrecto, eres un looser";
        }
     }
    $preguntas=["¿Qué es wp?","Desde donde se descarga WP","Como se llama el contenido de wp que tiene etiquetas?"];
    $numero=rand(0,count($preguntas)-1);
    $pregunta=$preguntas[$numero];
     // Formulario HTML
    ?>
    <h2><?=$pregunta?></h2>
    <form method="post">
        <input type="hidden" name="pregunta" value="<?=$numero?>"/>
        <p>
            <label for="fb_titulo">Respuesta:</label><br>
            <input type="text" name="respuesta" id="respuesta" required style="width:100%;">
        </p>
       <p>
            <input type="submit" name="fb_submit" value="enviar respuesta">
        </p>
    </form>
    <?php
    return ob_get_clean();
}

Versión PRO

<?php
/*
Plugin Name: Cuestionario WP
Description: Un pequeño cuestionario para poner a prueba nuestros conocimientos
Version: 1.0
Author: Tu Nombre
*/

add_shortcode("cuestionario","crear_cuestionario");

function crear_cuestionario(){
    ob_start();
    $cuestionario=[
        ["pregunta"=>"¿Qué es wordpress?",
        "respuestas"=>["CMS","Web","La palabra de la prensa","No tengo ni idea"]],
         ["pregunta"=>"¿Desde donde se descarga WP?",
        "respuestas"=>["wordpress.org","Un sitio pirata","Mis descargas.com","Tengo miedo de descargar cosas"]],
         ["pregunta"=>"¿Cómo se llama el contenido que tiene etiquetas?",
        "respuestas"=>["Entradas","Etiquetometro","Páginas","Me llamo Ralph"]],
    ];
     if ( isset($_POST['fb_submit']) ) {
        $correcta=sanitize_text_field($_POST['correcta']);
        $respuesta=sanitize_text_field($_POST['respuesta']);
        if ($respuesta==$correcta){
            echo "Respuesta correcta ¡Muy bien!";
        }else{
            echo "Incorrecto, eres un looser";
        }
     }

    $elegida=$cuestionario[array_rand($cuestionario)];
    $correcta=$elegida['respuestas'][0];
    shuffle($elegida['respuestas']);
     // Formulario HTML
    ?>
    <h2><?=$elegida['pregunta']?></h2>
    <form method="post">
        <input type="hidden" name="correcta" value="<?=$correcta?>"/>
        <p>
            <label for="fb_titulo">Respuesta:</label><br>
            <?php  
                foreach($elegida['respuestas'] as $respuesta){
            ?>
                <label><input type="radio" name='respuesta' value='<?=$respuesta?>'>
                <?=$respuesta?></label>
            <?php
            s }
    ?> </p>
       <p>
            <input type="submit" name="fb_submit" value="enviar respuesta">
        </p>
    </form>
    <?php
    return ob_get_clean();
}

Ejemplo shortcode

/**
 * Shortcode: [form_borrador]
 */
function fb_formulario_shortcode() {
    ob_start();

    // Procesar el formulario si se envió
    if ( isset($_POST['fb_submit']) ) {
        
        $titulo   = sanitize_text_field($_POST['fb_titulo']);
        $contenido = sanitize_textarea_field($_POST['fb_contenido']);

        // Crear el borrador
        $nuevo_post = array(
            'post_title'   => $titulo,
            'post_content' => $contenido,
            'post_status'  => 'draft',
            'post_type'    => 'post'
        );

        $post_id = wp_insert_post($nuevo_post);

        if ($post_id) {
            echo "<p style='color:green;'><strong>✅ Borrador creado correctamente.</strong></p>";
        } else {
            echo "<p style='color:red;'><strong>❌ Hubo un error al crear el borrador.</strong></p>";
        }
    }

    // Formulario HTML
    ?>
    <form method="post">
    
        <p>
            <label for="fb_titulo">Título:</label><br>
            <input type="text" name="fb_titulo" id="fb_titulo" required style="width:100%;">
        </p>

        <p>
            <label for="fb_contenido">Contenido:</label><br>
            <textarea name="fb_contenido" id="fb_contenido" rows="6" required style="width:100%;"></textarea>
        </p>

        <p>
            <input type="submit" name="fb_submit" value="Crear borrador">
        </p>
    </form>
    <?php

    return ob_get_clean();
}
add_shortcode('form_borrador', 'fb_formulario_shortcode');

Ejercicio plugins

Crear un plugin que al final de cada entrada nos diga el número de palabras que tiene.

Es decir, tendremos que modificar el contenido (the_content) añadiendo al final el número de palabras

Pasos a realizar:

1.- Crear los archivos de plugin

2.- Conseguir que al final de cada entrada ponga ‘hola’ y comprobar que funciona

3.- Hacer un código que cuente las palabras de un texto en php y añadir ese número al final.

<?php
/**
 * Plugin Name: Contar palabras
 * Description: Cuenta las palabras que tiene una entrada del blog y lo pone al final
 * Version: 1.1
 * Author: Jotapé
 */


// Esta función se encarga de contar las palabras y añadirlas
function contar_palabras($content){
    // usamos str_word_count para contar las palabras: se puede mejorar para no contar html o imágenes o etc...
    $num_palabras=str_word_count($content);
    // Calculo el tiempo de lectura
    $tiempo=round($num_palabras/200,1);
    // Creo el texto a añadir. Como son comillas dobles puedo poner la variable dentro
    $texto="Número de palabras: <b>$num_palabras</b>. Tiempo estimado de lectura: <b>$tiempo minutos</b>";

    // Devuelvo el contenido con el texto anterior. 
    return "<p>$texto</p>$content";
}

// Añado el filtro para modificar el contenido
add_filter("the_content","contar_palabras");

Ejemplo plugin registro entradas

<?php
/**
 * Plugin Name: Registro entradas
 * Plugin URI: https://trifulcas.com
 * Description: Un plugin que registra en un archivo cuando se publica una entrada
 * Version: 1.0
 * Author: Jotapé
 * Author URI: https://trifulcas.com
 * License: GPL2
 */

function registrar($id,$post){
    // Poner el código para escribir en el archivo
    $texto=$post->post_title." | ".$post->post_author.PHP_EOL;
    $archivo = plugin_dir_path( __FILE__ ) . 'registro.txt';
    file_put_contents( $archivo, $texto, FILE_APPEND | LOCK_EX );
}

add_action('publish_post','registrar',10,2);

Ejemplo plugin wp

<?php
/**
 * Plugin Name: Mi Plugin Personalizado
 * Plugin URI: https://tusitio.com
 * Description: Un plugin simple para demostrar cómo crear uno.
 * Version: 1.0
 * Author: Tu Nombre
 * Author URI: https://tusitio.com
 * License: GPL2
 */


function mensaje_final_personalizado($content) {
    
$aforismos = [
    "La vida es aquello que te sucede mientras estás ocupado haciendo otros planes. – John Lennon",
    "El conocimiento es poder. – Francis Bacon",
    "Pienso, luego existo. – René Descartes",
    "La imaginación es más importante que el conocimiento. – Albert Einstein",
    "El hombre está condenado a ser libre. – Jean-Paul Sartre",
    "Solo sé que no sé nada. – Sócrates",
    "No hay camino para la paz, la paz es el camino. – Mahatma Gandhi",
    "El secreto de la felicidad no es hacer siempre lo que se quiere, sino querer siempre lo que se hace. – León Tolstói",
    "La esperanza es el sueño del hombre despierto. – Aristóteles",
    "El que tiene un porqué para vivir puede soportar casi cualquier cómo. – Friedrich Nietzsche"
];
$aforismo=$aforismos[mt_rand(0,9)];

    if (is_single()) {
        $content .= '<p style="color: green;">'.$aforismo.'</p>';
    }
    return $content;
}
add_filter('the_content', 'mensaje_final_personalizado');