PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.19
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.19
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
← All changes | includes/Services/Settings/Abstract_Section.php +40 -2 1.10.21.10.19 View file →
@@ -120,8 +120,46 @@
120 120 return self::DB_PREFIX . $this->id();
121 121 }
122 122
123 123 /**
124 + * The wp_options key the upgrade-time autoload flip must target.
125 + *
126 + * A public accessor rather than a public option_name(): Pro's License
127 + * section overrides option_name() at protected visibility (its key is
128 + * Pro-prefixed), and a child cannot narrow a public parent method — making
129 + * option_name() public fatalled every Pro site (#1846/#1849). Deriving the
130 + * key from id() instead flipped the wrong row for that section and seeded a
131 + * stray `woocommerce_pos_settings_license` (measured 2026-09-03 on dev-pro:
132 + * one query per page for the license row).
133 + *
134 + * @return string
135 + */
136 + public function autoload_option_name(): string {
137 + return $this->option_name();
138 + }
139 +
140 + /**
141 + * Whether this section's option rides in alloptions.
142 + *
143 + * Off by default: byte-compatible with the legacy save path, and most
144 + * sections are only read on POS/admin requests. A section that is read on
145 + * EVERY request (General, via the Settings service during init) overrides
146 + * this, because without an object cache a non-autoloaded option costs one
147 + * query per page load (measured 2026-09-03 on dev-next). Declaring it here
148 + * is the whole contract: write() honours it for new writes, and
149 + * Activator::autoload_request_latches() flips existing rows on upgrade and
150 + * reactivation for every registered section that returns true — core's
151 + * update_option() never flips autoload on an unchanged value, so the
152 + * writer alone cannot repair an existing row. Keep it off for sections that
153 + * can hold unbounded lists (Visibility's product ids).
154 + *
155 + * @return bool
156 + */
157 + public function autoload(): bool {
158 + return false;
159 + }
160 +
161 + /**
124 162 * Read the raw option value, coerced to array.
125 163 *
126 164 * @return array
127 165 */
@@ -168,9 +206,9 @@
168 206 * Persist a full settings array.
169 207 *
170 208 * Behaviour is byte-compatible with the legacy
171 209 * Services\Settings::save_settings(): sanitize, stamp date_modified_gmt,
172 - * apply the pre-save filter, update_option (autoload off), detect
210 + * apply the pre-save filter, update_option (autoload per {@see autoload()}), detect
173 211 * unchanged-value no-ops, fire the saved action, return the post-save
174 212 * read.
175 213 *
176 214 * @param array $settings The full settings array to persist.
@@ -198,9 +236,9 @@
198 236 $settings = apply_filters( "woocommerce_pos_pre_save_{$this->id()}_settings", $settings, $this->id() );
199 237
200 238 $option_name = $this->option_name();
201 239 $previous_value = get_option( $option_name, null );
202 - $success = update_option( $option_name, $settings, false );
240 + $success = update_option( $option_name, $settings, $this->autoload() );
203 241
204 242 if ( ! $success ) {
205 243 // update_option() returns false both when the value is unchanged (no DB
206 244 // write) and on actual failure. Use the value read *before* the write