diff --git a/core/lib/Thelia/Admin/Controller/CategoryController.php b/core/lib/Thelia/Admin/Controller/CategoryController.php new file mode 100644 index 000000000..6f64d2a1d --- /dev/null +++ b/core/lib/Thelia/Admin/Controller/CategoryController.php @@ -0,0 +1,63 @@ +. */ +/* */ +/*************************************************************************************/ + +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"); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 58c0c8579..c4b517c38 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -9,11 +9,13 @@ + + @@ -82,7 +84,7 @@ - false + true %kernel.environment% %kernel.debug% diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 7c9740ee0..1f26e86fb 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -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(); } diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php index 7c79811bf..965f706ad 100755 --- a/core/lib/Thelia/Core/Template/Loop/Category.php +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -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(); diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php new file mode 100644 index 000000000..e1fa1fd30 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php @@ -0,0 +1,126 @@ +. */ +/* */ +/*************************************************************************************/ + +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 : + * + * + * #TITLE + * + * + * + * Class CategoryPath + * @package Thelia\Core\Template\Loop + * @author Franck Allimant + */ +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; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Loop/Content.php b/core/lib/Thelia/Core/Template/Loop/Content.php new file mode 100755 index 000000000..f0606755d --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Content.php @@ -0,0 +1,238 @@ +. */ +/* */ +/*************************************************************************************/ + +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 + */ +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; + } + +} diff --git a/core/lib/Thelia/Core/Template/Loop/Folder.php b/core/lib/Thelia/Core/Template/Loop/Folder.php new file mode 100755 index 000000000..b6b5768fd --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Folder.php @@ -0,0 +1,179 @@ +. */ +/* */ +/*************************************************************************************/ + +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 + */ +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; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php index 817419ff4..d50bfc495 100755 --- a/core/lib/Thelia/Core/Template/Loop/Product.php +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -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()) ; diff --git a/core/lib/Thelia/Model/Folder.php b/core/lib/Thelia/Model/Folder.php index b23f5998d..a19ab6796 100755 --- a/core/lib/Thelia/Model/Folder.php +++ b/core/lib/Thelia/Model/Folder.php @@ -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; + + } } diff --git a/core/lib/Thelia/Model/FolderQuery.php b/core/lib/Thelia/Model/FolderQuery.php index 388dff085..949cbbc43 100755 --- a/core/lib/Thelia/Model/FolderQuery.php +++ b/core/lib/Thelia/Model/FolderQuery.php @@ -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 diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/ContentTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/ContentTest.php new file mode 100755 index 000000000..71922dbab --- /dev/null +++ b/core/lib/Thelia/Tests/Core/Template/Loop/ContentTest.php @@ -0,0 +1,51 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Core\Template\Loop; + +use Thelia\Tests\Core\Template\Element\BaseLoopTestor; + +use Thelia\Core\Template\Loop\Content; + +/** + * + * @author Etienne Roudeix + * + */ +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(); + } +} diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/FolderTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/FolderTest.php new file mode 100755 index 000000000..2505c2fc2 --- /dev/null +++ b/core/lib/Thelia/Tests/Core/Template/Loop/FolderTest.php @@ -0,0 +1,51 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Core\Template\Loop; + +use Thelia\Tests\Core\Template\Element\BaseLoopTestor; + +use Thelia\Core\Template\Loop\Folder; + +/** + * + * @author Etienne Roudeix + * + */ +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(); + } +} diff --git a/install/faker.php b/install/faker.php index de3992c68..23bbed2bb 100755 --- a/install/faker.php +++ b/install/faker.php @@ -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; $jsetParent($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; $kaddFolder($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; $jsetFeature($feature); + $featureAv->setPosition($j); + $featureAv->setTitle($faker->text(20)); + $featureAv->setDescription($faker->text(255)); + + $featureAv->save(); + } + } $con->commit(); } catch (Exception $e) { diff --git a/templates/admin/default/assets/css/admin.less b/templates/admin/default/assets/css/admin.less index f93a1cdd6..0c6019d78 100755 --- a/templates/admin/default/assets/css/admin.less +++ b/templates/admin/default/assets/css/admin.less @@ -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; - } - } } } \ No newline at end of file diff --git a/templates/admin/default/assets/css/img/logout.png b/templates/admin/default/assets/css/img/logout.png new file mode 100644 index 000000000..af5e214cb Binary files /dev/null and b/templates/admin/default/assets/css/img/logout.png differ diff --git a/templates/admin/default/assets/css/img/title-header.png b/templates/admin/default/assets/css/img/title-header.png new file mode 100644 index 000000000..322076e65 Binary files /dev/null and b/templates/admin/default/assets/css/img/title-header.png differ diff --git a/templates/admin/default/categories.html b/templates/admin/default/categories.html new file mode 100644 index 000000000..2a43dd426 --- /dev/null +++ b/templates/admin/default/categories.html @@ -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'} + +
+
+ + + + {module_include location='catalog_top'} + +
+
+
+ + + + {ifloop rel="category_list"} + + + + + {module_include location='category_list_header'} + + + + + + + + + {loop name="category_list" type="category" parent="{$current_category_id}" order="manual"} + + + + {module_include location='category_list_row'} + + + + + + + + {/loop} + + {/ifloop} + + {elseloop rel="category_list"} + + + + + + {/elseloop} +
+ {* 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'} + + + + +
{intl l="Category title"}{intl l="Online"}{intl l="Position"}{intl l="Actions"}
{$TITLE} + + + + {$POSITION} + + + + + +
{intl l="This category has no sub-categories. To create a new one, click the + button above."}
+
+
+
+ +
+
+
+ + + + {ifloop rel="product_list"} + + + + + + + {module_include location='product_list_header'} + + + + + + + + + {loop name="product_list" type="product" category="{$current_category_id}" order="manual"} + + + + + + {module_include location='product_list_row'} + + + + + + + + {/loop} + + {/ifloop} + + {elseloop rel="product_list"} + + + + + + {/elseloop} +
+ {* 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'} + + + + +
{intl l="Image"}{intl l="Product title"}{intl l="Online"}{intl l="Position"}{intl l="Actions"}
Image !{$TITLE} + + + + {$POSITION} + + + + +
{intl l="This category doesn't have any products. To add a new product, click the + button above."}
+
+
+
+ + {module_include location='catalog_bottom'} +
+
+ +{include file='includes/js.inc.html'} + +{include file='includes/footer.inc.html'} \ No newline at end of file diff --git a/templates/admin/default/edit_category.html b/templates/admin/default/edit_category.html new file mode 100644 index 000000000..5ad547fa0 --- /dev/null +++ b/templates/admin/default/edit_category.html @@ -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'} + +
+
+ + +
+ +
+
+
+ {if $action == 'create'} + {intl l='Create a new category'} + {else} + {intl l='Edit category'} + {/if} +
+ +
+ + + {if $action != 'create'} + + + + {/if} +
+
+ +
+ + +
+
+
+
+
+
+
+ + +
+ +
+
+ +
+ + +
+ +
+
+ +
+ + +
+ + +
+
+ +
+ + +
+ +
+
+ +
+ + +
+ +
{intl l="The rewritten URL to the category page. Click \"Use Default\" button to use the default URL. Use only digits, letters, - and _ characters."}
+
+
+ +
+
+ +
+
+ +
+ + +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+
+

aff Date creation ?

+

aff date modif ?

+
+
+
+ +
+

Infos générales

+
+
+

Images

+
+
+

Documents

+
+
+

Modules

+
+
+ +
+
+
+
+
+ +{include file='includes/js.inc.html'} + + + +{include file='includes/footer.inc.html'} \ No newline at end of file diff --git a/templates/admin/default/includes/category_breadcrumb.html b/templates/admin/default/includes/category_breadcrumb.html new file mode 100644 index 000000000..8bb6aa6ff --- /dev/null +++ b/templates/admin/default/includes/category_breadcrumb.html @@ -0,0 +1,28 @@ + +
  • Home /
  • +
  • Catalog +{ifloop rel="category_path"} + /
  • + + {loop name="category_path" type="category-path" category="{$current_category_id}"} + {if $ID == $current_category_id} +
  • + {if $action == 'edit'} + {intl l='Editing %cat' cat="{$TITLE}"} + {else} + {$TITLE} {intl l="(edit)"} + {/if} +
  • + {else} +
  • {$TITLE} /
  • + {/if} + {/loop} +{/ifloop} +{elseloop rel="category_path"} + {if $action == 'create'}/{/if} +{/elseloop} + +{if $action == 'create'} +
  • {intl l='Create a new category'}
  • +{/if} + diff --git a/templates/admin/default/includes/header.inc.html b/templates/admin/default/includes/header.inc.html index e0a6d983e..1f11208d9 100755 --- a/templates/admin/default/includes/header.inc.html +++ b/templates/admin/default/includes/header.inc.html @@ -58,6 +58,8 @@ {/loop} + + diff --git a/templates/admin/default/includes/js.inc.html b/templates/admin/default/includes/js.inc.html new file mode 100644 index 000000000..367d966ff --- /dev/null +++ b/templates/admin/default/includes/js.inc.html @@ -0,0 +1,13 @@ + +{* Include required JS files *} + +{javascripts file='../assets/js/jquery.min.js'} + +{/javascripts} + +{javascripts file='../assets/bootstrap/js/bootstrap.min.js'} + +{/javascripts} + +{* Modules scripts are included now *} +{module_include location='footer_js'} diff --git a/templates/admin/default/includes/thelia_news_feed.html b/templates/admin/default/includes/thelia_news_feed.html new file mode 100644 index 000000000..8ef8e2528 --- /dev/null +++ b/templates/admin/default/includes/thelia_news_feed.html @@ -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"} +
    +

    {$DATE}

    +

    {$TITLE|strip_tags}

    +

    {$DESCRIPTION|strip_tags|truncate:250:"...":true}

    +

    {intl l='Lire la suite »'}

    +
    +{/loop} diff --git a/templates/default/bug.html b/templates/default/bug.html index a1bc296ac..e69de29bb 100644 --- a/templates/default/bug.html +++ b/templates/default/bug.html @@ -1,4 +0,0 @@ -{loop name="cat" type="category" id="99999"} - {loop name="prod" type="product" category="#ID"} - {/loop} -{/loop} \ No newline at end of file diff --git a/templates/default/folder.html b/templates/default/folder.html new file mode 100755 index 000000000..7d12036f9 --- /dev/null +++ b/templates/default/folder.html @@ -0,0 +1,16 @@ +{loop name="folder0" type="folder" parent="0" order="alpha_reverse"} +
    +

    FOLDER : #TITLE

    + {loop name="folder1" type="folder" parent="#ID"} +
    +

    SUBFOLDER : #TITLE (#LOOP_COUNT / #LOOP_TOTAL)

    + {loop name="content" type="content" folder="#ID"} +
    +

    CONTENT : #TITLE

    +

    #DESCRIPTION

    +
    + {/loop} +
    + {/loop} +
    +{/loop} \ No newline at end of file