avatar

Über Thomas Keil

Geschäftsführender Gesellschafter der Weblizards GbR und PHP-Entwickler

Codevervollständigung in PhpStorm für unbekannte Typen

Wer im MVC Modell programmiert verteilt seinen Code über mehrere Stellen, der in seiner Logik eigentlich zusammengehört.

So ist es oft so, dass im Controller Variablen deklariert und mit Objekten belegt werden, um diese dann an die View zu übergeben:

public function detailAction() {
  $productid = intval($this->_getParam("productid"));
  $product = Object_Product::getById($productid);
  $this->view->product = $product;
}

Und in der View zB:

print $this->product->getName();

Wer mit professionellen IDEs arbeitet, wird die Codevervollständigung zu schätzen gelernt haben.
PhPStorm zum Beispiel kennt die Klassendefinition von Object_Product, welche im Controller $product zugewiesen wird, und kann bei Bedarf entsprechende Vorschläge für zur Verfügung stehende Methonden machen.

In der View ist das anders – hier wird die Variable während der Laufzeit durch $this->view->product an $this->product “durchgeschleust” und steht daher im Code der View deklarationslos da – die IDE hat hierbei keinerlei Informationen, um welchen Typ es sich handelt und kann keine Vorschläge machen.

Hier kommt nun PhpDoc in’s Spiel, mit dem man bekanntlich Klassen- und Methodendefinitionen dokumentieren kann, um automatisch eine Dokumentation der API erzeugen zu können.
Was offenbar viele nicht wissen: es lassen sich auch die Deklaration von Einzelvariablen direkt im Code mit PhpDoc dokumentieren – hiermit kann man den meisten IDEs Informationen über die Variable zukommen lassen:

/**
 * @var Object_Product $product
 */
$product = $this->product;

