Archiv

Archiv für die Kategorie ‘Webentwicklung’

Having fun with lorempixum

24. Mai 2011

Nach loremipsum kann man mit lorempixum.com auch hübsche Testbilder in beliebiger Größe für Entwürfe anzeigen lassen, so wie in diesem Demo für Blider und Überschriften von mir. Bei jedem Reload der Seite gibt es frische Bilder.

WordPress mit Zend Framework Beispiel Plugin

27. April 2011

Nach einem aktuellen Auftrag, bei dem ich verschiedene WordPress Plugins angepasst habe, habe ich ein Beispiel-Plugin geschrieben, bei dem das ZendFramework integriert ist. Es kann als Grundgerüst für weitere WordPress-Plugins benutzt werden.

Interessantes zum Thema gibt es auch auf folgenden Seiten:

Zunächst wird ein Ordner namens gina-sample unter /wp-content/plugins erstellt (es ist egal, aber: GINA steht für Grandgeorg Internet Applications oder gerne auch für GINA is not annoying). In diesem Ordner wird die gina-sample.php Datei erstellt. Diese Datei ist unsere zentrale Plugin-Datei die alle Funktionsaufrufe für die WordPress-Action- und Filter-Hooks enthält. Sie sollte, damit die Übersichtlichkeit gewahrt bleibt, die einzige Datei in diesem Ordner bleiben. Alle anderen Dateien werden in Unterordner gespeichert. Ich lege i.d.R. folgende Unterordner dazu an:

  • css
  • img
  • js
  • languages
  • php
    • lib
      • Zend
    • views
      • scripts

Zunächst enthält die gina-sample.php-Datei Angaben zum Plugin (die von WordPress ausgewertet werden) und zum Copyright als PHP-Kommentar:

