<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>toscho.design</title>
	<atom:link href="http://toscho.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://toscho.de</link>
	<description>Redaktion, Druck- und Webdesign aus Halle (Saale)</description>
	<lastBuildDate>Wed, 11 Aug 2010 09:20:27 +0000</lastBuildDate>
	<language>de-DE-1901</language>
	<sy:updatePeriod>daily</sy:updatePeriod>
	<sy:updateFrequency>4</sy:updateFrequency>
	
		<item>
		<title>WordPress: Sprache der Ausgabe einstellen</title>
		<link>http://toscho.de/2010/wordpress-sprache-der-ausgabe-einstellen/</link>
		<comments>http://toscho.de/2010/wordpress-sprache-der-ausgabe-einstellen/#comments</comments>
		<pubDate>Mon, 02 Aug 2010 17:00:52 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Markup]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Sprache]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1707</guid>
		<description><![CDATA[Wie man die <i lang="en">Language-Tags</i> in WordPress an die tatsächlich verwendete Sprache anpaßt. Hintergründe, Links und Beispielcode inklusive.]]></description>
			<content:encoded><![CDATA[<!--TOC-->
<h2>Meine Sprache</h2>
<p>Ich bin kein viel versprechendes Talent. Aber ein vielversprechendes … nun, lassen wir das. Will sagen: Mich hat die <a href="http://www.schriftdeutsch.de/ortr-rat.htm">Reform der deutschen Rechtschreibung im Jahre 1996</a> nicht überzeugt. Die Reformen der Reform ebensowenig. Deshalb halte ich mich heute überwiegend an die <em>klassische</em> Orthographie, die seit dem letzten amtlichen Eingriff 1901 ganz allmählich durch den allgemeinen Sprachgebrauch entwickelt wurde.<br />
Und gerade weil ich den Gedanken einer <em>organischen</em> Entwicklung so mag, halte ich mich nicht immer genau an die Regeln von 1995: Ich übertrete sie, wenn mein Sprachgefühl mir dazu rät.</p>
<p>Im Großen aber muß ich meine Sprache für Maschinen als <a hreflang="en" href="http://www.iana.org/assignments/lang-tags/de-DE-1901"><code>de-DE-1901</code></a> kennzeichnen — der <a hreflang="en" lang="en" title="Request for comments 3066" href="ftp://ftp.rfc-editor.org/in-notes/rfc3066.txt">RFC 3066</a> verlangt es so.</p>
<p class="wideimg"><img src="http://toscho.de/wp-content/uploads/2010/08/language-tags-500.png" alt="" width="500" height="282" class="alignnone size-full wp-image-1708" /></p>
<h2>Sprachausgabe in WordPress</h2>
<p>In WordPress wird die Sprache des Blogs in der Datei <code>wp-config.php</code> angegeben:</p>
<pre class="notranslate">define (<code class="string">'WPLANG'</code>, <code class="string">'de_DE'</code>);</pre>
<p>Dann holt sich das CMS automagisch die <a href="http://wordpress-deutschland.org/download/sprachdatei/">passende Sprachdatei</a> namens <samp>de_DE.mo</samp>. Deshalb bringt es mir nichts, die präzise Sprache in der <code>wp-config.php</code> zu setzen: Eine Datei <samp>de_DE_1901.mo</samp> existiert ja leider nicht, und ich möchte auch nicht nach jeder Aktualisierung den Dateinamen hinterherrennen müssen.</p>
<p>Macht nichts.</p>
<p>In der Ausgabe für den Leser, im <i lang="en">Frontend</i> also, wird die Sprache nur an zwei Stellen angegeben: Im <code>lang</code>-Attribut des Elementes <code>html</code>:</p>
<pre class="notranslate">&lt;html lang=<code class="string">"de-DE-1901"</code>&gt;</pre>
<p>Und im Feed, beispielsweise in der Datei <code>/wp-includes/feed-atom.php</code>:</p>
<pre class="notranslate">xml:lang="&lt;?php echo get_option(<code class="string">'rss_language'</code>); ?&gt;"</pre>
<p>Im Theme kann man diese Angabe entweder konkret in den Code schreiben oder die Funktion <a hreflang="en" href="http://codex.wordpress.org/Function_Reference/language_attributes"><code>language_attributes()</code></a> verwenden:</p>
<pre class="notranslate">&lt;html &lt;?php language_attributes(); ?&gt;&gt;</pre>
<p>Diese Funktion gibt die Schreibrichtung und die Sprache aus. Da <code>ltr</code> der <a href="http://www.w3.org/TR/html401/struct/dirlang.html#h-8.2.2" hreflang="en">Standardwert für das Attribut <code>dir</code></a> ist, kann das hier weggefiltert werden.</p>
<p>Die beiden Filter, die wir ansprechen müssen, lauten <code class="string">'language_attributes'</code> und <code class="string">'pre_option_rss_language'</code>.</p>
<h2>Code zum Anpassen</h2>
<p>Ich habe mir dafür eine kleine Klasse geschrieben, die ich in der functions.php des Themes einfach per <a href="http://php.net/require"><code>require</code></a> aufrufe:</p>
<p class="downloadlink"><a href="http://gist.github.com/raw/504854/4aeaa5c3bce59206401f1a6b5a92c69d906a2afa/class.Toscho_Language_Filter.php">Download class.Toscho_Language_Filter.php</a></p>
<div class="php-code">
<pre class="notranslate php"><span class='openclose'>&lt;?php
</span><i class='comment'>/**
 * Adjust the public visible language declarations.
 *
 * @author &quot;Thomas Scholz&quot; <a href="http://toscho.de">http://toscho.de</a>
 * @version 1.0
 */</i>
<span class='internal'>class</span> Toscho_Language_Filter
{
    <i class='comment'>/**
     * @var string
     */</i>
    <span class='internal'>public</span> <span class='internal'>static</span> <var>$lang</var> <span class='operator'>=</span> <span class='string'>&#039;de&#039;</span>;

    <i class='comment'>/**
     * Pseudo constructor.
     *
     * @param  string $lang The language according to …
     * @link   <a href="http://www.evertype.com/standards/iso639/iana-lang-assignments.html">http://www.evertype.com/standards/iso639/iana-lang-assignments.html</a>
     * @return void
     */</i>
    <span class='internal'>public</span> <span class='internal'>static</span> <span class='internal'>function</span> setup(<var>$lang</var> <span class='operator'>=</span> <span class='string'>&#039;de-DE-1901&#039;</span>)
    {
        self<span class='operator'>::</span><var>$lang</var> <span class='operator'>=</span> <var>$lang</var>;

        add_filter(
            <span class='string'>&#039;language_attributes&#039;</span>
        ,   <span class='internal'>array</span> ( <span class='constant'>__CLASS__</span>, <span class='string'>&#039;html&#039;</span> )
        );
        add_filter(
            <span class='string'>&#039;pre_option_rss_language&#039;</span>
        ,   <span class='internal'>array</span> ( <span class='constant'>__CLASS__</span>, <span class='string'>&#039;get_lang&#039;</span> )
        );
    }

    <i class='comment'>/**
     * Returns the language string.
     * @return string
     */</i>
    <span class='internal'>public</span> <span class='internal'>static</span> <span class='internal'>function</span> get_lang()
    {
        <span class='internal'>return</span> self<span class='operator'>::</span><var>$lang</var>;
    }

    <i class='comment'>/**
     * Output for language_attributes().
     * We drop the &#039;dir&#039; attribute.
     *
     * @return string
     */</i>
    <span class='internal'>public</span> <span class='internal'>static</span> <span class='internal'>function</span> html()
    {
        <span class='internal'>return</span> <span class='string'>&#039;lang=&quot;&#039;</span> <span class='operator'>.</span> self<span class='operator'>::</span><var>$lang</var> <span class='operator'>.</span> <span class='string'>&#039;&quot;&#039;</span>;
    }

}
<i class='comment'>// Adjust this to your needs.
</i>Toscho_Language_Filter<span class='operator'>::</span>setup(<span class='string'>&#039;de-DE-1901&#039;</span>);</pre>
</div>
<p>Wer mag, kann die Funktion <code>setup()</code> auch mit einer eigenen Kreation aufrufen. Dann muß man ein <code>-x-</code> davorsetzen, wie Ian Hickson das in den <a hreflang="en" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/">Spezifikationen zu HTML5</a> macht: <code>lang=<code class="string">"en-US-x-hixie"</code></code>.<br />
Über den Nutzen möchte ich lieber nicht diskutieren.</p>
<h2>Mehr davon</h2>
<ul>
<li><a href="http://toscho.de/2010/wordpress-dashboard-approved-nicht-genehmigt/">WordPress-Dashboard: ›Approved‹ nicht ›Genehmigt‹</a></li>
<li><a href="http://toscho.de/2010/wordpress-auszug-zeichenzahl/">WordPress: Auszug mit bestimmter Zeichenzahl</a></li>
<li><a href="http://toscho.de/2009/php-funktion-genitiv/">PHP-Funktion Genitiv</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-sprache-der-ausgabe-einstellen/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Kommentare moderieren: Meine Richtlinien</title>
		<link>http://toscho.de/2010/kommentare-moderieren-richtlinien/</link>
		<comments>http://toscho.de/2010/kommentare-moderieren-richtlinien/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 11:09:22 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Interna]]></category>
		<category><![CDATA[Sprache]]></category>
		<category><![CDATA[Webdesign]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1646</guid>
		<description><![CDATA[Meine Kriterien zum Löschen und Bearbeiten der Kommentare. Ja, die dürfen kommentiert werden!]]></description>
			<content:encoded><![CDATA[<p>Ich halte die Kommentare in diesem Blog für ebenso wichtig wie meine Artikel. Mag die Diskussion mal das ursprüngliche Thema verlassen – stört mich nicht. Doch wenn sie von Backlinkjunkies zerfasert wird, schreite ich ein.</p>
<p>Den klassischen Spam für Mädels oder Hilfsmittel, um sie zu beeindrucken, fängt der <a href="http://toscho.de/2010/spam-verhindern-akismet-htaccess/">automatische Filter</a> ab. Kein Problem.</p>
<p>Für den Rest habe ich ein paar Kriterien gefunden, die mich zum Löschen bewegen:</p>
<ul>
<li>Offensichtliche <strong>SEO-Namen:</strong> Firmen- oder Berufsbezeichnungen, auch als angebliche Namensteile. Das schwimmt natürlich: Kurt Schuster nehme ich noch hin, Klara Modevertrieb hingegen … kann mich mal.</li>
<li><strong>E-Mail-Adressen</strong> in der Art <samp>pr@example.comn</samp>. Solche Leute gibt es tatsächlich. Internetversteher.</li>
<li>Kommentare mit Backlinks auf <strong>verdächtige Seiten:</strong> Hätte ich dahin freiwillig einen Link gesetzt? Nein? Weg damit! Steck dir deine Spartricks, deine Cycle-Page und dein Spamblog bitte dorthin, wo es wehtut.</li>
<li>Alle paar Wochen schreibt hier auch jemand mit einem wechselnden Frauennamen: Der Inhalt ist <em>gerade so</em> etwas zu lang für Spam und hat <em>gerade so</em> noch einen Bezug zum Artikel. Die verlinkte Website könnte man <em>gerade so</em> noch durchgehen lassen.<br />
Kindchen, ich bin Autor! Ich erkenne dich unter <em>jedem</em> Namen wieder, und wenn ich überhaupt ein Talent habe, dann für das Erkennen von Sprachmustern. Dafür habe ich sogar ein gutes Gedächtnis. Das hätte ich gerne woanders …</li>
</ul>
<p>Manche Kommentare kennzeichne ich <em>nicht als Spam,</em> aber ich entferne sie zugunsten der allgemeinen Übersicht:</p>
<ul>
<li>Nackte <strong>Ichbotschaften:</strong> »Kannte ich noch nicht.«, »Probier ich mal.« und Ähnliches. Benutz’ einen <a href="http://toscho.de/2010/webdesign-fuers-ipad/" title="Der teuerste Spiegel aller Zeiten: das iPad.">Spiegel</a>.</li>
<li>Nur <strong>»Danke!«</strong> Ich freue mich, wenn ich dir geholfen habe, und ich <em>brauche</em> auch ein wenig Anerkennung. Allerdings stelle ich die Bedürfnisse meiner Leser in diesem Punkt über meine eigenen.<br />
Mit einer E-Mail oder einer Empfehlung in deinem Blog kannst du mir das Lächeln auch zurückgeben, das ich dir hoffentlich entlockt habe.</li>
<li>Völlig <strong>sachfremde Fragen oder Hinweise,</strong> die keinen Bezug zum Artikel oder zu einem anderen Kommentar herstellen. Wenn ich sie dennoch interessant finde, melde ich mich bei dir per E-Mail.</li>
<li>Kommentare, die sich auf gelöschte Kommentare beziehen. Da bitte ich dich um Nachsicht.</li>
<li>Beschimpfungen und andere juristische Fallgruben. Dafür gibt’s das Heise-Forum.</li>
</ul>
<p>Natürlich kann ich mich auch irren. Also hebe ich einen manuell entfernten Kommentar <em>eine Woche</em> auf. Meldet sich der Autor nicht binnen dieser Zeit, lösche ich den ganzen Eintrag.</p>
<p>Bei manchen Kommentaren nehme ich nur einen Link heraus, ohne die Aussage zu zerstören, wenn ich ihn für fragwürdig halte oder das Ziel nicht mehr existiert. </p>
<p>Insgesamt werde ich künftig etwas strenger urteilen, denn meine Nachsicht ist in den letzten Wochen ein paar Mal zu oft ausgenutzt worden.<br />
Das ging so weit, daß folgende zwei Zeilen in meine <code>.htaccess</code> Einzug fanden:</p>
<pre class="notranslate">RewriteCond <var>%{HTTP_REFERER}</var> do-follow-blogs\.de
RewriteRule ^ http://www.do-follow-blogs.de/ [L,R=301]</pre>
<p>Wenn du dich zu Unrecht wegmoderiert siehst, dann schreib mir eine freundliche E-Mail. Wenn du aber weißt, daß du Spam geschrieben hast, dann geh Sterben.</p>
<h2>Weiterschmökern</h2>
<ul>
<li><a href="http://toscho.de/2010/wordpress-moderationslinks-fuer-kommentare/">WordPress: Moderationslinks für Kommentare</a></li>
<li><a href="http://toscho.de/2010/informieren-statt-sperren/">Informieren statt Sperren</a></li>
<li><a href="http://toscho.de/2009/wordpress-moderationsfalle-offenlegen/">WordPress: Moderationsfalle offenlegen</a></li>
<li><a href="http://toscho.de/2009/blocken-mit-htaccess/">Ungebetene Gäste mit .htaccess blocken</a></li>
<li><a href="http://toscho.de/2009/no-no-no-nofollow/">No no no nofollow</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/kommentare-moderieren-richtlinien/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>WordPress als CMS: Hilfreiche Plugins</title>
		<link>http://toscho.de/2010/wordpress-cms-plugins/</link>
		<comments>http://toscho.de/2010/wordpress-cms-plugins/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 08:44:42 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[e-mail]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1697</guid>
		<description><![CDATA[Eine Auswahl nützlicher kleiner Plugins. Screenshots, Hinweise zur Deinstallation und Urteile zum Code inbegriffen.]]></description>
			<content:encoded><![CDATA[<!--TOC-->
<p>Es gibt noch mehr als Fußball, ja! Nämlich … WordPress … ähm.<br />
<a href="http://blogwiese.de/blog/5283/plugin-parade-2010">Cindy bittet</a>, man möge seine Plugins vorstellen. Da mach ich mal mit.<br />
Bei dieser Auswahl habe ich mich an zwei Punkten orientiert: Die Plugins sollten noch nicht allzu bekannt sein und den Einsatz <a href='/2010/wordpress-cms/'>WordPress’ als CMS</a> unterstützen. Wer also mit mehreren Autoren arbeitet oder einfach deutlich mehr als ein Blog braucht, findet hier hoffentlich etwas Neues.</p>
<h2>Cleverness To-Do List</h2>
<p><a rel="author" href='http://cleverness.org'>Cindy M. Kendrick</a> · <a href='http://cleverness.org/plugins/to-do-list/'>Pluginseite</a> · <a href="http://wordpress.org/extend/plugins/cleverness-to-do-list/">Download</a></p>
<p>Dieses Plugin zeigt offene Aufgaben in einem Dashboard-Widget und auf einer eigenen Seite unter »Werkzeuge«:</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/06/todolist-dashboard-widget.png" alt="Todolist-Dashboard-Widget" width="423" height="182" class="size-full wp-image-1698" /></p>
<p>Man kann jede Aufgabe einer bestimmten Person zuweisen, die dann per E-Mail informiert wird. Obendrein läßt sich jeder Punkt mit einer Priorität versehen, damit oben steht, was brennt. Die Optionen sind eingedeutscht und mit hilfreichen Links versehen. Vielleicht ein bißchen voll.</p>
<p>Der Code … stinkt. Er verpestet den globalen Namensraum mit Variablen wie <var>$action</var>, <var>$priority</var> oder <var>$id</var>. Meine Güte.<br />
Teste das Plugin erst lokal mit allen anderen Plugins, die du verwendest.</p>
<p>Das Plugin räumt sauber auf: Es entsorgt die Optionen und die Aufgabentabelle <code><var>$wpdb-&gt;prefix</var> . 'todolist'</code> bei der Deinstallation.</p>
<p>Projektmanagement en miniature. Hat fast alles, was ich mir in diesem Rahmen wünsche; nur Markup würde ich gerne noch in der Beschreibung zulassen.</p>
<h2>Simply Show IDs</h2>
<p><a rel="author" href="http://sivel.net/">Matt Martz</a> · <a href="http://sivel.net/wordpress/simply-show-ids/">Pluginseite</a> · <a href="http://wordpress.org/extend/plugins/simply-show-ids/">Download</a></p>
<p><img src="http://toscho.de/wp-content/uploads/2010/06/simply-show-ids.png" alt="Simply show IDs" width="148" height="360" class="alignright size-full wp-image-1699 border" /></p>
<p>Jeder Beitrag, jeder Nutzer und jede Kategorie hat in der Datenbank eine eindeutige Nummer, <a href="http://toscho.de/2010/wordpress-id-anhand-titel-herausfinden/">die ID</a>. Diese Nummer braucht man beispielsweise für <code>wp_list_pages()</code> oder den <a href="http://toscho.de/2010/wordpress-shortlinks-reloaded/">Shortlink</a>. Das Plugin fügt den Listen im Backend eine (abschaltbare) Spalte hinzu, in der die Nummer steht. </p>
<p>Prozeduraler Code, aber nur ein paar Funktionen mit dem Präfix <code>ssid_</code>.</p>
<p>Das dürfte WordPress ruhig gleich von Haus aus mitbringen. Ich würde die Spalte gerne einfacher für normale Autoren abschalten können.</p>
<h2>WP Mail from</h2>
<p>Tristan Aston · <a href="http://wordpress.org/extend/plugins/wp-mailfrom/">Download</a></p>
<p>Wenn WordPress eine Mail verschickt, dann vom frei erfundenen Konto wordpress@<var>$hostname</var> aus. Manche Server verweigern jedoch den Versand von nicht existierenden Konten, und auch sonst möchte man vielleicht lieber eine korrekte Adresse verwenden.</p>
<p>Das Plugin bietet die Option, Namen und Adresse zu ändern. Beide Werte werden in separaten Optionen – <code>site_mail_from_email</code> und <code>site_mail_from_name</code> – gespeichert und bei der Deinstallation <em>nicht aufgeräumt</em>.</p>
<p class="wideimg"><img src="http://toscho.de/wp-content/uploads/2010/06/mailfrom-options.png" alt="" title="Mailfrom-Optionen" width="468" height="206" class="size-full wp-image-1700 border" /></p>
<p>Der Code ist prozedural, die Funktionsnamen finde ich nicht ausreichend gegen Kollisionen gesichert: <code>site_mail_from()</code> schreit nach Ärger. </p>
<p>So nützlich und so schlampig … das werde ich mal neu fassen und in mein Standard-Mega-Plugin einbauen.</p>
<h2>Bulk Password Reset</h2>
<p><a rel="author" href="http://rubenwoudsma.nl/">Ruben Woudsma</a> · <a href="http://rubenwoudsma.nl/bulk-password-reset/">Pluginseite</a> · <a href="http://wordpress.org/extend/plugins/bulk-password-reset/">Download</a></p>
<p>Hiermit kann man die Passwörter aller Nutzer einer Gruppe zurücksetzen. Sehr hilfreich, wenn man ein <a href="http://toscho.de/2009/website-gehackt/">gehacktes Blog repariert</a> oder vielen Nutzern auf einen Ruck den Zugang erlauben möchte.</p>
<p><a href="http://toscho.de/wp-content/uploads/2010/06/bulk-password-reset-optionen.png"><img src="http://toscho.de/wp-content/uploads/2010/06/bulk-password-reset-optionen-300x179.png" alt="Bulk-Password-Reset-Optionen" width="300" height="179" class="alignnone size-medium wp-image-1701 border" /></a></p>
<p>Die Optionsseite sieht sehr unbeholfen aus; hier kann man die zu versendende E-Mail anpassen oder ganz verbieten. Ich empfehle dringend, vorher das Plugin <em>WP Mail from</em> zu installieren, damit Antworten der betroffenen Nutzer an eine reale Adresse gehen.<br />
Die Option – immerhin nur ein Array – heißt <code>bpr_options</code>. Die muß man leider manuell löschen, denn das Plugin <em>räumt beim Deinstallieren nicht auf</em>.</p>
<p>Objektorientierter Code, wirft aber Notizen. <abbr title="Objekt-orientierte Programmierung">OOP</abbr> allein ist eben auch kein Wundermittel.</p>
<p>In manchen Situationen einfach unersetzbar. Die Optionsseite sollte jedem angehenden Pluginautor als warnendes Beispiel dienen: So bitte nicht!</p>
<h2>Custom Post Templates</h2>
<p><a rel="author" href="http://www.simonwheatley.co.uk/">Simon Wheatley</a> · <a href="http://www.simonwheatley.co.uk/wordpress/custom-post-template/">Pluginseite</a> · <a href="http://wordpress.org/extend/plugins/custom-post-template/">Download</a></p>
<p>Für Seiten oder spezielle Archive kennt WordPress schon lange <a href="/2010/wordpress-alle-artikel-auflisten/">eigene Templates</a>; für Posts jedoch braucht man dieses Plugin.<br />
Ein Template wird durch folgenden Eintrag am Dateianfang gekennzeichnet:</p>
<pre class="notranslate">/*
Template Name Posts: Jungtiere
*/</pre>
<p><img src="http://toscho.de/wp-content/uploads/2010/06/post-template.png" alt="Custom Post Template" width="287" height="185" class="alignright size-full wp-image-1702" /></p>
<p>Dann bekommt man beim Schreiben eines Artikels ein Auswahlfeld wie bei den Seiten.</p>
<p>Zusätzlich stellt das Plugin noch eine Funktion <code style="white-space:normal">is_post_template(<var>$template</var> = '')</code> bereit.</p>
<p>Der Code ist sehr sauber, bis auf die is-Funktion objektorientiert. Optionen müssen bei der Deinstallation nicht aufgeräumt werden, denn das Plugin speichert keine. Das zugeordnete Template wird in einem Meta-Key namens <code>custom_post_template</code> gespeichert, und der bleibt erhalten.</p>
<p><strong>Ich will das im Core haben.</strong> Es ist nicht einzusehen, warum ein Blogsystem hier Seiten bevorzugt. Der Code könnte einen Tick besser dokumentiert werden … ansonsten ist er die reine Freude.</p>
<h2>Vice Versa </h2>
<p><a rel="author" href="http://jasonlau.biz/">Jason Lau</a> ·<br />
<a href="http://jasonlau.biz/home/wordpress/convert-pages-to-posts-vice-versa">Pluginseite</a> · <a href="http://wordpress.org/extend/plugins/vice-versa/">Download</a></p>
<p><a href="http://toscho.de/wp-content/uploads/2010/06/vice-versa-optionen.png"><img src="http://toscho.de/wp-content/uploads/2010/06/vice-versa-optionen-208x300.png" alt="Vice-Versa-Optionen" width="208" height="300" class="alignright size-medium wp-image-1703" /></a></p>
<p>Mit diesem Plugin kann man eine Seite in einen Artikel wandeln und umgekehrt – daher der Name. Irre praktisch, wenn man Inhalte aus einer statischen Seite in WordPress integriert und der Kunde sich mehrmals umentscheidet. Man kann auch Elternseiten und -kategorien auswählen. Warum der Autor seine Seite unter den »Einstellungen« aufgehängt hat und nicht unter »Werkzeuge«, bleibt sein Geheimnis. Nun, jedes Kunstwerk birgt ein Rätsel …</p>
<p>Der Code freilich treibt einem die Tränen in die Augen: <code>eregi()</code>, massenhaft Inline-Styles, die der Optionsseite gar nicht gut tun, <code>echo</code>-Orgien … das geht besser. Immerhin werden keine dauerhaften Optionen gesetzt; eine Deinstallation verläuft also schmerzlos.</p>
<p>Die Funktion könnte man auch per Datenbankabfrage direkt übernehmen, aber ich bin im Nachhinein doch dankbar, daß ich das nicht tun mußte. Ich wünsche mir hierfür noch die Umwandlung mehrer Einträge auf einen Ruck.</p>
<hr />
<p>Insgesamt habe ich mit allen hier vorgestellten Plugins gute Erfahrungen gemacht. Besonders <em>Simply Show IDs</em> und <em>Custom Post Templates</em> füllen offensichtliche Lücken. Hätte ich ein echtes Mitspracherecht, so würde ich sie sofort in den Core einbauen – und dafür <a href="http://core.trac.wordpress.org/ticket/13583">anderen Schrott</a> entsorgen.</p>
<p>Leider merkt man auch, daß im <a href="http://wordpress.org/extend/plugins/">Pluginverzeichnis</a> niemand darauf achtet, ob ein <a href="http://toscho.de/2010/wordpress-tutorial-ein-framebreaker-plugin-schreiben/">Plugin sauber geschrieben</a> wurde. Hier ist vielleicht auch die API zu locker. Ein <a href="http://toscho.de/2010/wordpress-tutorial-eigenes-widget-schreiben/">Widget</a> muß einer festen OO-Struktur folgen; ein Plugin jedoch kann jeder schreiben wie er will. Und genau das passiert auch.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-cms-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress-Tutorial: Eigenes Widget schreiben</title>
		<link>http://toscho.de/2010/wordpress-tutorial-eigenes-widget-schreiben/</link>
		<comments>http://toscho.de/2010/wordpress-tutorial-eigenes-widget-schreiben/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 13:45:14 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1693</guid>
		<description><![CDATA[Kleines Lehrstück am konkreten Beispiel eines Widgets, das eine Einschränkung der letzten Posts auf bestimmte Kategorien erlaubt.]]></description>
			<content:encoded><![CDATA[<p><img src="http://toscho.de/wp-content/uploads/2010/06/wp-widget-150.png" alt="" width="150" height="150" class="alignleft size-full wp-image-1694" /></p>
<p>Widgets liegen in der WordPress-Architektur irgendwo zwischen Theme und Plugin: Die eigene Funktionalität und das Aussehen sind meistens eng an vorhandenen Code gebunden, doch können sie auch ganz eigenständig erzeugt werden.<br />
Sie lassen sich in Sidebars einbetten; man kann sie aber auch »manuell« im Theme aufrufen mit der Funktion <code><a href="http://codex.wordpress.org/Template_Tags/the_widget">the_widget()</a></code>.</p>
<p>Die <a href="http://codex.wordpress.org/Widgets_API">Widgets-API</a> ist die einzige, die objektorientiertes Arbeiten <em>erzwingt</em> – deshalb eignet sie sich gut zum Lernen und gefahrlosen Ausprobieren, finde ich.<br />
Themes und Plugins hingegen dürfen komplett prozedural geschrieben werden. Werden sie leider oft auch.</p>
<p>Ein Widget muß die <code><a href="http://core.trac.wordpress.org/browser/trunk/wp-includes/widgets.php">Klasse WP_Widget</a></code> erweitern. Ein Konstruktor wird für den Aufruf gebraucht und eine Funktion <code>widget()</code> für die Ausgabe. Um den Speicherfresser <code>create_function()</code> zu umgehen, packe ich noch eine Funktion <code>register()</code> dazu. Das sieht im einfachsten Falle so aus:</p>
<table class="php-code">
<tr>
<td>
<pre class='line-numbers'><a id='mw1' href='#mw1'>1</a>
<a id='mw2' href='#mw2'>2</a>
<a id='mw3' href='#mw3'>3</a>
<a id='mw4' href='#mw4'>4</a>
<a id='mw5' href='#mw5'>5</a>
<a id='mw6' href='#mw6'>6</a>
<a id='mw7' href='#mw7'>7</a>
<a id='mw8' href='#mw8'>8</a>
<a id='mw9' href='#mw9'>9</a>
<a id='mw10' href='#mw10'>10</a>
<a id='mw11' href='#mw11'>11</a>
<a id='mw12' href='#mw12'>12</a>
<a id='mw13' href='#mw13'>13</a>
<a id='mw14' href='#mw14'>14</a>
<a id='mw15' href='#mw15'>15</a>
<a id='mw16' href='#mw16'>16</a>
<a id='mw17' href='#mw17'>17</a>
<a id='mw18' href='#mw18'>18</a>
<a id='mw19' href='#mw19'>19</a>
<a id='mw20' href='#mw20'>20</a>
<a id='mw21' href='#mw21'>21</a>
<a id='mw22' href='#mw22'>22</a>
</pre>
</td>
<td>
<pre class="notranslate php"><span class='openclose'>&lt;?php
</span>add_action(
    <span class='string'>&#039;widgets_init&#039;</span>
,   <span class='internal'>array</span> (<span class='string'>&#039;Toscho_Mini_Widget&#039;</span>, <span class='string'>&#039;register&#039;</span> )
);
<span class='internal'>class</span> Toscho_Mini_Widget <span class='internal'>extends</span> WP_Widget
{
    <span class='internal'>function</span> Toscho_Mini_Widget()
    {
        <var>$this</var><span class='operator'>-&gt;</span>WP_Widget(<span class='constant'>__CLASS__</span>, <span class='constant'>__CLASS__</span>);
    }

    <span class='internal'>function</span> widget(<var>$args</var>, <var>$instance</var>)
    {
        <span class='internal'>print</span> <span class='string'>&#039;Juhu, hat geklappt!&#039;</span>;
    }

    <span class='internal'>function</span> register()
    {
        register_widget(<span class='constant'>__CLASS__</span>);
    }
}</pre>
</td>
</tr>
</table>
<p>Hier müffelt es noch schlimm nach PHP 4. Wenn der Konstruktor nicht wie die Klasse heißt, läuft der Speicher aus … das müssen wir vorerst wohl hinnehmen.</p>
<p>Das Beispiel oben kann im Backend aktiviert werden, wenn es im Theme eingebunden wird <em>und</em> wenn das Theme mindestens eine <a href="http://codex.wordpress.org/Function_Reference/register_sidebar">Sidebar registriert</a> hat.</p>
<p>Es tut natürlich noch nicht viel.</p>
<p><a href="http://toscho.de/wp-content/uploads/2010/06/widget-restricted-recent-posts.png"><img src="http://toscho.de/wp-content/uploads/2010/06/widget-restricted-recent-posts-225x300.png" alt="Screenshot Eingabemaske" title="Eingabemaske in voller Größe ansehen" width="225" height="300" class="alignright size-medium wp-image-1695 border" /></a></p>
<p>Im nächsten Schritt sehen wir uns mal ein Beispiel an, das wir tatsächlich einsetzen könnten: Wir wollen die letzten Posts auflisten, dabei aber bestimmte Kategorien ausschließen oder zulassen.</p>
<p>Da können wir uns bei der Klasse <code>WP_Widget_Recent_Posts</code> einigen Code abgucken. Die liegt WordPress schon bei in der <a href="http://core.trac.wordpress.org/browser/trunk/wp-includes/default-widgets.php">default-widgets.php</a>.</p>
<p>Wir brauchen zusätzlich noch eine Eingabemaske für die Kategorien, und wir müssen den <a href="http://codex.wordpress.org/Function_Reference/WP_Query">Query</a> erweitern. Die nötigen Argumente finden wir in der Dokumentation zu <code><a href="http://codex.wordpress.org/Template_Tags/query_posts">query_posts()</a></code>.</p>
<p>Die beiden letzten Funktionen stammen nicht aus der Elternklasse, sondern ich habe sie eingebaut, um den Rest des Codes lesbar zu halten.</p>
<p>Live läuft genau dieses Widget gerade auf der Website der <a href="http://ig-bkh.de/">Interessengemeinschaft Britisch Kurzhaar-Katzen</a> links in der Sidebar; hier werden die <a href="http://ig-bkh.de/thema/jungtiere/">Jungtiermeldungen</a> ausgeklammert, weil sie schon sehr prominent auf der Startseite präsentiert werden.</p>
<table class="php-code">
<tr>
<td>
<pre class='line-numbers'><a id='ex11' href='#ex11'>1</a>
<a id='ex12' href='#ex12'>2</a>
<a id='ex13' href='#ex13'>3</a>
<a id='ex14' href='#ex14'>4</a>
<a id='ex15' href='#ex15'>5</a>
<a id='ex16' href='#ex16'>6</a>
<a id='ex17' href='#ex17'>7</a>
<a id='ex18' href='#ex18'>8</a>
<a id='ex19' href='#ex19'>9</a>
<a id='ex110' href='#ex110'>10</a>
<a id='ex111' href='#ex111'>11</a>
<a id='ex112' href='#ex112'>12</a>
<a id='ex113' href='#ex113'>13</a>
<a id='ex114' href='#ex114'>14</a>
<a id='ex115' href='#ex115'>15</a>
<a id='ex116' href='#ex116'>16</a>
<a id='ex117' href='#ex117'>17</a>
<a id='ex118' href='#ex118'>18</a>
<a id='ex119' href='#ex119'>19</a>
<a id='ex120' href='#ex120'>20</a>
<a id='ex121' href='#ex121'>21</a>
<a id='ex122' href='#ex122'>22</a>
<a id='ex123' href='#ex123'>23</a>
<a id='ex124' href='#ex124'>24</a>
<a id='ex125' href='#ex125'>25</a>
<a id='ex126' href='#ex126'>26</a>
<a id='ex127' href='#ex127'>27</a>
<a id='ex128' href='#ex128'>28</a>
<a id='ex129' href='#ex129'>29</a>
<a id='ex130' href='#ex130'>30</a>
<a id='ex131' href='#ex131'>31</a>
<a id='ex132' href='#ex132'>32</a>
<a id='ex133' href='#ex133'>33</a>
<a id='ex134' href='#ex134'>34</a>
<a id='ex135' href='#ex135'>35</a>
<a id='ex136' href='#ex136'>36</a>
<a id='ex137' href='#ex137'>37</a>
<a id='ex138' href='#ex138'>38</a>
<a id='ex139' href='#ex139'>39</a>
<a id='ex140' href='#ex140'>40</a>
<a id='ex141' href='#ex141'>41</a>
<a id='ex142' href='#ex142'>42</a>
<a id='ex143' href='#ex143'>43</a>
<a id='ex144' href='#ex144'>44</a>
<a id='ex145' href='#ex145'>45</a>
<a id='ex146' href='#ex146'>46</a>
<a id='ex147' href='#ex147'>47</a>
<a id='ex148' href='#ex148'>48</a>
<a id='ex149' href='#ex149'>49</a>
<a id='ex150' href='#ex150'>50</a>
<a id='ex151' href='#ex151'>51</a>
<a id='ex152' href='#ex152'>52</a>
<a id='ex153' href='#ex153'>53</a>
<a id='ex154' href='#ex154'>54</a>
<a id='ex155' href='#ex155'>55</a>
<a id='ex156' href='#ex156'>56</a>
<a id='ex157' href='#ex157'>57</a>
<a id='ex158' href='#ex158'>58</a>
<a id='ex159' href='#ex159'>59</a>
<a id='ex160' href='#ex160'>60</a>
<a id='ex161' href='#ex161'>61</a>
<a id='ex162' href='#ex162'>62</a>
<a id='ex163' href='#ex163'>63</a>
<a id='ex164' href='#ex164'>64</a>
<a id='ex165' href='#ex165'>65</a>
<a id='ex166' href='#ex166'>66</a>
<a id='ex167' href='#ex167'>67</a>
<a id='ex168' href='#ex168'>68</a>
<a id='ex169' href='#ex169'>69</a>
<a id='ex170' href='#ex170'>70</a>
<a id='ex171' href='#ex171'>71</a>
<a id='ex172' href='#ex172'>72</a>
<a id='ex173' href='#ex173'>73</a>
<a id='ex174' href='#ex174'>74</a>
<a id='ex175' href='#ex175'>75</a>
<a id='ex176' href='#ex176'>76</a>
<a id='ex177' href='#ex177'>77</a>
<a id='ex178' href='#ex178'>78</a>
<a id='ex179' href='#ex179'>79</a>
<a id='ex180' href='#ex180'>80</a>
<a id='ex181' href='#ex181'>81</a>
<a id='ex182' href='#ex182'>82</a>
<a id='ex183' href='#ex183'>83</a>
<a id='ex184' href='#ex184'>84</a>
<a id='ex185' href='#ex185'>85</a>
<a id='ex186' href='#ex186'>86</a>
<a id='ex187' href='#ex187'>87</a>
<a id='ex188' href='#ex188'>88</a>
<a id='ex189' href='#ex189'>89</a>
<a id='ex190' href='#ex190'>90</a>
<a id='ex191' href='#ex191'>91</a>
<a id='ex192' href='#ex192'>92</a>
<a id='ex193' href='#ex193'>93</a>
<a id='ex194' href='#ex194'>94</a>
<a id='ex195' href='#ex195'>95</a>
<a id='ex196' href='#ex196'>96</a>
<a id='ex197' href='#ex197'>97</a>
<a id='ex198' href='#ex198'>98</a>
<a id='ex199' href='#ex199'>99</a>
<a id='ex1100' href='#ex1100'>100</a>
<a id='ex1101' href='#ex1101'>101</a>
<a id='ex1102' href='#ex1102'>102</a>
<a id='ex1103' href='#ex1103'>103</a>
<a id='ex1104' href='#ex1104'>104</a>
<a id='ex1105' href='#ex1105'>105</a>
<a id='ex1106' href='#ex1106'>106</a>
<a id='ex1107' href='#ex1107'>107</a>
<a id='ex1108' href='#ex1108'>108</a>
<a id='ex1109' href='#ex1109'>109</a>
<a id='ex1110' href='#ex1110'>110</a>
<a id='ex1111' href='#ex1111'>111</a>
<a id='ex1112' href='#ex1112'>112</a>
<a id='ex1113' href='#ex1113'>113</a>
<a id='ex1114' href='#ex1114'>114</a>
<a id='ex1115' href='#ex1115'>115</a>
<a id='ex1116' href='#ex1116'>116</a>
<a id='ex1117' href='#ex1117'>117</a>
<a id='ex1118' href='#ex1118'>118</a>
<a id='ex1119' href='#ex1119'>119</a>
<a id='ex1120' href='#ex1120'>120</a>
<a id='ex1121' href='#ex1121'>121</a>
<a id='ex1122' href='#ex1122'>122</a>
<a id='ex1123' href='#ex1123'>123</a>
<a id='ex1124' href='#ex1124'>124</a>
<a id='ex1125' href='#ex1125'>125</a>
<a id='ex1126' href='#ex1126'>126</a>
<a id='ex1127' href='#ex1127'>127</a>
<a id='ex1128' href='#ex1128'>128</a>
<a id='ex1129' href='#ex1129'>129</a>
<a id='ex1130' href='#ex1130'>130</a>
<a id='ex1131' href='#ex1131'>131</a>
<a id='ex1132' href='#ex1132'>132</a>
<a id='ex1133' href='#ex1133'>133</a>
<a id='ex1134' href='#ex1134'>134</a>
<a id='ex1135' href='#ex1135'>135</a>
<a id='ex1136' href='#ex1136'>136</a>
<a id='ex1137' href='#ex1137'>137</a>
<a id='ex1138' href='#ex1138'>138</a>
<a id='ex1139' href='#ex1139'>139</a>
<a id='ex1140' href='#ex1140'>140</a>
<a id='ex1141' href='#ex1141'>141</a>
<a id='ex1142' href='#ex1142'>142</a>
<a id='ex1143' href='#ex1143'>143</a>
<a id='ex1144' href='#ex1144'>144</a>
<a id='ex1145' href='#ex1145'>145</a>
<a id='ex1146' href='#ex1146'>146</a>
<a id='ex1147' href='#ex1147'>147</a>
<a id='ex1148' href='#ex1148'>148</a>
<a id='ex1149' href='#ex1149'>149</a>
<a id='ex1150' href='#ex1150'>150</a>
<a id='ex1151' href='#ex1151'>151</a>
<a id='ex1152' href='#ex1152'>152</a>
<a id='ex1153' href='#ex1153'>153</a>
<a id='ex1154' href='#ex1154'>154</a>
<a id='ex1155' href='#ex1155'>155</a>
<a id='ex1156' href='#ex1156'>156</a>
<a id='ex1157' href='#ex1157'>157</a>
<a id='ex1158' href='#ex1158'>158</a>
<a id='ex1159' href='#ex1159'>159</a>
<a id='ex1160' href='#ex1160'>160</a>
<a id='ex1161' href='#ex1161'>161</a>
<a id='ex1162' href='#ex1162'>162</a>
<a id='ex1163' href='#ex1163'>163</a>
<a id='ex1164' href='#ex1164'>164</a>
<a id='ex1165' href='#ex1165'>165</a>
<a id='ex1166' href='#ex1166'>166</a>
<a id='ex1167' href='#ex1167'>167</a>
<a id='ex1168' href='#ex1168'>168</a>
<a id='ex1169' href='#ex1169'>169</a>
<a id='ex1170' href='#ex1170'>170</a>
<a id='ex1171' href='#ex1171'>171</a>
<a id='ex1172' href='#ex1172'>172</a>
<a id='ex1173' href='#ex1173'>173</a>
<a id='ex1174' href='#ex1174'>174</a>
<a id='ex1175' href='#ex1175'>175</a>
<a id='ex1176' href='#ex1176'>176</a>
<a id='ex1177' href='#ex1177'>177</a>
<a id='ex1178' href='#ex1178'>178</a>
<a id='ex1179' href='#ex1179'>179</a>
<a id='ex1180' href='#ex1180'>180</a>
<a id='ex1181' href='#ex1181'>181</a>
<a id='ex1182' href='#ex1182'>182</a>
<a id='ex1183' href='#ex1183'>183</a>
<a id='ex1184' href='#ex1184'>184</a>
<a id='ex1185' href='#ex1185'>185</a>
<a id='ex1186' href='#ex1186'>186</a>
<a id='ex1187' href='#ex1187'>187</a>
<a id='ex1188' href='#ex1188'>188</a>
<a id='ex1189' href='#ex1189'>189</a>
<a id='ex1190' href='#ex1190'>190</a>
<a id='ex1191' href='#ex1191'>191</a>
<a id='ex1192' href='#ex1192'>192</a>
<a id='ex1193' href='#ex1193'>193</a>
<a id='ex1194' href='#ex1194'>194</a>
<a id='ex1195' href='#ex1195'>195</a>
<a id='ex1196' href='#ex1196'>196</a>
<a id='ex1197' href='#ex1197'>197</a>
<a id='ex1198' href='#ex1198'>198</a>
<a id='ex1199' href='#ex1199'>199</a>
<a id='ex1200' href='#ex1200'>200</a>
<a id='ex1201' href='#ex1201'>201</a>
<a id='ex1202' href='#ex1202'>202</a>
<a id='ex1203' href='#ex1203'>203</a>
<a id='ex1204' href='#ex1204'>204</a>
<a id='ex1205' href='#ex1205'>205</a>
<a id='ex1206' href='#ex1206'>206</a>
<a id='ex1207' href='#ex1207'>207</a>
<a id='ex1208' href='#ex1208'>208</a>
<a id='ex1209' href='#ex1209'>209</a>
<a id='ex1210' href='#ex1210'>210</a>
<a id='ex1211' href='#ex1211'>211</a>
<a id='ex1212' href='#ex1212'>212</a>
<a id='ex1213' href='#ex1213'>213</a>
<a id='ex1214' href='#ex1214'>214</a>
<a id='ex1215' href='#ex1215'>215</a>
<a id='ex1216' href='#ex1216'>216</a>
<a id='ex1217' href='#ex1217'>217</a>
<a id='ex1218' href='#ex1218'>218</a>
<a id='ex1219' href='#ex1219'>219</a>
<a id='ex1220' href='#ex1220'>220</a>
<a id='ex1221' href='#ex1221'>221</a>
<a id='ex1222' href='#ex1222'>222</a>
<a id='ex1223' href='#ex1223'>223</a>
<a id='ex1224' href='#ex1224'>224</a>
<a id='ex1225' href='#ex1225'>225</a>
<a id='ex1226' href='#ex1226'>226</a>
<a id='ex1227' href='#ex1227'>227</a>
<a id='ex1228' href='#ex1228'>228</a>
<a id='ex1229' href='#ex1229'>229</a>
<a id='ex1230' href='#ex1230'>230</a>
<a id='ex1231' href='#ex1231'>231</a>
<a id='ex1232' href='#ex1232'>232</a>
<a id='ex1233' href='#ex1233'>233</a>
<a id='ex1234' href='#ex1234'>234</a>
<a id='ex1235' href='#ex1235'>235</a>
<a id='ex1236' href='#ex1236'>236</a>
<a id='ex1237' href='#ex1237'>237</a>
<a id='ex1238' href='#ex1238'>238</a>
<a id='ex1239' href='#ex1239'>239</a>
<a id='ex1240' href='#ex1240'>240</a>
<a id='ex1241' href='#ex1241'>241</a>
<a id='ex1242' href='#ex1242'>242</a>
<a id='ex1243' href='#ex1243'>243</a>
<a id='ex1244' href='#ex1244'>244</a>
<a id='ex1245' href='#ex1245'>245</a>
<a id='ex1246' href='#ex1246'>246</a>
<a id='ex1247' href='#ex1247'>247</a>
<a id='ex1248' href='#ex1248'>248</a>
<a id='ex1249' href='#ex1249'>249</a>
<a id='ex1250' href='#ex1250'>250</a>
<a id='ex1251' href='#ex1251'>251</a>
<a id='ex1252' href='#ex1252'>252</a>
<a id='ex1253' href='#ex1253'>253</a>
<a id='ex1254' href='#ex1254'>254</a>
<a id='ex1255' href='#ex1255'>255</a>
<a id='ex1256' href='#ex1256'>256</a>
<a id='ex1257' href='#ex1257'>257</a>
<a id='ex1258' href='#ex1258'>258</a>
<a id='ex1259' href='#ex1259'>259</a>
<a id='ex1260' href='#ex1260'>260</a>
<a id='ex1261' href='#ex1261'>261</a>
<a id='ex1262' href='#ex1262'>262</a>
<a id='ex1263' href='#ex1263'>263</a>
<a id='ex1264' href='#ex1264'>264</a>
<a id='ex1265' href='#ex1265'>265</a>
<a id='ex1266' href='#ex1266'>266</a>
<a id='ex1267' href='#ex1267'>267</a>
<a id='ex1268' href='#ex1268'>268</a>
<a id='ex1269' href='#ex1269'>269</a>
<a id='ex1270' href='#ex1270'>270</a>
<a id='ex1271' href='#ex1271'>271</a>
<a id='ex1272' href='#ex1272'>272</a>
<a id='ex1273' href='#ex1273'>273</a>
<a id='ex1274' href='#ex1274'>274</a>
<a id='ex1275' href='#ex1275'>275</a>
<a id='ex1276' href='#ex1276'>276</a>
<a id='ex1277' href='#ex1277'>277</a>
<a id='ex1278' href='#ex1278'>278</a>
<a id='ex1279' href='#ex1279'>279</a>
<a id='ex1280' href='#ex1280'>280</a>
<a id='ex1281' href='#ex1281'>281</a>
<a id='ex1282' href='#ex1282'>282</a>
<a id='ex1283' href='#ex1283'>283</a>
<a id='ex1284' href='#ex1284'>284</a>
<a id='ex1285' href='#ex1285'>285</a>
<a id='ex1286' href='#ex1286'>286</a>
<a id='ex1287' href='#ex1287'>287</a>
<a id='ex1288' href='#ex1288'>288</a>
<a id='ex1289' href='#ex1289'>289</a>
<a id='ex1290' href='#ex1290'>290</a>
<a id='ex1291' href='#ex1291'>291</a>
<a id='ex1292' href='#ex1292'>292</a>
<a id='ex1293' href='#ex1293'>293</a>
<a id='ex1294' href='#ex1294'>294</a>
<a id='ex1295' href='#ex1295'>295</a>
<a id='ex1296' href='#ex1296'>296</a>
<a id='ex1297' href='#ex1297'>297</a>
<a id='ex1298' href='#ex1298'>298</a>
<a id='ex1299' href='#ex1299'>299</a>
</pre>
</td>
<td>
<pre class="notranslate php"><span class='openclose'>&lt;?php
</span>add_action(
    <span class='string'>&#039;widgets_init&#039;</span>
,   <span class='internal'>array</span> (<span class='string'>&#039;Restricted_Latest_Posts_Widget&#039;</span>, <span class='string'>&#039;register&#039;</span> )
);
<i class='comment'>/**
 * Restricted Recent Posts widget class.
 *
 * Restricts the list of recent posts to selected categories.
 * Derivate of the default widget.
 *
 * @todo Select post types
 * @todo Select taxonomy
 */</i>
<span class='internal'>class</span> Restricted_Latest_Posts_Widget <span class='internal'>extends</span> WP_Widget
{
    <i class='comment'>// Adjust this to your needs.
</i>    <span class='internal'>var</span>
        <var>$max_posts</var> <span class='operator'>=</span> 50
    ,   <var>$wid_name</var>  <span class='operator'>=</span> <span class='string'>&#039;widget_restricted_recent_posts&#039;</span>;

    <i class='comment'>/**
     * Constructor.
     */</i>
    <span class='internal'>function</span> Restricted_Latest_Posts_Widget()
    {
        <var>$widget_ops</var> <span class='operator'>=</span> <span class='internal'>array</span>(
            <span class='string'>&#039;classname&#039;</span>   <span class='operator'>=&gt;</span> <var>$this</var><span class='operator'>-&gt;</span>wid_name
        ,   <span class='string'>&#039;description&#039;</span> <span class='operator'>=&gt;</span> <span class='string'>&#039;Letzte Beiträge per Kategorie ausgewählt.
                                Mit Komma trennen.&#039;</span>
        );
        <var>$this</var><span class='operator'>-&gt;</span>WP_Widget(
            <span class='string'>&#039;restricted-recent-posts&#039;</span>
        ,   <span class='string'>&#039;Restricted Recent Posts&#039;</span>
        ,   <var>$widget_ops</var>
        );
        <var>$this</var><span class='operator'>-&gt;</span>alt_option_name <span class='operator'>=</span> <var>$this</var><span class='operator'>-&gt;</span>wid_name;

        add_action( <span class='string'>&#039;save_post&#039;</span>,
            <span class='internal'>array</span>(&amp;<var>$this</var>, <span class='string'>&#039;flush_widget_cache&#039;</span>) );
        add_action( <span class='string'>&#039;deleted_post&#039;</span>,
            <span class='internal'>array</span>(&amp;<var>$this</var>, <span class='string'>&#039;flush_widget_cache&#039;</span>) );
        add_action( <span class='string'>&#039;switch_theme&#039;</span>,
            <span class='internal'>array</span>(&amp;<var>$this</var>, <span class='string'>&#039;flush_widget_cache&#039;</span>) );
    }

    <i class='comment'>/**
     * Called statically to register the widget.
     *
     * @return void.
     */</i>
    <span class='internal'>function</span> register()
    {
        register_widget(<span class='constant'>__CLASS__</span>);
    }

    <span class='internal'>function</span> widget(<var>$args</var>, <var>$instance</var>)
    {
        <var>$cache</var> <span class='operator'>=</span> wp_cache_get(<var>$this</var><span class='operator'>-&gt;</span>wid_name, <span class='string'>&#039;widget&#039;</span>);

        <span class='internal'>if</span> ( <span class='operator'>!</span> <a href='http://php.net/is_array'>is_array</a>(<var>$cache</var>) )
        {
            <var>$cache</var> <span class='operator'>=</span> <span class='internal'>array</span>();
        }

        <span class='internal'>if</span> ( <span class='internal'>isset</span> ( <var>$cache</var>[ <var>$args</var>[<span class='string'>&#039;widget_id&#039;</span>] ] ) )
        {
            <span class='internal'>echo</span> <var>$cache</var>[ <var>$args</var>[<span class='string'>&#039;widget_id&#039;</span>] ];
            <span class='internal'>return</span>;
        }

        <a href='http://php.net/ob_start'>ob_start</a>();
        <a href='http://php.net/extract'>extract</a>(<var>$args</var>);

        <var>$title</var>        <span class='operator'>=</span> <span class='internal'>empty</span> ( <var>$instance</var>[<span class='string'>&#039;title&#039;</span>] )
                        <span class='operator'>?</span> <span class='string'>&#039;Restricted Recent Posts&#039;</span>
                        <span class='operator'>:</span> <var>$instance</var>[<span class='string'>&#039;title&#039;</span>];
        <var>$title</var>        <span class='operator'>=</span> apply_filters(<span class='string'>&#039;widget_title&#039;</span>, <var>$title</var>);

        <var>$number</var>       <span class='operator'>=</span> <var>$this</var><span class='operator'>-&gt;</span>sanitize_number(<var>$instance</var>[<span class='string'>&#039;number&#039;</span>]);

        <var>$include_cats</var> <span class='operator'>=</span> <a href='http://php.net/trim'>trim</a>(<var>$instance</var>[<span class='string'>&#039;include_cats&#039;</span>]);
        <var>$exclude_cats</var> <span class='operator'>=</span> <a href='http://php.net/trim'>trim</a>(<var>$instance</var>[<span class='string'>&#039;exclude_cats&#039;</span>]);

        <var>$query_args</var>   <span class='operator'>=</span> <span class='internal'>array</span>(
            <span class='string'>&#039;showposts&#039;</span>        <span class='operator'>=&gt;</span> <var>$number</var>
        ,   <span class='string'>&#039;nopaging&#039;</span>         <span class='operator'>=&gt;</span> 0
        ,   <span class='string'>&#039;post_status&#039;</span>      <span class='operator'>=&gt;</span> <span class='string'>&#039;publish&#039;</span>
        ,   <span class='string'>&#039;caller_get_posts&#039;</span> <span class='operator'>=&gt;</span> 1
        );

        <span class='internal'>if</span> ( <span class='operator'>!</span> <span class='internal'>empty</span> ( <var>$include_cats</var> ) )
        {
            <var>$query_args</var>[<span class='string'>&#039;category__in&#039;</span>]
                <span class='operator'>=</span> <var>$this</var><span class='operator'>-&gt;</span>catlist_to_array(<var>$include_cats</var>);
        }
        <span class='internal'>elseif</span> ( <span class='operator'>!</span> <span class='internal'>empty</span> ( <var>$exclude_cats</var> ) )
        {
            <var>$query_args</var>[<span class='string'>&#039;category__not_in&#039;</span>]
                <span class='operator'>=</span> <var>$this</var><span class='operator'>-&gt;</span>catlist_to_array(<var>$exclude_cats</var>);
        }

        <var>$r</var> <span class='operator'>=</span> <span class='internal'>new</span> WP_Query(<var>$query_args</var>);

        <span class='internal'>if</span> ( <var>$r</var><span class='operator'>-&gt;</span>have_posts() )
        {
            <span class='internal'>print</span> <var>$before_widget</var>
                <span class='operator'>.</span> ( <var>$title</var>
                        <span class='operator'>?</span> <var>$before_title</var> <span class='operator'>.</span> <var>$title</var> <span class='operator'>.</span> <var>$after_title</var> <span class='operator'>:</span> <span class='string'>&#039;&#039;</span>
                    )
                <span class='operator'>.</span> <span class='string'>&#039;&lt;ul&gt;&#039;</span>;

            <span class='internal'>while</span> ( <var>$r</var><span class='operator'>-&gt;</span>have_posts() )
            {
                <var>$r</var><span class='operator'>-&gt;</span>the_post();

                <span class='internal'>print</span> <span class='string'>&#039;&lt;li&gt;&lt;a href=&quot;&#039;</span> <span class='operator'>.</span> get_permalink() <span class='operator'>.</span> <span class='string'>&#039;&quot;&gt;&#039;</span>
                    <span class='operator'>.</span> get_the_title() <span class='operator'>.</span> <span class='string'>&#039;&lt;/a&gt;&lt;/li&gt;&#039;</span>;
            }

            <span class='internal'>print</span> &quot;<span class='string'>&lt;/ul&gt;</span><var>$after_widget</var>&quot;;

            <i class='comment'>// Restore global post data stomped by the_post().
</i>            wp_reset_query();
        }

        <var>$cache</var>[ <var>$args</var>[<span class='string'>&#039;widget_id&#039;</span>] ] <span class='operator'>=</span> <a href='http://php.net/ob_get_flush'>ob_get_flush</a>();

        wp_cache_add(<var>$this</var><span class='operator'>-&gt;</span>wid_name, <var>$cache</var>, <span class='string'>&#039;widget&#039;</span>);
    }

    <span class='internal'>function</span> update( <var>$new_instance</var>, <var>$old_instance</var> )
    {
        <var>$instance</var>                 <span class='operator'>=</span> <var>$old_instance</var>;
        <var>$instance</var>[<span class='string'>&#039;title&#039;</span>]        <span class='operator'>=</span> <a href='http://php.net/strip_tags'>strip_tags</a>(<var>$new_instance</var>[<span class='string'>&#039;title&#039;</span>]);
        <var>$instance</var>[<span class='string'>&#039;number&#039;</span>]       <span class='operator'>=</span>
                <var>$this</var><span class='operator'>-&gt;</span>sanitize_number(<var>$new_instance</var>[<span class='string'>&#039;number&#039;</span>]);
        <var>$instance</var>[<span class='string'>&#039;exclude_cats&#039;</span>] <span class='operator'>=</span> <var>$new_instance</var>[<span class='string'>&#039;exclude_cats&#039;</span>];
        <var>$instance</var>[<span class='string'>&#039;include_cats&#039;</span>] <span class='operator'>=</span> <var>$new_instance</var>[<span class='string'>&#039;include_cats&#039;</span>];

        <var>$this</var><span class='operator'>-&gt;</span>flush_widget_cache();

        <var>$alloptions</var> <span class='operator'>=</span> wp_cache_get( <span class='string'>&#039;alloptions&#039;</span>, <span class='string'>&#039;options&#039;</span> );

        <span class='internal'>if</span> ( <span class='internal'>isset</span> ( <var>$alloptions</var>[<var>$this</var><span class='operator'>-&gt;</span>wid_name] ) )
        {
            delete_option(<var>$this</var><span class='operator'>-&gt;</span>wid_name);
        }

        <span class='internal'>return</span> <var>$instance</var>;
    }

    <span class='internal'>function</span> flush_widget_cache()
    {
        wp_cache_delete(<var>$this</var><span class='operator'>-&gt;</span>wid_name, <span class='string'>&#039;widget&#039;</span>);
    }

    <span class='internal'>function</span> form( <var>$instance</var> )
    {
        <var>$title</var> <span class='operator'>=</span> <span class='internal'>isset</span> ( <var>$instance</var>[<span class='string'>&#039;title&#039;</span>] )
                <span class='operator'>?</span> esc_attr(<var>$instance</var>[<span class='string'>&#039;title&#039;</span>]) <span class='operator'>:</span> <span class='string'>&#039;&#039;</span>;

        <span class='internal'>if</span> (   <span class='operator'>!</span> <span class='internal'>isset</span> ( <var>$instance</var>[<span class='string'>&#039;number&#039;</span>])
            <span class='operator'>||</span> <span class='operator'>!</span> <var>$number</var> <span class='operator'>=</span> (int) <var>$instance</var>[<span class='string'>&#039;number&#039;</span>]
        )
        {
            <var>$number</var> <span class='operator'>=</span> 5;
        }

        <var>$incats</var> <span class='operator'>=</span> <span class='internal'>isset</span> ( <var>$instance</var>[<span class='string'>&#039;include_cats&#039;</span>] )
            <span class='operator'>?</span> esc_attr(<var>$instance</var>[<span class='string'>&#039;include_cats&#039;</span>]) <span class='operator'>:</span> <span class='string'>&#039;&#039;</span>;
        <var>$excats</var> <span class='operator'>=</span> <span class='internal'>isset</span> ( <var>$instance</var>[<span class='string'>&#039;exclude_cats&#039;</span>] )
            <span class='operator'>?</span> esc_attr(<var>$instance</var>[<span class='string'>&#039;exclude_cats&#039;</span>]) <span class='operator'>:</span> <span class='string'>&#039;&#039;</span>;
        <span class='openclose'>?&gt;
</span>        &lt;p&gt;
            &lt;label for=&quot;<span class='openclose'>&lt;?php
</span>                <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;title&#039;</span>);
            <span class='openclose'>?&gt;</span>&quot;&gt;
                <span class='openclose'>&lt;?php
</span>                    _e(<span class='string'>&#039;Title:&#039;</span>);
                <span class='openclose'>?&gt;
</span>            &lt;/label&gt;
            &lt;input class=&quot;widefat&quot;
                id=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;title&#039;</span>);
                <span class='openclose'>?&gt;</span>&quot;
                name=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_name(<span class='string'>&#039;title&#039;</span>);
                <span class='openclose'>?&gt;</span>&quot;
                type=&quot;text&quot;
                value=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$title</var>;
                <span class='openclose'>?&gt;</span>&quot;
            /&gt;
        &lt;/p&gt;

        &lt;p&gt;
            &lt;label for=&quot;<span class='openclose'>&lt;?php
</span>                <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;number&#039;</span>);
            <span class='openclose'>?&gt;</span>&quot;&gt;
                Artikelmenge
            &lt;/label&gt;
            &lt;input id=&quot;<span class='openclose'>&lt;?php
</span>                <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;number&#039;</span>);
            <span class='openclose'>?&gt;</span>&quot;
                name=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_name(<span class='string'>&#039;number&#039;</span>);
                <span class='openclose'>?&gt;</span>&quot;
                type=&quot;text&quot;
                value=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$number</var>;
                <span class='openclose'>?&gt;</span>&quot;
                size=&quot;3&quot; /&gt;
            &lt;small&gt;(maximal <span class='openclose'>&lt;?php
</span>                <span class='internal'>print</span> <var>$this</var><span class='operator'>-&gt;</span>max_posts;
            <span class='openclose'>?&gt;</span>)&lt;/small&gt;
        &lt;/p&gt;

        &lt;p&gt;
            &lt;label for=&quot;<span class='openclose'>&lt;?php
</span>                <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;include_cats&#039;</span>);
            <span class='openclose'>?&gt;</span>&quot;&gt;
                Auf Kategorien beschränken:
            &lt;/label&gt;
            &lt;input id=&quot;<span class='openclose'>&lt;?php
</span>                <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;include_cats&#039;</span>);
            <span class='openclose'>?&gt;</span>&quot;
                name=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_name(<span class='string'>&#039;include_cats&#039;</span>);
                <span class='openclose'>?&gt;</span>&quot;
                type=&quot;text&quot;
                value=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$incats</var>;
                <span class='openclose'>?&gt;</span>&quot;
                size=&quot;10&quot;
            /&gt;
            &lt;br /&gt;&lt;strong&gt;oder&lt;/strong&gt;&lt;br /&gt;
            &lt;label for=&quot;<span class='openclose'>&lt;?php
</span>                <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;exclude_cats&#039;</span>);
            <span class='openclose'>?&gt;</span>&quot;&gt;
                Kategorien ausschließen:
            &lt;/label&gt;
            &lt;input id=&quot;<span class='openclose'>&lt;?php
</span>                <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_id(<span class='string'>&#039;exclude_cats&#039;</span>);
            <span class='openclose'>?&gt;</span>&quot;
                name=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$this</var><span class='operator'>-&gt;</span>get_field_name(<span class='string'>&#039;exclude_cats&#039;</span>);
                <span class='openclose'>?&gt;</span>&quot;
                type=&quot;text&quot;
                value=&quot;<span class='openclose'>&lt;?php
</span>                    <span class='internal'>echo</span> <var>$excats</var>;
                <span class='openclose'>?&gt;</span>&quot;
                size=&quot;10&quot;
            /&gt;
        &lt;/p&gt;
        <span class='openclose'>&lt;?php
</span>    }

    <i class='comment'>/**
     * Guarantee a number between 1 and max_posts.
     *
     * @return int
     */</i>
    <span class='internal'>function</span> sanitize_number(<var>$nr</var>)
    {
        <var>$nr</var> <span class='operator'>=</span> (int) <var>$nr</var>;

        <span class='internal'>if</span> ( <var>$nr</var> &gt; <var>$this</var><span class='operator'>-&gt;</span>max_posts )
        {
            <span class='internal'>return</span> <var>$this</var><span class='operator'>-&gt;</span>max_posts;
        }

        <span class='internal'>if</span> ( 0 <span class='operator'>==</span> <var>$nr</var> )
        {
            <span class='internal'>return</span> 1;
        }

        <span class='internal'>return</span> <var>$nr</var>;
    }

    <i class='comment'>/**
     * Used by widget() to fill the category parameter.
     *
     * @param string $catlist
     * @return array
     */</i>
    <span class='internal'>function</span> catlist_to_array(<var>$catlist</var>)
    {
        <var>$tmp_cats</var> <span class='operator'>=</span> <a href='http://php.net/explode'>explode</a>(<span class='string'>&#039;,&#039;</span>, <var>$catlist</var>);
        <var>$new_cats</var> <span class='operator'>=</span> <span class='internal'>array</span> ();

        <span class='internal'>foreach</span> ( <var>$tmp_cats</var> <span class='internal'>as</span> <var>$cat</var> )
        {
            <var>$new_cats</var>[] <span class='operator'>=</span> (int) <a href='http://php.net/trim'>trim</a>(<var>$cat</var>);
        }

        <span class='internal'>return</span> <var>$new_cats</var>;
    }
}</pre>
</td>
</tr>
</table>
<p>Zwei mögliche Erweiterungen habe ich im Kopf angedeutet. Wer will es versuchen?</p>
<p>Eine sehr viel umfangreichere Erweiterung der WordPress-internen Widgets liefert <a href="http://justintadlock.com/archives/2008/12/09/widgets-reloaded-wordpress-plugin">Justin Tadlocks Plugin Widgets Reloaded</a>. Sehr praktisch – und von dem sauberen Code kann man eine Menge lernen.</p>
<p>Siehe auch:</p>
<ul>
<li><a href="http://toscho.de/2010/wordpress-tutorial-ein-framebreaker-plugin-schreiben/">WordPress-Tutorial: Ein Framebreaker-Plugin schreiben</a></li>
<li><a href="http://toscho.de/2010/wordpress-alle-artikel-auflisten/">WordPress: Alle Artikel auflisten</a></li>
<li><a href="http://toscho.de/2009/wordpress-parallele-widgets/">WordPress: Parallele Widgets</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-tutorial-eigenes-widget-schreiben/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WordPress: ID anhand des Titels herausfinden</title>
		<link>http://toscho.de/2010/wordpress-id-anhand-titel-herausfinden/</link>
		<comments>http://toscho.de/2010/wordpress-id-anhand-titel-herausfinden/#comments</comments>
		<pubDate>Tue, 25 May 2010 13:31:25 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1683</guid>
		<description><![CDATA[Ein kleiner Helfer, mit dem sich die WordPress-Funktionen leichter bestücken lassen.]]></description>
			<content:encoded><![CDATA[<p><img src="http://toscho.de/wp-content/uploads/2010/05/wp-id-150.png" alt="" width="150" height="150" class="alignleft size-full wp-image-1684" style="margin-top:-5px" /></p>
<p>Viele Template-Funktionen in WordPress erwarten eine ID als Argument – <a href="http://codex.wordpress.org/Template_Tags/wp_list_pages">wp_list_pages()</a> beispielsweise schließt damit einzelne Seiten aus.<br />
Damit ich nun nicht immer suchen muß, habe ich mir einen kleinen Helfer in die Template-Tools gesetzt. Auszug:</p>
<table class="php-code" style="clear:left">
<tr>
<td>
<pre class='line-numbers'><a id='ex11' href='#ex11'>1</a>
<a id='ex12' href='#ex12'>2</a>
<a id='ex13' href='#ex13'>3</a>
<a id='ex14' href='#ex14'>4</a>
<a id='ex15' href='#ex15'>5</a>
<a id='ex16' href='#ex16'>6</a>
<a id='ex17' href='#ex17'>7</a>
<a id='ex18' href='#ex18'>8</a>
<a id='ex19' href='#ex19'>9</a>
<a id='ex110' href='#ex110'>10</a>
<a id='ex111' href='#ex111'>11</a>
<a id='ex112' href='#ex112'>12</a>
<a id='ex113' href='#ex113'>13</a>
<a id='ex114' href='#ex114'>14</a>
<a id='ex115' href='#ex115'>15</a>
<a id='ex116' href='#ex116'>16</a>
<a id='ex117' href='#ex117'>17</a>
<a id='ex118' href='#ex118'>18</a>
<a id='ex119' href='#ex119'>19</a>
<a id='ex120' href='#ex120'>20</a>
<a id='ex121' href='#ex121'>21</a>
<a id='ex122' href='#ex122'>22</a>
<a id='ex123' href='#ex123'>23</a>
<a id='ex124' href='#ex124'>24</a>
<a id='ex125' href='#ex125'>25</a>
<a id='ex126' href='#ex126'>26</a>
<a id='ex127' href='#ex127'>27</a>
<a id='ex128' href='#ex128'>28</a>
<a id='ex129' href='#ex129'>29</a>
<a id='ex130' href='#ex130'>30</a>
<a id='ex131' href='#ex131'>31</a>
<a id='ex132' href='#ex132'>32</a>
<a id='ex133' href='#ex133'>33</a>
<a id='ex134' href='#ex134'>34</a>
<a id='ex135' href='#ex135'>35</a>
<a id='ex136' href='#ex136'>36</a>
<a id='ex137' href='#ex137'>37</a>
<a id='ex138' href='#ex138'>38</a>
<a id='ex139' href='#ex139'>39</a>
<a id='ex140' href='#ex140'>40</a>
<a id='ex141' href='#ex141'>41</a>
<a id='ex142' href='#ex142'>42</a>
<a id='ex143' href='#ex143'>43</a>
<a id='ex144' href='#ex144'>44</a>
<a id='ex145' href='#ex145'>45</a>
<a id='ex146' href='#ex146'>46</a>
<a id='ex147' href='#ex147'>47</a>
<a id='ex148' href='#ex148'>48</a>
<a id='ex149' href='#ex149'>49</a>
<a id='ex150' href='#ex150'>50</a>
<a id='ex151' href='#ex151'>51</a>
<a id='ex152' href='#ex152'>52</a>
<a id='ex153' href='#ex153'>53</a>
<a id='ex154' href='#ex154'>54</a>
<a id='ex155' href='#ex155'>55</a>
<a id='ex156' href='#ex156'>56</a>
<a id='ex157' href='#ex157'>57</a>
<a id='ex158' href='#ex158'>58</a>
<a id='ex159' href='#ex159'>59</a>
<a id='ex160' href='#ex160'>60</a>
<a id='ex161' href='#ex161'>61</a>
<a id='ex162' href='#ex162'>62</a>
<a id='ex163' href='#ex163'>63</a>
<a id='ex164' href='#ex164'>64</a>
<a id='ex165' href='#ex165'>65</a>
<a id='ex166' href='#ex166'>66</a>
<a id='ex167' href='#ex167'>67</a>
<a id='ex168' href='#ex168'>68</a>
<a id='ex169' href='#ex169'>69</a>
<a id='ex170' href='#ex170'>70</a>
<a id='ex171' href='#ex171'>71</a>
<a id='ex172' href='#ex172'>72</a>
<a id='ex173' href='#ex173'>73</a>
<a id='ex174' href='#ex174'>74</a>
<a id='ex175' href='#ex175'>75</a>
<a id='ex176' href='#ex176'>76</a>
</pre>
</td>
<td>
<pre class="notranslate php"><span class='openclose'>&lt;?php
</span><i class='comment'>/**
 * Toscho’s Template Tools
 *
 * Helpers for WordPress templates.
 *
 * @author  Thomas Scholz &lt;info@toscho.de&gt;
 * @version 1.1
 *
 */</i>
<span class='internal'>class</span> TTT
{
    <i class='comment'>/**
     * Retrieves a post/page/custom-type/taxonomy ID by its title.
     *
     * Returns only the first result. If you search for a post title
     * that you have used more than once, restrict the type.
     * Or don’t use this function. :)
     * Simple usage:
     * $page_start_id = TTT::id_by_title(&#039;Start&#039;);
     *
     * To get the ID of a taxonomy (category, tag, custom) set $tax
     * to the name of this taxonomy.
     * Example:
     * $cat_css_id = TTT::id_by_title(&#039;CSS&#039;, 0, &#039;category&#039;);
     *
     * The result is cached internally to save db queries.
     *
     * @param  string      $title
     * @param  string      $type Restrict the type.
     * @param  string|bool $tax Taxonomy to search for.
     * @return int         ID or -1 on failure
     */</i>
    <span class='internal'>static</span> <span class='internal'>function</span> id_by_title(<var>$title</var>, <var>$type</var> <span class='operator'>=</span> <span class='string'>&#039;any&#039;</span>, <var>$tax</var> <span class='operator'>=</span> <span class='internal'>FALSE</span>)
    {
        <span class='internal'>static</span> <var>$cache</var> <span class='operator'>=</span> <span class='internal'>array</span> ();

        <var>$title</var> <span class='operator'>=</span> <a href='http://php.net/mysql_real_escape_string'>mysql_real_escape_string</a>( <a href='http://php.net/trim'>trim</a>(<var>$title</var>, <span class='string'>&#039;&quot;\&#039;&#039;</span>) );

        <i class='comment'>// Unique index for the cache.
</i>        <var>$index</var> <span class='operator'>=</span> &quot;<var>$title</var><span class='string'>-</span><var>$type</var><span class='string'>-</span>&quot; <span class='operator'>.</span> ( <var>$tax</var> <span class='operator'>?</span> <var>$tax</var> <span class='operator'>:</span> 0 );

        <span class='internal'>if</span> ( <span class='internal'>isset</span> ( <var>$cache</var>[<var>$index</var>] ) )
        {
            <span class='internal'>return</span> <var>$cache</var>[<var>$index</var>];
        }

        <span class='internal'>if</span> ( <var>$tax</var> )
        {
            <var>$taxonomy</var>      <span class='operator'>=</span> get_term_by(<span class='string'>&#039;name&#039;</span>, <var>$title</var>, <var>$tax</var>);
            <var>$cache</var>[<var>$index</var>] <span class='operator'>=</span> <var>$taxonomy</var> <span class='operator'>?</span> <var>$taxonomy</var><span class='operator'>-&gt;</span>term_id <span class='operator'>:</span> <span class='operator'>-</span>1;

            <span class='internal'>return</span> <var>$cache</var>[<var>$index</var>];
        }

        <var>$type_sql</var> <span class='operator'>=</span> <span class='string'>&#039;any&#039;</span> <span class='operator'>==</span> <var>$type</var>
            <span class='operator'>?</span> <span class='string'>&#039;&#039;</span>
            <span class='operator'>:</span> <span class='string'>&quot;AND post_type = &#039;&quot;</span>
                <span class='operator'>.</span> <a href='http://php.net/mysql_real_escape_string'>mysql_real_escape_string</a>(<var>$type</var>) <span class='operator'>.</span> <span class='string'>&quot;&#039;&quot;</span>;

        <span class='internal'>global</span> <var>$wpdb</var>;

        <var>$query</var> <span class='operator'>=</span> &quot;<span class='string'>SELECT ID FROM </span><var>$wpdb</var><span class='operator'>-&gt;</span>posts<span class='string'>
            WHERE (
                    post_status = &#039;publish&#039;
                AND post_title = &#039;</span><var>$title</var><span class='string'>&#039;
                </span><var>$type_sql</var><span class='string'>
            )
            LIMIT 1</span>&quot;;

        <var>$result</var> <span class='operator'>=</span> <var>$wpdb</var><span class='operator'>-&gt;</span>get_results(<var>$query</var>);
        <var>$cache</var>[<var>$index</var>] <span class='operator'>=</span> <span class='internal'>empty</span> ( <var>$result</var> ) <span class='operator'>?</span> <span class='operator'>-</span>1 <span class='operator'>:</span> (int) <var>$result</var>[0]<span class='operator'>-&gt;</span>ID;

        <span class='internal'>return</span> <var>$cache</var>[<var>$index</var>];
    }
}</pre>
</td>
</tr>
</table>
<p>Im praktischen Einsatz sieht das dann so aus:</p>
<table class="php-code">
<tr>
<td>
<pre class='line-numbers'><a id='ey11' href='#ey11'>1</a>
<a id='ey12' href='#ey12'>2</a>
<a id='ey13' href='#ey13'>3</a>
<a id='ey14' href='#ey14'>4</a>
<a id='ey15' href='#ey15'>5</a>
<a id='ey16' href='#ey16'>6</a>
<a id='ey17' href='#ey17'>7</a>
<a id='ey18' href='#ey18'>8</a>
<a id='ey19' href='#ey19'>9</a>
<a id='ey20' href='#ey20'>10</a>
</pre>
</td>
<td>
<pre class="notranslate php"><span class='openclose'>&lt;?php
</span>wp_list_pages(
    <span class='internal'>array</span> (
        <span class='string'>&#039;sort_column&#039;</span>   <span class='operator'>=&gt;</span>  <span class='string'>&#039;menu_order&#039;</span>,
        <span class='string'>&#039;depth&#039;</span>         <span class='operator'>=&gt;</span>  1,
        <span class='string'>&#039;title_li&#039;</span>      <span class='operator'>=&gt;</span>  <span class='string'>&#039;&#039;</span>,
        <span class='string'>&#039;exclude&#039;</span>       <span class='operator'>=&gt;</span>  TTT<span class='operator'>::</span>id_by_title(<span class='string'>&#039;Start&#039;</span>)
    )
);
<span class='openclose'>?&gt;</span></pre>
</td>
</tr>
</table>
<p>Vorsicht: Wenn man einen Titel mehrmals verwendet hat, liefert die Funktion eventuell nicht die ID zurück, die man sich erhofft hat.</p>
<p>Im Backend findet man die meisten IDs übrigens am besten mit Hilfe dieses ungeheuer nützlichen Plugins: <a href="http://wordpress.org/extend/plugins/simply-show-ids/">Simply Show IDs</a>. </p>
<p>Mehr solches Zeug:</p>
<ul>
<li><a href="http://toscho.de/2010/wordpress-auszug-zeichenzahl/">Auszug mit bestimmter Zeichenzahl</a></li>
<li><a href="http://toscho.de/2010/wordpress-alle-artikel-auflisten/">Alle Artikel auflisten</a></li>
<li><a href="http://toscho.de/2009/wordpress-administrator-php-herausfinden/">Administrator mit PHP herausfinden</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-id-anhand-titel-herausfinden/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Browser-ABC</title>
		<link>http://toscho.de/2010/browser-abc/</link>
		<comments>http://toscho.de/2010/browser-abc/#comments</comments>
		<pubDate>Sun, 16 May 2010 06:35:03 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Browser]]></category>
		<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1680</guid>
		<description><![CDATA[Welche Seiten mir der Browser anbietet, wenn ich nur einen Buchstaben in das Adressfeld eintippe.]]></description>
			<content:encoded><![CDATA[<p>Ich bin gerade erst darüber gestolpert – Sonntagmorgen, fragt nicht! – <a href="http://leumund.ch/browser-abc-008247">Christian Leu listet auf</a>, welche Seite ihm der Browser für jeden einzelnen Buchstaben vorschlägt. Find’ ich lustig, also steige ich verspätet noch ein. Das Ergebnis entlarvt mich vermutlich als langweiligen Fachmenschen. Und doch stehe ich dazu.</p>
<p class="wideimg"><img src="http://toscho.de/wp-content/uploads/2010/05/browser-abc.png" alt="Browser-ABC" width="500" height="347" class="size-full wp-image-1681 border" /></p>
<ul>
<li><a href="http://www.andrewnacin.com/">andrewnacin.com</a></li>
<li><a href="http://bugs.webkit.org/">bugs.webkit.org</a></li>
<li><a href="http://core.trac.wordpress.org/">core.trac.wordpress.org</a></li>
<li><a href="http://developer.palm.com/">developer.palm.com</a></li>
<li><a href="http://www.evalotta.net/">evalotta.net</a></li>
<li><a href="http://www.fileformat.info/">fileformat.info</a></li>
<li><a href="https://github.com/">github.com</a></li>
<li><a href="http://hakre.wordpress.com">hakre.wordpress.com</a></li>
<li><a href="http://ip-lookup.net">ip-lookup.net</a></li>
<li><a href="http://www.joindiaspora.com/">joindiaspora.com</a></li>
<li><a href="http://kaliban.de/">kaliban.de</a></li>
<li><a href="http://labjs.com/">labjs.com</a></li>
<li><a href="http://meta.stackexchange.com">meta.stackexchange.com</a></li>
<li><a href="http://neuralmesh.com/">neuralmesh.com</a></li>
<li><a href="http://opera-info.de">opera-info.de</a></li>
<li><a href="http://www.php.net/">php.net</a></li>
<li><a href="http://www.quirksmode.org">quirksmode.org</a></li>
<li><a href="http://research.swtch.com/">research.swtch.com</a></li>
<li><a href="http://stackoverflow.com">stackoverflow.com</a></li>
<li><a href="http://www.typolexikon.de">typolexikon.de</a></li>
<li><a href="http://www.unwrongest.com/">unwrongest.com</a></li>
<li><a href="http://validator.nu">validator.nu</a></li>
<li><a href="http://wpdocs.labs.thedextrousweb.com/">wpdocs.labs.thedextrousweb.com</a></li>
<li><a href="http://xhtmlforum.de">xhtmlforum.de</a></li>
<li><a href="http://yoast.com">yoast.com</a></li>
<li><a href="http://zomigi.com/">zomigi.com</a></li>
</ul>
<p>Wer spielt mit?</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/browser-abc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Opera: Der Colorpicker</title>
		<link>http://toscho.de/2010/opera-colorpicker/</link>
		<comments>http://toscho.de/2010/opera-colorpicker/#comments</comments>
		<pubDate>Tue, 04 May 2010 21:20:35 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Browser]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Opera]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1673</guid>
		<description><![CDATA[Ausführliche Vorstellung des Farbwählers in Opera Dragonfly. Screenshots und eine Schritt-für-Schritt-Anleitung.]]></description>
			<content:encoded><![CDATA[<p>Seltsamerweise ist bei all der Presse um Opera 10.5 ein Detail nahezu untergegangen, über das <em>ich</em> mich sehr gefreut habe: Der Farbwähler in Opera <a href="http://www.opera.com/dragonfly/">Dragonfly</a>.</p>
<p><a href="http://toscho.de/wp-content/uploads/2010/05/colorpicker.png"><img src="http://toscho.de/wp-content/uploads/2010/05/colorpicker-300x106.png" alt="Opera Colorpicker" width="300" height="106" class="alignnone size-medium wp-image-1674 border" /></a></p>
<p>Wir finden ihn im Reiter <i lang="en">Utilities</i> in Dragonfly, das wir bei ausgeblendeter Menuleiste am leichtesten erreichen, wenn wir irgendwo im Dokument das Kontextmenu aufrufen und dort ›Element untersuchen‹ auswählen (im Englischen <i lang="en">›Inspect Element‹</i>).</p>
<p>Fahren wir jetzt mit der Maus über die Seite, so wird in einem Vorschaufenster die Fläche unter der Maus stark vergrößert dargestellt.</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/05/colorpicker-auswahlfeld.png" alt="Colorpicker Auswahlfeld" width="278" height="286" class="alignright size-full wp-image-1675 border" />Ganz links können wir festlegen, wie groß die jeweilige Auswahl sein soll, die von der Maus erfaßt wird, und wie stark die Vergrößerung ist.</p>
<p>Das finde ich noch nicht sehr verständlich, und mit <i lang="en">Scale 1</i> fährt sich der Auswahlmodus auch manchmal fest. Mit einem einem kleinen Trick gießen wir Öl ins Getriebe: Kurz den Reiter wechseln; dann läuft es wieder. Langfristig hilft wie bei <em>jedem</em> technischen Problem natürlich nur mehr RAM.</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/05/colorpicker-manage.png" alt="Colorpicker Farbmanager" width="191" height="142" class="alignright size-full wp-image-1676 border" />Auf der linken Fläche finden wir noch ein anderes Feature: Gespeicherte Farben. Hier können wir einmal ausgewählte Farben dauerhaft merken. Der Button <i lang="en">›Manage stored colors‹</i> bietet derzeit nur das Löschen an. Ich wünsche mir noch das Benennen und eine Sortierung nach Schlagworten oder Verzeichnissen. Ansonsten ist das schon sehr praktisch.</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/05/colorpicker-select.png" alt="Colorpicker Select" width="285" height="236" class="alignright size-full wp-image-1677 border" />Rechts des Vorschaufensters können wir innerhalb der Auswahl noch einmal wählen: Wir können ein Quadrat festlegen, das wir mit der Maus auf dem Vorschaufeld plazieren. Der durchschnittliche Farbwert des Quadrates wird dann in drei Notationen ausgegeben: als RGB, als HSL und als Hexwert. Und speichern können wir die Farbe natürlich auch.<br />
Die Maximalgröße des Quadrates beträgt 9×9 Pixel – das finde ich für einige Verläufe und Fotos etwas zu klein. Die Minimalgröße beträgt 1×1 Pixel. Klein genug. Subpixel sieht man ohnehin nicht.</p>
<p>Die Funktionsweise mal Schritt für Schritt zum Mitmachen:</p>
<ol>
<li>Eine Seite öffnen, beispielsweise diese hier.</li>
<li>Rechtsklick auf ein Element (das Auge) und im Kontextmenu ›Element untersuchen‹ auswählen.</li>
<li>Jetzt öffent sich Dragonfly unten im Browserfenster mit dem Reiter ›DOM‹</li>
<li>Zum Reiter ›Utilities‹ wechseln und mit der Maus über das Auge fahren.</li>
<li>Über einer besonders schönen Stelle einmal links klicken, damit das Vorschaubild die Auswahl festhält.</li>
<li>In <i lang="en">Color Select</i> eine Größe wählen (7×7) und im Vorschaubild auf die Stelle klicken, deren durschnittlichen Farbwert man gerne haben möchte.</li>
<li>Wenn der richtige gefunden wurde, auf ›Store color‹ klicken.</li>
<li>Fertig.</li>
</ol>
<p>Brauchen wir später eine gespeicherte Farbe, so klicken wir einfach darauf. Der Wert steht dann im rechten Feld.</p>
<p>Fazit: Die Oberfläche kann durchaus klarer werden, und ein paar Features fehlen mir noch: ein Export und Variieren der Farben beispielsweise. Aber im Ganzen ist das schon eine schöne Demonstration der Möglichkeiten, die die neue API Dragonflys bietet. Dragonfly ist übrigens Open Source, <a href="http://my.opera.com/dragonfly/blog/2010/05/04/100-000-milestone-and-changes-to-the-licence">seit heute</a> unter einer Apache-2.0-Lizenz. Es muß nicht extra installiert werden, womit eine Last wegfällt, die man mit externen Werkzeugen ja meistens hat.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/opera-colorpicker/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>WordPress: Moderationslinks für Kommentare</title>
		<link>http://toscho.de/2010/wordpress-moderationslinks-fuer-kommentare/</link>
		<comments>http://toscho.de/2010/wordpress-moderationslinks-fuer-kommentare/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 20:58:09 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Interna]]></category>
		<category><![CDATA[Markup]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1671</guid>
		<description><![CDATA[Wie man jeden Kommentar um Links ergänzt, die beim Verwalten helfen. Mit vollständigem PHP- und CSS-Code.]]></description>
			<content:encoded><![CDATA[<p>Trotz des <a href="http://toscho.de/2010/spam-verhindern-akismet-htaccess/">Antispam-Plugins</a> schlüpft auch hier manchmal ein Müllkommentar durch den Filter, oder ich vertippe mich … für diese Fälle bietet WordPress an, Kommentare zu bearbeiten, als Spam zu markieren oder ganz zu löschen. Im Backend.</p>
<p>Das ist mir ein wenig zu umständlich; deshalb habe ich in meiner Klasse ›XWP‹, die zusätzliche Templatetags erzeugt, folgenden kleinen Schnipsel eingebaut, den ich <a href="http://yoast.com/wordpress-functions-supercharge-theme/" hreflang="en">von Joost de Valk abgeguckt</a> habe:</p>
<pre class="notranslate">    <i>/* Generates comment moderation links.
     *
     * @author Joost de Valk
     * @link   <a href="http://yoast.com/wordpress-functions-supercharge-theme/">http://yoast.com/wordpress-functions-supercharge-theme/</a>
     * @param  int <var>$id</var> Comment id - use get_comment_ID()
     * @return void
     */</i>
    public static function delete_comment_link(<var>$id</var>)
    {
        if ( ! <a href="http://codex.wordpress.org/Roles_and_Capabilities#moderate_comments">current_user_can</a>('<code class="string">moderate_comments</code>') )
        {
            return;
        }

        global <var>$post</var>;

        <var>$redirect</var> = get_permalink( <var>$post</var>-&gt;ID );

        <var>$links</var> = array (
            '<code class="string">delete</code>'  =&gt; '<code class="string">cdc</code>',
            '<code class="string">spam</code>' =&gt; '<code class="string">cdc&amp;dt=spam</code>',
            '<code class="string">edit</code>' =&gt; '<code class="string">editcomment</code>'
        );

        <var>$return</var> = '<code class="string">&lt;span class="comment_admin"&gt;</code>';

        foreach ( <var>$links</var> as <var>$name</var> =&gt; <var>$param</var> )
        {
            <var>$return</var> .= "<code class="string">&lt;a href='</code>"
                    . admin_url("<code class="string">comment.php?c=<var>$id</var>&amp;action=<var>$param</var>&amp;redirect_to=<var>$redirect</var></code>")
                    . "<code class="string">'&gt;<var>$name</var>&lt;/a&gt;</code>";
        }

        print <var>$return</var> . '<code class="string">&lt;/span&gt;</code>';

        return;
    }</pre>
<p>In der <code>comments.php</code> rufe ich die Funktion innerhalb des Kommentarloops auf:</p>
<pre class="notranslate">XWP::delete_comment_link( get_comment_ID() );</pre>
<p>Das erzeugt etwa dieses <a href="http://toscho.de/thema/markup/">Markup</a>:</p>
<pre class="notranslate">&lt;span class="<code class="string">comment_admin</code>"&gt;
  &lt;a href='<code class="string">/wp-admin/comment.php?c=905&amp;action=cdc&amp;redirect_to=/2010/beispiel/</code>'
     &gt;delete&lt;/a&gt;
  &lt;a href='<code class="string">/wp-admin/comment.php?c=905&amp;action=cdc&amp;dt=spam&amp;redirect_to=/2010/beispiel/</code>'
     &gt;spam&lt;/a&gt;
  &lt;a href='<code class="string">/wp-admin/comment.php?c=905&amp;action=editcomment&amp;redirect_to=/2010/beispiel/</code>'
     &gt;edit&lt;/a&gt;
&lt;/span&gt;</pre>
<p>Mit ein wenig <a href="http://toscho.de/thema/css/">CSS</a> aufgepeppt …</p>
<pre class="notranslate">.comment_admin
    {
        float:              right;
        font:               .9em/1 Calibri;
        text-align:         center;
    }
.comment_admin a
    {
        color:              #444;
        background:         #f9f9f9;
        text-decoration:    none;
        border:             1px solid #bbb;
        border-radius:      4px;
        box-shadow:         0 2px 3px rgba(0,0,0,0.2);
        display:            inline-block;
        width:              3em;
        margin:             4px;
        padding:            4px 15px;
    }
#content .comment_admin a:hover
    {
        background:         #666;
        color:              #fff;
        border:             1px solid #222;
    }</pre>
<p>… sieht das Ergebnis dann so aus:</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/04/comment-moderation.png" alt="" title="comment moderation" width="280" height="123" class="alignnone size-full wp-image-1672 border" /></p>
<p>Nach einem Klick landet man in der Bearbeitungsmaske im Backend, <em>dann erst</em> wird der Kommentar per Knopfdruck gelöscht oder als Spam markiert.</p>
<p>Mehr so’n Zeug:</p>
<ul>
<li><a href="http://toscho.de/2009/wordpress-administrator-php-herausfinden/">Administrator mit PHP herausfinden</a></li>
<li><a href="http://toscho.de/2009/wordpress-moderationsfalle-offenlegen/">Moderationsfalle offenlegen</a></li>
<li><a href="http://toscho.de/2009/no-no-no-nofollow/">No no no nofollow</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-moderationslinks-fuer-kommentare/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Designlinks 12</title>
		<link>http://toscho.de/2010/designlinks-12/</link>
		<comments>http://toscho.de/2010/designlinks-12/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 10:19:33 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Browser]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Zeichen]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1669</guid>
		<description><![CDATA[Eine Katze, die gerne duscht, langsame Referenzen, schlanke User-Agent-Strings, fette Zeichenreferenzen, ein enorm flexibles Stylesheet und ein Malprogramm.]]></description>
			<content:encoded><![CDATA[<p>Wird mal wieder Zeit. Aber zuerst entspannen wir uns ein bißchen:</p>
<p class="wp-caption-text"><object type="application/x-shockwave-flash" data="http://www.collegehumor.com/moogaloop/moogaloop.swf?clip_id=1920326&#038;fullscreen=1" width="480" height="360" ><param name="allowfullscreen" value="true"/><param name="wmode" value="transparent"/><param name="allowScriptAccess" value="always"/><param name="movie" quality="best" value="http://www.collegehumor.com/moogaloop/moogaloop.swf?clip_id=1920326&#038;fullscreen=1"/><embed src="http://www.collegehumor.com/moogaloop/moogaloop.swf?clip_id=1920326&#038;fullscreen=1" type="application/x-shockwave-flash" wmode="transparent"  width="480" height="360"  allowScriptAccess="always"></embed></object><br />
Quelle: <a href="http://www.collegehumor.com/video:1920326" hreflang="en">CollegeHumor</a>.</p>
<p>›<a href="http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html" hreflang="en" lang="en">Do not use PHP references</a>‹, empfiehlt Johannes Schlüter, denn Referenzen kosten Tempo, Übersicht und Flexibilität. Ob seiner klaren und verständlichen Darstellung dieses kniffligen Themas möchte ich den Artikel jetzt schon in die Liste der zehn besten dieses Jahres rücken.</p>
<p>Nicholas C. Zakas: <a href="http://www.nczonline.net/blog/2010/01/12/history-of-the-user-agent-string/" hreflang="en" lang="en">History of the user-agent string</a>. Warum die UA-Strings heute oft so sonderbar aussehen. Die neue <a href="http://blogs.msdn.com/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx" hreflang="en">Kennung des IE 9</a> lautet:</p>
<pre class="notranslate">Mozilla/5.0 (compatible, MSIE 9.0; Windows NT 6.1; Trident/5.0)</pre>
<p>Anhängsel irgendwelcher Zusatzsoftware werden nicht mehr eingebaut; damit schrumpft die <a href="http://www.useragentstring.com/_uas_Internet%20Explorer_version_8.0.php" hreflang="en">Liste der möglichen Kennungen</a> gewaltig – was es Proxys erheblich erleichtert, gespeicherte Versionen einer Webseite auszuliefern. Das erklärt Billy Hoffman gut in: ›<a href="http://zoompf.com/blog/2010/03/the-big-performance-improvement-in-ie9-no-one-is-talking-about" hreflang="en" lang="en">The Big Performance Improvement in IE9 No One is Talking About</a>‹. Er rät auch dazu, die <a href="http://toscho.de/2010/gzip-pro-und-kontra/">gzip-komprimierte</a> Version <em>nur noch</em> anhand des Accept-Headers zu versenden und den User-Agent zu ignorieren, damit beispielsweise ein Safari-Nutzer die Version bekommt, die der Firefox-Nutzer zuvor in den Proxy gehievt hat.</p>
<p>Man kann <a href="http://toscho.de/2008/zeichenkodierung-begriffe/#toc-maskierung-entity-und-zeichenreferenz">dezimale Zeichenreferenzen</a> mit beliebig vielen führenden Nullen versehen. So läßt sich das <samp>A</samp> als <code>&amp;#65;</code> schreiben oder als <code>&amp;#000000000000000000000000000000065;</code><br />
›hakre‹ hat mal ausprobiert, wie weit man damit gehen kann: ›<a href="http://hakre.wordpress.com/2010/02/25/html-entity-boundaries-zero-padding/" hreflang="en" lang="en">HTML Entity Boundaries – Zero Padding</a>‹.<br />
Ein Experiment, dessen praktischer Nutzen sicher weit unter seinem Unterhaltungswert liegt. Doch zeigt es, wie weit die Entwickler vorausdenken und wo sie die Grenze ziehen zwischen ›das versuche ich noch‹ und ›das wird zu langsam‹. Wenig überraschend frißt Firefox die meisten Nullen – bis zum Erstickungstod.</p>
<p>Anne van Kesteren hat auch ein Experiment mit gewaltigem Geekpotential hingestellt: <a href="http://annevankesteren.nl/test/contenteditable-style.htm" lang="en">Live style sheet editing!</a><br />
Und da muß ich einfach mal den Quelltext zitieren:</p>
<pre class="notranslate">&lt;!doctype html&gt;
&lt;html&gt;
 &lt;head&gt;
  &lt;title&gt;Live style sheet editing!&lt;/title&gt;
  &lt;style style="<code class="string">white-space:pre <i>/* hack for Opera */</i></code>" contenteditable=""&gt;
html {
margin:.2em;
font-size:2em;
color:lime;
background:purple
}
head, title, style
{
display:block
}
body {
display:none
}
  &lt;/style&gt;
 &lt;/head&gt;
 &lt;body&gt;<i>&lt;!-- nothing is needed here --&gt;</i>&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Zum Schluß noch ein Link für die Freunde der Maus: <a href="http://mrdoob.com/projects/harmony/">Harmony</a>, ein Zeichenprogramm in Javascript und Canvas. Das macht wirklich Freude.</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/04/harmony-toscho.png" alt="Harmony. Ein Experiment." width="485" height="330" class="alignnone size-full wp-image-1670 border" /></p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/designlinks-12/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Text-rendering: illegibility</title>
		<link>http://toscho.de/2010/text-rendering-illegibility/</link>
		<comments>http://toscho.de/2010/text-rendering-illegibility/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 05:11:26 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Browser]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Typographie]]></category>
		<category><![CDATA[Webdesign]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1665</guid>
		<description><![CDATA[Der Browser des Palm OS stolpert über eine ganz harmlos wirkende CSS-Deklaration – und zeigt dann keinen Text mehr an. Wie man das testet und repariert, zeigt dieser Artikel.]]></description>
			<content:encoded><![CDATA[<p>Wenn zwischen Absicht und Ergebnis fremder Code steht, dann braucht der geübte Binärschubser seine wichtigste Kompetenz: Fluchen. So auch ich, als ich gestern von Christoph Schnieder dieses kleine Horrorstück zugesandt bekam:</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/04/palm-pre-broken.png" alt="palm-pre-broken" width="320" height="480" class="alignnone size-full wp-image-1666" /></p>
<p>Tatort war ein Palm Pre WebOS, Tatwerkzeug der eingebaute Browser auf WebKit-Basis.</p>
<p>Um das überhaupt nachzuvollziehen, habe ich den <a href="http://www.genuitec.com/mobile/" hreflang="en">MobiOne Emulator für Palm Pre</a> installiert. Das ging verdächtig leicht, und das Ergebnis half mir überhaupt nicht. Es war nämlich in Ordnung:</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/04/mobi-one-emulator.png" alt="mobi-one-emulator" width="404" height="758" class="alignnone size-full wp-image-1667" /> </p>
<p>Dieser Emulator ist im Wesentlichen ein zurechtgestutztes Eclipse; seine Abhängigkeit vom Gastsystem erkennt man schon daran, daß er dessen Schriften benutzt. Unbrauchbar.</p>
<p>Dann habe ich das <a hreflang="en" href="http://developer.palm.com/index.php?option=com_content&#038;view=article&#038;layout=page&#038;id=1661">Palm webOS SDK</a> installiert, das in einer virtuellen Maschine läuft – und das Problem ganz genau wiedergibt. Das scheint also ein recht realistisch arbeitendes Werkzeug zu sein. Etwas umständlich finde ich nur das <a href="http://www.uni-regensburg.de/EDV/Misc/KeyBoards/keys02.jpg">englische Tastaturlayout</a>, das ich nicht umstellen konnte.</p>
<p>Nach allerlei Tests habe ich endlich die Ursache gefunden: Ich hatte im Stylesheet eine Deklaration stehen, von der ich annahm, sie werde <a href="https://developer.mozilla.org/En/CSS/Text-rendering" hreflang="en">nur von Gecko interpretiert</a>.</p>
<pre class="notranslate">p,
address,
li
    {
        text-rendering:optimizeLegibility;
    }</pre>
<p>Diese Eigenschaft <a href="http://www.w3.org/TR/SVG/painting.html#TextRenderingProperty" hreflang="en">stammt aus SVG</a>, wie man leicht an der dämlichen Binnenmajuskel erkennt. Sie sollte Firefox dazu anregen, auch bei kleineren Schriftgraden als 20px das <a href="http://www.typolexikon.de/k/kerning.html">Kerning</a> zu respektieren.<br />
Was genau der Palm Browser hier versucht, vermag ich nicht zu sagen. Vielleicht hängt es mit der Schriftgröße zusammen, denn Überschriften, die mindestens 20px groß sind, werden noch gezeigt.</p>
<p>Ich habe die ganze Regel jetzt weggeworfen und einen Bugreport geschrieben.</p>
<p>Sicher ließe sich das auch hinter einem proprietären Selektor für Mozilla verstecken, aber davon will ich eigentlich weg. Und wenn ich damit leben kann, daß Mozilla-Nutzer noch keine abgerundeten Ecken sehen, dann darf ich genauso gut unterstellen, daß sie sich an schlampiges Kerning gewöhnt haben. Also nehmt es mir nicht übel, ja?</p>
<p>Ach ja, das aktuelle Ergebnis:</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/04/palm-web-os-sdk-fixed.png" alt="palm-web-os-sdk repariert" width="319" height="480" class="alignnone size-full wp-image-1668" /></p>
<p>Da der Browser jetzt nur die Systemschriften des Palm OS verwendet, setzt er keine Kursivschnitte für serifenlose Schriften mehr um, und eine Monospace-Schrift findet oder nutzt er auch nicht. Das ist nicht schlimm, aber man kann es unter »Aha. Mist!« ablegen.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/text-rendering-illegibility/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
