Oro CRM Tutorial "Hello World" + Oro BAP Platform

OroBAP ist eine neue Basis-Plattform für die Entwicklung von Business-Anwendungen. Die Entwickler von Oro implentieren auf dieser Basis derzeit OroCRM, ein neues Customer Relationship Management System. Derzeit sind die Informationen, die man dazu im Netz finden kann, recht spärlich. Aus diesem Grund leisten wir einen kleinen Beitrag zum Knowledge-Sharing und teilen unsere Erkenntnisse mit allen Interessierten.

Ziel des Tutorials ist die Erstellung eines eigenen Tabs im Hauptmenu und die Anzeige einer kleinen Hello-World Seite. Der Zugriff auf das Menu soll natürlich über das Rechte-Management von Oro verwaltet werden können. Ausgangspunkt ist eine fertig eingerichtete Oro-Plattform. Dafür einfach den Anweisungen bei Github folgen.

Die Oro-Plattform verwendet als Basis-Framework Symfony2. Wenn man sich also mit Oro beschäftigt, muss man also zwangsläufig auch in diese Welt eintauchen. Bei Symfony wird jegliche Software in sogenannten Bundles entwickelt. Der Core von Symfony2 wird damit genauso als Bundle geliefert, wie auch die Oro-Plattform. Die Bundles der Drittanbieter werden im Verzeichnis vendor abgelegt. Der Code der eigenen Applikation wird dagegen im Verzeichnis src gespeichert. Natürlich auch hier in Form eines Bundles. Neue Bundles kann man nun entweder manuell anlegen, in dem man die entsprechenden Verzeichnisse und Dateien erstellt. Einfacher und schneller ist die Verwendung von kleinen Skripten, die Symfony auf der Kommandozeile bereitstellt. Wer die Platform zusätzlich noch um das CRM erweitern möchte, muss nur noch die zusätzlichen OroCRM Bundles installieren.

Ein eigenes Bundle anlegen

Legen wir also im ersten Schritt unser neues Bundle an. Dazu in der Konsole ins Hauptverzeichnis der Applikation wechseln und folgenden Befehl eingeben:

php app/console generate:bundle --namespace=Acme/OroBundle

Der Befehl startet einen Wizard, der weitere Angaben für das Bundle benötigt. In den meisten Fällen macht er aber bereits sinnvolle Vorgaben, die man nur bestätigen muss. Beim Format für die Konfiguration sollte man yml wählen.

Die Frage nach Erzeugung der kompletten Verzeichnisstruktur sollte man wie vorgeschlagen verneinen. Nachdem das Bundle erstellt wurde, fragt der Wizard noch, ob es direkt für die Verwendung im Kernel und beim Routing registriert werden soll. Das sollte man bestätigen.

Damit haben wir ein einsatzfähiges Symfony Bundle erzeugt, welches sich im src-Ordner befindet. Der Controller des neuen Bundles wurde in app/AppKernel.php eingetragen und für die Navigation wurde das Routing in app/config/routing.yml erweitert. Mit diesen Änderungen hat sich aber im Frontend der Oro-Plattform noch gar nichts getan.

Das Oro-Menu erweitern

Für die Erweiterung des Hauptmenüs erstellen wir nun im Verzeichnis src/Acme/OroBundle/Resources/config eine Datei mit dem Namen navigation.yml und tragen folgenden Inhalt ein:

oro_menu_config: 
   items:
      acme_tab:
        label: 'Acme'
         uri: '#'
         extras:
            position: 10
      acme_hello:
         label: 'Hello'
         route: 'acme_oro_homepage'
         extras:
            routes: ['acme_oro_homepage_*']
   tree:
      application_menu:
         children:
            acme_tab:
               children:
                  acme_hello: ~
oro_titles:
   acme_oro_homepage: Hello Pagetitle

Im Abschnitt items definieren wir also ein neues Tab für das Menu und einen neuen Menu-Eintrag. Im Abschnitt tree werden die beiden Elemente in das Hauptmenu integriert. Der Abschnitt oro_title legt den Inhalt des title-Tags fest, der beim Aufruf des Menü-Eintrags verwendet werden soll.

Nun passen wir noch die Datei routing.yml an und stellen die Konfiguration auf Annotations um.

acme_oro_homepage: 
   resource: "@AcmeOroBundle/Controller"
   type: annotation
   prefix: /hello
#   pattern: /hello/{name}
#   defaults: { _controller: AcmeOroBundle:Default:index }

Diese Annotations müssen jetzt natürlich im Controller integriert werden:

