Open Source verstehen, leben

Aktuell konzentrieren sich viele Menschen in meinem Umfeld eher auf geschlossene Pakete, keine Transparenz und möglichst wenig Mitarbeiter. Weihnachten 🎄 steht vor der Tür und genießt den "Sommer".

Trotzdem mal wieder Raum und Zeit für einige Zeilen dich mich persönlich umtreiben. Open Source, egal ob nur die Sicht auf Code oder andere offene Quellen, die zu Produkten führen können. Ich möchte ein paar Gedankenanstöße los werden und vielleicht zum Nachdenken anregen.

Ich bin seit vielen Jahren im Zirkus unterwegs, lebe ihn aus unterschiedlichen Richtungen und bin ebenso Nutznießer aus verschiedenen Welten und mit verschiedenen Sichten. Diese Punkte bewegen mich dazu, die folgenden Worte nieder zu schreiben und diese Sicht, das Gefühl bzgl. Open Source zu haben.

Ich schreibe diese Zeilen mit dem Bild, dass Open Source und dessen Mitarbeit vorrangig in Freizeit entsteht. Ich weiß, dass es diverse Projekte gibt, die mit Hilfe von Arbeitszeit im Sinne "man wird entlohnt" entstehen. Ein großes Bild der Themen, die ich ansprechen möchte, trifft aber eher auf die Ressource nach dem Job zu und ringt mir daher um so mehr das Lob, die Huldigung ab.

Natürlich musst du nicht die gleiche Sichtweise haben, sie schildert mein Bild. Ich will auch nicht diskutieren, ich möchte darstellen und anregen.

Warum Open Source?

Jeder für sich sollte sich diese Frage beantworten. Warum stellt man seine Idee und Lösung öffentlich bereit. Will man dies tatsächlich, soll es anderen nutzen und ist Mitarbeit gewollt. Sucht man nur freien Speicherplatz oder Sichtbarkeit. Will man neue Ideen, Diskussionen zulassen. Mit einem Open Source Projekt öffnet man seinen Geist zu diesem einzelnen Thema, Produkt und oft auch zu vielen anderen Themen. Parallel sind Fehler sichtbar, angreifbar. Auch dies sollte in dem Umfeld nicht vergessen werden. Gleiches gilt für das Einbringen von Änderungen, will man das? Hier muss jeder für sich die Regeln fest legen, sollte dies auch sichtbar dokumentieren um potenzielle Mitarbeiter nicht abzuschrecken.

Open Source Projekte sind mehr als das Abliefern von Code

Die Mitarbeit, das Einbringen in Open Source Projekten kann sehr verschieden sein. Oft wird in erster Linie auf Code runter gebrochen, aber die Arbeit an solchen Projekten erfordert weit mehr. Es ist ebenso Dokumentation, Community Arbeit, Übersetzungen, Sichtbarkeit, Projektmanagement und vieles mehr notwendig. Hier kann jeder seine favorisierte Aufgabe wieder finden. Entscheidend ist, dass es nachhaltig geschieht. Das pure Abgeben von einigen Zeilen Code oder einem Issue ist in der Regel kaum hilfreich. Das Projekt lebt und stirbt mit den Leuten, die daran arbeiten.

Recruiting

Als Projektinhaber gilt es daher möglichst stabile Mitstreiter zu haben, die sich engagieren, die sich einbringen. Parallel gilt es stetig neue Leute zu rekrutieren, zur Mitarbeit zu bewegen. Populäre Projekte im Web beispielsweise sind hier sehr stark. Sie dominieren nicht wegen ihrer Qualität an Code oder einer Führungspersönlichkeit. Die Community, die Mitstreiter machen sehr oft den Wert aus. Neue Bewerber sollten mit wenig Hürden in das Projekt gelassen werden. Eine schnelle Lernkurve um ein entsprechendes Niveau zu haben hilft sehr. Hindernisse auf jedem Wege der Beteiligung stoßen ab, schrecken neue Mitarbeiter ab.

