iterator_taglib_item.php - 2 neue attribute für das Tag

Dieser Bereich dient dazu, neue Features zu diskutieren und für die Entwicklung zu dokumentieren. // This area is dedicated to new features including proposals and documentation.
Gesperrt
TipTop
Beiträge: 193
Registriert: 25.08.2011, 22:37:08
Wohnort: Klagenfurt, Österreich
Kontaktdaten:

iterator_taglib_item.php - 2 neue attribute für das Tag

Beitrag von TipTop » 15.03.2012, 17:10:05

Hallo!

Ich hätte 2 Attribut-Vorschläge für das Iterator-Item-Tag:
  • iteration="{iteration-name}"
  • pager="{page-section}"
Manchmal kommt es vor, dass man Datenlisten durchnummerieren möchte, um dem Betrachter einen bessern Überblick zu bieten. Momentan ist dies mit der Iterator-Item-Taglib nur umständlich lösbar. Ich dachte daher, dass man vielleicht 2 Attribute hinzufügen könnte. Ersteres, das iteration-Attribut, gibt den Namen von einem <iteration />-Tag an. In diesem wird die fortlaufende Zahl eingebettet.

item_taglib_iteration.php:

Code: Alles auswählen

<?php
class item_taglib_iteration extends html_taglib_placeholder {
}
?>
In der html_taglib_iterator.php wird dieser Platzhalter nun mit einer inkrementierenden Zahl ersetzt.

Ein Template sieht dann folgendermaß aus:

Code: Alles auswählen

<@controller namespace="..." class="my_controller" @>
<hml:iterator name="MyIterator" iteration="Number">
    <iterator:item getter="getProperty">
        <item:iteration name="Number" />
        <item:placeholder name="DisplayName" />
    </iterator:item>
</html:iterator>  
Übergibt man im dazugehörigen Document-Controller nun über fillDataContainer() ein Array mit 10 Objekten, dann werden die Items auch schön von 1-10 durchnummeriert. Das zweite Attribut, pager, kann verwendet werden, wenn man das Pager-Modul einsetzt. Wird dieses angegeben, wird die Pager-Config-Datei gelesen und anhand von Pager.EntriesPerPage und dem URL-Parameter Pager_Page kann dann auf Seite 2, 3, etc. mit der Nummerierung fortgefahren werden - so wird also nicht auf jeder Seite immer mit 1 begonnen.

Code: Alles auswählen

<html:iterator name="MyIterator" iteration="Number" pager="MyIterator">
    <!-- -->
</html:iterator> 
Das pager-Attribut gibt den Namen einer Sektion in der apps/config/modules/pager[/context]/DEFAULT_pager.ini an.


Was haltet Ihr von dieser Erweiterung - könntet Ihr diese auch gebrauchen? Falls Interesse besteht, kann ich ja mal einen Codevorschlag posten.

Grüße,
Nico

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: iterator_taglib_item.php - 2 neue attribute für das Tag

Beitrag von Screeze » 15.03.2012, 17:22:41

Klingt durchaus sinnvoll, wobei man das mit dem pager auch so regeln könnte, dass man (per skript) dem iterator optional die Startnummer geben kann.
$i->setStartIterationNumber($number), diese kann man ja bequem vom pager auslesen glaube ich.

TipTop
Beiträge: 193
Registriert: 25.08.2011, 22:37:08
Wohnort: Klagenfurt, Österreich
Kontaktdaten:

Re: iterator_taglib_item.php - 2 neue attribute für das Tag

Beitrag von TipTop » 15.03.2012, 19:01:42

Hab das nun umgesetzt und auch schon erfolgreich getestet.

Funktionieren tut's folgendermaßen:

Code: Alles auswählen

<html:iterator name="MyIterator">
    <iterator:item getter="getProperty">
        <item:placeholder name="IterationNumber" />
        <item:placeholder name="DisplayName" />
    </iterator:item>
</html:iterator> 
Bei diesem Code-Beispiel wird von 1 aus inkrementiert. Um die Nummerierung zu nutzen, ist lediglich ein Placeholder-Tag notwendig, der im name-Attribut IterationNumber stehen hat.

Um die Nummerierung zu beinflussen (bspw. wegen Pager-Modul) kann man zum Einen für den <html:iterator />-Tag das pager-Attribut angeben. In diesem Attribut muss der Name einer Sektion der DEFAUT_pager.ini definiert sein - das wars auch schon. Beispiel:

Code: Alles auswählen

