plugin_path() . '/vendor/autoload.php'; require $this->plugin_path() . '/vendor/strauss/autoload.php'; $this->plugin_basename = plugin_basename(__FILE__); $this->legacy_addons = apply_filters( 'wpo_wcpdf_legacy_addons', array( 'ubl-woocommerce-pdf-invoices.php' => 'UBL Invoices for WooCommerce', 'woocommerce-pdf-ips-number-tools.php' => 'PDF Invoices & Packing Slips for WooCommerce - Number Tools', 'woocommerce-pdf-ips-ubl-extender.php' => 'PDF Invoices & Packing Slips for WooCommerce - UBL Extender', 'wpo-ips-factur-x.php' => 'PDF Invoices & Packing Slips for WooCommerce - Factur-X', 'wpo-ips-cius-ro.php' => 'PDF Invoices & Packing Slips for WooCommerce - CIUS-RO', 'wpo-ips-xrechnung.php' => 'PDF Invoices & Packing Slips for WooCommerce - XRechnung', 'wpo-ips-fatturapa.php' => 'PDF Invoices & Packing Slips for WooCommerce - FatturaPA', ) ); $this->define( 'WPO_WCPDF_VERSION', $this->version ); // load the localisation & classes add_action( 'init', array( $this, 'translations' ), 8 ); add_action( 'init', array( $this, 'load_classes' ), 9 ); // Pro runs on default 10, if this runs after it will not work add_action( 'in_plugin_update_message-' . $this->plugin_basename, array( $this, 'in_plugin_update_message' ) ); add_action( 'before_woocommerce_init', array( $this, 'woocommerce_hpos_compatible' ) ); add_action( 'admin_notices', array( $this, 'nginx_detected' ) ); add_action( 'admin_notices', array( $this, 'mailpoet_mta_detected' ) ); add_action( 'admin_notices', array( $this, 'rtl_detected' ) ); add_action( 'admin_notices', array( $this, 'yearly_reset_action_missing_notice' ) ); add_action( 'admin_notices', array( $this, 'legacy_addon_notices' ) ); add_action( 'admin_notices', array( $this, 'unstable_option_announcement_notice' ) ); add_action( 'admin_notices', array( $this, 'new_unstable_version_available_notice' ) ); add_action( 'wpo_wcpdf_new_github_prerelease_available', array( $this, 'set_new_unstable_version_available_option' ), 10, 3 ); add_action( 'init', array( '\\WPO\\IPS\\Semaphore', 'init_cleanup' ), 999 ); // wait AS to initialize // deactivate legacy extensions if activated register_activation_hook( __FILE__, array( $this, 'deactivate_legacy_addons' ) ); } public function is_dependency_version_supported( $dependency ) { switch ( $dependency ) { case 'php': return defined( 'PHP_VERSION' ) && version_compare( PHP_VERSION, $this->version_php, '>=' ); case 'woo': return defined( 'WC_VERSION' ) && version_compare( WC_VERSION, $this->version_woo, '>=' ); case 'wp': global $wp_version; return version_compare( $wp_version, $this->version_wp, '>=' ); } return false; } /** * Define constant if not already set * @param string $name * @param string|bool $value */ private function define( $name, $value ) { if ( ! defined( $name ) ) { define( $name, $value ); } } /** * Load the translation / textdomain files * * Note: the first-loaded translation file overrides any following ones if the same translation is present */ public function translations() { $locale = $this->determine_locale(); $dir = trailingslashit( WP_LANG_DIR ); $textdomains = array( 'woocommerce-pdf-invoices-packing-slips' ); /** * Frontend/global Locale. Looks in: * * - WP_LANG_DIR/woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-LOCALE.mo * - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo * - woocommerce-pdf-invoices-packing-slips/languages/woocommerce-pdf-invoices-packing-slips-LOCALE.mo (which if not found falls back to:) * - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo */ foreach ( $textdomains as $textdomain ) { unload_textdomain( $textdomain ); load_textdomain( $textdomain, $dir . 'woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' ); load_textdomain( $textdomain, $dir . 'plugins/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' ); load_plugin_textdomain( $textdomain, false, dirname( plugin_basename(__FILE__) ) . '/languages' ); } } /** * Load the main plugin classes and functions */ public function includes() { // plugin legacy class mapping include_once $this->plugin_path() . '/wpo-ips-legacy-class-alias-mapping.php'; // deprecated include_once $this->plugin_path() . '/wpo-ips-deprecated-hooks.php'; include_once $this->plugin_path() . '/wpo-ips-deprecated-functions.php'; // plugin functions include_once $this->plugin_path() . '/wpo-ips-functions.php'; include_once $this->plugin_path() . '/wpo-ips-functions-edi.php'; // Compatibility classes $this->third_party_plugins = \WPO\IPS\Compatibility\ThirdPartyPlugins::instance(); $this->vat_plugins = \WPO\IPS\Compatibility\VatPlugins::instance(); $this->order_util = \WPO\IPS\Compatibility\OrderUtil::instance(); $this->file_system = \WPO\IPS\Compatibility\FileSystem::instance(); // Plugin classes $this->settings = \WPO\IPS\Settings::instance(); $this->documents = \WPO\IPS\Documents::instance(); $this->main = \WPO\IPS\Main::instance(); $this->endpoint = \WPO\IPS\Endpoint::instance(); $this->assets = \WPO\IPS\Assets::instance(); $this->admin = \WPO\IPS\Admin::instance(); $this->frontend = \WPO\IPS\Frontend::instance(); $this->install = \WPO\IPS\Install::instance(); $this->font_synchronizer = \WPO\IPS\FontSynchronizer::instance(); // EDI classes \WPO\IPS\EDI\Peppol::instance(); } /** * Instantiate classes when woocommerce is activated */ public function load_classes() { if ( ! $this->dependencies_are_ready() ) { return; } add_action( 'admin_init', array( $this, 'deactivate_legacy_addons') ); // all systems ready - GO! $this->includes(); } /** * Check if WooCommerce and PHP dependencies are met. * If not, show the appropriate admin notices. * * @return bool */ public function dependencies_are_ready(): bool { // Check if WooCommerce is activated and meets the minimum version if ( ! $this->is_woocommerce_activated() || ! $this->is_dependency_version_supported( 'woo' ) ) { add_action( 'admin_notices', array( $this, 'need_woocommerce' ) ); return false; } // Check if PHP version is supported if ( ! has_filter( 'wpo_wcpdf_pdf_maker' ) && ! $this->is_dependency_version_supported( 'php' ) ) { add_filter( 'wpo_wcpdf_document_is_allowed', '__return_false', 99999 ); add_action( 'admin_notices', array( $this, 'required_php_version' ) ); return false; } return true; } /** * WooCommerce notice. * * @return void */ public function need_woocommerce(): void { $error_message = sprintf( /* translators: 1. open anchor tag, 2. close anchor tag, 3. Woo version */ esc_html__( 'PDF Invoices & Packing Slips for WooCommerce requires %1$sWooCommerce%2$s version %3$s or higher to be installed & activated!' , 'woocommerce-pdf-invoices-packing-slips' ), '', '', esc_attr( $this->version_woo ) ); $message = '
'; $message .= sprintf( '

