PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.8
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.8
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 0.8.8 0.8.7 All 34 releases
desktop-mode / includes / migrations.php

migrations.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.8, at includes/migrations.php

211 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Desktop Mode — one-time data migrations.
4 *
5 * A tiny, option-versioned migration runner modeled on the lazy schema
6 * installer in `includes/desktop-files/schema.php`: a stored option holds
7 * the highest migration version that has run; on every admin load we
8 * compare it against {@see DESKTOP_MODE_MIGRATION_VERSION} and run any
9 * pending migrations exactly once. Guarded so it is a cheap no-op after
10 * the first successful pass.
11 *
12 * @package WPDesktopMode
13 */
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * Highest migration version shipped by the plugin.
19 *
20 * Bump this (and add a matching branch in
21 * {@see desktop_mode_run_pending_migrations}) whenever a new one-time
22 * migration is needed.
23 *
24 * - 1: native list windows flipped from opt-out (default ON) to opt-in
25 * Beta (default OFF). Clears the five `native*Enabled` flags from every
26 * user who had them persisted so the whole install reverts to opt-in.
27 * - 2: post & taxonomy-term AI analysis was removed (the copilot now only
28 * analyzes comments for spam, and the assistant finds content via native
29 * WordPress search). Unschedules any queued `desktop_mode_ai_analyze_post`
30 * / `desktop_mode_ai_analyze_term` cron events left over from prior versions.
31 * - 3: the copilot dropped its self-managed AI credentials in favour of
32 * WordPress 7.0 Connectors. Deletes the platform key option and strips the
33 * per-user `apiKey` / `apiKeys` / `provider` / `transport` fields from the
34 * stored OS settings so no provider secret lingers in the database.
35 */
36 const DESKTOP_MODE_MIGRATION_VERSION = 3;
37
38 /** Option storing the highest migration version that has run. autoload=no. */
39 const DESKTOP_MODE_MIGRATION_OPTION = 'desktop_mode_migration_version';
40
41 /**
42 * Runs any pending migrations, then records the new high-water mark.
43 *
44 * Idempotent: bails immediately when the stored version is already at
45 * or above the shipped version, so it is safe to fire on every request.
46 *
47 * @return void
48 */
49 function desktop_mode_maybe_run_migrations() {
50 $installed = (int) get_option( DESKTOP_MODE_MIGRATION_OPTION, 0 );
51 if ( $installed >= DESKTOP_MODE_MIGRATION_VERSION ) {
52 return;
53 }
54
55 desktop_mode_run_pending_migrations( $installed );
56
57 update_option( DESKTOP_MODE_MIGRATION_OPTION, DESKTOP_MODE_MIGRATION_VERSION, false );
58 }
59 add_action( 'admin_init', 'desktop_mode_maybe_run_migrations' );
60
61 /**
62 * Dispatches each migration whose version is newer than what has run.
63 *
64 * @param int $from The highest migration version already applied.
65 * @return void
66 */
67 function desktop_mode_run_pending_migrations( $from ) {
68 $from = (int) $from;
69
70 if ( $from < 1 ) {
71 desktop_mode_migrate_os_settings_optin();
72 }
73
74 if ( $from < 2 ) {
75 desktop_mode_migrate_unschedule_post_term_ai();
76 }
77
78 if ( $from < 3 ) {
79 desktop_mode_migrate_delete_ai_keys();
80 }
81 }
82
83 /**
84 * Migration 1 — reset the native list windows to opt-in.
85 *
86 * The native Posts/Pages/Users/Plugins/Comments windows used to default
87 * ON (opt-out). The shell persists the whole OS-settings object on every
88 * change, so most active users already have these flags stored as `true`
89 * and would keep the native UI even after the default flips. This clears
90 * the five flags from every user who has the meta, leaving the rest of
91 * their settings (wallpaper, accent, dock order, …) untouched. On the
92 * next read the cleared keys fall back to the new `false` default, so the
93 * whole install lands on opt-in and users re-enable each window from
94 * OS Settings → Features → Beta features.
95 *
96 * Only users who actually have the meta are queried — fresh accounts and
97 * users who never touched OS Settings are skipped entirely.
98 *
99 * @return void
100 */
101 function desktop_mode_migrate_os_settings_optin() {
102 $flags = array(
103 'nativePostsEnabled',
104 'nativePagesEnabled',
105 'nativeUsersEnabled',
106 'nativePluginsEnabled',
107 'nativeCommentsEnabled',
108 );
109
110 $user_ids = get_users(
111 array(
112 'fields' => 'ID',
113 'meta_key' => DESKTOP_MODE_OS_SETTINGS_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.
114 'meta_compare' => 'EXISTS',
115 )
116 );
117
118 foreach ( $user_ids as $user_id ) {
119 $raw = get_user_meta( (int) $user_id, DESKTOP_MODE_OS_SETTINGS_META_KEY, true );
120 if ( ! is_array( $raw ) ) {
121 continue;
122 }
123
124 $changed = false;
125 foreach ( $flags as $flag ) {
126 if ( array_key_exists( $flag, $raw ) ) {
127 unset( $raw[ $flag ] );
128 $changed = true;
129 }
130 }
131
132 if ( ! $changed ) {
133 continue;
134 }
135
136 // Re-save through the canonical sanitizer so the cleared flags are
137 // backfilled with the new `false` default and the rest of the
138 // settings array is normalized exactly as a client write would be.
139 desktop_mode_save_os_settings( (int) $user_id, $raw );
140 }
141 }
142
143 /**
144 * Migration 2 — unschedule leftover post/term AI analysis jobs.
145 *
146 * Post and taxonomy-term analysis was removed: the copilot now only
147 * analyzes comments (for the spam score), and the AI assistant finds
148 * content with native WordPress keyword search. Their cron callbacks no
149 * longer exist, so any single-events still queued from a prior version
150 * would simply no-op — but we clear them so the cron array stays tidy and
151 * `wp cron event list` doesn't show orphaned hooks.
152 *
153 * Existing `_desktop_mode_ai_analysis` meta on posts/terms is left in place
154 * (hidden, harmless, and cheap to ignore).
155 *
156 * @return void
157 */
158 function desktop_mode_migrate_unschedule_post_term_ai() {
159 wp_unschedule_hook( 'desktop_mode_ai_analyze_post' );
160 wp_unschedule_hook( 'desktop_mode_ai_analyze_term' );
161 }
162
163 /**
164 * Migration 3 — delete self-managed AI credentials.
165 *
166 * WordPress 7.0 owns provider credentials (Settings → Connectors), so the
167 * copilot no longer stores keys of its own. Remove the platform key option and
168 * strip the now-unused key / provider / model / transport fields from every
169 * user's stored OS settings so no secret is left behind. The only `ai` field
170 * that remains is `enabled` (the per-user assistant toggle), backfilled from
171 * defaults on next read.
172 *
173 * @return void
174 */
175 function desktop_mode_migrate_delete_ai_keys() {
176 // Platform-wide key option (formerly `desktop_mode_ai_platform`).
177 delete_option( 'desktop_mode_ai_platform' );
178
179 $user_ids = get_users(
180 array(
181 'fields' => 'ID',
182 'meta_key' => DESKTOP_MODE_OS_SETTINGS_META_KEY, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- one-time migration; guarded to run once.
183 'meta_compare' => 'EXISTS',
184 )
185 );
186
187 foreach ( $user_ids as $user_id ) {
188 $raw = get_user_meta( (int) $user_id, DESKTOP_MODE_OS_SETTINGS_META_KEY, true );
189 if ( ! is_array( $raw ) || ! isset( $raw['ai'] ) || ! is_array( $raw['ai'] ) ) {
190 continue;
191 }
192
193 // Strip every legacy AI field: the self-managed credentials/transport,
194 // plus the `provider` / `model` preferences — provider + model selection
195 // is now delegated entirely to the Core AI Client.
196 $changed = false;
197 foreach ( array( 'apiKey', 'apiKeys', 'transport', 'provider', 'model' ) as $stale ) {
198 if ( array_key_exists( $stale, $raw['ai'] ) ) {
199 unset( $raw['ai'][ $stale ] );
200 $changed = true;
201 }
202 }
203
204 if ( ! $changed ) {
205 continue;
206 }
207
208 desktop_mode_save_os_settings( (int) $user_id, $raw );
209 }
210 }
211