<html:iterator name="MyIterator" pager="PagerSection">
    <iterator:item getter="getProperty">
        <item:placeholder name="IterationNumber" />
        <item:placeholder name="DisplayName" />
    </iterator:item>
</html:iterator> 

Alternativ dazu kann man auch per Document-Controller die Startnummer der Iteration modifizieren:

Code: Alles auswählen

<?php
import('tools::html::taglib::documentcontroller', 'iteratorBaseController');

class my_controller extends iteratorBaseController {
    public function transformContent() {
        $i = $this->getIterator('MyIterator');
        $i->setIterationNumber(10); 
        $i->fillDataContainer($einArrayMitObjekten);
        $i->transformOnPlace();
    }
}
?>
Über setIterationNumber() kann man nun die Startnummer festlegen. Mit der ersten Variante (pager-Attribut) wird bereits berechnet, mit welcher Zahl auf einer anderen Seite (des Pager-Moduls) fortgefahren werden muss.


Hier der Code der html_taglib_iterator.php:

Code: Alles auswählen

<?php
/**
 * <!--
 * This file is part of the adventure php framework (APF) published under
 * http://adventure-php-framework.org.
 *
 * The APF is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * The APF 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the APF. If not, see http://www.gnu.org/licenses/lgpl-3.0.txt.
 * -->
 */
import('tools::html::taglib', 'iterator_taglib_item');
import('tools::html::taglib', 'iterator_taglib_addtaglib');
import('tools::html::taglib', 'iterator_taglib_getstring');
import('tools::html::taglib', 'iterator_taglib_placeholder');

import('tools::request', 'RequestHandler');

/**
 * @package tools::html::taglib
 * @class html_taglib_iterator
 *
 * Implements a taglib, that can display a list of objects (arrays with numeric offsets)
 * or associative arrays by defining a iterator with items and place holders within the
 * items. For convenience, the iterator can contain additional (html) content.
 * <p/>
 * Further, the
 * <pre><iterator:addtaglib /></pre>
 * tag allows you to include custom tags (e.g. for language dependent table headers). In
 * order to display language dependent values, you can use the
 * <pre><iterator:getstring /></pre>
 * tag.
 *
 * @author Christian Achatz
 * @version
 * Version 0.1, 01.06.2008<br />
 * Version 0.2, 04.06.2008 (Replaced __getIteratorItem() with key())<br />
 */
class html_taglib_iterator extends Document {

   /**
    * @protected
    * Data container. Array with numeric or associative offsets
    * or a list of objects.
    */
   protected $dataContainer = array();

   /**
    * @protected
    * Indicates, whether the iterator template should be displayed
    * at it's definition place (transform-on-place feature).
    */
   protected $transformOnPlace = false;

   /**
    * @protected
    * The iteration number
    */
   protected $iterationNumber = 0;

   /**
    * @public
    *
    * Defines the known taglibs. In this case, only the iterator item is parsed.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 01.06.2008<br />
    * Version 0.2, 09.08.2009 (Added the addtaglib tag to enable custom tags.)<br />
    */
   public function __construct() {
      $this->__TagLibs[] = new TagLib('tools::html::taglib', 'iterator', 'item');
      $this->__TagLibs[] = new TagLib('tools::html::taglib', 'iterator', 'addtaglib');
      $this->__TagLibs[] = new TagLib('tools::html::taglib', 'iterator', 'getstring');
      $this->__TagLibs[] = new TagLib('tools::html::taglib', 'iterator', 'placeholder');
   }

   /**
    * @public
    *
    * Implements the onParseTime method. Parses the iterator item taglib.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 01.06.2008<br />
    */
   public function onParseTime() {
      $this->__extractTagLibTags();
   }

   /**
    * @public
    *
    * This method allows you to fill the data container. Arrays with associative
    * keys are allowed as well as lists of objects (arrays with numeric offsets).
    *
    * @param array $data List of objects of an associative array.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 01.06.2008<br />
    */
   public function fillDataContainer($data) {
      $this->dataContainer = $data;
   }

   /**
    * @public
    *
    * Activates the transform-on-place feature for the iterator tag.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 01.06.2008<br />
    */
   public function transformOnPlace() {
      $this->transformOnPlace = true;
   }

