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 +99 -12 6.4.0 → 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
@@ -67,8 +69,19 @@
67 69 add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, function () {
68 70 $this->getContainer()->getFileManager()->includeTemplate( 'admin/banners/free-version-used-premium-available.php' );
69 71 } );
70 72 }
73 + add_action( 'admin_enqueue_scripts', function () {
74 + $assetName = self::SETTINGS_PAGE . '_script';
75 + wp_register_script(
76 + $assetName,
77 + $this->getContainer()->getFileManager()->locateJSAsset( 'admin/settings' ),
78 + array('jquery'),
79 + TierPricingTablePlugin::VERSION,
80 + true
81 + );
82 + wp_enqueue_script( $assetName );
83 + } );
71 84 }
72 85
73 86 protected function initCustomOptions() {
74 87 $this->getContainer()->add( 'settings.tpt_switch_option', new TPTSwitchOption() );
@@ -74,12 +87,13 @@
74 87 $this->getContainer()->add( 'settings.tpt_switch_option', new TPTSwitchOption() );
75 88 $this->getContainer()->add( 'settings.tpt_integration_option', new TPTIntegrationOption() );
76 89 $this->getContainer()->add( 'settings.tpt_feature_flag_option', new TPTFeatureFlagOption() );
77 90 $this->getContainer()->add( 'settings.tpt_text_template', new TPTTextTemplate() );
91 + $this->getContainer()->add( 'settings.tpt_multiple_fields', new TPTTableColumnsField() );
78 92 $this->getContainer()->add( 'settings.tpt_display_type', new TPTDisplayType() );
93 + $this->getContainer()->add( 'settings.tpt_checkbox_list', new TPTCheckboxListOption() );
79 94 $this->getContainer()->add( 'settings.tpt_link_button', new TPTLinkButton() );
80 95 $this->getContainer()->add( 'settings.tpt_quantity_measurement', new TPTQuantityMeasurementField() );
81 - $this->getContainer()->add( 'settings.tpt_multiple_fields', new TPTTableColumnsField() );
82 96 }
83 97
84 98 protected function initSections() {
85 99 }
@@ -92,17 +106,73 @@
92 106 $this->getContainer()->getCache()->purge();
93 107 }
94 108
95 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 + /**
96 143 * Init all settings
97 144 */
98 145 public function initSettings() {
99 146 $this->sections = apply_filters( 'tiered_pricing_table/settings/sections', array(
100 147 new GeneralSection(),
101 - new CalculationLogic(),
102 148 new AdvancedSection(),
149 + new MulticurrencySection(),
150 + new ProductAddonsSection(),
103 151 new IntegrationSection()
104 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 + }
105 175 foreach ( $this->sections as $section ) {
106 176 if ( $section->isActive() ) {
107 177 $this->settings = $section->getSettings();
108 178 break;
@@ -120,9 +190,23 @@
120 190 add_action( 'woocommerce_update_options_' . self::SETTINGS_PAGE, array($this, 'updateSettings') );
121 191 add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, array($this, 'renderSections'), 99 );
122 192 }
123 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 +
124 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 + }
125 209 ?>
126 210 <style>
127 211 h2 {
128 212 margin-top: 2em;
@@ -128,9 +212,9 @@
128 212 margin-top: 2em;
129 213 font-size: 1.45em;
130 214 }
131 215 </style>
132 -
216 +
133 217 <ul class="subsubsub" style="font-size: 1.1em; margin-top: 3px">
134 218 <?php
135 219 $sectionsCount = count( $this->sections );
136 220 ?>
@@ -158,8 +242,17 @@
158 242 ?>
159 243 <?php
160 244 echo esc_html( $section->getName() );
161 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 + }
254 + ?>
162 255 <?php
163 256 }
164 257 ?>
165 258
@@ -166,9 +259,9 @@
166 259 </a>
167 260 <?php
168 261 } else {
169 262 ?>
170 -
263 +
171 264 <?php
172 265 if ( $section->getSectionCSS() ) {
173 266 ?>
174 267 <style>
@@ -220,14 +313,8 @@
220 313 /**
221 314 * Add settings to WooCommerce
222 315 */
223 316 public function addTieredPricingTableSettings() {
224 - wp_enqueue_script(
225 - 'quantity-table-settings-js',
226 - $this->getContainer()->getFileManager()->locateJSAsset( 'admin/settings' ),
227 - array('jquery'),
228 - TierPricingTablePlugin::VERSION
229 - );
230 317 woocommerce_admin_fields( $this->settings );
231 318 }
232 319
233 320 /**