init_hooks(); $this->init_twig(); $this->includes(); } /** * Hook into WordPress and WooCommerce */ private function init_hooks() { // Register product type add_filter('product_type_selector', [$this, 'add_product_type']); add_filter('woocommerce_product_class', [$this, 'product_class'], 10, 2); // Enqueue scripts and styles add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_scripts']); add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']); // Admin settings add_filter('woocommerce_get_settings_pages', [$this, 'add_settings_page']); } /** * Initialize Twig template engine */ private function init_twig() { $loader = new \Twig\Loader\FilesystemLoader(WC_COMPOSABLE_PRODUCT_PATH . 'templates'); $this->twig = new \Twig\Environment($loader, [ 'cache' => WC_COMPOSABLE_PRODUCT_PATH . 'cache', 'auto_reload' => true, 'debug' => defined('WP_DEBUG') && WP_DEBUG, ]); // Add WordPress functions to Twig $this->twig->addFunction(new \Twig\TwigFunction('__', function($text) { return __($text, 'wc-composable-product'); })); $this->twig->addFunction(new \Twig\TwigFunction('esc_html', 'esc_html')); $this->twig->addFunction(new \Twig\TwigFunction('esc_attr', 'esc_attr')); $this->twig->addFunction(new \Twig\TwigFunction('esc_url', 'esc_url')); } /** * Include required files */ private function includes() { // Note: Settings.php is NOT included here because it extends WC_Settings_Page // which isn't loaded until later. It's included in add_settings_page() instead. require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/Admin/Product_Data.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/Product_Type.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/Stock_Manager.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/Cart_Handler.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/Product_Selector.php'; // Initialize components new Admin\Product_Data(); new Cart_Handler(); } /** * Add composable product type to selector * * @param array $types Product types * @return array */ public function add_product_type($types) { $types['composable'] = __('Composable product', 'wc-composable-product'); return $types; } /** * Use custom product class for composable products * * @param string $classname Product class name * @param string $product_type Product type * @return string */ public function product_class($classname, $product_type) { if ($product_type === 'composable') { $classname = 'WC_Composable_Product\Product_Type'; } return $classname; } /** * Enqueue frontend scripts and styles */ public function enqueue_frontend_scripts() { if (is_product()) { wp_enqueue_style( 'wc-composable-product', WC_COMPOSABLE_PRODUCT_URL . 'assets/css/frontend.css', [], WC_COMPOSABLE_PRODUCT_VERSION ); wp_enqueue_script( 'wc-composable-product', WC_COMPOSABLE_PRODUCT_URL . 'assets/js/frontend.js', ['jquery'], WC_COMPOSABLE_PRODUCT_VERSION, true ); wp_localize_script('wc-composable-product', 'wcComposableProduct', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('wc_composable_product_nonce'), 'i18n' => [ 'select_items' => __('Please select items', 'wc-composable-product'), 'max_items' => __('Maximum items selected', 'wc-composable-product'), 'min_items' => __('Please select at least one item', 'wc-composable-product'), ], ]); } } /** * Enqueue admin scripts and styles */ public function enqueue_admin_scripts($hook) { if ('post.php' === $hook || 'post-new.php' === $hook) { global $post_type; if ('product' === $post_type) { wp_enqueue_style( 'wc-composable-product-admin', WC_COMPOSABLE_PRODUCT_URL . 'assets/css/admin.css', [], WC_COMPOSABLE_PRODUCT_VERSION ); wp_enqueue_script( 'wc-composable-product-admin', WC_COMPOSABLE_PRODUCT_URL . 'assets/js/admin.js', ['jquery', 'wc-admin-product-meta-boxes'], WC_COMPOSABLE_PRODUCT_VERSION, true ); } } } /** * Add settings page to WooCommerce * * @param array $settings WooCommerce settings pages * @return array */ public function add_settings_page($settings) { // Include Settings.php here, when WC_Settings_Page is guaranteed to be loaded require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/Admin/Settings.php'; $settings[] = new Admin\Settings(); return $settings; } /** * Get Twig environment * * @return \Twig\Environment */ public function get_twig() { return $this->twig; } /** * Render a Twig template * * @param string $template Template name * @param array $context Template variables * @return string */ public function render_template($template, $context = []) { return $this->twig->render($template, $context); } }