core = $core; $this->settings_registrar = new AdminSettingsRegistrar(); // initCoreManagers inlined. $this->settings_manager = new \PDFIB\Managers\PDFBuilderSettingsManager( $this ); if ( class_exists( 'PDFIB\Managers\PdfBuilderTemplateManager' ) ) { $this->template_manager = new \PDFIB\Managers\PdfBuilderTemplateManager( $this ); } // initSpecializedModules inlined. $this->html_renderer = new \PDFIB\Admin\Renderers\HTMLRenderer( $this ); try { $this->template_processor = new \PDFIB\Admin\Processors\TemplateProcessor( $this ); } catch ( \Exception $e ) { $this->template_processor = null; } // initServicesAndLoaders inlined. $this->script_loader = new \PDFIB\Admin\Loaders\AdminScriptLoader( $this ); $this->admin_page_renderer = new \PDFIB\Admin\Renderers\AdminPageRenderer( $this ); // initConditionalModules inlined. // Le plugin PRO peut injecter une instance de manager via le filtre 'pdfib_predefined_templates_manager'. $this->predefined_templates_manager = apply_filters( 'pdfib_predefined_templates_manager', null ); // WooCommerce hooks via delegate. ( new AdminWooCommerceHooks( $this ) )->register_all(); // initHooks + initAdminHooks inlined. \add_action( 'admin_menu', array( $this, 'add_admin_menu' ) ); if ( $this->is_admin_context() ) { \add_action( 'admin_init', array( $this->settings_registrar, 'register_settings' ) ); \add_action( 'init', array( $this, 'register_template_post_type' ) ); \add_action( 'admin_enqueue_scripts', array( $this, 'disable_problematic_preferences' ), 1 ); } } /** * Récupère l'instance du template manager. * * @return mixed */ public function get_template_manager() { return $this->template_manager; } /** * Vérifie les permissions d'administration sans mise en cache. * * @return bool */ private function check_admin_permissions() { // Vérifier les rôles autorisés par défaut. $allowed_roles = array( 'administrator', 'editor', 'shop_manager' ); $user = \wp_get_current_user(); $user_roles = $user ? $user->roles : array(); foreach ( $user_roles as $role ) { if ( in_array( $role, $allowed_roles, true ) ) { return true; } } return false; } /** * Vérifie si la version PRO est active. * * @return bool */ public static function is_premium_active(): bool { if ( function_exists( 'pdfib_is_pro_plugin_active' ) && pdfib_is_pro_plugin_active() ) { return true; } $pdfib_license_manager = apply_filters( 'pdfib_license_manager_instance', null ); return is_object( $pdfib_license_manager ) && method_exists( $pdfib_license_manager, 'is_premium' ) && $pdfib_license_manager->is_premium(); } /** * Compte le nombre de templates créés par un utilisateur. * * @param int $user_id Identifiant de l'utilisateur. * @return int */ public static function count_user_templates( $user_id ) { // Compter depuis la table custom pdfib_templates. $table_templates = pdfib_db()->prefix . 'pdfib_templates'; // Récupérer le nombre de templates pour cet utilisateur. $count = pdfib_db()->get_var( pdfib_db()->prepare( 'SELECT COUNT(*) FROM %i WHERE user_id = %d', $table_templates, $user_id ) ); return (int) $count; } /** * Enregistre le custom post type pour les templates PDF. */ public function register_template_post_type() { \register_post_type( 'pdfib_template', array( 'labels' => array( 'name' => \__( 'Templates PDF', 'advanced-pdf-invoice-builder' ), 'singular_name' => \__( 'Template PDF', 'advanced-pdf-invoice-builder' ), 'add_new' => \__( 'Nouveau Template', 'advanced-pdf-invoice-builder' ), 'add_new_item' => \__( 'Ajouter un Nouveau Template', 'advanced-pdf-invoice-builder' ), 'edit_item' => \__( 'Éditer le Template', 'advanced-pdf-invoice-builder' ), 'new_item' => \__( 'Nouveau Template', 'advanced-pdf-invoice-builder' ), 'view_item' => \__( 'Voir le Template', 'advanced-pdf-invoice-builder' ), 'search_items' => \__( 'Rechercher Templates', 'advanced-pdf-invoice-builder' ), 'not_found' => \__( 'Aucun template trouvé', 'advanced-pdf-invoice-builder' ), 'not_found_in_trash' => \__( 'Aucun template dans la corbeille', 'advanced-pdf-invoice-builder' ), ), 'public' => false, 'show_ui' => true, 'show_in_menu' => false, // Masqué du menu principal. 'capability_type' => 'post', 'hierarchical' => false, 'supports' => array( 'title' ), 'has_archive' => false, 'rewrite' => false, ) ); } /** * Vérifie si on est dans le contexte d'administration. * * @return bool */ private function is_admin_context() { $request_action = sanitize_text_field( wp_unslash( $GLOBALS['_REQUEST']['action'] ?? '' ) ); return is_admin() || ( '' !== $request_action && strpos( $request_action, 'pdf_builder' ) !== false ); } /** * Désactive les préférences WordPress problématiques qui causent des erreurs API REST. */ public function disable_problematic_preferences() { global $pagenow; $page = sanitize_text_field( wp_unslash( $GLOBALS['_GET']['page'] ?? '' ) ); if ( 'pdf-builder-react-editor' !== $page ) { return; } $inline_js = "if(typeof wp!=='undefined'&&wp.apiFetch){var oAF=wp.apiFetch;wp.apiFetch=function(o){if(o.path&&o.path.includes('/wp/v2/users/me')){return Promise.reject({code:'blocked_endpoint',message:'Endpoint blocked to prevent errors'});}return oAF(o);};}if(typeof wp!=='undefined'&&wp.data&&wp.data.dispatch){try{if(wp.data.dispatch('core/preferences')){wp.data.dispatch('core/preferences').set=function(){};}}catch(e){}}if(typeof jQuery!=='undefined'){var JOB='{'.charCodeAt(0);var oA=jQuery.ajax;jQuery.ajax=function(o){if(o.dataType==='json'||(o.url&&o.url.includes('admin-ajax.php'))){var oS=o.success;var oE=o.error;o.success=function(d,t,x){if(typeof d==='string'&&d.trim().charCodeAt(0)!==JOB){if(oE){oE(x,'parsererror',{code:'invalid_json',message:'Invalid JSON response.'});}return;}if(oS){oS(d,t,x);}};o.error=function(x,t,e){console.warn('PDF Builder: AJAX error handled:',t,e);if(oE){oE(x,t,e);}};}return oA.call(this,o);};}"; wp_add_inline_script( 'jquery', $inline_js ); } /** * Ajoute le menu d'administration. */ public function add_admin_menu() { if ( ! \current_user_can( 'manage_options' ) ) { return; } \add_menu_page( \__( 'Advanced PDF Invoice Builder', 'advanced-pdf-invoice-builder' ), \__( 'PDF Builder', 'advanced-pdf-invoice-builder' ), 'manage_options', 'advanced-pdf-invoice-builder', array( $this, 'admin_page' ), 'dashicons-pdf', 30 ); \add_submenu_page( 'advanced-pdf-invoice-builder', \__( 'Accueil - Advanced PDF Invoice Builder', 'advanced-pdf-invoice-builder' ), \__( 'Accueil', 'advanced-pdf-invoice-builder' ), 'manage_options', 'advanced-pdf-invoice-builder', array( $this, 'admin_page' ) ); // Enregistrer la page éditeur en free avant do_action pour garantir l'accès même sans PRO. \add_submenu_page( 'advanced-pdf-invoice-builder', \__( 'Éditeur PDF - Advanced PDF Invoice Builder', 'advanced-pdf-invoice-builder' ), \__( 'Éditeur PDF', 'advanced-pdf-invoice-builder' ), 'manage_options', 'pdf-builder-react-editor', array( $this, 'react_editor_page' ) ); do_action( 'pdfib_admin_menu_after_home' ); \add_submenu_page( 'advanced-pdf-invoice-builder', \__( 'Templates PDF - Advanced PDF Invoice Builder', 'advanced-pdf-invoice-builder' ), \__( 'Templates', 'advanced-pdf-invoice-builder' ), 'manage_options', 'pdf-builder-templates', array( $this, 'templates_page' ) ); \add_submenu_page( 'advanced-pdf-invoice-builder', \__( 'Paramètres - Advanced PDF Invoice Builder', 'advanced-pdf-invoice-builder' ), \__( 'Paramètres', 'advanced-pdf-invoice-builder' ), 'manage_options', 'pdf-builder-settings', array( $this, 'settings_page' ) ); if ( ! self::is_premium_active() ) { \add_submenu_page( 'advanced-pdf-invoice-builder', \__( 'Découvrir PRO - Advanced PDF Invoice Builder', 'advanced-pdf-invoice-builder' ), \__( 'Découvrir PRO', 'advanced-pdf-invoice-builder' ), 'manage_options', 'pdf-builder-upgrade', array( $this, 'upgrade_page' ) ); } } /** * Page principale d'administration - Tableau de bord. */ public function admin_page() { if ( ! $this->check_admin_permissions() ) { \wp_die( esc_html__( 'Vous n\'avez pas les permissions nécessaires pour accéder à cette page.', 'advanced-pdf-invoice-builder' ) ); } // Utiliser le renderer pour afficher la page d'administration. if ( $this->admin_page_renderer ) { $this->admin_page_renderer->render_admin_page(); } else { // Fallback si le renderer n'est pas disponible. echo '

