Archiv der Kategorie: Tutorial

Ein Child-Theme anlegen, schnell und einfach

Jeder, der in WordPress mehr möchte, als nur fremd-produzierte Themes zu administrieren, kommt früher oder später dazu, ein Child Theme zu bearbeiten bzw. herzustellen.

Was ist ein Child Theme?

Ein Child Theme ist zunächst einmal ein Abkömmling (eben das “Child”) eines anderen Themes. Ist man mit dem bisher genutztes Theme für WordPress nicht zufrieden, ist ein Child Theme der beste Ansatzpunkt, um individuelle Lösungen einzubinden.

Das Child Theme übernimmt alle Eigenschaften des Eltern Themes – solange sie nicht im Child Theme expliziert überschrieben werden (was ja Sinn der ganzen Sache ist).

Das (Child)-Theme darf man dann ohne Gefahr manipulieren, wobei das Eltern Theme niemals angefasst wird. Dies hat mehrere Vorteile:

  1. Falls eine Änderung (vielleicht unwiederbringlich) misslingen, kann man das Child Theme einfach verwerfen und auf das Eltern Theme zurückgehen – oder einfach ein neues Child Theme anlegen.
  2. Sollte das Eltern Theme durch ein Update aufgefrischt werden, so gehen die eigenen Änderungsmaßnahmen im Child Theme nicht verloren, denn dieses Theme bleibt von Updates unberührt.
  3. Wenn man sich zwischen zwei (oder mehr) Änderungen nicht entscheiden kann, so legt man einfach weitere Child Themes an, um schnell zwischen die Änderungen hin- und herzuspringen.

Wichtige Regel daher: NIEMALS im Eltern Theme Änderungen vornehmen. NIEMALS NIEMALS NIEMALS

Was kann man im Child Theme machen?

Das child Theme bietet zwei große Gebiete, auf denen man sich nach Belieben austoben darf.

Design in Child Theme

HTML, CSS und Mediendateien

Im Child Theme darf (sollte) man den HTML Code anpassen. Aber nicht nur. Auch CSS Styles dürfen geändert werden. Ebenso liegt hier die beste Möglichkeit vor, Bilder, z.B Background-Images, oder andere Mediendateien permanent einzubinden. So erspart man sich den Umweg über den Medien-Upload von WordPress.

PHP Funktionalität

Ebenso lassen sich auch Funktionalitäten nachrüsten, die man sonst in einem extra anzulegenden Plugin speichern müsste. PHP-Code-lastige Teile des Themes kann man wunderbar in einer Datei namens functions.php auslagern, die man im Hauptverzeichnis des Child Themes anlegt.

Child Theme angelegen – Schritt für Schritt

1. Verzeichnis anlegen

  • per FTP mit dem Server verbinden
  •  im Verzeichnis wp-content/themes/ ein Verzeichnis anlegen. Dieses Verzeichnis bekannt den Namen des um die Endung -child erweiterten Namens des Eltern Themes. Heißt das Verzeichnis des Eltern Themes twentytwenty, so landet das Child Theme im Verzeichnis twentytwenty-child.
Wordpress Child Theme

2. Style Datei anlegen

Die wichtigsten Informationen über das Child Theme werden (vielleicht ungewohnterweise) in der anzulegenden Datei style.css eingefügt. Der Kopf der Datei sollte folgendermaßen aussehen:

/*
 Theme Name:   Twenty Twenty Child
 Description:  Ein Child Theme
 Author:       Clark Kent
 Author URI:   https://domain.de
 Template:     twentytwenty
 Version:      1.0
 Text Domain:  twenty-twenty-child
*/

Nicht alle diese Angaben sind verpflichtend. Lediglich zwei davon sind absolut notwendig:

Theme Name – Muss eindeutig sein.

Template – Der Verzeichnisname des Eltern Themes (hier also twentytwenty)

3. functions.php anlegen

In der Datei functions.php wird PHP Code eingebunden, der gezielt nur für dieses Child Theme zur Anwendung kommt. Zunächst einmal begnügen wir uns mit den befehlen zum Einbinden des Style Sheets der Eltern. Das Style Sheet des Child Themes wird automatisch korrekt eingebunden

<?php
/**
* Style sheets des Eltern Themes einbinden
*/
function my_child_theme_styles() {
	wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}
add_action( 'wp_enqueue_scripts', 'my_child_theme_styles' );
?>

