El shortcode se muestra en la parte superior del the_content
El shortcode producido por esta función - una lista de todos los sitios en una red multisitio - se muestra arriba del contenido en el loop, sin importar dónde se coloque en el editor.
He revisado otras preguntas y respuestas relacionadas en WPSE y entiendo que tiene que ver con que la función usa echo en lugar de return, pero no es tan simple como reemplazar las instancias de echo con return en la función de abajo. O añadir echo=0 con una función de WP como wp_list_pages()
¿Alguna idea? ¿Dónde está la función que necesita devolver un valor en lugar de hacer echo?
// Mostrar un elemento individual del menú
function projects_menu_entry($id, $title, $link_self)
{
global $blog_id;
if ($link_self || $id != $blog_id) {
echo '<li>';
if ($id == $blog_id) {
echo '<strong>';
}
$url = get_home_url($id);
if (substr($url, -1) != '/') {
// Nota: Añadí un "/" al final de la URL porque WordPress
// no lo hacía automáticamente en la versión 3.0.4
$url .= '/';
}
echo '<a href="' . $url . '">' . $title . '</a>';
if ($id == $blog_id) {
echo '</strong>';
}
echo '</li>';
}
}
// Mostrar el menú completo
// Si $link_self es false, omite el sitio actual - usado para mostrar el menú en la página principal
function projects_menu($link_self = true)
{
global $wpdb;
echo '<ul>';
projects_menu_entry(1, 'Home', $link_self);
$blogs = $wpdb->get_results("
SELECT blog_id
FROM {$wpdb->blogs}
WHERE site_id = '{$wpdb->siteid}'
AND spam = '0'
AND deleted = '0'
AND archived = '0'
AND blog_id != 1
");
$sites = array();
foreach ($blogs as $blog) {
$sites[$blog->blog_id] = get_blog_option($blog->blog_id, 'blogname');
}
natsort($sites);
foreach ($sites as $blog_id => $blog_title) {
projects_menu_entry($blog_id, $blog_title, $link_self);
}
echo '</ul>';
}
// Añade un shortcode [bloglist]
function bloglist_shortcode($atts)
{
projects_menu(false);
}
add_shortcode('bloglist', 'bloglist_shortcode');
Todas las funciones deben retornar una cadena, no deberías usar echo en ningún lugar. Reescribe las funciones, usa una variable interna para manejar las cadenas y retorna esa:
// Mostrar un solo elemento del menú
function projects_menu_entry($id, $title, $link_self)
{
global $blog_id;
$out = '';
if ($link_self || $id != $blog_id) {
$out .= '<li>';
if ($id == $blog_id) {
$out .= '<strong>';
}
$url = get_home_url( $id, '/' );
$out .= '<a href="' . $url . '">' . $title . '</a>';
if ($id == $blog_id) {
$out .= '</strong>';
}
$out .= '</li>';
}
return $out;
}
// Mostrar el menú completo
// Si $link_self es falso, omite el sitio actual - usado para mostrar el menú en la página de inicio
function projects_menu($link_self = true)
{
global $wpdb;
$out = '<ul>';
$out .= projects_menu_entry(1, 'Inicio', $link_self);
$blogs = $wpdb->get_results("
SELECT blog_id
FROM {$wpdb->blogs}
WHERE site_id = '{$wpdb->siteid}'
AND spam = '0'
AND deleted = '0'
AND archived = '0'
AND blog_id != 1
");
$sites = array();
foreach ($blogs as $blog) {
$sites[$blog->blog_id] = get_blog_option($blog->blog_id, 'blogname');
}
natsort($sites);
foreach ($sites as $blog_id => $blog_title) {
$out .= projects_menu_entry($blog_id, $blog_title, $link_self);
}
$out .= '</ul>';
return $out;
}
// Añade un shortcode [listadeblogs]
function bloglist_shortcode($atts)
{
return projects_menu(false);
}
add_shortcode('listadeblogs', 'bloglist_shortcode');
Para un ejemplo similar ampliado ver: Cómo retornar contenidos del loop.
No puedes reemplazar las instancias de echo porque solo puedes retornar una vez. Necesitas construir una cadena y retornarla.
function projects_menu_entry($id, $title, $link_self)
{
global $blog_id;
$ret = '';
if ($link_self || $id != $blog_id) {
$ret .= '<li>';
if ($id == $blog_id) {
$ret .= '<strong>';
}
// y así sucesivamente
$ret .= '</ul>';
return $ret;
}
Haz eso para ambas funciones y esperaría que esto funcione. Mis disculpas si he leído algo incorrectamente.
¿Alguna idea? ¿Dónde está la función que necesita devolverse en lugar de hacer echo?
Voy a ofrecer una solución alternativa que no requiere que reemplaces instancias de echo o construyas una cadena de retorno.
Puedes activar el almacenamiento en búfer de salida y devolver el búfer como una cadena.
Añade ob_start() al principio de la función antes de cualquier llamada a echo.
Al final de la función añade:
$response = ob_get_contents();
ob_end_clean();
return $response;