<?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>Yoda Condition &#187; Code-Snippets</title>
	<atom:link href="http://yoda.neun12.de/artikel-category/wordpress/code-snippets/feed" rel="self" type="application/rss+xml" />
	<link>http://yoda.neun12.de</link>
	<description>Debuggen du musst</description>
	<lastBuildDate>Sun, 18 May 2014 13:49:01 +0000</lastBuildDate>
	<language>de-DE</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>Mit Git und dem WordPress-SVN arbeiten</title>
		<link>http://yoda.neun12.de/artikel-93</link>
		<comments>http://yoda.neun12.de/artikel-93#comments</comments>
		<pubDate>Sun, 03 Feb 2013 19:32:21 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=93</guid>
		<description><![CDATA[In den vergangenen Tagen habe ich mein erstes Plugin im WordPress Repository veröffentlicht. Für jemanden der wie ich schon seit Version 1.2 mit WordPress arbeitet, eigentlich ein recht später Zeitpunkt. Die Gründe hierfür sind jedoch weitreichend und sehr verschieden. Neben den sehr restriktiven bürokratischen Hürden war vor allem der Umstand das es sich beim WordPress [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In den vergangenen Tagen habe ich <a title="AvatarPlus" href="http://wordpress.org/extend/plugins/avatarplus/">mein erstes Plugin im WordPress Repository</a> veröffentlicht. Für jemanden der wie ich schon seit Version 1.2 mit WordPress arbeitet, eigentlich ein recht später Zeitpunkt. Die Gründe hierfür sind jedoch weitreichend und sehr verschieden. Neben den sehr restriktiven bürokratischen Hürden war vor allem der Umstand das es sich beim WordPress Repository um ein SVN-Repository handelt ein Grund dort keinen Code einzureichen. Warum WordPress unbedingt ein SVN-Repo betreiben muss, erschließt sich mir nach wie vor nicht. Es würde reichen wenn sie Zip-Archive der Plugins hosten, alles was ein SVN-Repo an Möglichkeiten bietet, könnte man aus dem Zip-Archiv ableiten. Aber egal, sei&#8217;s drum.<br />
Das allerdings nicht nur ich eine Abneigung gegen SVN habe, zeigte sich schnell in einer <a title="Google+ Beitrag zu AvatarPlus" href="https://plus.google.com/116844107236111670286/posts/9z4zwV3hNGX">kleinen Diskussion</a> die sich entwickelte als ich zu meinen Plugin auf Google+ einen Beitrag veröffentlichte. Kernpunkt der Diskussion war, wie man am besten Git und SVN unter einen Hut bekommt.<br />
Die Schwierigkeit dabei ist gar nicht einmal beide unter einen Hut zu bekommen, dafür gibt es <code>git svn</code>, sondern auch noch die zusätzlichen Hürden zu überwinden die von WordPress aufgestellt wurden. So darf man z.B. nicht jeden Commit den man durchführt ins WP-Repo überführen, sondern lediglich wenn man eine neue Version veröffentlicht. Zudem muss man die neue Version taggen. <code>git svn</code> kann weder das eine noch das andere wirklich sauber durchführen. Nutzt man <code>git svn</code>, muss man vor jeden Commit ins SVN-Repo die Commit-History bereinigen (squashen), taggen muss man dann sogar von Hand da auch hier <code>git svn</code> nicht sehr sauber arbeitet. Es mag sein das <code>git svn</code> dies sehrwohl kann und ich es einfach nicht heraus bekommen habe wie man das sauber hin bekommt, da lasse ich mich gerne eines besseren belehren, jedoch hatte ich irgendwann auch einfach keine Lust mehr mich mit <code>git svn</code> auseinander zusetzen.</p>
<h3>Ein paar Basics</h3>
<p>Im Grunde genommen nutze ich immer zwei Git-Repos. Zum einen ein lokales Repo im Ordner in dem ich den Code entwickele. Zum anderen ein entferntes (remote) Repo in dem ich meine Arbeit speichere. Viele nutzen als Remote-Repo GitHub, BitBucket oder einen Firmenserver. Ich nutze aus verschiedenen Gründen einen Ordner in meiner Dropbox. Da im späteren Verlauf eine lokale Kopie des SVN-Repos benötigt wird, empfiehlt es sich neben den üblichen Remote-Repos (GitHub, BitBucket, usw.) ein Remote-Repo auf der eigenen Festplatte einzurichten. Das muss nicht zwingend in einer Dropbox sein, bietet sich jedoch an wenn man, so wie ich zum Beispiel, an mehreren Rechnern oder im Team an einem Plugin arbeitet.<br />
Beispielhaft sieht die Ordnerstruktur nun so aus das <code>/d/local/plugin-name/</code> der Ordner ist in dem entwickelt wird und <code>/d/dropbox/plugin-name/</code> der Ordner für das Remote-Repo darstellt. Um es etwas einfacher zu machen verwende ich &#8216;<code>local</code>&#8216; als Namen für den lokalen Entwickelungs-Ordner und &#8216;<code>remote</code>&#8216; als Namen für den Ordner der das Remote-Repo enthält.</p>
<h3>Hooks</h3>
<p>Um das automatische Committen ins SVN-Repo durchzuführen hatte ich recht schnell <a title="Git Book (en)" href="http://git-scm.com/book/en/Customizing-Git-Git-Hooks"><code>git hooks</code></a> als Lösungsweg ausgespäht. Dank einer guten Dokumentation zu Git und sich selbst installierende Beispielen, fand ich dann auch schnell einen passenden Hook und wie ich ihn zu meinen Zwecken nutzen kann. Bei dem Hook handelt es sich um den <code>update hook</code>, der immer dann ausgeführt wird, wenn in ein Remote-Repo hinein gepusht wird. Um das zu verstehen, ein kurzer Einblick in die Hooks von Git.<br />
Es gibt Hooks die nur dann ausgeführt werden wenn eine Aktion im lokalen Repo durchgeführt wird (z.B. beim Committen). Und es gibt Hooks die nur im Remote-Repo ausgeführt werden (z.B. beim Pushen). Die Hooks unterscheiden sich allerdings nicht nur darin wann (und wo) sie ausgeführt werden, sondern auch darin, welche Parameter sie mitgegeben bekommen. Da es keinen Hook gibt den man im lokalen Repo nutzen kann sofern man feststellen möchte ob ein Tag gesetzt bzw. gepusht wurde, entschied ich mich auf das Remote-Repo auszuweichen wo es den <code>update hook</code> gibt der von Git die benötigten Parameter übergeben bekommt.</p>
<h3>Das Setup</h3>
<p>Nun müssen noch ein paar Kleinigkeiten eingerichtet werden. Das <code>git init</code> im <code>local</code> Ordner dürfte mittlerweile in Fleisch und Blut übergegangen sein. Als nächstes wird mit einer Zeile sowohl das <code>remote</code> Verzeichnis als auch die Kopie des SVN-Repos angelegt. Dazu nach <code>/d/dropbox/</code> wechseln, eine Shell öffnen und <code>svn checkout http://plugins.svn.wordpress.org/plugin-name</code> eingegeben. SVN erzeugt einen Ordner <code>plugin-name</code> der bereits alle für SVN benötigten Unterordner enthält. Da nun noch das Remote-Git-Repo fehlt, wird in den Ordner <code>plugin-name</code> gewechselt und mit <code>git init --bare</code> ein Remote-Git-Repo angelegt. Wer es mal ausprobiert, wird merken das <code>git svn</code> im Grunde genommen nichts anderes macht. Es werden einfach zwei Repos unterschiedlicher CVS in einen Ordner untergebracht. Zum Schluß wird der <code>remote</code> noch in <code>local</code> als Remote-Repo hinzugefügt: <code>git remote add dropbox /d/dropbox/plugin-name</code><br />
Jetzt ist das Setup fast geschafft, was noch fehlt ist das Script für den <code>update hook</code>. In <code>/d/dropbox/plugin-name/hooks/</code> finden sich einige Beispiele für <code>git hooks</code>. Die können alle gelöscht werden um es schön übersichtlich zu halten. Statt der Beispiel-Scripte wird das <a title="update script on GitHub" href="https://github.com/RalfAlbert/git2svn4wp/blob/master/update"><code>update</code> Script</a> hier hinein kopiert und damit ist das Setup abgeschlossen.</p>
<p>Jetzt können wir fleißig an unseren Code im Entwickelungs-Ordner <code>local</code> arbeiten. Als gute Entwickler committen wir oft und aussagekräftig. Am Ende eines jeden Tages (oder auch öfters), pushen wir unsere Arbeit in den <code>remote</code>. Wenn man nun einmal in den <code>remote</code> schaut, wird man merken das sich nichts (sichtbares) dort tut. Weder kommt Code hinzu noch wird ein SVN-Commit durchgeführt (lässt sich ganz einfach mit <code>svn log</code> prüfen). Dies ist jedoch auch genau so gewollt. WordPress verbietet es uns jeden Commit in das WP-SVN zu committen.<br />
Wie kommt nun unsere neue Version ins WP-SVN? Wenn es denn soweit ist das eine neue Version fertig ist, dann wird diese in Git getaggt: <code>git tag 1.0 -a -m 'A new version of plugin-name was released with version number 1.0'</code> oder mit einen schlichteren &#8220;un-annotated tag&#8221; <code>git tag 1.0</code>. Dieser Tag muss noch nach <code>remote</code> gepusht werden (<code>git push dropbox 1.0</code>), ab jetzt fängt die Magie des <code>update hooks</code> an zu wirken.<br />
Das Shell-Script macht nun folgendes:</p>
<ul>
<li>Prüfe ob ein Git-Repo im Ordner <code>trunk</code> vorhanden ist. Wenn nicht, dann erzeuge eines</li>
<li>Prüfe ob in diesen Git-Repo ein Remote-Repo namens <code>svn-master</code> vorhanden ist. Wenn nicht, dann füge es hinzu</li>
<li>Hole dir die Daten aus dem Remote-Repo <code>svn-master</code> in den <code>master</code> branch (<code>pull</code> = <code>fetch</code>&amp;<code>merge</code>)</li>
<li>Füge den neuen Code/Dateien im SVN-Repo hinzu und führe ein SVN-Commit durch</li>
<li>Erzeuge mit <code>svn copy</code> einen sauberen SVN-Tag im Remote-SVN-Repo</li>
</ul>
<p>Das <code>update</code> Script muss dabei auf einen kleinen Trick zurück greifen. Tags sind nichts anderes als Revisionen die einen bestimmten Zustand des Codes widerspiegeln. Normalerweise könnte man beim <code>pull</code> auch auf den Tag zugreifen, dieser existiert im Remote-Repo allerdings zu diesen Zeitpunkt noch nicht. Deswegen <strong>muss der Code erst in einen Commit zum Remote-Repo gepusht werden</strong>, da der Code anschließend aus den letzten Commit gezogen wird!<br />
Es gibt sicherlich Möglichkeiten auch Clientseitige Hooks, also Hooks die im lokalen Repo ausgeführt werden, zu nutzen. Dann müsste man jedoch bei jedem klonen des Remote-Repos diese Hooks neu einrichten. So läuft der Prozess mehr oder minder zentral ab und man muss alles nur einmal einrichten egal mit wie vielen Computern oder Teammitgliedern man das ganze nutzt.</p>
<h3>Fazit</h3>
<p>Das ganze ist noch etwas wackelig, vor allem was Merge-Konflikte angeht. Mir fehlen dazu bisher die praktischen Erfahrungen und weitere Tests. Da das Git-Repo im Verzeichnis <code>trunk</code> jedoch einzig und alleine dazu dient den Code in das <code>trunk</code> Verzeichnis zu kopieren, kann man hier sehr grob vorgehen und einfach den bestehenden Code gnadenlos überschreiben. Es finden sich dazu mehrere Methoden im Netz, ich bin mir nur noch nicht ganz sicher welche die beste ist. Wahrscheinlich ist es das Beste den Code aus dem Remote-Repo in einen neuen, temporären Branch zu kopieren, den SVN-Commit durchzuführen und den Branch anschließend wieder zu löschen. Wer es ganz hart mag, kann das Git-Repo auch einfach komplett löschen indem er den Ordner <code>.git</code> im Verzeichnis <code>trunk</code> löscht.<br />
Auf ein <code>svn update</code> verzichte ich bewusst, da dies ebenfalls zu Merge-Konflikten führen kann. Meine Lösung ist also nichts für diejenigen, die mit mehreren an einen WP-SVN-repo arbeiten. Hier sind andere Strategien gefragt die um etwas Handarbeit, vor allem beim Lösen von Merge-Konflikten, nicht drum herum kommen.</p>
<p>Diejenigen die sich mit Shell- bzw. Bash-Scripten auskennen, werden schnell erkennen das dies mein allererstes Bash-Script ist. Der Code ist definitiv nicht optimal, erfüllt jedoch seinen Zweck. Auch lässt sich das eine oder andere in Sachen SVN vielleicht noch optimieren, denn auch SVN war bisher nicht mein Fachgebiet (wird es wohl auch nie werden).<br />
Ein paar Kleinigkeiten sollten noch gelöst werden, so zum Beispiel das automatische Übernehmen der Commit-Nachricht bei annotated Tags. In meinen Augen aber eher Komfort-Funktionen die eine etwas geringere Priorität haben.<br />
Das es ein Repo ist, kann sich ja ohnehin jeder den Code ziehen und die Verbesserungen/Optimierungen einbauen die er meint das sie dort hin gehören. Da es sich um &#8220;Social Coding&#8221; handelt, würde es mich freuen wenn auch der eine oder andere Pull Request bei mir ankommt.</p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-93/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gummi-Thickbox</title>
		<link>http://yoda.neun12.de/artikel-73</link>
		<comments>http://yoda.neun12.de/artikel-73#comments</comments>
		<pubDate>Wed, 30 May 2012 14:32:40 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[Quicktipp]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=73</guid>
		<description><![CDATA[Will man im Backend von WordPress die Thickbox verwenden, bekommt man ein Problem. Zumindest dann, wenn man mit der vorgegebenen Größe nicht einverstanden ist. Die wird nämlich von WordPress mittels eines Scriptes vorgegeben. Bindet man zusätzlich den Editor ein, wird es richtig haarig. Denn im media-upload.js steht dummerweise die Zeile $('a.thickbox').each( function() {...} Also alle [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Will man im Backend von WordPress die Thickbox verwenden, bekommt man ein Problem. Zumindest dann, wenn man mit der vorgegebenen Größe nicht einverstanden ist. Die wird nämlich von WordPress mittels eines Scriptes vorgegeben. Bindet man zusätzlich den Editor ein, wird es richtig haarig. Denn im media-upload.js steht dummerweise die Zeile <code>$('a.thickbox').each( function() {...}</code><br />
Also alle Links mit der Klasse <code>thickbox</code> werden manipuliert. Würde man die Klasse <code>thickbox</code> weg lassen, würde der Link keine Thickbox öffnen. Blöde Situation das ganze.</p>
<p>Ich suchte eine Möglichkeit wie ich die Thickbox in ihrer Größe ändern kann, darüber hinaus mir aber keine Gedanken mehr machen muss wie groß ich sie dimensionieren soll. Die Thickbox sollte sich in ihrer Größe immer schön am dargestellten Inhalt ausrichten. Nach etlichen rumprobieren und etwas suchen, kam ich dann auf folgende Lösung:<div class="gistem"><div id="gist-2837799" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nx">jQuery</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span></div><div class='line' id='LC2'>	<span class="kd">function</span><span class="p">(</span><span class="nx">$</span><span class="p">){</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'>		<span class="nx">resize_thickbox_iframe</span><span class="p">();</span></div><div class='line' id='LC5'><span class="cm">/*</span></div><div class='line' id='LC6'><span class="cm"> *</span></div><div class='line' id='LC7'><span class="cm"> * some other jQuery code</span></div><div class='line' id='LC8'><span class="cm"> *</span></div><div class='line' id='LC9'><span class="cm"> */</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>		<span class="kd">function</span> <span class="nx">resize_thickbox_iframe</span><span class="p">(){</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'>			<span class="c1">//padding</span></div><div class='line' id='LC14'>			<span class="kd">var</span> <span class="nx">pad</span> <span class="o">=</span> <span class="mi">50</span><span class="p">;</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'>			<span class="c1">// give the body a height</span></div><div class='line' id='LC17'>			<span class="nx">$</span><span class="p">(</span> <span class="s1">&#39;body&#39;</span> <span class="p">).</span><span class="nx">css</span><span class="p">(</span> <span class="s1">&#39;height&#39;</span><span class="p">,</span> <span class="s1">&#39;auto&#39;</span> <span class="p">);</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'>			<span class="c1">// read the bodys height and add some padding</span></div><div class='line' id='LC20'>			<span class="kd">var</span> <span class="nx">mh</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span> <span class="nx">$</span><span class="p">(</span> <span class="s1">&#39;body&#39;</span> <span class="p">).</span><span class="nx">height</span><span class="p">()</span> <span class="p">)</span> <span class="o">+</span> <span class="nx">pad</span><span class="p">;</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'>			<span class="kd">var</span> <span class="nx">max_height</span> <span class="o">=</span> <span class="nx">mh</span> <span class="o">+</span> <span class="s1">&#39;px&#39;</span><span class="p">;</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'>			<span class="c1">// get the parent window dimensions</span></div><div class='line' id='LC25'>			<span class="kd">var</span> <span class="nx">parent</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span> <span class="nb">window</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nb">document</span> <span class="p">);</span></div><div class='line' id='LC26'>			<span class="kd">var</span> <span class="nx">ph</span> <span class="o">=</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">height</span><span class="p">();</span></div><div class='line' id='LC27'><br/></div><div class='line' id='LC28'>			<span class="c1">// get the ID of this iframe and the iframe itself</span></div><div class='line' id='LC29'>			<span class="nx">frame_id</span> <span class="o">=</span> <span class="nx">frameElement</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span></div><div class='line' id='LC30'>			<span class="nx">frame</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span> <span class="s1">&#39;#&#39;</span><span class="o">+</span><span class="nx">frame_id</span><span class="p">,</span> <span class="nb">window</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nb">document</span> <span class="p">);</span></div><div class='line' id='LC31'><br/></div><div class='line' id='LC32'>			<span class="c1">// get the id of the overlay-div and the overlay-div itself</span></div><div class='line' id='LC33'>			<span class="nx">div_id</span> <span class="o">=</span> <span class="nx">frame</span><span class="p">.</span><span class="nx">parent</span><span class="p">().</span><span class="nx">attr</span><span class="p">(</span> <span class="s1">&#39;id&#39;</span> <span class="p">);</span></div><div class='line' id='LC34'>			<span class="nx">div</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span> <span class="s1">&#39;#&#39;</span><span class="o">+</span><span class="nx">div_id</span><span class="p">,</span> <span class="nb">window</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nb">document</span> <span class="p">);</span></div><div class='line' id='LC35'><br/></div><div class='line' id='LC36'>			<span class="c1">// first set the hight for the frame, than set the hight for the overlay-div</span></div><div class='line' id='LC37'>			<span class="nx">frame</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span> <span class="s1">&#39;height&#39;</span><span class="p">,</span> <span class="nx">max_height</span> <span class="p">);</span></div><div class='line' id='LC38'>			<span class="nx">div</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span> <span class="s1">&#39;height&#39;</span><span class="p">,</span> <span class="nx">max_height</span> <span class="p">);</span></div><div class='line' id='LC39'><br/></div><div class='line' id='LC40'>			<span class="c1">// calculate the new top position</span></div><div class='line' id='LC41'>			<span class="kd">var</span> <span class="nx">tb</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">round</span><span class="p">(</span> <span class="p">(</span> <span class="p">(</span> <span class="nx">ph</span> <span class="o">-</span> <span class="nx">mh</span> <span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> <span class="p">)</span> <span class="o">-</span> <span class="nx">pad</span> <span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;px&#39;</span><span class="p">;</span></div><div class='line' id='LC42'><br/></div><div class='line' id='LC43'>			<span class="c1">// set the new top position</span></div><div class='line' id='LC44'>			<span class="nx">frame</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span> <span class="s1">&#39;top&#39;</span><span class="p">,</span> <span class="nx">tb</span> <span class="p">);</span></div><div class='line' id='LC45'>			<span class="nx">div</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span> <span class="s1">&#39;top&#39;</span><span class="p">,</span> <span class="nx">tb</span> <span class="p">);</span></div><div class='line' id='LC46'><br/></div><div class='line' id='LC47'>		<span class="p">}</span></div><div class='line' id='LC48'><br/></div><div class='line' id='LC49'>	<span class="p">}</span></div><div class='line' id='LC50'><span class="p">);</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2837799/230e1f0bcb365096666c10b746e6b11188b00299/resize_thickbox.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2837799#file_resize_thickbox.js" style="float:right;margin-right:10px;color:#666">resize_thickbox.js</a>
            <a href="https://gist.github.com/2837799">This Gist</a> is brought to you using <a href="http://en.bainternet.info/2011/simple-gist-embed"><small>Simple Gist Embed</small></a>.
          </div>
        </div>
</div>
</div><style type="text/css">@import "http://gist.github.com/stylesheets/gist/embed.css"; .gistem .highlight {background: inherit; !important;}</style></p>
<p>Das Script setzt die Höhe des body-Tags im iFrame zuerst auf &#8216;auto&#8217; damit dieser eine Höhe bekommt (für den Fall das der body-Tag noch keine Höhe besitzt). Danach wird das iFrame aus dem Eltern-Dokument gefischt und seine Höhe angepasst. Da sich das iFrame allerdings innerhalb eines Overlay-Divs befindet, muss dieser ebenfalls aus dem DOM gefischt und angepasst werden. Zum Schluss werden Overlay-Div und iFrame neu ausgerichtet.</p>
<p>Das Script gehört <strong>in das</strong> iFrame hinein! Dementsprechend muss im iFrame auch noch jQuery geladen werden. Wer im iFrame auf jQuery verzichten kann, muss sihc die Funktion auf pures JavaScript umschreiben (ist auch nicht sooo schwer).</p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-73/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quicktipp: Checkboxen auswerten</title>
		<link>http://yoda.neun12.de/artikel-61</link>
		<comments>http://yoda.neun12.de/artikel-61#comments</comments>
		<pubDate>Sat, 11 Feb 2012 14:19:19 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Quicktipp]]></category>
		<category><![CDATA[auswertung]]></category>
		<category><![CDATA[checkboxen]]></category>
		<category><![CDATA[formular]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=61</guid>
		<description><![CDATA[Vor kurzem hatte ich das Problem das ich mehrere Checkboxen bzw. deren Kombination auswerten musste. Normalerweise eine Arbeit für Leute die Mutter &#38; Vadder erschlagen haben. Dazu gleich mal die Bedingungen: Wir haben drei Checkboxen (a, b und c) in einem Formular und müssen auswerten welche Checkbox ausgewählt wurde bzw. nicht ausgewählt wurde. Wenn das [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Vor kurzem hatte ich das Problem das ich mehrere Checkboxen bzw. deren Kombination auswerten musste. Normalerweise eine Arbeit für Leute die Mutter &amp; Vadder erschlagen haben. Dazu gleich mal die Bedingungen:<br />
Wir haben drei Checkboxen (a, b und c) in einem Formular und müssen auswerten welche Checkbox ausgewählt wurde bzw. <em>nicht</em> ausgewählt wurde. Wenn das Formular abgeschickt wird, bekommen wir ein POST- bzw. GET-Array mit den Werten (ich gehe im weiteren mal von einem POST-Array aus).<br />
Das Böse an Checkboxen ist, wenn eine Checkbox nicht ausgewählt wurde, wird auch kein Wert im POST- bzw. GET-Array gesetzt.<br />
Nach dem Absenden des Formulars bekommen wir also in etwa so etwas:</p>
<pre class="brush:php">$mPost = array(
		'action'	=&gt; 'send',
		'user'		=&gt; 'Horst',
		'a'		=&gt; 'On',
		'c'		=&gt; 'On',
		'foo'		=&gt; 'bar',
		'baz'		=&gt; '',
	);</pre>
<p>Dies ist nun eine Simulation des POST-Arrays und man kann sehen das für &#8216;b&#8217; kein Wert gesetzt wurde sofern die Checkbox &#8216;b&#8217; nicht ausgewählt wurde.<br />
Wie wertet man nun üblicherweise die drei Checkboxen aus? Wahrscheinlich mit vielen <code>If-ElseIf-Else</code> Konstrukten und <code>isset()</code>:</p>
<pre class="brush:php">if( isset( $_POST['a'] ) )
...
elseif( isset( $_POST['a'] ) &amp;&amp; isset( $_POST['b'] ) )
...
elseif( isset( $_POST['a' ) &amp;&amp; ! isset( $_POST['b' ) )
...

if( isset( $_POST['b'] ) &amp;&amp; isset( $_POST['c'] ) )
...</pre>
<p>So wühlt man sich Zeile für Zeile durch alle möglichen Kombinationen und versucht keine zu vergessen. <strong>Das. Ist. Blöd!</strong> Und nicht nur blöd, sondern auch verdammt unübersichtlich. Bei drei Checkboxen mag es noch machbar sein, aber wenn man fünf, acht oder mehr Checkboxen hat, dann wird es fast schon unmöglich alle Kombinationen von ausgewählten und nicht ausgewählten Checkboxen zu berücksichtigen.</p>
<p>Da eine Checkbox nur ein Ja-Nein-Wert (Wahr oder Falsch) darstellt, habe ich mich recht schnell an die Zeit erinnert als ich mit der Computerei angefangen habe. Damals hatte ich einen C16 mit 16kB RAM. Dort war jedes Bit kostbarer als Gold und durfte nicht verschwendet werden. Deswegen hatte man oft mit Bitmasken gearbeitet. In einer Bitmaske steht jedes Bit für einen Ja oder einen Nein-Wert. Das war und ist recht effizient, denn in einem Byte kann ich so 8 Werte speichern. Und natürlich auch wieder abfragen.</p>
<p>Nun stehen wir vor dem Problem unsere drei Checkboxen in eine Bitmaske zu bekommen. Dazu benötigen wir erst einmal eine entsprechende Maske. Mit <code>printf()</code> bzw. <code>sprintf()</code> können wir eine solche Maske leicht erstellen:</p>
<pre class="brush:php">$bin = sprintf( '%b%b%b', $mPost['a'], $mPost['b'], $mPost['c'] );</pre>
<p>Das PHP-Manual sagt zum Platzhalter <code>%b</code> folgendes:</p>
<blockquote><p>das Argument wird als Integer angesehen und als Binär-Wert ausgegeben</p></blockquote>
<p><code>%b</code> wird also immer zu 1 oder 0 umgewandelt. Wandeln wir nun unsere Variablen (a, b und c) in Boolsche Werte um, so würde PHP <code>%b</code> durch 1 bzw. 0 ersetzen, je nachdem ob die Variable <code>TRUE</code> oder <code>FALSE</code> ist. Denn zuerst würde der boolsche Wert in einen Integer (1 bzw. 0) umgewandelt und dann in einen einstelligen Binärwert. Dies erreichen wir dadurch, dass wir mit <code>isset()</code> abfragen ob die Variable überhaupt existiert. Somit umschiffen wir gleichzeitig das Problem das nicht ausgewählte Checkboxen keinen Wert übertragen.</p>
<pre class="brush:php">$bin = printf( '%b%b%b', isset( $mPost['a'] ), isset( $mPost['b'] ), isset( $mPost['c'] ) );</pre>
<p>Das klappt soweit schon wunderbar und bei drei Checkboxen ist es auch noch recht übersichtlich.<br />
Als Ergebnis erhalten wir einen String der z.B. &#8220;101&#8243; enthält. Je nachdem welche Variable gesetzt ist und welche nicht. Diesen String können wir nun ganz einfach mit einem <code>switch-case </code>abfragen und darauf reagieren:</p>
<pre class="brush:php">switch( $bin ){
	case '000':
		//nichts ausgewaehlt
	break;

	case '100':
		// nur checkbox 'a' wurde ausgewählt
	break;

	case '101':
		// checkbox 'a' wurde ausgewaehlt, checkbox 'b' jedoch NICHT, checkbox 'c' ist uns egal
	break;

	default:
		// alle anderen Faelle
	break;
}</pre>
<p>Bei drei Checkboxen ist das schon eine ganz brauchbare Lösung. Aber was ist wenn wir jetzt, sagen wir mal, 20 Checkboxen haben. Zum Beispiel eine Umfrage oder ähnliches?<br />
Hier stehen wir vor zwei Problemen. Zum einen wäre der <code>sprintf()</code> nicht mehr übersichtlich und recht unbrauchbar. Zum anderen müssen wir ja gewähren das jede Variable an ihren Platz ist und nicht z.B. &#8216;a&#8217; und &#8216;g&#8217; vertauscht sind.</p>
<p>Als erstes legen wir uns mal ein Muster fest welche Variablen uns in welcher Reihenfolge interessieren. Das machen wir einfach mit einem Array:</p>
<pre class="brush:php">$defaults = array(
		'a'	=&gt; '',
		'b'	=&gt; '',
		'c'	=&gt; '',
	);</pre>
<p>Damit wir nicht mit uninitialisierten Variablen arbeiten müssen, mischen wir das POST-Array mit unserer Vorgabe. Dadurch gehen wir sicher das alle benötigten Variablen auch mit einem (leeren) Wert initialisiert sind.</p>
<pre class="brush:php">$data = array_merge( $defaults, $mPost );</pre>
<p>Nun müssen wir nur noch über unser Vorgabe-Array (<code>$defaults</code>) laufen und abfragen ob die entsprechenden Schlüssel im Daten-Array (<code>$data</code>) gesetzt sind.</p>
<pre class="brush:php">$bin = '';
foreach( $defaults as $key =&gt; $val )
	$bin .= sprintf( '%b', !!$data[$key] );</pre>
<p>Dies kann man auch anders lösen, z.B. mit einem Trinären Operator. Je nach Geschmack des Programmierers halt:</p>
<pre class="brush:php">$bin .= ! empty( $data[$key] ) ? '1' : '0';</pre>
<p>Wenn der entsprechende Wert im Daten-Array <em>nicht</em> leer ist, wird eine 1 ausgegeben, ansonsten eine 0.<br />
Als Ergebnis erhalten wir wieder einen String mit vielen Einsen und Nullen den wir im Switch-Case abfragen können. Wandelt man den String mit <code>bindec()</code> in eine Dezimalzahl um, kann man die Auswahl schön platzsparend speichern. Wenn man mit Cookies arbeitet, wird man nämlich schnell wieder daran erinnert das Speicherplatz Mangelware ist. Odre man nutzt den Dezimalwert um eine statistische Auswertung durchzuführen. Oder verwendet ihn im Switch-Case. Oder mit If-Abfragen. Oder, oder, oder&#8230;</p>
<p>Und hier das ganze dann  noch mal als komplettes Script: <div class="gistem"><div id="gist-1799597" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="x">$mPost = array(</span></div><div class='line' id='LC2'><span class="x">		&#39;action&#39;	=&gt; &#39;send&#39;,</span></div><div class='line' id='LC3'><span class="x">		&#39;user&#39;		=&gt; &#39;Horst&#39;,</span></div><div class='line' id='LC4'><span class="x">		&#39;a&#39;			=&gt; &#39;On&#39;,</span></div><div class='line' id='LC5'><span class="x">		&#39;c&#39;			=&gt; &#39;On&#39;,</span></div><div class='line' id='LC6'><span class="x">		&#39;foo&#39;		=&gt; &#39;bar&#39;,</span></div><div class='line' id='LC7'><span class="x">		&#39;baz&#39;		=&gt; &#39;&#39;,</span></div><div class='line' id='LC8'><span class="x">	);</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'><span class="x">$defaults = array(</span></div><div class='line' id='LC11'><span class="x">		&#39;a&#39;	=&gt; &#39;&#39;,</span></div><div class='line' id='LC12'><span class="x">		&#39;b&#39;	=&gt; &#39;&#39;,</span></div><div class='line' id='LC13'><span class="x">		&#39;c&#39;	=&gt; &#39;&#39;,</span></div><div class='line' id='LC14'><span class="x">	);</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="x">$data = array_merge( $defaults, $mPost );</span></div><div class='line' id='LC17'><br/></div><div class='line' id='LC18'><span class="x">$bin = &#39;&#39;;</span></div><div class='line' id='LC19'><br/></div><div class='line' id='LC20'><span class="x">foreach( $defaults as $key =&gt; $val ){</span></div><div class='line' id='LC21'><span class="x">	$bin .= sprintf( &#39;%b&#39;, !!$data[$key] );</span></div><div class='line' id='LC22'><span class="x">	//$bin .= ! empty( $data[$key] ) ? &#39;1&#39; : &#39;0&#39;;</span></div><div class='line' id='LC23'><span class="x">}	</span></div><div class='line' id='LC24'><br/></div><div class='line' id='LC25'><span class="x">$dec = bindec( $bin );</span></div><div class='line' id='LC26'><br/></div><div class='line' id='LC27'><span class="x">var_dump( $bin );</span></div><div class='line' id='LC28'><span class="x">var_dump( $dec );</span></div><div class='line' id='LC29'><br/></div><div class='line' id='LC30'><span class="x">switch( $bin ){</span></div><div class='line' id='LC31'><span class="x">	case &#39;000&#39;:</span></div><div class='line' id='LC32'><span class="x">		//nichts ausgewaehlt</span></div><div class='line' id='LC33'><span class="x">	break;</span></div><div class='line' id='LC34'><span class="x">	</span></div><div class='line' id='LC35'><span class="x">	case &#39;100&#39;:</span></div><div class='line' id='LC36'><span class="x">		// nur checkbox &#39;a&#39; wurde ausgewählt</span></div><div class='line' id='LC37'><span class="x">	break;</span></div><div class='line' id='LC38'><span class="x">	</span></div><div class='line' id='LC39'><span class="x">	case &#39;101&#39;:</span></div><div class='line' id='LC40'><span class="x">		// checkbox &#39;a&#39; wurde ausgewaehlt, checkbox &#39;b&#39; jedoch NICHT</span></div><div class='line' id='LC41'><span class="x">	break;</span></div><div class='line' id='LC42'><span class="x">	</span></div><div class='line' id='LC43'><span class="x">	default:</span></div><div class='line' id='LC44'><span class="x">		// alle anderen Faelle</span></div><div class='line' id='LC45'><span class="x">	break;</span></div><div class='line' id='LC46'><span class="x">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1799597/a2eab75bf40e1ed29ddde59a7172caa57af58568/file1.php" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1799597#file_file1.php" style="float:right;margin-right:10px;color:#666">file1.php</a>
            <a href="https://gist.github.com/1799597">This Gist</a> is brought to you using <a href="http://en.bainternet.info/2011/simple-gist-embed"><small>Simple Gist Embed</small></a>.
          </div>
        </div>
</div>
</div></p>
<p>Zum Schluss noch etwas &#8220;dreckiges&#8221; PHP. Hier möchte ich mal schnell den NOTNOT-Operator einwerfen auf den ich bei der Suche nach der Lösung gestoßen bin. <code>!$data[$key]</code> wird Wahr (TRUE) wenn $data[$key] <em>leer</em> ist. Ich möchte aber wissen ob eine Variable <em>nicht</em> leer ist, denn <code>printf()</code> soll ja aus &#8216;%b&#8217; eine &#8217;1&#8242; machen wenn die Variable gesetzt ist. Also muss ich die Bedingung <code>!$data[$key]</code> noch einmal negieren. Aus <code>!$data[$key]</code> wird also <code>!!$data[$key]</code>.<br />
Dies ist also im Grunde genommen nur eine fürchterliche Kurzschreibweise für <code> ! empty( $data[$key] )</code>. Für das schnelle Programmieren sind solche Kurzschreibweisen ganz nützlich. Sie sparen eine Menge Tipperei wenn man viel Code schreiben muss. Für die Lesbarkeit des Codes sind sie jedoch sehr kontraproduktiv. Man muss schon genau überlegen was da gerade passiert und sicher gehen das die Variable auch initialisiert ist, ansonsten hagelt es Notices.</p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-61/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Quick-Tipp: Schnell-Login</title>
		<link>http://yoda.neun12.de/artikel-52</link>
		<comments>http://yoda.neun12.de/artikel-52#comments</comments>
		<pubDate>Sun, 15 Jan 2012 05:34:41 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=52</guid>
		<description><![CDATA[Hin und wieder gibt es das Bedürfnis sich ohne Angabe von Benutzername und Passwort einzuloggen. Das könnte z.B. der Fall sein wenn man automatisierte Tests durchführen möchte die einen Login benötigen. Oder aber man muss zum Testen immer wieder den Benutzer wechseln um verschiedene Szenarien durchzuspielen. Aber auch wenn man sich in einer eher &#8220;unsicheren [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Hin und wieder gibt es das Bedürfnis sich ohne Angabe von Benutzername und Passwort einzuloggen. Das könnte z.B. der Fall sein wenn man automatisierte Tests durchführen möchte die einen Login benötigen. Oder aber man muss zum Testen immer wieder den Benutzer wechseln um verschiedene Szenarien durchzuspielen.<br />
Aber auch wenn man sich in einer eher &#8220;unsicheren Umgebung&#8221; befindet (z.B. schlecht abgesichertes öffentliches Netzwerk) möchte man vielleicht nicht so gerne seine Login-Daten eintippen. Es wäre also ganz praktisch wenn man sich (automatisiert) einloggen kann ohne ständig Login-Daten einzutippen.</p>
<p>WordPress lässt sich relativ einfach dazu bringen Login-Daten automatisiert anzunehmen. In erster Linie ist die Funktion <code>wp_signon()</code> dafür zuständig den Login durchzuführen. Dazu übergibt man ihr Benutzername und Passwort, die Funktion gibt daraufhin <code>true</code> zurück bzw. ein WordPress-Fehler-Objekt. Dies kann man bequem mit <code>is_wp_error()</code> abfragen und so mit nur wenigen Zeilen einen Login durchführen.<div class="gistem"><div id="gist-1529022" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><span class="k">require</span><span class="p">(</span> <span class="nb">dirname</span><span class="p">(</span><span class="k">__FILE__</span><span class="p">)</span> <span class="o">.</span> <span class="s1">&#39;/wp-load.php&#39;</span> <span class="p">);</span></div><div class='line' id='LC3'><span class="nx">is_wp_error</span><span class="p">(</span></div><div class='line' id='LC4'>	<span class="nx">wp_signon</span><span class="p">(</span></div><div class='line' id='LC5'>		  <span class="k">array</span><span class="p">(</span></div><div class='line' id='LC6'>			<span class="s1">&#39;user_login&#39;</span><span class="o">=&gt;</span><span class="s1">&#39;YourLoginName&#39;</span><span class="p">,</span></div><div class='line' id='LC7'>			<span class="s1">&#39;user_password&#39;</span><span class="o">=&gt;</span><span class="s1">&#39;YoUrAw3s0M3P455W0rD&#39;</span></div><div class='line' id='LC8'>			<span class="p">)</span> </div><div class='line' id='LC9'>		 <span class="p">)</span></div><div class='line' id='LC10'><span class="p">)</span> <span class="o">?</span> <span class="k">die</span><span class="p">(</span><span class="s1">&#39;Mooo... :(&#39;</span><span class="p">)</span> <span class="o">:</span> <span class="nx">wp_safe_redirect</span><span class="p">(</span> <span class="nx">admin_url</span><span class="p">()</span> <span class="p">);</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1529022/41c58a4015161cb71154d1fdb3f0c91a4da5d0e1/quicklogin.php" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1529022#file_quicklogin.php" style="float:right;margin-right:10px;color:#666">quicklogin.php</a>
            <a href="https://gist.github.com/1529022">This Gist</a> is brought to you using <a href="http://en.bainternet.info/2011/simple-gist-embed"><small>Simple Gist Embed</small></a>.
          </div>
        </div>
</div>
</div></p>
<p>Speichert man den Code in einer separaten Datei ab, so muss zuerst <code>wp-load.php</code> eingebunden werden um die WordPress-Funktionen verfügbar zu machen. Hier bitte auf den Pfad achten, iom Gist liegt die Datei im gleichen Verzeichnis wie <code>wp-load.php</code>.  Danach wird direkt <code>wp_signon()</code> mit einem Array aus Benutzername und Passwort gefüttert, welches wiederum direkt als Parameter an <code>is_wp_error()</code> übergeben wird.<br />
Durch Aufruf der Datei ist man direkt eingeloggt und wird ins Backend umgeleitet. Möchte man lieber ins Frontend umgeleitet werden, so ersetzt man einfach <code>admin_url()</code> durch <code>site_url()</code>.</p>
<p>Ich habe mir für meine Entwicklungsarbeit ein kleines Plugin geschrieben mit dem ich recht schnell zwischen verschiedenen Benutzern hin- und her wechseln kann. Dazu listet mir das Plugin auf der Login-Seite die Test-User auf, welche ich zuvor angelegt habe. Durch einen Klick auf einen entsprechenden User-Namen kann ich mich dann ohne Eingabe von Benutzername und Passwort anmelden. Auf Optik habe ich verzichtet, da es ein Werkzeug bei der Entwicklung ist. Wer mag, kann dem ganzen ja noch ein bisschen optischen Feinschliff verpassen.<br />
Das Plugin <a title="WP-Quicklogin" href="https://github.com/RalfAlbert/WP-Quicklogin">WP-Quicklogin</a> ist auf Github zu finden.</p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-52/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress Version testen</title>
		<link>http://yoda.neun12.de/artikel-58</link>
		<comments>http://yoda.neun12.de/artikel-58#comments</comments>
		<pubDate>Wed, 11 Jan 2012 08:14:42 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=58</guid>
		<description><![CDATA[Momentan habe ich es mir zur Aufgabe gemacht ein veraltetes Plugin auf eine neue Codebasis zu setzen (Refactoring). Um welches Plugin es sich dabei handelt, werde ich verraten wenn es in einem vorzeigbaren Zustand ist. Derzeit braucht es noch recht viel Arbeit. Dabei fallen aber immer wieder ein paar Sachen ab die ich für erwähnenswert [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Momentan habe ich es mir zur Aufgabe gemacht ein veraltetes Plugin auf eine neue Codebasis zu setzen (Refactoring). Um welches Plugin es sich dabei handelt, werde ich verraten wenn es in einem vorzeigbaren Zustand ist. Derzeit braucht es noch recht viel Arbeit.<br />
Dabei fallen aber immer wieder ein paar Sachen ab die ich für erwähnenswert halte. Mein <a title="define( RACE_CONDITION, TRUE ) – Das Rennen um die Konstanten" href="http://yoda.neun12.de/artikel-57">letzter Artikel</a> war übrigens auch das Ergebnis dieser Arbeit. Diesmal ist es eine Klasse mit der man die minimale WordPress- und PHP-Version testen kann (MySQL könnte man auch testen, ich denke aber das wird kaum jemand machen da es eher selten der Fall ist das man eine bestimmte MySQL-Version voraussetzt). Minimale Version bedeutet hierbei, man testet ob WordPress bzw. PHP mindestens Version X hat.<br />
Bei dem Tempo das Automattic bei der Entwickelung von WordPress an den Tag legt (alleine für dieses Jahr sind 3 Versionen geplant), wird es immer wichtiger zumindest zu  prüfen unter welcher WP-Version ein Plugin oder Theme aktiviert wird. Kann man natürlich auch sein lassen, wenn man den Anwender lieber mit Fehlermeldungen bzw. nicht funktionierenden Funktionen beglücken möchte. Ich persönlich halte es aber für empfehlenswert zu prüfen und ggf. auf eine zu niedrige Version hinzuweisen.</p>
<p>Die Klasse lässt sich vielfältig konfigurieren und flexibel einsetzen. Mit der statischen Methode <code>is_WP()</code> lässt sich z.B. prüfen ob WordPress bereits gestartet wurde. Ist dies nicht der Fall, werden 403-Header (forbidden) gesendet und das Script beendet. Dies ist z.B. nützlich um ein Script gegen direktes Aufrufen zu schützen.<br />
Bsp.:</p>
<pre class="brush:php">// beendet das Script falls WordPress nicht zuvor gestartet wurde
WP_Environment_Check::is_WP();</pre>
<p>Kern der Klasse sind allerdings die drei Methoden <code>check_wp()</code>, <code>check_php()</code> und <code>run_all_tests()</code> (die Methode <code>check_mysql()</code> ist, wie erwähnt, nur der Vollständigkeit halber dabei und dürfte eher selten Anwendung finden). Konfiguriert man ein Array oder ein Objekt mit den entsprechenden Werten und übergibt das Array bzw. Object der Methode <code>run_all_tests()</code>, so werden die entsprechenden Versionen geprüft und ggf. das Script beendet. Natürlich kann man auch nur einzelne Komponenten testen. Im Gist ist noch eine Datei mit einigen Beispielen, ich denke dadurch wird klar wie man die Klasse verwenden kann.<br />
Im Normalfall ruft man die Klasse beim Aktivieren des Plugins auf, so dass das Plugin erst gar nicht aktiviert wird.</p>
<p>Nun möchte man vielleicht nicht gleich mit dem Hammer zuschlagen und das Script beenden weil es sich um ein Theme und nicht um ein Plugin handelt. Dafür ist die Methode <code>set_die_on_fail()</code> nützlich. Übergibt man ihr den Wert <code>TRUE</code>, so wird das Script bei einen fehlerhaften Test nicht beendet, sondern <code>FALSE</code> als Rückgabewert zurück gegeben. Die Rückgabewerte kann man dann entsprechend auswerten und Meldungen ausgeben.</p>
<p>Falls man mit den Standardmeldungen nicht glücklich ist, kann man diese ebenfalls recht einfach anpassen. Einfach der Klasse einen neuen String übergeben. Das macht z.B. Übersetzungen der Fehlermeldungen recht einfach. Auch hierzu gibt es ein Beispiel im Gist.</p>
<p>Vielleicht findet der eine oder andere die Klasse ganz nützlich oder erweitert sie sogar. In beiden Fällen würde ich mich über Feedback natürlich freuen. Und hier noch der Gist zur Klasse und den Beispielen:<div class="gistem"><div id="gist-1593410" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><span class="sd">/**</span></div><div class='line' id='LC3'><span class="sd"> * </span></div><div class='line' id='LC4'><span class="sd"> * Class to check the environment (WordPress-, PHP and MySQL-version)</span></div><div class='line' id='LC5'><span class="sd"> * Test only on minimum or equal version</span></div><div class='line' id='LC6'><span class="sd"> * </span></div><div class='line' id='LC7'><span class="sd"> * @author Ralf Albert</span></div><div class='line' id='LC8'><span class="sd"> * @version 1.0</span></div><div class='line' id='LC9'><span class="sd"> * </span></div><div class='line' id='LC10'><span class="sd"> * @var array|object $versions (optional) Array with key=&gt;val or object $version-&gt;wp|php|mysql; what to test =&gt; minimum version</span></div><div class='line' id='LC11'><span class="sd"> *</span></div><div class='line' id='LC12'><span class="sd"> */</span></div><div class='line' id='LC13'><span class="k">class</span> <span class="nc">WP_Environment_Check</span></div><div class='line' id='LC14'><span class="p">{</span></div><div class='line' id='LC15'>	<span class="sd">/**</span></div><div class='line' id='LC16'><span class="sd">	 * </span></div><div class='line' id='LC17'><span class="sd">	 * WP version</span></div><div class='line' id='LC18'><span class="sd">	 * @access public</span></div><div class='line' id='LC19'><span class="sd">	 * @var string minimum or equal version of WordPress</span></div><div class='line' id='LC20'><span class="sd">	 */</span></div><div class='line' id='LC21'>	<span class="k">public</span> <span class="nv">$wp</span>	  <span class="o">=</span> <span class="s1">&#39;3.2&#39;</span><span class="p">;</span></div><div class='line' id='LC22'><br/></div><div class='line' id='LC23'>	<span class="sd">/**</span></div><div class='line' id='LC24'><span class="sd">	 * </span></div><div class='line' id='LC25'><span class="sd">	 * PHP version</span></div><div class='line' id='LC26'><span class="sd">	 * @access public</span></div><div class='line' id='LC27'><span class="sd">	 * @var string minimum or equal version of PHP</span></div><div class='line' id='LC28'><span class="sd">	 */</span></div><div class='line' id='LC29'>	<span class="k">public</span> <span class="nv">$php</span>   <span class="o">=</span> <span class="s1">&#39;5.2&#39;</span><span class="p">;</span></div><div class='line' id='LC30'><br/></div><div class='line' id='LC31'>	<span class="sd">/**</span></div><div class='line' id='LC32'><span class="sd">	 * </span></div><div class='line' id='LC33'><span class="sd">	 * MySQL version</span></div><div class='line' id='LC34'><span class="sd">	 * @access public</span></div><div class='line' id='LC35'><span class="sd">	 * @var string minimum or equal version of MySQL</span></div><div class='line' id='LC36'><span class="sd">	 */</span></div><div class='line' id='LC37'>	<span class="k">public</span> <span class="nv">$mysql</span> <span class="o">=</span> <span class="s1">&#39;5.0&#39;</span><span class="p">;</span></div><div class='line' id='LC38'><br/></div><div class='line' id='LC39'>	<span class="sd">/**</span></div><div class='line' id='LC40'><span class="sd">	 * </span></div><div class='line' id='LC41'><span class="sd">	 * Exit message if WordPress test failed</span></div><div class='line' id='LC42'><span class="sd">	 * @access public</span></div><div class='line' id='LC43'><span class="sd">	 * @var string</span></div><div class='line' id='LC44'><span class="sd">	 */</span></div><div class='line' id='LC45'>	<span class="k">public</span> <span class="nv">$exit_msg_wp</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">;</span></div><div class='line' id='LC46'><br/></div><div class='line' id='LC47'>	<span class="sd">/**</span></div><div class='line' id='LC48'><span class="sd">	 * </span></div><div class='line' id='LC49'><span class="sd">	 * Exit message if PHP test failed</span></div><div class='line' id='LC50'><span class="sd">	 * @access public</span></div><div class='line' id='LC51'><span class="sd">	 * @var string</span></div><div class='line' id='LC52'><span class="sd">	 */</span></div><div class='line' id='LC53'>	<span class="k">public</span> <span class="nv">$exit_msg_php</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">;</span></div><div class='line' id='LC54'><br/></div><div class='line' id='LC55'>	<span class="sd">/**</span></div><div class='line' id='LC56'><span class="sd">	 * </span></div><div class='line' id='LC57'><span class="sd">	 * Exit message if MySQL test failed</span></div><div class='line' id='LC58'><span class="sd">	 * @access public</span></div><div class='line' id='LC59'><span class="sd">	 * @var string</span></div><div class='line' id='LC60'><span class="sd">	 */</span></div><div class='line' id='LC61'>	<span class="k">public</span> <span class="nv">$exit_msg_mysql</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">;</span></div><div class='line' id='LC62'><br/></div><div class='line' id='LC63'>	<span class="sd">/**</span></div><div class='line' id='LC64'><span class="sd">	 * </span></div><div class='line' id='LC65'><span class="sd">	 * If set to true, the class will die with a message if a WP|PHP|MySQL test fail.</span></div><div class='line' id='LC66'><span class="sd">	 * Does not affect is_WP() or if forbidden_headers() is called withot a message </span></div><div class='line' id='LC67'><span class="sd">	 * @access public static</span></div><div class='line' id='LC68'><span class="sd">	 * @var bool true (default)|false</span></div><div class='line' id='LC69'><span class="sd">	 */</span></div><div class='line' id='LC70'>	<span class="k">public</span> <span class="k">static</span> <span class="nv">$die_on_fail</span> <span class="o">=</span> <span class="k">TRUE</span><span class="p">;</span></div><div class='line' id='LC71'><br/></div><div class='line' id='LC72'>	<span class="sd">/**</span></div><div class='line' id='LC73'><span class="sd">	 * </span></div><div class='line' id='LC74'><span class="sd">	 * Constructor</span></div><div class='line' id='LC75'><span class="sd">	 * Run all test that are defined in $version</span></div><div class='line' id='LC76'><span class="sd">	 * @access public </span></div><div class='line' id='LC77'><span class="sd">	 * @param array|object $versions</span></div><div class='line' id='LC78'><span class="sd">	 */</span></div><div class='line' id='LC79'>	<span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span> <span class="nv">$versions</span> <span class="o">=</span> <span class="k">NULL</span> <span class="p">){</span></div><div class='line' id='LC80'>		<span class="nx">self</span><span class="o">::</span><span class="na">is_WP</span><span class="p">();</span></div><div class='line' id='LC81'><br/></div><div class='line' id='LC82'>		<span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$versions</span> <span class="p">)</span> <span class="o">||</span> <span class="p">(</span> <span class="nb">is_array</span><span class="p">(</span> <span class="nv">$versions</span> <span class="p">)</span> <span class="o">||</span> <span class="nb">is_object</span><span class="p">(</span> <span class="nv">$versions</span> <span class="p">)</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC83'>			<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">run_all_tests</span><span class="p">(</span> <span class="nv">$versions</span> <span class="p">);</span></div><div class='line' id='LC84'>	<span class="p">}</span></div><div class='line' id='LC85'><br/></div><div class='line' id='LC86'>	<span class="sd">/**</span></div><div class='line' id='LC87'><span class="sd">	 * </span></div><div class='line' id='LC88'><span class="sd">	 * Set $die_on_fail</span></div><div class='line' id='LC89'><span class="sd">	 * @param bool $status True exits the script with a message </span></div><div class='line' id='LC90'><span class="sd">	 */</span></div><div class='line' id='LC91'>	<span class="k">public</span> <span class="k">function</span> <span class="nf">set_die_on_fail</span><span class="p">(</span> <span class="nv">$status</span> <span class="o">=</span> <span class="k">TRUE</span> <span class="p">){</span></div><div class='line' id='LC92'>		<span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="nb">is_bool</span><span class="p">(</span> <span class="nv">$status</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC93'>			<span class="nv">$status</span> <span class="o">=</span> <span class="p">(</span><span class="nx">bool</span><span class="p">)</span> <span class="nv">$status</span><span class="p">;</span></div><div class='line' id='LC94'><br/></div><div class='line' id='LC95'>		<span class="nx">self</span><span class="o">::</span><span class="nv">$die_on_fail</span> <span class="o">=</span> <span class="nv">$status</span><span class="p">;</span></div><div class='line' id='LC96'>	<span class="p">}</span></div><div class='line' id='LC97'><br/></div><div class='line' id='LC98'>	<span class="sd">/**</span></div><div class='line' id='LC99'><span class="sd">	 * </span></div><div class='line' id='LC100'><span class="sd">	 * Check if WordPress is active (if $wp is an object of class wp() )</span></div><div class='line' id='LC101'><span class="sd">	 * @access public static</span></div><div class='line' id='LC102'><span class="sd">	 * @return bool true|die with message and send forbidden-headers if WP is not active</span></div><div class='line' id='LC103'><span class="sd">	 */</span></div><div class='line' id='LC104'>	<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="nf">is_WP</span><span class="p">(){</span></div><div class='line' id='LC105'>		<span class="k">global</span> <span class="nv">$wp</span><span class="p">;</span></div><div class='line' id='LC106'><br/></div><div class='line' id='LC107'>		<span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="nv">$wp</span> <span class="nx">instanceof</span> <span class="nx">WP</span> <span class="p">)</span></div><div class='line' id='LC108'>			<span class="nx">self</span><span class="o">::</span><span class="na">forbidden_header</span><span class="p">();</span></div><div class='line' id='LC109'>		<span class="k">else</span></div><div class='line' id='LC110'>			<span class="k">return</span> <span class="k">TRUE</span><span class="p">;</span></div><div class='line' id='LC111'>	<span class="p">}</span></div><div class='line' id='LC112'><br/></div><div class='line' id='LC113'>	<span class="sd">/**</span></div><div class='line' id='LC114'><span class="sd">	 * </span></div><div class='line' id='LC115'><span class="sd">	 * Run all tests</span></div><div class='line' id='LC116'><span class="sd">	 * @access public</span></div><div class='line' id='LC117'><span class="sd">	 * @param array|object $versions</span></div><div class='line' id='LC118'><span class="sd">	 * @return bool true if all tests passed successfully</span></div><div class='line' id='LC119'><span class="sd">	 */</span></div><div class='line' id='LC120'>	<span class="k">public</span> <span class="k">function</span> <span class="nf">run_all_tests</span><span class="p">(</span> <span class="nv">$versions</span> <span class="o">=</span> <span class="k">NULL</span> <span class="p">){</span></div><div class='line' id='LC121'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$versions</span> <span class="p">)</span> <span class="o">||</span> <span class="p">(</span> <span class="o">!</span> <span class="nb">is_array</span><span class="p">(</span> <span class="nv">$versions</span> <span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span> <span class="nb">is_object</span><span class="p">(</span> <span class="nv">$versions</span> <span class="p">)</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC122'>			<span class="k">return</span> <span class="k">FALSE</span><span class="p">;</span></div><div class='line' id='LC123'><br/></div><div class='line' id='LC124'>		<span class="nv">$tests</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span> <span class="s1">&#39;wp&#39;</span><span class="p">,</span> <span class="s1">&#39;php&#39;</span><span class="p">,</span> <span class="s1">&#39;mysql&#39;</span> <span class="p">);</span></div><div class='line' id='LC125'><br/></div><div class='line' id='LC126'>		<span class="k">foreach</span><span class="p">(</span> <span class="nv">$versions</span> <span class="k">as</span> <span class="nv">$test</span> <span class="o">=&gt;</span> <span class="nv">$version</span> <span class="p">){</span></div><div class='line' id='LC127'>			<span class="c1">// check if the wanted test is available (means: is the test x a method &#39;check_x&#39;)</span></div><div class='line' id='LC128'>			<span class="k">if</span><span class="p">(</span> <span class="nb">in_array</span><span class="p">(</span> <span class="nx">strtolower</span><span class="p">(</span> <span class="nv">$test</span> <span class="p">),</span> <span class="nv">$tests</span> <span class="p">)</span> <span class="p">){</span></div><div class='line' id='LC129'>				<span class="nv">$method</span> <span class="o">=</span> <span class="nx">strtolower</span><span class="p">(</span> <span class="nv">$test</span> <span class="p">);</span></div><div class='line' id='LC130'>				<span class="nv">$func</span> <span class="o">=</span> <span class="s1">&#39;check_&#39;</span> <span class="o">.</span> <span class="nv">$test</span><span class="p">;</span> <span class="c1">// create the method (check_wp|check_php|check_mysql)</span></div><div class='line' id='LC131'>				<span class="nv">$this</span><span class="o">-&gt;</span><span class="nv">$method</span> <span class="o">=</span> <span class="nv">$version</span><span class="p">;</span> <span class="c1">// set $this-&gt;wp|php|mysql to version x</span></div><div class='line' id='LC132'><br/></div><div class='line' id='LC133'>				<span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="nb">call_user_func</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="o">&amp;</span><span class="nv">$this</span><span class="p">,</span> <span class="nv">$func</span> <span class="p">)</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC134'>					<span class="k">die</span><span class="p">(</span> <span class="s1">&#39;Test &#39;</span> <span class="o">.</span> <span class="nx">__CLASS__</span> <span class="o">.</span> <span class="s1">&#39;::&#39;</span> <span class="o">.</span> <span class="nv">$func</span> <span class="o">.</span> <span class="s1">&#39; failed!&#39;</span> <span class="p">);</span> <span class="c1">// this should never happen...</span></div><div class='line' id='LC135'>			<span class="p">}</span></div><div class='line' id='LC136'>		<span class="p">}</span></div><div class='line' id='LC137'><br/></div><div class='line' id='LC138'>		<span class="k">return</span> <span class="k">TRUE</span><span class="p">;</span></div><div class='line' id='LC139'>	<span class="p">}</span></div><div class='line' id='LC140'><br/></div><div class='line' id='LC141'>	<span class="sd">/**</span></div><div class='line' id='LC142'><span class="sd">	 * </span></div><div class='line' id='LC143'><span class="sd">	 * Check WordPress version</span></div><div class='line' id='LC144'><span class="sd">	 * @access public</span></div><div class='line' id='LC145'><span class="sd">	 * @return bool true returns true if the test passed successfully. Die with a message if not.</span></div><div class='line' id='LC146'><span class="sd">	 */</span></div><div class='line' id='LC147'>	<span class="k">public</span> <span class="k">function</span> <span class="nf">check_wp</span><span class="p">(){</span></div><div class='line' id='LC148'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">wp</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC149'>			<span class="k">return</span> <span class="k">FALSE</span><span class="p">;</span></div><div class='line' id='LC150'><br/></div><div class='line' id='LC151'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_wp</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC152'>			<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_wp</span> <span class="o">=</span> <span class="s1">&#39;This plugin requires WordPress &#39;</span> <span class="o">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">wp</span> <span class="o">.</span> <span class="s1">&#39; or newer. &lt;a href=&quot;http://codex.wordpress.org/Upgrading_WordPress&quot;&gt;Please update WordPress&lt;/a&gt; or delete the plugin.&#39;</span><span class="p">;</span></div><div class='line' id='LC153'><br/></div><div class='line' id='LC154'>		<span class="k">global</span> <span class="nv">$wp_version</span><span class="p">;</span></div><div class='line' id='LC155'>		<span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="nb">version_compare</span><span class="p">(</span> <span class="nv">$wp_version</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">wp</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span> <span class="p">)</span> <span class="p">){</span></div><div class='line' id='LC156'>			<span class="k">return</span> <span class="nx">self</span><span class="o">::</span><span class="na">forbidden_header</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_wp</span> <span class="p">);</span></div><div class='line' id='LC157'>		<span class="p">}</span></div><div class='line' id='LC158'><br/></div><div class='line' id='LC159'>		<span class="k">return</span> <span class="k">TRUE</span><span class="p">;</span></div><div class='line' id='LC160'>	<span class="p">}</span></div><div class='line' id='LC161'><br/></div><div class='line' id='LC162'>	<span class="sd">/**</span></div><div class='line' id='LC163'><span class="sd">	 * </span></div><div class='line' id='LC164'><span class="sd">	 * Check PHP version</span></div><div class='line' id='LC165'><span class="sd">	 * @access public</span></div><div class='line' id='LC166'><span class="sd">	 * @return bool true|die with message</span></div><div class='line' id='LC167'><span class="sd">	 */</span></div><div class='line' id='LC168'>	<span class="k">public</span> <span class="k">function</span> <span class="nf">check_php</span><span class="p">(){</span></div><div class='line' id='LC169'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">php</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC170'>			<span class="k">return</span> <span class="k">FALSE</span><span class="p">;</span></div><div class='line' id='LC171'><br/></div><div class='line' id='LC172'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_php</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC173'>			<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_php</span> <span class="o">=</span> <span class="s1">&#39;This plugin requires at least PHP version &lt;strong&gt;&#39;</span> <span class="o">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">php</span> <span class="o">.</span> <span class="s1">&#39;&lt;/strong&gt;&#39;</span><span class="p">;</span> </div><div class='line' id='LC174'><br/></div><div class='line' id='LC175'>		<span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="nb">version_compare</span><span class="p">(</span> <span class="k">PHP_VERSION</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">php</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span> <span class="p">)</span> <span class="p">){</span></div><div class='line' id='LC176'>			<span class="k">return</span> <span class="nx">self</span><span class="o">::</span><span class="na">forbidden_header</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_php</span> <span class="p">);</span></div><div class='line' id='LC177'>		<span class="p">}</span></div><div class='line' id='LC178'><br/></div><div class='line' id='LC179'>		<span class="k">return</span> <span class="k">TRUE</span><span class="p">;</span></div><div class='line' id='LC180'>	<span class="p">}</span></div><div class='line' id='LC181'><br/></div><div class='line' id='LC182'>	<span class="sd">/**</span></div><div class='line' id='LC183'><span class="sd">	 * </span></div><div class='line' id='LC184'><span class="sd">	 * Check MYSQL version</span></div><div class='line' id='LC185'><span class="sd">	 * @access public</span></div><div class='line' id='LC186'><span class="sd">	 * @return bool true|die with message</span></div><div class='line' id='LC187'><span class="sd">	 */</span></div><div class='line' id='LC188'>	<span class="k">public</span> <span class="k">function</span> <span class="nf">check_mysql</span><span class="p">(){</span></div><div class='line' id='LC189'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">mysql</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC190'>			<span class="k">return</span> <span class="k">FALSE</span><span class="p">;</span></div><div class='line' id='LC191'><br/></div><div class='line' id='LC192'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_mysql</span> <span class="p">)</span> <span class="p">)</span></div><div class='line' id='LC193'>			<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_mysql</span> <span class="o">=</span> <span class="s1">&#39;This plugin requires at least MySQL version &lt;strong&gt;&#39;</span> <span class="o">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">mysql</span> <span class="o">.</span> <span class="s1">&#39;&lt;/strong&gt;&#39;</span><span class="p">;</span></div><div class='line' id='LC194'><br/></div><div class='line' id='LC195'>		<span class="k">global</span> <span class="nv">$wpdb</span><span class="p">;</span></div><div class='line' id='LC196'>		<span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="nb">version_compare</span><span class="p">(</span> <span class="nv">$wpdb</span><span class="o">-&gt;</span><span class="na">db_version</span><span class="p">(),</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">mysql</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span> <span class="p">)</span> <span class="p">){</span></div><div class='line' id='LC197'>			<span class="k">return</span> <span class="nx">self</span><span class="o">::</span><span class="na">forbidden_header</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">exit_msg_mysql</span> <span class="p">);</span></div><div class='line' id='LC198'>		<span class="p">}</span></div><div class='line' id='LC199'><br/></div><div class='line' id='LC200'>		<span class="k">return</span> <span class="k">TRUE</span><span class="p">;</span></div><div class='line' id='LC201'>	<span class="p">}</span></div><div class='line' id='LC202'><br/></div><div class='line' id='LC203'>	<span class="sd">/**</span></div><div class='line' id='LC204'><span class="sd">	 * </span></div><div class='line' id='LC205'><span class="sd">	 * Send forbidden-headers (403) if no message is set. Only dies if a message is set</span></div><div class='line' id='LC206'><span class="sd">	 * @access public static</span></div><div class='line' id='LC207'><span class="sd">	 * @param string (optional) $exit_msg</span></div><div class='line' id='LC208'><span class="sd">	 */</span></div><div class='line' id='LC209'>	<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="nf">forbidden_header</span><span class="p">(</span> <span class="nv">$exit_msg</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span> <span class="p">){</span></div><div class='line' id='LC210'><br/></div><div class='line' id='LC211'>		<span class="k">if</span><span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$exit_msg</span> <span class="p">)</span> <span class="p">){</span></div><div class='line' id='LC212'>			<span class="nx">header</span><span class="p">(</span> <span class="s1">&#39;Status: 403 Forbidden&#39;</span> <span class="p">);</span></div><div class='line' id='LC213'>			<span class="nx">header</span><span class="p">(</span> <span class="s1">&#39;HTTP/1.1 403 Forbidden&#39;</span> <span class="p">);</span></div><div class='line' id='LC214'>			<span class="k">die</span><span class="p">(</span> <span class="s2">&quot;I&#39;m sorry Dave, I&#39;m afraid I can&#39;t do that.&quot;</span> <span class="p">);</span></div><div class='line' id='LC215'>		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>		</div><div class='line' id='LC216'>			<span class="k">if</span><span class="p">(</span> <span class="k">FALSE</span> <span class="o">===</span> <span class="nx">self</span><span class="o">::</span><span class="nv">$die_on_fail</span> <span class="p">)</span></div><div class='line' id='LC217'>				<span class="k">return</span> <span class="k">FALSE</span><span class="p">;</span></div><div class='line' id='LC218'>			<span class="k">else</span>			</div><div class='line' id='LC219'>				<span class="k">die</span><span class="p">(</span> <span class="nv">$exit_msg</span> <span class="p">);</span></div><div class='line' id='LC220'>		<span class="p">}</span></div><div class='line' id='LC221'>	<span class="p">}</span>	</div><div class='line' id='LC222'><span class="p">}</span></div><div class='line' id='LC223'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1593410/e3c8391441bffc740bc2e95add72ebce5b6ed944/_wp_environment_check.php" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1593410#file__wp_environment_check.php" style="float:right;margin-right:10px;color:#666">_wp_environment_check.php</a>
            <a href="https://gist.github.com/1593410">This Gist</a> is brought to you using <a href="http://en.bainternet.info/2011/simple-gist-embed"><small>Simple Gist Embed</small></a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><span class="cm">/*</span></div><div class='line' id='LC3'><span class="cm"> * Mocking</span></div><div class='line' id='LC4'><span class="cm"> */</span></div><div class='line' id='LC5'><span class="k">class</span> <span class="nc">WP</span><span class="p">{}</span></div><div class='line' id='LC6'><span class="nv">$wp</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WP</span><span class="p">;</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="k">class</span> <span class="nc">WPDB</span></div><div class='line' id='LC9'><span class="p">{</span></div><div class='line' id='LC10'>	<span class="k">public</span> <span class="k">function</span> <span class="nf">db_version</span><span class="p">(){</span></div><div class='line' id='LC11'>		<span class="k">return</span> <span class="s1">&#39;5.1&#39;</span><span class="p">;</span></div><div class='line' id='LC12'>	<span class="p">}</span></div><div class='line' id='LC13'><span class="p">}</span></div><div class='line' id='LC14'><span class="nv">$wpdb</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WPDB</span><span class="p">();</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="nv">$wp_version</span> <span class="o">=</span> <span class="s1">&#39;3.3.1&#39;</span><span class="p">;</span></div><div class='line' id='LC17'><span class="cm">/* end mocking */</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'><span class="cm">/*</span></div><div class='line' id='LC20'><span class="cm"> * Creating an instance ov WP_Environment_Check</span></div><div class='line' id='LC21'><span class="cm"> * Setup the minimum versions</span></div><div class='line' id='LC22'><span class="cm"> * Setup an exit-message if the WordPress test fail</span></div><div class='line' id='LC23'><span class="cm"> * Performs every single test one by one  </span></div><div class='line' id='LC24'><span class="cm"> */</span></div><div class='line' id='LC25'><br/></div><div class='line' id='LC26'><span class="nv">$a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WP_Environment_Check</span><span class="p">();</span></div><div class='line' id='LC27'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">wp</span> <span class="o">=</span> <span class="s1">&#39;3.3.1&#39;</span><span class="p">;</span></div><div class='line' id='LC28'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">php</span> <span class="o">=</span> <span class="s1">&#39;5.2&#39;</span><span class="p">;</span></div><div class='line' id='LC29'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">mysql</span> <span class="o">=</span> <span class="s1">&#39;5.1&#39;</span><span class="p">;</span></div><div class='line' id='LC30'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">exit_msg_wp</span> <span class="o">=</span> <span class="s1">&#39;The plugin &lt;em&gt;&lt;a href=&quot;http://example.com/my_plugin/&quot;&gt;Acme Plugin&lt;/a&gt;&lt;/em&gt; requires WordPress &#39;</span> <span class="o">.</span> <span class="nv">$a</span><span class="o">-&gt;</span><span class="na">wp</span> <span class="o">.</span> <span class="s1">&#39; or newer. &lt;a href=&quot;http://codex.wordpress.org/Upgrading_WordPress&quot;&gt;Please update WordPress&lt;/a&gt; or delete the plugin.&#39;</span><span class="p">;</span></div><div class='line' id='LC31'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">check_wp</span><span class="p">();</span></div><div class='line' id='LC32'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">check_php</span><span class="p">();</span></div><div class='line' id='LC33'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">check_mysql</span><span class="p">();</span></div><div class='line' id='LC34'><br/></div><div class='line' id='LC35'><span class="cm">/*</span></div><div class='line' id='LC36'><span class="cm"> * Creating an object with the minimum versions</span></div><div class='line' id='LC37'><span class="cm"> * Create an instance of WP_Environment_Check</span></div><div class='line' id='LC38'><span class="cm"> * Performs all tests at once</span></div><div class='line' id='LC39'><span class="cm"> */</span></div><div class='line' id='LC40'><br/></div><div class='line' id='LC41'><span class="nv">$v</span> <span class="o">=</span> <span class="k">new</span> <span class="k">stdClass</span><span class="p">();</span></div><div class='line' id='LC42'><span class="nv">$v</span><span class="o">-&gt;</span><span class="na">wp</span> <span class="o">=</span> <span class="s1">&#39;3.3.1&#39;</span><span class="p">;</span></div><div class='line' id='LC43'><span class="nv">$v</span><span class="o">-&gt;</span><span class="na">php</span> <span class="o">=</span> <span class="s1">&#39;5.2&#39;</span><span class="p">;</span></div><div class='line' id='LC44'><span class="nv">$v</span><span class="o">-&gt;</span><span class="na">mysql</span> <span class="o">=</span> <span class="s1">&#39;5.0&#39;</span><span class="p">;</span></div><div class='line' id='LC45'><span class="nv">$a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WP_Environment_Check</span><span class="p">();</span></div><div class='line' id='LC46'><br/></div><div class='line' id='LC47'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">run_all_tests</span><span class="p">(</span> <span class="nv">$v</span> <span class="p">);</span></div><div class='line' id='LC48'><br/></div><div class='line' id='LC49'><br/></div><div class='line' id='LC50'><span class="cm">/*</span></div><div class='line' id='LC51'><span class="cm"> * Setup an array with the minimum versions</span></div><div class='line' id='LC52'><span class="cm"> * Performs all test by creating an instance of WP_Environment_Check</span></div><div class='line' id='LC53'><span class="cm"> */</span></div><div class='line' id='LC54'><br/></div><div class='line' id='LC55'><span class="nv">$v</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span> <span class="s1">&#39;wp&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;3.0&#39;</span><span class="p">,</span> <span class="s1">&#39;php&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;5.2&#39;</span><span class="p">,</span> <span class="s1">&#39;MySQL&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;5.1&#39;</span> <span class="p">);</span></div><div class='line' id='LC56'><span class="nv">$a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WP_Environment_Check</span><span class="p">(</span> <span class="nv">$v</span> <span class="p">);</span></div><div class='line' id='LC57'><br/></div><div class='line' id='LC58'><span class="cm">/*</span></div><div class='line' id='LC59'><span class="cm"> * Store testresult in an object. Disable dying if tests failed</span></div><div class='line' id='LC60'><span class="cm"> */</span></div><div class='line' id='LC61'><br/></div><div class='line' id='LC62'><span class="nv">$a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WP_Environment_Check</span><span class="p">();</span></div><div class='line' id='LC63'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">set_die_on_fail</span><span class="p">(</span> <span class="k">FALSE</span> <span class="p">);</span></div><div class='line' id='LC64'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">wp</span> <span class="o">=</span> <span class="s1">&#39;3.3.1&#39;</span><span class="p">;</span></div><div class='line' id='LC65'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">php</span> <span class="o">=</span> <span class="s1">&#39;5.2&#39;</span><span class="p">;</span></div><div class='line' id='LC66'><span class="nv">$a</span><span class="o">-&gt;</span><span class="na">mysql</span> <span class="o">=</span> <span class="s1">&#39;7.0&#39;</span><span class="p">;</span></div><div class='line' id='LC67'><br/></div><div class='line' id='LC68'><span class="nv">$r</span> <span class="o">=</span> <span class="k">new</span> <span class="k">stdClass</span><span class="p">();</span></div><div class='line' id='LC69'><br/></div><div class='line' id='LC70'><span class="nv">$r</span><span class="o">-&gt;</span><span class="na">wp</span> <span class="o">=</span> <span class="nv">$a</span><span class="o">-&gt;</span><span class="na">check_wp</span><span class="p">();</span></div><div class='line' id='LC71'><span class="nv">$r</span><span class="o">-&gt;</span><span class="na">php</span> <span class="o">=</span> <span class="nv">$a</span><span class="o">-&gt;</span><span class="na">check_php</span><span class="p">();</span></div><div class='line' id='LC72'><span class="nv">$r</span><span class="o">-&gt;</span><span class="na">mysql</span> <span class="o">=</span> <span class="nv">$a</span><span class="o">-&gt;</span><span class="na">check_mysql</span><span class="p">();</span> <span class="c1">// fail on MYSQL -&gt; &#39;mysql&#39; =&gt; false</span></div><div class='line' id='LC73'><br/></div><div class='line' id='LC74'><span class="nb">var_dump</span><span class="p">(</span> <span class="nv">$r</span> <span class="p">);</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1593410/74c2b4589e02c653cc798f9ba382e9e6443a3c3d/wp_environment_check-test.php" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1593410#file_wp_environment_check_test.php" style="float:right;margin-right:10px;color:#666">wp_environment_check-test.php</a>
            <a href="https://gist.github.com/1593410">This Gist</a> is brought to you using <a href="http://en.bainternet.info/2011/simple-gist-embed"><small>Simple Gist Embed</small></a>.
          </div>
        </div>
</div>
</div></p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-58/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick-Tipp: Benutzer nach Anzahl der Beiträge sortieren</title>
		<link>http://yoda.neun12.de/artikel-48</link>
		<comments>http://yoda.neun12.de/artikel-48#comments</comments>
		<pubDate>Mon, 26 Dec 2011 03:11:38 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=48</guid>
		<description><![CDATA[Seit WordPress3.1 lassen sich einige Tabellen im Backend durch einen Klick auf die Spaltenüberschrift sortieren. Auf der Benutzer-Seite lassen sich so z.B. die Benutzer nach Name, E-Mail oder Benutzername sortieren. Wer ein Blog mit vielen Autoren betreibt, möchte vielleicht auch mal die Benutzer nach Anzahl der geschriebenen Beiträge sortieren lassen. Dies ist jedoch nicht möglich, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Seit WordPress3.1 lassen sich einige Tabellen im Backend durch einen Klick auf die Spaltenüberschrift sortieren. Auf der Benutzer-Seite lassen sich so z.B. die Benutzer nach Name, E-Mail oder Benutzername sortieren.<br />
Wer ein Blog mit vielen Autoren betreibt, möchte vielleicht auch mal die Benutzer nach Anzahl der geschriebenen Beiträge sortieren lassen. Dies ist jedoch nicht möglich, da nur die ersten drei Spalten sortierbar sind. Mit ein paar Zeilen PHP kann man dies jedoch ändern.</p>
<p>Dazu filtern wir das Array mit den sortierbaren Spalten und fügen den Spalten-Schlüssel &#8216;<code>posts</code>&#8216; hinzu. Den Spalten-Schlüssel finden wir in den Core-Dateien, genauer gesagt in der Klasse <code>WP_Users_List_Table</code> (<a title="WP-Trac" href="http://core.trac.wordpress.org/browser/tags/3.3/wp-admin/includes/class-wp-users-list-table.php#L160">wp-admin/includes/class-wp-list-users-table.php; Zeile 160 &#8211; 174</a>) (direkt da drunter finden wir dann übrigens auch gleich die sortierbaren Spalten).<br />
Der Name des benötigten Filters setzt sich aus einem Muster und den Screennamen zusammen: <code>manage_xxx_sortable_columns</code>. xxx ist dabei durch den Screennamen zu ersetzen. Dies funktioniert auch mit anderen Seiten im Backend, sofern dort eine Tabelle mit <code>WP_List_Table</code> erstellt wurde. Dazu ein anderes mal mehr.</p>
<p>Der Wert für den entsprechenden Eintrag im Array kann entweder ein String oder ein Array sein. Übergibt man lediglich einen String, so legt man nur fest wonach sortiert werden soll. In diesen Fall wird dann die Standardsortierung <code>asc</code> (Ascending = Aufsteigend) verwendet. Möchte man eine absteigende Reihenfolge (<code>desc</code> = Descending = Absteigend), so muss man anstatt eines String ein Array übergeben. Der erste Wert im Array ist dabei der Schlüssel nach dem sortiert werden soll und der zweite Wert die Reihenfolge (<code>asc</code>/<code>desc</code>).<br />
In unseren Fall ist es ganz sinnvoll absteigend zu sortieren damit die Benutzer mit den meisten Beiträge als erstes aufgelistet werden. Wir übergeben also ein Array. Da wir nach Anzahl der Beiträge sortieren wollen, ist der erste Wert demnach &#8216;<code>post_count</code>&#8216; und der zweite Wert &#8216;<code>desc</code>&#8216;.</p>
<p>Das modifizierte Array mit <code>return</code> zurück geben und schon sind wir fertig. Im großen und Ganzen ist das alles eine recht interessante Sache da man auch Spalten hinzufügen bzw. entfernen kann. Dieser Code-Schnipsel ist lediglich ein kleiner Einstieg, ich werde demnächst noch etwas zu den Thema &#8220;Spalten in Tabellen&#8221; schreiben. Hier noch das komplette Plugin (wer es nicht als Plugin haben will, kopiert sich den Filter und die Funktion in die <code>functions.php</code>. Mit PHP5.3 ist das übrigens alles sehr kompakt und ein schöner Fall für eine anonyme Funktion).</p>
<div class="gistem"><div id="gist-1520418" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><span class="cm">/*</span></div><div class='line' id='LC3'><span class="cm">Plugin Name: Sortable post column</span></div><div class='line' id='LC4'><span class="cm">Description: Make posts column on users screen sortable</span></div><div class='line' id='LC5'><span class="cm">Version: 0.0.1</span></div><div class='line' id='LC6'><span class="cm">Author: Ralf Albert</span></div><div class='line' id='LC7'><span class="cm">Author URI: http://yoda.neun12.de </span></div><div class='line' id='LC8'><span class="cm">*/</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'><span class="c1">// make posts-column sortable</span></div><div class='line' id='LC11'><span class="nx">add_filter</span><span class="p">(</span> <span class="s1">&#39;manage_users_sortable_columns&#39;</span><span class="p">,</span> <span class="s1">&#39;register_user_post_column_sortable&#39;</span> <span class="p">);</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'><span class="k">function</span> <span class="nf">register_user_post_column_sortable</span><span class="p">(</span> <span class="nv">$columns</span> <span class="p">){</span></div><div class='line' id='LC14'>	<span class="nv">$columns</span><span class="p">[</span><span class="s1">&#39;posts&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span> <span class="s1">&#39;post_count&#39;</span><span class="p">,</span> <span class="s1">&#39;desc&#39;</span> <span class="p">);</span></div><div class='line' id='LC15'>	<span class="k">return</span> <span class="nv">$columns</span><span class="p">;</span></div><div class='line' id='LC16'><span class="p">}</span></div><div class='line' id='LC17'><br/></div><div class='line' id='LC18'><span class="cm">/* PHP5.3 style */</span></div><div class='line' id='LC19'><span class="cm">/*</span></div><div class='line' id='LC20'><span class="cm">add_filter( &#39;manage_users_sortable_columns&#39;, </span></div><div class='line' id='LC21'><span class="cm">	function( $columns ){		</span></div><div class='line' id='LC22'><span class="cm">		$columns[&#39;posts&#39;] = array( &#39;post_count&#39;, &#39;desc&#39; );</span></div><div class='line' id='LC23'><span class="cm">		</span></div><div class='line' id='LC24'><span class="cm">		return $columns;</span></div><div class='line' id='LC25'><span class="cm">	}</span></div><div class='line' id='LC26'><span class="cm">);</span></div><div class='line' id='LC27'><span class="cm">*/</span></div><div class='line' id='LC28'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1520418/a4fa0275e5e3bca0d38379cd0f24f1946f6ef40f/sortable_posts_column.php" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1520418#file_sortable_posts_column.php" style="float:right;margin-right:10px;color:#666">sortable_posts_column.php</a>
            <a href="https://gist.github.com/1520418">This Gist</a> is brought to you using <a href="http://en.bainternet.info/2011/simple-gist-embed"><small>Simple Gist Embed</small></a>.
          </div>
        </div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-48/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WP_Editor mit externen Seitenaufrufen verwenden</title>
		<link>http://yoda.neun12.de/artikel-37</link>
		<comments>http://yoda.neun12.de/artikel-37#comments</comments>
		<pubDate>Wed, 05 Oct 2011 22:06:52 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=37</guid>
		<description><![CDATA[Frank hat auf WordPress Deutschland schon vom neuen Editor in WordPress 3.3 berichtet. Die Verwendung der Klasse WP_Editor ist mit der Funktion wp_editor() denkbar einfach. Im einfachsten Fall übergibt man der Funktion einen String für den Content und eine ID für die Textarea. Beide Angaben sind Pflichtangaben, einen leeren Editor &#8211; was wohl die Standardsituation [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a title="Frank Bültge" href="http://bueltge.de/">Frank</a> hat auf <a title="WordPress Deutschland" href="wordpress-deutschland.org">WordPress Deutschland</a> schon vom <a title="WordPress Deutschland" href="http://blog.wordpress-deutschland.org/2011/09/27/editor-update-in-wordpress-3-3.html">neuen Editor in WordPress 3.3 </a>berichtet. Die Verwendung der Klasse <code>WP_Editor</code> ist mit der Funktion <code>wp_editor()</code> denkbar einfach. Im einfachsten Fall übergibt man der Funktion einen String für den Content und eine ID für die Textarea. Beide Angaben sind Pflichtangaben, einen leeren Editor &#8211; was wohl die Standardsituation sein dürfte &#8211; muss man also mit der Übergabe eines leeren Strings oder ein Boolean <code>FALSE</code> erzwingen.</p>
<p>Die genaue Konfiguration der Editor-Klasse soll aber nicht Gegenstand des Beitrages sein. Denn beim Testen der neuen Editor-Klasse bin ich auf ein ganz anderes Problem gestoßen zu dem ich hier ein paar Worte schreiben will.</p>
<p>Mein Wunsch war es nämlich, den Editor in einer Thickbox zu öffnen, dazu sollte der Editor mittels einem Ajax-Request in die Thickbox geladen werden. Was auf den ersten Blick recht simple erscheint, birgt ein paar Stolperfallen in sich. Denn der alleinige Aufruf von <code>wp_editor()</code> erzeugt zwar das benötigte HTML, jedoch nicht die ebenfalls benötigten JavaScripte.</p>
<p>Die Ausgangssituation ist folgende: Ich habe für den TinyMCE ein Plugin welches eine Thickbox öffnet und den Inhalt der Datei <code>editor_popup.php</code> in die Thickbox lädt. Die Datei <code>editor_popup.php</code> hat anfangs folgenden schlichten Inhalt:</p>
<pre class="brush:php">&lt;?php
// get wp-load
$abspath = isset( $_GET['abspath'] ) ? $_GET['abspath'] : '';
if( '' != $abspath )
	require_once $abspath.'/wp-load.php';
else
	die('No abspath submitted!');
?&gt;
&lt;!DOCTYPE html&gt;

&lt;html&gt;
	&lt;head&gt;
		&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
		&lt;title&gt;Thickbox test&lt;/title&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id="editorwrapper"&gt;
			&lt;form action="display.php" method="get" target="_blank"&gt;
&lt;?php 
	wp_editor( '&lt;p&gt;Some more content&lt;/p&gt;', 'editortest' );
?&gt;
				&lt;input type="submit" value="Submit" /&gt;
			&lt;/form&gt;
		&lt;/div&gt;

	&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Den ABSPATH übergebe ich als GET-Request, somit ist es ein Leichtes <code>wp-load.php</code> einzubinden um an die WordPress-Funktionen zu gelangen. Der Rest ist ein bisschen HTML und der Aufruf der Funktion <code>wp_editor()</code>.<br />
Dies führte jedoch zu keinem Ergebnis, denn es fehlt so ziemlich alles an JavaScript was benötigt wird damit der Editor überhaupt betriebsbereit ist.</p>
<p>Schaut man sich die Klasse WP_Editor einmal etwas genauer an, so findet man zwei Methoden die das Einbinden und die Ausgabe des benötigten JavaScriptes übernehmen. Dies sind zum einen <code>enqueue_scripts()</code> und <code>editor_js()</code>. Diese Methoden übernehmen die Ausgabe bzw. das Einreihen des benötigten JavaScriptes und werden in den Hooks &#8216;<em>admin_print_footer_scripts</em>&#8216; / &#8216;<em>wp_print_footer_scripts</em>&#8216; bzw. &#8216;<em>admin_footer</em>&#8216; und &#8216;<em>wp_footer</em>&#8216; eingehakt.<br />
Da wir in unserer Testseite weder den einen noch den anderen Hook automatisch ausführen, müssen wir dies von Hand machen. Dazu fügen wir einfach vor dem schließenden <code>&lt;/body&gt;</code> ein <code>&lt;?php do_action( 'wp_footer' ); ?&gt;</code> ein. Um noch das passende Loook&amp;Feel von WordPress zu bekommen, nutzen wir das Admin-CSS und optional noch z.B. das Stylesheet &#8216;<em>colors-fresh</em>&#8216; um ein paar Buttons zu stylen.</p>
<pre class="brush:php">&lt;?php
add_filter( 'show_admin_bar', '__return_false' );

$styles = array( 'wp-admin', 'colors-fresh'  );
wp_print_styles( $styles );
?&gt;</pre>
<p>Dieser Code kommt vor dem schließenden <code>&lt;/head&gt;</code>. Nebenbei habe ich noch die Admin-Bar entfernt, da diese in einem kleinen Popup eher suboptimal dargestellt wird und obendrein eher nutzlos ist.</p>
<p>Et voilá! Da ist der funktionierende Editor. Und hier noch einmal das komplette Script zusammen:</p>
<pre class="brush:php">&lt;?php
// get wp-load
$abspath = isset( $_GET['abspath'] ) ? $_GET['abspath'] : '';
if( '' != $abspath )
	require_once $abspath.'/wp-load.php';
else
	die('No abspath submitted!');
?&gt;
&lt;!DOCTYPE html&gt;

&lt;html&gt;
	&lt;head&gt;
		&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
		&lt;title&gt;Thickbox test&lt;/title&gt;

&lt;?php
add_filter( 'show_admin_bar', '__return_false' );

$styles = array( 'wp-admin', 'colors-fresh'  );
wp_print_styles( $styles );
?&gt;	
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id="editorwrapper"&gt;
			&lt;form action="display.php" method="get" target="_blank"&gt;
&lt;?php 
wp_editor( '&lt;p&gt;Some content&lt;/p&gt;', 'editortest' );  //, $settings );
?&gt;
				&lt;input type="submit" value="Submit" /&gt;
			&lt;/form&gt;
		&lt;/div&gt;
&lt;?php
do_action( 'wp_footer' );
?&gt;
	&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Wenn wir dieses Script nun in der Datei <code>wp-content/plugins/editor_popup.php</code> abspeichern, dann können wir sie z.B. mit <code>http://example.com/wp-content/plugins/editor_popup.php?abspath=c:/htdocs/wordpress</code> in einem Ajax-Request aufrufen und z.B. in einer Thickbox darstellen.</p>
<p>Wie man dann den Editor an seine Bedürfnisse anpasst, ist genug Stoff für einen eigenen Artikel. Ich hoffe dem einen oder anderen schon vor Erscheinen von WordPress 3.3 eine kleine Hilfe gegeben zu haben wie man solch ein Problem lösen kann.</p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-37/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Login-Name des Autoren verschlüsseln</title>
		<link>http://yoda.neun12.de/artikel-29</link>
		<comments>http://yoda.neun12.de/artikel-29#comments</comments>
		<pubDate>Fri, 11 Mar 2011 14:38:02 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Sicherheit]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=29</guid>
		<description><![CDATA[Klaus stört es das der Login-Name des Autors bei den Post-Metadaten im Link erscheint. Das ist jetzt etwas schwurbelig ausgedrückt, für eine genauere Erklärung einfach beim Klaus nachlesen was er meint. Manchmal bin ich pingelig und mich stört so etwas auch. Logindaten egal welcher Art haben in Links und anderen öffentlich zugänglichen Bereichen einfach nichts [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a title="Login-Name in den Post-Metadaten" href="http://webdesign-passau.com/wordpress/wp-3-sicherheitsluecke-ausgabe-loginname/" target="_blank">Klaus</a> stört es das der Login-Name des Autors bei den Post-Metadaten im Link erscheint. Das ist jetzt etwas schwurbelig ausgedrückt, für eine genauere Erklärung einfach beim Klaus nachlesen was er meint.</p>
<p>Manchmal bin ich pingelig und mich stört so etwas auch. Logindaten egal welcher Art haben in Links und anderen öffentlich zugänglichen Bereichen einfach nichts zu suchen. Das widerspricht auch der Idee das man neben den Login-Namen auch noch zwei andere Namen in seinem Profil angeben kann und auswählen kann welchen Namen man gerne öffentlich verwenden möchte.</p>
<h3>Der Workaround</h3>
<p>Um das Problem zu lösen gibt es einen Workaround und eine Möglichkeit mit Filtern zu arbeiten. Zuerst der Workaround. WordPress bietet nämlich die Möglichkeit für jeden Autoren eine eigene Autoren-Seite anzulegen. Dieses Template wird zuerst gezogen bevor das allgemeine Template für alle anderen Autoren verwendet wird. Anders ausgedrückt: Existiert für den Autor X ein spezielles Template, wird dieses verwendet. Existiert kein solches Template, dann wird das allgemeine Template verwendet.<br />
Dabei sucht WordPress in folgender Reihenfolge nach einem passenden Template:</p>
<ol>
<li><code>author-{autor-name}.php</code></li>
<li><code>author-{autor-ID}.php</code></li>
<li><code>author.php</code></li>
</ol>
<p>Ist der Login-Name des Autoren z.B. &#8220;Klaus&#8221; und existiert ein Template <code>author-klaus.php</code>, wird zuerst dieses Template verwendet. Dies hilft uns in diesem Fall jedoch nicht weiter, da weiterhin der Login-Name verwendet wird.<br />
Jedoch kann man auch die ID des Autoren verwenden. Existiert ein Template author-12.php und hat der Autor &#8220;Klaus&#8221; die ID 12, dann wird dieses Template verwendet. Ändert noch nichts daran das im Link immer noch der Login-Name erscheint.<br />
Um dies zu ändern, greift man in das Template ein in dem die Funktion get_author_posts_url() verwendet wird. Das ist von Theme zu Theme leider immer etwas unterschiedlich, je nach dem wo die Metadaten zum Post ausgegeben werden. Diesen Funktionsaufruf ersetzt man nun mit diesem Monster:</p>
<pre class="brush:php">str_replace(
  get_the_author_meta( 'user_nicename' ),
  get_the_author_meta( 'ID' ),
  get_author_posts_url( get_the_author_meta( 'ID' ) )
)</pre>
<p>Damit ersetzt man den Login-Namen (user_nicename) durch die ID des Autoren. Nun benötigt man noch ein Template <code>author-xy.php</code> wobei <code>xy</code> die jeweilige ID des Autoren ist.</p>
<p>Das ganze ist ein Workaround der nur sehr begrenzt einsatzfähig ist. Man muss jedes mal am Theme rumfummeln, die ganze Sache ist nicht wirklich übersichtlich und am Ende benötigt man auch noch für jeden Autoren ein eigenes Template. Eignet sich also normalerweise nur für Blogs in denen es 1-2 Autoren gibt und die eher selten ihr Theme wechseln.</p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-29/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Login überall</title>
		<link>http://yoda.neun12.de/artikel-21</link>
		<comments>http://yoda.neun12.de/artikel-21#comments</comments>
		<pubDate>Sun, 06 Feb 2011 00:09:51 +0000</pubDate>
		<dc:creator><![CDATA[Ralf]]></dc:creator>
				<category><![CDATA[Code-Snippets]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Tipps&Tricks]]></category>

		<guid isPermaLink="false">http://yoda.neun12.de/?p=21</guid>
		<description><![CDATA[Nicht wenige WordPress-Nutzer wünschen sich die Möglichkeit sich auch z.B. auf der Startseite einloggen zu können anstatt erst die Login-Seite aufrufen zu müssen. WordPress trägt dem Rechnung und stellt die Funktion wp_login_form zur Verfügung. Für einfacher gelagerte Fälle keine schlechte Lösung, jedoch für etwas anspruchsvollere Geister nicht unbedingt das was sie suchen. Denn im Fehlerfall, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Nicht wenige WordPress-Nutzer wünschen sich die Möglichkeit sich auch z.B. auf der Startseite einloggen zu können anstatt erst die Login-Seite aufrufen zu müssen. WordPress trägt dem Rechnung und stellt die Funktion <a href="http://codex.wordpress.org/Function_Reference/wp_login_form">wp_login_form</a> zur Verfügung. Für einfacher gelagerte Fälle keine schlechte Lösung, jedoch für etwas anspruchsvollere Geister nicht unbedingt das was sie suchen. Denn im Fehlerfall, z.B. bei einem falschen Passwort, landet man doch wieder auf der Login-Seite.<br />
Schöner wäre es, würde der komplette Login-Prozess genau dort statt findet, wo das Login-Formular angezeigt wird. Wer sich nicht scheut ein Iframe zu benutzen, der kann folgende vergleichsweise einfache Lösung benutzen.</p>
<h3>Login im Iframe</h3>
<p>Im Grunde genommen kann man den ganzen Login-Prozess in einem Iframe ablaufen lassen. Man muss sich dabei lediglich vor Augen halten das ein Iframe mit einem neuen Tab im Browser vergleichbar ist. Dem Server ist es jedoch egal ob man den Login in einem neuen Tab oder Iframe vornimmt. Ob ein Benutzer eingeloggt ist oder nicht, wird in einem Cookie gespeichert. Dadurch ist der &#8220;Ort&#8221; wo man sich einloggt uninteressant, so lange er vom gleichen Server aus erfolgt.</p>
<p>Fangen wir also gleich damit an die <code>wp-login.php</code> in einem Iframe anzuzeigen. Damit dies ein wenig komfortabler wird, legen wir uns eine Funktion an die wir in der <code>functions.php</code> oder einem Plugin ablegen können.</p>
<pre class="brush:php">function my_login_form( $args ){

	extract( $args );

	if( !isset( $width ) ){
		$width = 300;
	}

	if( !isset( $height ) ){
		$height = 300;
	}

	if( !isset( $redirect ) ){
		$redirect = content_url() . '/themes/my_theme/logout.php';
	}

	echo '&lt;iframe src="http://www.example.com/wp-login.php?redirect_to=' . $redirect . '&amp;iframe_mode=true" width="' . $width . '" height="' . $height . '"&gt;';
}</pre>
<p>Diese Funktion macht eigentlich nichts anderes als ein Iframe anzuzeigen welches als Source die <code>wp-login.php</code> hat. Die Zeilen 3-16 dienen lediglich dazu ein paar Parameter an die Funktion zu übergeben. Im Beispiel oben sind das <code>width</code> (Breite des Iframe), <code>height</code> (Höhe des Iframe) und <code>redirect_to</code> (Ziel-URL zu der nach dem Login umgeleitet werden soll). Diese Parameter werden per Array übergeben:</p>
<pre class="brush:php">if( function_exists('my_login_form') ){
	$args = array( 'width'=&gt;300,
		       'height'=&gt;200,
			redirect_to=&gt; content_url().'/themes/my_theme/mylogin_redirect.php' );
	my_login_form( $args );
}</pre>
<p>Fügen wir obigen Code-Schnipsel in unser Blog ein, z.B. in der Sidebar, dann fügt die Funktion an dieser Stelle ein Iframe mit der Breite 300px und Höhe 200px ein. Bis hierhin nichts wirklich aufregendes, einzig der Parameter <code>redirect_to</code> tanzt ein wenig aus der Reihe.<br />
Wir erinnern uns, die Anzeige im Iframe ist mit einem neuen Tab vergleichbar. Die Situation ist nun folgende: Innerhalb des Blogs wird die <code>wp-login.php</code> angezeigt, beim Betätigen des  Submit-Buttons leitet die <code>wp-login.php</code>, sofern die Login-Daten korrekt sind, automatisch auf eine andere Seite um. Diese Seite wird dann ebenfalls im Iframe angezeigt! Normalerweise wird auf die Profil-Seite des Benutzers bzw. ins Dashboard umgelietet, in einem kleinen Iframe dargestellt sieht dies eher unbrauchbar aus. Diese Umleitung kann man jedoch beim Aufruf der <code>wp-login.php</code> mit dem Parameter <code>redirect_to</code> beeinflussen.<br />
Dies machen wir uns zu nutzen und zeigen einfach eine eigene Seite an deren Inhalt besser in das Iframe passt. Diese Datei hat noch eine weitere recht wichtige Aufgabe. Denn durch den Aufruf von <code>wp-login.php</code> würden wir eine weitere Instanz von WordPress erzeugen was zu unschönen Nebeneffekten führen könnte. Ich habe hier als Beispiel mal den Benutzernamen und einen Logout-Link ausgegeben. Wichtig ist, dass das Script mit einem <code>exit;</code> beendet wird:</p>
<pre class="brush:php">&lt;?php
global $current_user;

echo $current_user-&gt;user_name . '&lt;br /&gt;';
echo '&lt;a href="' . wp_logout_url( site_url().'/wp-login.php' ) . '" title="Logout"&gt;' . __('Logout') . '&lt;/a&gt;';
exit;
?&gt;
</pre>
<p>Durch die Angabe von <code>site_url . '/wp-login.php'</code> wird beim Betätigen des Logout-Links (innerhalb des Iframes) wieder auf die Login-Seite umgeleitet.</p>
<h3>Fehlende Optik</h3>
<p>Damit haben wir uns bis jetzt ein schönes Karussell gebastelt.  Im Iframe wird die <code>wp-login.php</code> angezeigt, nach einem erfolgreichen Login wird unsere eigene Seite angezeigt und nach dem Ausloggen wieder die <code>wp-login.php</code>.<br />
Jetzt bleibt noch ein kleines aber nicht unbedeutendes Problem übrig. Die <code>wp-login.php</code> würde im Iframe mit dem originalem Stylesheet angezeigt werden, dieses ist aber nicht auf Miniformate wie z.B. 300x200px ausgelegt. Zudem haben wir nun ein paar Elemente drin auf die wir gerne verzichten würden. Ein angepasstes Stylesheet muss also her. Wie man den Login-Screen optisch an seine eigenen Bedürfnisse anpasst, dazu finden sich im Internet massig Anleitungen. Zur Not einfach Bei <a href="http://bueltge.de/wordpress-login-seite-anpassen-3/1214/http://bueltge.de/wordpress-login-seite-anpassen-3/1214/">Frank Bültge</a> vorbei schauen, dort findet sich (fast) immer etwas passendes.<br />
Ein kleines Problem gibt es dabei allerdings. Bei Verwendung des Hooks würde ein Benutzer der die <code>wp-login.php</code> &#8220;normal&#8221; aufrufen würde (z.B. über ein Bookmark), ebenfalls das angepasste Stylesheet zu sehen bekommen. Es muss also ein Kriterium her anhand dessen man unterscheiden kann ob die <code>wp-login.php</code> im Iframe oder in einem normalen Fenster angezeigt wird. Im Script selber können wir das (leider) nicht überprüfen, deswegen geben wir diese Information beim Aufruf der <code>wp-login.php</code> als GET-Parameter mit: <code>&amp;iframe_mode=true</code> sorgt dafür das wir im Hook überprüfen können ob dieser Parameter gesetzt ist. Ist dem so, dann wird das angepasste Stylesheet geladen, ansonsten passiert nichts.</p>
<pre class="brush:php">function check_iframe_mode(){

	if( isset( $_REQUEST['iframe_mode'] ) &amp;&amp; true === $_REQUEST['iframe_mode'] ){
		echo '&lt;style type="text/css"&gt;
		@import url("' . site_url().'/themes/my_theme/my_login_style.css");
		&lt;/style&gt;';
	}

}

add_action( 'login_head', 'check_iframe_mode' );</pre>
<p>Das Stylesheet liegt in diesen Beispiel im Themes-Ordner &#8216;my_theme&#8217; und hat den Namen &#8216;my_login_style.css&#8217;. Man kann das CSS auch direkt ausgeben, jedoch lässt sich eine separate Datei leichter pflegen und anpassen.</p>
<h3>Fazit</h3>
<p>Mit diesem letzten Schritt wären wir nun am Ziel angekommen. Nun findet der Login-Prozess komplett im Iframe statt. Allerdings hat diese Methode auch ein paar Nachteile die ich hier nicht verschweigen möchte.<br />
Zum einen wird keine Rücksicht auf die Seite genommen in der das Iframe eingebettet ist. Sind hier Elemente vorhanden die vom Login abhängig sind, z.B. Anzeige des Benutzernamens, dann werden diese Elemente erst dann sichtbar bzw. aktualisiert wenn die Seite erneut geladen wird. Diesen Mangel kann man zur Not noch mit etwas zusätzlichem JavaScript beheben indem man einen Reload der Hauptseite erzwingt.<br />
Zum anderen geht diese Methode nicht sehr schonend mit den Resourcen um. Denn alleine durch die Anzeige der <code>wp-login.php</code> werden Datenbankverbindungen aufgebaut, Variablen angelegt und damit letztendlich auch Speicher verbraucht. Für Blogs mit hohen Besucheraufkommen sollte man deswegen besser auf andere Lösungen, sprich komplexere Plugins, zurück greifen.<br />
Für kleinere Blogs und den Hobby-Bastler jedoch eine Anregung für einen weiteren Ausbau. Ein Workaround könnte so aussehen, dass man nach dem Logout nicht direkt wieder auf die <code>wp-login.php</code> umleitet, sondern auf eine dritte &#8220;Zwischenseite&#8221; die einen Link zur <code>wp-login.php</code> enthält.</p>
<p>Ich hoffe dem einen oder anderem mit diesem Artikel ein paar Anregungen gegeben zu haben und freue mich über etwas Feedback in den Kommentaren.</p>
]]></content:encoded>
			<wfw:commentRss>http://yoda.neun12.de/artikel-21/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