Wer die Syntax nicht kennt: PhpDoc wird eingeleitet durch einen Kommentar mit zwei Sternen: /**.
Ein Schlüsselwort, eingeleitet mit “@”, beschreibt dann einen eigenen Typ der Dokumentation, hier @var den Typ der Variable. Das Tag var erwartet als nächstes Wort den Typ der Variable, hier Object_Product, gefolgt vom Namen der Variable.

Mit diesen Angaben kennt dann auch die IDE den Typ der Variable und versorgt den Programmierer mit (mehr oder weniger ;-) ) sinnvollen Vorschlägen:

Dies funktioniert natürlich auch für die meisten anderen IDEs wie zum Beispiel Netbeans.

Liste von verfügbaren Sprachen in Pimcore auslesen und verarbeiten

Für ein Webformular brauchten wir wir eine Zend Framework Selectbox mit den validen Sprachen des Frontends.

Pimcore bietet auch hier wieder komfortable Möglichkeiten, die aktuell im Backend eingestellten Sprachen zu verarbeiten.

Das ganze Problem wird hierdurch wieder mal zum komfortablen Fünfzeiler wenn man weiß wo man hinfassen muss.

Pimcore liefert mit der statischen Methode Pimcore_Tool::getValidLanguages() einen Array an Kürzeln der validen Sprachen, also zB array(“de”, “en”).

Dies kann man sich nun noch vom Zend Framework übersetzen lassen, ebenfalls mit einer statischen Methode: Zend_Locale::getTranslation($kuerzel, “language”, $zielsprache).
Sinnvollerweise lässt man sich das Kürzel in die Sprache übersetzen, die es repräsentiert – ein auswählender User kann seine Sprache damit sicher identifizieren.

Der Select-Viewhelper erwartet nun noch die Werte im Format array($value => $label).

Zusammengefasst sieht das daher dann so aus:

$pimcore_languages = Pimcore_Tool::getValidLanguages();
$languages = array();
foreach ($pimcore_languages as $lang) {
  $languages[$lang] = Zend_Locale::getTranslation($lang, 'language', $lang);
}
$language = $this->createElement("select", "language");
$language->setLabel("Sprache")
         ->setMultioptions($languages);

Gastronomieeinrichtung Feil – Unternehmensseite online gegangen

Seit heute ist die Unternehmenswebseite des Gastronomieinneneinrichters Feil GmbH online gegangen.

Realisiert in Zusammenarbeit mit dem Büro für visuelle Kommunikation, Druck und Digitale Verarbeitung – “draw and style . Christine Müller” haben wir dieses Projekt mit dem Content Management Framework pimcore umgesetzt.

Highlights sind die durchgängige Mehrsprachigkeit in Deutsch, Englisch und Russisch sowie eine konsequente Orientierung des unterliegenden Quellcodes für eine optimale Verarbeitung durch die Suchmaschinen. HTML5 sowie klare Strukturen der Semantik waren hierbei absolute Pflicht.

Pimcore – Keys generieren für Objekte

Wer in Pimcore Objekte oder Assets mit einem eigenen Import-Skript einliest, muss auch gültige Keys für die Objekte generieren.
Diese müssen einem bestimmten Schema folgen oder alles fliegt früher oder später aus der Kurve.

Pimcore stellt intern Methoden bereit um gültige Keys zu erzeugen, zum Beispiel die Methode Pimcore_File::getValidFilename()

Diese hat für unseren Sprachraum nur den Schönheitsfehler, dass Umlaute entfernt werden.
Es liegt daher nahe, die ganze Geschichte etwas aufzubohren. Der Einfachheit halber mache ich das mit einer simplen Funktion:

function makeKey($key) {
  $key = str_replace(array("ä","ü","ö","ß"), array("ae", "ue", "oe", "ss"), utf8_encode($key));
  return Pimcore_File::getValidFilename($key);
}

Dies kann man nun ganz einfach nutzen – hier ein Beispiel aus einem unserer Importer:

  $objekt = new Object_Objekt();
  $objekt->setParentId($parent_id);
  $objekt->setCreationDate(new Zend_Date($row["ModDate"], Zend_Date::TIMESTAMP));
  $objekt->setUserOwner(1);
  $objekt->setUserModification(1);
  $objekt->setPublished(true);

  $key = makeKey("Mein Objekt");
  $objekt->setKey($key); // der Identifier wie er im Baum erscheint

Eiswürfel, äh, Brocken

Bei den heissen Tagen wollten wir uns Eiswürfel machen für unsere Getränke im Eisfach des Bürokühlschranks.

Das Vorhaben scheiterte an dem massiven und fast 100% raumfüllenden Eisbrocken, der das Gefrierfach belegte.

Der taut nun im Spülbecken ab:

Das wäre genug Eis für den Rest des Sommers gewesen :)
Aber wenigstens passt jetzt die Eiswürfelform wieder hinein.

Pimcore in Version 1.4.7

Pimcore wurde in Version 1.4.7 veröffentlicht.
Es wurden hauptsächlich Bugs gefixt und ein paar kleine Verbesserungen vorgenommen:

Bug

  • [PIMCORE-1585] – Video preview creation in backend fails
  • [PIMCORE-1593] – JS Minifier causes external scripts not to be included
  • [PIMCORE-1596] – after Document::render() not the correct layout script is set
  • [PIMCORE-1598] – Zend_Form_Decorator_Captcha_ReCaptcha leads to JS-Error in Internet Explorer
  • [PIMCORE-1602] – Renderlet throws error: Class: Document_Folder => call to undefined method getTemplate
  • [PIMCORE-1604] – Installation of plugin can throw exception on forced reload
  • [PIMCORE-1606] – On Asset Upload Version-User is not updated
  • [PIMCORE-1611] – Wrong Debug Message in Pimcore_Model_Cache::load()
  • [PIMCORE-1618] – Static routing for Document Folder
  • [PIMCORE-1619] – Unpublished documents are shown by Pimcore_View_Helper_PimcoreNavigation_Controller
  • [PIMCORE-1624] – Alt + s problem on polish keyboard, so that people from poland can’t write their “ś” char (just like: PIMCORE-524)

Improvement

  • [PIMCORE-530] – Drop target do not accept anything in Safari/Webkit
  • [PIMCORE-1506] – Park Objects without checking for mandatory fields
  • [PIMCORE-1549] – New Redis Cache Backend Class (related to PIMCORE-1534)
  • [PIMCORE-1578] – possibility to cleanup (empty) translations (admin/website)
  • [PIMCORE-1589] – Zend Framework 1.11.12 Upgrade
  • [PIMCORE-1601] – Too many “are you sure you want to leave this page” messages when leaving
  • [PIMCORE-1603] – Document_Tag_Video only allows “autoplay” Option of YouTube API
  • [PIMCORE-1612] – Update the less compiler to the latest build (0.3.5)
  • [PIMCORE-1625] – Looping through an areablock twice causes an infinite loop
  • [PIMCORE-1629] – Google API’s: Possibility to define a deviant browser key

New Feature

  • [PIMCORE-1580] – Add feature to download Assets from an URL
  • [PIMCORE-1613] – Link to Frontend Page on Right Click on the Navigation Tree
  • [PIMCORE-1626] – Open document from URL (in “File” menu)

Task

  • [PIMCORE-1594] – Safari is not recognized as a supported browser

Pimcore: Dropdown-Länderliste leicht befüllt

Wieder mal ein Griff in die Trickkiste, aus der Kategorie “nützliche Dreizeiler”.

Problemstellung war ein Kontaktformular mit einem Dropdown als Liste aller Länder.

Man kann diese Liste nun natürlich “zu Fuss” definieren, oder sich gleich komfortabel von Pimcore bzw dem Zend Framework befüllen lassen – dort liegen die Daten ohnehin schon vor:

    $countries = new Object_Class_Data_Country();
    $options = array();
    foreach ($countries->getOptions() as $country) $options[$country["value"]] = $country["key"];

Im Array $options liegen die Länder dann in der Form vor, wie man sie direkt in ein Zend Form Element vom Typ Select stecken kann:

    $land = $this->createElement("select", "land");
    $land->setLabel("Land")->setMultioptions($options);

Wer ein spezielleres Ergebnis braucht, kann die Erstellung auch selbst vornehmen und das abändern bzw kopieren, was in Object_Class_Data_Country gemacht wird:

        $countries = Zend_Locale::getTranslationList('territory');
        asort($countries);
        $options = array();

        foreach ($countries as $short => $translation) {
            if (strlen($short) == 2) {
                $options[] = array(
                    "key" => $translation,
                    "value" => $short
                );
            }
        }

        return $options;

Pimcore multihref in Dokument programmatisch befüllen

Für ein Kundenprojekt mussten Daten aus einem alten Auftritt übernommen werden. Problemstellung waren dabei Dokumente mit Multihref, die per Import-Script mit Objekten (Immobilien) gefüllt werden mussten.

Folgender Code erfüllt diese Aufgabe:

$objekt = Object_Objekt::getByPath("/objekte/".$objekt_key);
$document = Document::getById($document_id);
$multihref = $document->getElement("objekte");
$data = $multihref->getDataForResource();
$data[] = array("id" => $objekt->getId(), "path" => $objekt->getFullPath(), "type" => "object", "subtype" => "objekt");
$multihref->setDataFromEditmode($data);
$multihref->getResource()->save();
$objekt_document->update();

Die ganze Sache hat nur einen Schönheitsfehler: die Dependencies werden nicht mit aktualisiert, erst bei händischem Speichern des Dokuments werden diese aktualisiert.
Ich hab zwar versucht, diese ebenfalls per Script zu ergänzen, dies hatte aber keine Wirkung:

// Das funktioniert nicht...
$objekt_document->clearDependedCache();
$document_dependencies = $objekt_document->getDependencies();
$document_dependencies->addRequirement($objekt->getId(), "object");
$document_dependencies->save();

Für Hinweise, was hier falsch läuft, wäre ich daher dankbar :-)

EDIT:

Zita Kemeny hat in den Kommentaren eine Lösung zur Verfügung gestellt.
Die sieht, angepasst auf vorhergehendes Problem, folgendermaßen aus:

$dependency = new Dependency();
$dependency->setSourceId($document_id);
$dependency->setSourceType(“document”);
$dependency->addRequirement($objekt->getId(), “object”);
$dependency->save();

Danke, Zita!

Piwik Plugin nun offiziell gelistet bei piwik.org

Unser Piwik-Plugin für Pimcore ist nun auf der offiziellen Homepage von Piwik als verfügbares Plugin für ein CMS gelistet.

Wir freuen uns, dass wir zu diesem nützlichen Projekt beitragen konnten :-)

Pimcore View Helper für Conditional Comments um Metatags

View Helper stellen eine sehr praktische Möglichkeit des Zend Frameworks dar, sich den Umgang mit HTML erheblich zu erleichtern und viele Ding auf die Orte zu konzentrieren, an denen sie tatsächlich passieren.
Tags in den zu definieren, nur dort wo man sie auch tatsächlich braucht, ist zB mit dem headMeta View Helper ein Kinderspiel:

$this->view->headMeta()->setName("keywords", "blah, fasel");

Im Layout lässt sich das nun ausgeben:

<head>
<?php echo $this->headMeta().PHP_EOL ?>
// ...

Einziges Problem: die Meta-Tags lassen sich, in der Version des Zendframeworks die gegenwärtig mit Pimcore ausgeliefert wird, nicht mit Conditional Comments versehen.
Wir implementieren hier gerade ein gekauftes Seitentemplate, wo genau so ein Conditional Comment für Metatags gefragt ist:

<!--[if lte IE 9 ]><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><![endif]-->

In der aktuellen Version des Zend Frameworks ist das gefixt, und bis die in Pimcore Einzug hält, muss ein eigener ViewHelper her.

Schritt 1: Ein Verzeichnis für die View Helper anlegen. Sinnvollerweise /website/views/helpers

Schritt 2: Dem Zend Framework den Pfad zu seinen eigenen View Helpern mitteilen, zum Beispiel in /website/lib/Website/Controller/Action:

$this->view->addHelperPath(PIMCORE_WEBSITE_PATH . '/views/helpers/', 'Website_Helper');

Schritt 3: Den Viewhelper ConditionalHeadMeta.php anlegen:

class Website_Helper_ConditionalHeadMeta extends Zend_View_Helper_HeadMeta {

  public function conditionalHeadMeta($content = null, $keyValue = null, $keyType = 'name', $modifiers = array(), $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND) {
    return parent::headMeta($content, $keyValue, $keyType, $modifiers, $placement);
  }

  public function itemToString(stdClass $item) {
    $html = parent::itemToString($item);
    if (isset($item->modifiers['conditional']) && !empty($item->modifiers['conditional']) && is_string($item->modifiers['conditional'])) {
        $html = '';
    }
    return $html;
  }

}

Nun kann man mit dem neuen ViewHelper das gewünschte Resultat erzielen:

$this->view->conditionalHeadMeta()->appendName("X-UA-Compatible", "IE=edge,chrome=1", array("conditional" => "lte IE 9"));