PluginProbe
Tiered Pricing Table for WooCommerce / 8.0.2
Tiered Pricing Table for WooCommerce v8.0.2
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
← All changes | src/Settings/Settings.php +86 -4 7.1.5 → 8.0.2 View file →
@@ -2,20 +2,22 @@
2 2
3 3 namespace TierPricingTable\Settings;
4 4
5 5 use TierPricingTable\Core\ServiceContainerTrait;
6 +use TierPricingTable\Settings\CustomOptions\TPTCheckboxListOption;
6 7 use TierPricingTable\Settings\CustomOptions\TPTDisplayType;
7 8 use TierPricingTable\Settings\CustomOptions\TPTLinkButton;
9 +use TierPricingTable\Settings\CustomOptions\TPTQuantityMeasurementField;
8 10 use TierPricingTable\Settings\CustomOptions\TPTTableColumnsField;
9 -use TierPricingTable\Settings\CustomOptions\TPTQuantityMeasurementField;
10 11 use TierPricingTable\Settings\CustomOptions\TPTFeatureFlagOption;
11 12 use TierPricingTable\Settings\CustomOptions\TPTIntegrationOption;
12 13 use TierPricingTable\Settings\CustomOptions\TPTSwitchOption;
13 14 use TierPricingTable\Settings\CustomOptions\TPTTextTemplate;
14 15 use TierPricingTable\Settings\Sections\Advanced\AdvancedSection;
15 -use TierPricingTable\Settings\Sections\CalculationLogic\CalculationLogic;
16 16 use TierPricingTable\Settings\Sections\GeneralSection\GeneralSection;
17 17 use TierPricingTable\Settings\Sections\Integrations\IntegrationSection;
18 +use TierPricingTable\Settings\Sections\Multicurrency\MulticurrencySection;
19 +use TierPricingTable\Settings\Sections\ProductAddons\ProductAddonsSection;
18 20 use TierPricingTable\Settings\Sections\SectionAbstract;
19 21 use TierPricingTable\TierPricingTablePlugin;
20 22 /**
21 23 * Class Settings
@@ -85,12 +87,13 @@
85 87 $this->getContainer()->add( 'settings.tpt_switch_option', new TPTSwitchOption() );
86 88 $this->getContainer()->add( 'settings.tpt_integration_option', new TPTIntegrationOption() );
87 89 $this->getContainer()->add( 'settings.tpt_feature_flag_option', new TPTFeatureFlagOption() );
88 90 $this->getContainer()->add( 'settings.tpt_text_template', new TPTTextTemplate() );
91 + $this->getContainer()->add( 'settings.tpt_multiple_fields', new TPTTableColumnsField() );
89 92 $this->getContainer()->add( 'settings.tpt_display_type', new TPTDisplayType() );
93 + $this->getContainer()->add( 'settings.tpt_checkbox_list', new TPTCheckboxListOption() );
90 94 $this->getContainer()->add( 'settings.tpt_link_button', new TPTLinkButton() );
91 95 $this->getContainer()->add( 'settings.tpt_quantity_measurement', new TPTQuantityMeasurementField() );
92 - $this->getContainer()->add( 'settings.tpt_multiple_fields', new TPTTableColumnsField() );
93 96 }
94 97
95 98 protected function initSections() {
96 99 }
@@ -103,17 +106,73 @@
103 106 $this->getContainer()->getCache()->purge();
104 107 }
105 108
106 109 /**
110 + * Order the settings sections deterministically: configuration first, then display, features,
111 + * feature toggles, third-party sections, and maintenance last. Without this the tab order is an
112 + * accident of hook registration, because every addon splices its section in relative to another.
113 + *
114 + * Sections with an unknown slug (third-party) keep their relative order and land before Tools.
115 + *
116 + * @param array $sections
117 + *
118 + * @return array
119 + */
120 + protected function sortSections( array $sections ) : array {
121 + $order = (array) apply_filters( 'tiered_pricing_table/settings/sections_order', array(
122 + 'general' => 10,
123 + 'shop-loop-display' => 30,
124 + 'tier-labels' => 40,
125 + 'request-a-quote' => 50,
126 + 'integrations' => 70,
127 + 'multicurrency' => 80,
128 + 'product-addons' => 90,
129 + 'advanced' => 120,
130 + ) );
131 + // Stable sort: usort() is only guaranteed stable on PHP 8+, so tie-break on the original index.
132 + $indexed = array();
133 + foreach ( array_values( $sections ) as $index => $section ) {
134 + $indexed[] = array($order[$section->getSlug()] ?? 100, $index, $section);
135 + }
136 + usort( $indexed, function ( $a, $b ) {
137 + return ( $a[0] <=> $b[0] ?: $a[1] <=> $b[1] );
138 + } );
139 + return array_column( $indexed, 2 );
140 + }
141 +
142 + /**
107 143 * Init all settings
108 144 */
109 145 public function initSettings() {
110 146 $this->sections = apply_filters( 'tiered_pricing_table/settings/sections', array(
111 147 new GeneralSection(),
112 - new CalculationLogic(),
113 148 new AdvancedSection(),
149 + new MulticurrencySection(),
150 + new ProductAddonsSection(),
114 151 new IntegrationSection()
115 152 ) );
153 + $this->sections = $this->sortSections( $this->sections );
154 + // Only on the plugin's own settings tab: other WooCommerce tabs (REST API keys, webhooks, tax,
155 + // shipping…) use the same "section" parameter and must never see it rewritten.
156 + if ( $this->isOwnSettingsTab() ) {
157 + // The "Tools" tab merged into "Advanced" in 7.2.1; old links and bookmarks keep working.
158 + if ( isset( $_GET['section'] ) && 'tools' === $_GET['section'] ) {
159 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
160 + $_GET['section'] = 'advanced';
161 + }
162 + // A removed or unknown section in the URL (old links to the "Calculations" tab, for example)
163 + // opens the default section instead of an empty page. The sections read the request directly.
164 + if ( isset( $_GET['section'] ) ) {
165 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
166 + $known = array_map( function ( $section ) {
167 + return $section->getSlug();
168 + }, $this->sections );
169 + if ( !in_array( sanitize_text_field( wp_unslash( $_GET['section'] ) ), $known, true ) ) {
170 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
171 + unset($_GET['section']);
172 + }
173 + }
174 + }
116 175 foreach ( $this->sections as $section ) {
117 176 if ( $section->isActive() ) {
118 177 $this->settings = $section->getSettings();
119 178 break;
@@ -131,9 +190,23 @@
131 190 add_action( 'woocommerce_update_options_' . self::SETTINGS_PAGE, array($this, 'updateSettings') );
132 191 add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, array($this, 'renderSections'), 99 );
133 192 }
134 193
194 + /**
195 + * Whether the request is for the plugin's own WooCommerce settings tab.
196 + */
197 + protected function isOwnSettingsTab() : bool {
198 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
199 + return is_admin() && isset( $_GET['page'], $_GET['tab'] ) && 'wc-settings' === $_GET['page'] && self::SETTINGS_PAGE === $_GET['tab'];
200 + }
201 +
135 202 public function renderSections() {
203 + // Opening a section clears its "unread" indicator (store-wide)
204 + foreach ( $this->sections as $section ) {
205 + if ( $section->isActive() ) {
206 + $section->markBadgeSeen();
207 + }
208 + }
136 209 ?>
137 210 <style>
138 211 h2 {
139 212 margin-top: 2em;
@@ -168,8 +241,17 @@
168 241 } else {
169 242 ?>
170 243 <?php
171 244 echo esc_html( $section->getName() );
245 + ?>
246 + <?php
247 + if ( $section->isBadgeUnseen() ) {
248 + ?>
249 + <span class="tpt-unread-badge" aria-hidden="true">1</span><span class="screen-reader-text"><?php
250 + esc_html_e( 'New', 'tier-pricing-table' );
251 + ?></span>
252 + <?php
253 + }
172 254 ?>
173 255 <?php
174 256 }
175 257 ?>