From a3beb4c6f40b0f7048f1222b8127204142b7a082 Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:00:07 +0100 Subject: [PATCH 01/10] Add new fields (meta_title, meta_description and meta_keyword) under I18N Product --- core/lib/Thelia/Model/Base/Product.php | 72 + core/lib/Thelia/Model/Base/ProductI18n.php | 176 +- .../Thelia/Model/Base/ProductI18nQuery.php | 101 +- .../Thelia/Model/Map/ProductI18nTableMap.php | 52 +- core/lib/Thelia/Model/Map/ProductTableMap.php | 2 +- install/thelia.sql | 3 + local/config/schema.xml | 2531 +++++++++-------- 7 files changed, 1656 insertions(+), 1281 deletions(-) diff --git a/core/lib/Thelia/Model/Base/Product.php b/core/lib/Thelia/Model/Base/Product.php index 77824575c..e850d2acf 100644 --- a/core/lib/Thelia/Model/Base/Product.php +++ b/core/lib/Thelia/Model/Base/Product.php @@ -5866,6 +5866,78 @@ abstract class Product implements ActiveRecordInterface return $this; } + + /** + * Get the [meta_title] column value. + * + * @return string + */ + public function getMetaTitle() + { + return $this->getCurrentTranslation()->getMetaTitle(); + } + + + /** + * Set the value of [meta_title] column. + * + * @param string $v new value + * @return \Thelia\Model\ProductI18n The current object (for fluent API support) + */ + public function setMetaTitle($v) + { $this->getCurrentTranslation()->setMetaTitle($v); + + return $this; + } + + + /** + * Get the [meta_description] column value. + * + * @return string + */ + public function getMetaDescription() + { + return $this->getCurrentTranslation()->getMetaDescription(); + } + + + /** + * Set the value of [meta_description] column. + * + * @param string $v new value + * @return \Thelia\Model\ProductI18n The current object (for fluent API support) + */ + public function setMetaDescription($v) + { $this->getCurrentTranslation()->setMetaDescription($v); + + return $this; + } + + + /** + * Get the [meta_keyword] column value. + * + * @return string + */ + public function getMetaKeyword() + { + return $this->getCurrentTranslation()->getMetaKeyword(); + } + + + /** + * Set the value of [meta_keyword] column. + * + * @param string $v new value + * @return \Thelia\Model\ProductI18n The current object (for fluent API support) + */ + public function setMetaKeyword($v) + { $this->getCurrentTranslation()->setMetaKeyword($v); + + return $this; + } + // versionable behavior /** diff --git a/core/lib/Thelia/Model/Base/ProductI18n.php b/core/lib/Thelia/Model/Base/ProductI18n.php index cdab7349d..a72f07c83 100644 --- a/core/lib/Thelia/Model/Base/ProductI18n.php +++ b/core/lib/Thelia/Model/Base/ProductI18n.php @@ -90,6 +90,24 @@ abstract class ProductI18n implements ActiveRecordInterface */ protected $postscriptum; + /** + * The value for the meta_title field. + * @var string + */ + protected $meta_title; + + /** + * The value for the meta_description field. + * @var string + */ + protected $meta_description; + + /** + * The value for the meta_keyword field. + * @var string + */ + protected $meta_keyword; + /** * @var Product */ @@ -440,6 +458,39 @@ abstract class ProductI18n implements ActiveRecordInterface return $this->postscriptum; } + /** + * Get the [meta_title] column value. + * + * @return string + */ + public function getMetaTitle() + { + + return $this->meta_title; + } + + /** + * Get the [meta_description] column value. + * + * @return string + */ + public function getMetaDescription() + { + + return $this->meta_description; + } + + /** + * Get the [meta_keyword] column value. + * + * @return string + */ + public function getMetaKeyword() + { + + return $this->meta_keyword; + } + /** * Set the value of [id] column. * @@ -570,6 +621,69 @@ abstract class ProductI18n implements ActiveRecordInterface return $this; } // setPostscriptum() + /** + * Set the value of [meta_title] column. + * + * @param string $v new value + * @return \Thelia\Model\ProductI18n The current object (for fluent API support) + */ + public function setMetaTitle($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->meta_title !== $v) { + $this->meta_title = $v; + $this->modifiedColumns[] = ProductI18nTableMap::META_TITLE; + } + + + return $this; + } // setMetaTitle() + + /** + * Set the value of [meta_description] column. + * + * @param string $v new value + * @return \Thelia\Model\ProductI18n The current object (for fluent API support) + */ + public function setMetaDescription($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->meta_description !== $v) { + $this->meta_description = $v; + $this->modifiedColumns[] = ProductI18nTableMap::META_DESCRIPTION; + } + + + return $this; + } // setMetaDescription() + + /** + * Set the value of [meta_keyword] column. + * + * @param string $v new value + * @return \Thelia\Model\ProductI18n The current object (for fluent API support) + */ + public function setMetaKeyword($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->meta_keyword !== $v) { + $this->meta_keyword = $v; + $this->modifiedColumns[] = ProductI18nTableMap::META_KEYWORD; + } + + + return $this; + } // setMetaKeyword() + /** * Indicates whether the columns in this object are only set to default values. * @@ -628,6 +742,15 @@ abstract class ProductI18n implements ActiveRecordInterface $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : ProductI18nTableMap::translateFieldName('Postscriptum', TableMap::TYPE_PHPNAME, $indexType)]; $this->postscriptum = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : ProductI18nTableMap::translateFieldName('MetaTitle', TableMap::TYPE_PHPNAME, $indexType)]; + $this->meta_title = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 7 + $startcol : ProductI18nTableMap::translateFieldName('MetaDescription', TableMap::TYPE_PHPNAME, $indexType)]; + $this->meta_description = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 8 + $startcol : ProductI18nTableMap::translateFieldName('MetaKeyword', TableMap::TYPE_PHPNAME, $indexType)]; + $this->meta_keyword = (null !== $col) ? (string) $col : null; $this->resetModified(); $this->setNew(false); @@ -636,7 +759,7 @@ abstract class ProductI18n implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 6; // 6 = ProductI18nTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 9; // 9 = ProductI18nTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\ProductI18n object", 0, $e); @@ -875,6 +998,15 @@ abstract class ProductI18n implements ActiveRecordInterface if ($this->isColumnModified(ProductI18nTableMap::POSTSCRIPTUM)) { $modifiedColumns[':p' . $index++] = 'POSTSCRIPTUM'; } + if ($this->isColumnModified(ProductI18nTableMap::META_TITLE)) { + $modifiedColumns[':p' . $index++] = 'META_TITLE'; + } + if ($this->isColumnModified(ProductI18nTableMap::META_DESCRIPTION)) { + $modifiedColumns[':p' . $index++] = 'META_DESCRIPTION'; + } + if ($this->isColumnModified(ProductI18nTableMap::META_KEYWORD)) { + $modifiedColumns[':p' . $index++] = 'META_KEYWORD'; + } $sql = sprintf( 'INSERT INTO product_i18n (%s) VALUES (%s)', @@ -904,6 +1036,15 @@ abstract class ProductI18n implements ActiveRecordInterface case 'POSTSCRIPTUM': $stmt->bindValue($identifier, $this->postscriptum, PDO::PARAM_STR); break; + case 'META_TITLE': + $stmt->bindValue($identifier, $this->meta_title, PDO::PARAM_STR); + break; + case 'META_DESCRIPTION': + $stmt->bindValue($identifier, $this->meta_description, PDO::PARAM_STR); + break; + case 'META_KEYWORD': + $stmt->bindValue($identifier, $this->meta_keyword, PDO::PARAM_STR); + break; } } $stmt->execute(); @@ -977,6 +1118,15 @@ abstract class ProductI18n implements ActiveRecordInterface case 5: return $this->getPostscriptum(); break; + case 6: + return $this->getMetaTitle(); + break; + case 7: + return $this->getMetaDescription(); + break; + case 8: + return $this->getMetaKeyword(); + break; default: return null; break; @@ -1012,6 +1162,9 @@ abstract class ProductI18n implements ActiveRecordInterface $keys[3] => $this->getDescription(), $keys[4] => $this->getChapo(), $keys[5] => $this->getPostscriptum(), + $keys[6] => $this->getMetaTitle(), + $keys[7] => $this->getMetaDescription(), + $keys[8] => $this->getMetaKeyword(), ); $virtualColumns = $this->virtualColumns; foreach ($virtualColumns as $key => $virtualColumn) { @@ -1074,6 +1227,15 @@ abstract class ProductI18n implements ActiveRecordInterface case 5: $this->setPostscriptum($value); break; + case 6: + $this->setMetaTitle($value); + break; + case 7: + $this->setMetaDescription($value); + break; + case 8: + $this->setMetaKeyword($value); + break; } // switch() } @@ -1104,6 +1266,9 @@ abstract class ProductI18n implements ActiveRecordInterface if (array_key_exists($keys[3], $arr)) $this->setDescription($arr[$keys[3]]); if (array_key_exists($keys[4], $arr)) $this->setChapo($arr[$keys[4]]); if (array_key_exists($keys[5], $arr)) $this->setPostscriptum($arr[$keys[5]]); + if (array_key_exists($keys[6], $arr)) $this->setMetaTitle($arr[$keys[6]]); + if (array_key_exists($keys[7], $arr)) $this->setMetaDescription($arr[$keys[7]]); + if (array_key_exists($keys[8], $arr)) $this->setMetaKeyword($arr[$keys[8]]); } /** @@ -1121,6 +1286,9 @@ abstract class ProductI18n implements ActiveRecordInterface if ($this->isColumnModified(ProductI18nTableMap::DESCRIPTION)) $criteria->add(ProductI18nTableMap::DESCRIPTION, $this->description); if ($this->isColumnModified(ProductI18nTableMap::CHAPO)) $criteria->add(ProductI18nTableMap::CHAPO, $this->chapo); if ($this->isColumnModified(ProductI18nTableMap::POSTSCRIPTUM)) $criteria->add(ProductI18nTableMap::POSTSCRIPTUM, $this->postscriptum); + if ($this->isColumnModified(ProductI18nTableMap::META_TITLE)) $criteria->add(ProductI18nTableMap::META_TITLE, $this->meta_title); + if ($this->isColumnModified(ProductI18nTableMap::META_DESCRIPTION)) $criteria->add(ProductI18nTableMap::META_DESCRIPTION, $this->meta_description); + if ($this->isColumnModified(ProductI18nTableMap::META_KEYWORD)) $criteria->add(ProductI18nTableMap::META_KEYWORD, $this->meta_keyword); return $criteria; } @@ -1197,6 +1365,9 @@ abstract class ProductI18n implements ActiveRecordInterface $copyObj->setDescription($this->getDescription()); $copyObj->setChapo($this->getChapo()); $copyObj->setPostscriptum($this->getPostscriptum()); + $copyObj->setMetaTitle($this->getMetaTitle()); + $copyObj->setMetaDescription($this->getMetaDescription()); + $copyObj->setMetaKeyword($this->getMetaKeyword()); if ($makeNew) { $copyObj->setNew(true); } @@ -1286,6 +1457,9 @@ abstract class ProductI18n implements ActiveRecordInterface $this->description = null; $this->chapo = null; $this->postscriptum = null; + $this->meta_title = null; + $this->meta_description = null; + $this->meta_keyword = null; $this->alreadyInSave = false; $this->clearAllReferences(); $this->applyDefaultValues(); diff --git a/core/lib/Thelia/Model/Base/ProductI18nQuery.php b/core/lib/Thelia/Model/Base/ProductI18nQuery.php index d64c95892..01d3af9d4 100644 --- a/core/lib/Thelia/Model/Base/ProductI18nQuery.php +++ b/core/lib/Thelia/Model/Base/ProductI18nQuery.php @@ -27,6 +27,9 @@ use Thelia\Model\Map\ProductI18nTableMap; * @method ChildProductI18nQuery orderByDescription($order = Criteria::ASC) Order by the description column * @method ChildProductI18nQuery orderByChapo($order = Criteria::ASC) Order by the chapo column * @method ChildProductI18nQuery orderByPostscriptum($order = Criteria::ASC) Order by the postscriptum column + * @method ChildProductI18nQuery orderByMetaTitle($order = Criteria::ASC) Order by the meta_title column + * @method ChildProductI18nQuery orderByMetaDescription($order = Criteria::ASC) Order by the meta_description column + * @method ChildProductI18nQuery orderByMetaKeyword($order = Criteria::ASC) Order by the meta_keyword column * * @method ChildProductI18nQuery groupById() Group by the id column * @method ChildProductI18nQuery groupByLocale() Group by the locale column @@ -34,6 +37,9 @@ use Thelia\Model\Map\ProductI18nTableMap; * @method ChildProductI18nQuery groupByDescription() Group by the description column * @method ChildProductI18nQuery groupByChapo() Group by the chapo column * @method ChildProductI18nQuery groupByPostscriptum() Group by the postscriptum column + * @method ChildProductI18nQuery groupByMetaTitle() Group by the meta_title column + * @method ChildProductI18nQuery groupByMetaDescription() Group by the meta_description column + * @method ChildProductI18nQuery groupByMetaKeyword() Group by the meta_keyword column * * @method ChildProductI18nQuery leftJoin($relation) Adds a LEFT JOIN clause to the query * @method ChildProductI18nQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query @@ -52,6 +58,9 @@ use Thelia\Model\Map\ProductI18nTableMap; * @method ChildProductI18n findOneByDescription(string $description) Return the first ChildProductI18n filtered by the description column * @method ChildProductI18n findOneByChapo(string $chapo) Return the first ChildProductI18n filtered by the chapo column * @method ChildProductI18n findOneByPostscriptum(string $postscriptum) Return the first ChildProductI18n filtered by the postscriptum column + * @method ChildProductI18n findOneByMetaTitle(string $meta_title) Return the first ChildProductI18n filtered by the meta_title column + * @method ChildProductI18n findOneByMetaDescription(string $meta_description) Return the first ChildProductI18n filtered by the meta_description column + * @method ChildProductI18n findOneByMetaKeyword(string $meta_keyword) Return the first ChildProductI18n filtered by the meta_keyword column * * @method array findById(int $id) Return ChildProductI18n objects filtered by the id column * @method array findByLocale(string $locale) Return ChildProductI18n objects filtered by the locale column @@ -59,6 +68,9 @@ use Thelia\Model\Map\ProductI18nTableMap; * @method array findByDescription(string $description) Return ChildProductI18n objects filtered by the description column * @method array findByChapo(string $chapo) Return ChildProductI18n objects filtered by the chapo column * @method array findByPostscriptum(string $postscriptum) Return ChildProductI18n objects filtered by the postscriptum column + * @method array findByMetaTitle(string $meta_title) Return ChildProductI18n objects filtered by the meta_title column + * @method array findByMetaDescription(string $meta_description) Return ChildProductI18n objects filtered by the meta_description column + * @method array findByMetaKeyword(string $meta_keyword) Return ChildProductI18n objects filtered by the meta_keyword column * */ abstract class ProductI18nQuery extends ModelCriteria @@ -147,7 +159,7 @@ abstract class ProductI18nQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, LOCALE, TITLE, DESCRIPTION, CHAPO, POSTSCRIPTUM FROM product_i18n WHERE ID = :p0 AND LOCALE = :p1'; + $sql = 'SELECT ID, LOCALE, TITLE, DESCRIPTION, CHAPO, POSTSCRIPTUM, META_TITLE, META_DESCRIPTION, META_KEYWORD FROM product_i18n WHERE ID = :p0 AND LOCALE = :p1'; try { $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); @@ -436,6 +448,93 @@ abstract class ProductI18nQuery extends ModelCriteria return $this->addUsingAlias(ProductI18nTableMap::POSTSCRIPTUM, $postscriptum, $comparison); } + /** + * Filter the query on the meta_title column + * + * Example usage: + * + * $query->filterByMetaTitle('fooValue'); // WHERE meta_title = 'fooValue' + * $query->filterByMetaTitle('%fooValue%'); // WHERE meta_title LIKE '%fooValue%' + * + * + * @param string $metaTitle The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductI18nQuery The current query, for fluid interface + */ + public function filterByMetaTitle($metaTitle = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($metaTitle)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $metaTitle)) { + $metaTitle = str_replace('*', '%', $metaTitle); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(ProductI18nTableMap::META_TITLE, $metaTitle, $comparison); + } + + /** + * Filter the query on the meta_description column + * + * Example usage: + * + * $query->filterByMetaDescription('fooValue'); // WHERE meta_description = 'fooValue' + * $query->filterByMetaDescription('%fooValue%'); // WHERE meta_description LIKE '%fooValue%' + * + * + * @param string $metaDescription The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductI18nQuery The current query, for fluid interface + */ + public function filterByMetaDescription($metaDescription = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($metaDescription)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $metaDescription)) { + $metaDescription = str_replace('*', '%', $metaDescription); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(ProductI18nTableMap::META_DESCRIPTION, $metaDescription, $comparison); + } + + /** + * Filter the query on the meta_keyword column + * + * Example usage: + * + * $query->filterByMetaKeyword('fooValue'); // WHERE meta_keyword = 'fooValue' + * $query->filterByMetaKeyword('%fooValue%'); // WHERE meta_keyword LIKE '%fooValue%' + * + * + * @param string $metaKeyword The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductI18nQuery The current query, for fluid interface + */ + public function filterByMetaKeyword($metaKeyword = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($metaKeyword)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $metaKeyword)) { + $metaKeyword = str_replace('*', '%', $metaKeyword); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(ProductI18nTableMap::META_KEYWORD, $metaKeyword, $comparison); + } + /** * Filter the query by a related \Thelia\Model\Product object * diff --git a/core/lib/Thelia/Model/Map/ProductI18nTableMap.php b/core/lib/Thelia/Model/Map/ProductI18nTableMap.php index 79a01514a..e082ebccb 100644 --- a/core/lib/Thelia/Model/Map/ProductI18nTableMap.php +++ b/core/lib/Thelia/Model/Map/ProductI18nTableMap.php @@ -57,7 +57,7 @@ class ProductI18nTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 6; + const NUM_COLUMNS = 9; /** * The number of lazy-loaded columns @@ -67,7 +67,7 @@ class ProductI18nTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 6; + const NUM_HYDRATE_COLUMNS = 9; /** * the column name for the ID field @@ -99,6 +99,21 @@ class ProductI18nTableMap extends TableMap */ const POSTSCRIPTUM = 'product_i18n.POSTSCRIPTUM'; + /** + * the column name for the META_TITLE field + */ + const META_TITLE = 'product_i18n.META_TITLE'; + + /** + * the column name for the META_DESCRIPTION field + */ + const META_DESCRIPTION = 'product_i18n.META_DESCRIPTION'; + + /** + * the column name for the META_KEYWORD field + */ + const META_KEYWORD = 'product_i18n.META_KEYWORD'; + /** * The default string format for model objects of the related table */ @@ -111,12 +126,12 @@ class ProductI18nTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'Locale', 'Title', 'Description', 'Chapo', 'Postscriptum', ), - self::TYPE_STUDLYPHPNAME => array('id', 'locale', 'title', 'description', 'chapo', 'postscriptum', ), - self::TYPE_COLNAME => array(ProductI18nTableMap::ID, ProductI18nTableMap::LOCALE, ProductI18nTableMap::TITLE, ProductI18nTableMap::DESCRIPTION, ProductI18nTableMap::CHAPO, ProductI18nTableMap::POSTSCRIPTUM, ), - self::TYPE_RAW_COLNAME => array('ID', 'LOCALE', 'TITLE', 'DESCRIPTION', 'CHAPO', 'POSTSCRIPTUM', ), - self::TYPE_FIELDNAME => array('id', 'locale', 'title', 'description', 'chapo', 'postscriptum', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, ) + self::TYPE_PHPNAME => array('Id', 'Locale', 'Title', 'Description', 'Chapo', 'Postscriptum', 'MetaTitle', 'MetaDescription', 'MetaKeyword', ), + self::TYPE_STUDLYPHPNAME => array('id', 'locale', 'title', 'description', 'chapo', 'postscriptum', 'metaTitle', 'metaDescription', 'metaKeyword', ), + self::TYPE_COLNAME => array(ProductI18nTableMap::ID, ProductI18nTableMap::LOCALE, ProductI18nTableMap::TITLE, ProductI18nTableMap::DESCRIPTION, ProductI18nTableMap::CHAPO, ProductI18nTableMap::POSTSCRIPTUM, ProductI18nTableMap::META_TITLE, ProductI18nTableMap::META_DESCRIPTION, ProductI18nTableMap::META_KEYWORD, ), + self::TYPE_RAW_COLNAME => array('ID', 'LOCALE', 'TITLE', 'DESCRIPTION', 'CHAPO', 'POSTSCRIPTUM', 'META_TITLE', 'META_DESCRIPTION', 'META_KEYWORD', ), + self::TYPE_FIELDNAME => array('id', 'locale', 'title', 'description', 'chapo', 'postscriptum', 'meta_title', 'meta_description', 'meta_keyword', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, ) ); /** @@ -126,12 +141,12 @@ class ProductI18nTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'Locale' => 1, 'Title' => 2, 'Description' => 3, 'Chapo' => 4, 'Postscriptum' => 5, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'locale' => 1, 'title' => 2, 'description' => 3, 'chapo' => 4, 'postscriptum' => 5, ), - self::TYPE_COLNAME => array(ProductI18nTableMap::ID => 0, ProductI18nTableMap::LOCALE => 1, ProductI18nTableMap::TITLE => 2, ProductI18nTableMap::DESCRIPTION => 3, ProductI18nTableMap::CHAPO => 4, ProductI18nTableMap::POSTSCRIPTUM => 5, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'LOCALE' => 1, 'TITLE' => 2, 'DESCRIPTION' => 3, 'CHAPO' => 4, 'POSTSCRIPTUM' => 5, ), - self::TYPE_FIELDNAME => array('id' => 0, 'locale' => 1, 'title' => 2, 'description' => 3, 'chapo' => 4, 'postscriptum' => 5, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, ) + self::TYPE_PHPNAME => array('Id' => 0, 'Locale' => 1, 'Title' => 2, 'Description' => 3, 'Chapo' => 4, 'Postscriptum' => 5, 'MetaTitle' => 6, 'MetaDescription' => 7, 'MetaKeyword' => 8, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'locale' => 1, 'title' => 2, 'description' => 3, 'chapo' => 4, 'postscriptum' => 5, 'metaTitle' => 6, 'metaDescription' => 7, 'metaKeyword' => 8, ), + self::TYPE_COLNAME => array(ProductI18nTableMap::ID => 0, ProductI18nTableMap::LOCALE => 1, ProductI18nTableMap::TITLE => 2, ProductI18nTableMap::DESCRIPTION => 3, ProductI18nTableMap::CHAPO => 4, ProductI18nTableMap::POSTSCRIPTUM => 5, ProductI18nTableMap::META_TITLE => 6, ProductI18nTableMap::META_DESCRIPTION => 7, ProductI18nTableMap::META_KEYWORD => 8, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'LOCALE' => 1, 'TITLE' => 2, 'DESCRIPTION' => 3, 'CHAPO' => 4, 'POSTSCRIPTUM' => 5, 'META_TITLE' => 6, 'META_DESCRIPTION' => 7, 'META_KEYWORD' => 8, ), + self::TYPE_FIELDNAME => array('id' => 0, 'locale' => 1, 'title' => 2, 'description' => 3, 'chapo' => 4, 'postscriptum' => 5, 'meta_title' => 6, 'meta_description' => 7, 'meta_keyword' => 8, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, ) ); /** @@ -156,6 +171,9 @@ class ProductI18nTableMap extends TableMap $this->addColumn('DESCRIPTION', 'Description', 'CLOB', false, null, null); $this->addColumn('CHAPO', 'Chapo', 'LONGVARCHAR', false, null, null); $this->addColumn('POSTSCRIPTUM', 'Postscriptum', 'LONGVARCHAR', false, null, null); + $this->addColumn('META_TITLE', 'MetaTitle', 'VARCHAR', false, 255, null); + $this->addColumn('META_DESCRIPTION', 'MetaDescription', 'LONGVARCHAR', false, null, null); + $this->addColumn('META_KEYWORD', 'MetaKeyword', 'LONGVARCHAR', false, null, null); } // initialize() /** @@ -359,6 +377,9 @@ class ProductI18nTableMap extends TableMap $criteria->addSelectColumn(ProductI18nTableMap::DESCRIPTION); $criteria->addSelectColumn(ProductI18nTableMap::CHAPO); $criteria->addSelectColumn(ProductI18nTableMap::POSTSCRIPTUM); + $criteria->addSelectColumn(ProductI18nTableMap::META_TITLE); + $criteria->addSelectColumn(ProductI18nTableMap::META_DESCRIPTION); + $criteria->addSelectColumn(ProductI18nTableMap::META_KEYWORD); } else { $criteria->addSelectColumn($alias . '.ID'); $criteria->addSelectColumn($alias . '.LOCALE'); @@ -366,6 +387,9 @@ class ProductI18nTableMap extends TableMap $criteria->addSelectColumn($alias . '.DESCRIPTION'); $criteria->addSelectColumn($alias . '.CHAPO'); $criteria->addSelectColumn($alias . '.POSTSCRIPTUM'); + $criteria->addSelectColumn($alias . '.META_TITLE'); + $criteria->addSelectColumn($alias . '.META_DESCRIPTION'); + $criteria->addSelectColumn($alias . '.META_KEYWORD'); } } diff --git a/core/lib/Thelia/Model/Map/ProductTableMap.php b/core/lib/Thelia/Model/Map/ProductTableMap.php index 68a34a393..3cf8d3925 100644 --- a/core/lib/Thelia/Model/Map/ProductTableMap.php +++ b/core/lib/Thelia/Model/Map/ProductTableMap.php @@ -230,7 +230,7 @@ class ProductTableMap extends TableMap { return array( 'timestampable' => array('create_column' => 'created_at', 'update_column' => 'updated_at', ), - 'i18n' => array('i18n_table' => '%TABLE%_i18n', 'i18n_phpname' => '%PHPNAME%I18n', 'i18n_columns' => 'title, description, chapo, postscriptum', 'locale_column' => 'locale', 'locale_length' => '5', 'default_locale' => '', 'locale_alias' => '', ), + 'i18n' => array('i18n_table' => '%TABLE%_i18n', 'i18n_phpname' => '%PHPNAME%I18n', 'i18n_columns' => 'title, description, chapo, postscriptum, meta_title, meta_description, meta_keyword', 'locale_column' => 'locale', 'locale_length' => '5', 'default_locale' => '', 'locale_alias' => '', ), 'versionable' => array('version_column' => 'version', 'version_table' => '', 'log_created_at' => 'true', 'log_created_by' => 'true', 'log_comment' => 'false', 'version_created_at_column' => 'version_created_at', 'version_created_by_column' => 'version_created_by', 'version_comment_column' => 'version_comment', ), ); } // getBehaviors() diff --git a/install/thelia.sql b/install/thelia.sql index ed27071fb..e26acd742 100755 --- a/install/thelia.sql +++ b/install/thelia.sql @@ -1652,6 +1652,9 @@ CREATE TABLE `product_i18n` `description` LONGTEXT, `chapo` TEXT, `postscriptum` TEXT, + `meta_title` VARCHAR(255), + `meta_description` TEXT, + `meta_keyword` TEXT, PRIMARY KEY (`id`,`locale`), CONSTRAINT `product_i18n_FK_1` FOREIGN KEY (`id`) diff --git a/local/config/schema.xml b/local/config/schema.xml index 70df6710e..2a22eaa8e 100755 --- a/local/config/schema.xml +++ b/local/config/schema.xml @@ -1,1264 +1,1267 @@ - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - -
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - -
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - -
-
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
From 186b338f48b8971465befa6111b52929e2ea84be Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:03:32 +0100 Subject: [PATCH 02/10] Add new SEO form --- core/lib/Thelia/Config/Resources/form.xml | 2 +- core/lib/Thelia/Form/SeoFieldsTrait.php | 89 +++++++++++++++++++++++ core/lib/Thelia/Form/SeoForm.php | 81 +++++++++++++++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 core/lib/Thelia/Form/SeoFieldsTrait.php create mode 100644 core/lib/Thelia/Form/SeoForm.php diff --git a/core/lib/Thelia/Config/Resources/form.xml b/core/lib/Thelia/Config/Resources/form.xml index cf9ccd489..ec281266e 100644 --- a/core/lib/Thelia/Config/Resources/form.xml +++ b/core/lib/Thelia/Config/Resources/form.xml @@ -17,6 +17,7 @@
+ @@ -39,7 +40,6 @@ - diff --git a/core/lib/Thelia/Form/SeoFieldsTrait.php b/core/lib/Thelia/Form/SeoFieldsTrait.php new file mode 100644 index 000000000..dd66324d8 --- /dev/null +++ b/core/lib/Thelia/Form/SeoFieldsTrait.php @@ -0,0 +1,89 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Core\Translation\Translator; + +/** + * A trait to add standard localized description fields to a form. + * + * @author Christophe Laffont + */ +trait SeoFieldsTrait +{ + /** + * Add seo meta title, meta description and meta keywords fields + * + * @param array $exclude name of the fields that should not be added to the form + */ + protected function addSeoFields($exclude = array()) + { + + if (! in_array('url', $exclude)) + $this->formBuilder + ->add('url', 'text', array( + 'label' => Translator::getInstance()->trans('Rewriten URL'), + 'label_attr' => array( + 'for' => 'rewriten_url_field' + ), + 'required' => false + ) + ); + + if (! in_array('meta_title', $exclude)) + $this->formBuilder + ->add('meta_title', 'text', array( + 'constraints' => array( + new NotBlank() + ), + 'label' => Translator::getInstance()->trans('Page Title'), + 'label_attr' => array( + 'for' => 'meta_title' + ) + ) + ); + + if (! in_array('meta_description', $exclude)) + $this->formBuilder + ->add('meta_description', 'text', array( + 'label' => Translator::getInstance()->trans('Meta Description'), + 'label_attr' => array( + 'for' => 'meta_description' + ), + 'required' => false + ) + ); + + if (! in_array('meta_keyword', $exclude)) + $this->formBuilder + ->add('meta_keyword', 'text', array( + 'label' => Translator::getInstance()->trans('Meta Keyword'), + 'label_attr' => array( + 'for' => 'meta_keyword' + ), + 'required' => false + ) + ); + } +} diff --git a/core/lib/Thelia/Form/SeoForm.php b/core/lib/Thelia/Form/SeoForm.php new file mode 100644 index 000000000..28c90c9ba --- /dev/null +++ b/core/lib/Thelia/Form/SeoForm.php @@ -0,0 +1,81 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\GreaterThan; +use Symfony\Component\Validator\Constraints\NotBlank; + +/** + * Class SeoForm + * @package Thelia\Form + * @author Christophe Laffont + */ +class SeoForm extends BaseForm +{ + use SeoFieldsTrait; + + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + + $this->formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan(array('value' => 0)) + ) + )) + ->add("locale", "hidden", array( + "constraints" => array( + new NotBlank() + ) + )) + ; + + // Add SEO Fields + $this->addSeoFields(); + } + + public function getName() + { + return "thelia_seo"; + } +} From 1af1f90996848b42d5a2e82693b1de30cb29952c Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:05:03 +0100 Subject: [PATCH 03/10] Add SEO tab for a product --- .../backOffice/default/includes/seo-tab.html | 79 +++++++++++++++++++ .../backOffice/default/product-edit.html | 17 +++- 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 templates/backOffice/default/includes/seo-tab.html diff --git a/templates/backOffice/default/includes/seo-tab.html b/templates/backOffice/default/includes/seo-tab.html new file mode 100644 index 000000000..9ae515885 --- /dev/null +++ b/templates/backOffice/default/includes/seo-tab.html @@ -0,0 +1,79 @@ +
+ + + + {include + file = "includes/inner-form-toolbar.html" + hide_submit_buttons = false + + page_url = {$pageUrl} + close_url = {$closeUrl} + } + + {* Hidden field *} + + + {form_hidden_fields form=$form} + + {form_field form=$form field='success_url'} + + {/form_field} + + {form_field form=$form field='url'} +
+ +
+ {$url_language|default:{config key="url_site"}} + +
+
+ {/form_field} + + + {form_field form=$form field='meta_title'} +
+ +
+ +
+
+ {/form_field} + + {form_field form=$form field='meta_description'} +
+ + + +
+ {/form_field} + + {form_field form=$form field='meta_keyword'} +
+ + + +
+ {/form_field} + + {include + file = "includes/inner-form-toolbar.html" + hide_submit_buttons = false + hide_flags = true + + page_url = {$pageUrl} + close_url = {$closeUrl} + } + + +
\ No newline at end of file diff --git a/templates/backOffice/default/product-edit.html b/templates/backOffice/default/product-edit.html index e05bc7434..d20d7a953 100644 --- a/templates/backOffice/default/product-edit.html +++ b/templates/backOffice/default/product-edit.html @@ -48,6 +48,8 @@ data-toggle="tab">{intl l="General"} +
  • {intl l="SEO"}
  • +
  • {intl l="Details"}
  • @@ -79,7 +81,7 @@ {intl l="Documents"}
  • {intl l="Modules"}
  • - +
    @@ -87,6 +89,18 @@ {include file="includes/product-general-tab.html"}
    +
    + {form name="thelia.admin.seo"} + {include file="includes/seo-tab.html" + form = $form + currentId = "{$ID}" + formAction = "{url path='/admin/products/seo/save'}" + pageUrl = "{url path='/admin/products/update' product_id=$ID}" + closeUrl = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}" + } + {/form} +
    +
    {include file="includes/product-details-tab.html"}
    @@ -110,6 +124,7 @@
    {intl l="Please wait, loading"}
    + From d13bc0579bf494635ce7475652ea12461f12a5e9 Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:06:19 +0100 Subject: [PATCH 04/10] Add action buttons at the bottom of the product General tab --- .../default/includes/product-general-tab.html | 73 ++++++++----------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/templates/backOffice/default/includes/product-general-tab.html b/templates/backOffice/default/includes/product-general-tab.html index 84b9a836d..c78e380ae 100644 --- a/templates/backOffice/default/includes/product-general-tab.html +++ b/templates/backOffice/default/includes/product-general-tab.html @@ -11,15 +11,14 @@ close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}" } - {* Be sure to get the product ID, even if the form could not be validated *} + {* Be sure to get the product ID, even if the form could not be validated*} - - + {form_hidden_fields form=$form} {form_field form=$form field='id'} - + {/form_field} {form_field form=$form field='success_url'} @@ -32,33 +31,25 @@ {if $form_error}
    {$form_error_message}
    {/if} -
    - - -
    {$REF}
    - - {form_field form=$form field='ref'} - - {/form_field} - -
    - - {include file="includes/standard-description-form-fields.html"} - - {form_field form=$form field='url'} -
    - - - -
    - {/form_field} -
    -
    +
    + {form_field form=$form field='ref'} +
    + +
    + {* If ref's 'value is not empty the field is disable and the value is sent with an hidden field *} + + {if $value}{/if} +
    +
    + {/form_field} + + {include file="includes/standard-description-form-fields.html"} +
    + +
    {form_field form=$form field='default_category'}
    @@ -79,9 +70,7 @@
    {/form_field} -
    -
    {form_field form=$form field='visible'}
    @@ -96,16 +85,16 @@
    -
    -
    -
    - -
    -

    {intl l='Product created on %date_create. Last modification: %date_change' date_create="{format_date date=$CREATE_DATE}" date_change="{format_date date=$UPDATE_DATE}"}

    -
    -
    -
    -
    + {include + file = "includes/inner-form-toolbar.html" + hide_submit_buttons = false + hide_flags = true + + page_url = "{url path='/admin/products/update' product_id=$ID}" + close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}" + } + + {intl l='Product created on %date_create. Last modification: %date_change' date_create="{format_date date=$CREATE_DATE}" date_change="{format_date date=$UPDATE_DATE}"} {/form} From ad10b984f32503a27881dca83d71e37ff8b4e8bd Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:07:03 +0100 Subject: [PATCH 05/10] Add new route to save the product SEO information --- core/lib/Thelia/Config/Resources/routing/admin.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index 591e5c0e7..b821e775c 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -263,6 +263,10 @@ Thelia\Controller\Admin\ProductController::processUpdateAction + + Thelia\Controller\Admin\ProductController::processUpdateSeoAction + + Thelia\Controller\Admin\ProductController::setToggleVisibilityAction From 6418914a6d99fc3a83bbc431ccf67de094881b6d Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:10:10 +0100 Subject: [PATCH 06/10] Add Action + Event to manage SEO information --- core/lib/Thelia/Action/BaseAction.php | 36 ++++- core/lib/Thelia/Action/Product.php | 64 +++++---- .../Admin/AbstractCrudController.php | 115 +++++++++++++++- core/lib/Thelia/Core/Event/TheliaEvents.php | 3 + core/lib/Thelia/Core/Event/UpdateSeoEvent.php | 130 ++++++++++++++++++ 5 files changed, 315 insertions(+), 33 deletions(-) create mode 100644 core/lib/Thelia/Core/Event/UpdateSeoEvent.php diff --git a/core/lib/Thelia/Action/BaseAction.php b/core/lib/Thelia/Action/BaseAction.php index e1edab07d..e207a624e 100755 --- a/core/lib/Thelia/Action/BaseAction.php +++ b/core/lib/Thelia/Action/BaseAction.php @@ -23,9 +23,12 @@ namespace Thelia\Action; use Symfony\Component\DependencyInjection\ContainerInterface; -use Thelia\Model\AdminLog; use Propel\Runtime\ActiveQuery\ModelCriteria; + use Thelia\Core\Event\UpdatePositionEvent; +use Thelia\Core\Event\UpdateSeoEvent; + +use \Thelia\Model\Tools\UrlRewritingTrait; class BaseAction { @@ -73,4 +76,35 @@ class BaseAction return $object->movePositionDown(); } } + + /** + * Changes SEO Fields for an object. + * + * @param ModelCriteria $query + * @param UpdateSeoEvent $event + * + * @return mixed + */ + protected function genericUpdateSeo(ModelCriteria $query, UpdateSeoEvent $event) + { + if (null !== $object = $query->findPk($event->getObjectId())) { + + $object + ->setDispatcher($this->getDispatcher()) + + ->setLocale($event->getLocale()) + ->setMetaTitle($event->getMetaTitle()) + ->setMetaDescription($event->getMetaDescription()) + ->setMetaKeyword($event->getMetaKeyword()) + + ->save() + ; + + // Update the rewriten URL, if required + $object->setRewrittenUrl($event->getLocale(), $event->getUrl()); + + return $object; + } + } + } diff --git a/core/lib/Thelia/Action/Product.php b/core/lib/Thelia/Action/Product.php index 3917827d1..a5b117eb4 100644 --- a/core/lib/Thelia/Action/Product.php +++ b/core/lib/Thelia/Action/Product.php @@ -25,36 +25,37 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Model\Map\ProductTableMap; use Thelia\Model\ProductQuery; use Thelia\Model\Product as ProductModel; - -use Thelia\Core\Event\TheliaEvents; - -use Thelia\Core\Event\Product\ProductUpdateEvent; -use Thelia\Core\Event\Product\ProductCreateEvent; -use Thelia\Core\Event\Product\ProductDeleteEvent; -use Thelia\Core\Event\UpdatePositionEvent; -use Thelia\Core\Event\Product\ProductToggleVisibilityEvent; -use Thelia\Core\Event\Product\ProductAddContentEvent; -use Thelia\Core\Event\Product\ProductDeleteContentEvent; use Thelia\Model\ProductAssociatedContent; use Thelia\Model\ProductAssociatedContentQuery; use Thelia\Model\ProductCategory; use Thelia\Model\TaxRuleQuery; use Thelia\Model\AccessoryQuery; use Thelia\Model\Accessory; -use Thelia\Core\Event\FeatureProduct\FeatureProductUpdateEvent; use Thelia\Model\FeatureProduct; -use Thelia\Core\Event\FeatureProduct\FeatureProductDeleteEvent; use Thelia\Model\FeatureProductQuery; use Thelia\Model\ProductCategoryQuery; -use Thelia\Core\Event\Product\ProductSetTemplateEvent; use Thelia\Model\ProductSaleElementsQuery; + +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Event\Product\ProductUpdateEvent; +use Thelia\Core\Event\Product\ProductCreateEvent; +use Thelia\Core\Event\Product\ProductDeleteEvent; +use Thelia\Core\Event\Product\ProductToggleVisibilityEvent; +use Thelia\Core\Event\Product\ProductAddContentEvent; +use Thelia\Core\Event\Product\ProductDeleteContentEvent; +use Thelia\Core\Event\UpdatePositionEvent; +use Thelia\Core\Event\UpdateSeoEvent; +use Thelia\Core\Event\FeatureProduct\FeatureProductUpdateEvent; +use Thelia\Core\Event\FeatureProduct\FeatureProductDeleteEvent; +use Thelia\Core\Event\Product\ProductSetTemplateEvent; use Thelia\Core\Event\Product\ProductDeleteCategoryEvent; use Thelia\Core\Event\Product\ProductAddCategoryEvent; use Thelia\Core\Event\Product\ProductAddAccessoryEvent; use Thelia\Core\Event\Product\ProductDeleteAccessoryEvent; -use Thelia\Model\Map\ProductTableMap; + use Propel\Runtime\Propel; class Product extends BaseAction implements EventSubscriberInterface @@ -113,9 +114,6 @@ class Product extends BaseAction implements EventSubscriberInterface ->save() ; - // Update the rewriten URL, if required - $product->setRewrittenUrl($event->getLocale(), $event->getUrl()); - // Update default category (ifd required) $product->updateDefaultCategory($event->getDefaultCategory()); @@ -123,6 +121,17 @@ class Product extends BaseAction implements EventSubscriberInterface } } + /** + * Change a product SEO + * + * @param \Thelia\Core\Event\UpdateSeoEvent $event + */ + public function updateSeo(UpdateSeoEvent $event) + { + return $this->genericUpdateSeo(ProductQuery::create(), $event); + } + + /** * Delete a product entry * @@ -379,12 +388,13 @@ class Product extends BaseAction implements EventSubscriberInterface public static function getSubscribedEvents() { return array( - TheliaEvents::PRODUCT_CREATE => array("create", 128), - TheliaEvents::PRODUCT_UPDATE => array("update", 128), - TheliaEvents::PRODUCT_DELETE => array("delete", 128), - TheliaEvents::PRODUCT_TOGGLE_VISIBILITY => array("toggleVisibility", 128), + TheliaEvents::PRODUCT_CREATE => array("create", 128), + TheliaEvents::PRODUCT_UPDATE => array("update", 128), + TheliaEvents::PRODUCT_DELETE => array("delete", 128), + TheliaEvents::PRODUCT_TOGGLE_VISIBILITY => array("toggleVisibility", 128), - TheliaEvents::PRODUCT_UPDATE_POSITION => array("updatePosition", 128), + TheliaEvents::PRODUCT_UPDATE_POSITION => array("updatePosition", 128), + TheliaEvents::PRODUCT_UPDATE_SEO => array("updateSeo", 128), TheliaEvents::PRODUCT_ADD_CONTENT => array("addContent", 128), TheliaEvents::PRODUCT_REMOVE_CONTENT => array("removeContent", 128), @@ -394,13 +404,13 @@ class Product extends BaseAction implements EventSubscriberInterface TheliaEvents::PRODUCT_REMOVE_ACCESSORY => array("removeAccessory", 128), TheliaEvents::PRODUCT_UPDATE_ACCESSORY_POSITION => array("updateAccessoryPosition", 128), - TheliaEvents::PRODUCT_ADD_CATEGORY => array("addCategory", 128), - TheliaEvents::PRODUCT_REMOVE_CATEGORY => array("removeCategory", 128), + TheliaEvents::PRODUCT_ADD_CATEGORY => array("addCategory", 128), + TheliaEvents::PRODUCT_REMOVE_CATEGORY => array("removeCategory", 128), - TheliaEvents::PRODUCT_SET_TEMPLATE => array("setProductTemplate", 128), + TheliaEvents::PRODUCT_SET_TEMPLATE => array("setProductTemplate", 128), - TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE => array("updateFeatureProductValue", 128), - TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE => array("deleteFeatureProductValue", 128), + TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE => array("updateFeatureProductValue", 128), + TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE => array("deleteFeatureProductValue", 128), ); } } diff --git a/core/lib/Thelia/Controller/Admin/AbstractCrudController.php b/core/lib/Thelia/Controller/Admin/AbstractCrudController.php index 11ed4fc50..6fe387319 100644 --- a/core/lib/Thelia/Controller/Admin/AbstractCrudController.php +++ b/core/lib/Thelia/Controller/Admin/AbstractCrudController.php @@ -23,9 +23,12 @@ namespace Thelia\Controller\Admin; -use Thelia\Core\Security\AccessManager; -use Thelia\Form\Exception\FormValidationException; use Thelia\Core\Event\UpdatePositionEvent; +use Thelia\Core\Event\UpdateSeoEvent; +use Thelia\Core\Security\AccessManager; + +use Thelia\Form\Exception\FormValidationException; +use Thelia\Form\SeoForm; /** * An abstract CRUD controller for Thelia ADMIN, to manage basic CRUD operations on a givent object. @@ -49,6 +52,7 @@ abstract class AbstractCrudController extends BaseAdminController protected $deleteEventIdentifier; protected $visibilityToggleEventIdentifier; protected $changePositionEventIdentifier; + protected $updateSeoEventIdentifier; /** * @param string $objectName the lower case object name. Example. "message" @@ -64,6 +68,7 @@ abstract class AbstractCrudController extends BaseAdminController * * @param string $visibilityToggleEventIdentifier the dispatched visibility toggle TheliaEvent identifier, or null if the object has no visible options. Example: TheliaEvents::MESSAGE_TOGGLE_VISIBILITY * @param string $changePositionEventIdentifier the dispatched position change TheliaEvent identifier, or null if the object has no position. Example: TheliaEvents::MESSAGE_UPDATE_POSITION + * @param string $updateSeoEventIdentifier the dispatched update SEO change TheliaEvent identifier, or null if the object has no SEO. Example: TheliaEvents::MESSAGE_UPDATE_SEO */ public function __construct( $objectName, @@ -77,7 +82,8 @@ abstract class AbstractCrudController extends BaseAdminController $updateEventIdentifier, $deleteEventIdentifier, $visibilityToggleEventIdentifier = null, - $changePositionEventIdentifier = null + $changePositionEventIdentifier = null, + $updateSeoEventIdentifier = null ) { $this->objectName = $objectName; @@ -91,6 +97,7 @@ abstract class AbstractCrudController extends BaseAdminController $this->deleteEventIdentifier = $deleteEventIdentifier; $this->visibilityToggleEventIdentifier = $visibilityToggleEventIdentifier; $this->changePositionEventIdentifier = $changePositionEventIdentifier; + $this->updateSeoEventIdentifier = $updateSeoEventIdentifier; } /** @@ -139,7 +146,7 @@ abstract class AbstractCrudController extends BaseAdminController /** * Get the created object from an event. * - * @param unknown $createEvent + * @param unknown $event */ abstract protected function getObjectFromEvent($event); @@ -230,7 +237,7 @@ abstract class AbstractCrudController extends BaseAdminController /** * Put in this method post object position change processing if required. * - * @param unknown $deleteEvent the delete event + * @param unknown $positionChangeEvent the delete event * @return Response a response, or null to continue normal processing */ protected function performAdditionalUpdatePositionAction($positionChangeEvent) @@ -238,6 +245,17 @@ abstract class AbstractCrudController extends BaseAdminController return null; } + /** + * Put in this method post object update SEO processing if required. + * + * @param unknown $seoUpdateEvent the update event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalUpdateSeoAction($updateSeoEvent) + { + return null; + } + /** * Return the current list order identifier, updating it in the same time. */ @@ -423,6 +441,93 @@ abstract class AbstractCrudController extends BaseAdminController return $this->renderEditionTemplate(); } + + /** + * Return the update SEO form for this object + */ + protected function getUpdateSeoForm() + { + return new SeoForm($this->getRequest()); + } + + /** + * Creates the update SEO event with the provided form data + * + * @param $formData + * @return UpdateSeoEvent + */ + protected function getUpdateSeoEvent($formData) + { + + $updateSeoEvent = new UpdateSeoEvent($formData['id']); + + $updateSeoEvent + ->setLocale($formData['locale']) + ->setMetaTitle($formData['meta_title']) + ->setMetaDescription($formData['meta_description']) + ->setMetaKeyword($formData['meta_keyword']) + ; + + // Create and dispatch the change event + return $updateSeoEvent; + } + + /** + * Update SEO modification, and either go back to the object list, or stay on the edition page. + * + * @return Thelia\Core\HttpFoundation\Response the response + */ + + public function processUpdateSeoAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response; + + $error_msg = false; + + // Create the form from the request + $updateSeoForm = $this->getUpdateSeoForm($this->getRequest()); + + try { + + // Check the form against constraints violations + $form = $this->validateForm($updateSeoForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + $updateSeoEvent = $this->getUpdateSeoEvent($data); + + $this->dispatch($this->updateSeoEventIdentifier, $updateSeoEvent); + + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + + $response = $this->performAdditionalUpdateSeoAction($updateSeoEvent); + + if ($response == null) { + // If we have to stay on the same page, do not redirect to the successUrl, + // just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + $this->redirectToEditionTemplate($this->getRequest()); + } + + // Redirect to the success URL + $this->redirect($updateSeoForm->getSuccessUrl()); + } else { + return $response; + } + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + /** * Update object position (only for objects whichsupport that) * diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 1dfcb673c..ac2a6422f 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -167,6 +167,7 @@ final class TheliaEvents const CATEGORY_DELETE = "action.deleteCategory"; const CATEGORY_TOGGLE_VISIBILITY = "action.toggleCategoryVisibility"; const CATEGORY_UPDATE_POSITION = "action.updateCategoryPosition"; + const CATEGORY_UPDATE_SEO = "action.updateCategorySeo"; const CATEGORY_ADD_CONTENT = "action.categoryAddContent"; const CATEGORY_REMOVE_CONTENT = "action.categoryRemoveContent"; @@ -204,6 +205,7 @@ final class TheliaEvents const CONTENT_DELETE = "action.deleteContent"; const CONTENT_TOGGLE_VISIBILITY = "action.toggleContentVisibility"; const CONTENT_UPDATE_POSITION = "action.updateContentPosition"; + const CONTENT_UPDATE_SEO = "action.updateContentSeo"; const CONTENT_ADD_FOLDER = "action.contentAddFolder"; const CONTENT_REMOVE_FOLDER = "action.contentRemoveFolder"; @@ -276,6 +278,7 @@ final class TheliaEvents const PRODUCT_DELETE = "action.deleteProduct"; const PRODUCT_TOGGLE_VISIBILITY = "action.toggleProductVisibility"; const PRODUCT_UPDATE_POSITION = "action.updateProductPosition"; + const PRODUCT_UPDATE_SEO = "action.updateProductSeo"; const PRODUCT_ADD_CONTENT = "action.productAddContent"; const PRODUCT_REMOVE_CONTENT = "action.productRemoveContent"; diff --git a/core/lib/Thelia/Core/Event/UpdateSeoEvent.php b/core/lib/Thelia/Core/Event/UpdateSeoEvent.php new file mode 100644 index 000000000..99b19efe8 --- /dev/null +++ b/core/lib/Thelia/Core/Event/UpdateSeoEvent.php @@ -0,0 +1,130 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +class UpdateSeoEvent extends ActionEvent +{ + protected $object_id; + protected $locale; + protected $url; + protected $meta_title; + protected $meta_description; + protected $meta_keyword; + + protected $object; + + public function __construct($object_id, $locale = null, $url = null, $meta_title = null, $meta_description = null, $meta_keyword = null) + { + $this->object_id = $object_id; + $this->locale = $locale; + $this->url = $url; + $this->meta_title = $meta_title; + $this->meta_description = $meta_description; + $this->meta_keyword = $meta_keyword; + } + + public function getObjectId() + { + return $this->object_id; + } + + public function setObjectId($object_id) + { + $this->object_id = $object_id; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getUrl() + { + return $this->url; + } + + public function setUrl($url) + { + $this->url = $url; + + return $this; + } + + public function getParent() + { + return $this->parent; + } + + public function setParent($parent) + { + $this->parent = $parent; + + return $this; + } + + public function getMetaTitle() + { + return $this->meta_title; + } + + public function setMetaTitle($meta_title) + { + $this->meta_title = $meta_title; + + return $this; + } + + public function getMetaDescription() + { + return $this->meta_description; + } + + public function setMetaDescription($meta_description) + { + $this->meta_description = $meta_description; + + return $this; + } + + public function getMetaKeyword() + { + return $this->meta_keyword; + } + + public function setMetaKeyword($meta_keyword) + { + $this->meta_keyword = $meta_keyword; + + return $this; + } +} From dc28ce2d30a07365e86d200dc87b401f19061058 Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:11:45 +0100 Subject: [PATCH 07/10] Move URL to SeoForm (SEO tab) --- .../Core/Event/Product/ProductUpdateEvent.php | 13 ------------- core/lib/Thelia/Form/ProductModificationForm.php | 7 +------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/core/lib/Thelia/Core/Event/Product/ProductUpdateEvent.php b/core/lib/Thelia/Core/Event/Product/ProductUpdateEvent.php index 535f04462..7d0f9469c 100644 --- a/core/lib/Thelia/Core/Event/Product/ProductUpdateEvent.php +++ b/core/lib/Thelia/Core/Event/Product/ProductUpdateEvent.php @@ -33,7 +33,6 @@ class ProductUpdateEvent extends ProductCreateEvent protected $description; protected $postscriptum; - protected $url; protected $parent; public function __construct($product_id) @@ -89,18 +88,6 @@ class ProductUpdateEvent extends ProductCreateEvent return $this; } - public function getUrl() - { - return $this->url; - } - - public function setUrl($url) - { - $this->url = $url; - - return $this; - } - public function getParent() { return $this->parent; diff --git a/core/lib/Thelia/Form/ProductModificationForm.php b/core/lib/Thelia/Form/ProductModificationForm.php index 34785cf45..708599ffb 100644 --- a/core/lib/Thelia/Form/ProductModificationForm.php +++ b/core/lib/Thelia/Form/ProductModificationForm.php @@ -24,7 +24,7 @@ namespace Thelia\Form; use Symfony\Component\Validator\Constraints\GreaterThan; use Thelia\Core\Translation\Translator; -use Symfony\Component\Validator\Constraints\NotBlank; + class ProductModificationForm extends ProductCreationForm { @@ -46,11 +46,6 @@ class ProductModificationForm extends ProductCreationForm "label_attr" => array("for" => "product_template_field") )) - ->add("url", "text", array( - "label" => Translator::getInstance()->trans("Rewriten URL *"), - "constraints" => array(new NotBlank()), - "label_attr" => array("for" => "rewriten_url_field") - )) ; // Add standard description fields, excluding title and locale, which a re defined in parent class From a571db9a43cbb9d47b1799e7d6ea3d229fc458b5 Mon Sep 17 00:00:00 2001 From: touffies Date: Thu, 28 Nov 2013 12:12:24 +0100 Subject: [PATCH 08/10] Hydrate SeoForm under SEO Tab --- .../Controller/Admin/ProductController.php | 82 ++++++++++++------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/core/lib/Thelia/Controller/Admin/ProductController.php b/core/lib/Thelia/Controller/Admin/ProductController.php index 9aa2d279e..109e95a68 100644 --- a/core/lib/Thelia/Controller/Admin/ProductController.php +++ b/core/lib/Thelia/Controller/Admin/ProductController.php @@ -23,50 +23,56 @@ namespace Thelia\Controller\Admin; -use Thelia\Core\Security\Resource\AdminResources; -use Thelia\Core\Event\Product\ProductAddCategoryEvent; -use Thelia\Core\Event\Product\ProductDeleteCategoryEvent; -use Thelia\Core\Event\Product\ProductDeleteEvent; +use Symfony\Component\HttpFoundation\JsonResponse; +use Propel\Runtime\ActiveQuery\Criteria; + use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Event\Product\ProductUpdateEvent; use Thelia\Core\Event\Product\ProductCreateEvent; -use Thelia\Core\Security\AccessManager; -use Thelia\Model\ProductQuery; -use Thelia\Form\ProductModificationForm; -use Thelia\Form\ProductCreationForm; -use Thelia\Core\Event\UpdatePositionEvent; +use Thelia\Core\Event\Product\ProductAddCategoryEvent; +use Thelia\Core\Event\Product\ProductDeleteCategoryEvent; +use Thelia\Core\Event\Product\ProductDeleteEvent; use Thelia\Core\Event\Product\ProductToggleVisibilityEvent; use Thelia\Core\Event\Product\ProductDeleteContentEvent; use Thelia\Core\Event\Product\ProductAddContentEvent; -use Thelia\Model\FolderQuery; -use Thelia\Model\ContentQuery; -use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Model\ProductAssociatedContentQuery; -use Thelia\Model\AccessoryQuery; -use Thelia\Model\CategoryQuery; - use Thelia\Core\Event\Product\ProductAddAccessoryEvent; use Thelia\Core\Event\Product\ProductDeleteAccessoryEvent; -use Thelia\Model\ProductSaleElementsQuery; +use Thelia\Core\Event\Product\ProductCombinationGenerationEvent; +use Thelia\Core\Event\Product\ProductSetTemplateEvent; +use Thelia\Core\Event\UpdatePositionEvent; use Thelia\Core\Event\ProductSaleElement\ProductSaleElementDeleteEvent; use Thelia\Core\Event\ProductSaleElement\ProductSaleElementUpdateEvent; use Thelia\Core\Event\ProductSaleElement\ProductSaleElementCreateEvent; + +use Thelia\Core\Security\Resource\AdminResources; +use Thelia\Core\Security\AccessManager; + +use Thelia\Model\AccessoryQuery; +use Thelia\Model\CategoryQuery; +use Thelia\Model\FolderQuery; +use Thelia\Model\ContentQuery; use Thelia\Model\AttributeQuery; use Thelia\Model\AttributeAvQuery; -use Thelia\Form\ProductSaleElementUpdateForm; +use Thelia\Model\ProductQuery; +use Thelia\Model\ProductAssociatedContentQuery; +use Thelia\Model\ProductSaleElementsQuery; use Thelia\Model\ProductPriceQuery; -use Thelia\Form\ProductDefaultSaleElementUpdateForm; use Thelia\Model\ProductPrice; use Thelia\Model\Currency; -use Symfony\Component\HttpFoundation\JsonResponse; -use Thelia\TaxEngine\Calculator; -use Thelia\Model\Country; -use Thelia\Tools\NumberFormat; -use Thelia\Model\Product; use Thelia\Model\CurrencyQuery; +use Thelia\Model\Country; +use Thelia\Model\Product; + +use Thelia\Form\ProductCreationForm; +use Thelia\Form\ProductModificationForm; +use Thelia\Form\ProductSaleElementUpdateForm; +use Thelia\Form\ProductDefaultSaleElementUpdateForm; use Thelia\Form\ProductCombinationGenerationForm; -use Thelia\Core\Event\Product\ProductCombinationGenerationEvent; -use Thelia\Core\Event\Product\ProductSetTemplateEvent; +use Thelia\Form\SeoForm; + +use Thelia\TaxEngine\Calculator; +use Thelia\Tools\NumberFormat; + /** * Manages products @@ -89,7 +95,8 @@ class ProductController extends AbstractCrudController TheliaEvents::PRODUCT_DELETE, TheliaEvents::PRODUCT_TOGGLE_VISIBILITY, - TheliaEvents::PRODUCT_UPDATE_POSITION + TheliaEvents::PRODUCT_UPDATE_POSITION, + TheliaEvents::PRODUCT_UPDATE_SEO ); } @@ -153,9 +160,9 @@ class ProductController extends AbstractCrudController protected function getUpdateEvent($formData) { + $changeEvent = new ProductUpdateEvent($formData['id']); - // Create and dispatch the change event $changeEvent ->setLocale($formData['locale']) ->setTitle($formData['title']) @@ -163,10 +170,10 @@ class ProductController extends AbstractCrudController ->setDescription($formData['description']) ->setPostscriptum($formData['postscriptum']) ->setVisible($formData['visible']) - ->setUrl($formData['url']) ->setDefaultCategory($formData['default_category']) - ; + ; + // Create and dispatch the change event return $changeEvent; } @@ -307,6 +314,20 @@ class ProductController extends AbstractCrudController $this->getParserContext()->addForm($combinationPseForm); } + // The "SEO" tab form + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'url' => $object->getRewrittenUrl($this->getCurrentEditionLocale()), + 'meta_title' => $object->getMetaTitle(), + 'meta_description' => $object->getMetaDescription(), + 'meta_keyword' => $object->getMetaKeyword() + ); + + $seoForm = new SeoForm($this->getRequest(), "form", $data); + $this->getParserContext()->addForm($seoForm); + + // The "General" tab form $data = array( 'id' => $object->getId(), @@ -317,7 +338,6 @@ class ProductController extends AbstractCrudController 'description' => $object->getDescription(), 'postscriptum' => $object->getPostscriptum(), 'visible' => $object->getVisible(), - 'url' => $object->getRewrittenUrl($this->getCurrentEditionLocale()), 'default_category' => $object->getDefaultCategoryId() ); From ee7d62f9d5f82fe7df37ce452a7ec07f5001990b Mon Sep 17 00:00:00 2001 From: touffies Date: Fri, 29 Nov 2013 09:50:13 +0100 Subject: [PATCH 09/10] Extend AbstractCrudController to manage the SEO methods --- .../Admin/AbstractCrudController.php | 111 +---------- .../Admin/AbstractSeoCrudController.php | 183 ++++++++++++++++++ .../Controller/Admin/ProductController.php | 2 +- 3 files changed, 187 insertions(+), 109 deletions(-) create mode 100644 core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php diff --git a/core/lib/Thelia/Controller/Admin/AbstractCrudController.php b/core/lib/Thelia/Controller/Admin/AbstractCrudController.php index 6fe387319..19d0b782d 100644 --- a/core/lib/Thelia/Controller/Admin/AbstractCrudController.php +++ b/core/lib/Thelia/Controller/Admin/AbstractCrudController.php @@ -23,12 +23,9 @@ namespace Thelia\Controller\Admin; -use Thelia\Core\Event\UpdatePositionEvent; -use Thelia\Core\Event\UpdateSeoEvent; use Thelia\Core\Security\AccessManager; - use Thelia\Form\Exception\FormValidationException; -use Thelia\Form\SeoForm; +use Thelia\Core\Event\UpdatePositionEvent; /** * An abstract CRUD controller for Thelia ADMIN, to manage basic CRUD operations on a givent object. @@ -37,7 +34,7 @@ use Thelia\Form\SeoForm; */ abstract class AbstractCrudController extends BaseAdminController { - protected $objectName; + protected $objectName; // List ordering protected $defaultListOrder; @@ -52,7 +49,6 @@ abstract class AbstractCrudController extends BaseAdminController protected $deleteEventIdentifier; protected $visibilityToggleEventIdentifier; protected $changePositionEventIdentifier; - protected $updateSeoEventIdentifier; /** * @param string $objectName the lower case object name. Example. "message" @@ -68,7 +64,6 @@ abstract class AbstractCrudController extends BaseAdminController * * @param string $visibilityToggleEventIdentifier the dispatched visibility toggle TheliaEvent identifier, or null if the object has no visible options. Example: TheliaEvents::MESSAGE_TOGGLE_VISIBILITY * @param string $changePositionEventIdentifier the dispatched position change TheliaEvent identifier, or null if the object has no position. Example: TheliaEvents::MESSAGE_UPDATE_POSITION - * @param string $updateSeoEventIdentifier the dispatched update SEO change TheliaEvent identifier, or null if the object has no SEO. Example: TheliaEvents::MESSAGE_UPDATE_SEO */ public function __construct( $objectName, @@ -82,8 +77,7 @@ abstract class AbstractCrudController extends BaseAdminController $updateEventIdentifier, $deleteEventIdentifier, $visibilityToggleEventIdentifier = null, - $changePositionEventIdentifier = null, - $updateSeoEventIdentifier = null + $changePositionEventIdentifier = null ) { $this->objectName = $objectName; @@ -97,7 +91,6 @@ abstract class AbstractCrudController extends BaseAdminController $this->deleteEventIdentifier = $deleteEventIdentifier; $this->visibilityToggleEventIdentifier = $visibilityToggleEventIdentifier; $this->changePositionEventIdentifier = $changePositionEventIdentifier; - $this->updateSeoEventIdentifier = $updateSeoEventIdentifier; } /** @@ -245,17 +238,6 @@ abstract class AbstractCrudController extends BaseAdminController return null; } - /** - * Put in this method post object update SEO processing if required. - * - * @param unknown $seoUpdateEvent the update event - * @return Response a response, or null to continue normal processing - */ - protected function performAdditionalUpdateSeoAction($updateSeoEvent) - { - return null; - } - /** * Return the current list order identifier, updating it in the same time. */ @@ -441,93 +423,6 @@ abstract class AbstractCrudController extends BaseAdminController return $this->renderEditionTemplate(); } - - /** - * Return the update SEO form for this object - */ - protected function getUpdateSeoForm() - { - return new SeoForm($this->getRequest()); - } - - /** - * Creates the update SEO event with the provided form data - * - * @param $formData - * @return UpdateSeoEvent - */ - protected function getUpdateSeoEvent($formData) - { - - $updateSeoEvent = new UpdateSeoEvent($formData['id']); - - $updateSeoEvent - ->setLocale($formData['locale']) - ->setMetaTitle($formData['meta_title']) - ->setMetaDescription($formData['meta_description']) - ->setMetaKeyword($formData['meta_keyword']) - ; - - // Create and dispatch the change event - return $updateSeoEvent; - } - - /** - * Update SEO modification, and either go back to the object list, or stay on the edition page. - * - * @return Thelia\Core\HttpFoundation\Response the response - */ - - public function processUpdateSeoAction() - { - // Check current user authorization - if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response; - - $error_msg = false; - - // Create the form from the request - $updateSeoForm = $this->getUpdateSeoForm($this->getRequest()); - - try { - - // Check the form against constraints violations - $form = $this->validateForm($updateSeoForm, "POST"); - - // Get the form field values - $data = $form->getData(); - - $updateSeoEvent = $this->getUpdateSeoEvent($data); - - $this->dispatch($this->updateSeoEventIdentifier, $updateSeoEvent); - - } catch (FormValidationException $ex) { - // Form cannot be validated - $error_msg = $this->createStandardFormValidationErrorMessage($ex); - } catch (\Exception $ex) { - // Any error - return $this->errorPage($ex); - } - - - $response = $this->performAdditionalUpdateSeoAction($updateSeoEvent); - - if ($response == null) { - // If we have to stay on the same page, do not redirect to the successUrl, - // just redirect to the edit page again. - if ($this->getRequest()->get('save_mode') == 'stay') { - $this->redirectToEditionTemplate($this->getRequest()); - } - - // Redirect to the success URL - $this->redirect($updateSeoForm->getSuccessUrl()); - } else { - return $response; - } - - // At this point, the form has errors, and should be redisplayed. - return $this->renderEditionTemplate(); - } - /** * Update object position (only for objects whichsupport that) * diff --git a/core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php b/core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php new file mode 100644 index 000000000..744c4af17 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php @@ -0,0 +1,183 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Admin; + +use Thelia\Core\Event\UpdateSeoEvent; +use Thelia\Core\Security\AccessManager; + +use Thelia\Form\Exception\FormValidationException; +use Thelia\Form\SeoForm; + +/** + * Extend abstract CRUD controller to manage basic CRUD + SEO operations on a given object. + * + * @author Christophe Laffont + */ +abstract class AbstractSeoCrudController extends AbstractCrudController +{ + // Events + protected $updateSeoEventIdentifier; + + /** + * @param string $objectName the lower case object name. Example. "message" + * + * @param string $defaultListOrder the default object list order, or null if list is not sortable. Example: manual + * @param string $orderRequestParameterName Name of the request parameter that set the list order (null if list is not sortable) + * + * @param string $resourceCode the 'resource' code. Example: "admin.configuration.message" + * + * @param string $createEventIdentifier the dispatched create TheliaEvent identifier. Example: TheliaEvents::MESSAGE_CREATE + * @param string $updateEventIdentifier the dispatched update TheliaEvent identifier. Example: TheliaEvents::MESSAGE_UPDATE + * @param string $deleteEventIdentifier the dispatched delete TheliaEvent identifier. Example: TheliaEvents::MESSAGE_DELETE + * + * @param string $visibilityToggleEventIdentifier the dispatched visibility toggle TheliaEvent identifier, or null if the object has no visible options. Example: TheliaEvents::MESSAGE_TOGGLE_VISIBILITY + * @param string $changePositionEventIdentifier the dispatched position change TheliaEvent identifier, or null if the object has no position. Example: TheliaEvents::MESSAGE_UPDATE_POSITION + * @param string $updateSeoEventIdentifier the dispatched update SEO change TheliaEvent identifier, or null if the object has no SEO. Example: TheliaEvents::MESSAGE_UPDATE_SEO + */ + public function __construct( + $objectName, + + $defaultListOrder = null, + $orderRequestParameterName = null, + + $resourceCode, + + $createEventIdentifier, + $updateEventIdentifier, + $deleteEventIdentifier, + $visibilityToggleEventIdentifier = null, + $changePositionEventIdentifier = null, + $updateSeoEventIdentifier = null + ) + { + parent::__construct( + $objectName, + $defaultListOrder, + $orderRequestParameterName, + $resourceCode, + $createEventIdentifier, + $updateEventIdentifier, + $deleteEventIdentifier, + $visibilityToggleEventIdentifier, + $changePositionEventIdentifier + ); + + $this->updateSeoEventIdentifier = $updateSeoEventIdentifier; + + } + + /** + * Put in this method post object update SEO processing if required. + * + * @param unknown $updateSeoEvent the update event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalUpdateSeoAction($updateSeoEvent) + { + return null; + } + + /** + * Return the update SEO form for this object + */ + protected function getUpdateSeoForm() + { + return new SeoForm($this->getRequest()); + } + + /** + * Creates the update SEO event with the provided form data + * + * @param $formData + * @return UpdateSeoEvent + */ + protected function getUpdateSeoEvent($formData) + { + + $updateSeoEvent = new UpdateSeoEvent($formData['id']); + + $updateSeoEvent + ->setLocale($formData['locale']) + ->setMetaTitle($formData['meta_title']) + ->setMetaDescription($formData['meta_description']) + ->setMetaKeyword($formData['meta_keyword']) + ; + + // Create and dispatch the change event + return $updateSeoEvent; + } + + /** + * Update SEO modification, and either go back to the object list, or stay on the edition page. + * + * @return Thelia\Core\HttpFoundation\Response the response + */ + public function processUpdateSeoAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response; + + // Create the form from the request + $updateSeoForm = $this->getUpdateSeoForm($this->getRequest()); + + try { + + // Check the form against constraints violations + $form = $this->validateForm($updateSeoForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + $updateSeoEvent = $this->getUpdateSeoEvent($data); + + $this->dispatch($this->updateSeoEventIdentifier, $updateSeoEvent); + + } catch (FormValidationException $ex) { + // Form cannot be validated + return $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + + $response = $this->performAdditionalUpdateSeoAction($updateSeoEvent); + + if ($response == null) { + // If we have to stay on the same page, do not redirect to the successUrl, + // just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + $this->redirectToEditionTemplate($this->getRequest()); + } + + // Redirect to the success URL + $this->redirect($updateSeoForm->getSuccessUrl()); + } else { + return $response; + } + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ProductController.php b/core/lib/Thelia/Controller/Admin/ProductController.php index 109e95a68..abc233684 100644 --- a/core/lib/Thelia/Controller/Admin/ProductController.php +++ b/core/lib/Thelia/Controller/Admin/ProductController.php @@ -79,7 +79,7 @@ use Thelia\Tools\NumberFormat; * * @author Franck Allimant */ -class ProductController extends AbstractCrudController +class ProductController extends AbstractSeoCrudController { public function __construct() { From a375d942ec39809f6b5a92da50d4540f7084cf82 Mon Sep 17 00:00:00 2001 From: touffies Date: Fri, 29 Nov 2013 09:51:10 +0100 Subject: [PATCH 10/10] Missing hidden field product_id for the redirection when the user click "Save" --- templates/backOffice/default/includes/seo-tab.html | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/backOffice/default/includes/seo-tab.html b/templates/backOffice/default/includes/seo-tab.html index 9ae515885..5db7d3b06 100644 --- a/templates/backOffice/default/includes/seo-tab.html +++ b/templates/backOffice/default/includes/seo-tab.html @@ -11,6 +11,7 @@ } {* Hidden field *} + {form_hidden_fields form=$form}