%s

', $error_message ); $message .= '
'; echo wp_kses_post( $message ); } /** * Check if woocommerce is activated * * @return bool */ public function is_woocommerce_activated(): bool { $blog_plugins = (array) get_option( 'active_plugins', array() ); $site_plugins = is_multisite() ? (array) get_site_option( 'active_sitewide_plugins', array() ) : array(); $is_wc_activated = false; if ( in_array( 'woocommerce/woocommerce.php', $blog_plugins, true ) || isset( $site_plugins['woocommerce/woocommerce.php'] ) ) { $is_wc_activated = true; } return apply_filters( 'wpo_wcpdf_is_woocommerce_activated', $is_wc_activated ); } /** * Declares WooCommerce HPOS compatibility. * * @return void */ public function woocommerce_hpos_compatible(): void { if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); } } /** * PHP version requirement notice */ public function required_php_version() { $error_message = sprintf( /* translators: PHP version */ esc_html__( 'PDF Invoices & Packing Slips for WooCommerce requires PHP %s or higher.', 'woocommerce-pdf-invoices-packing-slips' ), esc_attr( $this->version_php ) ); $php_message = sprintf( /* translators: tags */ esc_html__( 'We strongly recommend to %1$supdate your PHP version%2$s.', 'woocommerce-pdf-invoices-packing-slips' ), '', '' ); $message = '
'; $message .= sprintf( '