Advanced PDF Invoice Builder

' . esc_html__( 'Erreur: Renderer non disponible.', 'advanced-pdf-invoice-builder' ) . '

'; } } /** * Page de l'éditeur React unifié. */ public function react_editor_page() { // Guard contre le double rendu si free et PRO enregistrent tous les deux le callback. static $rendered = false; if ( $rendered ) { return; } $rendered = true; // En mode preview, autoriser les utilisateurs avec droits WooCommerce. $is_preview_mode = isset( $GLOBALS['_GET']['preview'] ) && '1' === $GLOBALS['_GET']['preview']; $has_permission = $this->check_admin_permissions() || ( $is_preview_mode && \current_user_can( 'edit_shop_orders' ) ); if ( ! $has_permission ) { \wp_die( esc_html__( 'Vous n\'avez pas les permissions nécessaires pour accéder à cette page.', 'advanced-pdf-invoice-builder' ) ); } if ( ! $is_preview_mode && ! $this->pdfib_has_editor_entry_context() ) { \wp_safe_redirect( \admin_url( 'admin.php?page=pdf-builder-templates' ) ); exit; } ?>
0 ) { return true; } $legacy_template = isset( $GLOBALS['_GET']['template'] ) ? absint( wp_unslash( $GLOBALS['_GET']['template'] ) ) : 0; if ( $legacy_template > 0 ) { return true; } $predefined_template = isset( $GLOBALS['_GET']['predefined_template'] ) ? sanitize_key( wp_unslash( $GLOBALS['_GET']['predefined_template'] ) ) : ''; if ( '' !== $predefined_template ) { return true; } $editor_action = isset( $GLOBALS['_GET']['editor_action'] ) ? sanitize_key( wp_unslash( $GLOBALS['_GET']['editor_action'] ) ) : ''; // Permettre l'accès à l'éditeur en mode "new" uniquement si l'utilisateur peut créer un template. if ( 'new' === $editor_action ) { return self::can_create_template(); } return false; } /** * Page de gestion des templates. */ public function templates_page() { if ( ! $this->check_admin_permissions() ) { \wp_die( esc_html__( 'Vous n\'avez pas les permissions nécessaires pour accéder à cette page.', 'advanced-pdf-invoice-builder' ) ); } // Inclure la page dédiée de gestion des templates. if ( file_exists( \plugin_dir_path( dirname( __DIR__ ) ) . 'templates/admin/templates-page.php' ) ) { include_once \plugin_dir_path( dirname( __DIR__ ) ) . 'templates/admin/templates-page.php'; } else { // Fallback si le fichier n'existe pas. echo '
'; echo '

