initCustomOptions(); $this->hooks(); if ( !tpt_fs()->can_use_premium_code() ) { new PremiumSettingsManager(); } if ( !tpt_fs()->can_use_premium_code() ) { $template = 'upgrade-banner.php'; add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, function () use($template) { $this->getContainer()->getFileManager()->includeTemplate( 'admin/banners/' . $template, [ 'upgradeUrl' => tpt_fs_activation_url(), 'contactUsUrl' => TierPricingTablePlugin::getContactUsURL(), 'documentationUrl' => TierPricingTablePlugin::getDocumentationURL(), ] ); } ); } if ( tpt_fs()->can_use_premium_code() && !tpt_fs()->is_premium() ) { add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, function () { $this->getContainer()->getFileManager()->includeTemplate( 'admin/banners/free-version-used-premium-available.php' ); } ); } add_action( 'admin_enqueue_scripts', function () { $assetName = self::SETTINGS_PAGE . '_script'; wp_register_script( $assetName, $this->getContainer()->getFileManager()->locateJSAsset( 'admin/settings' ), array('jquery'), TierPricingTablePlugin::VERSION, true ); wp_enqueue_script( $assetName ); } ); } protected function initCustomOptions() { $this->getContainer()->add( 'settings.tpt_switch_option', new TPTSwitchOption() ); $this->getContainer()->add( 'settings.tpt_integration_option', new TPTIntegrationOption() ); $this->getContainer()->add( 'settings.tpt_feature_flag_option', new TPTFeatureFlagOption() ); $this->getContainer()->add( 'settings.tpt_text_template', new TPTTextTemplate() ); $this->getContainer()->add( 'settings.tpt_display_type', new TPTDisplayType() ); $this->getContainer()->add( 'settings.tpt_link_button', new TPTLinkButton() ); $this->getContainer()->add( 'settings.tpt_quantity_measurement', new TPTQuantityMeasurementField() ); $this->getContainer()->add( 'settings.tpt_multiple_fields', new TPTTableColumnsField() ); } protected function initSections() { } /** * Handle updating settings */ public function updateSettings() { woocommerce_update_options( $this->settings ); $this->getContainer()->getCache()->purge(); } /** * Order the settings sections deterministically: configuration first, then display, features, * feature toggles, third-party sections, and maintenance last. Without this the tab order is an * accident of hook registration, because every addon splices its section in relative to another. * * Sections with an unknown slug (third-party) keep their relative order and land before Tools. * * @param array $sections * * @return array */ protected function sortSections( array $sections ) : array { $order = (array) apply_filters( 'tiered_pricing_table/settings/sections_order', array( 'general' => 10, 'calculation_logic' => 20, 'shop-loop-display' => 30, 'tier-labels' => 40, 'request-a-quote' => 50, 'advanced' => 60, 'integrations' => 70, 'multicurrency' => 80, 'product-addons' => 90, 'tools' => 110, ) ); // Stable sort: usort() is only guaranteed stable on PHP 8+, so tie-break on the original index. $indexed = array(); foreach ( array_values( $sections ) as $index => $section ) { $indexed[] = array($order[$section->getSlug()] ?? 100, $index, $section); } usort( $indexed, function ( $a, $b ) { return ( $a[0] <=> $b[0] ?: $a[1] <=> $b[1] ); } ); return array_column( $indexed, 2 ); } /** * Init all settings */ public function initSettings() { $this->sections = apply_filters( 'tiered_pricing_table/settings/sections', array( new GeneralSection(), new CalculationLogic(), new AdvancedSection(), new MulticurrencySection(), new ProductAddonsSection(), new IntegrationSection() ) ); $this->sections = $this->sortSections( $this->sections ); foreach ( $this->sections as $section ) { if ( $section->isActive() ) { $this->settings = $section->getSettings(); break; } } } /** * Register hooks */ public function hooks() { add_action( 'init', array($this, 'initSettings') ); add_filter( 'woocommerce_settings_tabs_' . self::SETTINGS_PAGE, array($this, 'addTieredPricingTableSettings') ); add_filter( 'woocommerce_settings_tabs_array', array($this, 'addSettingsTab'), 50 ); add_action( 'woocommerce_update_options_' . self::SETTINGS_PAGE, array($this, 'updateSettings') ); add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, array($this, 'renderSections'), 99 ); } public function renderSections() { // Opening a section clears its "unread" indicator (store-wide) foreach ( $this->sections as $section ) { if ( $section->isActive() ) { $section->markBadgeSeen(); } } ?>