<?php
/**
* Plugin Name: Agulló · Tienda en preparación
* Description: WooCommerce sin precios ni compra, con área privada integrada en Agulló.
* Version: 0.1.6
* Requires PHP: 8.0
* Author: Electricidad Agulló
*/
if(!defined('ABSPATH'))exit;
function ags_message(){return 'Estamos preparando la compra online. Mientras tanto, puedes consultar productos y solicitar información a Agulló.';}
// El bloqueo es deliberadamente incondicional: cargar tarifas no abre la venta.
add_filter('woocommerce_is_purchasable','__return_false',PHP_INT_MAX);
add_filter('woocommerce_variation_is_purchasable','__return_false',PHP_INT_MAX);
add_filter('woocommerce_get_price_html','__return_empty_string',PHP_INT_MAX);
add_filter('woocommerce_available_payment_gateways','__return_empty_array',PHP_INT_MAX);
add_filter('woocommerce_add_to_cart_validation',function(){if(function_exists('wc_add_notice'))wc_add_notice(ags_message(),'error');return false;},PHP_INT_MAX);
add_action('woocommerce_after_checkout_validation',function($data,$errors){$errors->add('agullo_sales_closed',ags_message());},PHP_INT_MAX,2);
add_action('woocommerce_checkout_create_order',function(){throw new Exception(ags_message());},PHP_INT_MAX);
add_filter('rest_pre_dispatch',function($result,$server,$request){if(preg_match('#^/wc/store(?:/v[0-9]+)?/(?:checkout|cart/(?:add-item|update-item))(?:/|$)#',$request->get_route()))return new WP_Error('agullo_sales_closed',ags_message(),array('status'=>403));return $result;},PHP_INT_MAX,3);
add_filter('woocommerce_structured_data_product',function($data){unset($data['offers']);return $data;},PHP_INT_MAX);
add_action('after_setup_theme',function(){add_theme_support('woocommerce');},20);
add_action('init',function(){foreach(array('favoritos','facturas','ayuda')as $endpoint)add_rewrite_endpoint($endpoint,EP_ROOT|EP_PAGES);});
add_filter('woocommerce_account_menu_items',function($items){return array('dashboard'=>'Resumen','orders'=>'Mis pedidos','edit-address'=>'Direcciones','facturas'=>'Facturas','favoritos'=>'Favoritos','edit-account'=>'Datos personales','ayuda'=>'Ayuda','customer-logout'=>'Cerrar sesión');});
function ags_favorites($uid=0){return array_values((array)get_user_meta($uid?:get_current_user_id(),'ags_favorites',true));}
add_action('wp_ajax_ags_favorites',function(){check_ajax_referer('ags_favorites','nonce');if(!is_user_logged_in())wp_send_json_error(null,403);if(isset($_POST['ids'])){$input=json_decode(wp_unslash($_POST['ids']),true);if(!is_array($input)||count($input)>100)wp_send_json_error(null,400);$ids=array_values(array_unique(array_filter(array_map('sanitize_key',$input))));$valid=array();if($ids){$posts=get_posts(array('post_type'=>'agullo_luminaire','post_status'=>'publish','posts_per_page'=>100,'meta_key'=>'_agullo_seed_id','meta_value'=>$ids,'meta_compare'=>'IN'));foreach($posts as $post)$valid[]=get_post_meta($post->ID,'_agullo_seed_id',true);}update_user_meta(get_current_user_id(),'ags_favorites',$valid);}wp_send_json_success(array('ids'=>ags_favorites()));});
add_action('wp_enqueue_scripts',function(){if(!class_exists('WooCommerce'))return;if(is_account_page()||is_cart()||is_checkout()){wp_enqueue_style('ags-account',plugins_url('assets/account.css',__FILE__),array(),'0.1.0');}if(is_user_logged_in()){wp_add_inline_script('agullo-ui','try{const k="agullo-product-favorites",owner="agullo-favorites-owner",uid="'.get_current_user_id().'",pk="ags-favorites-pending-"+uid;const l=JSON.parse(localStorage.getItem(k)||"[]"),r='.wp_json_encode(ags_favorites()).',p=localStorage.getItem(pk),o=localStorage.getItem(owner);let ids=p?JSON.parse(p):(!o?Array.from(new Set([...r,...(Array.isArray(l)?l:[])])):r);ids=Array.isArray(ids)?ids.slice(0,100):r;localStorage.setItem(k,JSON.stringify(ids));localStorage.setItem(owner,uid);if(JSON.stringify(ids)!==JSON.stringify(r))localStorage.setItem(pk,JSON.stringify(ids));}catch(e){}','before');wp_enqueue_script('ags-favorites',plugins_url('assets/favorites.js',__FILE__),array('agullo-ui'),'0.1.3',true);wp_localize_script('ags-favorites','agsFavorites',array('ajax'=>admin_url('admin-ajax.php'),'nonce'=>wp_create_nonce('ags_favorites'),'ids'=>ags_favorites(),'uid'=>get_current_user_id()));}},30);
add_filter('template_include',function($template){if(function_exists('is_account_page')&&(is_account_page()||is_cart()||is_checkout()))return __DIR__.'/templates/account.php';return $template;},100);
add_filter('woocommerce_locate_template',function($file,$name){return $name==='myaccount/dashboard.php'?__DIR__.'/templates/dashboard.php':$file;},30,2);
add_action('woocommerce_account_facturas_endpoint',function(){echo '<h2>Tus facturas</h2><div class="ags-card"><p>Todavía no tienes facturas disponibles.</p><p>Cuando se active la compra online, podrás consultar aquí los documentos emitidos de tus pedidos.</p></div>';});
add_action('woocommerce_account_favoritos_endpoint',function(){echo '<h2>Una selección muy tuya.</h2><p>Las piezas que has guardado para tu próximo proyecto.</p>'; $ids=ags_favorites();if(!$ids){echo '<div class="ags-card"><p>Aún no has guardado piezas en tu cuenta.</p><a class="button" href="'.esc_url(home_url('/iluminacion/')).'">Explorar el catálogo</a></div>';return;}echo '<div class="ags-favorites-grid">';foreach($ids as $id){if(!function_exists('agullo_catalog_product_by_id'))continue;$p=agullo_catalog_product_by_id($id);if($p&&function_exists('agullo_card'))agullo_card($p);}echo '</div>';});
add_action('woocommerce_account_ayuda_endpoint',function(){echo '<h2>Te acompañamos.</h2><div class="ags-card"><p>Si necesitas ayuda con una pieza, una dirección o tu proyecto de iluminación, habla con nuestro equipo.</p><a class="button" href="'.esc_url(home_url('/contacto/')).'">Contactar con Agulló</a></div>';});
add_filter('woocommerce_billing_fields',function($fields){$fields['billing_company']=array('label'=>'Empresa / razón social','type'=>'text','required'=>false,'class'=>array('form-row-wide'),'priority'=>30);$fields['billing_nif']=array('label'=>'NIF / CIF para facturación','required'=>false,'class'=>array('form-row-wide'),'priority'=>35);return $fields;});
add_action('woocommerce_customer_save_address',function($uid,$type){if($type==='billing'&&isset($_POST['billing_nif']))update_user_meta($uid,'billing_nif',sanitize_text_field(wp_unslash($_POST['billing_nif'])));},10,2);
add_filter('woocommerce_get_breadcrumb',function($crumbs){return $crumbs;});
add_action('admin_menu',function(){add_management_page('Agulló · Preparar tienda','Preparar tienda Agulló','manage_options','agullo-tienda','ags_admin');});
function ags_admin(){if(!current_user_can('manage_options'))return;echo '<div class="wrap"><h1>Agulló · Tienda en preparación</h1><p><strong>Venta online bloqueada.</strong> No se muestran precios, no se pueden añadir productos a la cesta y se rechazan los intentos de compra clásicos y mediante Store API.</p><p>El catálogo de iluminación actual conserva sus fichas y URLs. No se importan precios, productos de muestra ni pedidos ficticios.</p>';if(!class_exists('WooCommerce')){echo '<p>Instala y activa WooCommerce antes de preparar las páginas.</p>';}else{echo '<p>WooCommerce '.esc_html(WC_VERSION).' activo.</p><form method="post" action="'.esc_url(admin_url('admin-post.php')).'"><input type="hidden" name="action" value="ags_setup">';wp_nonce_field('ags_setup');submit_button('Preparar páginas de cuenta, cesta y compra');echo '</form><p><a href="'.esc_url(wc_get_page_permalink('myaccount')).'">Abrir Mi cuenta</a></p>';}echo '<p>La venta no se abrirá automáticamente al incorporar tarifas. Será necesario retirar expresamente este bloqueo cuando estén listos precios, pagos, fiscalidad y envíos.</p></div>';}
add_action('admin_post_ags_setup',function(){if(!current_user_can('manage_options'))wp_die('Sin permisos',403);check_admin_referer('ags_setup');if(!class_exists('WooCommerce'))wp_die('WooCommerce no está activo.');foreach(array('myaccount'=>array('Mi cuenta','mi-cuenta','[woocommerce_my_account]'),'cart'=>array('Cesta','cesta','[woocommerce_cart]'),'checkout'=>array('Finalizar compra','finalizar-compra','[woocommerce_checkout]'))as $key=>$data){$current=absint(get_option('woocommerce_'.$key.'_page_id'));if($current&&get_post_status($current)==='publish')continue;$existing=get_page_by_path($data[1]);if($existing){if(!has_shortcode($existing->post_content,trim($data[2],'[]')))wp_die('Existe una página con la ruta '.$data[1].'. Revísala antes de continuar.');$id=$existing->ID;}else{$id=wp_insert_post(array('post_type'=>'page','post_title'=>$data[0],'post_name'=>$data[1],'post_content'=>$data[2],'post_status'=>'publish'),true);if(is_wp_error($id))wp_die(esc_html($id->get_error_message()));}update_option('woocommerce_'.$key.'_page_id',$id);update_post_meta($id,'_yoast_wpseo_meta-robots-noindex','1');}update_option('woocommerce_currency','EUR');update_option('woocommerce_currency_pos','right_space');update_option('woocommerce_price_decimal_sep',',');update_option('woocommerce_price_thousand_sep','.');update_option('woocommerce_enable_guest_checkout','no');update_option('woocommerce_enable_myaccount_registration','no');update_option('woocommerce_enable_checkout_login_reminder','yes');update_option('woocommerce_ship_to_destination','shipping');flush_rewrite_rules();wp_safe_redirect(admin_url('tools.php?page=agullo-tienda'));exit;});
register_activation_hook(__FILE__,function(){foreach(array('favoritos','facturas','ayuda')as $e)add_rewrite_endpoint($e,EP_ROOT|EP_PAGES);flush_rewrite_rules();});
register_deactivation_hook(__FILE__,'flush_rewrite_rules');
add_action('wp_enqueue_scripts',function(){if(!class_exists('WooCommerce'))return;wp_enqueue_script('ags-navigation',plugins_url('assets/navigation.js',__FILE__),array(),'0.1.1',true);wp_localize_script('ags-navigation','agsNavigation',array('account'=>wc_get_page_permalink('myaccount')));},35);
require_once __DIR__.'/emails.php';
require_once __DIR__.'/sitemaps.php';
require_once __DIR__.'/idiomas.php';
/* AGML_ADMIN_BRIDGE_20261113 */
/** Temporary, capability- and nonce-guarded translation import/export UI. */
if (!defined('ABSPATH')) exit;
add_action('admin_menu', function () {
add_management_page('Traducciones Agulló', 'Traducciones Agulló', 'manage_options', 'agullo-traducciones', 'agml_bridge_page');
});
function agml_bridge_page() {
if (!current_user_can('manage_options')) return;
echo '<div class="wrap"><h1>Traducciones Agulló</h1><p>Importa traducciones revisadas como borradores vinculados mediante WPML. Conserva imágenes, referencias y originales.</p>';
$report = get_transient('agml_import_' . get_current_user_id());
if ($report) echo '<div class="notice notice-success"><p>' . esc_html($report) . '</p></div>';
echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '"><input type="hidden" name="action" value="agml_import">';
wp_nonce_field('agml_import');
echo '<label for="agml-batch">Lote JSON de traducciones</label><textarea id="agml-batch" name="batch" rows="12" class="large-text code" required></textarea>';
submit_button('Importar borradores traducidos');
echo '</form><hr><h2>Consultar originales publicados</h2><form method="get"><input type="hidden" name="page" value="agullo-traducciones"><label>IDs de originales (máximo 20) <input name="source_ids" value="' . esc_attr(sanitize_text_field(wp_unslash($_GET['source_ids'] ?? ''))) . '"></label>';
submit_button('Consultar', 'secondary'); echo '</form>';
$ids = array_slice(array_filter(array_map('absint', explode(',', sanitize_text_field(wp_unslash($_GET['source_ids'] ?? '')))))), 0, 20);
$rows = array();
foreach ($ids as $id) {
$p = get_post($id);
if (!$p || $p->post_status !== 'publish' || !in_array($p->post_type, array('post','page','agullo_luminaire'), true)) continue;
$row = array('source_id'=>$id, 'type'=>$p->post_type, 'title'=>$p->post_title, 'slug'=>$p->post_name, 'content'=>$p->post_content, 'excerpt'=>$p->post_excerpt);
foreach (array('_agullo_record','_agullo_guide_record') as $key) {
$value = get_post_meta($id, $key, true);
if (is_array($value)) $row[$key] = array_intersect_key($value, array_flip(array('id','sku','brand','category','finish','material','size','light','bulb','ip','imageCaption','quick','credit','related_products','faq')));
}
$row['seo_title'] = get_post_meta($id, '_yoast_wpseo_title', true);
$row['seo_description'] = get_post_meta($id, '_yoast_wpseo_metadesc', true);
$rows[] = $row;
}
if ($ids) echo '<textarea readonly rows="18" class="large-text code" id="agml-export">' . esc_textarea(wp_json_encode($rows, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) . '</textarea>';
echo '</div>';
}
add_action('admin_post_agml_import', function () {
if (!current_user_can('manage_options')) wp_die('Sin permisos', '', array('response'=>403));
check_admin_referer('agml_import');
if (!defined('ICL_SITEPRESS_VERSION')) wp_die('WPML debe estar activo.');
$raw = wp_unslash($_POST['batch'] ?? '');
if (!is_string($raw) || strlen($raw) > 1500000) wp_die('Lote no válido.');
if (str_starts_with($raw, 'GZIP:')) {
$packed = base64_decode(substr($raw, 5), true);
$raw = $packed && function_exists('gzdecode') ? gzdecode($packed, 1500001) : false;
if (!is_string($raw) || strlen($raw) > 1500000) wp_die('Lote comprimido no válido.');
}
$rows = json_decode($raw, true);
if (!is_array($rows) || !$rows || count($rows) > 60) wp_die('El lote debe contener entre 1 y 60 traducciones.');
$seen = array();
foreach ($rows as $r) {
if (!is_array($r) || !in_array($r['language'] ?? '', array('en','fr','de'), true) || empty($r['source_id']) || empty($r['title']) || empty($r['slug']) || (!isset($r['segments']) && !isset($r['content']))) wp_die('Traducción incompleta.');
$p = get_post(absint($r['source_id']));
if (!$p || $p->post_status !== 'publish' || !in_array($p->post_type, array('post','page','agullo_luminaire'), true)) wp_die('Original no permitido.');
$key = $p->ID . ':' . $r['language'];
if (isset($seen[$key])) wp_die('Traducción duplicada en el lote.');
$seen[$key] = true;
$details = apply_filters('wpml_element_language_details', null, array('element_id'=>$p->ID, 'element_type'=>'post_' . $p->post_type));
if ($details && $details->language_code !== 'es') wp_die('El original no está en español.');
$existing = apply_filters('wpml_object_id', $p->ID, $p->post_type, false, $r['language']);
// Never replace translations created by WPML or earlier imports implicitly.
if ($existing && (int)$existing !== $p->ID) wp_die('Ya existe una traducción del original ' . $p->ID . ' en ' . esc_html($r['language']) . '. Revísala antes de sustituirla.');
if (isset($r['segments'])) {
if (!is_array($r['segments']) || count($r['segments']) > 300) wp_die('Segmentos no válidos.');
foreach ($r['segments'] as $s) if (!is_array($s) || !isset($s['source'],$s['translation']) || !is_string($s['source']) || $s['source'] === '' || !is_string($s['translation']) || strpos($p->post_content, $s['source']) === false) wp_die('El contenido original ha cambiado. Revisa sus segmentos.');
}
}
$created = array();
foreach ($rows as $r) {
$source = get_post(absint($r['source_id']));
$type = 'post_' . $source->post_type;
$details = apply_filters('wpml_element_language_details', null, array('element_id'=>$source->ID, 'element_type'=>$type));
if (!$details) {
do_action('wpml_set_element_language_details', array('element_id'=>$source->ID,'element_type'=>$type,'trid'=>false,'language_code'=>'es','source_language_code'=>null));
$details = apply_filters('wpml_element_language_details', null, array('element_id'=>$source->ID, 'element_type'=>$type));
}
if (!$details || !$details->trid) wp_die('No se ha podido vincular el original mediante WPML.');
$content = $source->post_content;
if (isset($r['segments'])) {
$replace = array(); foreach ($r['segments'] as $s) $replace[$s['source']] = $s['translation'];
$content = strtr($content, $replace);
} else $content = $r['content'];
$id = wp_insert_post(wp_slash(array('post_type'=>$source->post_type,'post_status'=>'draft','post_title'=>sanitize_text_field($r['title']),'post_name'=>sanitize_title($r['slug']),'post_content'=>wp_kses_post($content),'post_excerpt'=>sanitize_textarea_field($r['excerpt'] ?? ''),'menu_order'=>$source->menu_order)), true);
if (is_wp_error($id)) wp_die(esc_html($id->get_error_message()));
do_action('wpml_set_element_language_details', array('element_id'=>$id,'element_type'=>$type,'trid'=>$details->trid,'language_code'=>$r['language'],'source_language_code'=>'es'));
foreach (array('_thumbnail_id','_agullo_seed_id','_agullo_guide','_agullo_record','_agullo_guide_record','_yoast_wpseo_meta-robots-noindex') as $key) {
if (metadata_exists('post', $source->ID, $key)) update_post_meta($id, $key, get_post_meta($source->ID, $key, true));
}
foreach (array('_agullo_record'=>array('finish','material','size','light','bulb','ip','imageCaption'), '_agullo_guide_record'=>array('quick','credit')) as $key=>$allowed) {
$meta = get_post_meta($id, $key, true);
if (is_array($meta) && !empty($r[$key]) && is_array($r[$key])) {
foreach ($allowed as $field) if (isset($r[$key][$field]) && is_string($r[$key][$field])) $meta[$field] = sanitize_textarea_field($r[$key][$field]);
update_post_meta($id, $key, $meta);
}
}
foreach (array('seo_title'=>'_yoast_wpseo_title','seo_description'=>'_yoast_wpseo_metadesc') as $field=>$key) if (!empty($r[$field])) update_post_meta($id, $key, sanitize_text_field($r[$field]));
foreach (get_object_taxonomies($source->post_type) as $taxonomy) {
$terms = wp_get_object_terms($source->ID, $taxonomy, array('fields'=>'ids'));
if (is_wp_error($terms)) continue;
$mapped = array(); foreach ($terms as $term) $mapped[] = (int)apply_filters('wpml_object_id', $term, $taxonomy, true, $r['language']);
wp_set_object_terms($id, $mapped, $taxonomy);
}
update_post_meta($id, '_agml_manual_source', $source->ID);
$created[] = $source->ID . '→' . $id . ' (' . $r['language'] . ')';
}
set_transient('agml_import_' . get_current_user_id(), 'Borradores creados: ' . implode(', ', $created), HOUR_IN_SECONDS);
wp_safe_redirect(admin_url('tools.php?page=agullo-traducciones')); exit;
});
Iluminación de diseño y proyectos en Calpe | Agulló
Saltar al contenido
Explora Agulló
Volver al menú
NUESTRA MARCA DESTACADA
El universo Schuller.
Diseño con presencia, cristal y acabados que dan carácter a cada espacio.
Ver todo Schuller
Volver al menú
ENCUENTRA TU LUZ
Una luz para cada rincón.
Explora por tipo de lámpara y encuentra la pieza para tu espacio.
Ver toda la iluminación
Volver al menú
DISEÑO CON FIRMA
Diferentes miradas sobre la luz.
Colecciones para descubrir. Te ayudamos a elegir modelos y acabados.
Conocer todas las marcas
Volver al menú
MÁS ALLÁ DEL INTERIOR
La luz, en todas sus formas.
Iluminación exterior, soluciones técnicas, mecanismos y control para tu proyecto.
Conoce nuestros servicios
Buena luz. Espacios que se sienten.
Diseñamos contigo la luz de tu espacio.
CALPE · COSTA BLANCA
INSTALACIONES · MANTENIMIENTO · SERVICIOS
Electricidad para cada proyecto.
Instalamos, cuidamos y ponemos al día la electricidad de viviendas, negocios y comunidades.
La misma atención al detalle. También en lo que no se ve.
Conoce nuestros servicios
SCHULLER · MARCA DESTACADA
Diseño con presencia. Luz con carácter. Colgantes que visten el espacio, piezas de cristal y detalles que marcan la diferencia. Descubre Schuller y encuentra con nosotros la luz para tu casa.
Explorar Schuller LíA · SCHULLER
Schuller REF. 306094
Lía PAN DE ORO y detalles en baño dorado brillo · LED 37W · 2.800 lumen / 2.700-5.000 K
Schuller REF. 228091
Enora dorado brillo y negro mate · LED 39W DIMABLE · 3.900 lumen / 2.700-5.000 K
Schuller REF. 501965
Zaria negro mate · LED 21W DIMABLE · 1.456 lumen / 3.000 K
Schuller REF. 365093
Grace oro · 2 G9 LED 4W · 800 lumen / 3.000 K
Una selección para empezar a imaginar tu espacio.
Lucide REF. 21450/40/96
NIGELLA Café · GU10 · máx. 25 W
Lucide REF. 45591/01/55
ROLLO Terracota · E27 · máx. 40 W
Lucide REF. 45596/01/35
SIEMON Azul · E14 · máx. 25 W
Lucide REF. 03750/81/30
LESLEY Negro · E27 · máx. 40 W
ARQUITECTURA Y LUZ · INSPIRACIÓN 02 / PROYECTOS DE ILUMINACIÓN
Tu espacio. Nuestra mirada. La luz lo une. Desde la primera idea hasta la instalación. Pensamos la iluminación contigo para que cada punto de luz tenga un propósito.
Residencial Comercial Exterior
Cuéntanos tu proyecto
Explora las colecciones. Consulta disponibilidad y suministro con Agulló.
CERCA DE TI, EN CALPE
Ven a ver la luz de cerca. Descubre nuestra exposición y comparte tus ideas con nosotros. Te ayudamos a pensar la iluminación de tu espacio.
Visita nuestra tienda
¿Te ayudamos?
TE AYUDAMOS A ELEGIR
Hablemos de tu luz. Cuéntanos qué necesitas. Te asesoramos sobre el modelo, los acabados y las opciones para tu espacio.