Es gibt viele Gründe, warum Blockattribute geändert werden müssen. Vielleicht, weil sich die Anforderungen geändert haben, oder weil man von vornherein nicht daran gedacht hat. Dieser Leitfaden zeigt dir, wie du Block-Attribute von bestehenden Blöcken migrierst.

Einführung

Es gibt viele Gründe, warum Block-Attribute geändert werden müssen. Vielleicht, weil sich die Anforderungen geändert haben, oder weil man von vornherein nicht daran gedacht hat. Dieser Leitfaden zeigt dir, wie du Block-Attribute von bestehenden Blöcken migrierst.
Einführung

Block-Attribute speichern die Konfiguration für eine bestimmte Block-Instanz im Block-Editor. Sie werden direkt am Beitrag und innerhalb des Beitrags-Inhaltsfelds in der Datenbank gespeichert. Ein Ersetzen über MySQL ist zwar möglich (je nach Anwendungsfall), wird aber nicht empfohlen.

In meinem Fall ist das Attribut ein Breakpoint für einen bestimmten Block, der von einer Ganzzahl in eine Zeichenfolge geändert werden muss, um das Attributfeld von einem normalen Zahleneingabefeld in ein erweitertes Unit Control zu ändern. Dies speichert dann den Wert, z.B. 768, als 768px.

Hinweis: Diese Umstellung funktioniert nur bei Block-Attributen, für die weder ein selector noch eine source definiert ist, da diese Werte anders behandelt werden (sie sind direkt Teil des HTML des Blocks).

Dieser Artikel behandelt auch nur den eigentlichen Migrationsprozess der bestehenden Attribut-Werte in der Datenbank, nicht den React-Teil zum Ändern der Attribute und Steuerelemente oder die Migration in deinen Block. Letzteres sollte nach Ausführung der untenstehenden Migration nicht mehr erforderlich sein.

Das Skript

Mein Skript ist so aufgebaut, dass es über WP-CLI als eval-script ausgeführt werden kann, was die Ausführung jedes PHP-Skripts eines Drittanbieters im Kontext der WordPress-Instanz ermöglicht. Und da ich es innerhalb einer Multisite ausführe, iteriere ich über jede Website.

Die eigentliche Aufgabe besteht darin, alle Beiträge (in meinem Fall Seiten, Beiträge und synchronisierte Vorlagen) abzurufen und den Block-Inhalt in ein assoziatives Array mit Blöcken zu parsen. Auf diese Weise können alle Attribute über PHP bearbeitet werden. Dann ändere ich die Werte meiner Attribute entsprechend meiner Anforderungen. Da ich die Blöcke zuvor als Array geparst habe, muss ich sie wieder in eine Zeichenfolge umwandeln, um den geänderten Wert erneut zu aktualisieren. Dafür ist serialize_blocks da.

Das Skript läuft in einer Schleife, wobei in jeder Iteration 5 Beiträge verarbeitet werden, um den Speicherverbrauch gering zu halten.

Danach macht es dasselbe mit den Block-Widgets. Dies ist jedoch weniger komplex, da sich alle Widget-Blöcke innerhalb einer einzigen Option widget_block befinden, so dass hier keine Schleife erforderlich ist.

Der Code

<?php
$posts_args = [
	'ignore_sticky_posts' => true,
	'no_found_rows' => true,
	'offset' => 0,
	'post_type' => [
		'page',
		'post',
		'wp_block',
	],
	'update_post_meta_cache' => false,
	'update_post_term_cache' => false,
];
$sites = \get_sites( [
	'fields' => 'ids',
	'number' => 1000000,
] );

foreach ( $sites as $site_id ) {
	\switch_to_blog( $site_id );
	
	echo 'Processing ' . \home_url() . PHP_EOL;
	
	$posts_args['offset'] = 0;
	$_posts = \get_posts( $posts_args );
	
	while ( \count( $_posts ) ) {
		foreach ( $_posts as $_post ) {
			if ( ! \has_block( 'core/columns', $_post->ID ) ) {
				continue;
			}
			
			$blocks = \parse_blocks( $_post->post_content );
			$updated_blocks = migrate_column_attributes( $blocks, $_post->post_name );
			
			if ( $blocks !== $updated_blocks ) {
				$_post->post_content = \serialize_blocks( $updated_blocks );
				
				\wp_update_post( $_post );
			}
		}
		$posts_args['offset'] += 5;
		$_posts = \get_posts( $posts_args );
	}
	
	$widgets = \get_option( 'widget_block' );
	$has_changed_widgets = false;
	
	foreach ( $widgets as $widget_id => $widget ) {
		if ( \is_int( $widget ) ) {
			continue;
		}
		
		$blocks = \parse_blocks( $widget['content'] );
		$updated_blocks = rh_migrate_column_attributes( $blocks, 'widget ' . $widget_id );
		
		if ( $blocks !== $updated_blocks ) {
			$has_changed_widgets = true;
			$widgets[ $widget_id ]['content'] = \serialize_blocks( $updated_blocks );
		}
	}
	
	if ( $has_changed_widgets ) {
		\update_option( 'widget_block', $widgets );
	}
	
	\restore_current_blog();
}

function migrate_column_attributes( array $blocks, string $identifier ): array {
	foreach ( $blocks as &$block ) {
		if ( ! empty( $block['innerBlocks'] ) ) {
			$block['innerBlocks'] = rh_migrate_column_attributes( $block['innerBlocks'], $identifier );
		}
		
		if ( empty( $block['blockName'] ) || $block['blockName'] !== 'core/columns' ) {
			continue;
		}
		
		$old = [
			'default' => null,
			'large' => null,
		];
		
		if ( ! empty( $block['attrs']['breakpoint'] ) && \is_int( $block['attrs']['breakpoint'] ) ) {
			$old['default'] = $block['attrs']['breakpoint'];
			$block['attrs']['breakpoint'] = (string) $block['attrs']['breakpoint'];
		}
		
		if ( ! empty( $block['attrs']['breakpointLarge'] ) && \is_int( $block['attrs']['breakpointLarge'] ) ) {
			$old['large'] = $block['attrs']['breakpointLarge'];
			$block['attrs']['breakpointLarge'] = (string) $block['attrs']['breakpointLarge'];
		}
		
		if ( ! empty( $old['default'] ) || ! empty( $default['large'] ) ) {
			echo \home_url() . ' - Migrated ' . $identifier . ': ' . ( ! empty( $old['default'] ) ? 'default ' . $old['default'] . '/"' . $block['attrs']['breakpoint'] . '"; ' : '' ) . ( ! empty( $old['large'] ) ? 'large ' . $old['large'] . '/"' . $block['attrs']['breakpointLarge'] . '"' : '' ) . PHP_EOL;
		}
	}
	
	return $blocks;
}

Code-Sprache: PHP (php)

Anschließend werden alle Attribute in die Datenbank migriert und du kannst deinen aktualisierten React-Code (falls erforderlich) ins Produktivsystem übertragen. Da die Aktualisierung die eingebauten WordPress-Core-Funktionen verwendet, wird die Aktualisierung der Caches usw. bereits automatisch durchgeführt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert