A lo largo del tiempo, vas aprendiendo que, aunque pienses que has pagado por una plantilla y por lo tanto esta debe funcionar correctamente, no es así. Suele ocurrir que una vez has instalado la plantilla, plugins necesarios y cargado el contenido demo que es realmente la plantilla, es decir, la preconfiguración de las páginas bajo Elementor o Backery, estas o no funcionan correctamente, incluso hay referencias hacia un tercer dominio en vez de hacer referencia a los recursos locales. Cuando tratas de averiguar por qué no funciona adecuadamente, es cuando te sumerges en el código de la plantilla y es cuando te llevas las manos a la cabeza y te preguntas ¿quién ha programado esto?
Por poner un ejemplo (no diré el nombre exacto de la plantilla), uno de los módulos no mostraba uno de los iconos en uno de los módulos que se componía de 5 recuadros. Tras analizar el código, me encontré con esta función (el shortcode) que es donde estaba el “bug” (la función es un bug en sí misma).
function modeltheme_tabs_categories_shortcode($params, $content) {
extract( shortcode_atts(
array(
'tabs_item_title_tab1' => '',
'tabs_item_content1' => '',
'tabs_item_button_text1' => '',
'tabs_item_button_link1' => '',
'tabs_item_img1' => '',
'tabs_item_img2' => '',
'tabs_item_img3' => '',
'tabs_item_img4' => '',
'tabs_item_img5' => '',
'tabs_item_icon1' => '',
'tabs_item_icon2' => '',
'tabs_item_icon3' => '',
'tabs_item_icon4' => '',
'tabs_item_icon5' => '',
'tabs_item_title_tab2' => '',
'tabs_item_content2' => '',
'tabs_item_button_text2' => '',
'tabs_item_button_link2' => '',
'tabs_item_title_tab3' => '',
'tabs_item_content3' => '',
'tabs_item_button_text3' => '',
'tabs_item_button_link3' => '',
'tabs_item_title_tab4' => '',
'tabs_item_content4' => '',
'tabs_item_button_text4' => '',
'tabs_item_button_link4' => '',
'tabs_item_title_tab5' => '',
'tabs_item_content5' => '',
'tabs_item_button_text5' => '',
'tabs_item_button_link5' => '',
), $params ) );
$vc_css_class = apply_filters( VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG, vc_shortcode_custom_css_class( $css, ' ' ), 'mt_tabs_categories', $params );
$tabs_item_img1 = wp_get_attachment_image_src($tabs_item_img1, "clinika_50s0x500");
$tabs_item_img2 = wp_get_attachment_image_src($tabs_item_img2, "clinika_500x50");
$tabs_item_img3 = wp_get_attachment_image_src($tabs_item_img3, "clinika_500x50");
$tabs_item_img4 = wp_get_attachment_image_src($tabs_item_img4, "clinika_500x50");
$tabs_item_img5 = wp_get_attachment_image_src($tabs_item_img5, "clinika_500x50");
if( floatval($tabs_item_icon1)>0 ){
$tabs_item_icon1 = wp_get_attachment_image_src($tabs_item_icon1, "clinika_500x500");
}
if( floatval($tabs_item_icon2)>0 ){
$tabs_item_icon2 = wp_get_attachment_image_src($tabs_item_icon2, "clinika_500x500");
}
if( floatval($tabs_item_icon3)>0 ){
$tabs_item_icon3 = wp_get_attachment_image_src($tabs_item_icon3, "clinika_500x500");
}
if( floatval($tabs_item_icon4)>0 ){
$tabs_item_icon4 = wp_get_attachment_image_src($tabs_item_icon4, "clinika_500x500");
}
if( floatval($tabs_item_icon5)>0 ){
$tabs_item_icon5 = wp_get_attachment_image_src($tabs_item_icon5, "clinika_500x500");
}
if (!empty($tabs_item_img1) || !empty($tabs_item_icon1) || !empty($tabs_item_title_tab1)) {
$content .= '<li><a href="#section-iconbox-1" class="list-icon-title">
<img class="tabs_icon" src="'.esc_attr($tabs_item_icon1[0]).'" alt="tabs-image">
<h5 class="tab-title">'.$tabs_item_title_tab1.'</h5>
</a></li>';
if (!empty($tabs_item_img2) || !empty($tabs_item_icon2) || !empty($tabs_item_title_tab2)) {
$content .= '<li><a href="#section-iconbox-2" class="list-icon-title">
<img class="tabs_icon" src="'.esc_attr($tabs_item_icon2[0]).'" alt="tabs-image">
<h5 class="tab-title">'.$tabs_item_title_tab2.'</h5>
</a></li>';
}
if (!empty($tabs_item_img3) || !empty($tabs_item_icon3) || !empty($tabs_item_title_tab3)) {
$content .= '<li><a href="#section-iconbox-3" class="list-icon-title">
<img class="tabs_icon" src="'.esc_attr($tabs_item_icon3[0]).'" alt="tabs-image">
<h5 class="tab-title">'.$tabs_item_title_tab3.'</h5>
</a></li>';
}
if (!empty($tabs_item_img4) || !empty($tabs_item_icon4) || !empty($tabs_item_title_tab4)) {
$content .= '<li><a href="#section-iconbox-4" class="list-icon-title">
<img class="tabs_icon" src="'.esc_attr($tabs_item_icon4[0]).'" alt="tabs-image">
<h5 class="tab-title">'.$tabs_item_title_tab4.'</h5>
</a></li>';
}
if (!empty($tabs_item_img5) || !empty($tabs_item_icon5) || !empty($tabs_item_title_tab5)) {
$content .= '<li><a href="#section-iconbox-5" class="list-icon-title">
<img class="tabs_icon" src="'.esc_attr($tabs_item_icon5[0]).'" alt="tabs-image">
<h5 class="tab-title">'.$tabs_item_title_tab5.'</h5>
</a></li>';
}
$content .= '</ul>
</nav>
<div class="content-wrap">';
$content .= <section id="section-iconbox-1">
<div class="row">
<div class="col-md-6 text-center">
<img class="tabs_image" src="'.esc_attr($tabs_item_img1[0]).'" alt="tabs-image">
</div>
<div class="col-md-6">
<h3 class="tabs_title">'.$tabs_item_title_tab1.'</h3>
<p class="tabs_content">'.$tabs_item_content1.'</p>
<a href="'.$tabs_item_button_link1.'" class="rippler rippler-default button-winona btn btn-lg tabs_button">'.$tabs_item_button_text1.'</a>
</div>
</div>
</section>
<section id="section-iconbox-2">
<div class="row">
<div class="col-md-6 text-center">
<img class="tabs_image" src="'.esc_attr($tabs_item_img2[0]).'" alt="tabs-image">
</div>
<div class="col-md-6">
<h3 class="tabs_title">'.$tabs_item_title_tab2.'</h3>
<p class="tabs_content">'.$tabs_item_content2.'</p>
<a href="'.$tabs_item_button_link2.'" class="rippler rippler-default button-winona btn btn-lg tabs_button">'.$tabs_item_button_text2.'</a>
</div>
</div>
</section>
<section id="section-iconbox-3">
<div class="row">
<div class="col-md-6 text-center">
<img class="tabs_image" src="'.esc_attr($tabs_item_img3[0]).'" alt="tabs-image">
</div>
<div class="col-md-6">
<h3 class="tabs_title">'.$tabs_item_title_tab3.'</h3>
<p class="tabs_content">'.$tabs_item_content3.'</p>
<a href="'.$tabs_item_button_link3.'" class="rippler rippler-default button-winona btn btn-lg tabs_button">'.$tabs_item_button_text3.'</a>
</div>
</div>
</section>
<section id="section-iconbox-4">
<div class="row">
<div class="col-md-6 text-center">
<img class="tabs_image" src="'.esc_attr($tabs_item_img4[0]).'" alt="tabs-image">
</div>
<div class="col-md-6">
<h3 class="tabs_title">'.$tabs_item_title_tab4.'</h3>
<p class="tabs_content">'.$tabs_item_content4.'</p>
<a href="'.$tabs_item_button_link4.'" class="rippler rippler-default button-winona btn btn-lg tabs_button">'.$tabs_item_button_text4.'</a>
</div>
</div>
</section>
<section id="section-iconbox-5">
<div class="row">
<div class="col-md-6 text-center">
<img class="tabs_image" src="'.esc_attr($tabs_item_img5[0]).'" alt="tabs-image">
</div>
<div class="col-md-6">
<h3 class="tabs_title">'.$tabs_item_title_tab5.'</h3>
<p class="tabs_content">'.$tabs_item_content5.'</p>
<a href="'.$tabs_item_button_link5.'" class="rippler rippler-default button-winona btn btn-lg tabs_button">'.$tabs_item_button_text5.'</a>
</div>
</div>
</section>
*/
$content .= '</div><!-- /content -->
</div><!-- /tabs -->
</section>';
return $content;
}
Primero fue averiguar por qué no mostraba el icono. Era tan simple como que uno de los parámetros lo estaba tratando como una matriz, cuando realmente era una cadena con IDs separadas por comas. Una vez solventado eso, vino el comprobar que el “programador” había repetido 5 veces en dos bloques el código para dibujar cada uno de los 5 bloques. Es aquí donde uno ya se queda perplejo, ya que eso, hasta el programador más malo lo resuelve con un bucle. Así, esa chapuza de código, de manera eficiente quedaría como sigue:
function modeltheme_tabs_categories_shortcode($params, $content) {
extract( shortcode_atts(
array(
'tabs_item_title_tab1' => '',
'tabs_item_content1' => '',
'tabs_item_button_text1' => '',
'tabs_item_button_link1' => '',
'tabs_item_img1' => '',
'tabs_item_img2' => '',
'tabs_item_img3' => '',
'tabs_item_img4' => '',
'tabs_item_img5' => '',
'tabs_item_icon1' => '',
'tabs_item_icon2' => '',
'tabs_item_icon3' => '',
'tabs_item_icon4' => '',
'tabs_item_icon5' => '',
'tabs_item_title_tab2' => '',
'tabs_item_content2' => '',
'tabs_item_button_text2' => '',
'tabs_item_button_link2' => '',
'tabs_item_title_tab3' => '',
'tabs_item_content3' => '',
'tabs_item_button_text3' => '',
'tabs_item_button_link3' => '',
'tabs_item_title_tab4' => '',
'tabs_item_content4' => '',
'tabs_item_button_text4' => '',
'tabs_item_button_link4' => '',
'tabs_item_title_tab5' => '',
'tabs_item_content5' => '',
'tabs_item_button_text5' => '',
'tabs_item_button_link5' => '',
), $params ) );
# Bug extraer parámtros del shortcode
for($c=1;$c<=5;$c++)
{
// Imágenes
$x='tabs_item_img'.$c;
$x1='tabs_item_img'.$c;
$$x=wp_get_attachment_image_src($$x1, ($c==1?'clinika_50s0x500':'clinika_500x50'));
$vnom='tabs_item_icon'.$c;
if (!is_array($$vnom)&&trim($$vnom)!='')
{
$t=explode(',',$$vnom);
$$vnom=$t[0];
#echo $$vnom;
}
if( floatval($$vnom)>0 )
{
$$vnom = wp_get_attachment_image_src($$vnom, "clinika_500x500");
}
}
$content = '';
$content .= '<section class="mt-tabs">
<div class="tabs tabs-style-iconbox">
<nav>
<ul>';
for($c=1;$c<=5;$c++)
{
$vnom='tabs_item_title_tab'.$c;
$t='tabs_item_icon'.$c;
if (trim($$vnom)!=''&&isset($$t[0]))
{
$content .= '<li><a href="#section-iconbox-"'.$c.' class="list-icon-title">
<img class="tabs_icon" src="'.esc_attr($$t[0]).'" alt="tabs-image">
<h5 class="tab-title">'.$$vnom.'</h5>
</a></li>';
}
}
$content .= '</ul>
</nav>
<div class="content-wrap">';
for($c=1;$c<=5;$c++)
{
$vnom='tabs_item_title_tab'.$c;
$t='tabs_item_img'.$c;
$t1='tabs_item_content'.$c;
$t2='tabs_item_button_link'.$c;
$t3='tabs_item_button_text'.$c;
if (trim($$vnom)!=''&&isset($$t[0]))
{
$content .= '<section id="section-iconbox-1">
<div class="row">
<div class="col-md-6 text-center">
<img class="tabs_image" src="'.esc_attr($$t[0]).'" alt="tabs-image">
</div>
<div class="col-md-6">
<h3 class="tabs_title">'.$$vnom.'</h3>
<p class="tabs_content">'.$$t1.'</p>';
if (trim($$t3)!='')
{
$content .= '<a href="'.$$t2.'" class="rippler rippler-default button-winona btn btn-lg tabs_button">'.$$t3.'</a>';
}
$content .= '</div>
</div>
</section>';
}
}
$content .= '</div><!-- /content -->
</div><!-- /tabs -->
</section>';
return $content;
}
Como vemos, quien programó esto, simplemente no sabe programar y lo peor, están vendiendo una plantilla, no barata, cuya calidad no refleja el precio. De aquí además se infiere que uno empieza a poner en duda la seguridad.
Conclusión: WordPress ha surgido como una solución rápida para personas y empresas que no saben programar y piensan que simplemente con instalarlo ya tienen su sitio web. ¿Qué ocurre luego? Vienen las lamentaciones cuando les hackean el sitio, y además, estos sitios sirven como fuente de infección a los usuarios que los visitan. No solo eso, sino que si es un comercio electrónico online, pueden acabar con pérdidas económicas, pérdida de datos personales de los clientes… Por experiencia, cuando esto pasa y es una empresa/agencia grande quien ha implementado el sitio, no suele tener mayores consecuencias porque su renombre, digamos que avala y tapa su error. No así pasa cuando son pequeñas empresas o incluso un autónomo. Hemos de recordar que muchas veces estas grandes agencias incluyen en sus filas técnicos cuya preparación y/o experiencia es baja o nula (su coste salarial es menor), ya que estas grandes empresas cobran por proyecto ejecutado y rara vez pasan controles de calidad o fases de testing, ya que lo importante es cobrar lo antes posible. Para ello, hay que acortar tiempos y estos tiempos se acortan a costa de la fase adecuada de testing y calidad.