trailingslashit( $uploads['basedir'] ) . 'ga-share', 'file' => trailingslashit( $uploads['basedir'] ) . "ga-share/$name", 'url' => trailingslashit( $uploads['baseurl'] ) . "ga-share/$name", 'glob' => trailingslashit( $uploads['basedir'] ) . "ga-share/animal-$post_id-*.jpg", ); } /** Devuelve la URL de la imagen para redes, generándola si hace falta. */ function ga_share_image_url( $post_id ) { $p = ga_share_image_paths( $post_id ); if ( ! file_exists( $p['file'] ) && ! ga_generate_share_image( $post_id ) ) { return ''; } return $p['url']; } function ga_hex_color( $img, $hex ) { $hex = ltrim( $hex, '#' ); return imagecolorallocate( $img, hexdec( substr( $hex, 0, 2 ) ), hexdec( substr( $hex, 2, 2 ) ), hexdec( substr( $hex, 4, 2 ) ) ); } /** Carga una imagen de la biblioteca (JPEG, PNG o WebP) como recurso GD. */ function ga_gd_load( $path ) { $type = wp_check_filetype( $path )['type'] ?? ''; return match ( $type ) { 'image/jpeg' => @imagecreatefromjpeg( $path ), 'image/png' => @imagecreatefrompng( $path ), 'image/webp' => function_exists( 'imagecreatefromwebp' ) ? @imagecreatefromwebp( $path ) : false, default => false, }; } /** Parte un texto en líneas que quepan en $width con la fuente y tamaño dados. */ function ga_gd_wrap( $text, $font, $size, $width ) { $lines = array( '' ); foreach ( preg_split( '/\s+/u', $text ) as $word ) { $try = trim( end( $lines ) . ' ' . $word ); $box = imagettfbbox( $size, 0, $font, $try ); if ( $box[2] - $box[0] > $width && '' !== end( $lines ) ) { $lines[] = $word; } else { $lines[ count( $lines ) - 1 ] = $try; } } return $lines; } function ga_generate_share_image( $post_id ) { if ( ! function_exists( 'imagettftext' ) ) { return false; } $p = ga_share_image_paths( $post_id ); wp_mkdir_p( $p['dir'] ); foreach ( glob( $p['glob'] ) ?: array() as $old ) { @unlink( $old ); // Versiones anteriores de este animal. } $w = 1200; $h = 630; $split = 630; // Ancho de la foto (cuadrada, a la izquierda). $img = imagecreatetruecolor( $w, $h ); $primary = function_exists( 'ga_color' ) ? ga_color( 'primary' ) : '#401f0c'; $accent = function_exists( 'ga_color' ) ? ga_color( 'accent' ) : '#bd8537'; $surface = function_exists( 'ga_color' ) ? ga_color( 'surface' ) : '#f3ecdc'; $bg = ga_hex_color( $img, $primary ); imagefilledrectangle( $img, 0, 0, $w, $h, $bg ); // Foto (recorte cuadrado centrado) o, si no hay, el símbolo del logo sobre fondo claro. $photo = get_post_thumbnail_id( $post_id ) ? get_attached_file( get_post_thumbnail_id( $post_id ) ) : ''; $src = $photo ? ga_gd_load( $photo ) : false; if ( $src ) { $sw = imagesx( $src ); $sh = imagesy( $src ); $side = min( $sw, $sh ); imagecopyresampled( $img, $src, 0, 0, (int) ( ( $sw - $side ) / 2 ), (int) ( ( $sh - $side ) / 3 ), $split, $h, $side, $side ); imagedestroy( $src ); } else { imagefilledrectangle( $img, 0, 0, $split, $h, ga_hex_color( $img, $surface ) ); $mark = @imagecreatefrompng( __DIR__ . '/assets/logo-mark.png' ); if ( $mark ) { $mw = 380; $mh = (int) ( imagesy( $mark ) * $mw / imagesx( $mark ) ); imagecopyresampled( $img, $mark, (int) ( ( $split - $mw ) / 2 ), (int) ( ( $h - $mh ) / 2 ), 0, 0, $mw, $mh, imagesx( $mark ), imagesy( $mark ) ); imagedestroy( $mark ); } } // Texto a la derecha. $serif = __DIR__ . '/assets/fraunces-800.ttf'; $sans = __DIR__ . '/assets/karla-600.ttf'; $white = imagecolorallocate( $img, 255, 255, 255 ); $gold = ga_hex_color( $img, $accent ); $soft = ga_hex_color( $img, $surface ); $x = $split + 56; $max = $w - $x - 50; $lang = function_exists( 'pll_get_post_language' ) ? pll_get_post_language( $post_id ) : 'es'; $eu = 'eu' === $lang; imagettftext( $img, 17, 0, $x, 92, $gold, $sans, $eu ? 'BILAGUN · ADOPZIOA' : 'BILAGUN · ADOPCIÓN' ); $name = get_the_title( $post_id ); $size = 64; do { $lines = ga_gd_wrap( $name, $serif, $size, $max ); $size -= 4; } while ( ( count( $lines ) > 2 ) && $size > 30 ); $size += 4; $y = 190; foreach ( array_slice( $lines, 0, 3 ) as $line ) { imagettftext( $img, $size, 0, $x, $y, $white, $serif, $line ); $y += (int) ( $size * 1.25 ); } $status = ga_status( $post_id ); $tag = 'proceso' === $status ? ( $eu ? 'Prozesuan' : 'En proceso de adopción' ) : ( $eu ? 'Familia bila' : 'Busca familia' ); imagettftext( $img, 28, 0, $x, $y + 20, $soft, $sans, $tag ); $host = wp_parse_url( home_url(), PHP_URL_HOST ); imagettftext( $img, 18, 0, $x, $h - 60, $gold, $sans, $host ); $mark = @imagecreatefrompng( __DIR__ . '/assets/logo-mark.png' ); if ( $mark ) { $mw = 96; $mh = (int) ( imagesy( $mark ) * $mw / imagesx( $mark ) ); imagecopyresampled( $img, $mark, $w - $mw - 44, $h - $mh - 44, 0, 0, $mw, $mh, imagesx( $mark ), imagesy( $mark ) ); imagedestroy( $mark ); } $ok = imagejpeg( $img, $p['file'], 86 ); imagedestroy( $img ); return $ok; } /* Se regenera al guardar (si cambió la foto o el nombre, cambia el nombre de archivo). */ add_action( 'save_post_animal', function ( $post_id ) { if ( ! wp_is_post_revision( $post_id ) && 'publish' === get_post_status( $post_id ) ) { ga_share_image_url( $post_id ); } }, 30 ); /* Etiquetas Open Graph / Twitter con la imagen generada */ add_action( 'wpseo_add_opengraph_images', function ( $container ) { if ( is_singular( 'animal' ) && ( $url = ga_share_image_url( get_queried_object_id() ) ) ) { $container->add_image( array( 'url' => $url, 'width' => 1200, 'height' => 630, 'type' => 'image/jpeg' ) ); } } ); add_filter( 'wpseo_opengraph_image', fn( $url ) => is_singular( 'animal' ) ? ( ga_share_image_url( get_queried_object_id() ) ?: $url ) : $url ); add_filter( 'wpseo_twitter_image', fn( $url ) => is_singular( 'animal' ) ? ( ga_share_image_url( get_queried_object_id() ) ?: $url ) : $url ); add_filter( 'wpseo_opengraph_image_width', fn( $v ) => is_singular( 'animal' ) ? 1200 : $v ); add_filter( 'wpseo_opengraph_image_height', fn( $v ) => is_singular( 'animal' ) ? 630 : $v ); add_filter( 'wpseo_twitter_card_type', fn( $v ) => is_singular( 'animal' ) ? 'summary_large_image' : $v ); /* Sin Yoast: etiquetas mínimas propias */ add_action( 'wp_head', function () { if ( defined( 'WPSEO_VERSION' ) || ! is_singular( 'animal' ) ) { return; } $id = get_queried_object_id(); printf( '' . "\n", esc_attr( get_the_title( $id ) ) ); printf( '' . "\n", esc_url( get_permalink( $id ) ) ); printf( '' . "\n", esc_url( ga_share_image_url( $id ) ) ); echo '' . "\n"; }, 5 ); /* En la ficha del panel: vista previa y descarga (para publicarla en Instagram, etc.) */ add_action( 'add_meta_boxes_animal', function ( $post ) { add_meta_box( 'ga_share', 'Compartir', function ( $post ) { if ( 'publish' !== $post->post_status ) { echo '
Disponible cuando el animal esté publicado.
'; return; } $url = ga_share_image_url( $post->ID ); if ( $url ) { printf( 'La imagen se crea sola con la foto principal y el nombre, y es la que aparece al compartir el enlace en WhatsApp o redes.
', esc_url( ga_poster_url( array( $post->ID ) ) ) ); }, 'animal', 'side', 'default' ); } ); /* ------------------------------------------------------------------------- * Carteles con QR (para las jaulas, jornadas de adopción, etc.) * ---------------------------------------------------------------------- */ function ga_poster_url( array $ids ) { return wp_nonce_url( admin_url( 'admin-post.php?action=ga_poster&ids=' . implode( ',', array_map( 'absint', $ids ) ) ), 'ga_poster' ); } add_filter( 'post_row_actions', function ( $actions, $post ) { if ( 'animal' === $post->post_type && 'publish' === $post->post_status ) { $actions['ga_poster'] = sprintf( 'Cartel QR', esc_url( ga_poster_url( array( $post->ID ) ) ) ); } return $actions; }, 10, 2 ); add_filter( 'bulk_actions-edit-animal', function ( $actions ) { $actions['ga_posters'] = 'Imprimir carteles con QR'; return $actions; } ); add_filter( 'handle_bulk_actions-edit-animal', function ( $redirect, $action, $ids ) { return 'ga_posters' === $action ? ga_poster_url( $ids ) : $redirect; }, 10, 3 ); add_action( 'admin_post_ga_poster', function () { check_admin_referer( 'ga_poster' ); if ( ! current_user_can( 'edit_posts' ) ) { wp_die( 'Sin permiso.' ); } $ids = array_filter( array_map( 'absint', explode( ',', (string) ( $_GET['ids'] ?? '' ) ) ) ); $ids = array_filter( $ids, fn( $id ) => 'animal' === get_post_type( $id ) && 'publish' === get_post_status( $id ) ); if ( ! $ids ) { wp_die( 'No hay animales publicados seleccionados.' ); } $primary = function_exists( 'ga_color' ) ? ga_color( 'primary' ) : '#401f0c'; $accent = function_exists( 'ga_color' ) ? ga_color( 'accent' ) : '#bd8537'; $logo = function_exists( 'ga_logo_svg' ) ? ga_logo_svg( 'full' ) : ''; $fonts = content_url( 'themes/gure-ametsa/assets/fonts/' ); ?>