diff --git a/core/lib/Thelia/Controller/Admin/CustomerController.php b/core/lib/Thelia/Controller/Admin/CustomerController.php index f7766eac8..784790c2e 100644 --- a/core/lib/Thelia/Controller/Admin/CustomerController.php +++ b/core/lib/Thelia/Controller/Admin/CustomerController.php @@ -171,7 +171,6 @@ class CustomerController extends AbstractCrudController { return $this->render('customers', array_merge(array( 'customer_order' => $currentOrder, - 'display_customer' => 20, 'page' => $this->getRequest()->get('page', 1) ), $customParams) ); diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index df57077de..5841d8461 100644 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -14,10 +14,13 @@ namespace Thelia\Core\Template\Element; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\ModelCriteria; +use Propel\Runtime\Collection\ObjectCollection; +use Propel\Runtime\Util\PropelModelPager; use Symfony\Component\DependencyInjection\ContainerInterface; use Thelia\Core\Security\SecurityContext; use Thelia\Core\Template\Element\Exception\LoopException; use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Core\Translation\Translator; use Thelia\Type\EnumListType; use Thelia\Type\EnumType; use Thelia\Type\TypeCollection; @@ -53,8 +56,11 @@ abstract class BaseLoop protected $timestampable = false; protected $versionable = false; - private static $cacheLoopResult = array(); - private static $cacheCount = array(); + /** @var Translator */ + protected $translator = null; + + private static $cacheLoopResult = []; + private static $cacheCount = []; /** * Create a new Loop @@ -70,6 +76,7 @@ abstract class BaseLoop $this->request = $container->get('request'); $this->dispatcher = $container->get('event_dispatcher'); $this->securityContext = $container->get('thelia.securityContext'); + $this->translator = $container->get("thelia.translator"); $this->args = $this->getArgDefinitions()->addArguments($this->getDefaultArgs(), false); } @@ -81,53 +88,54 @@ abstract class BaseLoop */ protected function getDefaultArgs() { - $defaultArgs = array( + $defaultArgs = [ Argument::createBooleanTypeArgument('backend_context', false), Argument::createBooleanTypeArgument('force_return', false), Argument::createAnyTypeArgument('type'), - ); + ]; if (true === $this->countable) { - $defaultArgs = array_merge($defaultArgs, array( - Argument::createIntTypeArgument('offset', 0), - Argument::createIntTypeArgument('page'), - Argument::createIntTypeArgument('limit', PHP_INT_MAX), - )); + $defaultArgs = array_merge($defaultArgs, [ + Argument::createIntTypeArgument('offset', 0), + Argument::createIntTypeArgument('page'), + Argument::createIntTypeArgument('limit', PHP_INT_MAX), + ]); } if ($this instanceof SearchLoopInterface) { - $defaultArgs = array_merge($defaultArgs, array( - Argument::createAnyTypeArgument('search_term'), - new Argument( - 'search_in', - new TypeCollection( - new EnumListType($this->getSearchIn()) - ) - ), - new Argument( - 'search_mode', - new TypeCollection( - new EnumType(array( - SearchLoopInterface::MODE_ANY_WORD, - SearchLoopInterface::MODE_SENTENCE, - SearchLoopInterface::MODE_STRICT_SENTENCE, - )) + + $defaultArgs = array_merge($defaultArgs, [ + Argument::createAnyTypeArgument('search_term'), + new Argument( + 'search_in', + new TypeCollection( + new EnumListType($this->getSearchIn()) + ) ), - SearchLoopInterface::MODE_STRICT_SENTENCE - ) - )); + new Argument( + 'search_mode', + new TypeCollection( + new EnumType([ + SearchLoopInterface::MODE_ANY_WORD, + SearchLoopInterface::MODE_SENTENCE, + SearchLoopInterface::MODE_STRICT_SENTENCE, + ]) + ), + SearchLoopInterface::MODE_STRICT_SENTENCE + ) + ]); } return $defaultArgs; } /** - * Provides a getter to loop parameters + * Provides a getter to loop parameter values * - * @param string $name the methode name (only getArgname is supported) - * @param $arguments this parameter is ignored + * @param string $name the method name (only getArgname is supported) + * @param mixed $arguments this parameter is ignored * - * @return null + * @return mixed the argument value * @throws \InvalidArgumentException if the parameter is unknown or the method name is not supported. */ public function __call($name, $arguments) @@ -137,10 +145,12 @@ abstract class BaseLoop // camelCase to underscore: getNotEmpty -> not_empty $argName = strtolower(preg_replace('/([^A-Z])([A-Z])/', "$1_$2", substr($name, 3))); - return $this->getArg($argName)->getValue(); + return $this->getArgValue($argName); } - throw new \InvalidArgumentException(sprintf("Unsupported magic method %s. only getArgname() is supported.", $name)); + throw new \InvalidArgumentException( + $this->translator->trans("Unsupported magic method %name. only getArgname() is supported.", ['%name' => $name]) + ); } /** @@ -148,12 +158,12 @@ abstract class BaseLoop * * @param array $nameValuePairs a array of name => value pairs. The name is the name of the argument. * - * @throws \InvalidArgumentException if somùe argument values are missing, or invalid + * @throws \InvalidArgumentException if some argument values are missing, or invalid */ public function initializeArgs(array $nameValuePairs) { - $faultActor = array(); - $faultDetails = array(); + $faultActor = []; + $faultDetails = []; $loopType = isset($nameValuePairs['type']) ? $nameValuePairs['type'] : "undefined"; $loopName = isset($nameValuePairs['name']) ? $nameValuePairs['name'] : "undefined"; @@ -167,19 +177,38 @@ abstract class BaseLoop /* check if mandatory */ if ($value === null && $argument->mandatory) { $faultActor[] = $argument->name; - $faultDetails[] = sprintf('"%s" parameter is missing in loop type: %s, name: %s', $argument->name, $loopType, $loopName); + $faultDetails[] = $this->translator->trans( + '"%param" parameter is missing in loop type: %type, name: %name', [ + '%param' => $argument->name, + '%type' => $loopType, + '%name' => $loopName + ] + ); } else if ($value === '') { if (!$argument->empty) { /* check if empty */ $faultActor[] = $argument->name; - $faultDetails[] = sprintf('"%s" parameter cannot be empty in loop type: %s, name: %s', $argument->name, $loopType, $loopName); + $faultDetails[] = $this->translator->trans( + '"%param" parameter cannot be empty in loop type: %type, name: %name', [ + '%param' => $argument->name, + '%type' => $loopType, + '%name' => $loopName + ] + ); } } elseif ($value !== null && !$argument->type->isValid($value)) { /* check type */ $faultActor[] = $argument->name; - $faultDetails[] = sprintf('Invalid value "%s" for "%s" argument in loop type: %s, name: %s', $value, $argument->name, $loopType, $loopName); + $faultDetails[] = $this->translator->trans( + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name', [ + '%value' => $value, + '%param' => $argument->name, + '%type' => $loopType, + '%name' => $loopName + ] + ); } else { - /* set default */ + /* set default value */ /* did it as last checking for we consider default value is acceptable no matter type or empty restriction */ if ($value === null) { $value = $argument->default; @@ -189,9 +218,9 @@ abstract class BaseLoop } } - if (!empty($faultActor)) { - + if (! empty($faultActor)) { $complement = sprintf('[%s]', implode(', ', $faultDetails)); + throw new \InvalidArgumentException($complement); } } @@ -201,15 +230,17 @@ abstract class BaseLoop * * @param string $argumentName the argument name * + * @return Argument the loop argument. * @throws \InvalidArgumentException if argument is not found in loop argument list - * @return Argument the loop argument. */ protected function getArg($argumentName) { $arg = $this->args->get($argumentName); if ($arg === null) - throw new \InvalidArgumentException("Undefined loop argument '$argumentName'"); + throw new \InvalidArgumentException( + $this->translator->trans('Undefined loop argument "%name"', ['%name' => $argumentName]) + ); return $arg; } @@ -220,7 +251,7 @@ abstract class BaseLoop * @param string $argumentName the argument name * * @throws \InvalidArgumentException if argument is not found in loop argument list - * @return Argument the loop argument. + * @return mixed the loop argument value */ protected function getArgValue($argumentName) { @@ -228,20 +259,24 @@ abstract class BaseLoop } /** - * @param ModelCriteria $search - * @param null $pagination + * @param ModelCriteria $search the search request + * @param PropelModelPager $pagination the pagination part * - * @return array|mixed|\PropelModelPager|\PropelObjectCollection + * @return array|PropelModelPager|ObjectCollection + * @throws \InvalidArgumentException if the search mode is undefined. */ protected function search(ModelCriteria $search, &$pagination = null) { if (false === $this->countable) { return $search->find(); } + if ($this instanceof SearchLoopInterface) { - $searchTerm = $this->getSearch_term(); - $searchIn = $this->getSearch_in(); - $searchMode = $this->getSearch_mode(); + + $searchTerm = $this->getArgValue('search_term'); + $searchIn = $this->getArgValue('search_in'); + $searchMode = $this->getArgValue('search_mode'); + if (null !== $searchTerm && null !== $searchIn) { switch ($searchMode) { @@ -256,6 +291,10 @@ abstract class BaseLoop case SearchLoopInterface::MODE_STRICT_SENTENCE: $searchCriteria = Criteria::EQUAL; break; + default: + throw new \InvalidArgumentException( + $this->translator->trans("Undefined search mode '%mode'", ['%mode' => $searchMode]) + ); } $this->doSearch($search, $searchTerm, $searchIn, $searchCriteria); @@ -269,24 +308,31 @@ abstract class BaseLoop } } - protected function searchArray(array $search, &$pagination = null) + protected function searchArray(array $search) { if (false === $this->countable) { return $search; } + + $limit = intval($this->getArgValue('limit')); + $offset = intval($this->getArgValue('offset')); + if ($this->getArgValue('page') !== null) { - $nbPage = ceil(count($search)/$this->getArgValue('limit')); - if ($this->getArgValue('page') > $nbPage || $this->getArgValue('page') <= 0) { - return array(); + $pageNum = intval($this->getArgValue('page')); + + $totalPageCount = ceil(count($search) / $limit); + + if ($pageNum > $totalPageCount || $pageNum <= 0) { + return []; } - $firstItem = ($this->getArgValue('page')-1) * $this->getArgValue('limit') + 1; + $firstItem = ($pageNum - 1) * $limit + 1; - return array_slice($search, $firstItem, $firstItem + $this->getArgValue('limit'), false); + return array_slice($search, $firstItem, $firstItem + $limit, false); } else { - return array_slice($search, $this->getArgValue('offset'), $this->getArgValue('limit'), false); + return array_slice($search, $offset, $limit, false); } } @@ -294,30 +340,36 @@ abstract class BaseLoop /** * @param ModelCriteria $search * - * @return array|mixed|\PropelObjectCollection + * @return ObjectCollection */ protected function searchWithOffset(ModelCriteria $search) { - if ($this->getArgValue('limit') >= 0) { - $search->limit($this->getArgValue('limit')); + $limit = intval($this->getArgValue('limit')); + + if ($limit >= 0) { + $search->limit($limit); } - $search->offset($this->getArgValue('offset')); + + $search->offset(intval($this->getArgValue('offset'))); return $search->find(); } /** * @param ModelCriteria $search - * @param $pagination + * @param PropelModelPager $pagination * - * @return array|\Propel\Runtime\Util\PropelModelPager + * @return array|PropelModelPager */ protected function searchWithPagination(ModelCriteria $search, &$pagination) { - $pagination = $search->paginate($this->getArgValue('page'), $this->getArgValue('limit')); + $page = intval($this->getArgValue('page')); + $limit = intval($this->getArgValue('limit')); - if ($this->getArgValue('page') > $pagination->getLastPage()) { - return array(); + $pagination = $search->paginate($page, $limit); + + if ($page > $pagination->getLastPage()) { + return []; } else { return $pagination; } @@ -350,18 +402,21 @@ abstract class BaseLoop } /** - * @param $pagination + * @param PropelModelPager $pagination + * * @return LoopResult */ public function exec(&$pagination) { $hash = $this->args->getHash(); if (false === isset(self::$cacheLoopResult[$hash])) { + + $results = []; + if ($this instanceof PropelSearchLoopInterface) { $searchModelCriteria = $this->buildModelCriteria(); - if (null === $searchModelCriteria) { - $results = array(); - } else { + + if (null !== $searchModelCriteria) { $results = $this->search( $searchModelCriteria, $pagination @@ -369,13 +424,9 @@ abstract class BaseLoop } } elseif ($this instanceof ArraySearchLoopInterface) { $searchArray = $this->buildArray(); - if (null === $searchArray) { - $results = array(); - } else { - $results = $this->searchArray( - $searchArray, - $pagination - ); + + if (null !== $searchArray) { + $results = $this->searchArray($searchArray); } } @@ -405,30 +456,49 @@ abstract class BaseLoop * - ArraySearchLoopInterface */ $searchInterface = false; + if ($this instanceof PropelSearchLoopInterface) { if (true === $searchInterface) { - throw new LoopException('Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', LoopException::MULTIPLE_SEARCH_INTERFACE); + throw new LoopException( + $this->translator->trans( + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' + ), + LoopException::MULTIPLE_SEARCH_INTERFACE); } $searchInterface = true; } + if ($this instanceof ArraySearchLoopInterface) { if (true === $searchInterface) { - throw new LoopException('Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', LoopException::MULTIPLE_SEARCH_INTERFACE); + throw new LoopException( + $this->translator->trans( + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' + ), + LoopException::MULTIPLE_SEARCH_INTERFACE); } $searchInterface = true; } if (false === $searchInterface) { - throw new LoopException('Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', LoopException::SEARCH_INTERFACE_NOT_FOUND); + throw new LoopException( + $this->translator->trans( + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' + ), + LoopException::SEARCH_INTERFACE_NOT_FOUND); } /* Only PropelSearch allows timestamp and version */ if (!$this instanceof PropelSearchLoopInterface) { if (true === $this->timestampable) { - throw new LoopException("Loop must implements 'PropelSearchLoopInterface' to be timestampable", LoopException::NOT_TIMESTAMPED); + throw new LoopException( + $this->translator->trans("Loop must implements 'PropelSearchLoopInterface' to be timestampable"), + LoopException::NOT_TIMESTAMPED); } + if (true === $this->versionable) { - throw new LoopException("Loop must implements 'PropelSearchLoopInterface' to be versionable", LoopException::NOT_VERSIONED); + throw new LoopException( + $this->translator->trans("Loop must implements 'PropelSearchLoopInterface' to be versionable"), + LoopException::NOT_VERSIONED); } } } @@ -441,15 +511,14 @@ abstract class BaseLoop abstract public function parseResults(LoopResult $loopResult); /** - * - * define all args used in your loop - * + * Definition of loop arguments * * example : * * public function getArgDefinitions() * { * return new ArgumentCollection( + * * Argument::createIntListTypeArgument('id'), * new Argument( * 'ref', @@ -459,14 +528,7 @@ abstract class BaseLoop * ), * Argument::createIntListTypeArgument('category'), * Argument::createBooleanTypeArgument('new'), - * Argument::createBooleanTypeArgument('promo'), - * Argument::createFloatTypeArgument('min_price'), - * Argument::createFloatTypeArgument('max_price'), - * Argument::createIntTypeArgument('min_stock'), - * Argument::createFloatTypeArgument('min_weight'), - * Argument::createFloatTypeArgument('max_weight'), - * Argument::createBooleanTypeArgument('current'), - * + * ... * ); * } * @@ -474,4 +536,4 @@ abstract class BaseLoop */ abstract protected function getArgDefinitions(); -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php index 40dd04330..3658f652b 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php @@ -12,16 +12,20 @@ namespace Thelia\Core\Template\Smarty\Plugins; +use Propel\Runtime\Util\PropelModelPager; use Symfony\Component\DependencyInjection\ContainerInterface; use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; use Thelia\Core\Template\Element\Exception\ElementNotFoundException; use Thelia\Core\Template\Element\Exception\InvalidElementException; +use Thelia\Core\Translation\Translator; class TheliaLoop extends AbstractSmartyPlugin { + /** @var PropelModelPager[] */ protected static $pagination = null; protected $loopDefinition = array(); @@ -30,10 +34,15 @@ class TheliaLoop extends AbstractSmartyPlugin protected $dispatcher; protected $securityContext; + /** @var Translator */ + protected $translator; + /** @var ContainerInterface Service Container */ protected $container = null; + /** @var LoopResult[] */ protected $loopstack = array(); + protected $varstack = array(); /** @@ -46,31 +55,43 @@ class TheliaLoop extends AbstractSmartyPlugin $this->request = $container->get('request'); $this->dispatcher = $container->get('event_dispatcher'); $this->securityContext = $container->get('thelia.securityContext'); + $this->translator = $container->get("thelia.translator"); } /** - * @param $loopId - * - * @return \PropelModelPager + * @param string $loopName + * @return PropelModelPager + * @throws \InvalidArgumentException if no pagination was found for loop */ public static function getPagination($loopName) { if (array_key_exists($loopName, self::$pagination)) { return self::$pagination[$loopName]; } else { - throw new \InvalidArgumentException("Loop $loopName is not defined"); + throw new \InvalidArgumentException( + Translator::getInstance()->trans("No pagination currently defined for loop name '%name'", ['%name' => $loopName ]) + ); } } /** * Process the count function: executes a loop and return the number of items found + * + * @param array $params parameters array + * @param \Smarty_Internal_Template $template + * + * @return int the item count + * @throws \InvalidArgumentException if a parameter is missing + * */ - public function theliaCount($params, $template) + public function theliaCount($params, /** @noinspection PhpUnusedParameterInspection */ $template) { $type = $this->getParam($params, 'type'); if (null == $type) { - throw new \InvalidArgumentException("Missing 'type' parameter in count arguments"); + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'type' parameter in {count} loop arguments") + ); } $loop = $this->createLoopInstance($params); @@ -83,31 +104,39 @@ class TheliaLoop extends AbstractSmartyPlugin /** * Process {loop name="loop name" type="loop type" ... } ... {/loop} block * - * @param unknown $params - * @param unknown $content - * @param unknown $template - * @param unknown $repeat + * @param array $params + * @param string $content + * @param \Smarty_Internal_Template $template + * @param boolean $repeat + * * @throws \InvalidArgumentException - * @return string + * + * @return void|string */ public function theliaLoop($params, $content, $template, &$repeat) { $name = $this->getParam($params, 'name'); if (null == $name) { - throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments"); + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'name' parameter in loop arguments") + ); } $type = $this->getParam($params, 'type'); if (null == $type) { - throw new \InvalidArgumentException("Missing 'type' parameter in loop arguments"); + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'type' parameter in loop arguments") + ); } if ($content === null) { // Check if a loop with the same name exists in the current scope, and abort if it's the case. if (array_key_exists($name, $this->varstack)) { - throw new \InvalidArgumentException("A loop named '$name' already exists in the current scope."); + throw new \InvalidArgumentException( + $this->translator->trans("A loop named '%name' already exists in the current scope.", ['%name' => $name]) + ); } $loop = $this->createLoopInstance($params); @@ -120,7 +149,7 @@ class TheliaLoop extends AbstractSmartyPlugin $this->loopstack[$name] = $loopResults; - // Pas de résultat ? la boucle est terminée, ne pas évaluer le contenu. + // No results ? The loop is terminated, do not evaluate loop text. if ($loopResults->isEmpty()) $repeat = false; } else { @@ -173,52 +202,56 @@ class TheliaLoop extends AbstractSmartyPlugin return $content; } + + return ''; } /** * Process {elseloop rel="loopname"} ... {/elseloop} block * - * @param unknown $params - * @param unknown $content - * @param unknown $template - * @param unknown $repeat - * @return Ambigous + * @param array $params loop parameters + * @param string $content loop text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * @return string the loop output */ - public function theliaElseloop($params, $content, $template, &$repeat) + public function theliaElseloop($params, $content, /** @noinspection PhpUnusedParameterInspection */ $template, &$repeat) { - - // When encoutering close tag, check if loop has results. + // When encountering close tag, check if loop has results. if ($repeat === false) { - return $this->checkEmptyLoop($params, $template) ? $content : ''; + return $this->checkEmptyLoop($params) ? $content : ''; } + + return ''; } /** * Process {ifloop rel="loopname"} ... {/ifloop} block * - * @param unknown $params - * @param unknown $content - * @param unknown $template - * @param unknown $repeat - * @return Ambigous + * @param array $params loop parameters + * @param string $content loop text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * @return string the loop output */ - public function theliaIfLoop($params, $content, $template, &$repeat) + public function theliaIfLoop($params, $content, /** @noinspection PhpUnusedParameterInspection */ $template, &$repeat) { // When encountering close tag, check if loop has results. if ($repeat === false) { - return $this->checkEmptyLoop($params, $template) ? '' : $content; + return $this->checkEmptyLoop($params) ? '' : $content; } + + return ''; } /** * Process {pageloop rel="loopname"} ... {/pageloop} block * - * @param $params - * @param $content - * @param $template - * @param $repeat - * - * @return string + * @param array $params loop parameters + * @param string $content loop text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * @return string the loop output * @throws \InvalidArgumentException */ public function theliaPageLoop($params, $content, $template, &$repeat) @@ -226,73 +259,102 @@ class TheliaLoop extends AbstractSmartyPlugin $loopName = $this->getParam($params, 'rel'); if (null == $loopName) - throw new \InvalidArgumentException("Missing 'rel' parameter in page loop"); + throw new \InvalidArgumentException($this->translator->trans("Missing 'rel' parameter in page loop")); // Find pagination $pagination = self::getPagination($loopName); - if ($pagination === null) { // loop has no result + if ($pagination === null || $pagination->getNbResults() == 0) { + // No need to paginate return ''; } - if ($pagination->getNbResults() == 0) { - return ''; - } + $startPage = intval($this->getParam($params, 'start-page', 1)); + $displayedPageCount = intval($this->getParam($params, 'limit', 10)); - $nbPage = $this->getParam($params, 'numPage', 10); - $maxPage = $pagination->getLastPage(); + if (intval($displayedPageCount) == 0) $displayedPageCount = PHP_INT_MAX; + $totalPageCount = $pagination->getLastPage(); if ($content === null) { - $page = $pagination->getPage(); - if ($maxPage > ($page + $nbPage)) { - $end = $page + $nbPage; - } else { - $end = $maxPage; + + // The current page + $currentPage = $pagination->getPage(); + + // Get the start page. + if ($totalPageCount > $displayedPageCount) { + $startPage = $currentPage - round($displayedPageCount / 2); + + if ($startPage < 0) $startPage = 1; } - $template->assign('PREV', $page > 1 ? $page-1: $page); - $template->assign('NEXT', $page < $maxPage ? $page+1 : $maxPage); - $template->assign('END', $end); - $template->assign('LAST', $pagination->getLastPage()); + + // This is the iterative page number, the one we're going to increment in this loop + $iterationPage = $startPage; + + // The last displayed page number + $endPage = $startPage + $displayedPageCount - 1; + + if ($endPage > $totalPageCount) { + $endPage = $totalPageCount; + } + + // The first displayed page number + $template->assign('START' , $startPage); + // The previous page number + $template->assign('PREV' , $currentPage > 1 ? $currentPage-1 : $currentPage); + // The next page number + $template->assign('NEXT' , $currentPage < $totalPageCount ? $currentPage+1 : $totalPageCount); + // The last displayed page number + $template->assign('END' , $endPage); + // The overall last page + $template->assign('LAST' , $totalPageCount); } else { - $page = $template->getTemplateVars('PAGE'); - $page++; + $iterationPage = $template->getTemplateVars('PAGE'); + + $iterationPage++; } + if ($iterationPage <= $template->getTemplateVars('END')) { + // The iterative page number + $template->assign('PAGE', $iterationPage); - if ($page <= $template->getTemplateVars('END')) { - $template->assign('PAGE', $page); + // The overall current page number $template->assign('CURRENT', $pagination->getPage()); - $repeat = true; } if ($content !== null) { return $content; } + + return ''; } /** * Check if a loop has returned results. The loop shoud have been executed before, or an * InvalidArgumentException is thrown * - * @param unknown $params - * @param unknown $template + * @param array $params + * + * @return boolean true if the loop is empty * @throws \InvalidArgumentException */ - protected function checkEmptyLoop($params, $template) + protected function checkEmptyLoop($params) { $loopName = $this->getParam($params, 'rel'); if (null == $loopName) - throw new \InvalidArgumentException("Missing 'rel' parameter in ifloop/elseloop arguments"); + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'rel' parameter in ifloop/elseloop arguments") + ); - if (! isset($this->loopstack[$loopName])) { - throw new \InvalidArgumentException("Loop $loopName is not defined."); - } + if (! isset($this->loopstack[$loopName])) + throw new \InvalidArgumentException( + $this->translator->trans("Related loop name '%name'' is not defined.", ['%name' => $loopName]) + ); return $this->loopstack[$loopName]->isEmpty(); } @@ -309,14 +371,16 @@ class TheliaLoop extends AbstractSmartyPlugin $type = strtolower($smartyParams['type']); if (! isset($this->loopDefinition[$type])) { - throw new ElementNotFoundException(sprintf("'%s' loop type does not exists", $type)); + throw new ElementNotFoundException( + $this->translator->trans("Loop type '%type' is not defined.", ['%type' => $type])); } $class = new \ReflectionClass($this->loopDefinition[$type]); if ($class->isSubclassOf("Thelia\Core\Template\Element\BaseLoop") === false) { - throw new InvalidElementException(sprintf("'%s' Loop class should extends Thelia\Core\Template\Element\BaseLoop", - $type)); + throw new InvalidElementException( + $this->translator->trans("'%type' loop class should extends Thelia\Core\Template\Element\BaseLoop", ['%type' => $type]) + ); } $loop = $class->newInstance( @@ -350,7 +414,12 @@ class TheliaLoop extends AbstractSmartyPlugin { foreach ($loopDefinition as $name => $className) { if (array_key_exists($name, $this->loopDefinition)) { - throw new \InvalidArgumentException(sprintf("%s loop name already exists for %s class name", $name, $className)); + throw new \InvalidArgumentException( + $this->translator->trans("The loop name '%name' is already defined in %className class", [ + '%name' => $name, + '%className' => $className + ]) + ); } $this->loopDefinition[$name] = $className; @@ -360,7 +429,7 @@ class TheliaLoop extends AbstractSmartyPlugin /** * Defines the various smarty plugins hendled by this class * - * @return an array of smarty plugin descriptors + * @return SmartyPluginDescriptor[] smarty plugin descriptors */ public function getPluginDescriptors() { diff --git a/core/lib/Thelia/Module/AbstractDeliveryModule.php b/core/lib/Thelia/Module/AbstractDeliveryModule.php index c8477bec1..e59ed5a39 100644 --- a/core/lib/Thelia/Module/AbstractDeliveryModule.php +++ b/core/lib/Thelia/Module/AbstractDeliveryModule.php @@ -12,10 +12,8 @@ namespace Thelia\Module; -use Thelia\Model\Country; -use Thelia\Module\Exception\DeliveryException; - abstract class AbstractDeliveryModule extends BaseModule implements DeliveryModuleInterface { - + // This class is the base class for delivery modules + // It may contains common methods in the future. } \ No newline at end of file diff --git a/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php b/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php index dabee6c5e..69505ce62 100755 --- a/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php +++ b/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php @@ -18,6 +18,7 @@ use Thelia\Core\HttpFoundation\Request; use Thelia\Core\Security\SecurityContext; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Thelia\Core\HttpFoundation\Session\Session; +use Thelia\Core\Translation\Translator; use Thelia\Tools\URL; use Thelia\TaxEngine\TaxEngine; @@ -95,6 +96,7 @@ abstract class BaseLoopTestor extends \PHPUnit_Framework_TestCase $this->container->set('request', $request); $this->container->set('event_dispatcher', new EventDispatcher()); + $this->container->set('thelia.translator',new Translator($this->container)); $this->container->set('thelia.securityContext', new SecurityContext($request)); $this->container->set('router.admin', $stubRouterAdmin); $this->container->set('thelia.url.manager', new URL($this->container)); diff --git a/templates/backOffice/default/configs/variables.conf b/templates/backOffice/default/configs/variables.conf index d80dba5f7..f41a1b61e 100644 --- a/templates/backOffice/default/configs/variables.conf +++ b/templates/backOffice/default/configs/variables.conf @@ -1,5 +1,6 @@ #order max_displayed_orders = 20 +max_displayed_customers = 20 #order status order_not_paid = 'warning' diff --git a/templates/backOffice/default/customers.html b/templates/backOffice/default/customers.html index 9a16031b0..f839a24ea 100644 --- a/templates/backOffice/default/customers.html +++ b/templates/backOffice/default/customers.html @@ -120,7 +120,7 @@ - {loop name="customer_list" type="customer" current="false" visible="*" order=$customer_order backend_context="1" page=$page limit=$display_customer} + {loop name="customer_list" type="customer" current="false" visible="*" order=$customer_order backend_context="1" page=$page limit=#max_displayed_customers#} {assign "lastOrderDate" ''} {assign "lastOrderAmount" ''} {assign "lastOrderCurrency" ''} @@ -179,34 +179,13 @@ + {include + file = "includes/pagination.html" -
-
    - - {if $page != 1} -
  • «
  • - {/if} - {pageloop rel="customer_list" numPage="20"} - {if $PAGE == $CURRENT && $PAGE > 2} -
  • - {/if} - - {if $PAGE != $CURRENT} -
  • {$PAGE}
  • - - {else} -
  • {$PAGE}
  • - {/if} - - {if $PAGE == $END && $PAGE < $LAST} -
  • - {/if} - {/pageloop} - {if $LAST > $CURRENT} -
  • »
  • - {/if} -
-
+ loop_ref = "customer_list" + max_page_count = 10 + page_url = "{url path="/admin/customers" customer_order=$customer_order}" + } diff --git a/templates/backOffice/default/includes/pagination.html b/templates/backOffice/default/includes/pagination.html new file mode 100644 index 000000000..fd560ef79 --- /dev/null +++ b/templates/backOffice/default/includes/pagination.html @@ -0,0 +1,69 @@ +{* +A generic pager for thelia back-office + +Parameters : + +$loop_ref: the name of the related loop +$max_page_count : maximum number of pages to display +$page_url : the URL of the page. The parameter page=x is appended to this URL. + +*} + +{* Prepare the URL so that the page=x parameter coumd be safely appended *} + +{if strpos($page_url, '?')} + {$page_url="$page_url&"} +{else} + {$page_url="$page_url?"} +{/if} + +
+
    + {pageloop rel=$loop_ref limit=$max_page_count} + {$prev_page = $PREV} + {$next_page = $NEXT} + {$last_page = $LAST} + {$has_prev = $CURRENT > 1} + {$has_next = $CURRENT < $LAST} + + {$has_pages_after = $END < $LAST && $LAST > $max_page_count} + {$has_pages_before = $START > 1} + + {if $PAGE == $START} + {if $has_prev} +
  • «
  • +
  • + + {if $has_pages_before} +
  • + {/if} + + {else} +
  • «
  • +
  • + {/if} + {/if} + + {if $PAGE != $CURRENT} +
  • {$PAGE}
  • + {else} +
  • {$PAGE}
  • + {/if} + + {if $PAGE == $END} + {if $has_next} + {if $has_pages_after} +
  • + {/if} + +
  • +
  • »
  • + + {else} +
  • +
  • »
  • + {/if} + {/if} + {/pageloop} +
+
diff --git a/templates/backOffice/default/orders.html b/templates/backOffice/default/orders.html index 75bc22861..721ee459c 100644 --- a/templates/backOffice/default/orders.html +++ b/templates/backOffice/default/orders.html @@ -150,32 +150,13 @@ + {include + file = "includes/pagination.html" -
-
    - {if $order_page != 1} -
  • «
  • - {else} -
  • «
  • - {/if} - - {pageloop rel="order-list"} - {if $PAGE != $CURRENT} -
  • {$PAGE}
  • - - {else} -
  • {$PAGE}
  • - {/if} - - - {/pageloop} - {if $PAGE == $LAST && $LAST != $CURRENT} -
  • »
  • - {else} -
  • »
  • - {/if} -
-
+ loop_ref = "order-list" + max_page_count = 10 + page_url = "{url path="/admin/orders" orders_order=$orders_order}" + }