%s

', $error_message ); $message .= sprintf( '

%s

', $php_message ); $message .= '
'; echo wp_kses_post( $message ); } /** * Show plugin changes. Code adapted from W3 Total Cache. */ public function in_plugin_update_message( $args ) { $transient_name = 'wpo_wcpdf_upgrade_notice_' . $args['Version']; if ( false === ( $upgrade_notice = get_transient( $transient_name ) ) ) { $response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce-pdf-invoices-packing-slips/trunk/readme.txt' ); if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) { $upgrade_notice = self::parse_update_notice( $response['body'], $args['new_version'] ); set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS ); } } echo wp_kses_post( $upgrade_notice ); } /** * Parse update notice from readme file. * * @param string $content * @param string $new_version * @return string */ private function parse_update_notice( $content, $new_version ) { // Output Upgrade Notice. $matches = null; $regexp = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis'; $upgrade_notice = ''; if ( preg_match( $regexp, $content, $matches ) ) { $notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) ); // Convert the full version strings to minor versions. $notice_version_parts = explode( '.', trim( $matches[1] ) ); $current_version_parts = explode( '.', $this->version ); if ( 3 !== sizeof( $notice_version_parts ) ) { return $upgrade_notice; } $notice_version = $notice_version_parts[0] . '.' . $notice_version_parts[1]; $current_version = $current_version_parts[0] . '.' . $current_version_parts[1]; // Check the latest stable version and ignore trunk. if ( version_compare( $current_version, $notice_version, '<' ) ) { $upgrade_notice .= '

'; foreach ( $notices as $index => $line ) { if ( empty( $line ) ) { continue; } $upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '${1}', $line ); } } } return wp_kses_post( $upgrade_notice ); } public function nginx_detected() { if ( empty( $this->main ) ) { return; } $tmp_path = $this->main->get_tmp_path( 'attachments' ); $server_software = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : ''; $random_string = $this->main->get_random_string(); if ( stristr( $server_software, 'nginx' ) && $this->settings->user_can_manage_settings() && ! get_option( 'wpo_wcpdf_hide_nginx_notice' ) && ! $random_string ) { ob_start(); ?>

NGINX.', 'woocommerce-pdf-invoices-packing-slips' ), '' . wpo_wcpdf_escape_url_path_or_base64( $tmp_path ) . '' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>

main->generate_random_string(); $old_path = $this->main->get_tmp_base( false ); $new_path = $this->main->get_tmp_base(); $this->main->copy_directory( $old_path, $new_path ); // save option to hide nginx notice update_option( 'wpo_wcpdf_hide_nginx_notice', true ); wp_safe_redirect( admin_url( 'admin.php?page=wpo_wcpdf_options_page' ) ); exit; } } // save option to hide nginx notice if ( isset( $_REQUEST['wpo_wcpdf_hide_nginx_notice'] ) && isset( $_REQUEST['_wpnonce'] ) ) { // validate nonce if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ), 'hide_nginx_notice_nonce' ) ) { wcpdf_log_error( 'You do not have sufficient permissions to perform this action: wpo_wcpdf_hide_nginx_notice' ); wp_safe_redirect( admin_url( 'admin.php?page=wpo_wcpdf_options_page' ) ); exit; } else { update_option( 'wpo_wcpdf_hide_nginx_notice', true ); wp_safe_redirect( admin_url( 'admin.php?page=wpo_wcpdf_options_page' ) ); exit; } } } /** * Detect MailPoet. * @return void */ public function mailpoet_mta_detected() { if( is_callable( array( '\\MailPoet\\Settings\\SettingsController', 'getInstance' ) ) ) { $settings = \MailPoet\Settings\SettingsController::getInstance(); if( empty($settings) ) return; $send_transactional = $settings->get( 'send_transactional_emails', false ); if( $send_transactional && ! get_option('wpo_wcpdf_hide_mailpoet_notice') ) { ob_start(); ?>

MailPoet Sending Service or Your web host / web server, MailPoet does not include the PDF Invoices & Packing Slips for WooCommerce attachments in the emails.', 'woocommerce-pdf-invoices-packing-slips' ); ?>

The default WordPress sending method (default) on the Advanced tab.', 'woocommerce-pdf-invoices-packing-slips' ); ?>

settings ) || ! method_exists( $this->settings, 'maybe_schedule_yearly_reset_numbers' ) ) { return; } if ( ! $this->settings->maybe_schedule_yearly_reset_numbers() ) { return; } if ( ! function_exists( '\\as_get_scheduled_actions' ) ) { wcpdf_log_error( 'Action Scheduler function not available. Cannot verify if the yearly numbering reset action is scheduled.', 'critical' ); return; } $current_date = new \DateTime(); $end_of_year = new \DateTime( 'last day of December' ); $days_remaining = $current_date->diff( $end_of_year )->days; // Check if the current date is within the last 30 days of the year if ( $days_remaining <= 30 && ! $this->settings->yearly_reset_action_is_scheduled() ) { ob_start(); ?>

