Neuer Check für das Theme-Check-Plugin

Die Zeiten ändern sich.

Dieser Beitrag scheint älter als 3 Jahre zu sein – eine lange Zeit im Internet. Der Inhalt ist vielleicht veraltet.

Letzte Woche habe ich ja über das Child-Theme-Check-Plugin geschrieben. Um alles aus diesem Plugin herauszuholen müsste das Parent-Theme in jeder PHP-Template-Datei (außer der functions.php) eine Versionsnummer definieren. Das geht ganz einfach mit einer Angabe im Kommentarbereich am Anfang der Datei: @version 1.0.0. Damit jedes Theme dies umsetzt, welches in das offizielle Theme-Verzeichnis aufgenommen werden möchte, habe ich einen zusätzlichen Check für das Theme-Check-Plugin gebaut und einen Pull-Request erstellt. Und so bin ich bei dem Check vorgegangen …

Das Theme-Check-Plugin lässt sich sehr einfach erweitern. Eine Veränderung des Plugins selbst ist nicht nötig. Für einen weiteren Check wird einfach eine zusätzliche Datei in den Ordner checks eingefügt, welche dann automatisch geladen wird. Als Basis habe ich mir eine andere Test-Datei genommen und einfach zu meinem Test umgebaut. Praktischerweise gab es an anderer Stelle schon einen Test der Theme-Infos aus der style.css, so dass ich die Regular Expression nur minimal abwandeln musste.

Ein Check ist dabei eine Erweiterung der themecheck-Klasse. Wurde ein Fehler gefunden, so wird er in einem Fehler-Array gespeichert:

class VersionCheck implements themecheck {
	protected $error = array();

Übergeben werden alle PHP-Dateien, alle CSS-Dateien und alle anderen Dateien des Themes. Bei einem Child-Theme sind hier auch alle Dateien des Parent-Theme enthalten.

	function check( $php_files, $css_files, $other_files ) {
		$ret = true;
		checkcount();

Als nächstes definiere ich den Check über ein Array. Sollten in Zukunft noch mehr Prüfungen in allen PHP-Dateien vorgenommen werden, kann hier einfach das Array ergänzt werden. Aktuell testet der Check einfach auf das Vorhandensein der Zeile, die mit * @version beginnt.

		$checks = array(
			'[ \t\/*#]@version' => '@version',
			);

In der foreach-Schleife gehe ich nun durch alle PHP-Dateien des Themes. Nur die functions.php ist ein Sonderfall und wird ignoriert. Die functions.php überschreibt kein Template, sondern wird zusätzlich geladen und daher macht es keinen Sinn hier einen Vergleich der Versionen vorzunehmen. Daher ignoriere ich diese Datei hier und springe mit continue in die nächste foreach-Runde.

		foreach ( $php_files as $php_key => $phpfile ) {
			// leave out functions.php as this is a special case
			if ( tc_filename( $php_key ) == 'functions.php' ) { continue; }

Innerhalb dieser foreach-Schleife starte ich wiederum eine foreach-Schleife mit allen Tests. In diesem Fall ist das zwar nur einer, aber es können ja mal mehr werden. Findet der reguläre Ausdruck nicht die geforderte Zeile, dann wird eine entsprechende Fehlermeldung in das Fehler-Array geschrieben. Mit Angabe der betroffenen Datei.

			foreach ($checks as $key => $check) {

				if ( !preg_match( '/' . $key . '/i', $file_data, $matches ) ) {
					$filename = tc_filename( $php_key );
					
					// Point out the missing line.
					$error_msg = sprintf(
						__( '%1$s is missing in the file %2$s.', 'theme-check' ),
						'<strong>' . $check . '</strong>',
						'<strong>' . $filename . '</strong>'
					);
					// Add the finalized error message.
					$this->error[] = '<span class="tc-lead tc-recommended">' . __('RECOMMENDED','theme-check') . '</span>: ' . $error_msg;
						
				}
			}
		}
		return $ret;
	}
	function getError() { return $this->error; }
}
$themechecks[] = new VersionCheck;

Leider klappte das alles trotzdem nicht. 🙁 Also ab auf die Fehlersuche!

Fehlersuche

Problem Nummer 1 war folgende Zeile in der main.php vom Theme-Check-Plugin:

$php[$filename] = tc_strip_comments( $php[$filename] );

Alle Kommentare werden also entfernt. Dumm nur, wenn ich testen möchte, ob eine Kommentarzeile mit einem bestimmten Inhalt existiert. Da der Pfad zur Datei ja in dem Array-Key steht, kann ich aber die Datei selber nochmal auslesen (so wie das der Child-Theme-Check auch macht):

				// We don't need to write to the file, so just open for reading.
				// This is needed, because comments are stripped out in the main plugin
				$fp = fopen( $php_key, 'r' );
				// Pull only the first 8kiB of the file in.
				$file_data = fread( $fp, 8192 );
				// PHP will close file handle, but we are good citizens.
				fclose( $fp );
				// Make sure we catch CR-only line endings.
				$file_data = str_replace( "\r", "\n", $file_data );

Heureka! Geschafft!

Jetzt funktionierte der Check. Aber es gab noch ein weiteres Problem. Wenn ein Child-Theme getestet wird, dann gab der Check den Dateinamen aus. Aber so weiß ich nicht, ob der Fehler nun im Parent- oder Child-Theme war. Also ersetzte ich die Zeile:

$filename = tc_filename( $php_key );

durch folgende Zeile:

$filename = self::tc_templatepath( $php_key );

Und definierte noch die passende Funktion, bei der ich die Regular Expression so abänderte, dass der Theme-Name mit ausgegeben wird. Auch hier klappe der erste Anlauf nicht. Hier der erste Entwurf:

	function tc_templatepath( $file ) {
		$filename = ( preg_match( '/themes\/([a-z0-9]*\/.*)/', $file, $out ) ) ? $out[1] : basename( $file );
		return $filename;
	}

Mein Child-Theme hieß twentyfifteen-child. Aber der Verzeichnisname darf laut der Regular Expression nur Buchstaben und Ziffern enthalten, keinen Bindestrich. Mein Verzeichnisname enthielt aber einen Bindestrich … also kurzerhand ergänzt:

	function tc_templatepath( $file ) {
		$filename = ( preg_match( '/themes\/([a-z0-9-]*\/.*)/', $file, $out ) ) ? $out[1] : basename( $file );
		return $filename;
	}

Nun bekam ich die Ausgabe, die ich wollte:

RECOMMENDED: @version is missing in the file twentyfifteen-child/inc/custom-header.php.

Der Test auf das * @version funktionierte, gab den Ort inklusive Theme-Namen an und gab so alle Informationen aus, die ich wollte. Und das nur durch die Check-Datei und ohne weitere Änderungen am Haupt-Plugin.

Hier der gesamte Code am Stück:

Du hast eine Rückfrage? Ergänzung? Verbesserung? Immer her damit! Entweder auf Github oder hier in den Kommentaren.

Schreibe einen Kommentar

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