diff --git a/Classes/Domain/DoctrineRepository/PageRepository.php b/Classes/Domain/DoctrineRepository/PageRepository.php new file mode 100644 index 00000000..9f0291b0 --- /dev/null +++ b/Classes/Domain/DoctrineRepository/PageRepository.php @@ -0,0 +1,35 @@ +|false + * @throws Exception + */ + public function getProductPageByProduct(Product $product) + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLENAME); + + return $queryBuilder->select('*') + ->from(self::TABLENAME) + ->where( + $queryBuilder->expr()->eq('cart_products_product', $product->getUid()) + ) + ->orderBy('sorting') + ->setMaxResults(1) + ->executeQuery() + ->fetchAssociative(); + } +} diff --git a/Classes/Domain/DoctrineRepository/Product/ProductRepository.php b/Classes/Domain/DoctrineRepository/Product/ProductRepository.php index 97c2260f..856ee306 100644 --- a/Classes/Domain/DoctrineRepository/Product/ProductRepository.php +++ b/Classes/Domain/DoctrineRepository/Product/ProductRepository.php @@ -9,23 +9,43 @@ * LICENSE file that was distributed with this source code. */ +use Doctrine\DBAL\Exception; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\QueryBuilder; class ProductRepository { + public const TABLENAME = 'tx_cartproducts_domain_model_product_product'; + public function __construct( - private readonly ConnectionPool $connectionPool + private readonly ConnectionPool $connectionPool, ) {} + /** + * @return array|false + * @throws Exception + */ + public function findProductByUid(int $uid) + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLENAME); + + return $queryBuilder + ->select('product.title') + ->from(self::TABLENAME, 'product') + ->where($queryBuilder->expr()->eq('product.uid', $queryBuilder->createNamedParameter($uid))) + ->setMaxResults(1) + ->executeQuery() + ->fetchAssociative(); + } + public function getStock(int $uid): int { $queryBuilder = $this->getQueryBuilder(); return $queryBuilder ->select('stock') - ->from('tx_cartproducts_domain_model_product_product') + ->from(self::TABLENAME) ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, Connection::PARAM_INT)) ) @@ -43,7 +63,7 @@ public function addQuantityToStock(int $uid, int $quantity) $queryBuilder = $this->getQueryBuilder(); $queryBuilder - ->update('tx_cartproducts_domain_model_product_product') + ->update(self::TABLENAME) ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, Connection::PARAM_INT)) ) @@ -64,7 +84,7 @@ private function getQueryBuilder(): QueryBuilder { return $this ->connectionPool - ->getConnectionForTable('tx_cartproducts_domain_model_product_product') + ->getConnectionForTable(self::TABLENAME) ->createQueryBuilder(); } } diff --git a/Classes/Domain/Model/WatchlistItem.php b/Classes/Domain/Model/WatchlistItem.php new file mode 100644 index 00000000..3b44271f --- /dev/null +++ b/Classes/Domain/Model/WatchlistItem.php @@ -0,0 +1,45 @@ +type = 'CartProducts'; + } + + public function getUniqueIdentifier(): string + { + return $this->type . '-' . $this->uid . '-' . $this->detailPid; + } + + public function getType(): string + { + return $this->type; + } + + public function getUid(): int + { + return $this->uid; + } + + public function getDetailPid(): int + { + return $this->detailPid; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/Classes/Handler/WatchlistItemHandler.php b/Classes/Handler/WatchlistItemHandler.php new file mode 100644 index 00000000..94efd139 --- /dev/null +++ b/Classes/Handler/WatchlistItemHandler.php @@ -0,0 +1,46 @@ +productRepository->findProductByUid((int)$uid); + + if ($product === false) { + return null; + } + + return new WatchlistItem( + (int)$uid, + (int)$detailPid, + (string)$product['title'] + ); + } + + public function handlesType(): string + { + return 'CartProducts'; + } +} diff --git a/Classes/ViewHelpers/Product/PageUidViewHelper.php b/Classes/ViewHelpers/Product/PageUidViewHelper.php new file mode 100644 index 00000000..33908240 --- /dev/null +++ b/Classes/ViewHelpers/Product/PageUidViewHelper.php @@ -0,0 +1,59 @@ +registerArgument( + 'product', + Product::class, + 'product', + true + ); + + $this->registerArgument( + 'settings', + 'array', + 'settings array', + true + ); + } + + public function render(): string + { + $product = $this->arguments['product']; + + $page = $this->pageRepository->getProductPageByProduct($product); + + if ($page) { + return $page['uid']; + } + if ($product->getCategory() && $product->getCategory()->getCartProductShowPid()) { + return $product->getCategory()->getCartProductShowPid(); + } + if ($this->arguments['settings']['showPageUids']) { + return $this->arguments['settings']['showPageUids']; + } + + return $GLOBALS['TSFE']->id; + } +} diff --git a/Configuration/Services.php b/Configuration/Services.php new file mode 100644 index 00000000..a6f964ba --- /dev/null +++ b/Configuration/Services.php @@ -0,0 +1,27 @@ +hasDefinition(ItemHandlerRegistry::class)) { + $watchlistItemHandlerDefinition = new Definition( + WatchlistItemHandler::class + ); + $watchlistItemHandlerDefinition->addTag('watchlist.itemHandler') + ->setAutoconfigured(true) + ->setAutowired(true); + $containerBuilder->addDefinitions( + [ + WatchlistItemHandler::class => $watchlistItemHandlerDefinition, + ] + ); + } +}; diff --git a/Documentation/Changelog/6.2/Feature-262-AddWatchlistItemHandler.rst b/Documentation/Changelog/6.2/Feature-262-AddWatchlistItemHandler.rst new file mode 100644 index 00000000..5eaafb7c --- /dev/null +++ b/Documentation/Changelog/6.2/Feature-262-AddWatchlistItemHandler.rst @@ -0,0 +1,16 @@ +.. include:: ../../Includes.rst.txt + +======================================== +Feature: #262 - Add WatchlistItemHandler +======================================== + +See `Issue 262 `__ + +Description +=========== + +After the release of the werkraummedia/watchlist extension for TYPO3 v12 the +WatchlistItemHandler for extcode/cart-products can be added again. +This allows products to be added to the watchlist. + +.. index:: Frontend diff --git a/Documentation/Changelog/6.2/Index.rst b/Documentation/Changelog/6.2/Index.rst new file mode 100644 index 00000000..a546cf1a --- /dev/null +++ b/Documentation/Changelog/6.2/Index.rst @@ -0,0 +1,20 @@ +.. include:: ../../Includes.rst.txt + +6.2 Changes +=========== + +**Table of contents** + +.. contents:: + :local: + :depth: 1 + +Features +^^^^^^^^ + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :glob: + + Feature-* diff --git a/Documentation/Changelog/Index.rst b/Documentation/Changelog/Index.rst index 54941eb2..efc2813c 100644 --- a/Documentation/Changelog/Index.rst +++ b/Documentation/Changelog/Index.rst @@ -10,6 +10,7 @@ ChangeLog :maxdepth: 5 :titlesonly: + 6.2/Index 6.1/Index 6.0/Index 5.0/Index diff --git a/Documentation/Index.rst b/Documentation/Index.rst index f217053e..ca79bb59 100644 --- a/Documentation/Index.rst +++ b/Documentation/Index.rst @@ -20,7 +20,7 @@ Cart Products - extend EXT:cart with products cart_products :Package name: - extcode/cart_products + extcode/cart-products :Version: |release| @@ -60,7 +60,7 @@ Cart Products - extend EXT:cart with products .. card:: :ref:`Introduction ` - Introduction to the extension cart, general information. + Introduction to the extension, general information. .. card:: :ref:`For Administrators ` diff --git a/Documentation/guides.xml b/Documentation/guides.xml index 164d1fd2..7b98c31e 100644 --- a/Documentation/guides.xml +++ b/Documentation/guides.xml @@ -11,8 +11,8 @@ interlink-shortcode="extcode/cart_products" /> diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 58725ece..0eb07597 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -57,6 +57,13 @@ back + + add to watchlist + + + remove from watchlist + + Product Listing diff --git a/Resources/Private/Partials/Product/WatchlistButtons.html b/Resources/Private/Partials/Product/WatchlistButtons.html new file mode 100644 index 00000000..e0bcd50c --- /dev/null +++ b/Resources/Private/Partials/Product/WatchlistButtons.html @@ -0,0 +1,9 @@ + + + + diff --git a/composer.json b/composer.json index bcd81454..ae5e299c 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "authors": [ { "name": "Daniel Gohlke", - "email": "ext.cart@extco.de", + "email": "ext@extco.de", "role": "Developer" } ], @@ -46,7 +46,7 @@ } }, "require": { - "php": "^8.1", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "ext-pdo": "*", "extcode/cart": "^10.0", "typo3/cms-core": "^12.4", @@ -66,7 +66,8 @@ "typo3/cms-fluid-styled-content": "^12.4", "typo3/cms-install": "^12.4", "typo3/cms-reactions": "^12.4", - "typo3/testing-framework": "^8.0" + "typo3/testing-framework": "^8.0", + "werkraummedia/watchlist": "^2.0" }, "scripts": { "test:cgl": [ @@ -108,5 +109,8 @@ "@test:typoscript:lint", "@test:php" ] + }, + "suggest": { + "werkraummedia/watchlist": "^2.0" } } diff --git a/ext_emconf.php b/ext_emconf.php index b31a5299..f4bd6edc 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -4,7 +4,7 @@ 'title' => 'Cart - Products', 'description' => 'Shopping Cart(s) for TYPO3 - Products', 'category' => 'plugin', - 'version' => '6.1.0', + 'version' => '6.2.0', 'state' => 'stable', 'author' => 'Daniel Gohlke', 'author_email' => 'ext@extco.de',