Jetzt sollte unser Verzeichnis so aussehen.

Wordpress Child Theme

4. Screenshot anlegen

Ich lege gerne eine Screenshot Datei an, um bei mehreren Themes nicht die Übersicht zu verlieren. Am schnellsten geht es, wenn man die Datei screenshot.png aus dem Verzeichnis des Eltern Themes anpasst.

Wordpress Child Theme

Das Verzeichnis sieht jetzt so aus:

Wordpress Child Theme

Jetzt können wir unsere noch “nacktes” Child Theme erstmalig in WordPress auswählen.

Wordpress Child Theme

Wenn wir jetzt den Source Code unserer Seite im Browser anzeigen lassen (in der Regel mit dem Tastaturbefehl STRG+U) sollte es genau so aussehen:

Der Source Code unserer Website unter Verwendung eines Child Theme

Wie man sehen kann, werden hier die Style Sheet des Parent Themes und des Child Themes eingebunden.

Das war es für jetzt. Wir werden im Weiteren noch lernen, wie man im Child Theme eigene CSS Styles einbindet bzw. die des Eltern Themes anpasst und/oder überschreibt.

Ein Papierkorb für Samba

Der Papierkorb für Windows ist eine unleugbar nützliche Sache. Leider arbeitet er nicht mit Netzlaufwerken zusammen, die man zum Beispiel per Samba eingebunden hat.

Aber man kann für Samba selbst einen Papierkorb installieren und versehentlich gelöschte Dateien daraus retten.

Zunächst bearbeiten wir die Konfigurationsdatei von Samba.

sudo nano /etc/samba/smb.conf

Ans Ende des betreffenden Absatzes, der mit [NAME] startet, fügen wir etwas hinzu.

vfs object = recycle
recycle:repository = .recyclebin
recycle:keeptree = Yes
recycle:touch = Yes
recycle:versions = Yes
recycle:maxsixe = 0
recycle:exclude = *.tmp,*.temp,*.TMP,*.TEMP,*.log
recycle:excludedir = /recycle,/tmp,/temp,/TMP,/TEMP

Insgesamt sieht es (ungefähr) so aus:

[www]
path = /var/www/
public = yes
writable = yes
comment = smb share
printable = no
guest ok = yes
create mode = 0644
directory mode = 0755
force group = www-data
force user = www-data

vfs object = recycle
recycle:repository = .recyclebin
recycle:keeptree = Yes
recycle:touch = Yes
recycle:versions = Yes
recycle:maxsixe = 0
recycle:exclude = *.tmp,*.temp,*.TMP,*.TEMP,*.log
recycle:excludedir = /recycle,/tmp,/temp,/TMP,/TEMP

Die Einträge dürften sich größenteils von selbst erklären. Aber hier noch einmal eine kleine Erläuterung.

recycle:repository = .recyclebin

Das ist der Ordner, der uns als Papierkorb nutzen wird. Er wird beim ersten Löschvorgang mit den richtigen Rechten angelegt. Bei diesem Beispiel: /var/www/.recyclebin

recycle:keeptree = Yes

Die Ordnerstruktur wird in den Papierkorb übernommen. Kann nicht schaden, weil es die Suche einfacher gestaltet.

recycle:touch = Yes

Setzt den letzten Zugriffszeitpunkt auf das Löschdatum. Das ist wichtig, da beim automatischen Leeren eines zu vollen Papierkorbes zu alte, versehentlich gelöschte Dateien sofort entsorgt werden. Wer den Papierkorb nicht automatisch leert, der kann die Option auch weglassen.

recycle:versions = Yes

Für eine Versionierung namensgleicher Dateien.

recycle:maxsixe = 0

Ab welcher Dateigröße soll der Papierkorb nicht gelten und stattdessen sofort gelöscht werden. 0 steht für keine Beschränkung.

recycle:exclude = *.tmp,*.temp,*.TMP,*.TEMP,*.log

Welche Dateien sollen vom Papierkorb ausgeschlossen werden und stattdessen sofort gelöscht werden? Ich empfehle neben den üblichen Verdächtigen wie “tmp” und “log” auch Binärdateien, die immer Resultat von anderen Dateien sind, und somit aus der Quelle selbst rekonstruiert werden können. JPEG-Dateien kann man z.B. aus den Photoshop-Dateien wieder herstellen.

recycle:excludedir = /recycle,/tmp,/temp,/TMP,/TEMP