/*
Plugin Name: GINA Sample
Plugin URI: http://intelligibel.de/wordpress/plugin/gina-sample
Description: GINA Sample Plugin is ment for testing plugin development.
Version: 1.0
Author: Viktor Grandgeorg
Author URI: http://intelligibel.de
License: GPL2

Copyright 2011  Viktor Grandgeorg  (email : i...@yourdomain.de)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2, as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

Als Nächstes wird eine PHP-Klasse mit statischen Methoden definiert. Es wird eine Klasse verwendet und nicht lediglich Funktionen, um Namenskollisionen von Funktionsnamen zu vermeiden und dennoch kurze und prägnante Benennungen zu ermöglichen. Dabei wird eine Methode namens dispatch() verwendet. Sie soll später alle gewünschten Aufrufe von WordPress “Actions” und “Filters” enthalten:

if (!class_exists("GinaSample")) {

    class GinaSample
    {
        public static function dispatch()
        {
            // actions
            // admin actions
            // filters
        }
    }
    GinaSample::dispatch();
}

In der dispatch-Methode wird darüber hinaus auch die ZendFramework-Integration vollzogen, indem ZF in den include-Pfad aufgenommen und eine Instanz von Zend_Loader_Autoloader erzeugt wird. Dabei müssen selbstverständlich die Dateien von ZendFramework unter /wp-content/plugins/gina-sample/lib/Zend liegen. Falls möglich, sollte dort eine symbolische Verknüpfung auf die Dateien erzeugt werden.

Außerdem werden die Get-, Post- und Cookie-Variablen zunächst von überflüssigen Schrägstrichen befreit und anschließend einer lokalen Eigenschaft der Klasse zugeordnet. Dies ist notwendig, da WordPress und/oder andere Plugins während des Verarbeitungsprozesses den Strings der Superglobalen Schrägstriche hinzufügen (ganz gleich, ob magic_quotes aktiviert ist oder nicht). ZF hingegen setzt voraus, dass die Strings ohne zusätzliche Schrägstriche vorhanden sind.

Darüber hinaus werden, falls nötig, die Übersetzungsdateien für das Plugin geladen.
Damit sieht die Klasse wie folgt aus:


    define('GINASAMPLE_PLUGIN_PATH', realpath(__DIR__));

    class GinaSample
    {

        public static $adminOptionsName = "GinaSample";
        public static $ginaSampleGPC = array();

        public static function dispatch()
        {
            set_include_path(implode(PATH_SEPARATOR, array(get_include_path(),
                realpath(GINASAMPLE_PLUGIN_PATH. '/php/lib'))));
            require_once 'Zend/Loader/Autoloader.php';
            $autoloader = Zend_Loader_Autoloader::getInstance();

            // Zend expects magic qoutes to be turned off.
            if (get_magic_quotes_gpc()) {
                $_POST      = array_map('stripslashes_deep', $_POST);
                $_GET       = array_map('stripslashes_deep', $_GET);
                $_COOKIE    = array_map('stripslashes_deep', $_COOKIE);
                $_REQUEST   = array_map('stripslashes_deep', $_REQUEST);
            }

            // As WP (or Plugins) add slashes to globals anyway, we use our own.
            self::$ginaSampleGPC = array(
                '_POST'     => $_POST,
                '_GET'      => $_GET,
                '_COOKIE'   => $_COOKIE
            );

            if(!load_plugin_textdomain('gina-sample',
                                       '/wp-content/languages/')) {
                load_plugin_textdomain('gina-sample', false,
                    dirname(plugin_basename(__FILE__)) . '/languages');
            }

            //actions
            //admin actions
            //filters
        }
    GinaSample::dispatch();
}

Damit ist das Grundgerüst des Plugins fertig. Anhand von zwei Methoden sollen nun konkrete Funktionen als Beispiel erzeugt werden. Die erste Funktion namens helloWorld() soll die Zeichenkette “Hallo Welt!” in verschiedenen Sprachen am Anfang von jedem Post ausgeben. Die Zweite Funktion namens addContent() soll beliebigen Text zu jedem Post bzw. zu jeder Seite hinzufügen. Im Administrationsbereich von WordPress soll es durch die Methode printAdminPage() möglich sein beide Funktionen ein- und auszuschalten und es soll natürlich möglich sein den Text, der an die Seiten angefügt wird, für die zweite Funktion anzugeben. Für das Formular im Administrationsbereich soll Zend_Form mit Zend_View verwendet werden. Die Einstellungen sollen in der WordPress Datenbank als Konfigurationsoption gespeichert werden. Deshalb wird auch eine Methode namens getAdminOptions() benötigt, die die Werte aus der Datenbank wieder ausliest und Standardwerte setzt, falls keine Werte in der Datenbank vorhanden sind. Das ist unter anderem dann der Fall, wenn das Plugin das erste Mal aktiviert wird. Deshalb soll diese Methode auch bei der Aktivierung ausgeführt werden.

        public static function helloWorld()
        {
            $options = self::getAdminOptions();
            if (true == $options['runHelloWord']) {
                echo '<h3>' . __('Hello World!', 'gina-sample') . '</h3>';
            }
        }

        public static function addContent($content = '')
        {
            $options = self::getAdminOptions();
            if (true == $options['runAddContent']) {
                if (!empty($options['contentAddContent'])) {
                    $content .= '<p>' . $options['contentAddContent'] . '</p>';
                } else {
                    $content .= '<p>'
                             . __('You hit GinaSample::addContent();',
                                  'gina-sample')
                             . '</p>';
                }
            }
            return $content;
        }

        public static function getAdminOptions()
        {
            $defaultOptions = array(
                'runHelloWord'      => true,
                'runAddContent'     => true,
                'contentAddContent' => ''
            );
            $options = get_option(self::$adminOptionsName, false);
            if (false === $options) {
                $options = $defaultOptions;
                update_option(self::$adminOptionsName, $options);
            }
            return $options;
        }

        public static function printAdminPage()
        {
            $_POST = self::$ginaSampleGPC{'_POST'};
            $_GET = self::$ginaSampleGPC{'_GET'};
            $_COOKIE = self::$ginaSampleGPC{'_COOKIE'};

            $options = self::getAdminOptions();

            $view = new Zend_View();
            $view->setBasePath(realpath(GINASAMPLE_PLUGIN_PATH . '/php/views/'));

            $form = new Zend_Form();
            $form->setAction($_SERVER['REQUEST_URI'])
                 ->setMethod('post')
                 ->setAttrib('id', 'ginaSampleAdminForm')
                 ->addElement('radio', 'ginaSampleOptionRunHelloWord', array(
                    'label' => __('Show Hello World in Posts?', 'gina-sample'),
                    'multioptions' => array('true' => __('Yes', 'gina-sample'),
                                            'false' => __('No', 'gina-sample')),
                    'separator' => '&#160;'))
                 ->addElement('radio', 'ginaSampleOptionRunAddContent', array(
                    'label' => __('Allow Content Added to the End of a Post?',
                                  'gina-sample'),
                    'multioptions' => array('true' => __('Yes', 'gina-sample'),
                                            'false' => __('No', 'gina-sample')),
                    'separator' => '&#160;'))
                 ->addElement('textarea', 'ginaSampleContentAddContent', array(
                    'label' => __('Content to Add to the End of a Post',
                                  'gina-sample'),
                    'cols' => 35,
                    'rows' => 5))
                 ->addElement('submit', 'updateGinaSamplePluginSettings', array(
                    'label' => __('Update Settings', 'gina-sample')))
                 ;

            if ($form->isValid($_POST)
                && isset($_POST['updateGinaSamplePluginSettings'])) {

                $formValues = $form->getValues();
                if (isset($formValues['ginaSampleOptionRunHelloWord'])) {
                    if ('true' == $formValues['ginaSampleOptionRunHelloWord']) {
                        $options['runHelloWord'] = true;
                    } else {
                        $options['runHelloWord'] = false;
                    }
                }
                if (isset($formValues['ginaSampleOptionRunAddContent'])) {
                    if ('true' == $formValues['ginaSampleOptionRunAddContent']) {
                        $options['runAddContent'] = true;
                    } else {
                        $options['runAddContent'] = false;
                    }
                }
                if (isset($_POST['ginaSampleContentAddContent'])) {
                    $options['contentAddContent'] = apply_filters(
                        'content_save_pre',
                        $formValues['ginaSampleContentAddContent']);
                }
                update_option(self::$adminOptionsName, $options);
                $view->update = true;
            }

            $form->populate(array(
                'ginaSampleOptionRunHelloWord' =>
                    (true === $options['runHelloWord'])? 'true' : 'false',
                'ginaSampleOptionRunAddContent' =>
                    (true === $options['runAddContent'])? 'true' : 'false',
                'ginaSampleContentAddContent' => $options['contentAddContent']
            ));
            $view->form = $form->render($view);
            echo $view->render('admin.phtml');

        }

Für das Zend-View-Objekt in der Methode printAdminPage() muss noch die Datei admin.phtml im Unterordner views\scripts\ (s.o.) mit folgendem Inhalt definiert werden:

<div class="wrap">
<h2>Gina Sample Plugin</h2>
<?php if (true === $this->update): ?>
<div class="updated"><p><strong><?php _e('Settings Updated.', 'gina-sample'); ?></strong></p></div>
<?php endif; ?>
<?php echo $this->form ?>
</div>

Schließlich wird noch eine Methode in der GinaSample Klasse definiert, die die Administrationsseite zum AdminPanel hinzufügt so, dass sie im Menü Einstellungen zu sehen ist:

        public function addAdminPanel()
        {
            if (function_exists('add_options_page')) {
                add_options_page('Gina Sample Plugin', 'Gina Sample Plugin',
                                 'manage_options', __FILE__,
                                 array('GinaSample', 'printAdminPage'));
            }
        }

Schlußendlich müssen dann in der dispatch-Methode nur noch die jeweiligen Aktionen und Filter aufgerufen werden:


            //actions
            add_action('the_post', array('GinaSample', 'helloWorld'));

            //admin actions
            add_action('admin_menu', array('GinaSample', 'addAdminPanel'), 0);
            add_action('activate_gina-sample/gina-sample.php',
                       array('GinaSample', 'getAdminOptions'));
            //filters
            add_filter('the_content', array('GinaSample', 'addContent'));

Um zu entscheiden, an welcher Stelle das Plugin eingeklinkt werden soll, ist die WP-Dokumentation zu Aktionen und zu Filtern zu konsultieren.

Das ganze Beispiel-Plugin kann hier heruntergeladen werden.

Die ZIP-Datei ist inklusive deutscher Sprachdateien, enthält aber nicht das ZendFramework.

Zend Framework mit Eclipse PDT (Galileo) und SVN

22. Februar 2010

Wer ZendStudio nicht benötigt oder sich nicht leisten kann oder will, kann mit der hier beschriebenen Konfiguration Eclipse mit Subversion für seine PHP Zend Framework Projekte unter Windows verwenden.

Zunächst gehen wir davon aus, dass Apache und PHP bereits installiert sind und dass irgendwo eine Version von Zend Framework gespeichert ist (z.B.: c:\server\library\ZendFramework-1.9.0). Darüber hinaus werden wir die Möglichkeit benötigen unter Windows symbolische Verknüpfungen anzulegen, dazu kann man einfach (falls nicht vorhanden) die junction.exe bei Microsoft herunterladen.

In diesem Beispiel gehe ich von folgender Verzeichnisstruktur aus (die natürlich auch ganz anders sein kann). Was die einzelnen Verzeichnisse beinhalten wird im Laufe der Konfiguration klar:

C:\\

  • Programme
    • eclipse
    • SlikSvn
      • bin
  • server
    • Apache
    • eclipse
      • workspaces
    • library
      • PEAR
      • ZendFramework
      • etc.
    • MySQL
    • php
    • svn
      • repository
    • vhost
    • xdebug

Als Nächstes installieren wir eclipse-php-galileo-SR1-win32.

Dann benötigen wir Subversion für Windows. Derzeit kann man von tigris.org nichts herunterladen, da das Projekt Apache übergeben wird. Wir installieren deshalb Subversion von sliksvn.com – ist ein super Paket.

Jetzt müssen wir den Subversion-Server unter Windows einrichten. Bei codinghorror.com gibt es dazu eine wunderbare Anleitung. Hier die wesentlichen Schritte zusammengefasst:

  • cmd:
    svnadmin create "c:\server\svn\repository"
  • conf/svnserve.conf des erstellten Repository:
    anon-access = none
    auth-access = write
    password-db = passwd
  • conf/passwd des erstellten Repository:
    dein-name= dein-passwort
  • Subversion als Dienst registrieren, Server starten, SVN-Editor setzen, SVN-(Test)-Verzeichnis erzeugen – cmd:
    sc create svnserver binpath= "c:\Programme\SlikSvn\bin\svnserve.exe --service -r c:\server\svn\repository" displayname= "Subversion" depend= Tcpip start= auto
    net start svnserver
    set SVN_EDITOR=c:\Programme\Notepad++\notepad++.exe
    svn mkdir svn://localhost/test

Damit wir loslegen können, müssen wir jetzt nur noch Subversion unter Eclipse konfigurieren. Dazu gibt es wiederum eine wunderbare Anleitung bei javathreads.de. Ich verzichte auf eine Zusammenfassung, hier nur der benötigte Link für die Installation des Connectors:

http://community.polarion.com/projects/subversive/download/eclipse/2.0/galileo-site/

Die eigentliche Konfiguration hier als ein kleiner Screencast:
(Die Audiospur hängt ganz schön hinterher und ich bin mit der Maus zuweilen ganz schön am Abwandern, aber worum es geht wird, denke ich, recht klar)

P.S. Unter Umständen ist es sinnvoll am Ende die Datei .buildpath und den Ordner .settings in die ignore-Liste von SVN aufzunehmen – am Besten einfach mit TortoiseSVN o.Ä.