Added UrlRewritingTrait to manage URLs from model classes
This commit is contained in:
@@ -126,7 +126,7 @@ class CategoryController extends AbstractCrudController
|
||||
'description' => $object->getDescription(),
|
||||
'postscriptum' => $object->getPostscriptum(),
|
||||
'visible' => $object->getVisible(),
|
||||
'url' => $object->getUrl($this->getCurrentEditionLocale()),
|
||||
'url' => $object->getRewritenUrl($this->getCurrentEditionLocale()),
|
||||
'parent' => $object->getParent()
|
||||
);
|
||||
|
||||
|
||||
@@ -173,6 +173,22 @@ class Category extends BaseI18nLoop
|
||||
$loopResult = new LoopResult($categories);
|
||||
|
||||
foreach ($categories as $category) {
|
||||
|
||||
// Find previous and next category
|
||||
$previous = CategoryQuery::create()
|
||||
->filterByParent($category->getParent())
|
||||
->filterByPosition($category->getPosition(), Criteria::LESS_THAN)
|
||||
->orderByPosition(Criteria::DESC)
|
||||
->findOne()
|
||||
;
|
||||
|
||||
$next = CategoryQuery::create()
|
||||
->filterByParent($category->getParent())
|
||||
->filterByPosition($category->getPosition(), Criteria::GREATER_THAN)
|
||||
->orderByPosition(Criteria::ASC)
|
||||
->findOne()
|
||||
;
|
||||
|
||||
/*
|
||||
* no cause pagination lost :
|
||||
* if ($this->getNotEmpty() && $category->countAllProducts() == 0) continue;
|
||||
@@ -193,7 +209,13 @@ class Category extends BaseI18nLoop
|
||||
->set("PRODUCT_COUNT", $category->countChild())
|
||||
->set("VISIBLE", $category->getVisible() ? "1" : "0")
|
||||
->set("POSITION", $category->getPosition())
|
||||
;
|
||||
|
||||
->set("HAS_PREVIOUS", $previous != null ? 1 : 0)
|
||||
->set("HAS_NEXT" , $next != null ? 1 : 0)
|
||||
|
||||
->set("PREVIOUS", $previous != null ? $previous->getId() : -1)
|
||||
->set("NEXT" , $next != null ? $next->getId() : -1)
|
||||
;
|
||||
|
||||
$loopResult->addRow($loopResultRow);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ class Category extends BaseCategory
|
||||
|
||||
use \Thelia\Model\Tools\PositionManagementTrait;
|
||||
|
||||
use \Thelia\Model\Tools\UrlRewritingTrait;
|
||||
|
||||
/**
|
||||
* @return int number of child for the current category
|
||||
*/
|
||||
@@ -23,9 +25,11 @@ class Category extends BaseCategory
|
||||
return CategoryQuery::countChild($this->getId());
|
||||
}
|
||||
|
||||
public function getUrl($locale)
|
||||
{
|
||||
return URL::getInstance()->retrieve('category', $this->getId(), $locale)->toString();
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
return 'category';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,20 +55,38 @@ class Category extends BaseCategory
|
||||
return $countProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate next position relative to our parent
|
||||
*/
|
||||
protected function addCriteriaToPositionQuery($query) {
|
||||
$query->filterByParent($this->getParent());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->setPosition($this->getNextPosition($this->parent));
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
$this->dispatchEvent(TheliaEvents::BEFORE_CREATECATEGORY, new CategoryEvent($this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function postInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::AFTER_CREATECATEGORY, new CategoryEvent($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preUpdate(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::BEFORE_UPDATECATEGORY, new CategoryEvent($this));
|
||||
@@ -72,11 +94,17 @@ class Category extends BaseCategory
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function postUpdate(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::AFTER_UPDATECATEGORY, new CategoryEvent($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preDelete(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::BEFORE_DELETECATEGORY, new CategoryEvent($this));
|
||||
@@ -84,6 +112,9 @@ class Category extends BaseCategory
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function postDelete(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->dispatchEvent(TheliaEvents::AFTER_DELETECATEGORY, new CategoryEvent($this));
|
||||
|
||||
@@ -4,11 +4,41 @@ namespace Thelia\Model;
|
||||
|
||||
use Thelia\Model\Base\Content as BaseContent;
|
||||
use Thelia\Tools\URL;
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
|
||||
class Content extends BaseContent
|
||||
{
|
||||
public function getUrl($locale)
|
||||
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
|
||||
|
||||
use \Thelia\Model\Tools\PositionManagementTrait;
|
||||
|
||||
use \Thelia\Model\Tools\UrlRewritingTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
return 'content';
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate next position relative to our parent
|
||||
*/
|
||||
protected function addCriteriaToPositionQuery($query) {
|
||||
|
||||
// TODO: Find the default folder for this content,
|
||||
// and generate the position relative to this folder
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
return URL::getInstance()->retrieve('content', $this->getId(), $locale)->toString();
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,19 @@ use Thelia\Tools\URL;
|
||||
|
||||
class Folder extends BaseFolder
|
||||
{
|
||||
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
|
||||
|
||||
use \Thelia\Model\Tools\PositionManagementTrait;
|
||||
|
||||
use \Thelia\Model\Tools\UrlRewritingTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
return 'folder';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int number of contents for the folder
|
||||
*/
|
||||
@@ -15,11 +28,6 @@ class Folder extends BaseFolder
|
||||
return FolderQuery::countChild($this->getId());
|
||||
}
|
||||
|
||||
public function getUrl($locale)
|
||||
{
|
||||
return URL::getInstance()->retrieve('folder', $this->getId(), $locale)->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* count all products for current category and sub categories
|
||||
@@ -43,4 +51,23 @@ class Folder extends BaseFolder
|
||||
return $contentsCount;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate next position relative to our parent
|
||||
*/
|
||||
protected function addCriteriaToPositionQuery($query) {
|
||||
$query->filterByParent($this->getParent());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,16 +9,25 @@ use Thelia\TaxEngine\Calculator;
|
||||
|
||||
class Product extends BaseProduct
|
||||
{
|
||||
public function getUrl($locale)
|
||||
{
|
||||
return URL::getInstance()->retrieve('product', $this->getId(), $locale)->toString();
|
||||
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
|
||||
|
||||
use \Thelia\Model\Tools\PositionManagementTrait;
|
||||
|
||||
use \Thelia\Model\Tools\UrlRewritingTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getRewritenUrlViewName() {
|
||||
return 'product';
|
||||
}
|
||||
|
||||
public function getRealLowestPrice($virtualColumnName = 'real_lowest_price')
|
||||
{
|
||||
try {
|
||||
$amount = $this->getVirtualColumn($virtualColumnName);
|
||||
} catch(PropelException $e) {
|
||||
}
|
||||
catch(PropelException $e) {
|
||||
throw new PropelException("Virtual column `$virtualColumnName` does not exist in Product::getRealLowestPrice");
|
||||
}
|
||||
|
||||
@@ -30,4 +39,26 @@ class Product extends BaseProduct
|
||||
$taxCalculator = new Calculator();
|
||||
return $taxCalculator->load($this, $country)->getTaxedPrice($this->getRealLowestPrice());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate next position relative to our default category
|
||||
*/
|
||||
protected function addCriteriaToPositionQuery($query) {
|
||||
|
||||
// TODO: Find the default category for this product,
|
||||
// and generate the position relative to this category
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
$this->generateRewritenUrl($this->getLocale());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
78
core/lib/Thelia/Model/Tools/UrlRewritingTrait.php
Normal file
78
core/lib/Thelia/Model/Tools/UrlRewritingTrait.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?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 Thelia\Tools\URL;
|
||||
/**
|
||||
* A trait for managing Rewriten URLs from model classes
|
||||
*/
|
||||
trait UrlRewritingTrait {
|
||||
|
||||
/**
|
||||
* @returns string the view name of the rewriten object (e.g., 'category', 'product')
|
||||
*/
|
||||
protected abstract function getRewritenUrlViewName();
|
||||
|
||||
/**
|
||||
* Get the object URL for the given locale, rewriten if rewriting is enabled.
|
||||
*
|
||||
* @param string $locale a valid locale (e.g. en_US)
|
||||
*/
|
||||
public function getUrl($locale)
|
||||
{
|
||||
return URL::getInstance()->retrieve($this->getRewritenUrlViewName(), $this->getId(), $locale)->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a rewriten URL from the object title, and store it in the rewriting table
|
||||
*
|
||||
* @param string $locale a valid locale (e.g. en_US)
|
||||
*/
|
||||
public function generateRewritenUrl($locale)
|
||||
{
|
||||
URL::getInstance()->generateRewritenUrl($this->getRewritenUrlViewName(), $this->getId(), $locale, $this->getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* return the rewriten URL for the given locale
|
||||
*
|
||||
* @param string $locale a valid locale (e.g. en_US)
|
||||
*/
|
||||
public function getRewritenUrl($locale)
|
||||
{
|
||||
return "fake url - TODO";
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rewriten URL for the given locale
|
||||
*
|
||||
* @param string $locale a valid locale (e.g. en_US)
|
||||
*/
|
||||
public function setRewritenUrl($locale, $url)
|
||||
{
|
||||
// TODO - code me !
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -183,6 +183,7 @@ class URL
|
||||
|
||||
return $this->absoluteUrl($path, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a rewritten URL from a view, a view id and a locale
|
||||
*
|
||||
@@ -261,4 +262,50 @@ class URL
|
||||
|
||||
return $this->resolver;
|
||||
}
|
||||
|
||||
protected function sanitize($string, $force_lowercase = true, $alphabetic_only = false)
|
||||
{
|
||||
static $strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]",
|
||||
"}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—",
|
||||
"—", "–", ",", "<", ".", ">", "/", "?");
|
||||
|
||||
$clean = trim(str_replace($strip, "", strip_tags($string)));
|
||||
|
||||
$clean = preg_replace('/\s+/', "-", $clean);
|
||||
|
||||
$clean = ($alphabetic_only) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;
|
||||
|
||||
return ($force_lowercase) ?
|
||||
(function_exists('mb_strtolower')) ?
|
||||
mb_strtolower($clean, 'UTF-8') :
|
||||
strtolower($clean) :
|
||||
$clean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Genenerate the file part of a rewriten URL from a given baseString, using a view, a view id and a locale
|
||||
*
|
||||
* @param $view
|
||||
* @param $viewId
|
||||
* @param $viewLocale
|
||||
* @param $baseString the string to be converted in a valid URL
|
||||
*
|
||||
* @return A valid file part URL.
|
||||
*/
|
||||
public function generateRewritenUrl($view, $viewId, $viewLocale, $baseString)
|
||||
{
|
||||
// Borrowed from http://stackoverflow.com/questions/2668854/sanitizing-strings-to-make-them-url-and-filename-safe
|
||||
|
||||
// Replace all weird characters with dashes
|
||||
$string = preg_replace('/[^\w\-~_\.]+/u', '-', $baseString);
|
||||
|
||||
// Only allow one dash separator at a time (and make string lowercase)
|
||||
$cleanString = mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8');
|
||||
|
||||
$urlFilePart = $cleanString . ".html";
|
||||
|
||||
// TODO :
|
||||
// check if URL url already exists, and add a numeric suffix, or the like
|
||||
// insert the URL in the rewriting table
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,20 +8,31 @@
|
||||
<div class="catalog edit-category">
|
||||
<div id="wrapper" class="container">
|
||||
|
||||
{include file="includes/catalog-breadcrumb.html"}
|
||||
{include file="includes/catalog-breadcrumb.html" editing_category="true"}
|
||||
|
||||
<div class="row">
|
||||
{loop name="category_edit" type="category" visible="*" id="{$category_id}" backend_context="1" lang="$edit_language_id"}
|
||||
<div class="col-md-12 general-block-decorator">
|
||||
<div class="row">
|
||||
<div class="col-md-7 title">
|
||||
{intl l='Edit category'}
|
||||
{intl l='Edit category %title' title=$TITLE}
|
||||
</div>
|
||||
|
||||
<div class="col-md-5 actions">
|
||||
<button class="btn btn-default" title="{intl l='Edit previous category'}"><i class="glyphicon glyphicon-arrow-left"></i></button>
|
||||
<button class="btn btn-default" title="{intl l='Preview category page'}"><i class="glyphicon glyphicon-eye-open"></i></button>
|
||||
<button class="btn btn-default" title="{intl l='Edit next category'}"><i class="glyphicon glyphicon-arrow-right"></i></button>
|
||||
|
||||
{if $HAS_PREVIOUS != 0}
|
||||
<a href="{url path='/admin/categories/update' category_id=$PREVIOUS}" class="btn btn-default" title="{intl l='Edit previous category'}"><span class="glyphicon glyphicon-arrow-left"></span></a>
|
||||
{else}
|
||||
<a href="#" disabled="disabled" class="btn btn-default"><span class="glyphicon glyphicon-arrow-left"></span></a>
|
||||
{/if}
|
||||
|
||||
<a href="{$URL}" target="_blank" class="btn btn-default" title="{intl l='Preview category page'}"><span class="glyphicon glyphicon-eye-open"></span></a>
|
||||
|
||||
{if $HAS_NEXT != 0}
|
||||
<a href="{url path='/admin/categories/update' category_id=$NEXT}" class="btn btn-default" title="{intl l='Edit next category'}"><span class="glyphicon glyphicon-arrow-right"></span></a>
|
||||
{else}
|
||||
<a href="#" disabled="disabled" class="btn btn-default"><span class="glyphicon glyphicon-arrow-right"></span></a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
{loop name="category_path" type="category-path" visible="*" category=$category_id}
|
||||
{if $ID == $category_id}
|
||||
<li class="active">
|
||||
{if $action == 'edit'}
|
||||
{intl l='Editing %cat' cat="{$TITLE}"}
|
||||
{if $editing_category == true}
|
||||
{intl l='Editing %cat' cat="{$TITLE}"}
|
||||
{else}
|
||||
{$TITLE} <a href="{url path='admin/catalog/category/edit' category_id=$ID}" title="{intl l='Edit this category'}">{intl l="(edit)"}</a>
|
||||
{$TITLE} <a href="{url path='/admin/categories/update' category_id=$ID}" title="{intl l='Edit this category'}">{intl l="(edit)"}</a>
|
||||
{/if}
|
||||
</li>
|
||||
{else}
|
||||
<li><a href="{url path='admin/catalog/category' id=" $ID" action='browse'}">{$TITLE}</a></li>
|
||||
<li><a href="{url path='/admin/categories' category_id=" $ID" action='browse'}">{$TITLE}</a></li>
|
||||
{/if}
|
||||
{/loop}
|
||||
{/ifloop}
|
||||
|
||||
Reference in New Issue
Block a user