Merge branch 'master' into cart

Conflicts:
	core/lib/Thelia/Core/Template/Loop/Category.php
	install/faker.php
This commit is contained in:
Manuel Raynaud
2013-08-07 10:23:44 +02:00
24 changed files with 1398 additions and 30 deletions

View File

@@ -0,0 +1,63 @@
<?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\Admin\Controller;
class CategoryController extends BaseAdminController {
public function indexAction()
{
// Show top level categories and products
$args = array(
'action' => 'browse',
'current_category_id' => 0
);
return $this->render('categories', $args);
}
public function processAction($action)
{
list($action, $id) = explode('/', $action);
$args = array(
'action' => $action,
'current_category_id' => $id
);
// Browe categories
if ($action == 'browse') {
return $this->render('categories', $args);
}
// Create a new category
else if ($action = 'create') {
return $this->render('edit_category', $args);
}
// Edit an existing category
else if ($action = 'edit') {
return $this->render('edit_category', $args);
}
//return $this->render("categories");
}
}

View File

@@ -9,11 +9,13 @@
<loop class="Thelia\Core\Template\Loop\Address" name="address"/>
<loop class="Thelia\Core\Template\Loop\Auth" name="auth"/>
<loop class="Thelia\Core\Template\Loop\Category" name="category"/>
<loop class="Thelia\Core\Template\Loop\Content" name="content"/>
<loop class="Thelia\Core\Template\Loop\Country" name="country"/>
<loop class="Thelia\Core\Template\Loop\Customer" name="customer"/>
<loop class="Thelia\Core\Template\Loop\Feature" name="feature"/>
<loop class="Thelia\Core\Template\Loop\FeatureAvailable" name="feature_available"/>
<loop class="Thelia\Core\Template\Loop\FeatureValue" name="feature_value"/>
<loop class="Thelia\Core\Template\Loop\Folder" name="folder"/>
<loop class="Thelia\Core\Template\Loop\Order" name="order"/>
<loop class="Thelia\Core\Template\Loop\OrderStatus" name="order-status"/>
<loop class="Thelia\Core\Template\Loop\CategoryPath" name="category-path"/>
@@ -82,7 +84,7 @@
<argument type="service" id="request" />
<argument type="service" id="event_dispatcher"/>
<argument type="service" id="thelia.parser.context"/>
<argument >false</argument>
<argument >true</argument> <!-- debug mode -->
<argument >%kernel.environment%</argument>
<argument >%kernel.debug%</argument>
</service>

View File

@@ -97,7 +97,8 @@ abstract class BaseLoop
if (substr($name, 0, 3) == 'get') {
$argName = strtolower(substr($name, 3));
// camelCase to underscore: getNotEmpty -> not_empty
$argName = strtolower(preg_replace('/([^A-Z])([A-Z])/', "$1_$2", substr($name, 3)));
return $this->getArg($argName)->getValue();
}

View File

