      1: <?php
      2: /*************************************************************************************/
      3: /*                                                                                   */
      4: /*      Thelia                                                                       */
      5: /*                                                                                   */
      6: /*      Copyright (c) OpenStudio                                                     */
      7: /*  email : info@thelia.net                                                      */
      8: /*      web : http://www.thelia.net                                                  */
      9: /*                                                                                   */
     10: /*      This program is free software; you can redistribute it and/or modify         */
     11: /*      it under the terms of the GNU General Public License as published by         */
     12: /*      the Free Software Foundation; either version 3 of the License                */
     13: /*                                                                                   */
     14: /*      This program is distributed in the hope that it will be useful,              */
     15: /*      but WITHOUT ANY WARRANTY; without even the implied warranty of               */
     16: /*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
     17: /*      GNU General Public License for more details.                                 */
     18: /*                                                                                   */
     19: /*      You should have received a copy of the GNU General Public License            */
     20: /*      along with this program. If not, see <http://www.gnu.org/licenses/>.     */
     21: /*                                                                                   */
     22: /*************************************************************************************/
     23:
     24: namespace Thelia\Tpex\Element;
     25:
     26: use Thelia\Tpex\Tools;
     27: use Thelia\Tpex\TpexToken;
     28: use Thelia\Tpex\Exception\ElementNotFoundException;
     29: use Thelia\Tpex\Exception\InvalidElementException;
     30: use Thelia\Tpex\Element\Loop\LoopIteration;
     31: use Thelia\Tpex\Element\Loop\LoopIterationCollection;
     32:
     33: use Symfony\Component\HttpFoundation\Request;
     34: use Symfony\Component\EventDispatcher\EventDispatcherInterface;
     35:
     36: class SimpleLoopElement extends BaseElement
     37: {
     38:
     39:     public $name;
     40:     public $args;
     41:     public $variables = array();
     42:     public $type;
     43:     public $empty = true;
     44:
     45:     protected $count = 1;
     46:
     47:     protected $loop = array();
     48:     protected $loopInstance = array();
     49:
     50:     protected $request;
     51:     protected $dispatcher;
     52:
     53:     public function __construct($name, array $loop, Request $request, EventDispatcherInterface $dispatcher)
     54:     {
     55:         $this->name = $name;
     56:         $this->loop = $loop;
     57:         $this->request = $request;
     58:         $this->dispatcher = $dispatcher;
     59:     }
     60:
     61:     public function setArgs($args)
     62:     {
     63:         $this->args = $args;
     64:     }
     65:
     66:     /**
     67:      *
     68:      * main function.
     69:      *
     70:      * execute the loop, make substitution and return the result.
     71:      *
     72:      * Result can be an empty string
     73:      *
     74:      * @param  array  $substitutions
     75:      * @return string
     76:      */
     77:     public function exec($substitutions = array())
     78:     {
     79:         $this->empty = true;
     80:
     81:         $result = '';
     82:
     83:         $args = $this->replace($substitutions, $this->args);
     84:
     85:         $loopIterateCollection = $this->prepareLoop($args);
     86:
     87:         if ($loopIterateCollection !== false) {
     88:             $this->empty = false;
     89:
     90:             foreach ($loopIterateCollection->getIteration() as $iteration) {
     91:
     92:                 if ($iteration->getPrefix() !== false) {
     93:                     $result .= $iteration->getPrfix();
     94:                 }
     95:
     96:                 if ($iteration->getReplacement() !== false) {
     97:                     $result .= $iteration->getReplacement();
     98:                 } else {
     99:                     $result .= $this->content->exec($iteration->getVarVal());
    100:                 }
    101:             }
    102:         }
    103:
    104:         return $result;
    105:     }
    106:
    107:     /**
    108:      *
    109:      *
    110:      * @param $args
    111:      * @return bool|\Thelia\Tpex\Element\Loop\LoopIterationCollection
    112:      */
    113:     protected function prepareLoop($args)
    114:     {
    115:         $var_template = "";
    116:         $this->count = 1;
    117:
    118:         usort($this->variables, array("Thelia\Tpex\Tools", "sortArray"));
    119:
    120:         foreach ($this->variables as $variable) {
    121:             if($var_template != '') $var_template .= TpexToken::COUPLE_SEP;
    122:
    123:             $var_template .= $variable . TpexToken::ASSIGN_SEP . "#" . $variable;
    124:         }
    125:
    126:         $var_template = TpexToken::START_MARK . $var_template . TpexToken::ITER_SEP;
    127:
    128:         $result = $this->execLoop($var_template, $args);
    129:
    130:         if (trim($result) != '') {
    131:
    132:             $loopIterationCollection = new LoopIterationCollection();
    133:
    134:             $rows = explode(TpexToken::ITER_SEP, $result);
    135:
    136:             $count = count($rows);
    137:
    138:             foreach($rows as $row) if($row == '') $count--;
    139:
    140:             foreach ($rows as $row) {
    141:                 if($row == '') continue;
    142:
    143:                 $iterate = new LoopIteration();
    144:
    145:                 if ($row[0] != TpexToken::START_MARK) {
    146:                     $start_pos = strpos($row, TpexToken::START_MARK);
    147:
    148:                     if ($start_pos === false) {
    149:                         $iterate->setReplacement($row);
    150:
    151:                         $loopIterationCollection->addIteration($iterate);
    152:
    153:                         //stop here
    154:                         continue;
    155:                     } else {
    156:                         $iterate->setPrefix(substr($row, 0, $start_pos));
    157:
    158:                         $row = substr($row, $start_pos + 1);
    159:                     }
    160:                 } else {
    161:                     $row = substr($row, 1);
    162:                 }
    163:
    164:                 $vars = explode(TpexToken::COUPLE_SEP, $row);
    165:
    166:                 foreach ($vars as $varval) {
    167:                     list($var, $value) = explode(TpexToken::ASSIGN_SEP, $varval);
    168:
    169:                     $iterate->addVarVal($var, $value);
    170:                 }
    171:
    172:                 $iterate->addVarVal("__COUNT__", $this->count++);
    173:
    174:                 $iterate->addVarVal('__NUMBER__', $count);
    175:
    176:                 $loopIterationCollection->addIteration($iterate);
    177:             }
    178:
    179:         } else {
    180:             $loopIterationCollection = false;
    181:         }
    182:
    183:         return $loopIterationCollection;
    184:     }
    185:
    186:     /**
    187:      *
    188:      * execute the loop and return the substitutions
    189:      *
    190:      * @param  string $text all the variable
    191:      * @param  string $args arguments loop
    192:      * @return string
    193:      */
    194:     protected function execLoop($text, $args)
    195:     {
    196:         $type = Tools::extractValueParam("type", $args);
    197:
    198:         $loop = $this->constructLoop($type);
    199:
    200:         return $loop->exec($text, $args);
    201:     }
    202:
    203:     /**
    204:      *
    205:      * find the loop class with his name and construct an instance of this class
    206:      *
    207:      * @param  string                                          $name
    208:      * @return \Thelia\Tpex\Element\Loop\BaseLoop
    209:      * @throws \Thelia\Tpex\Exception\InvalidElementException
    210:      * @throws \Thelia\Tpex\Exception\ElementNotFoundException
    211:      */
    212:     protected function constructLoop($name)
    213:     {
    214:
    215:         if (! isset($this->loop[$name])) {
    216:             throw new ElementNotFoundException(sprintf("%s loop does not exists", $name));
    217:         }
    218:
    219:         $class = new \ReflectionClass($this->loop[$name]);
    220:
    221:         if ($class->isSubclassOf("Thelia\Tpex\Element\Loop\BaseLoop") === false) {
    222:             throw new InvalidElementException(sprintf("%s Loop class have to extends Thelia\Tpex\Element\Loop\BaseLoop",
    223:                 $name));
    224:         }
    225:
    226:         return $class->newInstance($this->request, $this->dispatcher);
    227:     }
    228:
    229:     public function addVar($token)
    230:     {
    231:         if (!in_array($token, $this->variables)) {
    232:             $this->variables[] = $token;
    233:         }
    234:     }
    235:
    236:     public function addContent($content)
    237:     {
    238:         $this->content = $content;
    239:     }
    240:
    241:     public function type()
    242:     {
    243:         return TpexToken::TPEX_SIMPLE_LOOP;
    244:     }
    245: }
    246: