laipower/wp-content/plugins/activitypub/includes/class-migration.php

288 lines
7.1 KiB
PHP

<?php
namespace Activitypub;
use Activitypub\Activitypub;
use Activitypub\Model\Blog_User;
use Activitypub\Collection\Followers;
/**
* ActivityPub Migration Class
*
* @author Matthias Pfefferle
*/
class Migration {
/**
* Initialize the class, registering WordPress hooks
*/
public static function init() {
\add_action( 'activitypub_migrate', array( self::class, 'async_migration' ) );
self::maybe_migrate();
}
/**
* Get the target version.
*
* This is the version that the database structure will be updated to.
* It is the same as the plugin version.
*
* @return string The target version.
*/
public static function get_target_version() {
return get_plugin_version();
}
/**
* The current version of the database structure.
*
* @return string The current version.
*/
public static function get_version() {
return get_option( 'activitypub_db_version', 0 );
}
/**
* Locks the database migration process to prevent simultaneous migrations.
*
* @return void
*/
public static function lock() {
\update_option( 'activitypub_migration_lock', \time() );
}
/**
* Unlocks the database migration process.
*
* @return void
*/
public static function unlock() {
\delete_option( 'activitypub_migration_lock' );
}
/**
* Whether the database migration process is locked.
*
* @return boolean
*/
public static function is_locked() {
$lock = \get_option( 'activitypub_migration_lock' );
if ( ! $lock ) {
return false;
}
$lock = (int) $lock;
if ( $lock < \time() - 1800 ) {
self::unlock();
return false;
}
return true;
}
/**
* Whether the database structure is up to date.
*
* @return bool True if the database structure is up to date, false otherwise.
*/
public static function is_latest_version() {
return (bool) version_compare(
self::get_version(),
self::get_target_version(),
'=='
);
}
/**
* Updates the database structure if necessary.
*/
public static function maybe_migrate() {
if ( self::is_latest_version() ) {
return;
}
if ( self::is_locked() ) {
return;
}
self::lock();
$version_from_db = self::get_version();
// check for inital migration
if ( ! $version_from_db ) {
self::add_default_settings();
$version_from_db = self::get_target_version();
}
// schedule the async migration
if ( ! \wp_next_scheduled( 'activitypub_migrate', $version_from_db ) ) {
\wp_schedule_single_event( \time(), 'activitypub_migrate', $version_from_db );
}
if ( version_compare( $version_from_db, '0.17.0', '<' ) ) {
self::migrate_from_0_16();
}
if ( version_compare( $version_from_db, '1.3.0', '<' ) ) {
self::migrate_from_1_2_0();
}
if ( version_compare( $version_from_db, '2.1.0', '<' ) ) {
self::migrate_from_2_0_0();
}
if ( version_compare( $version_from_db, '2.3.0', '<' ) ) {
self::migrate_from_2_2_0();
}
update_option( 'activitypub_db_version', self::get_target_version() );
self::unlock();
}
/**
* Asynchronously migrates the database structure.
*
* @param string $version_from_db The version from which to migrate.
*/
public static function async_migration( $version_from_db ) {
if ( version_compare( $version_from_db, '1.0.0', '<' ) ) {
self::migrate_from_0_17();
}
}
/**
* Updates the custom template to use shortcodes instead of the deprecated templates.
*
* @return void
*/
private static function migrate_from_0_16() {
// Get the custom template.
$old_content = \get_option( 'activitypub_custom_post_content', ACTIVITYPUB_CUSTOM_POST_CONTENT );
// If the old content exists but is a blank string, we're going to need a flag to updated it even
// after setting it to the default contents.
$need_update = false;
// If the old contents is blank, use the defaults.
if ( '' === $old_content ) {
$old_content = ACTIVITYPUB_CUSTOM_POST_CONTENT;
$need_update = true;
}
// Set the new content to be the old content.
$content = $old_content;
// Convert old templates to shortcodes.
$content = \str_replace( '%title%', '[ap_title]', $content );
$content = \str_replace( '%excerpt%', '[ap_excerpt]', $content );
$content = \str_replace( '%content%', '[ap_content]', $content );
$content = \str_replace( '%permalink%', '[ap_permalink type="html"]', $content );
$content = \str_replace( '%shortlink%', '[ap_shortlink type="html"]', $content );
$content = \str_replace( '%hashtags%', '[ap_hashtags]', $content );
$content = \str_replace( '%tags%', '[ap_hashtags]', $content );
// Store the new template if required.
if ( $content !== $old_content || $need_update ) {
\update_option( 'activitypub_custom_post_content', $content );
}
}
/**
* Updates the DB-schema of the followers-list
*
* @return void
*/
public static function migrate_from_0_17() {
// migrate followers
foreach ( get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
$followers = get_user_meta( $user_id, 'activitypub_followers', true );
if ( $followers ) {
foreach ( $followers as $actor ) {
Followers::add_follower( $user_id, $actor );
}
}
}
Activitypub::flush_rewrite_rules();
}
/**
* Clear the cache after updating to 1.3.0
*
* @return void
*/
private static function migrate_from_1_2_0() {
$user_ids = \get_users(
array(
'fields' => 'ID',
'capability__in' => array( 'publish_posts' ),
)
);
foreach ( $user_ids as $user_id ) {
wp_cache_delete( sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
}
}
/**
* Unschedule Hooks after updating to 2.0.0
*
* @return void
*/
private static function migrate_from_2_0_0() {
wp_clear_scheduled_hook( 'activitypub_send_post_activity' );
wp_clear_scheduled_hook( 'activitypub_send_update_activity' );
wp_clear_scheduled_hook( 'activitypub_send_delete_activity' );
wp_unschedule_hook( 'activitypub_send_post_activity' );
wp_unschedule_hook( 'activitypub_send_update_activity' );
wp_unschedule_hook( 'activitypub_send_delete_activity' );
$object_type = \get_option( 'activitypub_object_type', ACTIVITYPUB_DEFAULT_OBJECT_TYPE );
if ( 'article' === $object_type ) {
\update_option( 'activitypub_object_type', 'wordpress-post-format' );
}
}
/**
* Add the ActivityPub capability to all users that can publish posts
* Delete old meta to store followers
*
* @return void
*/
private static function migrate_from_2_2_0() {
// add the ActivityPub capability to all users that can publish posts
self::add_activitypub_capability();
}
/**
* Set the defaults needed for the plugin to work
*
* * Add the ActivityPub capability to all users that can publish posts
*
* @return void
*/
public static function add_default_settings() {
self::add_activitypub_capability();
}
/**
* Add the ActivityPub capability to all users that can publish posts
*
* @return void
*/
private static function add_activitypub_capability() {
// get all WP_User objects that can publish posts
$users = \get_users(
array(
'capability__in' => array( 'publish_posts' ),
)
);
// add ActivityPub capability to all users that can publish posts
foreach ( $users as $user ) {
$user->add_cap( 'activitypub' );
}
}
}