/me hat's auch ein Templatesystem angetan

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • /me hat's auch ein Templatesystem angetan

    Ich hab mir nun auch vorgenommen mal eine eigene Templattklasse zu entwickeln. Wir würdet ihr dabei vorgehen? Ich habe mir die Funktion-struktur oder bzw. Ablauf etwa so vorgestellt:



    1. Arrays einlesen und rekursiv füllen ( Assign )

    2. Bei der Absicht mit Display

    2.1. Angegebene Template-Datei auf Existenz prüfen sowie bei Erfolg das DIR ermitteln
    2.2. Datei als String auslesen. Entweder mit file_ob_content oder besser mit fred? Kennt ihr da nennenswerte Zeitdifferenzen? Was ist schneller?
    2.3. Prüfen ob die gechanchte PHP-Datei aus der TPL-Datei existiert oder verändert wurde
    2.3.1. Wenn verändert oder nicht vorhanden, erzeugen)

    2.4. Komplilieren
    2.4.1. Alle {}-Klammern bspw. mit preg_match oder ( _all ) einlesen
    2.4.2. Auf Fehler prüfen
    2.4.3. Die generierte Datei erzeugen und den String Zeile für Zeile abarbeiten

    2.5. diese Datei includieren und mit den Assign.Arrays harmonisieren.

    Das wären mal meine Ideen bis jetzt. Allerdings hab ich noch Subtemplates nicht berücksichtigt. Was ich noch nicht ganz verstanden habe, wie das mit den ID's funktioniert, damit die Subtemplates verknüpft werden können. Ich kam der Logik noch nicht ganz auf der Spur.. Anbei: Wie baut ihr die Dateinamen auf? Mit einem Logarismus? Was für Anhaltspunkte benutzt ihr dabei? Filesize,Zeichenlänge der Datei als String?

    Ich hätte da noch eine Frage. Ich bin leider kein Regex Experte.
    Mein Ziel ist, nur Strings einzulesen, welche {} enthalten, dabei kam mir noch die Idee, das { in der Anzahl ähnlich

    Code:
    /\{{1,1}/
    zu begrenzen. Am besten wäre natürlich ein preg_match(_all), dass mir x arrays in array liefert.

    [0] ( ganzer {} String )
    [1] ( { )
    [2] ( [a-Z / ] ) - Operatoren
    [3] ( $Variable )
    [4] ( [a-Z / ] )
    [5] ( $Variable )
    [6] ( } )

    Anhand [2] ggf. die Funktionen vertiefen, Schleifen etc. und wieder mit Preg_match abarbeiten.

    Ist der Denkansatz so richtig? Ist das mit preg_match_all() überhaupt so möglich so aufzubauen, dass im abweichenden falle, die anderen [x] leer bleiben, falls nicht vorhanden? so, dass man struktuiert ggf. rekusiv damit arbeiten bzw. alles abarbeiten kann.

    Mein bisherige Regex-Versuche

    Code:
    ~(\{)?([ a-z0-9\_\-\.]+)?(?!\: )(\})~Uxs

    oder auch

    Code:
    %[(/\{{1,1}/)]+?[/? {0,}/]+[\$](.*)}%U
    aber am 'logischsten' wäre mir sowas ( keine Ahnung ob das jetzt syntaxtisch Richtig ist )

    Code:
    ~( (\{{1,1}) ?([a-Z/]) ([\$]+[a-Z]) ?([a-Z/]) !([\$]+[a-Z]) (\}{1,1}) )~U
    Mh, oder wäre es sinnvoller zuerst

    [0] Alles
    [1] {
    [2] a-Z / $
    [3] }

    und dann abarbeiten?
    Zuletzt geändert von xManUx; 11.07.2005, 22:18.

    Es kommt nicht darauf an, mit dem Kopf durch den Monitor zu rennen,
    sondern mit den Augen das Manual zu lesen.

  • #2
    Re: /me hat's auch ein Templatesystem angetan

    Original geschrieben von xManUx
    Ich hab mir nun auch vorgenommen mal eine eigene Templattklasse zu entwickeln. Wir würdet ihr dabei vorgehen?
    Strukturiert und wohlüberlegt

    1. Arrays einlesen und rekursiv füllen ( Assign )
    rekursiv?

    2. Bei der Absicht mit Display

    2.1. Angegebene Template-Datei auf Existenz prüfen sowie bei Erfolg das DIR ermitteln
    2.2. Datei als String auslesen. Entweder mit file_ob_content oder besser mit fred? Kennt ihr da nennenswerte Zeitdifferenzen? Was ist schneller?
    2.3. Prüfen ob die gechanchte PHP-Datei aus der TPL-Datei existiert oder verändert wurde
    2.3.1. Wenn verändert oder nicht vorhanden, erzeugen)
    Warum erst das Template einlesen und danach doch im Normalfall die gecachte Version verwenden?

    2.4. Komplilieren
    2.4.1. Alle {}-Klammern bspw. mit preg_match oder ( _all ) einlesen
    Du solltest dich nicht auf { und } festlegen
    2.4.2. Auf Fehler prüfen
    Löblich, aber je nach genauer Herangehensweise nicht notwendig
    2.4.3. Die generierte Datei erzeugen und den String Zeile für Zeile abarbeiten
    Zeile für Zeile?
    Erkläre er sich

    2.5. diese Datei includieren und mit den Assign.Arrays harmonisieren.
    Ich glaube, ich verstehe, was du meinst

    Das wären mal meine Ideen bis jetzt.
    Recht grobe welche

    Allerdings hab ich noch Subtemplates nicht berücksichtigt. Was ich noch nicht ganz verstanden habe, wie das mit den ID's funktioniert, damit die Subtemplates verknüpft werden können. Ich kam der Logik noch nicht ganz auf der Spur..
    Was für IDs?
    Anbei: Wie baut ihr die Dateinamen auf? Mit einem Logarismus? Was für Anhaltspunkte benutzt ihr dabei? Filesize,Zeichenlänge der Datei als String?
    Logarismus?
    Wenn, dann mit einem Algorithmus

    Ich nehme [color=blue]engine-version[/color]____ordner[i][color=green]___dateiname[/color].php
    Der Ordnerteil kann natürlich mehrfach vorkommen. Auf diese Weise klappt das ganze auch da, wo ich nicht mit PHP automatisch Ordner anlegen und dann beschreiben kann (Stichwort: safemode)


    Was deine regulären Ausdrücke angeht:
    Mache die Begrenzer für von der Engine abzuarbeitende Teile variabel. Beim Setzen verwende preg_quote um keine Probleme mit deinen Delimiter zu bekommen
    Und ganz wichtig: Überlege dir, wie du versch. Tokens systematisch anlegst/unterscheidest/...

    Beispiel:
    Code:
    {variable}
    {schleife schleifenvariable}
    ...
    {/schleife schleifenvariable}
    Code:
    {variable}
    {schleifenvariable schleife}
    ...
    {/schleifenvariable}
    Code:
    <tpl_var:variable />
    {tpl_loop:schleifenvariable>
    ...
    </tpl_loop:schleifenvariable>
    Die Möglichkeiten sind unbegrenzt
    Ich denke, also bin ich. - Einige sind trotzdem...

    Kommentar


    • #3
      Re: Re: /me hat's auch ein Templatesystem angetan

      Strukturiert und wohlüberlegt
      Ich stecke in dieser Thematik noch in den Kinderschuhen, ich versuch mein Bestes.

      rekursiv?
      Nennt man das in dem Fall nicht auch so? Wie nennt man das richtig?

      PHP-Code:
        /*--- Assign ---*/

              
      function _assign($name $replace NULL )
              {

                 
      // mehrere Arrays erlaubt!

                   
      IF ( IS_ARRAY($name) )
                    {
                        foreach ( 
      $name AS $key => $var ) {
                          IF ( 
      $key != '' ) {
                             
      $this->_assign$key $var );                     }
                        }
                    }  else {
                        IF ( 
      $name != '' )
                            
      $this->_vars$name ] = $replace
                    }
              }

         
      /*--- Assign ---*/ 
      Warum erst das Template einlesen und danach doch im Normalfall die gecachte Version verwenden?
      Versteh ich nicht so ganz =/ Was verstehst du unter Einlesen?

      Du solltest dich nicht auf { und } festlegen
      Wieso?

      Löblich, aber je nach genauer Herangehensweise nicht notwendig
      Auch schon gemerkt. Aber wiederum ist es doch gut, wenn man weiß das man ein Tag falsch geschrieben hat - und welches?

      Zeile für Zeile?
      Erkläre er sich
      Ich glaube, ich verstehe, was du meinst
      Mh. Wie würdest du vorgehen wenn du

      PHP-Code:
      $this->sitetostring file_get_contents($this->file); 
      gemacht hättest? Der nächste Schritt wäre ja, die {$}-Variabeln zu ersetzen in ' <?php echo $this->_vars['blah']; ?>' etc.

      mh. groß gesagt mal so

      PHP-Code:
      preg_match_all ("~{$this->dleft}\s*(.*?)\s*{$this->dright}~s"$this->sitetostring$erg); 
      wobei $erg[1] weitergegeben wird an

      PHP-Code:
      /*--- replace_tags_to_php ---*/

         
      function _replacetags($source,$tags) {
          for ( 
      $i 0$i COUNT($tags); $i++) {
           
      $allow implode('|',$this->allowfuncs);
             
      preg_match("~(^".$allow."*)~i",$tags[$i],$match);

               SWITCH ( 
      strtolower($match[0]) ) {

                CASE 
      "if";
                 BREAK;

                CASE 
      "elseif";
                 BREAK;


                  DEFAULT:
                      
      $this->_toechophp($tags[$i]);
                  }

              }

          }


       
      /*--- replace_tags_to_php ---*/ 
      und dabei $this->allowfuncs

      PHP-Code:

          
      var $allowfuncs         = array(
                                            
      'if','elseif'
                                                         
      ); 
      ist.

      Bauen tue ich die einfachen Variabeln etwa so

      PHP-Code:
      <?php
        
      function _toechophp($tag) {

               
      $tag_x eregi_replace('\$','',$tag); // $ entfernen
                
      $count explode('.',$tag); // zählen
                  
      IF ( COUNT($count) == ) {
                      
      $this->_buildarray('\$'.$tag_x 
       
      '<?php echo $this->_vars["'.$tag_x.'"]; ?>');
                    } else {

                       
      $zusammen '<?php echo $this->_vars';
                         for ( 
      $ty 0$ty COUNT($count); $ty++ ) {
                           
      $zusammen .= '["'.eregi_replace('\$','',$count[$ty]).'"]';
                          }
                       
      $zusammen .= '; ?>';

                   
      $this->_buildarray('\$'.$tag_x$zusammen );

          }
       }

      Ersetzen das ganze

      PHP-Code:
      function _doreplacestring () {
            
      $this->endstring $this->sitetostring;
             foreach ( 
      $this->__replacement AS $keys => $values ) {
               
      $this->endstring preg_replace('/{?([ ]*|)'.$keys.'?([ ]*|)\}/is',
       
      $values$this->endstring);
             }
          } 
      Ich nehme [color=blue]engine-version[/color]____ordner[i][color=green]___dateiname[/color].php
      Der Ordnerteil kann natürlich mehrfach vorkommen. Auf diese Weise klappt das ganze auch da, wo ich nicht mit PHP automatisch Ordner anlegen und dann beschreiben kann (Stichwort: safemode)
      Wirklich originell

      Was deine regulären Ausdrücke angeht:
      Mache die Begrenzer für von der Engine abzuarbeitende Teile variabel. Beim Setzen verwende preg_quote um keine Probleme mit deinen Delimiter zu bekommen.
      PHP-Code:
      // oben
      var $dleft     '{';                            // begrenzer left   | Steuerelement
      var $dright   '}';                            // begrenzer right | Steuerelement

      // irgendwo unten

      $this->dleft_reg preg_quote($this->dleft,"/");
      $this->dleft_reg preg_quote($this->dright,"/"); 
      Meinst so?



      Und ganz wichtig: Überlege dir, wie du versch. Tokens systematisch anlegst/unterscheidest/...
      Das ist für mich eine Herausfordung, die noch 'behürdigen' muss.
      Zuletzt geändert von xManUx; 12.07.2005, 13:31.

      Es kommt nicht darauf an, mit dem Kopf durch den Monitor zu rennen,
      sondern mit den Augen das Manual zu lesen.

      Kommentar


      • #4
        Original geschrieben von xManUx
        Was verstehst du unter Einlesen?
        Original geschrieben von xManUx
        2.2. Datei als String auslesen. Entweder mit file_ob_content oder besser mit fred? Kennt ihr da nennenswerte Zeitdifferenzen? Was ist schneller?
        2.3. Prüfen ob die gechanchte PHP-Datei aus der TPL-Datei existiert oder verändert wurde
        2.3.1. Wenn verändert oder nicht vorhanden, erzeugen)
        Ich lese das so, dass du erst das Template komplett einliest und dann schaust, ob du das Template gar nicht einlesen musst, weil die gecachte Version aktuell ist


        Warum willst du dich auf { und } festlegen?
        Warum nicht z. B. etwas mehr "XML-iges"?
        Warum sich selbst Fesseln anlegen?
        Was machst du, wenn du mal geschweifte Klammern schreiben willst?


        Wenn man ein Tag falsch schreibt, merkt man das spätestens beim Test *g*
        Da du momentan ja sowieso nur Variablenersetzung implementierst, kann man Tags ja auch nicht wirklich falsch schreiben, oder?



        Wie ich vorgehen würde ist schwer zu sagen... da ich dein ganzes schon vorhandenes Coding, vor dessen Erstellung du unsere Meinung hören wolltest, nicht so recht einzuordnen vermag...

        @preg_quote: Ja, so meine ich das


        Zur allgemeinen Vorgehensweise
        Überlege dir erstmal, ob du aus dem Template eine entsprechende PHP-Datei erstellen willst oder ob du alles immer on the fly machen willst

        Ersteres ist geringfügig komplizierter, macht aber mehr Spaß und ist, wenn du's richtig machst, schneller als letzteres

        Letzteres ist schneller realisiert und muss - je nach Herangehensweise - nicht zwingend langsamer sein


        Du solltest dir beim Aufbau der Engine, dazu gehört auch der Aufbau eines Templates zur Engine, Gedanken über eine möglichst leichte Erweiterbarkeit machen.

        Bei deinem jetzigem Code bekommst du mit Sicherheit Probleme, wenn du mit Blöcken o. ä. arbeiten willst.


        Du könntest z. B. alles bis aufs Ersetzen von Variablen auslagern in Dateien namens special.if.php und ähnliches.
        Nach dem Einlesen des Templates liest du alle Dateien namens special.*.php (Stichwort: glob) und suchst nach entsprechenden Tags.
        Diese Tags (z. B. das if) nimmst du von Anfang bis Ende, lässt den Code aus special.if.php drüberlaufen und fertig

        Beispiel:
        Ich habe für Dateien, die ich nur einmal generiere und danach keine Dynamik mehr benötigen ein Tag
        Code:
        {cache_file /}
        definiert.
        Demzufolge habe ich eine Datei special.cache_file.php.
        Die sieht (vereinfacht so aus:
        PHP-Code:
        function ext3___compile_command_cache_file($code, &$this$commands) {
            
        //empty $code ($code = {cache_file /}
            //this code has to be removed completely from the template
            
        $code '';
            
        //generate caching code
            
        $cache_compiled 'code for parsing the template once and rewriting it afterwards so it
                only contains the result of the first parsing'
        ;
            
        //store function in template engine
                
        $this->add_compiled_part('cache_file'$cache_compiled);
                
        //return empty string to remove {cache_file /} from remaining template
            
        return $code;

        Die Funktionsnamen orientieren sich an einem bestimmten Schema, die Parameter sind für alle identisch und die Engine ruft einfach alle, die es findet auf.
        Was da im Detail passiert, ist ihr herzlich egal.



        Die optimale Art und Weise gibt es wohl nicht, jeder kocht da sein eigenes Süppchen
        Zuletzt geändert von mrhappiness; 13.07.2005, 08:04.
        Ich denke, also bin ich. - Einige sind trotzdem...

        Kommentar


        • #5
          Wegen des Argumentes: Was für eine ID

          Besonderer Knackpunkt ist diese Situation:
          <!-- BEGIN Block a -->
          sdfsf
          fs
          <!-- BEGIN Block a.a -->
          fsd
          gdfg
          d
          <!-- BEGIN Block a.a.a -->
          gd
          dg
          <!-- BEGIN Block a.a.a -->
          dfg
          <!-- END Block a.a -->
          sdf
          <!-- END Block a -->

          Nun wenn ich eine Schleife habe den Block a.a 8 mal parse und dabei beim Ersten und Fünften Durchlauf den Block a.a.a
          auch noch parse....

          Dann muss festgehalten werden bei welchem Durchlauf bzw. welchen Block der Subblock geparst werden muss und das ist wohl
          nur mit einer internen Bezeichnung möglich.

          Geht man nach der Reihenfolge wird das zu einem logischen Problem.....
          [color=blue]MfG Payne_of_Death[/color]

          [color=red]Manual(s):[/color] <-| PHP | MySQL | SELFHTML |->
          [color=red]Merke:[/color]
          [color=blue]Du brauchst das Rad nicht neu erfinden ! [/color]<-ForumSuche rettet Leben-> || <-Schau in den Codeschnippsels->

          Murphy`s Importanst LAWS
          Jede Lösung bringt nur neue Probleme
          Das Fluchen ist die einzige Sprache, die jeder Programmierer beherrscht.
          In jedem kleinen Problem steckt ein großes, das gern raus moechte.

          Kommentar


          • #6
            [PHP_MANUAL]
            array glob ( string pattern [, int flags])

            Returns an array containing the matched files/directories or FALSE on error.

            Anmerkung: This function is disabled in safe mode and therefore will always return FALSE in safe mode.
            [/PHP_MANUAL]

            Wie wahrscheinlich ist es erfahrungsgemäß, dass Hoster safe_mode auf off gestellt haben? Ich denke mal nur wenige, oder?

            Ansonsten

            Du könntest z. B. alles bis aufs Ersetzen von Variablen auslagern in Dateien namens special.if.php und ähnliches.
            Nach dem Einlesen des Templates liest du alle Dateien namens special.*.php (Stichwort: glob) und suchst nach entsprechenden Tags.
            Diese Tags (z. B. das if) nimmst du von Anfang bis Ende, lässt den Code aus special.if.php drüberlaufen und fertig
            finde ich das eine sehr überlegte und gute Stratagie.
            Macht das aufbauen recht variabel und flexsibel.

            Ich lese das so, dass du erst das Template komplett einliest und dann schaust, ob du das Template gar nicht einlesen musst, weil die gecachte Version aktuell ist
            Mh. Als ich hatte und habe es auch noch immer vor, die evil'ische eval()-Funktion zu vermeiden. Lieber für jedes TPL eine Phpdatei kompilieren und includieren. Fände ich ehrlich gesagt praktischer, weil sich so auch evtl. Fehler beim Kompilieren besser debuggen lassen. ( Weil man sieht, was man macht. ) Man könnte zwar htmlspecialchars() für Testzwecke verwenden, ist aber umständlich. ( ? ) Ein weiteres Argument wäre, dass dabei der Lerneffekt größer ist. IMHO.

            Aber zur eigentlich Frage: Wie prüfst du, ob die vorhandene - falls vorhanden - kompilierte Datei aktuell ist? Ich weiß ja eigentlich nur, wie der Dateiname dann ist und kann prüfen, ob diese vorhanden ist. Auf die Zeichenlänge bzw. Dateigröße ist kein 100%tiger Verlass, oder?

            Warum willst du dich auf { und } festlegen?
            Mh.. Wie kann ich denn noch wissen, dass es sich um Tag handelt, das man zum PHP code bearbeiten soll? wenn ich jetzt schreiben würde:

            Code:
            {if $variable == '1'}
             tu's
              {else}
             tu's nicht
            {/if}
            dann weiß ich ja, bzw. kann nach sowas suchen, dass es sich um ein Befehl handelt.

            Code:
            if $variable == '1'
             tu's
              else
             tu's nicht
            /if
            würde sich ja schwierig gestalten, da ich ja auch nur so mal 'if' schreiben könnte?

            Es kommt nicht darauf an, mit dem Kopf durch den Monitor zu rennen,
            sondern mit den Augen das Manual zu lesen.

            Kommentar


            • #7
              @PoD

              Hm, doofe Frage... Wozu braucht man "Blocks" ?

              Im endeffekt würde es ja dann kompiliert so aussehen:

              PHP-Code:
              text
              <?php foreach( $ich AS $keyich => $varich ) {
               echo 
              $this->_vars$keyich ];
              }
              ?>

              nochn text

              <?php  echo $this->_vars'wasicheingab' ]; ?>

              irgendwie so...

              Oder hab ich was falsch verstanden?
              Zuletzt geändert von xManUx; 13.07.2005, 20:42.

              Es kommt nicht darauf an, mit dem Kopf durch den Monitor zu rennen,
              sondern mit den Augen das Manual zu lesen.

              Kommentar


              • #8
                Original geschrieben von xManUx
                [PHP_MANUAL]
                array glob ( string pattern [, int flags])

                Returns an array containing the matched files/directories or FALSE on error.

                Anmerkung: This function is disabled in safe mode and therefore will always return FALSE in safe mode.
                [/PHP_MANUAL]
                wo hast du das denn her?

                das kann ich weder auf der deutschen noch der englischen seite im offiziellen manual finden, und unter http://www.php.net/manual/en/feature....functions.php taucht glob() auch überhaupt nicht auf ...
                I don't believe in rebirth. Actually, I never did in my whole lives.

                Kommentar


                • #9
                  Original geschrieben von wahsaga
                  wo hast du das denn her?

                  das kann ich weder auf der deutschen noch der englischen seite im offiziellen manual finden, und unter http://www.php.net/manual/en/feature....functions.php taucht glob() auch überhaupt nicht auf ...

                  http://www.php-resource.de/manual.php?p=function.glob

                  [hände_waschen]
                  Ich hab wahrscheinlich ins 00 gegriffen? :/
                  [/hände_waschen]
                  Zuletzt geändert von xManUx; 13.07.2005, 17:11.

                  Es kommt nicht darauf an, mit dem Kopf durch den Monitor zu rennen,
                  sondern mit den Augen das Manual zu lesen.

                  Kommentar


                  • #10
                    Original geschrieben von xManUx
                    Im endeffekt würde es ja dann kompiliert so aussehen
                    So könnte es aussehen.

                    Überleg dir lieber was eigenes, bei Smarty abgucken kann jeder
                    Ich denke, also bin ich. - Einige sind trotzdem...

                    Kommentar


                    • #11
                      Zwischenfrage:

                      Wie kann man per extradatei die Funktionen in der Klasse "registrieren" ?

                      sagen wir mal bswp. so ähnlich:

                      PHP-Code:
                                    function _compile() {
                                          
                      // GATTER
                                          
                      $regex "~($this->dleft)\s*(.*?)\s*($this->dright)~is";
                                           
                      preg_match_all $regex $this->filetostring $erg );
                                            echo 
                      $this->_debug($erg[2]);
                                            
                      $sdir dirname(__FILE__).
                      DIRECTORY_SEPARATOR.
                      "specials".
                      DIRECTORY_SEPARATOR.
                      "special.*.php";
                                             foreach (
                      glob($sdir) as $filename) {
                                              
                      #??                       
                                             
                      }
                                          
                      # $this->_funkton_aus_der_datei("sf");
                                       

                      Zuletzt geändert von xManUx; 16.07.2005, 03:33.

                      Es kommt nicht darauf an, mit dem Kopf durch den Monitor zu rennen,
                      sondern mit den Augen das Manual zu lesen.

                      Kommentar


                      • #12
                        Wozu soll das gut sein?
                        Ich denke, also bin ich. - Einige sind trotzdem...

                        Kommentar


                        • #13
                          Ich weiß nicht, wie es richtig machen würde.
                          Ich möchte extra Dateien für spezialfunktionen in nem seperaten Verzeichnis. Ordnungshalber.

                          Es kommt nicht darauf an, mit dem Kopf durch den Monitor zu rennen,
                          sondern mit den Augen das Manual zu lesen.

                          Kommentar


                          • #14
                            Original geschrieben von xManUx
                            Ich weiß nicht, wie es richtig machen würde.
                            Tja
                            Ich möchte extra Dateien für spezialfunktionen in nem seperaten Verzeichnis. Ordnungshalber.
                            Und warum willst du deshalb die Klasse erweitern?

                            Lese die Dateien ein, rufe eine Methode namens special_dein_kommand_do auf (sofern vorhanden) und übergib sowohl den Teil des Quelltexts, der bearbeitet werden soll als auch eine Referenz auf $this
                            Ich denke, also bin ich. - Einige sind trotzdem...

                            Kommentar

                            Lädt...
                            X