Aktuell kannst du keine Inhaltstyp-Archive zum Navigationsblock hinzufügen. Zumindest nicht auf eine Art und Weise, dass dieser den Status erkennt, beispielsweise ob es der aktuell aktive Menüpunkt ist. Das ist ein seit Mai 2021 bekanntes Problem im Gutenberg-Projekt (siehe GitHub). Und leider sieht es nicht danach aus, als wenn es bald angepasst wird.

Als ich diese Funktionalität aber für ein individuelles Inhaltstyp-Archiv „job“ benötigte, kam ich auf eine Lösung, die die Ausgabe des Navigationsblocks verändert. Dies wird nur benötigt, um die korrekten Klassen current-menu-item und current-menu-ancestor zu setzen.

Das Skript prüft praktisch, ob die aktuelle Anfrage das Inhaltsarchiv oder eine Einzelseite des gewünschten Inhaltstyps betrifft und fügt dann die richtige Klasse zum Menüeintrag über PHPs DOMDocument hinzu. Hierbei verlass ich mich explizit auf die URL des Menüeintrags, in meinem Fall ist das /job/.

Für einen einzelnen Inhaltstypen sieht der Code demnach so aus:

/**
 * Set job archive menu item as active if needed.
 * 
 * Currently, post type archives cannot be added to the navigation block.
 * 
 * @see		https://github.com/WordPress/gutenberg/issues/31452
 * 
 * @param	string	$block_content Block content
 * @return	string Updated block content
 */
static function my_set_job_archive_active( string $block_content ): string {
	if ( ! \is_post_type_archive( 'job' ) && ! \is_singular( 'job' ) ) {
		return $block_content;
	}
	
	$libxml_use_errors = \libxml_use_internal_errors( true );
	
	$dom = new \DOMDocument();
	$dom->loadHTML(
		'<html><meta charset="utf-8">' . $block_content . '</html>',
		LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
	);
	$has_changed = false;
	
	/** @var \DOMElement $list_element */
	foreach ( $dom->getElementsByTagName( 'li' ) as $list_element ) {
		$class_name = '';
		
		// get classes of first link
		foreach ( $list_element->getElementsByTagName( 'a' ) as $child_link ) {
			$class_name = $child_link->getAttribute( 'class' );
			break;
		}
		
		// current item already has desired class
		if (
			\str_contains( $class_name, 'current-menu-item' )
			|| \str_contains( $class_name, 'current-menu-ancestor' )
		) {
			continue;
		}
		
		if ( \str_contains( $list_element->getAttribute( 'class' ), 'has-child' ) ) {
			$is_target = false;
			
			// check if a child is active
			foreach ( $list_element->getElementsByTagName( 'a' ) as $child_link ) {
				if ( \str_ends_with( $child_link->getAttribute( 'href' ), '/job/' ) ) {
					$is_target = true;
				}
			}
			
			if ( $is_target ) {
				foreach ( $list_element->getElementsByTagName( 'a' ) as $link ) {
					$link->setAttribute( 'class', \trim( $link->getAttribute( 'class' ) . ' current-menu-ancestor' ) );
					$has_changed = true;
					
					// only check the first item
					break;
				}
			}
		}
		else {
			foreach ( $list_element->getElementsByTagName( 'a' ) as $link ) {
				if ( \str_ends_with( $link->getAttribute( 'href' ), '/job/' ) ) {
					$new_class = 'current-menu-' . ( \is_singular( 'job' ) ? 'ancestor' : 'item' );
					$list_element->setAttribute( 'class', \trim( $list_element->getAttribute( 'class' ) . ' ' . $new_class ) );
					$has_changed = true;
				}
				
				// only check the first item
				break;
			}
		}
	}
	
	if ( $has_changed ) {
		$block_content = $dom->saveHTML( $dom->documentElement->firstChild->nextSibling ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
	}
	
	\libxml_use_internal_errors( $libxml_use_errors );
	
	return $block_content;
}

\add_filter( 'render_block_core/navigation', 'my_set_job_archive_active' );
Code-Sprache: PHP (php)

Um mehrere unterschiedliche Inhaltstypen zu unterstützen, führe den Code in einer Schleife für jeden Inhaltstypen aus.

Schreibe einen Kommentar

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