/** * Plugin Name: ronin CRM Link * Plugin URI: https://www.ronins.org/ * Description: Shortcode [enlace_crm] para enlaces salientes al CRM, con registro de leads en un CPT propio y aviso por correo. El seguimiento usa navigator.sendBeacon contra un endpoint REST del plugin, así que no depende de formularios de Elementor. * Version: 3.5.0 * Author: ronin * Author URI: https://www.ronincreativos.com * Ronin Module: yes * Requires at least: 5.0 * Requires PHP: 8.0 * License: GPLv2 or later * * El historial de versiones vive en changelog.md. */ defined( 'ABSPATH' ) || exit; // Ya no hay que mantener nada en sync: la version sale del header, que es la // unica fuente de verdad. La constante escrita a mano ya se habia quedado atras // (3.4.4 frente a 3.4.4.1 del header), y como alimenta el cache busting del JS // del tracker, los navegadores seguian sirviendo la version vieja del script. define( 'RCL_VERSION', get_file_data( __FILE__, [ 'Version' => 'Version' ] )['Version'] ?: '0.0.0' ); define( 'RCL_FILE', __FILE__ ); define( 'RCL_PATH', plugin_dir_path( __FILE__ ) ); define( 'RCL_URL', plugin_dir_url( __FILE__ ) ); define( 'RCL_OPTION', 'ronin_crm_link' ); // Clave unica de la option (array). define( 'RCL_CPT', 'rcl_lead' ); // Custom post type donde viven los leads. require_once RCL_PATH . 'includes/shortcode.php'; require_once RCL_PATH . 'includes/class-rcl-settings.php'; require_once RCL_PATH . 'includes/class-rcl-cpt.php'; require_once RCL_PATH . 'includes/class-rcl-admin.php'; require_once RCL_PATH . 'includes/class-rcl-mailer.php'; require_once RCL_PATH . 'includes/class-rcl-rest.php'; require_once RCL_PATH . 'includes/class-rcl-tracker.php'; add_action( 'plugins_loaded', function () { new RCL_Settings(); new RCL_CPT(); new RCL_Admin(); new RCL_Rest(); new RCL_Tracker(); } ); /** * En activacion registramos el CPT y refrescamos reglas. No es publico (no tiene * rewrite), pero es buena practica dejar el menu/listado consistente. */ register_activation_hook( __FILE__, function () { RCL_CPT::register_post_type(); flush_rewrite_rules(); } ); register_deactivation_hook( __FILE__, 'flush_rewrite_rules' ); /** * Menu padre compartido "Ronin". Convencion del ecosistema: el primero en * definir RONIN_PARENT_MENU registra el parent; los demas se cuelgan de el. * Prioridad 9 (antes 5): Ronin Plugins Hub se engancha en 1 y gana siempre la * carrera, los submenus propios van en 20. * * La callback dejo de ser la funcion global ronin_hub_page() y pasa a ser un * closure. Esa funcion sin prefijo era el origen de una colision con el propio * Hub, que tuvo que renombrar la suya; con el closure el nombre desaparece del * espacio global y el conflicto no puede repetirse. */ add_action( 'admin_menu', function () { if ( defined( 'RONIN_PARENT_MENU' ) ) { return; } define( 'RONIN_PARENT_MENU', 'ronin' ); add_menu_page( 'Ronin Plugins', 'Ronin', 'manage_options', 'ronin', function () { echo '

Ronin Plugins

Selecciona un plugin del menu lateral.

'; }, 'dashicons-superhero', 58 ); // Quitar el submenu duplicado que WP crea con el mismo slug del parent. add_action( 'admin_menu', function () { remove_submenu_page( 'ronin', 'ronin' ); }, 999 ); }, 9 ); /** * Registro en el ronin-license-manager para updates automaticos (PUC). * Prioridad 2: el manager se inicializa en 1, los hijos en 2, PUC despacha en 99. * El nombre y la version se leen del header (fuente unica) con get_file_data, * que no carga textdomain temprano. */ add_action( 'plugins_loaded', function () { if ( ! function_exists( 'ronin_register_plugin' ) ) { return; // El license-manager no esta activo; el plugin funciona igual, sin updates. } $data = get_file_data( RCL_FILE, [ 'Name' => 'Plugin Name', 'Version' => 'Version' ] ); ronin_register_plugin( 'ronin-crm-link', $data['Name'], $data['Version'], RCL_FILE, false, true ); }, 2 ); // Accent del módulo y color de texto legible sobre él: los provee el Hub. // Fallback local en pri 5 para funcionar igual sin el Hub. add_action( 'plugins_loaded', function () { if ( ! function_exists( 'ronin_get_module_accent' ) ) { function ronin_get_module_accent( $slug, $default = '#c0392b' ) { return $default; } } if ( ! function_exists( 'ronin_accent_on' ) ) { function ronin_accent_on( $hex, $light = '#ffffff', $dark = '#1d2327' ) { $hex = ltrim( (string) $hex, '#' ); if ( strlen( $hex ) === 3 ) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } if ( ! preg_match( '/^[0-9a-f]{6}$/i', $hex ) ) { return $light; } $lin = function ( $c ) { $c = $c / 255; return $c <= 0.03928 ? $c / 12.92 : pow( ( $c + 0.055 ) / 1.055, 2.4 ); }; $l = 0.2126 * $lin( hexdec( substr( $hex, 0, 2 ) ) ) + 0.7152 * $lin( hexdec( substr( $hex, 2, 2 ) ) ) + 0.0722 * $lin( hexdec( substr( $hex, 4, 2 ) ) ); return $l > 0.42 ? $dark : $light; } } }, 5 ); https://www.ronincreativos.com/post-sitemap.xml 2026-09-01T07:39:11+00:00 https://www.ronincreativos.com/page-sitemap.xml 2026-09-01T07:41:18+00:00 https://www.ronincreativos.com/product-sitemap.xml 2026-04-19T05:25:07+00:00 https://www.ronincreativos.com/cliente-sitemap.xml 2021-02-05T15:11:33+00:00 https://www.ronincreativos.com/category-sitemap.xml 2026-09-01T07:39:11+00:00