Welche Ordner sollen vom Papierkorb ausgeschlossen werden? Hier gelten anlog meine Anmerkungen zu oben. Mehr Einstellungsmöglichkeiten werden hier: https://www.samba.org/… erläutert.

Zum Schluss starten wir den Samba-Server neu

sudo /etc/init.d/samba restart

Von nun an sollten alle Dateien und Ordner im geteilten Verzeichnis vor versehentlichen Löschen geschützt sind. Sie finden Sie nun, samt Verzeichnisstruktur, unter /var/www/.recyclebin

Test

Bitte unbedingt testen, denn exotische Rechtevergabe kann auch dazu führen, dass der Papierkorb schlicht nicht funktioniert.

VORSICHT: Damit keine Missverständnisse aufkommen, es werden natürlich nur die Dateien in den Papierkorb befördert, die über Samba gelöscht werden, also bspw. von einem unvorsichtigen Windows-Nutzer. Dateien, die direkt über die Shell oder über Skripte gelöscht werden, bleiben davon unberührt und landen weiterhin im Unix-Nirvana.

Automatisches Leeren des Papierkorbes

Das erledigt natürlich cron für uns.

sudo crontab -e

Ans Ende setzen wir folgenden Eintrag für root:

01 00 * * * find /var/www/.recyclebin  -mindepth 1 -atime +7 -print -exec rm -rf {} \;

Dann werden täglich um 00:01 alle Dateien und Ordner im Papierkorb gelöscht, die älter als sieben Tag sind. Das ” -mindepth 1″ verhindert, dass der Papierkorb selbst gelöscht wird, wenn er älter als sieben Tage ist.

Danke

Mein Dank geht an http://blog.is-a-geek.org/… für die Anregungen.

Minibian – Raspberry PI – Installieren

Ziel: ein minimales Linux für einen kompletten (Web)server auf Basis eines Raspberry Pi

Quelle: https://minibianpi.wordpress.com/features/

Software: Win32DiskImagerPuTTY

Hardware: Raspberry Pi 2B (oder 3), SD Mikro Karte 32 GB (oder größer)

Netzwerk: (W)LAN-Router mit LAN-Anschluss

Image auf SD-Karte installieren

  • Download https://sourceforge.net/projects/minibian/
  • Das Image (Endung: img) entzippen und mit Win32DiskImager auf SD-Karte schreiben. Vorsicht, nicht aus Versehen einen falschen Laufwerksbuchstaben wählen.
  • SD-Karte auswerfen, in Raspberry Pi packen
  • Pi per LAN mit Router verbinden
  • Pi mit Strom versorgen und einige Minuten warten, bis der Name im Netzwerk bekannt ist

Mit Maschine verbinden

  • PuTTY starten und mit “minibian” verbinden.
    • Login: root
    • Passwort: raspberry
passwd # Passwort ändern

Festplatte voll ausreizen

fdisk /dev/mmcblk0 # dann folgende Kommandos
  • p – Partitionen zeigen (i. d. R. zwei) – Startwert der zweiten, der Hauptpartition notieren (hier 125056)
  • d – zweite Partition löschen
  • n – neue Partition anlegen, Partition type: Primary, Partition number: 2, Startwert: 125056 (der notierte, NICHT der default Wert), Endwert: Default für volle Größe
  • p – überprüfen der Eingaben
  • w – schreiben der Partitionen (Fehlermeldung ignorieren)
reboot
resize2fs /dev/mmcblk0p2
df -h # sollte jetzt (nahezu) die volle Größe unter /dev/root/ belegt haben

Vorbereitungen

apt-get install sudo
adduser BENUTZER # besser nicht mit root arbeiten
usermod -aG sudo BENUTZER # packen wir ihn zur sudo-Gruppe
su - BENUTZER # das Minus-Zeichen, damit auch wirklich ein kompletter Wechsel stattfindet
sudo apt-get install nano # bloß kein vi

Bash-Tuning

sudo nano ~/.bashrc # folgendes ans Ende eintragen:

alias +=’pushd .’
alias ..=’cd ..’
alias …=’cd ../..’
alias beep=’echo -en “\007″‘
alias dir=’ls -l’
alias gzcat=’gunzip -c’
alias l=’ls -alF’
alias la=’ls -la’
alias ll=’ls -la’
alias ls=’/bin/ls $LS_OPTIONS’
alias ls-l=’ls -l’
alias md=’mkdir -p’
alias o=’less’
alias rd=’rmdir’
alias rehash=’hash -r’
alias rm=’rm -i’
alias unzip=’tar xfvz’
alias which=’type -p’
alias zip=’tar cfvz’