   /**
    * @public
    *
    * Creates the output of the iterator. Can be called manually to use the output within
    * a document controller or surrounding taglib or automatically using the
    * transform-on-place feature.
    *
    * @return string String representation of the iterator object.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 01.06.2008<br />
    * Version 0.2, 04.06.2008 (Enhanced method)<br />
    * Version 0.3, 15.06.2008 (Bugfix: the item was not found using PHP5)<br />
    * Version 0.4, 09.08.2009 (Added new taglibs iterator:addtaglib and iterator:getstring due to request in forum)<br />
    */
   public function transformIterator() {

      $t = &Singleton::getInstance('BenchmarkTimer');
      /* @var $t BenchmarkTimer */
      $t->start('(html_taglib_iterator) ' . $this->getObjectId() . '::transformIterator()');

      $buffer = (string)'';

 
      if ($this->iterationNumber == 0) { 
          
         $this->iterationNumber = 1; // Default value 
               
         $pager = $this->getAttribute('pager', false);
          
         if ($pager != false) {
          
            // get pager-config
            $pagerConfig = $this->getConfiguration('modules::pager', 'pager');
            $pagerConfig = $pagerConfig->getSection($pager);
              
            // get the number of entries per page
            $entriesPerPage = RequestHandler::getValue(
               $pagerConfig->getValue('Pager.ParameterCountName'), 
               $pagerConfig->getValue('Pager.EntriesPerPage')
            ); 
              
            // get the number of the actual page
            $actualPage = RequestHandler::getValue(
               $pagerConfig->getValue('Pager.ParameterPageName'),
               1
            );
              
            $startNumber = $entriesPerPage * (--$actualPage);
            $startNumber++;
            $this->iterationNumber = $startNumber;  
                       
         }
          
      }


      // the iterator item must not always be the first child
      // of the current node!
      $itemObjectId = $this->getIteratorItemObjectId();
      $iteratorItem = &$this->__Children[$itemObjectId];
      /* @var $iteratorItem iterator_taglib_item */

      // define the dynamic getter.
      $getter = $iteratorItem->getAttribute('getter');

      // get the place holders
      $placeHolders = &$iteratorItem->getPlaceHolders();

      $itemCount = count($this->dataContainer);
      for ($i = 0; $i < $itemCount; $i++) {

         if (is_array($this->dataContainer[$i])) {

            foreach ($placeHolders as $objectId => $DUMMY) {
            
               // if we find a placeholder with IterationNamer as name-Attribute-Value set Iteration number
               if ($placeHolders[$objectId]->getAttribute('name') == 'IterationNumber') {
                   $placeHolders[$objectId]->setContent($this->iterationNumber);
                   $this->iterationNumber++;
                   continue;
               }
                           
               $placeHolders[$objectId]->setContent($this->dataContainer[$i][$placeHolders[$objectId]->getAttribute('name')]);
            }

            $buffer .= $iteratorItem->transform();

         } elseif (is_object($this->dataContainer[$i])) {

            foreach ($placeHolders as $objectId => $DUMMY) {
            
               // if we find a placeholder with IterationNamer as name-Attribute-Value set Iteration number
               if ($placeHolders[$objectId]->getAttribute('name') == 'IterationNumber') {
                   $placeHolders[$objectId]->setContent($this->iterationNumber);
                   $this->iterationNumber++;
                   continue;
               }
               
               // evaluate per-place-holder getter
               $localGetter = $placeHolders[$objectId]->getGetterMethod();
               if ($localGetter == null) {
                  $placeHolders[$objectId]->setContent($this->dataContainer[$i]->{
                                                       $getter
                                                       }(
                                                          $placeHolders[$objectId]->getAttribute('name'))
                  );
               } else {
                  $placeHolders[$objectId]->setContent($this->dataContainer[$i]->{
                                                       $localGetter
                                                       }());
               }
            }

            $buffer .= $iteratorItem->transform();

         } else {
            throw new InvalidArgumentException('[html_taglib_iterator::transformIterator()] '
                                               . 'Given list entry is not an array or object (' . $this->dataContainer[$i]
                                               . ')! The data container must contain a list of associative arrays or objects!',
               E_USER_WARNING);
         }

      }

      $t->stop('(html_taglib_iterator) ' . $this->__ObjectID . '::transformIterator()');

      // add the surrounding content of the iterator to enable the
      // user to define some html code as well.
      $iterator = str_replace('<' . $itemObjectId . ' />', $buffer, $this->__Content);

      // transform all other child tags except the iterator item(s)
      foreach ($this->__Children as $objectId => $DUMMY) {

         if (get_class($this->__Children[$objectId]) !== 'iterator_taglib_item') {
            $iterator = str_replace('<' . $objectId . ' />', $this->__Children[$objectId]->transform(), $iterator);
         }

      }

      return $iterator;

   }

