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 +115 -39 6.1.0 → 8.0.2 View file →
@@ -2,19 +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;
11 +use TierPricingTable\Settings\CustomOptions\TPTFeatureFlagOption;
10 12 use TierPricingTable\Settings\CustomOptions\TPTIntegrationOption;
11 13 use TierPricingTable\Settings\CustomOptions\TPTSwitchOption;
12 14 use TierPricingTable\Settings\CustomOptions\TPTTextTemplate;
13 15 use TierPricingTable\Settings\Sections\Advanced\AdvancedSection;
14 -use TierPricingTable\Settings\Sections\CalculationLogic\CalculationLogic;
15 16 use TierPricingTable\Settings\Sections\GeneralSection\GeneralSection;
16 17 use TierPricingTable\Settings\Sections\Integrations\IntegrationSection;
18 +use TierPricingTable\Settings\Sections\Multicurrency\MulticurrencySection;
19 +use TierPricingTable\Settings\Sections\ProductAddons\ProductAddonsSection;
17 20 use TierPricingTable\Settings\Sections\SectionAbstract;
18 21 use TierPricingTable\TierPricingTablePlugin;
19 22 /**
20 23 * Class Settings
@@ -55,10 +58,11 @@
55 58 if ( !tpt_fs()->can_use_premium_code() ) {
56 59 $template = 'upgrade-banner.php';
57 60 add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, function () use($template) {
58 61 $this->getContainer()->getFileManager()->includeTemplate( 'admin/banners/' . $template, [
59 - 'upgradeUrl' => tpt_fs_activation_url(),
60 - 'contactUsUrl' => TierPricingTablePlugin::getContactUsURL(),
62 + 'upgradeUrl' => tpt_fs_activation_url(),
63 + 'contactUsUrl' => TierPricingTablePlugin::getContactUsURL(),
64 + 'documentationUrl' => TierPricingTablePlugin::getDocumentationURL(),
61 65 ] );
62 66 } );
63 67 }
64 68 if ( tpt_fs()->can_use_premium_code() && !tpt_fs()->is_premium() ) {
@@ -65,18 +69,31 @@
65 69 add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, function () {
66 70 $this->getContainer()->getFileManager()->includeTemplate( 'admin/banners/free-version-used-premium-available.php' );
67 71 } );
68 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 + } );
69 84 }
70 85
71 86 protected function initCustomOptions() {
72 87 $this->getContainer()->add( 'settings.tpt_switch_option', new TPTSwitchOption() );
73 88 $this->getContainer()->add( 'settings.tpt_integration_option', new TPTIntegrationOption() );
89 + $this->getContainer()->add( 'settings.tpt_feature_flag_option', new TPTFeatureFlagOption() );
74 90 $this->getContainer()->add( 'settings.tpt_text_template', new TPTTextTemplate() );
91 + $this->getContainer()->add( 'settings.tpt_multiple_fields', new TPTTableColumnsField() );
75 92 $this->getContainer()->add( 'settings.tpt_display_type', new TPTDisplayType() );
93 + $this->getContainer()->add( 'settings.tpt_checkbox_list', new TPTCheckboxListOption() );
76 94 $this->getContainer()->add( 'settings.tpt_link_button', new TPTLinkButton() );
77 95 $this->getContainer()->add( 'settings.tpt_quantity_measurement', new TPTQuantityMeasurementField() );
78 - $this->getContainer()->add( 'settings.tpt_multiple_fields', new TPTTableColumnsField() );
79 96 }
80 97
81 98 protected function initSections() {
82 99 }
@@ -89,17 +106,73 @@
89 106 $this->getContainer()->getCache()->purge();
90 107 }
91 108
92 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 + /**
93 143 * Init all settings
94 144 */
95 145 public function initSettings() {
96 146 $this->sections = apply_filters( 'tiered_pricing_table/settings/sections', array(
97 147 new GeneralSection(),
98 - new CalculationLogic(),
99 148 new AdvancedSection(),
149 + new MulticurrencySection(),
150 + new ProductAddonsSection(),
100 151 new IntegrationSection()
101 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 + }
102 175 foreach ( $this->sections as $section ) {
103 176 if ( $section->isActive() ) {
104 177 $this->settings = $section->getSettings();
105 178 break;
@@ -117,9 +190,23 @@
117 190 add_action( 'woocommerce_update_options_' . self::SETTINGS_PAGE, array($this, 'updateSettings') );
118 191 add_action( 'woocommerce_settings_' . self::SETTINGS_PAGE, array($this, 'renderSections'), 99 );
119 192 }
120 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 +
121 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 + }
122 209 ?>
123 210 <style>
124 211 h2 {
125 212 margin-top: 2em;
@@ -125,12 +212,15 @@
125 212 margin-top: 2em;
126 213 font-size: 1.45em;
127 214 }
128 215 </style>
129 -
216 +
130 217 <ul class="subsubsub" style="font-size: 1.1em; margin-top: 3px">
131 218 <?php
132 - foreach ( $this->sections as $section ) {
219 + $sectionsCount = count( $this->sections );
220 + ?>
221 + <?php
222 + foreach ( $this->sections as $index => $section ) {
133 223 ?>
134 224 <li>
135 225 <?php
136 226 if ( !$section->isActive() ) {
@@ -152,8 +242,17 @@
152 242 ?>
153 243 <?php
154 244 echo esc_html( $section->getName() );
155 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 + ?>
156 255 <?php
157 256 }
158 257 ?>
159 258
@@ -160,9 +259,9 @@
160 259 </a>
161 260 <?php
162 261 } else {
163 262 ?>
164 -
263 +
165 264 <?php
166 265 if ( $section->getSectionCSS() ) {
167 266 ?>
168 267 <style>
@@ -181,36 +280,19 @@
181 280 </a>
182 281 <?php
183 282 }
184 283 ?>
185 - |
284 + <?php
285 + if ( $index < $sectionsCount - 1 ) {
286 + ?>
287 + |
288 + <?php
289 + }
290 + ?>
186 291 </li>
187 292 <?php
188 293 }
189 294 ?>
190 - <li>
191 - <a href="<?php
192 - echo esc_attr( TierPricingTablePlugin::getDocumentationURL() );
193 - ?>" target="_blank">
194 - <?php
195 - esc_html_e( 'Documentation', 'tier-pricing-table' );
196 - ?>
197 - <svg
198 - style="
199 - width: 0.8rem;
200 - height: 0.8rem;
201 - stroke: currentColor;
202 - fill: none;"
203 - xmlns='http://www.w3.org/2000/svg'
204 - stroke-width='10' stroke-dashoffset='0'
205 - stroke-dasharray='0' stroke-linecap='round'
206 - stroke-linejoin='round' viewBox='0 0 100 100'>
207 - <polyline fill="none" points="40 20 20 20 20 90 80 90 80 60"/>
208 - <polyline fill="none" points="60 10 90 10 90 40"/>
209 - <line fill="none" x1="89" y1="11" x2="50" y2="50"/>
210 - </svg>
211 - </a>
212 - </li>
213 295 </ul>
214 296 <br class="clear">
215 297 <?php
216 298 }
@@ -231,14 +313,8 @@
231 313 /**
232 314 * Add settings to WooCommerce
233 315 */
234 316 public function addTieredPricingTableSettings() {
235 - wp_enqueue_script(
236 - 'quantity-table-settings-js',
237 - $this->getContainer()->getFileManager()->locateJSAsset( 'admin/settings' ),
238 - array('jquery'),
239 - TierPricingTablePlugin::VERSION
240 - );
241 317 woocommerce_admin_fields( $this->settings );
242 318 }
243 319
244 320 /**