logout # wieder ausloggen und einloggen, damit das Bash-Tuning anschlägt
su - BENUTZER

Betriebssystem und Komponenten auf den neuesten Stand bringen

sudo apt-get -y update
sudo apt-get -y dist-upgrade # kann dauern
sudo apt-get -y autoremove
sudo apt-get -y autoclean
sudo apt-get install cpufrequtils
cpufreq-info # zeigt Informationen zur CPU an

Firmware updaten

sudo apt-get install rpi-update # nur für Raspberry
sudo rpi-update # nur für Raspberry, neue Firmware
sudo reboot #  neustart, kann etwas länger dauern, bis Rechner wieder gefunden wird

Benchmarks

Diese Befehle benötigt man natürlich nur, wenn man die aktuelle Rechenleistung mit anderen Systemen vergleichen möchte.

sudo apt-get install sysbench
sysbench --test=cpu --num-threads=4 run # CPU Test
sysbench --test=memory --memory-block-size=500MB --memory-total-size=10GB run # Speichertest
sysbench --test=fileio --file-total-size=20G prepare # Lese/Schreibtest benötigt ein File
sysbench --test=fileio --file-total-size=4G prepare #  viermal soviel wie RAM, kann dauern
sysbench --test=fileio --file-total-size=4G --file-test-mode=rndrw --init-rng=on --max-time=300 --max-requests=0 run # Kb/sec-Wert wichtig
sysbench --test=fileio --file-total-size=4G cleanup # und wieder entfernen

Sicherheitsupdates automatisieren

sudo apt-get -y update && sudo apt-get -y install cron-apt # kann dauern
sudo nano /etc/cron-apt/action.d/5-secupdates # neue Datei mit Inhalt:

upgrade -y -o APT::Get::Show-Upgraded=true

dann

sudo mkdir /etc/apt/sources.d
sudo nano /etc/apt/sources.d/security.sources.list # neue Datei mit Inhalt:

deb https://security.debian.org/ wheezy/updates main contrib non-free
deb-src https://security.debian.org/ wheezy/updates main contrib non-free

und

sudo nano /etc/cron-apt/config.d/5-secupdates # neue datei mit Inhalt:

OPTIONS=”-o quiet=1 -o Dir::Etc::SourceList=/etc/apt/sources.d/security.sources.list -o Dir::Etc::SourceParts=\”/dev/null\””

abschließend

sudo nano /etc/cron.d/cron-apt # zeiten anpassen, wenn gewünscht
sudo cron-apt -s # test, kann dauern
sudo cat /var/log/cron-apt/log # prüfen

LAMP

sudo groupadd www-data # eventuell schon vorhanden
sudo usermod -a -G www-data www-data
sudo apt-get install apache2 -y
sudo apt-get install php5 -y
sudo apt-get install mysql-server -y # passwörter für MySQL müssen erstellt werden
sudo a2enmod rewrite # mod_rewrite fuer URL-Manipulation
sudo service apache2 restart
sudo apt-get install php5-mysql phpmyadmin -y # dauert, verlangt MySQL-Passwort (s.o.), für apache2 und lighttpd einrichten

Webmin

sudo apt-get update
cd ~
wget http://prdownloads.sourceforge.net/webadmin/webmin_1.831_all.deb
sudo apt-get -y install perl libnet-ssleay-perl openssl libauthen-pam-perl libpam-runtime libio-pty-perl apt-show-versions python
sudo dpkg --install webmin_1.831_all.deb # dauert lang
rm webmin*l.deb -f
sudo reboot

Test im Browser:

http://minibian/

http://minibian/phpmyadmin (Benutzer: root, Passwort: siehe oben)

https://minibian:10000/

Eine simple API für WordPress, Teil 4

Wir wissen jetzt, wie wir mit Hilfe unserer kleinen API einen Artikel anlegen und wie wir ihn mit einem Bild versorgen. Nun fügen wir einige Metadaten hinzu. Dazu benötigen wird die Funktion “add_post_meta“. Diese verlangt folgende Parameter:

  • post_id – Die eindeutige Artikel-ID aus Teil 2
  • meta_key – Der Name des Metadaten-Feldes
  • meta_value – Der Wert des Metadaten-Feldes

