Kategorie: Uncategorized

  • Node Annotationen mit OG Mitgliedern teilen

    Dieses Modul ist eine Abwandlung von annotations. Es ist für die Integration mit OG (Organic Groups) gedacht. Was ist möglich:

    Der Admin hat die Möglichkeit zu sagen, welche Nodetypen annotierbar sind. Der Benutzer kann dann Annotationen zu einem Node hinterlassen. Die Sichtbarkeit der Annotationen sind dabei private und eine OG, wo er Mitglied ist. Das heisst, wenn der Benutzer in keiner OG ist, dann wird er auf dem Node ein Annotationsfeld haben -> das für die privaten Annotationen.

    Ist der Benutzer Mitglied der Gruppe Test1 und Test2, dann kommen initial 2 Textfelder, eines für die Privaten und eines, wo die Gruppenzugehörigkeit ausgewählt werden kann. Der Benutzer kann also wählen, in welcher Gruppe die Annotation sichtbar ist. Für jede Gruppe mit Annotationen gibt es sodann ein neues Textfeld.

  • Drupal Modulentwicklung – Views Integration

    Views lässt sich eigentlich extrem einfach in die eigenen Module integrieren. Ich muss zugeben, ich habe ein wenig an der API rumgebastelt, bis ich meine erste View zum laufen gebracht habe, aber wenn man es dann anschaut ist es eigentlich wirklich einfach (auf jeden Fall die Basics und damit kommt man schon weit). Die Infos finden sich ausführlich im Views Handbuch.

    Zuerst einmal muss der "hook" von views implementiert werden. Dieser heisst mymodule_views_tables(). Im folgenden Beispiel heisst mein Modul kapitel. Im Modul geht es darum die Permissions für nodes zu erweitern. Standardmässig sind diese auf 0 bzw. 1 für Published und not published. Ich habe jetzt ein Modul geschrieben, welche es ermöglich Statuse von 0-3 zu setzen, für Draft, ready for revision, ready for publishing und published.

    Es gibt eine separate Tabelle node_status, welches aus 2 Spalten besteht:

    -----------------------------|sid | status_text          |-----------------------------| 0  | draft                || 1  | published            || 2  | ready for revision   || 3  | ready for publishing |-----------------------------

    sid bezieht sich auf die Status id, welche sich auch in der node Tabelle wieder finet. So jetzt wollen wir also diese Statuse für Views zugänglich machen. Jetzt folgt das Beispiel für eine einfache Views Integration. Im Kommentar sind die einzelnen Sachen beschrieben.

    <!–?php
    function kapitel_views_tables() {
    $tables["node_status"] = array( //bezieht sich auf die Tabelle, von welcher wir Infos holen wollen
    'name' => 'node_status', //in unserem Fall eigentlich überflüssig. Ist einfach nochmals der Name
    'join' => array( //Jetzt müssen wir sagen, wie diese Tabelle mit der nodes Tabelle zusammenhängt, passiert mittels join (left joing standardmässig)
    'left' => array(
    'table' => 'node', //tabelle node
    'field' => 'status', //Feld welches für den Join verwendet werden soll
    ),
    'right' => array(
    'field' => 'sid', //und dann das Feld aus der Tabelle node_status. Das Feld hier muss mit dem Field aus left übereinstimmen
    ),
    ),
    'fields' => array( //Jetzt wollen wir ein Feld für die View sichtbar machen.
    'status_text' => array( //ist das Feld aus der Tabelle, welche oben spezifiziert wurde, welche wir Sichtbar machen wollen
    'name' => t('Node: Status'), //der Name, welcher angezeigt wird im Dropdown bei den Views
    'help' => t('Select the status'), //die Hilfe
    'sortable' => true, //ob man dieses Feld sortieren kann
    ),
    ),
    //das wäre eigentlich auch schon das wichtigste gewesen. Jetzt wollen wir aber noch die Möglichkeit geben, daraus einen Filter zu machen:
    'filters' => array(
    'name' => t('Node: Status'), //der Name welche in dem Dropdown erscheint. Wir befinden uns immer noch in der Tabelle node_status
    'field' => 'sid', //Gib das Feld an, welches für den Filter verwendet werden soll. Wenn wir das auf SQL Ebene anschauen, wird hier gesagt, welches Feld in die Where Klausel kommt
    'operator' => 'views_handler_operator_andor', //Was für Operatoren. Hier gibt es bereits eine grosse Auswahl an gängigen Operatoren. Hier wird einfach diese Funktion aufgerufen, es kann aber auch ein assoziatives Array verwendet werden, um eigenen Operatoren zu spezifizieren.
    'value' => array( //Was für ein Wert. Kann man die FormAPI verwenden
    '#type' => 'select',
    '#options' => 'views_handler_get_all_status', //hier werden die Valus geholt. Die Funktion welche ich weiter unten reinkopiert habe, wird aufgerufen.
    '#multiple' => true,
    ),
    'help' => t('extended status of node.'),
    )
    );
    return $tables;
    }
    /**

    • get the possible status for a node
      *
    • @return array
      */
      function views_handler_get_all_status(){
      $sql = 'SELECT sid,status_text FROM {node_status}';
      $result = db_query($sql);
      $return = array();
      while ($row = db_fetch_object($result)) {
      $return[$row->sid] = $row->status_text;
      }
      return $return;
      }
      ?>

    Das wäre es dann auch bereits gewesen. Mit dem Kommentar sollte es eigentlich recht verständlich sein. Was noch wichtig zu wissen ist, ist bezüglich Testing! Der Drupal Cache ist da ziemlich tricky und kann einem ein wenig verwundern. Ich habe vor jedem neuen Versuch schnell mit dem Devel Modul den Cache geleert, damit ich auch wirklich die neusten Änderungen zu gesicht bekommen habe. Ansonsten klappt das dann nicht.

    Update: 26.3.08: Der Kommentar von awesomeg wurde integriert. Sprich, das Return Statement eingefügt… Flüchtigkeitsfehler von meiner Seite.

  • Block welcher sich automatisch alle x sekunden aktualisiert

    Die AJAX Module sind langsam aber sicher am Kommen. Habe gerade in meinem Feed ein echt cooles Teil gesehen: Block Refresh. Dieses Modul aktualisiert einen Block alle x Sekunden -> natürlich über AJAX. Dadurch liesse sich dann auch meine "Wer ist online" sehr einfach implementieren -> gibt ja eigentlich fast nichts zu machen.

    Interessante Anwendungsgebiete für Block Refresh:

    • Neuste Kommentare
    • Neuste Forenbeiträge -> z.B. auf drupalcenter.de. Damit man die Seite nicht immer neue laden muss
    • Wer ist online
    • und wahrscheinlich noch mehr

    Kommt auf meine Liste, der zu testenden Module.

    Hier noch der Link dazu: http://drupal.org/project/block_refresh

  • Ultimative online PDF converter

    Leider gibt es tausende von Formate und manchmal klappt es beim einen oder anderen einfach nicht. Habe den ultimativen online converter gefunden. Als Input frisst er alles, was irgendwie mit Text zu tun hat. Wirklich alles! Als Output kann gewählt werden zwischen

    • pdf
    • eps
    • jpg
    • gif
    • Postscript
    • PCX
    • Tiff

    Hier gehts zum Converter

    😉 … es muss ja nicht immer jeder Blogeintrag mit Drupal zu tun haben…

    Dieser Converter scheint noch besser zu sein.

  • Grundkonzepte von Views

    Views gehört mit CCK zu den mächtigsten Modulen von Drupal. Es ist daher wichtig, die grundlegenden Konzepte zu verstehen. Nachdem in Drupalcenter danach gefragt wurde, habe ich beschlossen, doch daraus einen kleinen Artikel zu machen, da Views einfach wirklich zu den Basics gehört.

    • Drupal besteht aus nodes. Jeder Artikel, Story, Beitrag ist ein Node.
    • Standartmässig wird pro Seite ein Node angezeigt. Dies ist manchmal jedoch zu wenig, z.B. will ich alle Beiträge vom Jahr 2000 auflisten, oder ich will lediglich alle Blogeinträge von einem bestimmten User auflisten usw. Views wird benötigt!
    • Views kann als Listengenerierungstool gesehen werden, wobei die Listen ziemlich flexibel sein können, als Tabelle, als Liste und es gibt noch viele Bonus views.
    • Jetzt muss eigentlich diese Liste nur noch definiert werden, sprich: Was für Elemente kommen in die Liste (ein Node besteht ja aus vielen Elementen, z.B. Ersteller, Zeit, Titel, Body usw.), die Liste kann gefiltert werden, und dann kann noch gewählt werden ob das ganze in einem Block erscheint oder als eigene Seite

    Dies sind die absoluten Basics des Views Modul. Es können dann noch Argumente übergeben werden, Filter können für den Benutzer anpassbar gemacht werden und natürlich kann die Views auch noch gethemed werden. Es kann also schon ein wenig komplexer werden.

    Views wird zudem erst richtig spannend, wenn CCK mit ins Spiel kommt. Denn mit CCK lässt sich ein Nodetyp entsprechend erweitern. Auf diese erweiterten Eigenschaften lässt sich dann via Views zugriefen. So ist zum Beispiel hier auf dieser Seite die rechte Spalten mit den Vorschauen der Themes eine Views. Der CCK Type darunter besteht aus diversen Feldern und unter anderem auch aus einem Feld für ein Bild. Ich habe also jetzt eine View gemacht, welche einen Filter hat (es sollen nur Theme Inhaltstypen aufgelistet werden ) und davon soll nur das Bild und der Titel gelistet werden und das Ganze soll als Block angezeigt werden. Voilà.

    Typische Problemlösungen für Views

    • Neusten Nodes auflisten
    • Archiv nach Jahr sortieren
    • Fotoalbum machen (Grid View verwenden)
    • Userliste
    • einfach Listen, Listen, Listen

    Also hier nochmals. Views ist für Listen da! Überall dort, wo irgend etwas gelistet werden soll, kommt Views zum Einsatz. Manchmal muss man halt ein wenig über den Nasenspitz hinaus sehen, um zu erkennen, dass es sich um ein Listenproblem handelt und sich Views für die Problemlösung sehr gut eignet.

    Listen, Listen, Listen. -> Hier der Link zum Handbuch (Deutsch).

  • Unterlinks von Primary Links separat darstellen

    So, hier geht es um fortgeschrittenes Themeing! Aber man kann wirklich coole Sachen machen und es ist eigentlich gar nicht schwierig.

    Problemstellung:

    Also, die Primary Links werden ja normalerweise ganz normal dargestellt. Die sind eigentlich in jedem Theme drin. Nur was passiert, wenn man Unterlinks von den Primary Links macht? Oftmals wird da das Design ziemlich über den Haufen geworden und es kommt nicht viel schlaues raus. Das Problem lässt sich sehr elegant lösen: Die Unterkategorie rauslösen damit die separat in Theme dargestellt werden kann.

    Hier jetzt also die Schritt für Schritt Anleitung:

    1. Navigationsstruktur zum Testen erstellen

    Diese Struktur solle ungefähr wie folgt aussehen:

    • Bücher
      • Buch 1
      • Buch 2
      • Buch 3
    • DVDs
      • DVD 1
      • DVD 2
      • DVD 3
    • Witze
      • Witz 1
      • Witz 2

    Dies ist wichtig, damit wir auch sehen, ob das ganze funktioniert.

    2. template.php modifizieren

    uid > 0){
    $vars['logged_in'] = 'true';
    }
    else{
    $vars['logged_in'] = 'false';

    }
    $vars['primary_links'] = primary_secondary_links(variable_get('menu_primary_menu', 1),'tablist'); //$primary_links überschreiben
    $vars['primary_sublinks'] = primary_sublinks(variable_get('menu_primary_menu', 1)); //das werden dann Buch 1, Buch 2 usw.

    break;
    }
    return $vars;
    }
    ?>

    So, mit dem obigen Schnipsel werden neue Variablen für page.tpl.php vorbereitet. Die Primary Links ($primary_links) werden überschrieben. Es wird nur noch die oberste Stufe ausgegeben. Im Weiteren wird eine neue Variable eingeführt: $primary_sublinks. Dies enthält dann Buch 1, Buch 2 usw. und kann dann beliebig eingefügt werden.

    <?php
    /
    Die Primary Sublinks werden herausgelöst, damit diese sepparat angezeigt werden können und nicht irgendwie verschachtelt.

    @param int $pid
    @return string html
    */
    function primary_sublinks($pid,$anz=2){
    $item = menu_get_item($pid); // hole den jeweiligen menupunkt
    $out = '';
    $final_out = '

      ';
      foreach ($item['children'] as $mid) {
      if(menu_in_active_trail_in_submenu($mid,$pid)){
      $current_menu_item = menu_get_item($mid);
      if(is_array($current_menu_item['children'])){

      $counter = 0;
      foreach ($current_menu_item['children'] as $value) {
      if($value > 0){
      $final_out .= '

      ';
      if ($counter >= $anz) {
      $final_out .= '

      ';
      $counter = 0;
      }
      $counter++;
      }
      }
      }
      }
      }
      return $final_out.'

    ';
    }
    ?>

    Der obige Schnipsel macht dann schlussendlich die Hauptarbeit. Hier werden die Sublinks extrahiert und in entsprechenden HTML Code verpackt. Dieser kann natürlich nach belieben noch geändert und den eigenen Bedürfnissen angepasst werden.

    Der Parameter $anz ist ein bisschen speziell. Dieser macht es möglich, die Links in mehrere Spalten zu schreiben, wobei $anz angibt, wieviele Links in einer Spalte sind. Kann nach belieben umgeschrieben werden.

    Damit wäre es dann eigentlich auch schon geschafft. War doch gar nicht so schwierig, das Tüpfelchen auf dem i wäre dann natürlich noch, wenn die der aktive Primary Link passend markiert wird. Dies ist vor allem nützlich, wenn man z.B. Tabs hat und diese als aktiv markieren will.

    <?php
    /

    überschreibt theme_menu_item() aus includes/menu.inc

    fügt zusätzlich eine class 'active' für alle aktiven menupunkte zum

  • -element

    */
    function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) {
    $item = menu_get_item($mid); // hole den jeweiligen menupunkt

    if ((drupal_get_normal_path($item['path']) == $_GET['q']) // pfad aktiv?
    || (drupal_is_front_page() && $item['path'] == '') // oder sind wir auf der startseite?
    || menu_in_active_trail($mid)) { // oder sind wir irgendwo im aktiven pfad, also in einem übergeordneten element des gerade angewählten?
    #$active = ' active'; falsch. führt zu klassen wie z.b. 'activeexpanden' statt 'active expanded'
    $active = 'current '; # so ists korrekt
    } else {
    $active = '';
    }
    return '

  • '. menu_item_link($mid) . $children .'
  • ';
    }
    ?>

    Damit wird der aktive primary Link markiert. -> Habe ich auf Drupalcenter gefunden.

    3. Unterlinks an passender Stelle einbauen

    So, jetzt nur noch node.tpl.php öffnen und die Variable einfügen:

    Halt einfach da wo man will

    Jo, das wäre es dann auch schon gewesen, Ich wollte eigentlich noch einen kleinen Screenshot einfügen, aber irgendwie ist bei mir lokal gerade ein Problem

    Update: Ich habe doch wirklich ein Codestück vergessen 😉

    <?php
    /*
    Hier werden die primary und secondary links formatiert, so dass diese einen zusatz markup bekommen
    zum schauen, welcher Punkt aktiv ist und welcher nicht.

    @param int $pid
    @param string $id
    @return string html
    /
    function primary_secondary_links($pid, $id='primary-links') {
    /if ($tree = menu_tree($pid)) {
    return '

      '. $tree .'

    ';
    }
    /

    $menu = menu_get_menu();
    $output = '';

    if (isset($menu['visible'][$pid])) {//I only want the once that are visible -> since its the primary navigation
    foreach ($menu['visible'][$pid]['children'] as $mid) {
    $output .= theme('menu_item', $mid);
    }
    }
    return '

      '. $output .'

    ';
    }
    ?>

    Im Anhang kann die Datei sonst noch runtergeladen werden

  • Drupal 7 in den Entwicklungsstartlöcher

    Drupal 6 ist ja noch gar nicht offiziell gelaunched und schon sprechen viele Leute über die Version 7:

    Es scheint, dass vor allem auf Datenbankebene noch einiges gemacht werden will. Was mir auch gefällt, ist dass das core Forum verbessert werden will. Dies ist oft ein "Anklagepunkt" von Drupal. Ich freue mich auf jeden Fall auf die Stable release von D6 und dass möglichst viele Module schnell portiert werden…

  • Domains lokal simulieren

    Wahrscheinlich wird jeder Drupal Entwickler lokal entwickeln und testen und dann wenn es fertig ist und läuft auf den produktiven Server laden. Dies ist manchmal ein bisschen mühsam, da unter Umständen manchmal config Dateien im Code konfiguriert werden müssen -> z.B. im FCKEditor. Daher wäre es eigentlich praktisch, wenn man lokal unter den gleichen Pfadbedingungen programmieren könnte. Ist eigentlich ganz einfach:

    In der host Datei muss etwas geändert werden. Die Host Datei (bei mir unter C:WINDOWSsystem32driversetchosts) gibt an, unter welcher IP ein Domainnamen gefunden werden kann. Also, meine sieht z.B. so aus:

    127.0.0.1       rapsli.ch

    Also rapsli.ch wird jetzt nicht mehr auf dem Server von hostorama gesucht, sondern lokal unter 127.0.0.1. So, jetzt müssen wir noch sagen, dass alle rapsli.ch Anfragen auf ein eigenes Directory im Rootverzeichnis des lokalen Servers geleitet werden. Dafür muss die Datei httpd.conf geändert werden. Diese findet sich unter "xamppapacheconf".

    #
    # ServerName gives the name and port that the server uses to identify itself.
    # This can often be determined automatically, but we recommend you specify
    # it explicitly to prevent problems during startup.
    #
    # If your host doesn't have a registered DNS name, enter its IP address here.
    #

    ServerName rapsli:80
    <VirtualHost :80>
        ServerName rapsli
        DocumentRoot "C:/Programme/xampp/xampp/htdocs/drupal-5.5"
        ErrorLog logs/rapsli-error_log
    </VirtualHost>


    ServerName localhost:80
    <VirtualHost
    :80>
        ServerName localhost
        DocumentRoot "C:/Programme/xampp/xampp/htdocs"
        ErrorLog logs/localhost-error_log
        CustomLog logs/localhost
    -access_log common
    </VirtualHost>

    Standartmässig ist wohl nur der unter Virtual Host drin. Oder vielleicht auch gar nichts? Ich weiss nicht, ob ich da schon mal etwas reingebastelt haben. Auf jeden Fall werden jetzt alle Anfragen welche von rapsli.ch an das drupal-5.5 Unterverzeichnis geleitet.

    Wenn man jetzt auf rapsli.ch geht, so landet man nicht online, sondern auf dem lokalen Entwicklungsverzeichnis. Falls man sich das ganze mal wieder Online anschauen möchte, sollte man einfach nicht vergessen, in der Host Datei die Umleitung zu löschen 😉 -> das könnte zu ein paar Unverständlichen Problemen führen.

    Update: Irgendwie klappt jetzt zwar rapsli.ch lokal, dafür geht der localhost nicht mehr. Muss ich wohl noch ein wenig pröbeln. Falls jemand eine Idee hat oder gerade weiss, wie es klappt -> Kommentar.

    Update 5.2.08 – So es hat geklappt -> siehe Kommentar.

  • uncaught exception: Die Erlaubnis für das Setzen der Eigenschaft Window.FCK_STATUS_NOTLOADED wurde verweigert

    Dieser Error kann sehr ätzend sein: Anstatt des Textfeldes kommt einfach eine Fehlermeldung:

    "uncaught exception: Die Erlaubnis für das Setzen der Eigenschaft Window.FCK_STATUS_NOTLOADED wurde verweigert"

    Man kann lange suchen und wird das Problem nicht finden. Zudem merkt man, dass es manchmal funktioniert und manchmal nicht. Sehr komisch. Am Browser kann es auch nicht liegen, aber Server jedoch auch nicht. Woran liegt es. Die Lösung habe ich in diesem Post gefunden.

    Einfach mal anstatt www.mydomain.ch mydomain.ch ausprobieren und man wird wahre wunder erleben. Es kann manchmal schon ziemlich einfach sein. Im Artikel schlägt er vor, im .htaccess File eine entsprechende Weiterleitung zu machen, damit immer die richtige URL benützt wird.

    Hoffe, das kann jemandem helfen 😉

  • 1. Schweizer Drupalianertreffen hat statt gefunden

    Nachdem das erste Treffen letztes Jahr nicht stattgefunden hat, konnten wir uns unter schweiz Drupalianern doch treffen. Immerhin 8 Leute waren wir. Auf der Agenda war vor allem ganz gross ein erstes Kennenlernen. So hat jeder seine Aktivitäten vorgestellt. Es war interessant zu sehen, was für Sachen andere Drupalianer machen. Diejenigen, die danach nicht auf den Zug mussten, haben noch gemeinschaftlich etwas getrunken. Es kam sogar die Ideen auf, die DrupalCon in die Schweiz zu bringen… das wäre was. Alles in allem ein sehr positiver Start!

    Leider habe ich meine schöne DigiCam vergessen. Eigentlich wollte ich ja ein paar Fotos knipsen 🙁

    Ein nächstes Treffen wurde bereits wieder festgelegt: Mittwoch, 12. März 2008.