Die Akzeptanz von Requests beispielsweise sollte nicht zu hohe Hürden enthalten. Lieber einmal mehr korrigieren, auf das gewünschte Level bringen und zurück mappen, was fehlt, was man besser machen kann. Nur so steigt die Lernkurve auf der anderen Seite und die Zufriedenheit, die zur Mitarbeit benötigt wird.

Balance

Gleichzeitig gilt es eine Balance der Mitarbeit zu finden, so dass Mitstreiter nicht verbrannt werden. Die Meinung, die Arbeit jedes einzelnen zählt, vor allem wenn sie in ihrer Form mit der Gruppe abgestimmt ist. Daher helfen Contributor-Regeln um hier schnell klare Linien zu erkennen. Parallel ist Kommunikation über die Issue-liste hinaus wichtig, Austausch auf menschlicher Ebene kann ein Projekt beflügeln. Wir haben heute eine ganze Reihe toller Tools um sich gut aus dem Wege zu gehen und trotzdem einen Austusch zu leben, trotzdem halte ich einen Austausch um das Problem und darüber hinaus für sehr hilfreich. Zufriedenheit kommt sicher aus verschiedenen Motivationen heraus, aber auf lange Sicht ist ein gutes Familienleben sicher sehr hilfreich.

Vergiss in diesem Zusammenhang die unterschiedlichen Altersstrukturen nicht. Während die einen mit dem Austausch per Tastatur aufgewachsen sind, brauchen die anderen mehr Worte zum korrekten "Sagen" und nicht nur eine Emoticon. Die Welt ist bunt, ihrer Bewohner erst recht und das macht auch in einem Projekt die Mischung und dessen Wert aus. Ein breit aufgestelltes Projektteam kann sehr wertvoll sein.

Gleiches gilt für unterschiedliche Kenntnisse. Was dem einen als Selbstverständlichkeit im Alltag begegnet ist dem anderen neu. Antworten, Fragen sind einfacher wenn man sie versteht und man nicht nur it kurzen Worten abgefertigt wird. Ob Issue oder Pull Request, ein paar erläuternde Antworten machen es leichter. Ich wurde neulig bei einem Pull Request um ein interactives Rebasing gebeten. Die Hinweise, das Feedback kamen nicht vom Repo-Projekt-Inhaber, sondern von einem Außenstehenden, der sich lediglich für meinen Code interessiert hat. Zu Nachfragen erhielt ich immer sachliche Rückmeldungen und ein Mail-Austausch ist parallel entstanden. Ich habe neues gelernt und meine Arbeitsweise der "schmalen" Commits muss weiter überdacht werden, oder wie hier im Nachgang überarbeitet werden. Es entsteht Mehrarbeit, die aber Wertvoll ist. Im ersten Schritt baute ich nur eine kleine Erweiterung, im zweiten entschloss ich mich zum Pull Request und nun waren die zu kurzen Commit-Messages nachteilig. Darum ist der Hinweis wertvoll. In diesem speziellen Fall wurde mir dies sogar abgenommen, in dem der Reviewende dies übernahm und positive Beispiele aufzeigte.
Ich denke, dass solche Beispiele aufzeigen, wie man miteinander umgehen kann, soll. Es hilft beiden Seiten und mein nächster Request ist sicher gepflegter und der interaktive Rebase ist nun auch erlernt. Parallel steht dem Repo-Inhaber nun ein Pull-Request an, der zu durchschauen ist und neue Mitstreiter sind gefunden, abgeholt.