Wir packen also wieder einen Befehlsaufruf für unseren Server zusammen:

$postdata_array=array(
	'function' => 'add_post_meta', 
	'post_id' => $parent_post_id,
	'meta_key' => 'Geschmack',
	'meta_value' => 'sauer'
	);

Und natürlich müssen wir auch unseren Server wieder ein wenig ergänzen.

if ($postdata_array['function']=='add_post_meta') {
	print add_post_meta($postdata_array['post_id'], $postdata_array['meta_key'], $postdata_array['meta_value']);
}

Diese 3 Zeilen erweitern unseren Server um die Fähigkeit, mit Hilfe der Funktion “add_post_meta” Artikel mit beliebigen Metadaten zu versorgen.

Und so sieht dann das neue benutzerdefinierte Feld aus.

Zusammenfassung

Server

<?php
define('WP_USE_THEMES', false);
header('Content-Type: text/html; charset=utf-8');
if (count($_GET)>0) $postdata_array=unserialize(array_shift($_GET));
if (count($_POST)>0) $postdata_array=unserialize(array_shift($_POST));
require('../wp-load.php');

if ($postdata_array['function']=='wp_insert_post') {
	print wp_insert_post($postdata_array['wp_post_array']);
}

if ($postdata_array['function']=='wp_insert_attachment') {
	$filetype = wp_check_filetype( basename( $postdata_array['file'] ), null );
	$wp_upload_dir = wp_upload_dir();
	$attachment = array(
		'guid'           => $wp_upload_dir['url'] . '/' . basename( $postdata_array['file']), 
		'post_mime_type' => $filetype['type'],
		'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $postdata_array['file'] ) ),
		'post_content'   => '',
		'post_status'    => 'inherit'
	);
	$attach_id = wp_insert_attachment( $attachment, $postdata_array['file'], $postdata_array['parent_post_id'] );
	require_once( ABSPATH . 'wp-admin/includes/image.php' );
	$attach_data = wp_generate_attachment_metadata( $attach_id, $postdata_array['file'] );
	wp_update_attachment_metadata( $attach_id, $attach_data );
	set_post_thumbnail( $postdata_array['parent_post_id'], $attach_id );	
}

if ($postdata_array['function']=='add_post_meta') {
	print add_post_meta($postdata_array['post_id'], $postdata_array['meta_key'], $postdata_array['meta_value']);
}

exit();
?>

Client

<?php
function call_server($postdata_array) {
	$username='mueller';
	$password='geheim';
	$serverurl='http://domain.tld/maschine/';

	$postdata = http_build_query(
		array(
			'postdata_string' => serialize($postdata_array)
		)
	);

	$auth = base64_encode($username.':'.$password);
	$header = array("Authorization: Basic $auth",
		'Content-type: application/x-www-form-urlencoded'
		);

	$opts = array('http' =>
		array(
			'method'  => 'POST',
			'header'  => $header,
			'content' => $postdata,
			'timeout' => 5000,  //5 Sekunden
		)
	);

	$context = stream_context_create($opts);
	return file_get_contents($serverurl, false, $context);
}


$postdata_array=array(
	'function' => 'wp_insert_post', 
	'wp_post_array' => array(
		'post_content' => '<p>Das ist ein <b>Test äöüß</b><br>Und noch eine Zeile</p>',
		'post_title' => 'Meine erste Überschrift',
		'post_status' => 'publish',
		'post_category' => null
		)
	);
$parent_post_id = call_server($postdata_array);

# FTP Upload des Bildes
$ftp_server='domain.tld';
$ftp_user='john';
$ftp_password='secret007';
$remote_folder='/var/www/domain.tld/wp-content/uploads/maschine/';
$local_folder='/var/upload/bilder/';
$file_name='bild.jpg';

$conn_id = ftp_connect($ftp_server);
ftp_login($conn_id, $ftp_user, $ftp_password);
ftp_put($conn_id, $remote_folder.$file_name, $local_folder.$file_name, FTP_BINARY);
ftp_close($conn_id);

$postdata_array=array(
	'function' => 'wp_insert_attachment', 
	'file' => $remote_folder.$file_name,
	'parent_post_id' => $parent_post_id
	);

print call_server($postdata_array);

# Metadaten hinzufügen
$postdata_array=array(
	'function' => 'add_post_meta', 
	'post_id' => $parent_post_id,
	'meta_key' => 'Geschmack',
	'meta_value' => 'sauer'
	);
	
