query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- einmalige Umbenennung. $wpdb->prepare( "UPDATE IGNORE {$wpdb->options} SET option_name = CONCAT( %s, SUBSTRING( option_name, %d ) ) WHERE option_name LIKE %s", $new, strlen( $old ) + 1, $wpdb->esc_like( $old ) . '%' ) ); if ( false === $renamed ) { $ok = false; continue; } $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- einmalige Umbenennung. $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", $wpdb->esc_like( $old ) . '%' ) ); } $renamed = $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- einmalige Umbenennung. $wpdb->prepare( "UPDATE {$wpdb->usermeta} SET meta_key = CONCAT( %s, SUBSTRING( meta_key, %d ) ) WHERE meta_key LIKE %s", self::NEW_PREFIX, strlen( self::OLD_PREFIX ) + 1, $wpdb->esc_like( self::OLD_PREFIX ) . '%' ) ); if ( false === $renamed ) { $ok = false; } $renamed = $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- einmalige Umbenennung. $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_key = CONCAT( %s, SUBSTRING( meta_key, %d ) ) WHERE meta_key LIKE %s", self::NEW_PREFIX, strlen( self::OLD_PREFIX ) + 1, $wpdb->esc_like( self::OLD_PREFIX ) . '%' ) ); if ( false === $renamed ) { $ok = false; } if ( ! self::migrate_cron() ) { $ok = false; } wp_cache_delete( 'alloptions', 'options' ); wp_cache_delete( 'notoptions', 'options' ); // Metadaten wurden per SQL umbenannt -- ein persistenter Object-Cache // (Redis, Memcached) lieferte sonst weiter die alten Schluessel aus. wp_cache_flush(); // Erledigt ist die Umstellung erst, wenn jeder Schritt geklappt hat. // Sonst naechster Versuch in einer Stunde; was schon umbenannt ist, // findet der nicht mehr und laesst es in Ruhe. if ( $ok ) { update_option( self::DONE_OPTION, 1, true ); } else { set_transient( self::RETRY_TRANSIENT, 1, HOUR_IN_SECONDS ); } } /** * Geplante Ereignisse unter neuem Namen mit gleichem Takt einplanen und den * alten erst danach abmelden -- scheitert das Einplanen, bleibt der alte * Termin stehen, statt dass ein Zeitplan verloren geht. * * @return bool Ob alle Ereignisse umgezogen sind. */ private static function migrate_cron() { $crons = _get_cron_array(); if ( ! is_array( $crons ) ) { return true; } $ok = true; foreach ( $crons as $timestamp => $hooks ) { foreach ( $hooks as $hook => $events ) { if ( 0 !== strpos( $hook, self::OLD_PREFIX ) ) { continue; } $new_hook = self::NEW_PREFIX . substr( $hook, strlen( self::OLD_PREFIX ) ); foreach ( $events as $event ) { $scheduled = (bool) wp_next_scheduled( $new_hook, $event['args'] ); if ( ! $scheduled ) { $result = empty( $event['schedule'] ) ? wp_schedule_single_event( $timestamp, $new_hook, $event['args'] ) : wp_schedule_event( $timestamp, $event['schedule'], $new_hook, $event['args'] ); $scheduled = true === $result; } if ( ! $scheduled ) { $ok = false; continue; } wp_unschedule_event( $timestamp, $hook, $event['args'] ); } } } return $ok; } }