Kurz: Der Mensch macht`s.

Sichtbarkeit, Feedback

Wie erreicht man es, dass Projekte sichtbar werden? Viele von uns haben offene Projekte, suchen hier und da Mitarbeit. Nicht alle erstellen Open Source aus dem Gedanken heraus freie Lösungen bereit zu stellen. Oft entstehen sie auch aus dem Beweggrund der Sichtbarkeit bzgl. Recruiting heraus, eventuell auch weil die freie sichtbare Lösung keine Kosten verursacht und die Vorteile eines Repositories im www mit sich bringt.
Andere wiederum hoffen auf mehr Sichtbarkeit und neue Mitarbeiter. Ich für meinen Teil habe einige offene Projekte laufen, jeder Pull Request ist wie ein innerliches Weihnachten. Die Freude darüber ist unglaublich. Ich bekomme Korrekturen, Erweiterungen - im besten Fall lerne ich etwas. Darum verstehe ich nicht, warum an anderer Stelle Request ewig liegen oder gar unangetastet bleiben. Um das Projekt ist es Schade und um den Menschen der sich einbringt.
Daher die Bitte, solltet ihr Pull Requests oder andere Formen der Mitarbeit haben, holt die Leute ab, gebt ihnen ein Zeichen.

Open Door 😉

Weihnachten steht vor der Tür und auch ich werde es rein lassen müssen. Insofern schließe ich die heutigen Gedanken, vielleicht entstehen weitere bei dir. In jedem Fall wünsche ich schöne Weihnachten und eine friedliche Zeit, Zeit zum Nachdenken und mit Anderen in Austausch zu treten, zum Weihnachtsessen oder zum direkten Austausch, ohne Tastatur vielleicht und hoffentlich vielfältig. Bis bald ...

Blue Beanie Day 2014

bueltge_blue_beanieHeute setzen eine ganze Reihe von Webentwicklern ein Zeichen mit dem Symbol der blauen Mütze - Bewusstsein für Webstandard ist der kurzgefasste Hintergrund der Idee "Blue Beanie Day". Es schadet nicht, sich damit ein wenig auseinander zu setzen, egal ob man blaue Mützen mag oder nicht.

Seit fast einem Jahrzehnt ist die HTML5 Entwicklung aktiv und sie hat in meinen Augen viele positive Resultate erzielt.

  • Semantik 1 - Wir haben eine Semantik, die verständlich ist, die sich an die Bedürfnisse im Netz anpasst. Parallel haben wir diverse Möglichkeiten um die Grundsemantik header, main, footer weiter zu detaillieren.
  • Semantik 2 - Mit den vielen neuen Möglichkeiten wird es aber auch komplizierter. Div-Suppen waren semantischer Unsinn, sind aber leicht verständlich beim Entwickler, der nur das sichtbare Resultat im Auge hat.
  • Semantik 3 - Die neuen Möglichkeiten lassen komplexe Strukturen zu und man kann von grundauf semantisch seine Website planen, was dementsprechend zu einem erhöhten Aufwand führt. Letztlich sicher ist man sich nur, wenn man ausreichend Erfahrung und entsprechende Tools zur Kontrolle mitbringt. In der Regel werden sicher diverse Vorgaben populärer Systeme oder Repositories kopiert.

Der Standard HTML5 ist für mich ein klares Plus, gibt mir Strukturen (Elemente und Attribute) die ich einsetzen kann und ich versuche einen Mittelweg zwischen Aufwand und "Übersemantik" zu erreichen. Allein die bessere Übersicht im Quellcode macht mir Freude und immer wieder gilt es den Istzustand in Frage zu stellen und zu Lernen. Fakt ist aber auch, damit wird es nicht einfacher ein Resultat zu erzielen, was uns glücklich macht und bei HTML erreichen wir den gleichen Status wie im Coding mit Programmiersprachen - der Code von gestern ist "Legacy". Es wäre sicher hilfreich, wenn wir mehr praktische Beispiele bekommen, die ggf. auch die Wertigkeit nachgewiesen haben. Das W3C und die WHATWG bieten zwar Beispiele an, aber die Gesamtstruktur muss man sich doch im Vorfeld selbst erarbeiten.

Nicht zu letzt ist also ein Blue Beanie Day mehr als das Ändern des Avatars, es soll zum Nachdenken anregen, ggf. Diskussionen entfachen und sicher auch an die Vielfalt im Netz erinnern. Aber gerade diese Vielfalt macht es für mich so spannend am und im Netz dabei zu sein. Vielleicht ist also der eine oder andere ebenso angeregt darüber nachzudenken, sein Tun in Frage zu stellen oder auch den Hintergrund, das Ziel für die blaue Mütze zu verstehen.

Wildcard in WP_User_Query()

Für nutzerbezogene Daten steht in WordPress die Klasse WP_User_Query() zur Verfügung. Üblicherweise gibt man dort einen Schlüssel mit und bekommt die entsprechenden Werte zum User zurück. Durch ein Entwicklungsthema ist mir eine Besonderheit in der Query aufgefallen, die diesen kleinen Beitrag als Folge hat. Die Klasse erlaubt das Ergänzen von * als Wildcard. Innerhalb der Klasse wird dieser Stern dann für die SQL Abfrage ersetzt (%).

Im Codex findet man beispielsweise folgendes einfaches Beispiel zur User-Abfrage.


$user_query = new WP_User_Query( array( 'search' => 'Rami' ) );

Will man vor oder nach diesem String "Rami" per Wildcard schauen, was es weiter gibt, oder flexibler suchen, dann ist lediglich das Ergänzen von * notwendig. Dazu finde ich aktuell nichts im Codex, so dass der Hinweis hier ggf. hilfreich ist.

Im Core wird dies betrachtet:


// @see wp-includes/user.php#L599
if ( $search ) {
        $leading_wild = ( ltrim($search, '*') != $search );
        $trailing_wild = ( rtrim($search, '*') != $search );
        if ( $leading_wild && $trailing_wild )
                $wild = 'both';
        elseif ( $leading_wild )
                $wild = 'leading';
        elseif ( $trailing_wild )
                $wild = 'trailing';
        else
                $wild = false;
        if ( $wild )
                $search = trim($search, '*');

Damit kann also vor oder nach dem String ein Wildcard mitgegeben werden.


$user_query = new WP_User_Query( array( 'search' => '*Rami*' ) ); //%Rami%

$user_query = new WP_User_Query( array( 'search' => 'Rami*' ) ); //Rami%

Zum Ende nochmal der Hinweis, die Wildcard ist nur am Anfang oder Ende des Suchstrings möglich, nicht innerhalb des Strings.

Entscheidungshilfe: get_post() oder WP_Query

WordPress stellt oft verschieden Wege bereit um an Daten zu kommen. Im Umfeld von Inhalt - Einzelne Artikel, Kommentare, ... - beschränkt sich dies im Grunde auf zwei Wege. Beide sind im Netz zigfach in Tutorials hinterlegt und oft ist die Nutzung des jeweiligen Weges nicht zu Ende gedacht. Es gibt viele Artikel um die Hintergründe zu verstehen und sich mit dem gewonnen Verständnis für die entsprechende Methode zu entscheiden. Herausragend in Bildform und verständlich ist der Eintrag #1753 im WPSE.

Bitte nicht mit get_posts() verwechseln, get_posts() und get_post() sind für unterschiedliche Resultate erstellt. In kurzer Form dient get_posts() für viele Inhalte zum Type post. Die Entscheidungshilfe hier ist für die Ausgabe von einem Artikel, dessen Inhalte, dessen zugehörigen Daten. Im Grunde kann man aber von der Regel zu get_posts vs. WP_Query einiges ableiten.

Ich möchte nur eine kurze Entscheidungshilfe geben, die euch und mich in die Lage versetzt, aufgrund einiger weniger Punkte zu entscheiden, beim Holen einzelner Inhalte - get_post() oder WP_Query.

Tests

An folgendem kleinen Beispiel kann man die Unterschiede bspw. messen und an Hand der Anzahl der Queries vergleichen. Man kann wesentlich komplexere Beispiele bauen. Aber ich denke, dass gerade die Einfachheit das Verständnis fördert. Die Queries kann man entweder einfach per Ausgabe sehen $wpdb->queries oder alternativ bspw. mit Hilfe des Plugins Debug Objects ohne Aufwand einsehen.

Als erster wird der Artikel mit ID 1 geholt und Title und Content ausgelesen.


$post_1  = get_post( 1 );
$title   = $post_1->post_title;
$content = $post_1->post_content;

Den gleichen Inhalt holen wir nun über den WP_Query.


$query_1 = new WP_Query( 'p=1' );
$title   = $query_1->posts[0]->post_title;
$content = $query_1->posts[0]->post_content;

Welche Daten werden benötigt?

Wenn Daten zum Artikel, wie Kommentare, -Anzahl, Autoren-Daten oder Benutzerdefinierte Felder benötigt werden, dann nutze WP_Query. Wenn lediglich Daten aus der Tabelle posts benötigt werden, dann nutze get_post() und spare Datenbankabfragen.

Es wird ein Loop benötigt?

Werden im Loop Conditionals benötigt (if else, is_tag() etc.) dann nutze WP_Query. Sollen die Conditionals im Bezug auf den Artikel laufen, dann nutze get_post().

Code als Sprache?

WP-Query is komplexer, nicht so schnell zu durchschauen. Wenn man explizit auf verschiedene Post Types will, dann WP_Query. Ansonsten kann das Lesen und verstehen des Codes bei der Verwendung von get_post() einfacher sein. Für Live-betrieb sollte aber die Anzahl der Datenbankabfragen ein gewichtige Zahl sein.

Hinweis WP_Query

Bei der Verwendung von WP_Query lohnt immer der Gedanke an einen Cache, beispielsweise ist der standard WP_Object_Cache oder alternativ der Transient Cache von WordPress dafür schnell genutzt.

HTML5 Support seit WordPress 3.6

HTML5 in Buchform
Eines der Themen, die uns seit WordPress 3.6 neu zur Verfügung stehen ist der HTML5 Support, der in Themes Unterstützung findet. Dabei können drei Bereiche in den Genuss kommen. Die seit Version 3.4 zur Verfügung stehende Funktion add_theme_support() ist auch hier Schlüssel und so können aktuell drei Funktionalitäten für den Support von html5 registriert werden.

Im Theme, üblicherweise via functions.php werden alle drei Funktionalitäten registriert.


add_action( 'after_setup_theme', 'fb_example_setup' );
function fb_example_setup() {
	add_theme_support(
		'html5',
		array( 'comment-list', 'comment-form', 'search-form' )
	);
}

Die Namen der Funktionen sollten für sich sprechen.

  • 'comment-list' - Kommentarliste, wp_list_comments
  • 'comment-form' - Kommentar-Formular, comment_form()
  • 'search-form' - Such-Formular, get_search_form()

In existierenden Themes gibt es nichts zu tun, alle Funktionen sind abwärtskompatibel und damit wird weiter das bekannte xhtml Markup genutzt. Attribute wie placeholder sind dann nicht genutzt.

Die Funktion für den Aufruf der Kommentarliste im Template ist damit auch kürzer geworden, ein Beispiel.


<ol class="comment-list">
	<?php
		wp_list_comments( array(
			'style'       => 'ol',
			'short_ping'  => TRUE,
			'avatar_size' => 74,
		) );
	?>
</ol><!-- .comment-list -->

Die Vorgaben werden in einem Array übergeben und folgende Standard-Einstellungen werden genutzt.


	$defaults = array(
		'walker'            => null,
		'max_depth'         => '',
		'style'             => 'ul',
		'callback'          => null,
		'end-callback'      => null,
		'type'              => 'all',
		'page'              => '',
		'per_page'          => '',
		'avatar_size'       => 32,
		'reverse_top_level' => null,
		'reverse_children'  => '',
		'format'            => current_theme_supports( 'html5', 'comment-list' ) ? 'html5' : 'xhtml',
		'short_ping'        => false,
	);

Damit ist WordPress perse nicht sauber in der Ausgabe im Hinblick auf HTML5, aber erste Zeichen sind gesetzt. Insbesondere das Markup, was zum Content erzeugt wird, macht da Schwierigkeiten, wo nur eigene Anpassungen als Plugin oder im Theme helfen können.

Einfaches PHP Debugging in Browser Console

Ich nutze die Console im Browser der gern um Debug-Inhalte auszugeben. Insbesondere bei Kunden-Sites kann ich so recht unscheinbar arbeiten und muss nicht die Oberfläche mit Debug-Meldungen zu zerstören, auch wenn man dies natürlich via Rechtabfrage filtern sollte. Im folgenden eine kleine Funktion, die mir den Inhalt in die Console schreibt, ohne Helferlein. Dies ist auch im Plugin Debug Objects untergebracht und kann beim Einsatz des Plugins direkt genutzt werden.

Der Screenshot demonstriert dies an einem komplexen Objekt in der Ausgabe und dient nur dem Verständnis. Den Inhalt, den ihr ausgeben wollt, liegt natürlich in eurer Hand.
debug-to-console

Die einfache Variante, die allerdings keine Objekte verarbeiten kann - lediglich Strings und Arrays. Im weiteren Verlauf dann eine etwas aufwendigere Funktion, die Objekte zulässt.


	/**
	 * Simple helper to debug to the console
	 * 
	 * @param  Array, String $data
	 * @return String
	 */
	function debug_to_console( $data ) {

		if ( is_array( $data ) )
			$output = "<script>console.log( 'Debug Objects: " . implode( ',', $data) . "' );</script>";
		else
			$output = "<script>console.log( 'Debug Objects: " . $data . "' );</script>";

		echo $output;
	}

Will man Objekte nutzen, so muss die Funktion erweitert werden. Will man Beispielsweise den Inhalt des globalen Objektes der WordPress Datenbank ausgeben, siehe folgende Zeilen


global $wpdb;
debug_to_console( $wpdb );

dann genügt die einfache Helferfunktion nicht, darum eine erweiterte Version, die auch Objekte ausgibt.


	/**
	 * Simple helper to debug to the console
	 * 
	 * @param  Array, Object, String $data
	 * @return String
	 */
	function debug_to_console( $data ) {
		
		$output = '';
		
		if ( is_array( $data ) ) {
			$output .= "<script>console.warn( 'Debug Objects with Array.' ); console.log( '" . implode( ',', $data) . "' );</script>";
		} else if ( is_object( $data ) ) {
			$data    = var_export( $data, TRUE );
			$data    = explode( "\n", $data );
			foreach( $data as $line ) {
				if ( trim( $line ) ) {
					$line    = addslashes( $line );
					$output .= "console.log( '{$line}' );";
				}
			}
			$output = "<script>console.warn( 'Debug Objects with Object.' ); $output</script>";
		} else {
			$output .= "<script>console.log( 'Debug Objects: {$data}' );</script>";
		}
		
		echo $output;
	}

Als schlanke und effiziente Lösung nutze ich gern folgende kleine Funktion, ohne Overhead.


	/**
	 * Simple helper to debug to the console
	 * 
	 * @param  object, array, string $data
	 * @return string
	 */
	function debug_to_console( $data ) {
		
		$output = '';

		// new and smaller version, easier to maintain
		$output .= 'console.info( \'Debug in Console via Debug Objects Plugin:\' );';
		$output .= 'console.log(' . json_encode( $data ) . ');';

		echo '';
	}

Den aktuellen Code findet ihr auf Github, dem Link folgen.

Theme für Mantis Bugtracker

MantisBT ist eines meiner Werkzeuge zum Tracken von Bugs und Entwicklung. In dem Zusammenhang nutze ich ein eigenes Theme seit vielen Jahren um die Arbeit der Anwender zu unterstützen. Insbesondere für Nicht-Entwickler war dies ein wichtiger Schritt um sie in der Oberfläche abzuholen. Eine abgewandelte Form ist dies nun frei nutzbar, wie auch das Markdown Plugin für MantisBT.

mantibt-screenshot

Erweiterungen, Verbesserungen sind wie immer willkommen, dazu das Repo nutzen. Informationen zu Installation und den Farben für diverse Status, die in der Konfiguration gesetzt werden, sind ebenso am Repo abgelegt - Colorized, a MantisBT Stylesheet.

Liste aller Blogs in WordPress Multisite

WordPress Multisite ist seit der Zusammenlegung von MU und Single ab Version 3.0 populärer geworden. Nicht nur die Verwaltung meherer Sites, sondern auch in diversen Szenarios findet Multisite seinen Einsatz. Als ein Beispiel sei die Mehrsprachigkeits-Lösung genannt.

In diesem Umfeld werden des öfteren die Inhalte oder Daten aus allen Blogs gebraucht, wozu man ggf. alle Blogs kennen muss. Bemüht man eine Suche um eine Lösung zu finden, dann erscheinen sehr oft div. SQL Selects, die auch in vielen Lösungen verbaut wurden und daher zum Nachahmen aufrufen. Da ich aktuell in einem Projekt wieder damit zu tun hatte und ein Select nicht die erste Wahl sein sollte, wenn es Core Functionen gibt, hier ein kurzes Snippet, was alle Blogs im Network zurück gibt.


// Get all blogs of WordPress Multisite
$blogs = get_blog_list( 0, 'all' );

Das Auswerten ist dann schnell getan, da die ID der Blogs im zurückgegebenen Array steckt und darüber alle weiteren Daten geholt werden können, ein Beispiel soll es verdeutlichen.


foreach( (array) $blogs as $blog ) {
    
    $stylesheet = get_blog_option( $blog['blog_id'], 'stylesheet' );
    $blogname   = get_blog_details( $blog['blog_id'] )->blogname;

}

Natürlich hat diese Lösung einen Haken. Die Funktione wurde mit WordPress 3.0 abgekündigt, womit man sie aktuell noch nutzen kann, aber irgendwann ist sie im Core weg. Sie wurde aus Gründen der Performance deaktiviert, da sie mit sehr großen Netzwerken (> 1000 Blogs) Probleme macht. Alternativ ist also die Funktion bereit zu stellen. Daher im folgenden die Funktion, die ich abhängig ablege. Ich werde die Funktion mit Transients erweitern, so dass mit WP Core Mitteln performanter ist. Dazu bitte in den Code auf Github schauen. Dort wird er gepflegt. Ihr seit herzlich eingeladen, den Code zu verbessern, zu ergänzen - die Fork-Funktion kann gern genutzt werden.


 if ( ! function_exists( 'get_blog_list' ) ) {
	
	/**
	 * Returns an array of arrays containing information about each public blog hosted on this WPMU install.
	 * Only blogs marked as public and flagged as safe (mature flag off) are returned.
	 * 
	 * @param   Integer  The first blog to return in the array.
	 * @param   Integer  The number of blogs to return in the array (thus the size of the array).
	 *                   Setting this to string 'all' returns all blogs from $start
	 * @return  Array    Returns an array of arrays each representing a blog hosted on this WPMU install. 
	 *                   Details are represented in the following format:
	 *                       blog_id   (integer)ID of blog detailed.
	 *                       domain    (string) Domain used to access this blog.
	 *                       path      (string) Path used to access this blog.
	 *                       postcount (integer) The number of posts in this blog.
	 */
	function get_blog_list( $start = 0, $num = 10 ) {
	
		global $wpdb;
		$blogs = $wpdb->get_results(
			$wpdb->prepare( "
				SELECT blog_id, domain, path 
				FROM $wpdb->blogs WHERE site_id = %d 
				AND public = '1' 
				AND archived = '0' 
				AND mature = '0' 
				AND spam = '0' 
				AND deleted = '0' 
				ORDER BY registered DESC
			", $wpdb->siteid ), 
		ARRAY_A );
		
		foreach ( (array) $blogs as $details ) {
			$blog_list[ $details['blog_id'] ] = $details;
			$blog_list[ $details['blog_id'] ]['postcount'] = $wpdb->get_var( "
				SELECT COUNT(ID) 
				FROM " . $wpdb->get_blog_prefix( $details['blog_id'] ). "posts 
				WHERE post_status='publish' 
				AND post_type='post'" 
			);
		}
		unset( $blogs );
		$blogs = $blog_list;
		
		if ( false == is_array( $blogs ) )
			return array();
		
		if ( $num == 'all' )
			return array_slice( $blogs, $start, count( $blogs ) );
		else
			return array_slice( $blogs, $start, $num );
	}
	
} // end if fct exist

Eventuell hilft dieser kleine Hinweis dem einen oder anderen bei seinem Projekten.

WordPress Puls? – Heartbeat API

Mit WordPress 3.6 wird es eine neue API geben - Heartbeat. Am Ticket 23216 im Trac sammeln sich alle Diskussionen und Hinweise. Da Heartbeat aber auch Einflüsse für Anwender haben kann, hier einige Worte und Hinweise. Heartbeat wird eingeführt um diverse Aktivitäten, wie Autosave, Sperren von Artikeln und An- und Abmelde-Benachrichtigungen zu händeln. Parallel kann die API auch für eigene Entwicklungen genutzt werden.

Am Puls

Im Standard wird Heartbeat mit einem Puls von 15 Sekunden schlagen - Arbeit die der Prozessor tun muss und so kann es sinnvoll sein, diesen Wert zu ändern. Dabei kann nicht beliebig geändert werden. Der Pulsschlag von Heartbeat muss zwischen 5 und 60 Sekunden liegen. Folgendes kleines Plugin ändert auf den maximalen Wert von 60s.

Die Heartbeat API hat vielleicht im ersten Blick nicht die großen Vorteile, schauen wir aber auf ein einfaches Beispiel. Deine Installation hat zehn verschieden Plugins, die einen Poll auf den Server brauchen. Dann finden diese Hits getrennt statt, 10 mal. Wenn die Plugins die Heartbeat API verwenden, dann werden die Polls gebündelt, ein Hit für 10 Polls, alle 15 Sekunden im Standard.


<?php
/**
 * Plugin Name: Set Heartbeat pulse
 */

! defined( 'ABSPATH' ) and exit;

add_filter( 'heartbeat_settings', 'fb_heartbeat_settings' );
function fb_heartbeat_settings( $settings = array() ) {

	$settings['interval'] = 60;

	return $settings;
}

Parallel kann man Heartbeat auch still legen, den Puls abklemmen, was das folgenden kleine Plugin tut.


<?php
/**
 * Plugin Name: Remove Heartbeat pulse
 */

! defined( 'ABSPATH' ) and exit;

remove_action( 'admin_init', 'wp_auth_check_load' );

Debugging

Im Core von WordPress wurde die API so implementiert, dass die Console Infos ausspucken kann. Dazu muss der Parameter wp.heartbeat.debug auf TRUE gesetzt werden und schon kann das JavaScript infos geben.


if ( typeof console !== 'undefined' ) {
	// Show debug info
	wp.heartbeat.debug = true;
}

Entwicklung

Ein einfaches Beispiel liegt dem Trac bei, wo das Dashboard Widget für Kommentare am Pulsschlag aktualsiet wird - man kann also alle 15s einen Refresh der Zahlen erleben, insofern neue Kommentare eintreffen. Das Beispiel zeigt die wichtigsten Hooks und Funktionen und daher hier auch keine weitere Erklärung.

Weitere Hinweise, Links zum Thema

Post Format UI deaktivieren

WordPress Version 3.6 kommt mit neuer Oberfläche für die Post Formats, präsenter ist das Schlagwort. Die Post Format UI ist eine wunderbare Möglichkeit mit wenig Aufwand Artikel besser uns sichtbar zu deklarieren, für den Leser verschieden aufzubereiten. Trotzdem ist sie nicht immer notwendig. Im Standard kann die UI in den jeweiligen Optionen des Users deaktiviert werden, siehe Screenshot.

post-format-ui

Alternativ kann der Filter Hook enable_post_format_ui genutzt werden. Mittels dieses Hooks kann die UI global in der Installation deaktiviet werden und kein User hat die Möglichkeit die Post Formats zu nutzen. Folgende Zeilen in einer php-Datei als Plugin abgelegt und aktiviert sind daher ausreichend.

<?php
/**
 * Plugin Name: Disable Post Format UI
 */

! defined( 'ABSPATH' ) and exit;

add_filter( 'enable_post_format_ui', '__return_false' );

WordPress Lightbox Plugin