Files
wc-composable-product/includes/Plugin.php

247 lines
6.6 KiB
PHP
Raw Normal View History

<?php
/**
* Main Plugin Class
*
* @package Magdev\WcComposableProduct
*/
namespace Magdev\WcComposableProduct;
defined( 'ABSPATH' ) || exit;
/**
* Main plugin class - Singleton pattern
*/
class Plugin {
/**
* The single instance of the class
*
* @var Plugin
*/
protected static $instance = null;
/**
* Twig environment
*
* @var \Twig\Environment
*/
private $twig = null;
/**
* Main Plugin Instance
*
* Ensures only one instance is loaded or can be loaded.
*
* @return Plugin
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->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 );
}
}