settings->schedule_yearly_reset_numbers(); wcpdf_log_error( 'Yearly reset numbering system rescheduled!', 'info' ); } wp_safe_redirect( admin_url( 'admin.php?page=wpo_wcpdf_options_page&tab=debug§ion=status' ) ); exit; } } /** * Get an array of all active plugins, including multisite * @return array active plugin paths */ public function get_active_plugins() { $active_plugins = (array) apply_filters( 'active_plugins', get_option( 'active_plugins' ) ); if ( is_multisite() ) { // get_site_option( 'active_sitewide_plugins', array() ) returns a 'reversed list' // like [hello-dolly/hello.php] => 1369572703 so we do array_keys to make the array // compatible with $active_plugins $active_sitewide_plugins = (array) array_keys( get_site_option( 'active_sitewide_plugins', array() ) ); // merge arrays and remove doubles $active_plugins = (array) array_unique( array_merge( $active_plugins, $active_sitewide_plugins ) ); } return $active_plugins; } public function deactivate_legacy_addons() { foreach ( $this->legacy_addons as $filename => $name ) { $legacy_addon = $this->plugin_is_activated( $filename ); if ( ! empty( $legacy_addon ) ) { deactivate_plugins( $legacy_addon ); $transient_name = $this->get_legacy_addon_transient_name( $filename ); set_transient( $transient_name, 'yes', DAY_IN_SECONDS ); } } } public function plugin_is_activated( $filename ) { $active_plugins = $this->get_active_plugins(); $active_plugin = ''; foreach ( $active_plugins as $plugin ) { if ( ! empty( $plugin ) && false !== strpos( $plugin, $filename ) ) { $active_plugin = $plugin; break; } } return $active_plugin; } public function get_legacy_addon_transient_name( $filename ) { $filename_without_ext = basename( $filename, '.php' ); $legacy_addon_name = str_replace( '-', '_', $filename_without_ext ); return "wpo_wcpdf_legacy_addon_{$legacy_addon_name}"; } public function legacy_addon_notices() { foreach ( $this->legacy_addons as $filename => $name ) { $transient_name = $this->get_legacy_addon_transient_name( $filename ); $query_arg = "{$transient_name}_notice"; if ( get_transient( $transient_name ) ) { ob_start(); ?>

' . esc_attr( $name ) . '' ); ?>

settings->user_can_manage_settings() ) { return; } // Handle dismissal if ( isset( $_GET[ $dismiss_arg ] ) && isset( $_GET['_wpnonce'] ) ) { if ( wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), $nonce_action ) ) { update_option( $dismiss_option, 'yes' ); } else { wcpdf_log_error( 'Invalid nonce while dismissing unstable version feature notice.' ); } wp_safe_redirect( remove_query_arg( array( $dismiss_arg, '_wpnonce' ) ) ); exit; } // Build dismiss URL $dismiss_url = wp_nonce_url( add_query_arg( $dismiss_arg, '1' ), $nonce_action ); ?>

' . esc_html__( 'PDF Invoices & Packing Slips for WooCommerce', 'woocommerce-pdf-invoices-packing-slips' ) . '' ); ?>

settings->debug_settings; $check_unstable_enabled = isset( $debug_settings['check_unstable_versions'] ); $unstable_state = get_option( 'wpo_wcpdf_unstable_version_state', array() ); $current_tag = isset( $unstable_state['tag'] ) ? $unstable_state['tag'] : ''; $is_dismissed = isset( $unstable_state['dismissed'] ) ? $unstable_state['dismissed'] : false; $hide_version_arg = 'wpo_wcpdf_hide_unstable_version'; // Don't show the notice if disabled or dismissed if ( ! $check_unstable_enabled || empty( $current_tag ) || $is_dismissed ) { return; } // Handle dismissal if ( isset( $_GET[ $hide_version_arg ], $_GET['_wpnonce'] ) ) { $nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ); if ( wp_verify_nonce( $nonce, 'wcpdf_hide_unstable_version' ) ) { update_option( 'wpo_wcpdf_unstable_version_state', array( 'tag' => $current_tag, 'dismissed' => true, ) ); } else { wcpdf_log_error( 'Invalid nonce while hiding unstable version notice.' ); } $redirect_url = remove_query_arg( array( $hide_version_arg, '_wpnonce' ), wp_get_referer() ); if ( ! $redirect_url ) { $redirect_url = admin_url(); // Fallback } wp_safe_redirect( $redirect_url ); exit; } $hide_url = wp_nonce_url( add_query_arg( $hide_version_arg, 1, wp_get_referer() ?: admin_url() ), 'wcpdf_hide_unstable_version' ); // Display the notice ?>

' . esc_html__( 'PDF Invoices & Packing Slips for WooCommerce', 'woocommerce-pdf-invoices-packing-slips' ) . '' ); ?>

settings->debug_settings; $enabled = isset( $debug_settings['check_unstable_versions'] ); $new_tag = sanitize_text_field( $unstable['tag'] ); if ( $enabled && ! empty( $new_tag ) && 'wpovernight' === $owner && 'woocommerce-pdf-invoices-packing-slips' === $repo ) { $current = get_option( 'wpo_wcpdf_unstable_version_state', array() ); if ( ! isset( $current['tag'] ) || $current['tag'] !== $new_tag ) { update_option( 'wpo_wcpdf_unstable_version_state', array( 'tag' => $new_tag, 'dismissed' => false, ) ); } } } /** * Get the plugin url. * @return string */ public function plugin_url() { return untrailingslashit( plugins_url( '/', __FILE__ ) ); } /** * Get the plugin path. * @return string */ public function plugin_path() { return untrailingslashit( plugin_dir_path( __FILE__ ) ); } /** * Determine the site locale */ public function determine_locale() { if ( function_exists( 'determine_locale' ) ) { // WP5.0+ $locale = determine_locale(); } else { $locale = is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(); } return apply_filters( 'plugin_locale', $locale, 'woocommerce-pdf-invoices-packing-slips' ); } } // class WPO_WCPDF endif; // class_exists /** * Returns the main instance of PDF Invoices & Packing Slips for WooCommerce to prevent the need to use globals. * * @since 1.6 * @return WPO_WCPDF */ function WPO_WCPDF() { return WPO_WCPDF::instance(); } WPO_WCPDF(); // load plugin