<?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; }); Guías de iluminación | Agulló
LUZ, DISEÑO Y ACOMPAÑAMIENTOVisítanos en Calpe
agullóELECTRICIDAD · ILUMINACIÓN
Hablemos

IDEAS PARA VIVIR MEJOR LA LUZ

Guías de
iluminación.

Una buena luz empieza por saber elegir.

Ideas claras, detalles que importan y piezas para imaginar tu espacio con otra luz.

Encuentra tu guía
Janderin · Lucide. Fotografía de fabricante.
Janderin · Lucide

¿Por dónde empezamos?

Elegir lámparas Por estancias Entender la luz Exterior

MENOS DUDAS. MEJOR LUZ.

Encuentra tu próxima idea.

12 guías para explorar

UNA MARCA CON CARÁCTER

El universo
Schuller.

Antes de elegir una pieza que destaque, descubre qué hace que encaje en tu casa.

La guía para elegir Explorar el catálogo Schuller
Lía · Schuller. Imagen de ambiente de la colección; fotografía de fabricante.
LÍA · SCHULLER

LA LUZ SE PIENSA. Y SE VIVE.

Tu espacio.
Una nueva forma de verlo.

¿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.

Tus datos se utilizarán para responder a esta consulta. Información sobre privacidad. Responsable: Electricidad Agulló. Finalidad: responder a tu consulta y facilitar información sobre los productos o servicios solicitados. Base jurídica: tu consentimiento. Puedes ejercer tus derechos en info@electricidadagullo.com. Consulta destinatarios, conservación y demás información en la política de privacidad.

Consultar por WhatsApp