namespace Acme\OroBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class DefaultController extends Controller
{
 /**
  * @Route(
  *   "/{_format}",
  *   name="acme_oro_homepage",
  *   requirements={"_format"="html|json"},
  *   defaults={"_format" = "html"}
  * )
  */
 public function indexAction(Request $request){
   return $this->render('AcmeOroBundle:Default:index.html.twig', array('name' => 'Hello ORO!'));
  }
}

Aus der ursprünglichen Route wurde in diesem Fall der notwendige Parameter entfernt. Entsprechend wird dem Template hier ein fester String übergeben.

Damit diese Änderungen wirksam werden müssen zwei Befehle auf der Kommandozeile ausgeführt werden:

php app/console oro:navigation:init 
php app/console cache:clear --env=dev

Der erste Befehl stammt von Oro und übernimmt den konfigurierten Seitentitel in die Datenbank. Der zweite Befehl löscht den Cache von Symfony. In diesem Fall für die Entwicklungsumgebung. Wer im Produktivmodus entwickelt, verwendet statt dessen die Option --env=prod. Bei der Ausführung des zweiten Befehls, wird es vermutlich zu einer Fehlermeldung kommen:

[Symfony\Component\Filesystem\Exception\IOException] 
Failed to remove file /home/rene/develop/www/oro/oro-app/app/../web/bundles/jsformvalidation/js/oro_user_role_update_oro_user_role_form.js

Das liegt daran, daß das Bundle jsformvalidation mit dem User des Webservers schreibend auf das Verzeichnis web zugreift. Das Problem behebt man am schnellsten in dem man die Zugriffsrechte der Datei ändert:

sudo chmod -R o+w web/bundles/jsformvalidation/

Wenn beide Befehle fehlerfrei durchgelaufen sind, kann man sich das Ergebnis im Frontend der Plattform anschauen. Der neue Menüeintrag erscheint. Allerdings wird beim Aufruf der neuen Seite noch ein Fehler erzeugt. Um diesen zu beheben, muss das Template etwas angepaßt werden. Da es sich um einen Ajax-Call handelt, muss man den gewünschten Inhalt in eine Vorlage von Oro integrieren. Also in die Datei [bundle]/Resources/Views/Default/index.html.twig folgenden Inhalt einfügen:

{% extends bap.layout is defined ? bap.layout : 'OroUserBundle::layout.html.twig' %}
{% block page_container %}
   {% block content %}
Hello Vorlage:Name!
   {% endblock %}
{% endblock %}

Nach einem Refresh der Seite, sollte der Aufruf nun funktionieren.

Rechteverwaltung

Die Oro-Plattform bietet unter System->Roles die Möglichkeit Zugriffsrechte auf Systemfunktionen über Nutzerrollen zu beschränken. Wenn man eine der Rollen bearbeitet, erscheint ein Formular mit der gesamten Access Control List (ACL). In dieser Liste ist unser neuer Menüeintrag noch nicht aufgeführt.

Oro liest die vorhandenen Access Control Entities (ACE) über Annotations ein. Also müssen wir unsere Controllerklasse nochmal erweitern:

namespace Acme\OroBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

use Oro\Bundle\UserBundle\Annotation\Acl;

/**
 * @Acl(
 *   id="acme_oro_homepage",
 *   name="Acme homepage controller",
 *   description="Access to acme homepage",
 *   parent="root"
 * )
 */
class DefaultController extends Controller{
/**
 * @Route(
 *   "/{_format}",
 *   name="acme_oro_homepage",
 *   requirements={"_format"="html|json"},
 *   defaults={"_format" = "html"}
 * )
 * @Acl(
 *   id="acme_oro_homepage_show",
 *   name="View acme homepage",
 *   description="Right to view homepage",
 *   parent="acme_oro_homepage"
 * )
 */
 public function indexAction(Request $request) {
   return $this->render('AcmeOroBundle:Default:index.html.twig', array('name' => 'Hello ORO!'));
 }
}

Wir beschränken den Zugriff hier also auf zwei Ebenen. Zunächst definieren wir eine ACE für den Zugriff auf den Controller und dann in der zweiten Ebene den Zugriff auf die einzelnen Methode. In diesem Fall haben wir nur die Index-Methode. Wenn es weitere Methoden für die Datenmanipulation gäbe, dann könnten diese mit eigenen ACEs ausgestattet werden.

Damit die Änderungen wirksam werden, müssen wir wieder auf die Kommandozeile. Diesmal hilft uns folgender Befehl weiter:

php app/console oro:acl:load

Dieser Befehl durchläuft sämtliche relevanten Klassen und erstellt aus den die ACL-Tags Datensätze in der Tabelle oro_user_acl. Wenn das Script beendet ist, muss man sich erneut einloggen. Die beiden neuen ACEs sollten nun unter den in der ACLs auftauchen.    

Kontaktieren Sie uns