<?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/"
	 xmlns:media="http://search.yahoo.com/mrss/" >

<channel>
	<title>Du hast nach css gesucht - Macnotes.de</title>
	<atom:link href="https://macnotes.de/search/css/feed/rss2/" rel="self" type="application/rss+xml" />
	<link>https://macnotes.de/</link>
	<description>iPhone, iPod, iPad, Mac - das unabhängige Magazin rund um Apple</description>
	<lastBuildDate>Fri, 26 Nov 2021 14:19:29 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://macnotes.de/images/2021/02/image-150x150.jpg</url>
	<title>Du hast nach css gesucht - Macnotes.de</title>
	<link>https://macnotes.de/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Black Friday: AirTags und Zubehör günstig</title>
		<link>https://macnotes.de/2021/11/26/black-friday-airtags-und-zubehor-gunstig/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Fri, 26 Nov 2021 13:03:13 +0000</pubDate>
				<category><![CDATA[Schnäppchen]]></category>
		<category><![CDATA[Hardware]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=604808</guid>

					<description><![CDATA[<p>P&#252;nktlich zum Black Friday gibt es auch f&#252;r die J&#228;ger der AirTags Angebote auf Amazon. Die Tokens dienen der Nachverfolgung von Objekten wie Portemonnaies oder Schl&#252;sseln und k&#246;nnen aber auch im Auto gelassen werden, um es auf Parkpl&#228;tzen wiederzufinden, und nat&#252;rlich kann man sie auf Reisen einsetzen, damit Taschen und Koffer nicht verloren gehen. Tats&#228;chlich [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2021/11/26/black-friday-airtags-und-zubehor-gunstig/">Black Friday: AirTags und Zubehör günstig</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>P&uuml;nktlich zum Black Friday gibt es auch f&uuml;r die J&auml;ger der AirTags Angebote auf Amazon. Die Tokens dienen der Nachverfolgung von Objekten wie Portemonnaies oder Schl&uuml;sseln und k&ouml;nnen aber auch im Auto gelassen werden, um es auf Parkpl&auml;tzen wiederzufinden, und nat&uuml;rlich kann man sie auf Reisen einsetzen, damit Taschen und Koffer nicht verloren gehen.</p>
<p>Tats&auml;chlich gibt es just heute eine Reihe von Angeboten zu den AirTags selbst, aber auch passendem Zubeh&ouml;r auf Amazon.</p>
<ul>
<li>AirTags im Viererpack <a href="https://www.amazon.de/Neu-Apple-AirTag-4er-Pack/dp/B0935JRJ59/?tag=sajonara0d-21" rel="nofollow">f&uuml;r nur 89,90 Euro</a>.</li>
<li>Apple Lederschl&uuml;sselanh&auml;nger <a href="https://www.amazon.de/Apple-AirTag-Schl%C3%BCsselanh%C3%A4nger-aus-Leder/dp/B0932Q8QY3/?tag=sajonara0d-21" rel="nofollow">f&uuml;r 35,84 Euro</a>.</li>
<li>Belkin Schl&uuml;sselanh&auml;nger-Zubeh&ouml;r <a href="https://www.amazon.de/Belkin-Schl%C3%BCsselanh%C3%A4nger-Schutzh%C3%BClle-Accessoire-Kratzschutz/dp/B093333693/?tag=sajonara0d-21" rel="nofollow">f&uuml;r 9,99 Euro</a>.</li>
<li>Weiteres Zubeh&ouml;r von unterschiedlichen Herstellern ist ebenfalls <a href="https://www.amazon.de/s?k=airtag&tag=sajonara0d-21" rel="nofollow">im Angebot</a>.</li>
</ul>
<p>Fernab der AirTags gibt es nat&uuml;rlich noch andere Apple-Produkte bei Amazon im Angebot. <a href="https://www.amazon.de/s?k=apple&tag=sajonara0d-21" rel="nofollow">Darunter</a> auch AirPods Pro mit neuem MagSafe Ladecase zu einem g&uuml;nstigen Kurs und viele andere Dinge mehr. St&ouml;bern lohnt sich, <a href="https://www.awin1.com/cread.php?awinmid=15536&awinaffid=644589&clickref=&ued=https%3A%2F%2Fwww.idealo.de%2F" rel="nofollow">Preise vergleichen</a> nat&uuml;rlich auch.</p>
<p><small>Dieser Artikel enthält Affiliate-Links.</small></p><p>Der Beitrag <a href="https://macnotes.de/2021/11/26/black-friday-airtags-und-zubehor-gunstig/">Black Friday: AirTags und Zubehör günstig</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>macOS 11.4: Deshalb sollte man möglichst schnell updaten</title>
		<link>https://macnotes.de/2021/05/31/macos-114-deshalb-sollte-man-moglichst-schnell-updaten/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Mon, 31 May 2021 13:58:59 +0000</pubDate>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=564366</guid>

					<description><![CDATA[<p>Apple schloss mit dem Update auf macOS 11.4 eine schwerwiegende Sicherheitsl&#252;cke in&#160; seinem Desktopbetriebssystem. Entsprechend sollten alle Nutzer und Nutzerinnen m&#246;glichst zeitnah die Aktualisierung ausf&#252;hren. Apple ver&#246;ffentlichte das neue macOS 11.4 am 24. Mai. Schon Ende April aber ver&#246;ffentlichte die Firma Jamf einen Hinweis auf eine passende Sicherheitsl&#252;cke, die im Verlauf des Betatests geschlossen wurde. [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2021/05/31/macos-114-deshalb-sollte-man-moglichst-schnell-updaten/">macOS 11.4: Deshalb sollte man möglichst schnell updaten</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'><a href="https://macnotes.de/firma/apple/">Apple</a> schloss mit dem Update auf macOS 11.4 eine schwerwiegende Sicherheitsl&uuml;cke in&nbsp; seinem Desktopbetriebssystem. Entsprechend sollten alle Nutzer und Nutzerinnen m&ouml;glichst zeitnah die Aktualisierung ausf&uuml;hren.</p>
<p>Apple ver&ouml;ffentlichte <a href="https://macnotes.de/2021/05/24/macos-114-big-sur-von-apple-veroffentlicht/">das neue macOS 11.4</a> am 24. Mai. Schon Ende April aber ver&ouml;ffentlichte die Firma Jamf einen Hinweis auf eine passende Sicherheitsl&uuml;cke, die im Verlauf des Betatests geschlossen wurde.</p>
<h2>Malware im Schlepptau</h2>
<p>Das Problem? Eine Sicherheitsl&uuml;cke in Apples Autorisierungssystem f&uuml;r Apps (Transparency Consent and Control, kurz TCC). Hacker machten sich den Fehler zunutze und &uuml;berarbeiteten eine Mac-Malware namens XCSSET.</p>
<p>Diese konnte dann ungefragt davon profitieren, dass beispielsweise Apps wie Zoom, TeamViewer, Skype, MS Teams und viele andere, vom Nutzer bereits autorisiert wurden. Diesen gew&auml;hrte man beispielsweise Zugriff auf Dateien, die integrierte Kamera oder aber das Mikrofon. Auf diese Weise konnte die Malware beispielsweise stetig Screenshots von der Benutzeroberfl&auml;che erstellen und an Dritte senden. Mitunter wurden so Passw&ouml;rter kompromittiert und sensible Informationen entwendet.</p>
<h3>Schadsoftware aktiv genutzt</h3>
<p><a href="https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/">Tats&auml;chlich erkl&auml;ren</a> Stuart Ashenbrenner, Jaron Bradley und Ferdous Saljooki, dass sie eine Zunahme der Verwendung von XCSSET entdeckten. Nachdem die Malware auf die neue Schwachstelle angepasst worden war, wurde sie in kurzer Zeit deutlich h&auml;ufiger genutzt. Es ist sehr wohl davon auszugehen, dass die Schadsoftware, die es in ihrer urspr&uuml;nglichen Form bereits seit August 2020 gibt, auch Schaden anrichtete.</p>
<h3>Entwickler verbreiten die Malware selbst</h3>
<p>Wie aber kommt die Malware auf die Rechner der Nutzerinnen und Nutzer? Entwickler selbst verteilen sie, und zwar &uuml;ber die Zuhilfenahme von manipulierten Programmbibliotheken, die beispielsweise &uuml;ber GitHub geteilt werden und dann bei der Einbindung in Xcode zusammen mit der eigentlichen App kompiliert werden.</p>
<p>Dabei versteckt sich die Malware selbst in vermeintlich harmlos wirkenden Scriptdateien unterschiedlicher Syntax (AppleScript, Python, und andere mehr).</p>
<p>Wer also seinen Mac noch nicht auf macOS 11.4 aktualisiert hat, dem empfehlen wir dies nun nachzuholen.</p>
<p>Der Beitrag <a href="https://macnotes.de/2021/05/31/macos-114-deshalb-sollte-man-moglichst-schnell-updaten/">macOS 11.4: Deshalb sollte man möglichst schnell updaten</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>WordPress: Die Suche und Suchergebnisse optimieren</title>
		<link>https://macnotes.de/2021/05/06/wordpress-die-suche-und-suchergebnisse-optimieren/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Thu, 06 May 2021 11:28:26 +0000</pubDate>
				<category><![CDATA[Tipps]]></category>
		<category><![CDATA[Internet]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=560075</guid>

					<description><![CDATA[<p>Habt Ihr schon einmal das Gef&#252;hl gehabt, dass die WordPress-Suche unheimlich langsam ist? Dies kann viele Gr&#252;nde haben. Wir wollen Euch in diesem Artikel zweierlei zeigen: Einmal, wie Ihr die Suchergebnisse optimieren k&#246;nnt, beispielsweise indem Ihr sie optisch hervorhebt. Wir wollen Euch aber auch zeigen, wie Ihr die Suche deutlich beschleunigen k&#246;nnt, indem Ihr unn&#252;tze [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2021/05/06/wordpress-die-suche-und-suchergebnisse-optimieren/">WordPress: Die Suche und Suchergebnisse optimieren</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>Habt Ihr schon einmal das Gef&uuml;hl gehabt, dass die WordPress-Suche unheimlich langsam ist? Dies kann viele Gr&uuml;nde haben. Wir wollen Euch in diesem Artikel zweierlei zeigen: Einmal, wie Ihr die Suchergebnisse optimieren k&ouml;nnt, beispielsweise indem Ihr sie optisch hervorhebt. Wir wollen Euch aber auch zeigen, wie Ihr die Suche deutlich beschleunigen k&ouml;nnt, indem Ihr unn&uuml;tze Abfragen aus der Suche entfernt.</p>
<h2>WordPress-Suche beschleunigen</h2>
</p>
<p>Derzeit entwickle ich f&uuml;r Macnotes ein neues Thema, das ausschlie&szlig;lich AMP nutzt, damit die Website f&uuml;r den Google-Bot, und andere sowohl auf dem Desktop als auch am Smartphone oder Tablet die gleichen Resultate liefert. Diese Konsistenz soll auf Dauer daf&uuml;r sorgen, dass ich &Auml;nderungen an der Website besser mit Erfolgen bei Google in Einklang bringen kann.</p>
<p>In meiner lokalen Entwicklungsumgebung ist mir neulich aufgefallen, wie langsam die Suche ist, und also habe ich mich daran begeben, die Ursache zu finden, und die Suche letzten Endes zu beschleunigen. Ein Plug-in, das Euch dabei behilflich sein kann, ist &bdquo;<a href="https://de.wordpress.org/plugins/query-monitor/">Query Monitor</a>&ldquo; von John Blackbourn. Ihr solltet es aber vor allem in Entwicklungsumgebungen einsetzen, weil es seinerseits einige Ressourcen nutzt und so die Seite selbst verlangsamen kann.</p>
<h3>Tablepress-Ergebnisse verlangsamen die Suche ungemein</h3>
<p>Query Monitor (QM) zeigt Euch unter anderem PHP-Fehler an, es f&auml;ngt aber auch die Datenbankabfragen ab und stellt fest, wie lange sie dauern. Ihr k&ouml;nnt auf diese Weise auch die Abfragen nachverfolgen und so &uuml;ber ein Datenbank-Tool wie <a href="https://apps.apple.com/us/app/sequel-ace/id1518036000?mt=12">Sequel Ace</a> noch einmal nachstellen.</p>
<p>Dabei habe ich zum Beispiel rausgefunden, dass WordPress mit installiertem Tablepress folgende Abfrage startet, wenn Ihr nach &bdquo;iphone 12&ldquo; sucht:</p>
<pre><code class="language-sql">SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND (((wp_posts.post_title LIKE '%iphone%')
OR (wp_posts.post_excerpt LIKE '%iphone%')
OR (wp_posts.post_content LIKE '%iphone%')
OR (wp_posts.post_content REGEXP '[table “” not found /]<br />
?)(9|10|11|13|14|44|45|50)([]"' /])'))
AND ((wp_posts.post_title LIKE '%12%')
OR (wp_posts.post_excerpt LIKE '%12%')
OR (wp_posts.post_content LIKE '%12%')
OR (wp_posts.post_content REGEXP '[table “” not found /]<br />
?)(1|2|3|5|7|10|11|13|14|17|19|20|21|23|30|32|39|41|43|44|47|50|51|55|57|58|59|60)([]"' /])')))
AND wp_posts.post_type IN ('post', 'page', 'attachment', 'buch', 'event', 'firma', 'person', 'plattform', 'produkt')
AND (wp_posts.post_status = 'publish')
ORDER BY (CASE
WHEN wp_posts.post_title LIKE '%iphone 12%'
THEN 1
WHEN wp_posts.post_title LIKE '%iphone%'
AND wp_posts.post_title LIKE '%12%'
THEN 2
WHEN wp_posts.post_title LIKE '%iphone%'
OR wp_posts.post_title LIKE '%12%'
THEN 3
WHEN wp_posts.post_excerpt LIKE '%iphone 12%'
THEN 4
WHEN wp_posts.post_content LIKE '%iphone 12%'
THEN 5
ELSE 6 END), wp_posts.post_date DESC
LIMIT 0, 10; 
</code></pre>
<p>Mal abgesehen von generell ziemlich vielen Zeilen, fallen sofort zwei ins Auge, n&auml;mlich die mit dem &bdquo;REGEXP&ldquo;. Das sind Suchabfragen, die explizit von Tablepress stammen.</p>
<p>Ja und dann habe ich einfach mal ausprobiert, wie lange die Suche mit und ohne diese Zeilen dauert. In der Entwicklungsumgebung waren das 13,7 Sekunden mit Tablepress-Ergebnissen versus 1,39 Sekunden ohne. Es w&uuml;rde zwar auf dem Webserver wegen mehr RAM und Ressourcen, etc. nicht derma&szlig;en auseinander driften, aber es ist trotzdem ein unn&ouml;tiger Ballast.</p>
<p>Denn ich nutze Tabellen nur innerhalb von Texten und in den Texten selber kommen die Suchw&ouml;rter &bdquo;hoffentlich&ldquo; auch vor. Also habe ich mich entschieden, WordPress nicht mehr die Tablepress-Tabellen zu durchsuchen.</p>
<p>Ihr f&uuml;gt dazu folgenden Befehl in die &bdquo;functions.php&ldquo; ein:</p>
<pre><code class="language-php">add_filter( 'tablepress_wp_search_integration', '__return_false' );
</code></pre>
<h3>Unn&ouml;tige Bestandteile entfernen</h3>
<p>Tablepress ist aber nicht das Einzige, das ich aus der Suche entferne. Ihr selbst k&ouml;nnt Euch &uuml;berlegen, welche Beitragstypen (Post Type) Bestandteil der Suche sein sollen. Wenn Ihr beispielsweise f&uuml;r einen &bdquo;Custom Post Type&ldquo; gar kein Archiv habt und stattdessen die Inhalte dahinter mehr wie in einem Glossar nutzt, kann es sich auch lohnen, diese aus der Suche zu entfernen.</p>
<p>Ebenfalls macht es in meinen Augen zum Beispiel keinen Sinn, die &bdquo;Attachments&ldquo; durchsuchen zu lassen. Ich nutze Bilder, PDFs oder Audiodateien und Videos ebenfalls innerhalb von Beitr&auml;gen, und entsprechend kann ich sie aus der Suche rausfiltern.</p>
<p>Das k&ouml;nnt Ihr wie folgt tun:</p>
<pre><code class="language-php"> add_action( 'init', 'sn_exclude_from_search_results' );
function sn_exclude_from_search_results() {
	global $wp_post_types;
	$wp_post_types['attachment']-&gt;exclude_from_search = true;
}
</code></pre>
<h2>Suchw&ouml;rter hervorheben</h2>
<p>Noch etwas finde ich pers&ouml;nlich sehr hilfreich, und zwar das optische Hervorheben von Suchw&ouml;rtern. So kann man den Kontext um das Gesuchte schneller in den Blick nehmen. Dazu ist nat&uuml;rlich ein bisschen CSS notwendig. Also f&uuml;ge ich entsprechend eine Klasse zu den Suchworten hinzu. Das klappt folgenderma&szlig;en:</p>
<pre><code class="language-php">function sn_highlight_title() {
  $title = get_the_title();
  $keys = implode('|', explode(' ', get_search_query()));
  $title = preg_replace('/(' . $keys .')/iu', '&lt;strong class="search-highlight"&gt;</code></pre>
<p>Der Beitrag <a href="https://macnotes.de/2021/05/06/wordpress-die-suche-und-suchergebnisse-optimieren/">WordPress: Die Suche und Suchergebnisse optimieren</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>Wie man bei der WordPress-Programmierung für Waffengleichheit sorgt</title>
		<link>https://macnotes.de/2021/03/15/wie-man-bei-der-wordpress-programmierung-fur-waffengleichheit-sorgt/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Mon, 15 Mar 2021 06:08:48 +0000</pubDate>
				<category><![CDATA[Tipps]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=524013</guid>

					<description><![CDATA[<p>Der Titel des Beitrags mag ein wenig kryptisch klingen, dahinter steckt aber eine konkrete Idee, die ich anders gerade nicht umschreiben kann. Die wird aber im Verlauf des Artikels klarer. Noch konkreter geht es um ein Beispiel aus der WordPress-Programmierung und damit um PHP. Allerdings sind diese Konzepte universell einsetzbar, sodass man sie auch in [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2021/03/15/wie-man-bei-der-wordpress-programmierung-fur-waffengleichheit-sorgt/">Wie man bei der WordPress-Programmierung für Waffengleichheit sorgt</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>Der Titel des Beitrags mag ein wenig kryptisch klingen, dahinter steckt aber eine konkrete Idee, die ich anders gerade nicht umschreiben kann. Die wird aber im Verlauf des Artikels klarer. Noch konkreter geht es um ein Beispiel aus der WordPress-Programmierung und damit um PHP. Allerdings sind diese Konzepte universell einsetzbar, sodass man sie auch in anderen Programmiersprachen abbilden kann und natürlich auch außerhalb von WordPress.</p>
<h2>Worum geht es?</h2>
<p>Stellt Euch vor, Ihr habt eine Idee für eine Funktion oder am Ende des Tages sogar eine Klasse. Nehmen wir an, Ihr wollt eine Funktion programmieren, die Euch egal in welchem Kontext das passende Bild in Form eines Arrays mit Bildinformationen zurückgibt.</p>
<p>Die Funktion gibt Euch diese Bilddaten sowohl auf der Startseite, als auch in den Archiven und aber auch in einzelnen Beiträgen oder Seiten zurück und Ihr könntet Sie außerdem für viele andere Zwecke nutzen, in denen es immer um Bilder geht. Grob also in etwa:</p>
<pre><code>function my_img() {
…
return $img;
}
</code></pre>
<p>Normalerweise verzweifelt man irgendwann daran, dass es viel zu viele Ausnahmen gibt. Denn im Umfeld von WordPress gibt es diverse Funktionen, eine für Artikelbilder (<code>the_post_thumbnail()</code>), eine für Avatare, eine ganz andere, falls Bilder in Form von Metadaten an „Custom Post Types“ angehängt wurden (<code>get_post_meta()</code>), und so fort. Und wenn man die Bilder dann nicht im Rahmen des normalen „Loop“ von WordPress abgreift, sondern mit einem persönlichen Query, dann bekommt man es ohnehin mit einem anderen Ergebnis zu tun (<code>wp_get_attachment_img_src()</code>). Mal hat man dann mit Objekten zu tun, mal mit Arrays, mal mit bloßen Zeichenketten, in denen der URL des Bildes enthalten ist, aber nicht viel mehr.</p>
<p>Ist es nicht nervig, dass man dann überall einen anderen Ansatz für die Entwicklung des eigenen WordPress-Themes benötigt?</p>
<h2>Für Waffengleichheit sorgen</h2>
<p>Wie bekommt man all diese unterschiedlichen Ergebnisse sortiert? Ganz einfach. Indem man für Ordnung sorgt!</p>
<p>Die Absicht hinter einer eigenen Funktion oder sogar einer Klasse ist ja, dass man sie „immer gleich“ nutzen kann. Mithilfe von Parametern kann man dann noch entscheiden, welcher Code ausgegeben werden soll.</p>
<p>Im Laufe der Arbeit müsst Ihr dann einfach mal einen Schritt zurücktreten und schauen, wo überhaupt Gemeinsamkeiten bestehen. Eine WordPressfunktion wie <code>get_the_post_thumbnail()</code> liefert Euch am Ende des Tages einen fertigen HTML-Tag zurück. Für ein Bild, das als Metadaten zu einem Custom Post Type gespeichert wurde, erhaltet Ihr über <code>get_post_meta()</code> die URL zurück, aber keinen fertigen HTML-Tag. Über <code>wp_get_attachment_img_src()</code> gibt es ein Array, das neben der URL auch die Daten für Breite und Höhe enthält.</p>
<p>Wenn Ihr wollt, dass Ihr Eure Funktion immer auf die gleiche Art verwenden könnt, beispielsweise eine ID des Bildes angebt und dann aber ein Array mit URL, Breite und Höhe zurückbekommt, damit Ihr in Eurem Template dann den HTML-Tag selbst erstellen könnt, müsst Ihr einen gemeinsamen Nenner suchen.</p>
<p>Und was ist beispielsweise für den Fall, dass es gar kein Artikelbild gibt? Ja, auch dann müsst Ihr eben ein Array erstellen, das ein Standardbild als URL enthält, und Angaben für dessen Breite und Höhe.</p>
<p>So eine Funktion könnte unvollständigerweise wie folgt ausschauen:</p>
<pre><code>function my_img($id, $standort) {
	switch($standort) {
		case 'Startseite':
			$img = wp_get_attachment_src($id);
			$my_img = [
				'width' =&gt; $img[1],
				'height' =&gt; $img[2],
				'url' =&gt; $img[0]
			];
			break;
		case 'CPT':
			$img = get_post_meta(…);
			$my_img = [
				'width' =&gt; 1920,
				'height' =&gt; 1080,
				'url' =&gt; $img
			];
	}
	// für den Fall, dass noch gar kein Bild-Array erstellt wurde, müssen wir noch eines hinzufügen.

	if(!isset($my_img)) {
		$my_img = [
			'width' = 1920,
			'height' = 1080,
			'url' = 'Adresse zum Standardbild'
		];
	}
	return $my_img;
} 
</code></pre>
<p>Der obige Code ist nicht auf Fehler geprüft, da ich gerade nur einen Texteditor zur Hand habe. Aber mir kam eben gerade jetzt die Idee zu diesem Artikel.</p>
<p>Die Funktion liefert Euch also theoretisch „in jedem Fall“ ein Array mit URL, Breite und Höhe zurück. Auf diese Weise könnt Ihr sie dann immer auf die gleiche Weise verwenden.</p>
<h3>Nicht dem Chaos nachgeben</h3>
<p>Denn es passiert viel zu schnell, dass man sich mit einer Situation zufriedengibt, in der man sagt, ach komm, an dieser Stelle geht es nun mal nicht, weil da hab ich keine ID vom Bild, sondern nur eine vom Kommentar, und brauche aber den Avatar. Ja, genau dann muss man vorab für Waffengleichheit sorgen.</p>
<p>Das kann man entweder „vorher“, also außerhalb der Funktion. Das ist zu begrüßen. Denn eine Funktion sollte tatsächlich nur eine Aufgabe haben und die immer gleich ausführen. Man könnte es theoretisch auch innerhalb der Funktion, aber das würde die Funktion unnötig aufblähen.</p>
<p>Wenn man also eine ID von einem Kommentar hat und aber die ID des zugehörigen Avatar-Bildes benötigt, muss man im Vorfeld erst mit den vorhandenen Daten diese ID rausfinden. Auch dafür könnte man wieder eine eigene Funktion erstellen, wenn es nicht womöglich auch schon eine bei WordPress gibt. Da ist dann im Fall von WordPress <a href="https://developer.wordpress.org/reference/">die Code Reference</a> eine gute Anlaufstelle.</p>
<p>Ich habe persönlich eine Weile gebraucht, bis ich vor Jahren irgendwann gemerkt habe, dass es mir hilft, wenn ich in meinen Funktionen für Waffengleichheit sorge, statt ständig neuen Code zu schreiben, oder aber dutzende Ausnahmen zu schaffen.</p>
<p>Denn wenn Ihr wisst, dass Ihr die Funktion <code>my_img()</code> verwendet und immer auf die gleiche Weise verwenden könnt, habt Ihr beim Durchsehen des Quellcodes wesentlich mehr Überblick und ärgert Euch nicht, dass WordPress in dem Kontext mal so programmiert werden will und in einer anderen Situation aber anders. Ihr könnt dann ruhigen Gewissens Eure Vorlagen entwerfen und müsst nur einmal auf die Animositäten von WordPress Rücksicht nehmen, aber eben nicht immer wieder aufs Neue.</p>
<p>Ihr schafft dann einmal „Ordnung“ und könnt Euch immer darauf verlassen, dass Ihr ein korrektes Ergebnis erhaltet, mit dem Ihr arbeiten könnt.</p>
<h3>Weitere Beispiele</h3>
<p>Die thematisierte Bild-Funktion ist nur ein Beispiel von vielen.</p>
<p>Ich reduziere, wenn ich mit WordPress arbeite, mittlerweile meine Abfragen auf ein Minimum. So kann man eine QUERY nur IDs als Ergebnis zurückgeben lassen, statt vollständige Artikel samt aller Metadaten. Ich bekomme dann ein Array mit IDs zurück und kann es überall sinnvoll einsetzen, egal ob auf der Startseite, in Archiven, oder wo immer ich es möchte.</p>
<p>Statt womöglich mehrere Male einen QUERY zum Beispiel im Template für die Startseite zu nutzen, habe ich mir einfach eine eigene <code>my_query()</code>-Funktion geschrieben. Auch die hat den Vorteil, dass ich immer weiß, was ich am Ende bekomme. Ich kann mittels Parameter den QUERY auf Artikel einer anderen Kategorie steuern. Aber ich kann auch Fälle berücksichtigen, in denen ich vielleicht ähnliche Artikel über Metadaten abfragen möchte. All das kann ich vorab einrichten, sodass ich am Ende bei <code>my_guery()</code> immer die IDs von Artikeln erhalte, mit denen ich weiterarbeiten kann.</p>
<h3>Was geht rein, was soll raus</h3>
<p>„Früher“ &#8482; hab ich eigentlich nie darüber nachgedacht, was ich mit Funktionen erreichen möchte. Also grob schon, aber nie im Detail.</p>
<p>Vor Jahren war der Anspruch eigentlich, ein wenig Arbeit zu erleichtern. Das ist er heute zwar immer noch. Doch wenn man sich darauf besinnt, zu prüfen, welche Daten in eine Funktion hineingehen und welche am Ende herauskommen, kann man sogar noch weitere Optimierungen vornehmen.</p>
<h4>Zu viele Parameter sind ein „Zeichen“!</h4>
<p>Wenn ich beispielsweise merke, dass ich noch einen, und noch einen Parameter brauche und am Ende eine Funktion habe, die zwar alles tut, was sie soll, aber ich womöglich 10, 12 unterschiedliche Parameter brauchen könnte, dann ist das auch nicht im Sinne des Erfinders. Dann ist es eher Zeit, sich vor Augen zu führen, dass ich mit weiteren Funktionen besser bedient bin, um am Ende wieder den Normalzustand herzustellen.</p>
<p>Will heißen: Wenn ich sage, in eine Funktion gehen IDs von Bildern rein und kommen Arrays mit Bildinformationen raus, dann sollte ich diese Funktion nicht damit belasten, aus möglicherweise Artikel-IDs noch Bild-IDs zu extrahieren. Für derartige Fälle kann ich mir lieber einfallen lassen, eine <code>get_my_img_ID()</code>-Funktion zu schreiben, die mir die benötigte Bild-ID liefert, mit der ich meine <code>my_img()</code>-Funktion füttern kann.</p>
<h4>Eine Zeichenkette ist eine Zeichenkette, ist eine Zeichenkette?</h4>
<p>An dieser Stelle möchte ich zum Ausklang noch ein etwas anderes Beispiel aufführen. Vielleicht kennen manche von Euch die WordPress-Funktion <code>wp_remote_get()</code>, wenn nicht, dann könnt Ihr dessen Funktionsweise in der Code Reference von WordPress <a href="https://developer.wordpress.org/reference/functions/wp_remote_get/">nachlesen</a>.</p>
<p>Die Funktion liefert ein Array zurück, das neben den Verbindungsdaten aus dem „Header“ auch den „Body“, also die eigentliche Webseite als Zeichenkette zurückgibt. Wenn Ihr aber am Ende des Tages etwas Anderes benötigt, oder nur Teile davon, dann könnt Ihr natürlich auch hier für Waffengleichheit sorgen, indem Ihr mit einer Funktion das Ergebnis bearbeitet, bis es Euren Bedürfnissen entspricht. Ich habe diese Funktion auch mal verwendet, um URLs von Bildern zu erhalten. Natürlich musste ich dann den Quellcode entsprechend „parsen“.</p>
<h4>Einen hab ich noch …</h4>
<p>Daran anschließen möchte ich noch einen Hinweis, der prima zum Stichwort Parsen passt. Es gibt ein mächtiges Werkzeug zum Parsen von Dokumenten, das sind die regulären Ausdrücke. Damit kann man tolle Sachen machen, allerdings benötigen reguläre Ausdrücke (REGEX) auch eine gewisse Einarbeitungszeit.</p>
<p>Doch wenn Ihr spontan tatsächlich gewisse „Elemente“ einer HTML-Seite extrahieren oder bearbeiten möchtet, sagen wir alle Bilder, oder alle Links, dann eignet sich dafür auch <a href="https://www.php.net/manual/de/class.domdocument.php">die PHP-Klasse DOMDocument</a> relativ gut. Wer schon mal mit Javascript programmiert hat, der wird diese Klasse zu schätzen wissen. Denn sie bietet ähnliche Angriffspunkte wie das auch in Javascript genutzte „Document Object Model“ (DOM) und ist aus diesem Grund leichter zugänglich als reguläre Ausdrücke.</p>
<p>Ihr sucht nach einem Anwendungszweck? Ihr könntet mit Javascript, unter manchen Umständen auch mit CSS, gewisse Links kennzeichnen. Aber wenn der Nutzer Javascript ausschaltet, dann ist auch die Kennzeichnung futsch und mit CSS seid Ihr nicht so flexibel. Also könntet Ihr dann den <code>$content</code> von WordPress mit DOMDocument bearbeiten. Damit Ihr am Ende aber nicht weiteren HTML-Tags oder unnötigen Ballast erhaltet, gibt es mittlerweile in PHP passende Parameter, um das zu unterbinden. Für die Funktion „loadHTML“ gibt es nämlich mittlerweile die Parameter <code>LIBXML_HTML_NOIMPLIED</code> und <code>LIBXML_HTML_NODEFDTD</code>. <a href="https://www.php.net/manual/en/libxml.constants.php">Mehr dazu</a> findet Ihr in der PHP-Dokumentation.</p>
<pre><code>function manipulate_my_content() {
	global $post
	$content = $post-&gt;post_content;
	$document = new DOMDocument();
	$document-&gt;loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
	// links extrahieren oder dergleichen geht dann ganz einfach mit:
	$links = $document-&gt;getElementsByTagName('a');
	// irgendwas mit den Links anfangen
	…
	// den manipulierten Inhalt speichern und wieder zurückgeben
	return $document-&gt;saveHTML();
}
</code></pre>
<p>Diese Ansätze, die ich in dem Beitrag erwähnt habe, helfen mir dabei, Waffengleichheit zu erzielen, und mich bei der Arbeit mit WordPress ein wenig voranzubringen.</p>
<p>Vielleicht helfen Sie Euch ja ebenso. Interessant findet Ihr dann womöglich auch die Beiträge:</p>
<ul>
<li>„<a href="https://macnotes.de/2021/01/24/von-der-idee-zum-wordpress-plug-in-schlagworter-automatisch-hinzufugen-1/">Von der Idee zum WordPress-Plug-in #1</a>“ und</li>
<li>„<a href="https://macnotes.de/2021/01/26/von-der-idee-zum-wordpress-plug-in-schlagworter-automatisch-hinzufugen-2/">Von der Idee zum WordPress-Plug-in #2“</a>.</li>
</ul>
<p>Der Beitrag <a href="https://macnotes.de/2021/03/15/wie-man-bei-der-wordpress-programmierung-fur-waffengleichheit-sorgt/">Wie man bei der WordPress-Programmierung für Waffengleichheit sorgt</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>Von der Idee zum WordPress-Plug-in: Schlagwörter automatisch hinzufügen #2</title>
		<link>https://macnotes.de/2021/01/26/von-der-idee-zum-wordpress-plug-in-schlagworter-automatisch-hinzufugen-2/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Tue, 26 Jan 2021 00:33:34 +0000</pubDate>
				<category><![CDATA[Tipps]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=516259</guid>

					<description><![CDATA[<p>In Teil 1 von der Idee zum WordPress-Plug-in beschrieb ich bereits umfassend die Beweggründe, wie man von ein paar Zeilen Code für eine regelmäßig wiederkehrende Aufgabe am Ende des Tages zu einem ausgewachsenen Plug-in kam. Der vorherige Text wies außerdem bereits fertigen, funktionierenden Quellcode auf, mit dem man von Hand ohne Weiteres hätte arbeiten können. [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2021/01/26/von-der-idee-zum-wordpress-plug-in-schlagworter-automatisch-hinzufugen-2/">Von der Idee zum WordPress-Plug-in: Schlagwörter automatisch hinzufügen #2</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'><a href="https://macnotes.de/2021/01/24/von-der-idee-zum-wordpress-plug-in-schlagworter-automatisch-hinzufugen-1/">In Teil 1 von der Idee zum WordPress-Plug-in</a> beschrieb ich bereits umfassend die Beweggründe, wie man von ein paar Zeilen Code für eine regelmäßig wiederkehrende Aufgabe am Ende des Tages zu einem ausgewachsenen Plug-in kam. Der vorherige Text wies außerdem bereits fertigen, funktionierenden Quellcode auf, mit dem man von Hand ohne Weiteres hätte arbeiten können. Doch was wäre ein Plug-in ohne Komfort. Für Komfort dient die Eingabe vom Nutzer, und die speichert man am besten in der Datenbank ab.</p>
<p>Genau das wollen wir Euch dann in dieser Ausgabe erklären, und auch, welche Grenzen unser Plug-in weiterhin hat. Die Herangehensweise zeigt vor allem, dass so ein relativ einfaches Projekt mit ein wenig Fantasie und Aufwand zu etwas richtig seriösem aufgebaut werden kann.</p>
<h2>Das Plug-in braucht mehr Komfort</h2>
<p>Anstatt den Quellcode immer von Hand anzupassen, wenn man neue Schlagwörter hinzufügen möchte, kann man dazu die Datenbank bei WordPress verwenden und entsprechende Formulare. Folgende „Details“ und „Fragen“ gibt es unter anderem zu klären, von denen wir aber nur einige exemplarisch nennen wollen:</p>
<ul>
<li>Wie kann ich mit der Datenbank von WordPress kommunizieren?</li>
<li>Benötige ich eine eigene Tabelle?</li>
<li>Wie handhabt WordPress Formulare?</li>
<li>Gibt es Sicherheitsvorkehrungen zu treffen?</li>
<li>Muss ich mehrere Plug-in-Dateien erstellen?</li>
<li>Was ist die WordPress-Nonce, und wie kann sie mir in diesem Fall helfen?</li>
</ul>
<h2>Wann benötige ich für mein Plug-in eine eigene Tabelle?</h2>
<p>Es ist eine <a href="https://wordpress.stackexchange.com/questions/53932/is-it-bad-practice-to-create-own-table-for-a-plugin">viel diskutierte Frage</a>, ob es sinnvoll sein kann, eine eigene Tabelle für ein WordPress-Plug-in einzurichten. Eines der Schwergewichte unter den WordPress-Plug-ins, Yoast SEO, änderte vor ein paar Monaten seine Einstellung zu der Thematik und migriert seitdem mit jedem Update zunehmend mehr Daten aus WordPress-Tabellen in eigene.</p>
<p>Für mich liegt die Antwort auf der Hand: Ich mache immer eine eigene Tabelle, wenn ich eigene Daten verwenden möchte. Sieht man davon ab, dass WordPress-Tabellen vor allem bei großen Websites sowieso relativ unübersichtlich werden, kann es beim Abfragen von Daten auch Performance-Vorteile bieten. In der Tat ergibt es aber nur wenig Sinn, den Aufwand zu betreiben, wenn man am Ende nur eine Handvoll Datensätze speichern mag. Die lassen sich zur Not auch noch in der WordPress-Tabelle sichern.</p>
<h2>Wie kommuniziere ich mit der WordPress-Datenbank?</h2>
<p>WordPress hält für Entwickler Befehle zur Verfügung, um mit der Datenbank zu kommunizieren. In Einzelfällen kann es sinnvoll sein, die WordPress-Routinen zu umgehen und mittels PHP oder anderer Scriptsprachen die Kommunikation zur Datenbank auf eigene Faust zu unternehmen. Das ist aber nur in Fällen ratsam, in denen man wirklich viele Datensätze bearbeitet, und an dieser Stelle rede ich von zehntausenden Datensätzen und mehr, die regelmäßig immer wieder abgefragt werden oder aktualisiert werden. Denn zur Wahrheit gehört, <a href="https://macnotes.de/2020/01/16/wie-wordpress-das-web-verstopft-google-fonts-gutenberg-und-mehr/">dass die WordPress-Datenbank-Engine nicht die schnellste ist</a>.</p>
<p>In Teil 1 wiesen wir bereits auf Befehle wie <code>add_option()</code> (vgl. <a href="https://developer.wordpress.org/reference/functions/add_option/">WordPress Code-Referenz</a>) hin, mit dem sich Daten ohne Weiteres in die Tabelle <code>wp_options</code> von WordPress hinzufügen lassen. Mittels <code>update_option()</code> kann man vorhandene Datensätze aktualisieren, und sie mit <code>delete_option()</code> entsprechend wieder entfernen.</p>
<p>Doch wir wollen nicht die WordPress-Tabelle zumüllen, sondern mit der eigenen Tabelle kommunizieren. Diese funktioniert über die <code>wpdb</code>-Schnittstelle.</p>
<h3>Eigene Tabelle für WordPress erstellen</h3>
<p>Klar kann man die Tabelle für das eigene Plug-in auch von Hand erstellen, über phpMyAdmin oder eine andere Software, auch am Desktop-Computer. Wer sich auskennt, kann dazu auch einfach die mysql-Schnittstelle auf dem Server mittels Terminal verwenden. Doch bei einem Plug-in geht es ja um die Wiederverwendbarkeit und die Möglichkeit, dass auch andere Nutzer damit arbeiten können.</p>
<p>Entsprechend nutzen wir die WordPress-eigenen Mittel, um die Tabelle zu erstellen. Der beste Zeitpunkt dafür ist übrigens beim „Aktivieren“ des Plug-ins. Wie im ersten Teil dieses Tutorials schon beschrieben, trennt WordPress zwischen dem Aktivieren, Deaktivieren und Deinstallieren. Dafür gibt es extra drei passende „Auslöser“, die wir uns zunutze machen können.</p>
<p>In unserem Fall benötigen wir eine Tabelle, die lediglich drei Reihen umfasst, eine fortlaufende Nummerierung (ID), eine Suchphrase (searchstring) und ein Schlagwort (keywordstring). Um in mySQL eine Tabelle mit dieser Struktur einzurichten, benötigt man folgenden Code:</p>
<pre><code>CREATE TABLE XYZ (
		id mediumint(9) NOT NULL AUTO_INCREMENT,
		searchstring varchar(25) NOT NULL,
		keywordstring varchar(25) NOT NULL,
		UNIQUE KEY id (id),
	    UNIQUE KEY searchstring (searchstring)
	) ZEICHENSATZ;
</code></pre>
<p>Wir müssen der Tabelle noch einen Namen geben und auch einen Zeichensatz angeben. Da aber durch die Installation von WordPress je nach Konfiguration von WordPress ein Zeichensatz genutzt wird, und wir uns nicht den Kopf darüber zerbrechen wollen, welcher das ist, verwenden wir einfach <code>$wpdb-&gt;get_charset_collate()</code> (vgl. <a href="https://developer.wordpress.org/reference/classes/wpdb/get_charset_collate/">WordPress Code-Referenz</a>), um den Zeichensatz abzufragen.</p>
<p>Ja, und auch bei der Namensgebung für die Tabelle, wollen wir uns zumindest an die Gepflogenheiten halten und greifen daher auf das Präfix zurück, das WordPress uns anbietet, und Nutzer bei der Installation individuell einrichten können (<code>$wpdb-&gt;prefix</code>). Unsere Tabelle nennen wir dann noch <code>sn_add_keywords</code>, die entsprechend mit dem Präfix von WP ausgestattet wird.</p>
<h3>Tabelle bei Plug-in-Aktivierung einrichten</h3>
<p>Nun gehen wir davon aus, dass wir die Tabelle beim Aktivieren des Plug-ins einrichten möchten. Wir greifen dazu also auf den <code>register_activation_hook()</code> (vgl. <a href="https://developer.wordpress.org/reference/functions/register_activation_hook/">WordPress Code-Referenz</a>) zurück.</p>
<p>Dieser Aufruf hat zwei Parameter. Der erste nennt den Dateinamen des Plug-ins inklusive Pfadangabe. Dafür gibt es glücklicherweise eine Konstante namens <code>__FILE__</code>, die uns die Arbeit erleichtert, wenn wir uns an die Konventionen halten und unser Plug-in auch im Plug-in-Verzeichnis unterbringen. Der zweite Parameter ruft eine Funktion auf, die dann zum Zeitpunkt der Aktivierung des Plug-ins aktiv wird.</p>
<p>Wir erstellen also eine Funktion, die uns die Tabelle erstellt. Die sieht wie folgt aus:</p>
<pre><code>function sn_add_keywords_create_database() {
  global $wpdb;
  $charset_collate = $wpdb-&gt;get_charset_collate();
  $table_name = $wpdb-&gt;prefix . 'sn_add_keywords';

  $sql = "CREATE TABLE $table_name (
		id mediumint(9) NOT NULL AUTO_INCREMENT,
		searchstring varchar(25) NOT NULL,
		keywordstring varchar(25) NOT NULL,
		UNIQUE KEY id (id),
    UNIQUE KEY searchstring (searchstring)
	) $charset_collate;";

	require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
	dbDelta( $sql );
}
</code></pre>
<p>Die rufen wir dann mit dem passenden Auslöser auf:</p>
<pre><code>register_activation_hook(__FILE__, 'sn_add_keywords_create_database');
</code></pre>
<h3>Tabelle bei der Deinstallation löschen</h3>
<p>Man könnte die Tabelle theoretisch auch beim Deaktivieren schon löschen. Aber das erachten wir für nicht sinnvoll. Bei der Deinstallation eines Plug-ins sollte man aber sehr wohl darauf achten, hinter sich sauberzumachen. Wir setzen in dem Fall den <code>register_uninstall_hook()</code> ein. Der funktioniert analog zum Aktivierungsauslöser und hat die gleichen beiden Parameter. Wir erstellen also eine Funktion, die die Datenbank löscht:</p>
<pre><code>function sn_add_keywords_remove_database() {
  global $wpdb;
  $table_name = $wpdb-&gt;prefix . 'sn_add_keywords';
  $sql = "DROP TABLE IF EXISTS $table_name";
  $wpdb-&gt;query($sql);
}
</code></pre>
<p>Diese rufen wir dann mit dem Auslöser wie folgt auf:</p>
<pre><code>register_uninstall_hook(__FILE__, 'sn_add_keywords_remove_database');
</code></pre>
<h2>Wie kommuniziert unser Plug-in mit der Datenbank?</h2>
<p>Wie man mittels WordPress-Funktionen mit der Datenbank kommuniziert, haben wir schon angeschnitten. Aber damit unser Plug-in, das ebenfalls kann, benötigt es ein Formular.</p>
<p>Zudem können wir an dieser Stelle noch ein paar Sicherheitsvorkehrungen treffen. Anders als bei einem Formular zur Anmeldung beim Newsletter, wollen wir vermutlich nur Personen Schlagworte hinzufügen lassen, denen wir vertrauen. Auch müssen wir sicherstellen, dass in der Datenbank nichts „Bösartiges“ gespeichert wird. Aus diesem Grund nutzen wir die wordpress-eigenen Befehle für die Datenbankkommunikation, weil manche von ihnen bereits Sicherheitsmechanismen enthalten, und wir so ein bisschen beruhigter sein können. Doch, der Reihe nach.</p>
<h3>Formular für die Datenbankeingabe erstellen</h3>
<p>An dieser Stelle kann man ohne Umschweife zunächst einmal ein einfaches Formular in HTML erstellen. Wir benötigen zwei Eingabefelder für Text, eventuell noch zwei Etiketten und einen Button (oder Link) zum Absenden des Formulars. Der Einfachheit halber – weil es funktioniert, und um schnell erste Ergebnisse zu erhalten – verwenden wir keine spezielle Aktion zum Auslösen, und nutzen die <code>POST</code>-Methode.</p>
<p>Unser HTML-Formular sieht wie folgt aus:</p>
<pre><code>&lt;form method="POST"&gt;
	&lt;?php wp_nonce_field('sn_add_keywords', 'sn_add_keywords_nonce', true, true); ?&gt;
    &lt;h2&gt;Neuen Eintrag hinzufügen:&lt;/h2&gt;
    &lt;label for="searchstring"&gt;Searchstring:&lt;/label&gt;
    &lt;input type="text" id="searchstring" name="searchstring" required&gt;
    &lt;label for="keywordstring"&gt;Keywordstring:&lt;/label&gt;
    &lt;input type="text" id="keywordstring" name="keywordstring" required&gt;
	&lt;?php submit_button('Hinzufügen'); ?&gt;
&lt;/form&gt;
</code></pre>
<p>Die <code>submit_button()</code>-Funktion stellt WordPress zur Verfügung. In Klammern übergeben wir die Beschriftung für den Button. Der Button erhält dann auch die typischen Klassen, damit er mittels CSS automatisch in der für WordPress typischen Kolorierung und Form erscheint. Wer das individuelle handhaben mag, kann natürlich einen eigenen Button erstellen.</p>
<h3>Was ist dieses Nonce, und wieso brauche ich sie?</h3>
<p>Im obersten Feld des Formulars erkennt Ihr den Befehl <code>wp_nonce_field()</code>, den WordPress ebenfalls zur Verfügung stellt. Die „Nonce“ (vgl. <a href="https://de.wikipedia.org/wiki/Nonce">Wikipedia</a>) ist eine flüchtige Phrase, die zum Zwecke der Authentifizierung erstellt wird.</p>
<p>WordPress bietet dieses System ebenfalls an. Es ist sehr hilfreich, wenn man die Kommunikation mit der Datenbank nur authentifizierten Nutzern zu ermöglichen. Denn die Nonce wird beim Aufruf erzeugt und ist dann nur in der Session des Nutzers gültig. Würde jemand, der gar nicht mit WordPress eingeloggt ist, versuchen die Funktion auszuführen, scheiterte die Kommunikation daran, dass er nicht die korrekte „Nonce“ dafür hat.</p>
<p>Wir werden dann die erstellte Nonce noch überprüfen, bevor wir tatsächlich in die Datenbank schreiben.</p>
<h3>Formular-Daten in die Datenbank schreiben</h3>
<p>Nun müssen wir uns also noch darum kümmern, die im Formular eingegebenen Daten beim Klick auf den Button in die Datenbank zu speichern. Wie machen wir das?</p>
<p>Zum einen haben wir ja geschrieben, dass die Daten mittels POST-Methode übergeben werden. Sie sind dann entsprechend über die <a href="https://www.php.net/manual/de/reserved.variables.post.php">POST-Variablen</a> auslesbar. Mit dem Nonce-Field erzeugt WordPress aber noch ein unsichtbares Feld mit dem Authentifizierungstoken. Auch der ist dann als POST-Variable abfragbar und lässt sich so vergleichen.</p>
<p>Für das Schreiben in die Datenbank, kann man entweder ein eigenes QUERY and <code>$wpdb</code> übergeben, oder wir nutzen den von WordPress implementierten <code>$wpdb-&gt;insert()</code>-Befehl.</p>
<pre><code>if(is_admin() &amp;&amp; (isset($_POST['sn_add_keywords_nonce']) || wp_verify_nonce($_POST['sn_add_keywords_nonce'], 'sn_add_keywords'))) {
	global $wpdb;
	$table_name = $wpdb-&gt;prefix . 'sn_add_keywords';
	$newdata = array(
        'searchstring' =&gt; sanitize_text_field($_POST['searchstring']),
        'keywordstring' =&gt; sanitize_text_field($_POST['keywordstring']),
      );
    $wpdb-&gt;insert($table_name, $newdata, '%s');
    wp_safe_redirect(esc_url(admin_url('admin.php?page=sn_add_keywords%2Fsnak.php')));
}
exit();
</code></pre>
<p>Über den Befehl <code>wp_safe_redirect()</code> leiten wir nach dem Absenden den Benutzer wieder zurück zur Ausgangsseite. Diese Vorgehensweise hat übrigens einen Nachteil, den wir in Kauf nehmen, der aber für ein frei verfügbares Plug-in ausgebessert werden sollte, zum Beispiel, indem man AJAX verwendet.</p>
<p>Zuletzt stellen wir über den <code>exit()</code>-Befehl sicher, dass wirklich alle POST-Variablen nach dem Abschluss gelöscht werden. So wird das Formular geleert und auch eine neue Nonce erstellt.</p>
<p>Das Plug-in, wie wir es verwenden sieht bei uns dann übrigens derzeit so aus.</p>
<div data-id="516258" class="ajaxGalleryInit" style="display:none;"></div>
<h2>Was wir nicht erzählt haben?</h2>
<p>Auch dieser Beitrag ist schon wieder ziemlich lang geworden. Deshalb haben wir einige Details geschlabbert. Darunter:</p>
<ul>
<li>Denn in unserem Plug-in haben wir beispielsweise bei der Aktivierung auch eine Versionsnummer übergeben. Die können wir dann bei einem Update vergleichen und nutzen, um so Änderungen an der Datenbank vorzunehmen.</li>
<li>Wir haben aber auch unterschlagen, dass wir unsere Tabelle beim Aktivieren bereits mit ein paar Datensätzen ausgestattet haben. Ich finde es immer schöner, wenn man zumindest ein paar Anhaltspunkte hat.</li>
<li>Es kann außerdem sinnvoll sein, die Daten nicht zu löschen, oder dies dem Nutzer zur Wahl zu stellen. Um so eine Option haben wir uns bislang nicht gekümmert.</li>
<li>WordPress hält auch Alternativen zu den „Auslösern“ bereit. So kann man Dateien namens <code>uninstall.php</code> oder <code>activation.php</code> erstellen. Deren Inhalte werden dann automatisch ausgeführt.</li>
<li>Wie Ihr auf dem Screenshot erkennen könnt, geben wir die vorhandenen Datensätze auch im WordPress-Administrationsportal aus. Wie wir das gemacht haben, haben wir an dieser Stelle ebenso geschlabbert.</li>
<li>Nicht thematisiert haben wir den Prozess, wie man ein Plug-in bei WordPress einreicht. Vielleicht kommt das in einem anderen Beitrag einmal zur Sprache, oder Ihr findet es bis dahin selbst heraus.</li>
<li>Spannend ist auch, wie man bereits vorhandene Daten wieder löscht, oder überarbeitet.</li>
<li>Der Quellcode hier enthält auch kein CSS und gibt ganz grundsätzlich nicht das komplette Plug-in wieder, wie wir es verwenden. Zum Zwecke des Tutorials habe ich diesen angepasst, damit er allgemein verständlicher wird.</li>
</ul>
<p>Tatsächlich ist diese „Idee“, aus der erst eine Handvoll Quellcode wurde, in unserem Fall mittlerweile auf fünf Dateien mit rund 250 Zeilen Quellcode angewachsen (Kommentare inklusive).</p>
<p>Wenn jemand von Euch Fragen zu diesem Projekt hat, kann er uns gerne auf den üblichen Kanälen anschreiben.</p>
<p>Der Beitrag <a href="https://macnotes.de/2021/01/26/von-der-idee-zum-wordpress-plug-in-schlagworter-automatisch-hinzufugen-2/">Von der Idee zum WordPress-Plug-in: Schlagwörter automatisch hinzufügen #2</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>Gibt es noch Klopapier bei DM? Widget fürs iPhone weiß Rat</title>
		<link>https://macnotes.de/2020/10/22/gibt-es-noch-klopapier-bei-dm-widget-furs-iphone-weiss-rat/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Thu, 22 Oct 2020 17:26:02 +0000</pubDate>
				<category><![CDATA[Tipps]]></category>
		<category><![CDATA[Gesundheit]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Technologie]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=430937</guid>

					<description><![CDATA[<p>Es gibt eigentlich nichts, was nicht gibt. Vor allem in unserer vernetzten Welt stehen viele Informationen zur Verf&#252;gung, auch &#252;ber APIs, die man nur abrufen muss. Wer nun in der Covid-19-Pandemie wissen will, ob es bei seinem DM um die Ecke noch Klopapier gibt, der kann sich dazu mit ein wenig Aufwand ein Widget aufs [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/10/22/gibt-es-noch-klopapier-bei-dm-widget-furs-iphone-weiss-rat/">Gibt es noch Klopapier bei DM? Widget fürs iPhone weiß Rat</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>Es gibt eigentlich nichts, was nicht gibt. Vor allem in unserer vernetzten Welt stehen viele Informationen zur Verf&uuml;gung, auch &uuml;ber APIs, die man nur abrufen muss. Wer nun in der Covid-19-Pandemie wissen will, ob es bei seinem DM um die Ecke noch Klopapier gibt, der kann sich dazu mit ein wenig Aufwand ein Widget aufs <a href="https://macnotes.de/produkt/iphone/">iPhone</a> basteln. Wir erkl&auml;ren Euch, wie es funktioniert, und auch, wie Ihr die Information im Terminal am Mac oder Windows-PC abfragen k&ouml;nnt.</p>
<p>Marco Dengel machte sich die M&uuml;he mit der Scriptable-App ein Widget anzufertigen, das den Restbestand an Klopapier in einem DM-Drogeriemarkt anzeigt. M&ouml;glich macht dies eine Produkt-API, an der man die Verf&uuml;gbarkeit abfragen kann.</p>
<p>Ihr ben&ouml;tigt daf&uuml;r in jedem Fall ein iPhone, <a href="https://macnotes.de/produkt/ipad/">iPad</a> oder einen iPod touch mit <a href="https://macnotes.de/2020/09/16/ios-14-und-ipados-14-von-apple-veroffentlicht/">iOS 14</a> oder neuer und <a href="https://apps.apple.com/us/app/scriptable/id1405459188?ign-mpt=uo%3D4">die App Scriptable</a> in Version 1.5 oder neuer.</p>
<h2>Quellcode in die Scriptable-App eintragen</h2>
<p>Marco Dengel stellt den Quellcode freundlicherweise <a href="https://gist.github.com/marco79cgn/23ce08fd8711ee893a3be12d4543f2d2">auf Github bereit</a>. Diesen Quellcode m&uuml;sst Ihr lediglich in die Scriptable-App am iPhone eingeben.</p>
<h3>Was ist Scriptable?</h3>
<p>Scriptable ist eine App, die Euch erm&ouml;glich mittels Javascript Aufgaben am iPhone (oder andernorts) auszuf&uuml;hren. Ihr k&ouml;nnt Euch dann zum Beispiel &uuml;ber Benachrichtigungen informieren lassen, wenn Euer Webserver nicht erreichbar ist, oder wenn, wie in diesem Fall, bei DM das Klopapier knapp wird.</p>
<h3>Wie werden die Daten abgefragt?</h3>
<p>DM stellt dazu offenbar eine API bereit und diese fragt Dengel in seinem Code mittels JSON-Objekt ab, wertet die Informationen aus und gibt sie &uuml;ber das Widget aus.</p>
<h2>Widget installieren</h2>
<p>Ihr geht folgenderma&szlig;en vor, wenn Ihr das Klopapier-Widget installieren m&ouml;chtet:</p>
<ol>
<li>&Ouml;ffnet die passende Github-Seite auf Eurem iPhone.</li>
<li>Klickt dann auf die &bdquo;RAW&ldquo;-Anzeige. Markiert und kopiert den Text. Wenn Euer Mac und iPhone oder iPad neu genug sind, k&ouml;nnt Ihr den Quellcode auch am Mac in die geteilte Zwischenablage kopieren und dann trotzdem am iOS-Ger&auml;t einf&uuml;gen.</li>
<li>&Ouml;ffnet Scriptable.</li>
<li>Tippt dort auf das Plus-Symbol und f&uuml;gt ein Script hinzu.</li>
<li>Kopiert dann den Quellcode in das Editorfenster.</li>
<li>Gebt dem Kind noch einen Namen und speichert es.</li>
<li>&Ouml;ffnet dann Euren Home-Bildschirm am iPhone oder iPad. Haltet dort ein Programm-Icon l&auml;nger gedr&uuml;ckt, bis der Dialog erscheint, in dem Ihr &bdquo;Home-Bildschirm bearbeiten&ldquo; ausw&auml;hlen k&ouml;nnt.</li>
<li>Tippt nun auf das Plus-Symbol oben links, um ein Widget hinzuzuf&uuml;gen. Scrollt ein wenig herunter, um Scriptable ausw&auml;hlen zu k&ouml;nnen und f&uuml;gt ein Widget hinzu.</li>
<li>Solange die Icons noch am Wackeln sind, tippt auf das neue Widget. Ihr k&ouml;nnt nun Einstellungen vornehmen, bspw. das Script ausw&auml;hlen, als Ausf&uuml;hrart &bdquo;Run Script&ldquo; und als Parameter m&uuml;sst Ihr die ID des Ladengesch&auml;fts Eurer Wahl angeben.</li>
<li>Fertig!</li>
</ol>
<h3>Wie finde ich die ID meines DM-Ladengesch&auml;fts?</h3>
<p>&Ouml;ffnet den &bdquo;<a href="https://www.dm.de/store">Store Finder</a>&ldquo; auf der Webseite von DM. Tippt dann in der Ergebnisliste auf &bdquo;weitere Details&ldquo;. W&auml;hrend die &Uuml;bersichtskarte sich ver&auml;ndert, passt DM aber auch die URL an. In der URL seht Ihr dann die ID Eures Ladengesch&auml;fts.</p>
<p><strong>Beispiel:</strong> Ein DM bei uns in der N&auml;he hat die ID 2764, die sich aus dem URL <code>https://www.dm.de/store/de-2764/niederzier/rurbenden-2</code> ergibt.</p>
<h2>Wie korrekt ist die Anzeige?</h2>
<p>Marco Dengel hat in seinem Script alle Klopapier-Sorten fest programmiert, filtert aber das &bdquo;feuchte&ldquo; Klopapier heraus. Wenn Ihr ein wenig Ahnung von Javascript habt, oder zumindest der englischen Sprache m&auml;chtig seid, k&ouml;nnt Ihr das Script schnell so anpassen, dass ein anderes Produkt abgefragt wird, Babywindeln vielleicht, oder Tofu, oder nur eine spezielle Sorte Klopapier.</p>
<h2>Ist das nicht illegal?</h2>
<p>DM stellt die API bereit, entsprechend ist es nicht illegal sie abzufragen. Aber vermutlich hat der Drogeriemarkt-Betreiber die API nicht f&uuml;r diese Zwecke erdacht. Sollte es DM irgendwann zu viel Datenaufkommen sein, k&ouml;nnte der Anbieter sich entscheiden, die API nur noch privat mit passenden Schl&uuml;sseln anzubieten. Dann w&auml;re das Widget hinf&auml;llig. Aber solange k&ouml;nnen wir uns daran erfreuen.</p>
<p>Vielen Dank an Marco Dengel f&uuml;r diese sinnvolle Verwendung von modernster Technik. ;)</p>
<h2>Klopapier per Terminal abfragen</h2>
<p>Um eine Abfrage einfach per Terminal in Windows, macOS oder Linux zu starten, reicht der folgende Befehl:</p>
<p><code><span class="css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0"> curl -s "</span><span class="css-901oao css-16my406 r-1qd0xha r-hiw28u r-ad9z0x r-bcqeeo r-qvutc0" aria-hidden="true">https://</span>products.dm.de/store-availabi<span class="css-901oao css-16my406 r-1qd0xha r-hiw28u r-ad9z0x r-bcqeeo r-qvutc0" aria-hidden="true">lity/DE/availability?dans=595420,708997,137425,28171,485698,799358,863567,452740,610544,846857,709006,452753,879536,452744,485695,853483,594080,504606,593761,525943,842480,535981,127048,524535&amp;storeNumbers=2764</span><span class="css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0">" | jq '[.storeAvailabilities[][0].stockLevel] | add'</span></code></p>
<p>Ihr m&uuml;sst ganz am Ende nat&uuml;rlich auch die Store-ID anpassen. Am&uuml;sant ist, wenn Nutzer dies nun noch <a href="https://twitter.com/amdux/status/1319283464097574914">automatisieren</a> und regelm&auml;&szlig;ig den Stand diverser Ladengesch&auml;fte abfragen.</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/10/22/gibt-es-noch-klopapier-bei-dm-widget-furs-iphone-weiss-rat/">Gibt es noch Klopapier bei DM? Widget fürs iPhone weiß Rat</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>WordPress: CSS-Klasse zu Tablepress hinzufügen (mit Javascript oder PHP)</title>
		<link>https://macnotes.de/2020/07/29/wordpress-tablepress-eine-klasse-hinzufugen-mit-javascript-oder-php/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Wed, 29 Jul 2020 14:48:29 +0000</pubDate>
				<category><![CDATA[Tipps]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=402579</guid>

					<description><![CDATA[<p>Momentan setzen wir bei Macnotes „noch“ auf WordPress.1 Da ich zuletzt auch ein Projekt für eine Kundin betreute, bei dem ich ein Joomla auf ein WordPress migrieren musste, sind bei der Arbeit viele Erkenntnisse angefallen, die ich nun nach und nach mit Euch teilen möchte. Eines davon ist, wie man Tablepress eine oder mehrere CSS-Klassen [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/07/29/wordpress-tablepress-eine-klasse-hinzufugen-mit-javascript-oder-php/">WordPress: CSS-Klasse zu Tablepress hinzufügen (mit Javascript oder PHP)</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>Momentan setzen wir bei Macnotes „noch“ auf WordPress.<sup><a id="ffn1" class="footnote" href="#fn1">1</a></sup> Da ich zuletzt auch ein Projekt für eine Kundin betreute, bei dem ich ein Joomla auf ein WordPress migrieren musste, sind bei der Arbeit viele Erkenntnisse angefallen, die ich nun nach und nach mit Euch teilen möchte. Eines davon ist, wie man Tablepress eine oder mehrere CSS-Klassen hinzufügen kann.</p>
<p>Wichtig ist zu erwähnen. Es gibt in der Regel mehrere Möglichkeiten, das Ziel zu erreichen. Zum Beispiel könntet Ihr einfach die vorhandenen CSS-Klassen nutzen und denen zusätzliche Einheiten und Werte zuordnen.</p>
<p>Doch vielleicht arbeitet Ihr mit einem CSS-Framework, das regelmäßig aktualisiert wird, und möchtet einfach von dessen Stilvorlagen profitieren.</p>
<h2>Tablepress eine CSS-Klasse hinzufügen</h2>
<p>Wir verwenden momentan das CSS-Framework Bulma. Dort gibt es unter anderem die Klasse „table“ für Tabellen. Tablepress aber nutzt seine eigene Klasse „tablepress“. Die Recherche nach Lösungen, wie man eine weitere Klasse hinzufügen kann, lieferte nur unzureichende Ergebnisse. Deshalb war es an der Zeit, selbst aktiv zu werden. Wir präsentieren Euch in der Folge gleich zwei mögliche Lösungen.</p>
<h3>Der einfache Weg: Javascript</h3>
<p>Ich habe in den letzten Monaten Javascript zu schätzen gelernt.<sup><a id="ffn2" class="footnote" href="#fn2">2</a></sup> Über die Konsole im Browser kann man nämlich direkt mit der Webseite interagieren und kann auf einfachste Weise schnell Änderungen vornehmen.</p>
<p>So auch in diesem Fall. Ihr sucht also einfach nach dem Element, das Ihr verändern wollt. Da Tablepress die Klasse „tablepress“ seinen Tabellen hinzufügt, habt Ihr es einfach, denn über <code>document.getElementsByClassName('tablepress')</code> könnt Ihr die Tabelle im Text finden. Auf diese Weise erreicht Ihr eine HTML-Kollektion, denn es sind ja in der Regel noch Inhalte in der Tabelle. Mit <code>[0]</code> wählt Ihr, vergleichbar wie bei einem Array, das erste Resultat aus. Das könnte man auch in einer Variable speichern, muss man aber nicht, sondern kann es direkt „manipulieren“.</p>
<p>Javascript erlaubt Euch dazu mit <code>classList</code> auf die vorhandenen Klassen zuzugreifen und über <code>add()</code> könnt Ihr direkt eine oder mehrere Klassen hinzufügen. Das sieht dann wie folgt aus:</p>
<pre><code>document.getElementsByClassName('tablepress')[0].classList.add('table');</code></pre>
<h4>Ressourcen schonen</h4>
<p>Wir sind aber noch nicht am Ende. Denn ich lagere solchen Javascript-Code meist in den Footer aus, damit er das Laden der Seite nicht blockiert. Doch Ihr könnt auch noch abfragen, ob der Text überhaupt eine solche Tabelle enthält. Dafür stellt WordPress ja die Funktion (vgl. <a href="https://developer.wordpress.org/reference/functions/has_shortcode/">WordPress-Codex</a>) <code>has_shortcode()</code> zur Verfügung. Ihr ladet also den obigen Code nur dann, wenn der Nutzer überhaupt eine Tabelle sieht. Damit wird er auf anderen Seiten ohne Tabelle gar nicht erst geladen. Und weil Tabellen auch nicht auf Archiv-Seiten oder der Startseite und in Suchergebnissen gezeigt werden, eignet sich noch eine weitere Funktion (Conditional Tag) namens <code>is_singular()</code> (vgl. <a href="https://developer.wordpress.org/reference/functions/is_singular/">WordPress-Codex</a>). <code>is_singular()</code> berücksichtigt im Vergleich zu <code>is_single()</code> auch Seiten und eben nicht nur Beiträge. Da wir auf Seiten auch Tabellen von Tablepress einsetzen, ist das in dem Fall sinnvoll.</p>
<p>Die komplette Integration sieht dann am Ende wie folgt aus:</p>
<pre><code>&lt;?php if (is_singular()) {
if(has_shortcode( $post-&gt;post_content, 'table')) { ?&gt;
&lt;script&gt;
	document.getElementsByClassName('tablepress')[0].classList.add('table');
&lt;/script&gt;
&lt;?php }
} ?&gt;</code></pre>
<p>Warum ist dies der „einfachere“ Weg? Nun, weil ich das binnen weniger Minuten in der Konsole des Browsers ausprobieren kann und so direkt zum Ziel komme.</p>
<p>Veränderungen am Quellcode kann man so sehr einfach vornehmen und austüfteln.</p>
<h4>Einschränkungen (und Lösung): Mehr als eine Tabelle</h4>
<p>In dem hier gegebenen Beispiel gehen wir davon aus, dass man nur eine Tabelle nutzt. Wer sich ein wenig mit Javascript auskennt, kann aber auch die Vorkommnisse mehrerer Tabellen berücksichtigen und dann mit einer Schleife die Klasse in allen hinzufügen. Das Ergebnis der „Suche“ ist eine „HTMLCollection“, also kein Array. Doch weil diese Element sich ähneln, hält Javascript eine Funktion <code>Array.from()</code> bereit, um so eine Sammlung in ein Array zu verwandeln. Auf diese kann man dann eine forEach-Schleife anwenden. Der Vollständigkeit halber präsentieren wir auch diesen Code:</p>
<pre><code>&lt;?php if (is_singular()) {
if(has_shortcode( $post-&gt;post_content, 'table')) { ?&gt;
&lt;script&gt;
var tables = document.getElementsByClassName('tablepress');
Array.from(tables).forEach(addClass);
function addClass(table) {
	table.classList.add('dodoBingo');
}
&lt;/script&gt;
&lt;?php }
} ?&gt;</code></pre>
<h3>Der nicht viel schwierigere Weg: PHP</h3>
<p>„Schwieriger“ ist in diesem Zusammenhang vermutlich das falsche Attribut. Denn es war eher „aufwändiger“ an die Lösung mittels PHP zu gelangen.</p>
<p>Der Dampfhammer wäre gewesen, den <code>$content</code> zu manipulieren. Aber es gibt andere Mittel und Wege, die auch ein wenig den Entdeckergeist wecken können. WordPress bietet sogenannter „Hooks“ und „Filter“ (vgl. <a href="https://developer.wordpress.org/plugins/hooks/custom-hooks/">WordPress-Codex</a>). Plugin-Entwickler, gerade von komplexeren Plugins, machen von diesen ebenfalls Gebrauch, um unterschiedliche Situationen zu kreieren. Sie selbst nutzen dann diese Hooks und Filter, um die Ausführung des Plugins zu manipulieren, je nachdem, was der Nutzer eingegeben hat. Blöderweise sind diese Hooks und Filter der Plugins aber kaum wirklich durch die Entwickler dokumentiert.</p>
<h4>Entdeckungsreise im Quellcode</h4>
<p>Bei Tablepress sieht der Entwickler einige Anwendungen vor und beschreibt diese aber nicht. Er gibt ein paar Beispiele und <a href="https://tablepress.org/faq/documentation-plugin-hooks/">erklärt ansonsten</a>, dass der „Quellcode viele davon enthielte“.</p>
<p>Also öffnen wir ein Terminal und schauen uns an, ob denn nicht eventuell sogar ein Filter dabei ist, der die Ausgabe nach unseren Wünschen verändern kann. Dazu eignet sich z. B. der Befehl <code>grep</code>. Wir navigieren also ins Plugin-Verzeichnis.<sup><a id="ffn3" class="footnote" href="#fn3">3</a></sup> Da wir nicht wissen, in welcher Datei die Filter enthalten sind, und das Plugin aber Unterverzeichnisse hat probieren wir es mit <code>grep -r 'apply_filters' .</code>. Der Parameter „r“ steht für „rekursiv“ und arbeitet auch alle Unterverzeichnisse ab. Der „Punkt“ am Ende sagt der Funktion, dass sie in dem aktuellen Verzeichnis starten soll.</p>
<div data-id="402578" class="ajaxGalleryInit" style="display:none;"></div>
<p>Tatsächlich spuckt die Suche einige Ergebnisse aus. Voran steht immer auch der Dateiname und das etwaige Verzeichnis. Tablepress verfügt also über einen Filter (im Bild markiert), den wir gebrauchen können. Scheinbar gibt es einen Filter namens <code>tablepress_table_css_classes</code>.</p>
<p>Ich habe dann die Datei „class-render.php“ geöffnet und nach der betroffenen Zeile gesucht. In deren Umfeld habe ich geschaut, wie der Entwickler den Filter selbst einsetzt. Man stellt dann schnell fest, dass er ein „Array“ mit Klassennamen konstruiert und dieses übergibt. Das ist ganz wichtig. Denn damit der Filter unsere Eingabe versteht, müssen wir sie auch als Array übergeben. Gesagt, getan.</p>
<p>Der Quellcode kommt in die <code>functions.php</code> und wir können uns die Abfrage sparen, ob der Text auch den Shortcode enthält. Tatsächlich würde, wenn wir so weit sind, die Tabelle schon gerendert sein, und wir können dann nichts mehr (außer eben mit Javascript) verändern. Wir greifen mit einem <code>add_filter()</code> (vgl. <a href="https://developer.wordpress.org/reference/functions/add_filter/">WordPress-Codex</a>) zu einem früheren Zeitpunkt der Ausführung ein und fügen die Klasse wie folgt hinzu.</p>
<pre><code>add_filter( 'tablepress_table_css_classes', function($css){
  $css[] = "table";
  return $css;
});</code></pre>
<p>Der Einfachheit halber haben wir eine anonyme Funktion genutzt, die als Rückgabewert ein Array hat.</p>
<h4>Apply und Add gehören zusammen</h4>
<p>Die Entdeckungsreise haben wir nach <code>apply_filters()</code> unternommen. Denn damit wird im Plugin etwas verändert. Doch so eine Funktion hat eben das Gegenstück <code>add_filter()</code>. Damit übergebt Ihr quasi dem Filter etwas, das er berücksichtigen soll. Tatsächlich nutzt Tablepress selbst den <code>tablepress_table_css_classes</code> Filter nirgendwo selbst aktiv, aber es hat sich eben an dieser Stelle „erweiterbar“ gemacht.</p>
<h3>Klassen zu Tablepress hinzufügen</h3>
<p>Auf die oben beschriebenen Weisen könnt Ihr nun Klassen zu Tablepress hinzufügen, wahlweise mit ein bisschen Javascript, oder eben direkt mit PHP. Mit Javascript leistet der Browser die Arbeit, mit PHP der Server.</p>
<p>Solltet Ihr komplexere Änderungen vornehmen wollen, empfiehlt es sich, dies in jedem Fall mit PHP zu machen. Aber für „Kleinigkeiten“ ist Javascript auf die Schnelle immer geeignet. Vor allem könnt Ihr es auch als Übergangslösung einsetzen, bis Ihr die andere fertigstellen könnt. Ein „Hotfix“ sozusagen.</p>
<ol id="footnotes">
<li id="fn1">Langfristig wollen wir ein eigenes System von Apps im Web und auf Smartphones und Desktops sowohl für Nutzer als auch Autoren etablieren. <a href="#ffn1">↩︎</a></li>
<li id="fn2">Lustig aber wahr, denn 1998 registrierte ich meine erste Domain und schon Mitte der 90er baute ich eigene Webseiten auf Geocities. Trotzdem brauchte es 25 Jahre, ehe ich die Einfachheit erkannte, schnell Ergebnisse zu erzielen. <a href="#ffn2">↩︎</a></li>
<li id="fn3">Ich habe vergessen zu erwähnen, dass ich eine lokale WordPress-Installation nutze, um die Webseite zu entwickeln. <a href="#ffn3">↩︎</a></li>
</ol>
<p>Der Beitrag <a href="https://macnotes.de/2020/07/29/wordpress-tablepress-eine-klasse-hinzufugen-mit-javascript-oder-php/">WordPress: CSS-Klasse zu Tablepress hinzufügen (mit Javascript oder PHP)</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>Wasserstand #16: Es geht wieder weiter</title>
		<link>https://macnotes.de/2020/07/17/wasserstand-16-es-geht-wieder-weiter/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Fri, 17 Jul 2020 01:35:34 +0000</pubDate>
				<category><![CDATA[Kommentar]]></category>
		<category><![CDATA[Internet]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=401767</guid>

					<description><![CDATA[<p>Es ist rund zwei Wochen her, als ich das letzte Mal über den Status Quo bei Macnotes informierte. Dieser Wasserstand fällt etwas kürzer aus als der letzte. Dafür hat er deutlich bessere Nachrichten in petto. Und zwar geht es um die nahe Zukunft von Macnotes, also das, was schon recht bald kommt. Denn letzten Sonntag [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/07/17/wasserstand-16-es-geht-wieder-weiter/">Wasserstand #16: Es geht wieder weiter</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>Es ist rund zwei Wochen her, als ich das letzte Mal über den Status Quo bei Macnotes informierte. Dieser Wasserstand fällt etwas kürzer aus als <a href="https://macnotes.de/2020/07/01/wasserstand-15-aderlass-abmahnung-rebounce-und-durststrecke/">der letzte</a>. Dafür hat er deutlich bessere Nachrichten in petto. Und zwar geht es um die nahe Zukunft von Macnotes, also das, was schon recht bald kommt.</p>
<p>Denn letzten Sonntag hab ich das Gröbste für einen Kundenauftrag erledigt und widme mich seitdem auch einem neuen Layout/Theme für Macnotes. Natürlich mache ich damit auf den ersten Blick tolle Fortschritte. Denn man hat „schnell mal“ was zusammengeschustert. Mir kommt es aber auch aufs Detail an und es gibt genügend Fallstricke, die über Wohl und Wehe entscheiden können.</p>
<p>Ich bin jedenfalls froh, dass ich Euch aktuell zeigen kann, was ich in der kurzen Zeit seit vergangenen Sonntag auf die Beine gestellt habe.</p>
<h2>Neues Design in mehreren Phasen</h2>
<p>Entsprechend werde ich aber trotzdem die Kirche zunächst im Dorf lassen und versuchen die Funktionalität von Macnotes jetzt nachzubauen, und aber den Schnickschnack für später übrig zu lassen. Beispielsweise möchte ich mittels Javascript Inhaltsverzeichnisse implementieren, wo dies angebracht erscheint, oder aber auch eine eigene Bildergalerie und womöglich auch ein Glossar etablieren. Das muss aber noch ein wenig warten.</p>
<h3>Die neue Startseite</h3>
<p>Stand heute habe ich die neue Startseite bereits „fertig“. Es fehlen dort im Prinzip Änderungen im Detail.</p>
<div data-id="401761" class="ajaxGalleryInit" style="display:none;"></div>
<p>Die neue Startseite wird allerdings ein wenig von allem enthalten. Also aus bestimmten Kategorien die Inhalte bereitstellen. Sie erhält dafür keine Seiten-Navigation zum Blättern. Denn meines Erachtens ist sie dafür nicht gedacht.</p>
<p>Sehr wohl möchte ich aber mittelfristig auch die Usability erhöhen und habe damit bereits begonnen. Denn jeder Abschnitt der Startseite enthält eine Navigation, über die man zu den Abschnitten springen kann. Ein kleines Detail ist, dass das Pfeil-Symbol immer auch in die Richtung zeigt, in der sich der Bereich befindet (und selbstredend ist der sichtbare Bereich nicht gleichzeitig Teil der Navigation).</p>
<div data-id="401766" class="ajaxGalleryInit" style="display:none;"></div>
<p>Sieht man mal vom Bild ab, das in meiner Entwicklungsumgebung fehlt, bin ich derzeit damit ganz zufrieden.</p>
<h3>Die neue Artikelseite</h3>
<p>Die neue Artikelseite zeigt, dass man ein Design nicht einfach so aus der Taufe heben kann. Sie gefällt mir noch nicht (ganz). Abstände und Details passen irgendwie noch nicht zusammen und wirken noch unrund. Aber zumindest kann sie sich trotzdem sehen lassen.</p>
<p>In der Seitenleiste gibt es zugehörige Firmen, Events, Plattformen, Personen und Produkte, wenn denn welche ausgewählt sind. Die Event-Seiten beispielsweise enthalten ihrerseits Links zu Nachrichten über das Event. So könnt Ihr dann bei der kommenden WWDC 2021 schon alle Meldungen an einer Stelle abrufen.</p>
<div data-id="401765" class="ajaxGalleryInit" style="display:none;"></div>
<p>Am unteren Ende gibt es eine Vor- und Zurück-Navigation und außerdem „ähnliche Nachrichten“. Diese sind „hausgemacht“. Denn ich habe für WordPress und auch auf Macnotes schon vor Jahren eine zusätzliche Taxonomie eingerichtet, die jedoch unsichtbar ist. Ich frage dann Beiträge ab, die über gleiche „Keywords“ verfügen und gebe sie aber außerdem per Zufall wieder. Auf diese Weise möchte ich sowohl die Themenzugehörigkeit sicherstellen als auch die Neugier von Euch befriedigen. Denn vielleicht gibt es ja noch etwas zu lesen, das Ihr noch nicht kennt. Und also werden bei einem Seitenabruf regelmäßig neue ähnliche Beiträge angezeigt. Wie ich das technisch umgesetzt habe, darüber werde ich Euch auch „später“ (alias irgendwann und nicht heute) noch informieren, sodass Ihr das auf Euren Webseiten womöglich nachmachen könnt.</p>
<div data-id="401762" class="ajaxGalleryInit" style="display:none;"></div>
<p>Auch hier fehlen bei meiner lokalen Installation einige Bilder, aber das soll Euch nicht weiter stören, weil es, wenn das neue Design live geht, anders sein wird.</p>
<h3>Das neue Archiv</h3>
<p>Auch für das/die Archiv(e) habe ich bereits angefangen ein neues Design anzulegen. Natürlich bekommen außerdem die Archive eine Seitennavigation. Denn dort macht sie Sinn.</p>
<p>Beim Überfahren der Bilder nutze ich CSS-Effekte, die ich leider im Standbild nicht wiedergeben kann. Aber auch das ist etwas, das ich Euch „später“ noch im Detail vorstelle, damit Ihr es eventuell auf Eurer Webseite nachmachen könnt.</p>
<div data-id="401763" class="ajaxGalleryInit" style="display:none;"></div>
<p>Wenn ich allerdings „Effekte“ benutze oder Funktionen umsetze, dann möchte ich diese mit möglichst wenig Ressourcen am Browser einrichten. Umso dankbarer bin ich, dass es mittlerweile auch CSS-Effekte und -Animationen gibt. Also ich mit dem Web Ende der 1990er anfing lauteten die HTML-Befehle noch ganz anders und <a href="https://de.wikipedia.org/wiki/JavaScript">steckte Javascript noch in den Kinderschuhen</a>. Heute ist vieles wesentlich eingängiger als damals. Doch meine Devise lautet: Ich werde keine Javascript-Bibliothek installieren, nur weil es womöglich einfacher ist. Sieht man davon ab, dass WordPress von Haus aus JQuery lädt, nutze ich für meinen Alltag sogenanntes „Vanilla Javascript“, für das man keine zusätzlichen Dinge laden muss.</p>
<h2>Was noch fehlt</h2>
<p>Hier und da muss ich auf jeden Fall noch am Kontrast schrauben. Ich bin selbst rot-grün-fehlsichtig. Entsprechend sind mir manche Farbkombinationen leider ein Dorn im Auge und muss ich entsprechend nachbessern. Es ist auch nicht ausgeschlossen, dass ich im Zuge der Arbeiten die Schriftarten noch auswechsle.</p>
<p>In jedem Fall werden ich versuchen sie lokal auf dem Webserver abzulegen, damit auch in diesem Fall keine Kommunikation mit fremden Server stattfinden muss.</p>
<p>Macnotes hab ich im November 2019 gekauft, wie ich es vorgefunden habe. Entsprechend gibt es noch super viel zu tun. Aber es kommt jetzt wieder ein wenig mehr Fahrt in die ganze Geschichte, selbst wenn es „noch“ nicht danach ausschaut.</p>
<h2>Was schon da ist: Responsivität</h2>
<p>Ja und in einer Angelegenheit habe ich aber auf ein Framework gesetzt, und zwar ein CSS-Framework. Dabei wollte ich vor allem eines, das nicht zu viele Features bietet und von Haus aus eher einen kleinen „Fußabdruck“ hinterlässt. Mit <a href="https://bulma.io/">Bulma</a> denke ich, hab ich eine gute Alternative gefunden. Denn ich habe in der Vergangenheit auch mit anderen, deutlich größeren Frameworks gearbeitet, wie beispielsweise <a href="https://getbootstrap.com/">Bootstrap</a>, <a href="https://get.foundation/">Foundation</a> oder <a href="https://materializecss.com/">Materialize</a>. Ausprobieren möchte ich irgendwann auch noch <a href="https://tailwindcss.com/">Tailwind</a>. Aber wenn man Fortschritte erzielen möchte, dann muss man Entscheidungen treffen, und also fiel die Wahl auf Bulma, weil es mir nicht ganz fremd war und ich die überschaubare Größe schätze.</p>
<p>In jedem Fall habe ich auch die „Responsivität“ im Blick. Ein Thema in diesem Zusammenhang sind natürlich auch die Überschriften oder Typographie im Allgemeinen. Denn es gibt zwar Lösungen, aber die sind entweder sehr komplex oder eben begrenzt einsatzfähig. Wie ich dieses Problem gelöst habe, werde ich auch an anderer Stelle explizit breittreten. ;)</p>
<p>So in etwa sieht dann das neue Macnotes auf dem iPhone aus: Also zumindest, wenn Google Euch keine AMP-Version liefert.</p>
<div data-id="401764" class="ajaxGalleryInit" style="display:none;"></div>
<p>Mittelfristig möchten wir auch dafür eine eigenständige Lösung anbieten. Aber vermutlich macht es da mehr Sinn, gleich ein eigenes CMS zu programmieren, was durchaus auf unserem Schmierzettel als Idee vermerkt ist.</p>
<p>Falls Euch das Thema langweilt, habt Ihr hoffentlich nicht zu viel von dem Beitrag gelesen. Ansonsten sind wir auch gerne offen für Feedback schon zu diesem frühen Zeitpunkt, damit wir das neue Macnotes schon in der Entwicklungsphase optimieren können. Das ist auch der Grund, warum ich diesen Wasserstand loswerden wollte.</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/07/17/wasserstand-16-es-geht-wieder-weiter/">Wasserstand #16: Es geht wieder weiter</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>Wasserstand #12: PHP, Javascript und viel Arbeit</title>
		<link>https://macnotes.de/2020/05/07/wasserstand-12-php-javascript-und-viel-arbeit/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Thu, 07 May 2020 00:35:07 +0000</pubDate>
				<category><![CDATA[Kommentar]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Technologie]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=398655</guid>

					<description><![CDATA[<p>Es kommt immer anders als man denkt. Deshalb gibt es einen neuen Wasserstand erst heute, und gab es ihn nicht schon im April. Zwar versprach ich vollmundig, den Newsletter zu veröffentlichen, konnte mich aber nicht dran halten. Wir wollten – ich möchte mit Macnotes eigentlich jeden Tag immer weiter sein, als wir es tatsächlich sind. [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/05/07/wasserstand-12-php-javascript-und-viel-arbeit/">Wasserstand #12: PHP, Javascript und viel Arbeit</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>Es kommt immer anders als man denkt. Deshalb gibt es einen neuen Wasserstand erst heute, und gab es ihn nicht schon im April. <a href="https://macnotes.de/2020/04/19/kommentar-vorbestellen-bestellen-der-akku-ist-leer-jetzt/">Zwar versprach ich vollmundig</a>, den Newsletter zu veröffentlichen, konnte mich aber nicht dran halten.</p>
<p>Wir wollten – ich möchte mit Macnotes eigentlich jeden Tag immer weiter sein, als wir es tatsächlich sind.</p>
<h2>Tun, was man tun muss</h2>
<p>Doch es gibt eben diese finanziellen Zwänge, die es notwendig machen, dass wir unsere Ideen in dem Maße verfolgen, wie es das Portmonee zulässt. Im November 2019 investierten wir einen ganzen Batzen unseres privaten Kapitals, um die Webseite aufzukaufen.</p>
<p>Wir wollten und wollen die Dinge anders machen. Das haben wir mehrfach artikuliert. Wir verzichten auf die große Werbung, aber im Umkehrschluss ist Macnotes &#8211; Stand heute &#8211; absolut nicht wirtschaftlich. <a href="https://macnotes.de/2019/12/16/darum-sind-wir-nicht-mehr-amazon-partner/">Amazon wollte uns nicht im Affiliate-Programm</a>, darüber hinaus ist AdSense ein Schatten seiner selbst und gibt es viele Aufräumarbeiten. Unter dem Strich kommt so im Monat meist nur ein niedriger dreistelliger Betrag zusammen.</p>
<p>Das ist „noch“ egal, denn wir sind in der Lage, unser Geld „anderswo“ zu verdienen. Tatsächlich portiere ich selbst aktuell ein uraltes Joomla 1.5 auf ein WordPress und benötige dafür viel PHP, Javascript und habe sogar ein eigenes Importscript in Ruby geschrieben, nachdem ich Zugriff auf die MySQL-Datenbank des Kunden erhielt. Diese Arbeit hält Macnotes natürlich auch auf, vor allem im Tagesgeschäft. Aber diese Arbeit bringt Macnotes auch etwas. Denn manche der Dinge, die ich für meine Kunden erledige, kann ich in Zukunft auch für Macnotes verwenden.</p>
<h2>Gefährlich genug</h2>
<p>Vielleicht kennt ihr die Situation, wenn man sich intensiv mit einer Sache befasst und am Ende so viel Know-how hat, dass man eigene, kreative Ideen entwickelt. Ganz gleich, ob’s ums Kochen, Basteln oder Programmieren geht. Genau das passierte mir unter anderem während meiner Arbeit an dem Joomla-Projekt für den Kunden. Denn ich musste mich sehr viel mit Javascript abgeben und weil ich aber nicht auf ein Framework vertrauen wollte, habe ich mit purem Javascript sehr sehr viele Lösungen gesucht und die allermeisten davon auch umgesetzt. Ob es um ein Akkordeon-Menü geht, ein rekursives Formular oder Register für ein Glossar.</p>
<p>Am Ende wollte ich aus einer Laune heraus einen eigenen einfachen Textersetzungsbefehl von TextExpander für die „Wayback Machine“ <em>ausbauen</em>. Dabei herausgekommen ist ein ausgewachsenes Formular in HTML und Javascript, mit dem ich mit der API des Internetarchivs interagiere. Dazu verbinde ich das Formular, empfange das Ergebnis als JSON-Objekt und verarbeite es dann. Wenn ich dann die Daten eintrage und den Button klicke, kopiert mir die „App“ (hust) das Ergebnis in die Zwischenablage. Damit habe ich gerade bei der Arbeit mit Macnotes eine riesige Erleichterung erlebt. Denn viele der Links von früher gibt es so heute nicht mehr.</p>
<p>Und weil ich ein Spielkind bin, aber auch Herausforderungen liebe, habe ich gar nicht lang darüber nachgedacht, sondern das Formular mittels CSS-Framework in Form gebracht. Außer mir hätte es bis dahin eigentlich niemand gesehen, doch nun zeige ich Euch das Ergebnis zumindest im Screenshot.</p>
<div data-id="398654" class="ajaxGalleryInit" style="display:none;"></div>
<p>Ich möchte mittelfristig auch den Quellcode <a href="https://github.com/sajonara">auf Github veröffentlichen</a> und womöglich sogar ein WordPress-Plug-in daraus machen. Aber das sind Nebenkriegsschauplätze, die vielleicht auch nie zur Vollendung kommen. So ehrlich muss ich zu mir selbst sein. Denn ich habe jeden Tag mehr Ideen als der Tag Stunden.</p>
<h2>Informationen sammeln und aufbereiten</h2>
<p>Ich arbeite daran, Macnotes noch in diesem Jahr ein neues Layout zu verpassen. Allerdings ist der langfristige Plan vor allen Dingen, die Webseite mit Informationen auszurüsten. Teilweise tue ich das schon jetzt, selbst wenn es momentan noch „sch…“ ausschaut. Beispielsweise habe ich auf Seiten zu Veranstaltungen wie der <a href="https://macnotes.de/events/wwdc-2008/">WWDC 2008</a> die passenden Nachrichtenmeldungen dazu untergebracht. Das sieht dann wie folgt aus:</p>
<div data-id="398653" class="ajaxGalleryInit" style="display:none;"></div>
<h2>Taxonomien und Post Types</h2>
<p>Gerne hätte ich auch schon früher Infos zu besonderen Themen eingebunden, beispielsweise zu Schlagwörtern wie „Coronavirus“. Da ich aber die alten „Schlagwörter“ offline nehme und eine und mehrere neue Taxonomien einrichte, möchte ich das Pferd nicht von hinten aufzäumen. Denn erst einmal braucht die Seite ein neues Layout, bevor ich anfange die Inhalte passend aufzubereiten.</p>
<p>Bei dem eingangs angesprochenen Kundenprojekt beispielsweise habe ich, ähnlich wie ich nur „reines“ Javascript einsetzen wollte, auch möglichst versucht, auf WordPress-Plug-ins zu verzichten. So habe ich am Ende selbst die Eingabeoberfläche für einen Custom Post Type mit Metaboxen erstellt und dann mittels Javascript dem Nutzer die Möglichkeit bereitgestellt, neue Felder „on the fly“ hinzuzufügen. Dabei musste ich einmal mehr feststellen, dass WordPress doch leider so ein Umstandskasten ist. Ich verstehe nicht, warum das System Metadaten als „serialisierte Objekte“ speichert, anstatt von echten JSON-Objekten oder alternativ Arrays. Aber <a href="https://wordpress.stackexchange.com/questions/183475/why-wordpress-choose-data-serialization-over-json-encode">irgendwas werden sich die Entwickler schon dabei gedacht haben</a>.</p>
<p>Diese ganzen Erkenntnisse möchte ich auf Macnotes irgendwann auch mit Euch teilen, wahrscheinlich in Form von Tutorials, wie Ihr gewisse Dinge nachbauen könnt. Denn es gibt eine Menge Dinge, die ich gelernt habe, nicht nur was PHP oder Javascript angeht, sondern auch Ruby, SEO, CSS und so fort.</p>
<h2>Von Stöckchen auf Retro-Steinchen</h2>
<p>Ein Thema, das Ihr auf Macnotes „irgendwann“ auch vermehrt erleben werdet, ist das Thema Retro. Denn ich habe auch da vieles ausprobiert und zum Beispiel einen Basic-Interpreter für den Mac wie <a href="https://www.qb64.org/portal/">QB64</a> ausprobiert, einige eigene Programme <a href="https://twitter.com/Macnotes/status/1255944468269879297">dafür geschrieben</a>.</p>
<p>Nur Retro heißt bei mir nicht nur Theorie, sondern auch Praxis. Die elektronische Bucht, <a href="https://www.youtube.com/channel/UCPiFOcskeiOj0jHz3YCWDBQ">wie Wolfgang Rudolph sie oft nennt</a>, bescherte mir zuletzt beispielsweise einen Atari 1040 STF samt Monochrom-Monitor, aber auch einen C64C samt 5,25 Zoll Disketten-Laufwerk.</p>
<div data-id="398660" class="ajaxGalleryInit" style="display:none;"></div>
<p>Ich denke, dass einige von Euch diese Leidenschaft für die Nostalgie teilen und letztlich kann man aus der Beschäftigung mit der Vergangenheit auch für die Zukunft lernen. Dass ich übrigens keinen Amiga ersteigert habe, liegt nur zum Teil an mir. Ich hatte es vor, aber die Preise gingen regelmäßig durch die Decke. Aber ich liege auf der Lauer und hätte nichts dagegen, wenn ich dann auch irgendwann einen Amiga in meine Sammlung aufnehmen kann. Denn alte DOS-PCs besitze ich schon zu Genüge.</p>
<div data-id="398659" class="ajaxGalleryInit" style="display:none;"></div>
<p>Das Schöne ist auch immer wieder, wie man das Alte mit dem Neuen verbinden kann. Denn es gibt ja da diese Arduinos und Raspberrys, mit denen man alte Retro-Konsolen beleben kann, oder eben die Heimautomatisierung steuern. Auch darüber möchte ich schreiben.</p>
<h2>Weiter, immer weiter</h2>
<p>Nun habe ich Euch wieder ein wenig den Mund wässrig gemacht, kann aber leider noch nichts liefern. Ich muss erst das erwähnte Projekt beenden, bevor ich wieder mehr Zeit in Macnotes investieren kann. Dass ich mir trotzdem die Nächte für das Projekt um die Ohren schlage zeigt mir selbst, dass ich ein klein wenig verrückt bin, aber eben auch voll hinter dem Projekt stehe. Denn <a href="https://macnotes.de/2020/03/31/wasserstand-11-der-newsletter-mit-corona/">gegenüber dem letzten Wasserstand</a> habe ich vorgestern einen Haken unter die Beiträge aus Juli 2008 gemacht.</p>
<p>Wenn zwischendrin außerdem noch <a href="https://macnotes.de/2020/05/06/test-magic-keyboard-furs-ipad-ist-gut-aber-teuer/">Tests wie der zum Magic Keyboard fürs iPad Pro</a> abfallen, und Apple weiter fleißig neue Produkte veröffentlicht, dann bin ich guter Dinge, dass wir uns gemeinsam auf <a href="https://macnotes.de/2020/05/05/wwdc-2020-am-22-juni-mit-swift-challenge/">die erste digitale WWDC 2020 im Juni</a> freuen können. Es bleibt spannend!</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/05/07/wasserstand-12-php-javascript-und-viel-arbeit/">Wasserstand #12: PHP, Javascript und viel Arbeit</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
		<item>
		<title>Wasserstand #7: Thin Content, Dubletten und Ideen für die Zukunft von Macnotes</title>
		<link>https://macnotes.de/2020/02/23/wasserstand-7-thin-content-dubletten-und-ideen-fuer-die-zukunft-von-macnotes/</link>
		
		<dc:creator><![CDATA[Alexander Trust]]></dc:creator>
		<pubDate>Sun, 23 Feb 2020 15:53:31 +0000</pubDate>
				<category><![CDATA[Kommentar]]></category>
		<category><![CDATA[Internet]]></category>
		<guid isPermaLink="false">https://macnotes.de/?p=396590</guid>

					<description><![CDATA[<p>Man muss die Feste feiern, wie sie fallen. Entsprechend folgt auf den letzten Wasserstand #6 von vor wenigen Tagen bereits die nächste Ausgabe dieser Newsletter-artigen Beiträge. Diese Episode befasst sich natürlich immer noch mit dem Jahr 2008 und sowohl Thin Content als auch Dubletten, aber auch der Zukunft von Macnotes. Im März 2008 überarbeiteten die [&#8230;]</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/02/23/wasserstand-7-thin-content-dubletten-und-ideen-fuer-die-zukunft-von-macnotes/">Wasserstand #7: Thin Content, Dubletten und Ideen für die Zukunft von Macnotes</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class='lead'>Man muss die Feste feiern, wie sie fallen. Entsprechend folgt auf den letzten <a href="https://macnotes.de/2020/02/21/wasserstand-6-sichtbarkeit-sichtbarkeit-und-unsichtbarkeit/">Wasserstand #6</a> von vor wenigen Tagen bereits die nächste Ausgabe dieser Newsletter-artigen Beiträge. Diese Episode befasst sich natürlich immer noch mit dem Jahr 2008 und sowohl Thin Content als auch Dubletten, aber auch der Zukunft von Macnotes.</p>
<p>Im März 2008 überarbeiteten die damaligen Besitzer von Macnotes die Webseite. Sie führten eine Rubrik ein, die Kurznachrichten bedient. Die tauchten im Layout gar nicht direkt in der Hauptsortierung auf. Vielmehr gab es damals eine Seitenleiste, in der die Kurznachrichten auftauchten.</p>
<p>Darüber, dass ich diesen Thin Content einfach lösche und auf die <a href="https://macnotes.de/qa/">Qualitätssicherungsseite</a> weiterleite, schrieb ich schon im letzten Wasserstand. Doch der war mehr ein Gedächtnisprotokoll und ich hatte gerade keinen Screenshot zur Hand. Da ich nun im Mai 2008 auf weitere &#8222;dünne&#8220; Inhalte treffe, hab ich mir gedacht, dokumentiere ich doch einfach, wie dünn diese Inhalte tatsächlich sind.</p>
<div data-id="396591" class="ajaxGalleryInit" style="display:none;"></div>
<h2>Thin Content wirklich sehr dünn</h2>
<p>Im Screenshot könnt Ihr gleich drei Sätze sehen. Der Link hinter dem Wort <a href="https://macnotes.de/firma/apple/">Apple</a> geschieht automatisch, mit Hilfe eines Plug-ins, das Stefan Keller und ich vor Jahren entwickelten. Manchmal, wenn Inhalte ein bisschen zu kurz geraten sind, gehe ich bei meiner Aufarbeitung auch hin, und besuche die alten Quellen und schreibe neue Informationen in die Beiträge. Ja, das kostet Zeit. Doch in Fällen wie diesem im Beispiel mache ich mir die Mühe nicht. Mir liegt keine Quelle vor und die Suche danach würde am Ende mein primäres Ziel viel zu weit verzögern.</p>
<p>Letztlich möchte ich alle über 35.000 Beiträge bei Macnotes auf eine gemeinsame Datenbasis packen, bevor wir mit der Webseite anfangen &#8222;ganz andere&#8220; Dinge anzustellen. Bis dahin müsst Ihr Euch leider ein wenig gedulden.</p>
<h2>Dubletten seit 2008 an der Tagesordnung</h2>
<p>Auch über Dubletten schrieb ich im letzten Wasserstand. Im März und April 2008 gab es &#8222;ein paar&#8220;. Doch im Mai gab es deutlich mehr. Denn im Mai gab es auch vielmehr Inhalte auf iPhonenotes, einer Webseite von Andre S., die zu einem späteren Zeitpunkt in Macnotes aufging.</p>
<p>Manche der Inhalte von iPhonenotes behalte ich, andere führe ich mit Inhalten von Macnotes zusammen. Ich hoffe natürlich auch, dass unter dem Strich viel wertiger Content übrig bleibt. Letztlich kümmerte sich damals niemand darum und umso wichtiger ist es, dass man endlich Ordnung schafft. Wenn Ihr regelmäßig den Wasserstand lest, kommen Euch diese Zeilen bald schon wie ein Mantra vor.</p>
<p>Deshalb möchte ich die Neugierigen von Euch nochmal darauf hinweisen, ab und an einen Blick auf die Seiten-Navigation am unteren Rand der Startseite zu werfen. Dort sind zumindest alle &#8222;Artikel&#8220; (ohne Seiten, Firmen, Events, Produkte und weitere Landingpages) enthalten. Die Zahl schwankt seit November 2019, <a href="https://macnotes.de/2019/11/01/nahkastchen-19-da-bin-ich-wieder/">als wir Macnotes übernahmen</a>. Und im nächsten Wasserstand muss ich vielleicht schon schreiben, dass wir nur noch &#8222;beinahe&#8220; 35.000 Texte auf Macnotes anbieten. Denn wir produzieren zwar auch neuen Content, aber bei der Überarbeitung der alten Beiträge fällt eben auch viel weg. Entsprechend gibt es Wochen, in denen wir mehr alte Artikel löschen als wir neue schreiben.</p>
<h2>Ideen für die Zukunft</h2>
<p>Wir haben uns außerdem für ein CSS-Framework entschieden, das wir beim Re-Design der Webseite einsetzen wollen. Es lautet auf den Namen <a href="https://bulma.io/">Bulma</a>. Ihr müsst wissen, dass wir mittelfristig neben dem Design auch neue Funktionen zur Webseite hinzufügen möchten. Wenn dabei beispielsweise Plug-ins für WordPress oder Scripte anfallen sollten, dann möchten wir den Quellcode natürlich mit Euch teilen, damit auch Ihr etwas davon habt.</p>
<p>Es gab damals mal einen Event-Kalender. Den fanden auch wir ganz toll. Mal schauen, ob das Ding irgendwann ein Revival erlebt. Im Forum gab es außerdem die Möglichkeit für Nutzer, RSS-Feeds anderer Webseiten in eine individualisierte Nachrichten-Übersicht zu packen. Ebenfalls interessant. Ein Problem bei diesen Community-Funktionen ist halt der Datenschutz. Wenn wir Daten erheben und zwar mit eigenen Programmen, müssen wir diese auch so gestalten, dass sie der DSGVO genügen. Das beschleunigt die Entwicklung jedenfalls nicht.</p>
<p>Wir wollen mittelfristig aber auch die Verbindung der Webseite zu Social Networks ausweiten, wir planen eigene Lösungen fürs Affiliate-Marketing und wollen Datenbanken mit Tipps, Tests und mehr aufbauen. Wenn Ihr außerdem Ideen für die Zukunft von Macnotes habt, lasst es uns wissen.</p>
<p>Bei alldem dürft Ihr nicht vergessen, dass momentan quasi nur anderthalb Personen an Macnotes arbeiten.</p>
<p>Für diejenigen, die trotz Yulia Karneval feiern: Viel Spaß dabei. Den anderen, zu denen auch wir gehören, wünschen wir mindestens genauso jecke Tage. ;)</p>
<p>Der Beitrag <a href="https://macnotes.de/2020/02/23/wasserstand-7-thin-content-dubletten-und-ideen-fuer-die-zukunft-von-macnotes/">Wasserstand #7: Thin Content, Dubletten und Ideen für die Zukunft von Macnotes</a> erschien zuerst auf <a href="https://macnotes.de">Macnotes.de</a>.</p>
]]></content:encoded>
					
		
		
		
	</item>
	</channel>
</rss>