' . esc_html__( 'Gestion des Templates PDF', 'advanced-pdf-invoice-builder' ) . '

'; echo '

' . esc_html__( 'Erreur: Fichier de templates introuvable.', 'advanced-pdf-invoice-builder' ) . '

'; echo '
'; } } /** * Page des paramètres - centralisée dans settings-main.php. */ public function settings_page() { if ( ! $this->check_admin_permissions() ) { \wp_die( esc_html__( 'Vous n\'avez pas les permissions nécessaires pour accéder à cette page.', 'advanced-pdf-invoice-builder' ) ); } // Inclure le fichier centralisé des paramètres. include_once \plugin_dir_path( dirname( __DIR__ ) ) . 'templates/admin/settings-parts/settings-main.php'; } /** * Page d'aperçu PRO pour le free. */ public function upgrade_page() { if ( ! $this->check_admin_permissions() ) { \wp_die( esc_html__( 'Vous n\'avez pas les permissions nécessaires pour accéder à cette page.', 'advanced-pdf-invoice-builder' ) ); } if ( self::is_premium_active() ) { \wp_safe_redirect( \admin_url( 'admin.php?page=advanced-pdf-invoice-builder' ) ); exit; } $pdfib_purchase_url = 'https://hub.threeaxe.fr/nos-produits/pdf-builder-pro-2'; $pdfib_dashboard_url = \admin_url( 'admin.php?page=advanced-pdf-invoice-builder' ); $capabilities = array( array( 'icon' => '🖼️', 'tone' => 'blue', 'title' => __( 'Export et rendu', 'advanced-pdf-invoice-builder' ), 'desc' => __( 'Des sorties plus propres pour les documents publiés, archivés ou partagés.', 'advanced-pdf-invoice-builder' ), 'items' => array( __( 'PNG et JPG', 'advanced-pdf-invoice-builder' ), __( '300 & 600 DPI', 'advanced-pdf-invoice-builder' ), __( 'Formats de page étendus', 'advanced-pdf-invoice-builder' ), ), ), array( 'icon' => '🧲', 'tone' => 'violet', 'title' => __( 'Précision et confort', 'advanced-pdf-invoice-builder' ), 'desc' => __( 'Des outils pensés pour placer et ajuster les éléments plus rapidement.', 'advanced-pdf-invoice-builder' ), 'items' => array( __( 'Grille, guides et aimantation', 'advanced-pdf-invoice-builder' ), __( 'Sélection multiple', 'advanced-pdf-invoice-builder' ), __( 'Raccourcis clavier', 'advanced-pdf-invoice-builder' ), ), ), array( 'icon' => '📚', 'tone' => 'amber', 'title' => __( 'Contenus et modèles', 'advanced-pdf-invoice-builder' ), 'desc' => __( 'Plus de modèles prêts à l\'emploi pour couvrir davantage de cas métier.', 'advanced-pdf-invoice-builder' ), 'items' => array( __( '36 modèles de texte', 'advanced-pdf-invoice-builder' ), __( '21 modèles de mentions', 'advanced-pdf-invoice-builder' ), __( 'Types de document étendus', 'advanced-pdf-invoice-builder' ), ), ), ); $pricing_plans = array( array( 'slug' => 'monthly', 'period' => __( 'Mensuel', 'advanced-pdf-invoice-builder' ), 'price' => '3,99€', 'cycle' => __( '/mois', 'advanced-pdf-invoice-builder' ), 'note' => __( 'Annulable à tout moment', 'advanced-pdf-invoice-builder' ), 'popular' => false, ), array( 'slug' => 'yearly', 'ribbon' => __( 'Option annuelle', 'advanced-pdf-invoice-builder' ), 'period' => __( 'Annuel', 'advanced-pdf-invoice-builder' ), 'price' => '39,99€', 'cycle' => __( '/an', 'advanced-pdf-invoice-builder' ), 'note' => __( 'Économisez 3 mois !', 'advanced-pdf-invoice-builder' ), 'popular' => true, ), array( 'slug' => 'lifetime', 'ribbon' => __( 'Licence à vie', 'advanced-pdf-invoice-builder' ), 'period' => __( 'À vie', 'advanced-pdf-invoice-builder' ), 'price' => '69,99€', 'cycle' => __( 'paiement unique', 'advanced-pdf-invoice-builder' ), 'note' => __( 'Zéro renouvellement', 'advanced-pdf-invoice-builder' ), 'popular' => false, ), ); ?>


