PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.12
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.12
1.1.12 1.1.11 1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 All 36 releases
← All changes | includes/migrations.php +128 -1 1.1.11 → 1.1.12 View file →
@@ -55,10 +55,19 @@
55 55 * separate migration from 4.
56 56 * - 6: the Trash stopped registering a desktop icon. Removes the
57 57 * placement the shell had auto-placed for it and closes the hole that
58 58 * leaves in the icon column.
59 + * - 7: seeds a face for every agent that has none.
60 + * - 8: retires automatic AI comment scoring.
61 + * - 9: repairs the Comment Concierge's misspelled ability slug in every
62 + * agent's stored allowlist.
63 + * - 10: the first-run stamps and the shell tour. On a site with prior
64 + * desktop use, records that the site was enabled before the stamps
65 + * existed (`openstation_first_enabled_at` with `at: 0, via: backfill`)
66 + * and marks the `shell-tour` intro seen for every prior user, so an
67 + * update never greets a veteran with a first-boot tour.
59 68 */
60 -const OPENSTATION_MIGRATION_VERSION = 8;
69 +const OPENSTATION_MIGRATION_VERSION = 10;
61 70
62 71 /**
63 72 * Option storing the highest migration version that has run. autoload=no.
64 73 *
@@ -163,8 +172,126 @@
163 172 }
164 173
165 174 if ( $from < 8 ) {
166 175 openstation_migrate_remove_comments_ai();
176 + }
177 +
178 + if ( $from < 9 ) {
179 + openstation_migrate_agent_ability_slugs();
180 + }
181 +
182 + if ( $from < 10 ) {
183 + openstation_migrate_first_run_stamps();
184 + }
185 +}
186 +
187 +/**
188 + * Migration 9 — repair a misspelled ability slug in stored agent
189 + * allowlists.
190 + *
191 + * The shipped Comment Concierge listed `desktop-mode/search-comments-on-post`,
192 + * an ability that was never registered: the real one is
193 + * `desktop-mode/search-comments-by-post`. The runner drops an unknown
194 + * slug without a word, so every seeded Concierge ran without the one
195 + * tool that reads a post's thread. Fixing the definition only reaches
196 + * sites that seed from now on; this rewrites the slug in place on every
197 + * agent that already stored it, whoever created the agent.
198 + *
199 + * Reads the meta directly rather than through the agents store, because
200 + * that module only loads while the Agents feature is on and an agent
201 + * row outlives the flag being turned off. The key is the frozen
202 + * `_desktop_mode_agent_abilities`; nothing is renamed.
203 + *
204 + * @return void
205 + */
206 +function openstation_migrate_agent_ability_slugs() {
207 + $meta_key = '_desktop_mode_agent_abilities';
208 + $renames = array(
209 + 'desktop-mode/search-comments-on-post' => 'desktop-mode/search-comments-by-post',
210 + );
211 +
212 + $user_ids = get_users(
213 + array(
214 + 'fields' => 'ID',
215 + 'meta_key' => $meta_key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- one-time migration; the key is indexed in usermeta and the scan is guarded to run once.
216 + 'meta_compare' => 'EXISTS',
217 + )
218 + );
219 +
220 + foreach ( $user_ids as $user_id ) {
221 + $raw = get_user_meta( (int) $user_id, $meta_key, true );
222 + $slugs = is_string( $raw ) ? json_decode( $raw, true ) : $raw;
223 + if ( ! is_array( $slugs ) ) {
224 + continue;
225 + }
226 +
227 + $changed = false;
228 + foreach ( $slugs as $i => $slug ) {
229 + if ( is_string( $slug ) && isset( $renames[ $slug ] ) ) {
230 + $slugs[ $i ] = $renames[ $slug ];
231 + $changed = true;
232 + }
233 + }
234 + if ( ! $changed ) {
235 + continue;
236 + }
237 +
238 + // Stored as a JSON string, the shape the agents store writes.
239 + // Slashed because update_user_meta() unslashes its value.
240 + update_user_meta(
241 + (int) $user_id,
242 + $meta_key,
243 + wp_slash( (string) wp_json_encode( array_values( array_unique( $slugs ) ) ) )
244 + );
245 + }
246 +}
247 +
248 +/**
249 + * Migration 10 — the first-run stamps meet an install with a past.
250 + *
251 + * Two facts about a site that already had people in the shell, neither
252 + * of which the stamps can learn on their own:
253 + *
254 + * 1. The site HAS activated. `openstation_first_enabled_at` is written
255 + * the first time a user enables from here on, so without this an
256 + * old, busy install would look like one nobody ever turned on: the
257 + * activation nudge would show to its admins, and the deactivation
258 + * funnel would read "never enabled". The stamp is recorded as
259 + * `at: 0, via: backfill` — a real moment is not known and is not
260 + * invented, and every age computation treats it as unknown.
261 + * 2. Its users have already learned the shell. The tour is for a first
262 + * boot, and the slug it records lives in the seen-intros registry,
263 + * so marking it seen for every prior user is the whole opt-out.
264 + * "Reset what's-new dialogs" brings it back for anyone curious.
265 + *
266 + * On a site with no history both loops are empty, and the runner fires
267 + * at activation, where the activation hook that stamps the real install
268 + * moment runs right after it. The install stamp is deliberately not
269 + * written here: for the in-place update it belongs to the lazy
270 + * `admin_init` backfill, which is honest about being a backfill.
271 + *
272 + * @return void
273 + */
274 +function openstation_migrate_first_run_stamps() {
275 + $prior_users = openstation_users_with_prior_desktop_use();
276 + if ( empty( $prior_users ) ) {
277 + return;
278 + }
279 +
280 + if ( null === openstation_get_first_enabled_stamp() ) {
281 + add_option(
282 + OPENSTATION_FIRST_ENABLED_AT_OPTION,
283 + array(
284 + 'at' => 0,
285 + 'via' => 'backfill',
286 + ),
287 + '',
288 + false
289 + );
290 + }
291 +
292 + foreach ( $prior_users as $user_id ) {
293 + openstation_mark_intro_seen( $user_id, OPENSTATION_SHELL_TOUR_INTRO_SLUG );
167 294 }
168 295 }
169 296
170 297 /**