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

02 / PROYECTOS

El principio de
una buena atmósfera.

Proyectos de iluminación interior y exterior. Unimos la elección de la luz con el conocimiento de la instalación.

Interior residencial de inspiraciónINSPIRACIÓN RESIDENCIAL · IMAGEN ILUSTRATIVA

De la idea a la luz.

01

Te escuchamos

Cómo vives el espacio, qué necesitas y qué quieres sentir.

02

Definimos la luz

Capas de iluminación, temperatura, orientación y regulación.

03

Elegimos las piezas

Luminarias, acabados y soluciones técnicas para el conjunto.

04

Lo hacemos realidad

Definimos contigo el alcance de la instalación.

EMPECEMOS POR UNA CONVERSACIÓN

¿Y si vemos tu espacio
con otra luz?

Cuéntanos tu proyecto
¿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