call_server($postdata_array);

exit();
?>

 

Eine simple API für WordPress, Teil 3

Kommen wir nun zum wichtigen Thema: Wie füge ich dem Artikel ein Bild bei?

Auch das wird in vielen Beiträgen im Internet gerne angerissen, aber mal ein paar schnelle, praktikable Lösungen werden selten präsentiert. Dabei ist es nicht so schwer, wenn man weiß, was zu tun ist.

Der Ablauf

Im Grunde müssen folgende Schritte abgearbeitet werden:

  1. Wir erzeugen einen Artikel und merken uns die ID (siehe Teil 2)
  2. Wir laden ein Bild per FTP auf den WordPress-Server
  3. Wir verbinden Artikel und Bild mit Hilfe der Funktionen: wp_generate_attachment_metadatawp_insert_attachment und set_post_thumbnail

Damit das funktioniert, müssen wir unseren Server gleich zweimal bemühen: Beim Erzeugen des Artikels und beim Verbinden des Bildes mit ersterem.

Der Upload per FTP

Keine Angst, das ist per PHP einfacher, als man denkt.

Zunächst benötigen wir auf dem WordPress-Blog einen Zielordner. Den kann man per Konsole oder FTP anlegen:

md /var/www/domain.tld/wp-content/uploads/maschine/

Auf diesen Server werden die Bilder (oder was immer man später mit den Artikeln verknüpfen möchte: ZIP-File, E-Book, PDF etc.) zwischengespeichert. Man sollte darauf achten, dass die Dateinamen dabei immer einzigartig sind, denn sonst werden sie gnadenlos überschrieben. Erreichen kann man das z.B. durch eine Ergänzung mit einer Time-id und einer laufenden Nummer.

Wir erweitern den Client um einige Zeilen:

$ftp_server='domain.tld';
$ftp_user='john';
$ftp_password='secret007';
$remote_folder='/var/www/domain.tld/wp-content/uploads/maschine/';
$local_folder='/var/upload/bilder/';
$file_name='bild.jpg';

$conn_id = ftp_connect($ftp_server);
ftp_login($conn_id, $ftp_user, $ftp_password);
ftp_put($conn_id, $remote_folder.$file_name, $local_folder.$file_name, FTP_BINARY);
ftp_close($conn_id);

Damit wird die Datei “bild.jpg” vom lokalen Verzeichnis “/var/upload/bilder/” auf das entfernte Verzeichnis “/var/www/domain.tld/wp-content/uploads/maschine/” des Servers “domain.tld” kopiert. Wenn Sie nicht wissen, wie das entfernte Verzeichnis lautet, fragen Sie ihren Provider.

Bevor wir nun an den Client gehen, packen wir dessen Kernaufgabe in eine Funktion, damit wir sie mehrfach benützen können.

function call_server($postdata_array) {
	$username='mueller';
	$password='geheim';
	$serverurl='http://domain.tld/maschine/';

	$postdata = http_build_query(
		array(
			'postdata_string' => serialize($postdata_array)
		)
	);

	$auth = base64_encode($username.':'.$password);
	$header = array("Authorization: Basic $auth",
		'Content-type: application/x-www-form-urlencoded'
		);

	$opts = array('http' =>
		array(
			'method'  => 'POST',
			'header'  => $header,
			'content' => $postdata,
			'timeout' => 5000,  //5 Sekunden
		)
	);

	$context = stream_context_create($opts);
	return file_get_contents($serverurl, false, $context);
}

Diese Funktion sendet ein Array an unseren Server und gibt dessen Antwort wieder zurück.

Die Aufgaben des Servers werden jetzt erweitert. Er kann nicht nur Artikel anlegen, sondern auch Bilder verarbeiten. Das geschieht durch folgende Zeilen:

$filetype = wp_check_filetype( basename( $postdata_array['file'] ), null );
$wp_upload_dir = wp_upload_dir();
$attachment = array(
	'guid'           => $wp_upload_dir['url'] . '/' . basename( $postdata_array['file']), 
	'post_mime_type' => $filetype['type'],
	'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $postdata_array['file'] ) ),
	'post_content'   => '',
	'post_status'    => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $postdata_array['file'], $postdata_array['parent_post_id'] );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$attach_data = wp_generate_attachment_metadata( $attach_id, $postdata_array['file'] );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $postdata_array['parent_post_id'], $attach_id );

