init_hooks(); $this->init_twig(); $this->includes(); } /** * Hook into WordPress and WooCommerce */ private function init_hooks() { // Register product type add_filter( 'product_type_selector', array( $this, 'add_product_type' ) ); add_filter( 'woocommerce_product_class', array( $this, 'product_class' ), 10, 2 ); // Enqueue scripts and styles add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) ); // Admin settings add_filter( 'woocommerce_get_settings_pages', array( $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, array( '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 ) { // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText -- dynamic Twig template strings. 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' ) ); $this->twig->addFunction( new \Twig\TwigFunction( 'wc_price', 'wc_price' ) ); // Add WordPress escaping functions as Twig filters $this->twig->addFilter( new \Twig\TwigFilter( 'esc_html', 'esc_html' ) ); $this->twig->addFilter( new \Twig\TwigFilter( 'esc_attr', 'esc_attr' ) ); $this->twig->addFilter( new \Twig\TwigFilter( '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/ProductData.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/ProductType.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/StockManager.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/CartHandler.php'; require_once WC_COMPOSABLE_PRODUCT_PATH . 'includes/ProductSelector.php'; // Initialize components new Admin\ProductData(); new CartHandler(); } /** * 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 ( 'composable' === $product_type ) { $classname = 'Magdev\WcComposableProduct\ProductType'; } 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', array(), WC_COMPOSABLE_PRODUCT_VERSION ); wp_enqueue_script( 'wc-composable-product', WC_COMPOSABLE_PRODUCT_URL . 'assets/js/frontend.js', array( 'jquery' ), WC_COMPOSABLE_PRODUCT_VERSION, true ); wp_localize_script( 'wc-composable-product', 'wcComposableProduct', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'wc_composable_product_nonce' ), 'i18n' => array( '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' ), ), 'price_format' => array( 'currency_symbol' => get_woocommerce_currency_symbol(), 'decimal_separator' => wc_get_price_decimal_separator(), 'thousand_separator' => wc_get_price_thousand_separator(), 'decimals' => wc_get_price_decimals(), 'price_format' => get_woocommerce_price_format(), ), ) ); } } /** * 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', array(), WC_COMPOSABLE_PRODUCT_VERSION ); wp_enqueue_script( 'wc-composable-product-admin', WC_COMPOSABLE_PRODUCT_URL . 'assets/js/admin.js', array( '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 = array() ) { return $this->twig->render( $template, $context ); } }