@@ -161,11 +161,14 @@ class Category extends BaseLoop
$categories = $this->search($search, $pagination);
$notEmpty = $this->getNot_empty();
$loopResult = new LoopResult();
foreach ($categories as $category) {
if ($this->getNot_empty() && $category->countAllProducts() == 0) continue;
if ($this->getNotEmpty() && $category->countAllProducts() == 0) continue;
$loopResultRow = new LoopResultRow();

View File

@@ -0,0 +1,126 @@
<?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\Template\Loop;
use Propel\Runtime\ActiveQuery\Criteria;
use Thelia\Core\Template\Element\BaseLoop;
use Thelia\Core\Template\Element\LoopResult;
use Thelia\Core\Template\Element\LoopResultRow;
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
use Thelia\Core\Template\Loop\Argument\Argument;
use Thelia\Log\Tlog;
use Thelia\Model\CategoryQuery;
use Thelia\Model\ConfigQuery;
use Thelia\Type\TypeCollection;
use Thelia\Type;
/**
*
* Category path loop, to get the path to a given category.
*
* - category is the category id
* - depth is the maximum depth to go, default unlimited
* - level is the exact level to return. Example: if level = 2 and the path is c1 -> c2 -> c3 -> c4, the loop will return c2
* - visible if true or missing, only visible categories will be displayed. If false, all categories (visible or not) are returned.
*
* example :
*
* <THELIA_cat type="category-path" category="3">
* <a href="#URL">#TITLE</a>
* </THELIA_cat>
*
*
* Class CategoryPath
* @package Thelia\Core\Template\Loop
* @author Franck Allimant <franck@cqfdev.fr>
*/
class CategoryPath extends BaseLoop
{
/**
* @return ArgumentCollection
*/
protected function getArgDefinitions()
{
return new ArgumentCollection(
Argument::createIntTypeArgument('category', null, true),
Argument::createIntTypeArgument('depth'),
Argument::createIntTypeArgument('level'),
Argument::createBooleanTypeArgument('visible', true, false)
);
}
/**
* @param $pagination (ignored)
*
* @return \Thelia\Core\Template\Element\LoopResult
*/
public function exec(&$pagination)
{
$id = $this->getCategory();
$visible = $this->getVisible();
$search = CategoryQuery::create();
$search->filterById($id);
if ($visible == true) $search->filterByVisible($visible);
$results = array();
do {
$category = $search->findOne();
if ($category != null) {
$loopResultRow = new LoopResultRow();
$loopResultRow
->set("TITLE",$category->getTitle())
->set("URL", $category->getUrl())
->set("ID", $category->getId())
;
$results[] = $loopResultRow;
$parent = $category->getParent();
if ($parent > 0) {
$search = CategoryQuery::create();
$search->filterById($parent);
if ($visible == true) $search->filterByVisible($visible);
}
}
}
while ($category != null && $parent > 0);
// Reverse list and build the final result
$results = array_reverse($results);
$loopResult = new LoopResult();
foreach($results as $result) $loopResult->addRow($result);
return $loopResult;
}
}

View File

@@ -0,0 +1,238 @@
<?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\Template\Loop;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\ActiveQuery\Join;
use Thelia\Core\Template\Element\BaseLoop;
use Thelia\Core\Template\Element\LoopResult;
use Thelia\Core\Template\Element\LoopResultRow;
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
use Thelia\Core\Template\Loop\Argument\Argument;
use Thelia\Log\Tlog;
use Thelia\Model\Base\FeatureContentQuery;
use Thelia\Model\FolderQuery;
use Thelia\Model\Map\ContentTableMap;
use Thelia\Model\ContentFolderQuery;
use Thelia\Model\ContentQuery;
use Thelia\Model\ConfigQuery;
use Thelia\Type\TypeCollection;
use Thelia\Type;
/**
*
* Content loop
*
*
* Class Content
* @package Thelia\Core\Template\Loop
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*/
class Content extends BaseLoop
{
/**
* @return ArgumentCollection
*/
protected function getArgDefinitions()
{
return new ArgumentCollection(
Argument::createIntListTypeArgument('id'),
Argument::createIntListTypeArgument('folder'),
Argument::createBooleanTypeArgument('current'),
Argument::createBooleanTypeArgument('current_folder'),
Argument::createIntTypeArgument('depth', 1),
Argument::createBooleanTypeArgument('visible', 1),
new Argument(
'order',
new TypeCollection(
new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse', 'random', 'given_id'))
),
'alpha'
),
Argument::createIntListTypeArgument('exclude'),
Argument::createIntListTypeArgument('exclude_folder')
);
}
/**
* @param $pagination
*
* @return LoopResult
* @throws \InvalidArgumentException
*/
public function exec(&$pagination)
{
$search = ContentQuery::create();
$id = $this->getId();
if (!is_null($id)) {
$search->filterById($id, Criteria::IN);
}
$folder = $this->getFolder();
if (!is_null($folder)) {
$folders = FolderQuery::create()->filterById($folder, Criteria::IN)->find();
$depth = $this->getDepth();
if(null !== $depth) {
foreach(FolderQuery::findAllChild($folder, $depth) as $subFolder) {
$folders->prepend($subFolder);
}
}
$search->filterByFolder(
$folders,
Criteria::IN
);
}
$current = $this->getCurrent();
if ($current === true) {
$search->filterById($this->request->get("content_id"));
} elseif($current === false) {
$search->filterById($this->request->get("content_id"), Criteria::NOT_IN);
}
$current_folder = $this->getCurrent_folder();
if ($current_folder === true) {
$search->filterByFolder(
FolderQuery::create()->filterByContent(
ContentFolderQuery::create()->filterByContentId(
$this->request->get("content_id"),
Criteria::EQUAL
)->find(),
Criteria::IN
)->find(),
Criteria::IN
);
} elseif($current_folder === false) {
$search->filterByFolder(
FolderQuery::create()->filterByContent(
ContentFolderQuery::create()->filterByContentId(
$this->request->get("content_id"),
Criteria::EQUAL
)->find(),
Criteria::IN
)->find(),
Criteria::NOT_IN
);
}
$visible = $this->getVisible();
$search->filterByVisible($visible);
$orders = $this->getOrder();
foreach($orders as $order) {
switch ($order) {
case "alpha":
$search->addAscendingOrderByColumn(\Thelia\Model\Map\ContentI18nTableMap::TITLE);
break;
case "alpha_reverse":
$search->addDescendingOrderByColumn(\Thelia\Model\Map\ContentI18nTableMap::TITLE);
break;
case "manual":
if(null === $folder || count($folder) != 1)
throw new \InvalidArgumentException('Manual order cannot be set without single folder argument');
$search->orderByPosition(Criteria::ASC);
break;
case "manual_reverse":
if(null === $folder || count($folder) != 1)
throw new \InvalidArgumentException('Manual order cannot be set without single folder argument');
$search->orderByPosition(Criteria::DESC);
break;
case "given_id":
if(null === $id)
throw new \InvalidArgumentException('Given_id order cannot be set without `id` argument');
foreach($id as $singleId) {
$givenIdMatched = 'given_id_matched_' . $singleId;
$search->withColumn(ContentTableMap::ID . "='$singleId'", $givenIdMatched);
$search->orderBy($givenIdMatched, Criteria::DESC);
}
break;
case "random":
$search->clearOrderByColumns();
$search->addAscendingOrderByColumn('RAND()');
break(2);
}
}
$exclude = $this->getExclude();
if (!is_null($exclude)) {
$search->filterById($exclude, Criteria::NOT_IN);
}
$exclude_folder = $this->getExclude_folder();
if (!is_null($exclude_folder)) {
$search->filterByFolder(
FolderQuery::create()->filterById($exclude_folder, Criteria::IN)->find(),
Criteria::NOT_IN
);
}
/**
* Criteria::INNER_JOIN in second parameter for joinWithI18n exclude query without translation.
*
* @todo : verify here if we want results for row without translations.
*/
$search->joinWithI18n(
$this->request->getSession()->getLocale(),
(ConfigQuery::read("default_lang_without_translation", 1)) ? Criteria::LEFT_JOIN : Criteria::INNER_JOIN
);
$search->groupBy(ContentTableMap::ID);
$contents = $this->search($search, $pagination);
$loopResult = new LoopResult();
foreach ($contents as $content) {
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $content->getId())
->set("TITLE",$content->getTitle())
->set("CHAPO", $content->getChapo())
->set("DESCRIPTION", $content->getDescription())
->set("POSTSCRIPTUM", $content->getPostscriptum())
->set("POSITION", $content->getPosition())
;
$loopResult->addRow($loopResultRow);
}
return $loopResult;
}
}

View File

@@ -0,0 +1,179 @@
<?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\Template\Loop;
use Propel\Runtime\ActiveQuery\Criteria;
use Thelia\Core\Template\Element\BaseLoop;
use Thelia\Core\Template\Element\LoopResult;
use Thelia\Core\Template\Element\LoopResultRow;
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
use Thelia\Core\Template\Loop\Argument\Argument;
use Thelia\Log\Tlog;
use Thelia\Model\FolderQuery;
use Thelia\Model\ConfigQuery;
use Thelia\Type\TypeCollection;
use Thelia\Type;
/**
* Class Folder
*
* @package Thelia\Core\Template\Loop
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*/
class Folder extends BaseLoop
{
/**
* @return ArgumentCollection
*/
protected function getArgDefinitions()
{
return new ArgumentCollection(
Argument::createIntListTypeArgument('id'),
Argument::createIntTypeArgument('parent'),
Argument::createBooleanTypeArgument('current'),
Argument::createBooleanTypeArgument('not_empty', 0),
Argument::createBooleanTypeArgument('visible', 1),
new Argument(
'order',
new TypeCollection(
new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual-reverse', 'random'))
),
'manual'
),
Argument::createIntListTypeArgument('exclude')
);
}
/**
* @param $pagination
*
* @return \Thelia\Core\Template\Element\LoopResult
*/
public function exec(&$pagination)
{
$search = FolderQuery::create();
$id = $this->getId();
if (!is_null($id)) {
$search->filterById($id, Criteria::IN);
}
$parent = $this->getParent();
if (!is_null($parent)) {
$search->filterByParent($parent);
}
$current = $this->getCurrent();
if ($current === true) {
$search->filterById($this->request->get("folder_id"));
} elseif ($current === false) {
$search->filterById($this->request->get("folder_id"), Criteria::NOT_IN);
}
$exclude = $this->getExclude();
if (!is_null($exclude)) {
$search->filterById($exclude, Criteria::NOT_IN);
}
$search->filterByVisible($this->getVisible() ? 1 : 0);
$orders = $this->getOrder();
foreach($orders as $order) {
switch ($order) {
case "alpha":
$search->addAscendingOrderByColumn(\Thelia\Model\Map\FolderI18nTableMap::TITLE);
break;
case "alpha_reverse":
$search->addDescendingOrderByColumn(\Thelia\Model\Map\FolderI18nTableMap::TITLE);
break;
case "manual-reverse":
$search->orderByPosition(Criteria::DESC);
break;
case "manual":
$search->orderByPosition(Criteria::ASC);
break;
case "random":
$search->clearOrderByColumns();
$search->addAscendingOrderByColumn('RAND()');
break(2);
break;
}
}
/**
* \Criteria::INNER_JOIN in second parameter for joinWithI18n exclude query without translation.
*
* @todo : verify here if we want results for row without translations.
*/
$search->joinWithI18n(
$this->request->getSession()->getLocale(),
(ConfigQuery::read("default_lang_without_translation", 1)) ? Criteria::LEFT_JOIN : Criteria::INNER_JOIN
);
$folders = $this->search($search, $pagination);
$notEmpty = $this->getNot_empty();
$loopResult = new LoopResult();
foreach ($folders as $folder) {
if ($notEmpty && $folder->countAllProducts() == 0) continue;
$loopResultRow = new LoopResultRow();
$loopResultRow
->set("ID", $folder->getId())
->set("TITLE",$folder->getTitle())
->set("CHAPO", $folder->getChapo())
->set("DESCRIPTION", $folder->getDescription())
->set("POSTSCRIPTUM", $folder->getPostscriptum())
->set("PARENT", $folder->getParent())
->set("CONTENT_COUNT", $folder->countChild())
->set("VISIBLE", $folder->getVisible() ? "1" : "0")
->set("POSITION", $folder->getPosition())
->set("CREATE_DATE", $folder->getCreatedAt())
->set("UPDATE_DATE", $folder->getUpdatedAt())
->set("VERSION", $folder->getVersion())
->set("VERSION_DATE", $folder->getVersionCreatedAt())
->set("VERSION_AUTHOR", $folder->getVersionCreatedBy())
;
$loopResult->addRow($loopResultRow);
}
return $loopResult;
}
}

