PluginProbe
ActivityPub / 3.2.2
ActivityPub v3.2.2
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / class-migration.php

class-migration.php in ActivityPub 3.2.2, at includes/class-migration.php

341 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Activitypub;
3
4 use Activitypub\Activitypub;
5 use Activitypub\Model\Blog;
6 use Activitypub\Collection\Followers;
7
8 /**
9 * ActivityPub Migration Class
10 *
11 * @author Matthias Pfefferle
12 */
13 class Migration {
14 /**
15 * Initialize the class, registering WordPress hooks
16 */
17 public static function init() {
18 \add_action( 'activitypub_migrate', array( self::class, 'async_migration' ) );
19
20 self::maybe_migrate();
21 }
22
23 /**
24 * Get the target version.
25 *
26 * This is the version that the database structure will be updated to.
27 * It is the same as the plugin version.
28 *
29 * @return string The target version.
30 */
31 public static function get_target_version() {
32 return get_plugin_version();
33 }
34
35 /**
36 * The current version of the database structure.
37 *
38 * @return string The current version.
39 */
40 public static function get_version() {
41 return get_option( 'activitypub_db_version', 0 );
42 }
43
44 /**
45 * Locks the database migration process to prevent simultaneous migrations.
46 *
47 * @return void
48 */
49 public static function lock() {
50 \update_option( 'activitypub_migration_lock', \time() );
51 }
52
53 /**
54 * Unlocks the database migration process.
55 *
56 * @return void
57 */
58 public static function unlock() {
59 \delete_option( 'activitypub_migration_lock' );
60 }
61
62 /**
63 * Whether the database migration process is locked.
64 *
65 * @return boolean
66 */
67 public static function is_locked() {
68 $lock = \get_option( 'activitypub_migration_lock' );
69
70 if ( ! $lock ) {
71 return false;
72 }
73
74 $lock = (int) $lock;
75
76 if ( $lock < \time() - 1800 ) {
77 self::unlock();
78 return false;
79 }
80
81 return true;
82 }
83
84 /**
85 * Whether the database structure is up to date.
86 *
87 * @return bool True if the database structure is up to date, false otherwise.
88 */
89 public static function is_latest_version() {
90 return (bool) version_compare(
91 self::get_version(),
92 self::get_target_version(),
93 '=='
94 );
95 }
96
97 /**
98 * Updates the database structure if necessary.
99 */
100 public static function maybe_migrate() {
101 if ( self::is_latest_version() ) {
102 return;
103 }
104
105 if ( self::is_locked() ) {
106 return;
107 }
108
109 self::lock();
110
111 $version_from_db = self::get_version();
112
113 // check for inital migration
114 if ( ! $version_from_db ) {
115 self::add_default_settings();
116 $version_from_db = self::get_target_version();
117 }
118
119 // schedule the async migration
120 if ( ! \wp_next_scheduled( 'activitypub_migrate', $version_from_db ) ) {
121 \wp_schedule_single_event( \time(), 'activitypub_migrate', array( $version_from_db ) );
122 }
123 if ( version_compare( $version_from_db, '0.17.0', '<' ) ) {
124 self::migrate_from_0_16();
125 }
126 if ( version_compare( $version_from_db, '1.3.0', '<' ) ) {
127 self::migrate_from_1_2_0();
128 }
129 if ( version_compare( $version_from_db, '2.1.0', '<' ) ) {
130 self::migrate_from_2_0_0();
131 }
132 if ( version_compare( $version_from_db, '2.3.0', '<' ) ) {
133 self::migrate_from_2_2_0();
134 }
135 if ( version_compare( $version_from_db, '3.0.0', '<' ) ) {
136 self::migrate_from_2_6_0();
137 }
138
139 update_option( 'activitypub_db_version', self::get_target_version() );
140
141 self::unlock();
142 }
143
144 /**
145 * Asynchronously migrates the database structure.
146 *
147 * @param string $version_from_db The version from which to migrate.
148 */
149 public static function async_migration( $version_from_db ) {
150 if ( version_compare( $version_from_db, '1.0.0', '<' ) ) {
151 self::migrate_from_0_17();
152 }
153 }
154
155 /**
156 * Updates the custom template to use shortcodes instead of the deprecated templates.
157 *
158 * @return void
159 */
160 private static function migrate_from_0_16() {
161 // Get the custom template.
162 $old_content = \get_option( 'activitypub_custom_post_content', ACTIVITYPUB_CUSTOM_POST_CONTENT );
163
164 // If the old content exists but is a blank string, we're going to need a flag to updated it even
165 // after setting it to the default contents.
166 $need_update = false;
167
168 // If the old contents is blank, use the defaults.
169 if ( '' === $old_content ) {
170 $old_content = ACTIVITYPUB_CUSTOM_POST_CONTENT;
171 $need_update = true;
172 }
173
174 // Set the new content to be the old content.
175 $content = $old_content;
176
177 // Convert old templates to shortcodes.
178 $content = \str_replace( '%title%', '[ap_title]', $content );
179 $content = \str_replace( '%excerpt%', '[ap_excerpt]', $content );
180 $content = \str_replace( '%content%', '[ap_content]', $content );
181 $content = \str_replace( '%permalink%', '[ap_permalink type="html"]', $content );
182 $content = \str_replace( '%shortlink%', '[ap_shortlink type="html"]', $content );
183 $content = \str_replace( '%hashtags%', '[ap_hashtags]', $content );
184 $content = \str_replace( '%tags%', '[ap_hashtags]', $content );
185
186 // Store the new template if required.
187 if ( $content !== $old_content || $need_update ) {
188 \update_option( 'activitypub_custom_post_content', $content );
189 }
190 }
191
192 /**
193 * Updates the DB-schema of the followers-list
194 *
195 * @return void
196 */
197 public static function migrate_from_0_17() {
198 // migrate followers
199 foreach ( get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
200 $followers = get_user_meta( $user_id, 'activitypub_followers', true );
201
202 if ( $followers ) {
203 foreach ( $followers as $actor ) {
204 Followers::add_follower( $user_id, $actor );
205 }
206 }
207 }
208
209 Activitypub::flush_rewrite_rules();
210 }
211
212 /**
213 * Clear the cache after updating to 1.3.0
214 *
215 * @return void
216 */
217 private static function migrate_from_1_2_0() {
218 $user_ids = \get_users(
219 array(
220 'fields' => 'ID',
221 'capability__in' => array( 'publish_posts' ),
222 )
223 );
224
225 foreach ( $user_ids as $user_id ) {
226 wp_cache_delete( sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
227 }
228 }
229
230 /**
231 * Unschedule Hooks after updating to 2.0.0
232 *
233 * @return void
234 */
235 private static function migrate_from_2_0_0() {
236 wp_clear_scheduled_hook( 'activitypub_send_post_activity' );
237 wp_clear_scheduled_hook( 'activitypub_send_update_activity' );
238 wp_clear_scheduled_hook( 'activitypub_send_delete_activity' );
239
240 wp_unschedule_hook( 'activitypub_send_post_activity' );
241 wp_unschedule_hook( 'activitypub_send_update_activity' );
242 wp_unschedule_hook( 'activitypub_send_delete_activity' );
243
244 $object_type = \get_option( 'activitypub_object_type', ACTIVITYPUB_DEFAULT_OBJECT_TYPE );
245 if ( 'article' === $object_type ) {
246 \update_option( 'activitypub_object_type', 'wordpress-post-format' );
247 }
248 }
249
250 /**
251 * Add the ActivityPub capability to all users that can publish posts
252 * Delete old meta to store followers
253 *
254 * @return void
255 */
256 private static function migrate_from_2_2_0() {
257 // add the ActivityPub capability to all users that can publish posts
258 self::add_activitypub_capability();
259 }
260
261 /**
262 * Rename DB fields
263 *
264 * @return void
265 */
266 private static function migrate_from_2_6_0() {
267 wp_cache_flush();
268
269 self::update_usermeta_key( 'activitypub_user_description', 'activitypub_description' );
270
271 self::update_options_key( 'activitypub_blog_user_description', 'activitypub_blog_description' );
272 self::update_options_key( 'activitypub_blog_user_identifier', 'activitypub_blog_identifier' );
273 }
274
275 /**
276 * Set the defaults needed for the plugin to work
277 *
278 * * Add the ActivityPub capability to all users that can publish posts
279 *
280 * @return void
281 */
282 public static function add_default_settings() {
283 self::add_activitypub_capability();
284 }
285
286 /**
287 * Add the ActivityPub capability to all users that can publish posts
288 *
289 * @return void
290 */
291 private static function add_activitypub_capability() {
292 // get all WP_User objects that can publish posts
293 $users = \get_users(
294 array(
295 'capability__in' => array( 'publish_posts' ),
296 )
297 );
298
299 // add ActivityPub capability to all users that can publish posts
300 foreach ( $users as $user ) {
301 $user->add_cap( 'activitypub' );
302 }
303 }
304
305 /**
306 * Rename meta keys.
307 *
308 * @param string $old The old commentmeta key
309 * @param string $new The new commentmeta key
310 */
311 private static function update_usermeta_key( $old, $new ) { // phpcs:ignore
312 global $wpdb;
313
314 $wpdb->update( // phpcs:ignore
315 $wpdb->usermeta,
316 array( 'meta_key' => $new ), // phpcs:ignore
317 array( 'meta_key' => $old ), // phpcs:ignore
318 array( '%s' ),
319 array( '%s' )
320 );
321 }
322
323 /**
324 * Rename option keys.
325 *
326 * @param string $old The old option key
327 * @param string $new The new option key
328 */
329 private static function update_options_key( $old, $new ) { // phpcs:ignore
330 global $wpdb;
331
332 $wpdb->update( // phpcs:ignore
333 $wpdb->options,
334 array( 'option_name' => $new ), // phpcs:ignore
335 array( 'option_name' => $old ), // phpcs:ignore
336 array( '%s' ),
337 array( '%s' )
338 );
339 }
340 }
341