PNG / JPG 300 & 600 DPI 57

PRO
PNG / JPG
300 / 600
57

7

“”

✓  ·  ✓  ·  ✓

thumbnail_manager ) { if ( ! class_exists( 'PDFIB\Managers\PdfBuilderThumbnailManager' ) ) { $thumbnail_manager_file = self::SRC_DIR . '/Managers/class-pdfbuilderthumbnailmanager.php'; if ( file_exists( $thumbnail_manager_file ) ) { require_once $thumbnail_manager_file; } } $this->thumbnail_manager = \PDFIB\Managers\PdfBuilderThumbnailManager::get_instance(); } return $this->thumbnail_manager; } /** * Getter pour le Dashboard Data Provider avec lazy loading. * * @return mixed */ public function get_dashboard_data_provider() { if ( null === $this->dashboard_data_provider ) { if ( ! class_exists( '\PDFIB\Admin\Providers\DashboardDataProvider' ) ) { require_once self::SRC_DIR . '/Admin/Providers/class-dashboarddataprovider.php'; } $this->dashboard_data_provider = new \PDFIB\Admin\Providers\DashboardDataProvider(); } return $this->dashboard_data_provider; } /** * Getter pour l'intégration WooCommerce avec lazy loading. * * @return mixed */ public function get_woo_commerce_integration() { if ( null === $this->woocommerce_integration && \did_action( 'plugins_loaded' ) && ( defined( 'WC_VERSION' ) || class_exists( 'WooCommerce' ) ) ) { if ( ! class_exists( 'PDFIB\Managers\PdfBuilderWooCommerceIntegration' ) ) { $woo_file = PDFIB_PLUGIN_DIR . 'src/Managers/class-pdfbuilderwoocommerceintegration.php'; if ( file_exists( $woo_file ) ) { require_once $woo_file; } } if ( class_exists( 'PDFIB\Managers\PdfBuilderWooCommerceIntegration' ) ) { $this->woocommerce_integration = new \PDFIB\Managers\PdfBuilderWooCommerceIntegration( $this->core ); } } return $this->woocommerce_integration; } /** * Getter pour le Predefined Templates Manager. * * @return mixed */ public function get_predefined_templates_manager() { if ( null === $this->predefined_templates_manager ) { $this->predefined_templates_manager = apply_filters( 'pdfib_predefined_templates_manager', null ); } return $this->predefined_templates_manager; } /** * Get template processor instance. * * @return mixed */ public function get_template_processor() { if ( null === $this->template_processor ) { try { $this->template_processor = new \PDFIB\Admin\Processors\TemplateProcessor( $this ); } catch ( \Exception $e ) { $this->template_processor = null; } } return $this->template_processor; } /** * Compte les templates personnalisés d'un utilisateur. * * Tous les templates de l'utilisateur comptent dans le quota, y compris * ceux marqués comme "par défaut" : le drapeau is_default est modifiable * via l'action "Définir comme template par défaut" et ne doit pas * permettre de contourner la limite de la version gratuite. * * @param int $user_id Identifiant de l'utilisateur. * @return int */ public static function count_user_custom_templates( int $user_id ): int { $table_templates = pdfib_db()->prefix . 'pdfib_templates'; $count = pdfib_db()->get_var( pdfib_db()->prepare( 'SELECT COUNT(*) FROM %i WHERE user_id = %d', $table_templates, $user_id ) ); return (int) $count; } /** * Vérifie si l'utilisateur peut créer un nouveau template. * * La version premium est illimitée. La version gratuite est limitée à un * seul template personnalisé. * * @return bool */ public static function can_create_template() { $pdfib_license_manager = apply_filters( 'pdfib_license_manager_instance', null ); $is_premium = is_object( $pdfib_license_manager ) && method_exists( $pdfib_license_manager, 'is_premium' ) && $pdfib_license_manager->is_premium(); if ( $is_premium ) { return true; } $user_id = \get_current_user_id(); $templates_count = self::count_user_custom_templates( $user_id ); return $templates_count < 1; } }