Zeile 1 ermittelt den Mime-Type der Datei (hier: “image/jpeg”), das Array mit den Meta-Daten (Titel, eindeutiger Bezeichner etc.) wird automatisch gefüllt. Natürlich können Sie den Titel des Bildes auch aus den eigenen Daten erzeugen.

Zeile 10 fügt dann das eben hochgeladene Bild der Mediendatenbank des Blogs hinzu. Von nun an finden Sie das Bild dort, aber es ist noch nicht mit einem Artikel verbunden. Das erledigen wir gleich.

Zeile 12 versorgt das Bild in der Mediendatenbank mit den soeben festgelegten Metadaten und legt die einzelnen Vorschaubilder in den verschiedenen Größen an, die in den Medien-Einstellungen von WordPress festgelegt sind.

Zeile 14 macht die Magie: Das Bild wird mit dem Artikel verbunden.

Zusammengefasst

Der Server

<?php
define('WP_USE_THEMES', false);
header('Content-Type: text/html; charset=utf-8');
if (count($_GET)>0) $postdata_array=unserialize(array_shift($_GET));
if (count($_POST)>0) $postdata_array=unserialize(array_shift($_POST));
require('../wp-load.php');

if ($postdata_array['function']=='wp_insert_post') {
	print wp_insert_post($postdata_array['wp_post_array']);
}

if ($postdata_array['function']=='wp_insert_attachment') {
	$filetype = wp_check_filetype( basename( $postdata_array['file'] ), null );
	$wp_upload_dir = wp_upload_dir();
	$attachment = array(
		'guid'           => $wp_upload_dir['url'] . '/' . basename( $postdata_array['file']), 
		'post_mime_type' => $filetype['type'],
		'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $postdata_array['file'] ) ),
		'post_content'   => '',
		'post_status'    => 'inherit'
	);
	$attach_id = wp_insert_attachment( $attachment, $postdata_array['file'], $postdata_array['parent_post_id'] );
	require_once( ABSPATH . 'wp-admin/includes/image.php' );
	$attach_data = wp_generate_attachment_metadata( $attach_id, $postdata_array['file'] );
	wp_update_attachment_metadata( $attach_id, $attach_data );
	set_post_thumbnail( $postdata_array['parent_post_id'], $attach_id );	
}


exit();
?>

Der Client

<?php
function call_server($postdata_array) {
	$username='mueller';
	$password='geheim';
	$serverurl='http://domain.tld/maschine/';

	$postdata = http_build_query(
		array(
			'postdata_string' => serialize($postdata_array)
		)
	);

	$auth = base64_encode($username.':'.$password);
	$header = array("Authorization: Basic $auth",
		'Content-type: application/x-www-form-urlencoded'
		);

	$opts = array('http' =>
		array(
			'method'  => 'POST',
			'header'  => $header,
			'content' => $postdata,
			'timeout' => 5000,  //5 Sekunden
		)
	);

	$context = stream_context_create($opts);
	return file_get_contents($serverurl, false, $context);
}


$postdata_array=array(
	'function' => 'wp_insert_post', 
	'wp_post_array' => array(
		'post_content' => '<p>Das ist ein <b>Test äöüß</b><br>Und noch eine Zeile</p>',
		'post_title' => 'Meine erste Überschrift',
		'post_status' => 'publish',
		'post_category' => null
		)
	);
$parent_post_id = call_server($postdata_array);

# FTP Upload des Bildes
$ftp_server='domain.tld';
$ftp_user='john';
$ftp_password='secret007';
$remote_folder='/var/www/domain.tld/wp-content/uploads/maschine/';
$local_folder='/var/upload/bilder/';
$file_name='bild.jpg';

$conn_id = ftp_connect($ftp_server);
ftp_login($conn_id, $ftp_user, $ftp_password);
ftp_put($conn_id, $remote_folder.$file_name, $local_folder.$file_name, FTP_BINARY);
ftp_close($conn_id);

$postdata_array=array(
	'function' => 'wp_insert_attachment', 
	'file' => $remote_folder.$file_name,
	'parent_post_id' => $parent_post_id
	);

print call_server($postdata_array);

exit();
?>

Das war ja nicht so schwer, wenn man weiß, wie es geht – aber das gilt wohl für alles im Leben. Im nächsten Schritt lernen wir, unseren Artikel nachträglich mit Daten anzureichern.