Fixed TheliaLoop Smarty plugin (lopp imbrication was broken)

This commit is contained in:
franck
2013-09-04 19:02:26 +02:00
parent 31c074d492
commit d3a287333e
17 changed files with 484 additions and 17 deletions

View File

@@ -0,0 +1,157 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program 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 General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Action;
use Thelia\Core\Event\BaseChangePositionEvent;
trait PositionManagementTrait {
const POSITION_UP
/**
* Changes object position, selecting absolute ou relative change.
*
* @param BaseChangePositionEvent $event
*/
public function changePosition(BaseChangePositionEvent $event)
{
if ($event->getMode() == BaseChangePositionEvent::POSITION_ABSOLUTE)
return $this->changeAbsolutePosition($event);
else
return $this->exchangePosition($event);
}
/**
* Move up or down a object
*
* @param BaseChangePositionEvent $event
*/
protected function exchangePosition(BaseChangePositionEvent $event)
{
$object = CategoryQuery::create()->findPk($event->getCategoryId());
if ($object !== null) {
// The current position of the object
$my_position = $object->getPosition();
// Find object to exchange position with
$search = CategoryQuery::create()
->filterByParent($object->getParent());
// Up or down ?
if ($event->getMode() == BaseChangePositionEvent::POSITION_UP) {
// Find the object immediately before me
$search->filterByPosition(array('max' => $my_position-1))->orderByPosition(Criteria::DESC);
} elseif ($event->getMode() == BaseChangePositionEvent::POSITION_DOWN) {
// Find the object immediately after me
$search->filterByPosition(array('min' => $my_position+1))->orderByPosition(Criteria::ASC);
} else
return;
$result = $search->findOne();
// If we found the proper object, exchange their positions
if ($result) {
$cnx = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME);
$cnx->beginTransaction();
try {
$object
->setDispatcher($this->getDispatcher())
->setPosition($result->getPosition())
->save()
;
$result->setPosition($my_position)->save();
$cnx->commit();
} catch (Exception $e) {
$cnx->rollback();
}
}
}
}
/**
* Changes object position
*
* @param BaseChangePositionEvent $event
*/
protected function changeAbsolutePosition(BaseChangePositionEvent $event)
{
$object = CategoryQuery::create()->findPk($event->getCategoryId());
if ($object !== null) {
// The required position
$new_position = $event->getPosition();
// The current position
$current_position = $object->getPosition();
if ($new_position != null && $new_position > 0 && $new_position != $current_position) {
// Find categories to offset
$search = CategoryQuery::create()->filterByParent($object->getParent());
if ($new_position > $current_position) {
// The new position is after the current position -> we will offset + 1 all categories located between us and the new position
$search->filterByPosition(array('min' => 1+$current_position, 'max' => $new_position));
$delta = -1;
} else {
// The new position is brefore the current position -> we will offset - 1 all categories located between us and the new position
$search->filterByPosition(array('min' => $new_position, 'max' => $current_position - 1));
$delta = 1;
}
$results = $search->find();
$cnx = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME);
$cnx->beginTransaction();
try {
foreach ($results as $result) {
$result->setPosition($result->getPosition() + $delta)->save($cnx);
}
$object
->setDispatcher($this->getDispatcher())
->setPosition($new_position)
->save($cnx)
;
$cnx->commit();
} catch (Exception $e) {
$cnx->rollback();
}
}
}
}
}

View File

@@ -53,7 +53,7 @@
<default key="_controller">Thelia\Controller\Admin\ConfigController::changeAction</default>
</route>
<route id="admin.configuration.variables.save-change" path="/admin/configuration/variables/save-change">
<route id="admin.configuration.variables.save" path="/admin/configuration/variables/save">
<default key="_controller">Thelia\Controller\Admin\ConfigController::saveChangeAction</default>
</route>
@@ -75,7 +75,7 @@
<default key="_controller">Thelia\Controller\Admin\MessageController::changeAction</default>
</route>
<route id="admin.configuration.messages.save-change" path="/admin/configuration/messages/save-change">
<route id="admin.configuration.messages.save" path="/admin/configuration/messages/save">
<default key="_controller">Thelia\Controller\Admin\MessageController::saveChangeAction</default>
</route>
@@ -97,7 +97,7 @@
<default key="_controller">Thelia\Controller\Admin\CurrencyController::changeAction</default>
</route>
<route id="admin.configuration.currencies.save-change" path="/admin/configuration/currencies/save-change">
<route id="admin.configuration.currencies.save" path="/admin/configuration/currencies/save">
<default key="_controller">Thelia\Controller\Admin\CurrencyController::saveChangeAction</default>
</route>

View File

@@ -241,7 +241,7 @@ class ConfigController extends BaseAdminController
if ($this->getRequest()->get('save_mode') == 'stay') {
$this->redirectToRoute(
"admin.configuration.variables.update",
"admin.configuration.variables.change",
array('variable_id' => $variable_id)
);
}

View File

@@ -0,0 +1,87 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program 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 General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Event;
class BaseUpdatePositionEvent extends ActionEvent
{
const POSITION_UP = 1;
const POSITION_DOWN = 2;
const POSITION_ABSOLUTE = 3;
protected $object_id;
protected $mode;
protected $position;
protected $object;
public function __construct($object_id, $mode, $position = null)
{
$this->object_id = $object_id;
$this->mode = $mode;
$this->position = $position;
}
public function getMode()
{
return $this->mode;
}
public function setMode($mode)
{
$this->mode = $mode;
return $this;
}
public function getPosition()
{
return $this->position;
}
public function setPosition($position)
{
$this->position = $position;
return $this;
}
public function getObjectId()
{
return $this->object_id;
}
public function setObjectId($object_id)
{
$this->object_id = $object_id;
return $this;
}
public function getObjectId()
{
return $this->object_id;
}
public function setObjectId($object_id)
{
$this->object_id = $object_id;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program 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 General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Event;
class CategoryChangePositionEvent extends BaseChangePositionEvent
{
}

View File

@@ -70,7 +70,7 @@ class AdminUtilities extends AbstractSmartyPlugin
if ($permissions == null || $this->securityContext->isGranted("ADMIN", array($permission))) {
return sprintf(
'<a href="%s"><i class="icon-arrow-up"></i></a><span class="%s" data-id="%s">%s</span><a href="%s"><i class="icon-arrow-down"></i></a>',
'<a href="%s"><i class="glyphicon glyphicon-arrow-up"></i></a><span class="%s" data-id="%s">%s</span><a href="%s"><i class="glyphicon glyphicon-arrow-down"></i></a>',
URL::getInstance()->absoluteUrl("$path/positionUp", array($url_parameter => $id)),
$in_place_edit_class,
$id,

View File

@@ -136,8 +136,23 @@ class TheliaLoop extends AbstractSmartyPlugin
}
if ($loopResults->valid()) {
$loopResultRow = $loopResults->current();
// On first iteration, save variables that may be overwritten by this loop
if (! isset($this->varstack[$name])) {
$saved_vars = array();
$varlist = $loopResultRow->getVars();
foreach ($varlist as $var) {
$saved_vars[$var] = $template->getTemplateVars($var);
}
$this->varstack[$name] = $saved_vars;
}
foreach ($loopResultRow->getVarVal() as $var => $val) {
$template->assign($var, $val);
}

View File

@@ -122,7 +122,9 @@ class TheliaHttpKernel extends HttpKernel
*/
protected function initParam(Request $request)
{
// Ensure an instaciation of URL service
// Ensure an instaciation of URL service, which is accessed as a pseudo-singleton
// in the rest of the application.
// See Thelia\Tools\URL class.
$this->container->get('thelia.url.manager');
$lang = $this->detectLang($request);

View File

@@ -0,0 +1,176 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program 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 General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Model\Tools;
use Propel\Runtime\ActiveQuery\PropelQuery;
use Propel\Runtime\ActiveQuery\Criteria;
trait PositionManagementTrait {
/**
* Create an instancer of this object query
*/
private function createQuery() {
return PropelQuery::from(__CLASS__);
}
/**
* Return the database name from this object's table map.
*/
private function getDatabaseNameFromMap() {
$class = new \ReflectionClass(self::TABLE_MAP);
return $class->getConstant('DATABASE_NAME');
}
/**
* Get the position of the next inserted object
*/
public function getNextPosition($parent) {
$last = $this->createQuery()
->filterByParent($parent)
->orderByPosition(Criteria::DESC)
->limit(1)
->findOne()
;
return $last != null ? $last->getPosition() + 1 : 1;
}
/**
* Move up a object
*/
protected function movePositionUp() {
$this->movePositionUpOrDown(true);
}
/**
* Move down a object
*/
protected function movePositionDown() {
$this->movePositionUpOrDown(false);
}
/**
* Move up or down a object
*
* @param the exchange mode: go up (POSITION_UP) or go down (POSITION_DOWN)
*/
protected function movePositionUpOrDown($up = true)
{
// The current position of the object
$my_position = $this->getPosition();
// Find object to exchange position with
$search = $this->createQuery()
->filterByParent($this->getParent());
// Up or down ?
if ($up === true) {
// Find the object immediately before me
$search->filterByPosition(array('max' => $my_position-1))->orderByPosition(Criteria::DESC);
}
else {
// Find the object immediately after me
$search->filterByPosition(array('min' => $my_position+1))->orderByPosition(Criteria::ASC);
}
$result = $search->findOne();
// If we found the proper object, exchange their positions
if ($result) {
$cnx = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME);
$cnx->beginTransaction();
try {
$this
->setDispatcher($this->getDispatcher())
->setPosition($result->getPosition())
->save()
;
$result->setPosition($my_position)->save();
$cnx->commit();
} catch (Exception $e) {
$cnx->rollback();
}
}
}
/**
* Changes object position
*
* @param newPosition
*/
protected function changeAbsolutePosition($newPosition)
{
// The current position
$current_position = $this->getPosition();
if ($newPosition != null && $newPosition > 0 && $newPosition != $current_position) {
// Find categories to offset
$search = $this->createQuery()->filterByParent($this->getParent());
if ($newPosition > $current_position) {
// The new position is after the current position -> we will offset + 1 all categories located between us and the new position
$search->filterByPosition(array('min' => 1+$current_position, 'max' => $newPosition));
$delta = -1;
} else {
// The new position is brefore the current position -> we will offset - 1 all categories located between us and the new position
$search->filterByPosition(array('min' => $newPosition, 'max' => $current_position - 1));
$delta = 1;
}
$results = $search->find();
$cnx = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME);
$cnx->beginTransaction();
try {
foreach ($results as $result) {
$result->setPosition($result->getPosition() + $delta)->save($cnx);
}
$this
->setDispatcher($this->getDispatcher())
->setPosition($newPosition)
->save($cnx)
;
$cnx->commit();
} catch (Exception $e) {
$cnx->rollback();
}
}
}
}

View File

@@ -48,6 +48,8 @@ class URL
public function __construct(ContainerInterface $container, $environment)
{
// Allow singleton style calls once intanciated.
// For this to work, the URL service has to be instanciated very early. This is done manually
// in TheliaHttpKernel, by calling $this->container->get('thelia.url.manager');
self::$instance = $this;
$this->container = $container;

View File

@@ -85,17 +85,17 @@
</thead>
<tbody>
{loop name="category_list" type="category" visible="*" parent="{$current_category_id}" order="$category_order"}
{loop name="category_list" type="category" visible="*" parent=$current_category_id order=$category_order backend_context="1" lang=$lang_id}
<tr>
<td>
{loop type="image" name="cat_image" source="category" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"}
i={$ID} {loop type="image" name="cat_image" source="category" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"}
<a href="{url path='admin/catalog/category' id="$ID" action='browse'}" title="{intl l='Browse this category'}"><img src="#IMAGE_URL" alt="#TITLE" /></a>
{/loop}
</td>
<td class="object-title">
<a href="{url path='admin/catalog/category' id="$ID" action='browse'}" title="{intl l='Browse this category'}">
{$TITLE}
{$ID} p={$POSITION} {$TITLE}
</a>
</td>

View File

@@ -155,7 +155,7 @@
<td class="actions">
<div class="btn-group">
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.currencies.change"}
<a class="btn btn-default btn-xs currency-change" title="{intl l='Change this currency'}" href="{url path='/admin/configuration/currencies/change' currency_id="$ID"}"><i class="glyphicon glyphicon-edit"></i></a>
<a class="btn btn-default btn-xs currency-change" title="{intl l='Change this currency'}" href="{url path='/admin/configuration/currencies/update' currency_id="$ID"}"><i class="glyphicon glyphicon-edit"></i></a>
{/loop}
{loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.configuration.currencies.delete"}

View File

@@ -29,7 +29,7 @@
<div class="form-container">
<div class="form-horizontal col-md-12">
{form name="thelia.admin.currency.modification"}
<form method="POST" action="{url path='/admin/configuration/currencies/save-change'}" {form_enctype form=$form}>
<form method="POST" action="{url path='/admin/configuration/currencies/save'}" {form_enctype form=$form}>
<fieldset>
{* Be sure to get the currency ID, even if the form could not be validated *}
<input type="hidden" name="currency_id" value="{$currency_id}" />

View File

@@ -29,7 +29,7 @@
<div class="form-container">
<div class="form-horizontal col-md-12">
{form name="thelia.admin.message.modification"}
<form method="POST" action="{url path='/admin/configuration/messages/save-change'}" {form_enctype form=$form}>
<form method="POST" action="{url path='/admin/configuration/messages/save'}" {form_enctype form=$form}>
<fieldset>
{* Be sure to get the message ID, even if the form could not be validated *}
<input type="hidden" name="message_id" value="{$message_id}" />

View File

@@ -19,7 +19,7 @@
<div class="row">
<div class="col-md-12">
<form action="{url path='/admin/configuration/messages/change-values'}" method="post">
<form action="{url path='/admin/configuration/messages/update-values'}" method="post">
<div class="general-block-decorator">
<table class="table table-striped table-condensed table-left-aligned">
<caption>
@@ -64,7 +64,7 @@
{if ! $SECURED}
<div class="btn-group">
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.messages.change"}
<a class="btn btn-default btn-xs message-change" title="{intl l='Change this mailing template'}" href="{url path='/admin/configuration/messages/change' message_id="$ID"}"><i class="glyphicon glyphicon-edit"></i></a>
<a class="btn btn-default btn-xs message-change" title="{intl l='Change this mailing template'}" href="{url path='/admin/configuration/messages/update' message_id="$ID"}"><i class="glyphicon glyphicon-edit"></i></a>
{/loop}
{loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.configuration.messages.delete"}

View File

@@ -29,7 +29,7 @@
<div class="form-container">
<div class="form-horizontal col-md-12">
{form name="thelia.admin.config.modification"}
<form method="POST" action="{url path='/admin/configuration/variables/save-change'}" {form_enctype form=$form}>
<form method="POST" action="{url path='/admin/configuration/variables/save'}" {form_enctype form=$form}>
<fieldset>
{* Be sure to get the variable ID, even if the form could not be validated *}
<input type="hidden" name="variable_id" value="{$variable_id}" />

View File

@@ -19,7 +19,7 @@
<div class="row">
<div class="col-md-12">
<form action="{url path='/admin/configuration/variables/change-values'}" method="post">
<form action="{url path='/admin/configuration/variables/update-values'}" method="post">
<div class="general-block-decorator">
<table class="table table-striped table-condensed table-left-aligned">
<caption>
@@ -102,7 +102,7 @@
<a class="btn btn-default btn-xs cancel-edit" id="cancel_edit_btn_{$ID}" data-id="{$ID}" title="{intl l='Cancel changes and revert to original value'}" href="#"><i class="glyphicon glyphicon-remove"></i></a>
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.variables.change"}
<a class="btn btn-default btn-xs config-change" title="{intl l='Change this variable'}" href="{url path='/admin/configuration/variables/change' variable_id="$ID"}"><i class="glyphicon glyphicon-edit"></i></a>
<a class="btn btn-default btn-xs config-change" title="{intl l='Change this variable'}" href="{url path='/admin/configuration/variables/update' variable_id="$ID"}"><i class="glyphicon glyphicon-edit"></i></a>
{/loop}
{loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.configuration.variables.delete"}