View File

@@ -109,6 +109,7 @@ class Product extends BaseLoop
* @param $pagination
*
* @return \Thelia\Core\Template\Element\LoopResult
* @throws \InvalidArgumentException
*/
public function exec(&$pagination)
{
@@ -402,11 +403,11 @@ class Product extends BaseLoop
->set("CHAPO", $product->getChapo())
->set("DESCRIPTION", $product->getDescription())
->set("POSTSCRIPTUM", $product->getPostscriptum())
->set("PRICE", $product->getPrice())
->set("PROMO_PRICE", $product->getPrice2())
->set("WEIGHT", $product->getWeight())
->set("PROMO", $product->getPromo())
->set("NEW", $product->getNewness())
//->set("PRICE", $product->getPrice())
//->set("PROMO_PRICE", $product->getPrice2())
//->set("WEIGHT", $product->getWeight())
//->set("PROMO", $product->getPromo())
//->set("NEW", $product->getNewness())
->set("POSITION", $product->getPosition())
;

View File

@@ -4,6 +4,37 @@ namespace Thelia\Model;
use Thelia\Model\Base\Folder as BaseFolder;
class Folder extends BaseFolder {
class Folder extends BaseFolder
{
/**
* @return int number of contents for the folder
*/
public function countChild()
{
return FolderQuery::countChild($this->getId());
}
/**
*
* count all products for current category and sub categories
*
* @return int
*/
public function countAllContents()
{
$children = FolderQuery::findAllChild($this->getId());
array_push($children, $this);
$contentsCount = 0;
foreach($children as $child)
{
$contentsCount += ProductQuery::create()
->filterByCategory($child)
->count();
}
return $contentsCount;
}
}

View File

@@ -15,6 +15,52 @@ use Thelia\Model\Base\FolderQuery as BaseFolderQuery;
* long as it does not already exist in the output directory.
*
*/
class FolderQuery extends BaseFolderQuery {
class FolderQuery extends BaseFolderQuery
{
/**
*
* count how many direct contents a folder has
*
* @param int $parent folder id
* @return int
*/
public static function countChild($parent)
{
return self::create()->filterByParent($parent)->count();
}
/**
* find all contents for a given folder.
*
* @param $folderId the folder id or an array of id
* @param int $depth max depth you want to search
* @param int $currentPosition don't change this param, it is used for recursion
* @return \Thelia\Model\Folder[]
*/
public static function findAllChild($folderId, $depth = 0, $currentPosition = 0)
{
$result = array();
if(is_array($folderId)) {
foreach($folderId as $folderSingleId) {
$result = array_merge($result, (array) self::findAllChild($folderSingleId, $depth, $currentPosition));
}
} else {
$currentPosition++;
if($depth == $currentPosition && $depth != 0) return;
$categories = self::create()
->filterByParent($folderId)
->find();
foreach ($categories as $folder) {
array_push($result, $folder);
$result = array_merge($result, (array) self::findAllChild($folder->getId(), $depth, $currentPosition));
}
}
return $result;
}
} // FolderQuery

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Content;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class ContentTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Content';
}
public function getTestedInstance()
{
return new Content($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Folder;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class FolderTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Folder';
}
public function getTestedInstance()
{
return new Folder($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -42,13 +42,21 @@ try {
);
$folder = Thelia\Model\FolderQuery::create()
->find();
$folder->delete();
$content = Thelia\Model\ContentQuery::create()
->find();
$content->delete();
//first category
$sweet = new Thelia\Model\Category();
$sweet->setParent(0);
$sweet->setVisible(1);
$sweet->setPosition(1);
$sweet->setDescription($faker->text(255));
$sweet->setTitle($faker->bs);
$sweet->setTitle($faker->text(20));
$sweet->save();
@@ -58,7 +66,7 @@ try {
$jeans->setVisible(1);
$jeans->setPosition(2);
$jeans->setDescription($faker->text(255));
$jeans->setTitle($faker->bs);
$jeans->setTitle($faker->text(20));
$jeans->save();
@@ -68,14 +76,14 @@ try {
$other->setVisible(1);
$other->setPosition(3);
$other->setDescription($faker->text(255));
$other->setTitle($faker->bs);
$other->setTitle($faker->text(20));
$other->save();
for ($i=1; $i <= 5; $i++) {
$product = new \Thelia\Model\Product();
$product->addCategory($sweet);
$product->setTitle($faker->bs);
$product->setTitle($faker->text(20));
$product->setDescription($faker->text(250));
/* $product->setQuantity($faker->randomNumber(1,50));
$product->setPrice($faker->randomFloat(2, 20, 2500));*/
@@ -101,7 +109,7 @@ try {
for ($i=1; $i <= 5; $i++) {
$product = new \Thelia\Model\Product();
$product->addCategory($jeans);
$product->setTitle($faker->bs);
$product->setTitle($faker->text(20));
$product->setDescription($faker->text(250));
/* $product->setQuantity($faker->randomNumber(1,50));
$product->setPrice($faker->randomFloat(2, 20, 2500));*/
@@ -124,6 +132,60 @@ try {
}
//folders and contents
for($i=0; $i<4; $i++) {
$folder = new Thelia\Model\Folder();
$folder->setParent(0);
$folder->setVisible(rand(1, 10)>7 ? 0 : 1);
$folder->setPosition($i);
$folder->setTitle($faker->text(20));
$folder->setDescription($faker->text(255));
$folder->save();
for($j=0; $j<rand(0, 4); $j++) {
$subfolder = new Thelia\Model\Folder();
$subfolder->setParent($folder->getId());
$subfolder->setVisible(rand(1, 10)>7 ? 0 : 1);
$subfolder->setPosition($j);
$subfolder->setTitle($faker->text(20));
$subfolder->setDescription($faker->text(255));
$subfolder->save();
for($k=0; $k<rand(1, 5); $k++) {
$content = new Thelia\Model\Content();
$content->addFolder($subfolder);
$content->setVisible(rand(1, 10)>7 ? 0 : 1);
$content->setPosition($k);
$content->setTitle($faker->text(20));
$content->setDescription($faker->text(255));
$content->save();
}
}
}
//features and features_av
for($i=0; $i<4; $i++) {
$feature = new Thelia\Model\Feature();
$feature->setVisible(rand(1, 10)>7 ? 0 : 1);
$feature->setPosition($i);
$feature->setTitle($faker->text(20));
$feature->setDescription($faker->text(50));
$feature->save();
for($j=0; $j<rand(1, 5); $j++) {
$featureAv = new Thelia\Model\FeatureAv();
$featureAv->setFeature($feature);
$featureAv->setPosition($j);
$featureAv->setTitle($faker->text(20));
$featureAv->setDescription($faker->text(255));
$featureAv->save();
}
}
$con->commit();
} catch (Exception $e) {

View File

@@ -217,6 +217,16 @@ hr {
height: @top-bar-height;
}
}
.view-shop {
line-height: @top-bar-height;
margin-right: 20px;
float: right;
a {
color: #fff;
text-decoration: none;
}
}
}
// -- Brandbar ----------------------------------------------------------------
@@ -540,11 +550,95 @@ textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[ty
border-color: #3a87ad;
}
// -- General decoration of back-office boxes ---------------------------------
.general-block-decorator {
background: none repeat scroll 0 0 white;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 4px 4px 4px 4px;
box-shadow: 0 -4px 0 rgba(0, 0, 0, 0.05) inset, 0 2px 3px rgba(0, 0, 0, 0.1);
padding: 1em;
margin-bottom: 20px;
.title {
color: #5A6876;
text-transform: uppercase;
font-weight: bold;
padding-bottom: 0.5em;
line-height: 30px;
}
.actions {
text-align: right;
}
}
// -- Admin forms tweaking ----------------------------------------------------
label {
font-weight: bold;
&.checkbox {
font-weight: normal;
}
}
// Information in field label
.label-help-block, .help-block {
color: lighten(#595959, 20);
display: block;
font-size: 80%;
font-style: italic;
line-height: 130%;
font-weight: normal;
}
.form-horizontal input + .help-block,
.form-horizontal select + .help-block,
.form-horizontal textarea + .help-block,
.form-horizontal .uneditable-input + .help-block,
.form-horizontal .input-prepend + .help-block,
.form-horizontal .input-append + .help-block
.help-block, .form-horizontal .help-block {
margin-top: 0px;
}
// Fix for append-fields shorter than others
// see http://stackoverflow.com/questions/13306670/bootstrap-prepended-and-appended-input-how-to-max-input-field-width
.input-append.input-block-level,
.input-prepend.input-block-level {
display: table;
}
.input-append.input-block-level .add-on,
.input-prepend.input-block-level .add-on {
display: table-cell;
width: 1%; /* remove this if you want default bootstrap button width */
}
.input-append.input-block-level > input,
.input-prepend.input-block-level > input {
box-sizing: border-box; /* use bootstrap mixin or include vendor variants */
display: table; /* table-cell is not working well in Chrome for small widths */
min-height: inherit;
width: 100%;
}
.input-append.input-block-level > input {
border-right: 0;
}
.input-prepend.input-block-level > input {
border-left: 0;
}
// -- Catalog Tables ----------------------------------------------------------
.table-striped {
background: white;
margin-bottom: 1em;
caption {
text-align: left;
@@ -552,7 +646,7 @@ textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[ty
text-transform: uppercase;
font-weight: bold;
background-color: #fff;
padding: 0.5em 0.5em 0.5em 1em;
padding-bottom: 0.5em;
border-bottom: 2px solid #A5CED8;
line-height: 30px;
@@ -574,15 +668,5 @@ textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[ty
td.message {
// Center the alert box (20px bottom margin) in the table cell
padding: 20px 20px 0 20px;
// No border, nor background in alert blocks
.alert {
border: none;
background-color: transparent;
&-info {
background-color: transparent;
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,170 @@
{check_auth context="admin" roles="ADMIN" permissions="admin.catalog.view" login_tpl="/admin/login"}
{$page_title={intl l='Catalog'}}
{include file='includes/header.inc.html'}
<div class="catalog">
<div id="wrapper" class="container">
<ul class="breadcrumb">
{include file="includes/category_breadcrumb.html"}
</ul>
{module_include location='catalog_top'}
<div class="row-fluid">
<div class="span12">
<div class="general-block-decorator">
<table class="table table-striped">
<caption>
{* display parent category name, and get current cat ID *}
{loop name="category_title" type="category" id="{$current_category_id}"}
{intl l="Categories in %cat" cat=$TITLE}
{$cat_id = $ID}
{/loop}
{elseloop rel="category_title"}
{intl l="Top level categories"}
{/elseloop}
{module_include location='category_list_caption'}
<a class="btn btn-primary btn-add-item" title="{intl l='Add a new category'}" href="{url path="admin/catalog/category/create/{$cat_id|default:0}"}">
<i class="icon-plus-sign icon-white"></i>
</a>
</caption>
{ifloop rel="category_list"}
<thead>
<tr>
<th class="object-title">{intl l="Category title"}</th>
{module_include location='category_list_header'}
<th>{intl l="Online"}</th>
<th>{intl l="Position"}</th>
<th>{intl l="Actions"}</th>
</tr>
</thead>
<tbody>
{loop name="category_list" type="category" parent="{$current_category_id}" order="manual"}
<tr>
<td class="object-title"><a href="{url path="admin/catalog/category/browse/$ID"}" title="{intl l='Browse this category'}">{$TITLE}</a></td>
{module_include location='category_list_row'}
<td>
<input type="checkbox" data-id="{$ID}" class="displayToggle" {if $VISIBLE == 1}checked="checked"{/if}>
</td>
<td>
<a href="{url path='admin/catalog/category/positionUp/{$ID}'}"><i class="icon-arrow-up"></i></a>
<span class="object_classement_editable" data-action="changeCategoryPosition" data-name="category_id" data-id="{$ID}">{$POSITION}</span>
<a href="{url path='admin/catalog/category/positionDown/{$ID}'}"><i class="icon-arrow-down"></i></a>
</td>
<td>
<a class="btn btn-mini" title="{intl l='Browse this category'}" href="{url path="admin/catalog/category/browse/{$ID}"}"><i class="icon-folder-open"></i></a>
<a class="btn btn-mini" title="{intl l='Edit this category'}" href="{url path="admin/catalog/category/edit/{$ID}"}"><i class="icon-edit"></i></a>
<a class="btn btn-mini category-delete" title="{intl l='Delete this category and all its contents'}" href="{url path='admin/catalog/category/delete/{$ID}'}"><i class="icon-trash"></i></a>
</td>
</tr>
{/loop}
</tbody>
{/ifloop}
{elseloop rel="category_list"}
<thead>
<tr>
<td class="message"><div class="alert alert-info">{intl l="This category has no sub-categories. To create a new one, click the + button above."}</div></td>
</tr>
</thead>
{/elseloop}
</table>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="general-block-decorator">
<table class="table table-striped">
<caption>
{* display parent category name *}
{loop name="category_title" type="category" id="{$current_category_id}"}
{intl l="Products in %cat" cat=$TITLE}
{/loop}
{elseloop rel="category_title"}
{intl l="Top level Products"}
{/elseloop}
{module_include location='product_list_caption'}
<a class="btn btn-primary btn-add-item" title="{intl l='Add a new product'}" href="#productAddModal" data-toggle="modal">
<i class="icon-plus-sign icon-white"></i>
</a>
</caption>
{ifloop rel="product_list"}
<thead>
<tr>
<th>{intl l="Image"}</th>
<th class="object-title">{intl l="Product title"}</th>
{module_include location='product_list_header'}
<th>{intl l="Online"}</th>
<th>{intl l="Position"}</th>
<th>{intl l="Actions"}</th>
</tr>
</thead>
<tbody>
{loop name="product_list" type="product" category="{$current_category_id}" order="manual"}
<tr>
<td><a href="{url path="admin/catalog/product/edit/$ID"}" title="{intl l='Edit this product'}">Image !</a></td>
<td class="object-title"><a href="{url path="admin/catalog/product/edit/$ID"}" title="{intl l='Edit this product'}">{$TITLE}</a></td>
{module_include location='product_list_row'}
<td>
<input type="checkbox" data-id="{$ID}" class="displayToggle" {if $VISIBLE == 1}checked="checked"{/if}>
</td>
<td>
<a href="{url path='admin/catalog/product/positionUp/{$ID}'}"><i class="icon-arrow-up"></i></a>
<span class="object_classement_editable" data-action="changeProductPosition" data-name="product_id" data-id="{$ID}">{$POSITION}</span>
<a href="{url path='admin/catalog/product/positionDown/{$ID}'}"><i class="icon-arrow-down"></i></a>
</td>
<td>
<a class="btn btn-mini" title="{intl l='Edit this category'}" href="{url path="admin/catalog/product/edit/{$ID}"}"><i class="icon-edit"></i></a>
<a class="btn btn-mini product-delete" title="{intl l='Delete this product'}" href="{url path='admin/catalog/product/delete/{$ID}'}"><i class="icon-trash"></i></a>
</td>
</tr>
{/loop}
</tbody>
{/ifloop}
{elseloop rel="product_list"}
<thead>
<tr>
<td class="message"><div class="alert alert-info">{intl l="This category doesn't have any products. To add a new product, click the + button above."}</div></td>
</tr>
</thead>
{/elseloop}
</table>
</div>
</div>
</div>
{module_include location='catalog_bottom'}
</div>
</div>
{include file='includes/js.inc.html'}
{include file='includes/footer.inc.html'}

View File

@@ -0,0 +1,195 @@
{check_auth context="admin" roles="ADMIN" permissions="admin.catalog.view" login_tpl="/admin/login"}
{if $action == 'create'}
{$page_title={intl l='Create a new category'}}
{else}
{$page_title={intl l='Edit category'}}
{/if}
{include file='includes/header.inc.html'}
<div class="catalog">
<div id="wrapper" class="container">
<ul class="breadcrumb">
{include file="includes/category_breadcrumb.html"}
</ul>
<div class="row-fluid">
<div class="span12 general-block-decorator">
<div class="row-fluid">
<div class="span7 title">
{if $action == 'create'}
{intl l='Create a new category'}
{else}
{intl l='Edit category'}
{/if}
</div>
<div class="span5 actions">
<button class="btn btn-primary" title="{intl l='Save and stay on this page'}">{intl l='Save'} <i class="icon icon-white icon-ok"></i></button>
<button class="btn btn-info" title="{intl l='Save and close'}">{intl l='Save'} <i class="icon icon-remove icon-white"></i></button>
{if $action != 'create'}
<button class="btn" title="{intl l='Edit previous category'}"><i class="icon icon-arrow-left"></i></button>
<button class="btn" title="{intl l='Preview category page'}"><i class="icon icon-eye-open"></i></button>
<button class="btn" title="{intl l='Edit next category'}"><i class="icon icon-arrow-right"></i></button>
{/if}
</div>
</div>
<div class="tabbable">
<ul class="nav nav-tabs" id="tabbed_menu">
<li class="active">
<a href="#general_description">{intl l="General description"}</a>
</li>
<li>
<a href="#details">{intl l="Details"}</a>
</li>
<li>
<a href="#images">{intl l="Images"}</a>
</li>
<li>
<a href="#documents">{intl l="Documents"}</a>
</li>
<li>
<a href="#modules">{intl l="Modules"}</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="general_description">
<form class="form-horizontal span12">
<fieldset>
<div class="row-fluid">
<div class="span12">
<div class="control-group">
<label class="control-label">
{intl l='Title *'}
</label>
<div class="controls">
<input type="text" required="required" title="{intl l='Category title'}" placeholder="{intl l='Category title'}" class="input-block-level">
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Summary'}
<span class="label-help-block">{intl l="A short category description, used when a summary or an introduction is required"}</span>
</label>
<div class="controls">
<textarea name="summary" rows="3" title="{intl l='Short category description'}" placeholder="{intl l='Short category description'}" class="input-block-level"></textarea>
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Detailed description'}
<span class="label-help-block">{intl l="The détailed category description."}</span>
</label>
<div class="controls">
<textarea name="summary" rows="10" class="input-block-level"></textarea>
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Conclusion'}
<span class="label-help-block">{intl l="A short post-description information"}</span>
</label>
<div class="controls">
<textarea name="summary" rows="3" title="{intl l='Short category description'}" placeholder="{intl l='Short category description'}" class="input-block-level"></textarea>
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Rewriten URL'}
</label>
<div class="controls">
<div class="input-append input-block-level">
<input type="text" required="required" title="{intl l='Rewriten URL'}" placeholder="{intl l='Rewriten URL'}" class="input-block-level">
<a class="btn add-on" href="#">{intl l='Use default'}</a>
</div>
<div class="help-block">{intl l="The rewritten URL to the category page. Click \"Use Default\" button to use the default URL. Use only digits, letters, - and _ characters."}</div>
</div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span6">
<div class="control-group">
<label class="control-label">
{intl l='Parent category *'}
</label>
<div class="controls">
<select required="required" name="parent" class="input-block-level">
<option value="">{intl l="Choose a category"}</option>
</select>
</div>
</div>
</div>
<div class="span6">
<div class="control-group">
<label class="control-label">
{intl l='Visibility'}
</label>
<div class="controls">
<label class="checkbox">
<input type="checkbox" name="visible"> {intl l="Display this category on front-office"}
</label>
</div>
</div>
</div>
</div>
<p>aff Date creation ?</p>
<p>aff date modif ?</p>
</fieldset>
</form>
</div>
<div class="tab-pane" id="details">
<p>Infos générales</p>
</div>
<div class="tab-pane" id="images">
<p>Images</p>
</div>
<div class="tab-pane" id="documents">
<p>Documents</p>
</div>
<div class="tab-pane" id="modules">
<p>Modules</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{include file='includes/js.inc.html'}
<script>
$(function() {
$('#tabbed_menu a').click(function (e) {
e.preventDefault();
$(this).tab('show');
});
})
</script>
{include file='includes/footer.inc.html'}

View File

@@ -0,0 +1,28 @@
<li><a href="{url path='admin/home'}">Home</a> <span class="divider">/</span></li>
<li><a href="{url path='admin/catalog'}">Catalog</a>
{ifloop rel="category_path"}
<span class="divider">/</span></li>
{loop name="category_path" type="category-path" category="{$current_category_id}"}
{if $ID == $current_category_id}
<li class="active">
{if $action == 'edit'}
{intl l='Editing %cat' cat="{$TITLE}"}
{else}
{$TITLE} <a href="{url path="admin/catalog/category/edit/$ID"}" title="{intl l='Edit this category'}">{intl l="(edit)"}</a>
{/if}
</li>
{else}
<li><a href="{url path="admin/catalog/category/browse/$ID"}">{$TITLE}</a> <span class="divider">/</span></li>
{/if}
{/loop}
{/ifloop}
{elseloop rel="category_path"}
{if $action == 'create'}<span class="divider">/</span>{/if}</li>
{/elseloop}
{if $action == 'create'}
<li class="active">{intl l='Create a new category'}</li>
{/if}

View File

@@ -58,6 +58,8 @@
</div>
</form>
{/loop}
<div class="view-shop"><a href="{$INDEX_PAGE}" title="{intl l='View site'}" target="_blank"><i class="icon-white icon-eye-open"></i> {intl l="View shop"}</a></div>
</div>
</div>

View File

@@ -0,0 +1,13 @@
{* Include required JS files *}
{javascripts file='../assets/js/jquery.min.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='../assets/bootstrap/js/bootstrap.min.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{* Modules scripts are included now *}
{module_include location='footer_js'}

View File

@@ -0,0 +1,10 @@
{* this temlate is loaded via Ajax in the login page, to prevent login page slowdown *}
{loop type="feed" name="thelia_feeds" url="http://thelia.net/Flux-rss.html?id_rubrique=8" limit="3"}
<div class="span4 feed-list-item">
<h3>{$DATE}</h3>
<h2><a href="#URL" target="_blank" title="{intl l='Lire la suite'}">{$TITLE|strip_tags}</a></h2>
<p>{$DESCRIPTION|strip_tags|truncate:250:"...":true}</p>
<p><a class="btn" href="#URL" target="_blank">{intl l='Lire la suite »'}</a></p>
</div>
{/loop}

View File

@@ -1,4 +0,0 @@
{loop name="cat" type="category" id="99999"}
{loop name="prod" type="product" category="#ID"}
{/loop}
{/loop}

16
templates/default/folder.html Executable file
View File

@@ -0,0 +1,16 @@
{loop name="folder0" type="folder" parent="0" order="alpha_reverse"}
<div style="border: solid 4px blue; padding: 20px; margin: 10px;">
<h2>FOLDER : #TITLE</h2>
{loop name="folder1" type="folder" parent="#ID"}
<div style="border: double 4px lightseagreen; padding: 20px; margin: 10px;">
<h3>SUBFOLDER : #TITLE (#LOOP_COUNT / #LOOP_TOTAL)</h3>
{loop name="content" type="content" folder="#ID"}
<div style="border: solid 1px green; padding: 20px; margin: 10px;">
<h3>CONTENT : #TITLE</h3>
<p>#DESCRIPTION</p>
</div>
{/loop}
</div>
{/loop}
</div>
{/loop}