   /**
    * @public
    *
    *  Implements the transform method for the iterator tag.
    *
    * @return string Content of the tag or an empty string.
    *
    * @author Christian Achatz
    * @version
    *  Version 0.1, 01.06.2008<br />
    */
   public function transform() {
      if ($this->transformOnPlace === true) {
         return $this->transformIterator();
      }

      return '';
   }

   /**
    * @protected
    *
    * Returns the first iterator item, that is found in the children list.
    * All other occurrences are ignored, due to the fact, that it is not
    * allowed to define more that one iterator item.
    *
    * @return string The iterator item's object id.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 09.08.2009<br />
    */
   protected function getIteratorItemObjectId() {

      foreach ($this->__Children as $objectId => $DUMMY) {
         if (get_class($this->__Children[$objectId]) === 'iterator_taglib_item') {
            return $objectId;
         }
      }

      // defining no iterator item is not allowed!
      throw new InvalidArgumentException('[html_taglib_iterator::getIteratorItemObjectId()] '
                                         . 'The definition for iterator "' . $this->getAttribute('name')
                                         . '" does not contain a iterator item, hence this is no legal iterator tag '
                                         . 'definition. Please refer to the documentation.', E_USER_ERROR);

   }

   /**
    * @public
    *
    * Fills a place holder within the iterator.
    *
    * @param string $name The name of the place holder to set.
    * @param string $value The value of the place holder.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 10.09.2010<br />
    */
   public function setPlaceHolder($name, $value) {
      $count = 0;
      foreach ($this->__Children as $objectId => $DUMMY) {
         if (get_class($this->__Children[$objectId]) == 'iterator_taglib_placeholder'
             && $this->__Children[$objectId]->getAttribute('name') === $name
         ) {
            $this->__Children[$objectId]->setContent($value);
            $count++;
         }
      }

      if ($count == 0 || count($this->__Children) == 0) {
         throw new InvalidArgumentException('[' . get_class($this) . '::setPlaceHolder()] No place '
                                            . 'holder object with name "' . $name . '" can be found within html:iterator tag '
                                            . 'with name "' . $this->getAttribute('name') . '" requested in document controller '
                                            . '"' . ($this->getParentObject()->getDocumentController()) . '"!', E_USER_ERROR);
      }
   }

   /**
    * @public
    *
    * This method is for concenient setting of multiple place holders. The applied
    * array must contain a structure like this:
    * <code>
    * array(
    *    'key-a' => 'value-a',
    *    'key-b' => 'value-b',
    *    'key-c' => 'value-c',
    *    'key-d' => 'value-d',
    *    'key-e' => 'value-e',
    * )
    * </code>
    * Thereby, the <em>key-*</em> offsets define the name of the place holders, their
    * values are used as the place holder's values.
    *
    * @param array $placeHolderValues Key-value-couples to fill place holders.
    *
    * @author Christian Achatz
    * @version
    * Version 0.1, 20.11.2010<br />
    */
   public function setPlaceHolders(array $placeHolderValues) {
      foreach ($placeHolderValues as $key => $value) {
         $this->setPlaceHolder($key, $value);
      }
   }
   
   /**
    * @public
    * 
    * Sets the value of the iterationNumber-Object-Attribute
    *
    * @param integer $number The number of iterationNumber
    *
    * @author Nicolas Pecher
    * @version
    * Version 0.1, 15.03.2012
    */
   public function setIterationNumber($number) {
       $this->iterationNumber(intval($number));
   }
}

?>
Folgende Code-Zeilen wurden geändert bzw. hinzugefügt:
68
154-184
207-211
223-227
393-395

Grüße
Nico


EDIT

Hier noch eine Live-Demo:
Login: http://www.webrex.org/test/acp
Username: Admin
Passwort: Demo
Nach dem Login auf Module klicken.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: iterator_taglib_item.php - 2 neue attribute für das Tag

Beitrag von dr.e. » 15.03.2012, 20:50:01

Hi,

klingt gut und sollten wir daher aufnehmen. Ich würde dazu gerne wie folgt vorgehen: du erhälst SVN-Zugriff und kannst die Änderungen dann direkt im 1.15er Zweig ausführen und die Doku-Files anpassen.

Schick mir bitte deinen sourceforge.net-Account, dann regle ich alles weiter.
Viele Grüße,
Christian

Gesperrt

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste