bring into standalone plugin for distribution
This commit is contained in:
95
src/CakeProductsPlugin.php
Normal file
95
src/CakeProductsPlugin.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts;
|
||||
|
||||
use Cake\Console\CommandCollection;
|
||||
use Cake\Core\BasePlugin;
|
||||
use Cake\Core\ContainerInterface;
|
||||
use Cake\Core\PluginApplicationInterface;
|
||||
use Cake\Http\MiddlewareQueue;
|
||||
use Cake\Routing\RouteBuilder;
|
||||
use CakeProducts\Service\CatalogManagerServiceProvider;
|
||||
|
||||
/**
|
||||
* Plugin for CakeProducts
|
||||
*/
|
||||
class CakeProductsPlugin extends BasePlugin
|
||||
{
|
||||
/**
|
||||
* Load all the plugin configuration and bootstrap logic.
|
||||
*
|
||||
* The host application is provided as an argument. This allows you to load
|
||||
* additional plugin dependencies, or attach events.
|
||||
*
|
||||
* @param \Cake\Core\PluginApplicationInterface $app The host application
|
||||
* @return void
|
||||
*/
|
||||
public function bootstrap(PluginApplicationInterface $app): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add routes for the plugin.
|
||||
*
|
||||
* If your plugin has many routes and you would like to isolate them into a separate file,
|
||||
* you can create `$plugin/config/routes.php` and delete this method.
|
||||
*
|
||||
* @param \Cake\Routing\RouteBuilder $routes The route builder to update.
|
||||
* @return void
|
||||
*/
|
||||
public function routes(RouteBuilder $routes): void
|
||||
{
|
||||
$routes->plugin(
|
||||
'CakeProducts',
|
||||
['path' => '/cake-products'],
|
||||
function (RouteBuilder $builder) {
|
||||
// Add custom routes here
|
||||
|
||||
$builder->fallbacks();
|
||||
}
|
||||
);
|
||||
parent::routes($routes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add middleware for the plugin.
|
||||
*
|
||||
* @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to update.
|
||||
* @return \Cake\Http\MiddlewareQueue
|
||||
*/
|
||||
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
|
||||
{
|
||||
// Add your middlewares here
|
||||
|
||||
return $middlewareQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add commands for the plugin.
|
||||
*
|
||||
* @param \Cake\Console\CommandCollection $commands The command collection to update.
|
||||
* @return \Cake\Console\CommandCollection
|
||||
*/
|
||||
public function console(CommandCollection $commands): CommandCollection
|
||||
{
|
||||
// Add your commands here
|
||||
|
||||
$commands = parent::console($commands);
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register application container services.
|
||||
*
|
||||
* @param \Cake\Core\ContainerInterface $container The Container to update.
|
||||
* @return void
|
||||
* @link https://book.cakephp.org/4/en/development/dependency-injection.html#dependency-injection
|
||||
*/
|
||||
public function services(ContainerInterface $container): void
|
||||
{
|
||||
// Add your services here
|
||||
$container->addServiceProvider(new CatalogManagerServiceProvider());
|
||||
}
|
||||
}
|
||||
10
src/Controller/AppController.php
Normal file
10
src/Controller/AppController.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Controller;
|
||||
|
||||
use App\Controller\AppController as BaseController;
|
||||
|
||||
class AppController extends BaseController
|
||||
{
|
||||
}
|
||||
110
src/Controller/ExternalProductCatalogsController.php
Normal file
110
src/Controller/ExternalProductCatalogsController.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Controller;
|
||||
|
||||
use Cake\Log\Log;
|
||||
use CakeProducts\Controller\AppController;
|
||||
|
||||
/**
|
||||
* ExternalProductCatalogs Controller
|
||||
*
|
||||
* @property \CakeProducts\Model\Table\ExternalProductCatalogsTable $ExternalProductCatalogs
|
||||
*/
|
||||
class ExternalProductCatalogsController extends AppController
|
||||
{
|
||||
/**
|
||||
* Index method
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Renders view
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$query = $this->ExternalProductCatalogs->find()
|
||||
->contain(['ProductCatalogs']);
|
||||
$externalProductCatalogs = $this->paginate($query);
|
||||
|
||||
$this->set(compact('externalProductCatalogs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* View method
|
||||
*
|
||||
* @param string|null $id External Product Catalog id.
|
||||
* @return \Cake\Http\Response|null|void Renders view
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function view($id = null)
|
||||
{
|
||||
$externalProductCatalog = $this->ExternalProductCatalogs->get($id, contain: ['ProductCatalogs']);
|
||||
$this->set(compact('externalProductCatalog'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add method
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$externalProductCatalog = $this->ExternalProductCatalogs->newEmptyEntity();
|
||||
if ($this->request->is('post')) {
|
||||
$externalProductCatalog = $this->ExternalProductCatalogs->patchEntity($externalProductCatalog, $this->request->getData());
|
||||
if ($this->ExternalProductCatalogs->save($externalProductCatalog)) {
|
||||
$this->Flash->success(__('The external product catalog has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
Log::debug(print_r('$externalProductCatalog->getErrors() next - failed /add', true));
|
||||
Log::debug(print_r($externalProductCatalog->getErrors(), true));
|
||||
$this->Flash->error(__('The external product catalog could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCatalogs = $this->ExternalProductCatalogs->ProductCatalogs->find('list', limit: 200)->all();
|
||||
$this->set(compact('externalProductCatalog', 'productCatalogs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit method
|
||||
*
|
||||
* @param string|null $id External Product Catalog id.
|
||||
* @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function edit($id = null)
|
||||
{
|
||||
$externalProductCatalog = $this->ExternalProductCatalogs->get($id, contain: []);
|
||||
if ($this->request->is(['patch', 'post', 'put'])) {
|
||||
$externalProductCatalog = $this->ExternalProductCatalogs->patchEntity($externalProductCatalog, $this->request->getData());
|
||||
if ($this->ExternalProductCatalogs->save($externalProductCatalog)) {
|
||||
$this->Flash->success(__('The external product catalog has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
Log::debug(print_r('$externalProductCatalog->getErrors() next - failed /edit', true));
|
||||
Log::debug(print_r($externalProductCatalog->getErrors(), true));
|
||||
$this->Flash->error(__('The external product catalog could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCatalogs = $this->ExternalProductCatalogs->ProductCatalogs->find('list', limit: 200)->all();
|
||||
$this->set(compact('externalProductCatalog', 'productCatalogs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete method
|
||||
*
|
||||
* @param string|null $id External Product Catalog id.
|
||||
* @return \Cake\Http\Response|null Redirects to index.
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
$this->request->allowMethod(['post', 'delete']);
|
||||
$externalProductCatalog = $this->ExternalProductCatalogs->get($id);
|
||||
if ($this->ExternalProductCatalogs->delete($externalProductCatalog)) {
|
||||
$this->Flash->success(__('The external product catalog has been deleted.'));
|
||||
} else {
|
||||
$this->Flash->error(__('The external product catalog could not be deleted. Please, try again.'));
|
||||
}
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
}
|
||||
111
src/Controller/ProductCatalogsController.php
Normal file
111
src/Controller/ProductCatalogsController.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Controller;
|
||||
|
||||
use Cake\Datasource\Exception\RecordNotFoundException;
|
||||
use Cake\Http\Response;
|
||||
use Cake\Log\Log;
|
||||
use CakeProducts\Controller\AppController;
|
||||
use CakeProducts\Model\Table\ProductCatalogsTable;
|
||||
use CakeProducts\Service\InternalCatalogManagerService;
|
||||
|
||||
/**
|
||||
* ProductCatalogs Controller
|
||||
*
|
||||
* @property ProductCatalogsTable $ProductCatalogs
|
||||
*/
|
||||
class ProductCatalogsController extends AppController
|
||||
{
|
||||
/**
|
||||
* Index method
|
||||
*
|
||||
* @return Response|null|void Renders view
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$query = $this->ProductCatalogs->find();
|
||||
$productCatalogs = $this->paginate($query);
|
||||
|
||||
$this->set(compact('productCatalogs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* View method
|
||||
*
|
||||
* @param string|null $id Product Catalog id.
|
||||
* @return Response|null|void Renders view
|
||||
* @throws RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function view(InternalCatalogManagerService $catalogManagerService, $id = null)
|
||||
{
|
||||
$productCatalog = $catalogManagerService->getCatalog($id);
|
||||
$this->set(compact('productCatalog'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add method
|
||||
*
|
||||
* @return Response|null|void Redirects on successful add, renders view otherwise.
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$productCatalog = $this->ProductCatalogs->newEmptyEntity();
|
||||
if ($this->request->is('post')) {
|
||||
$productCatalog = $this->ProductCatalogs->patchEntity($productCatalog, $this->request->getData());
|
||||
if ($this->ProductCatalogs->save($productCatalog)) {
|
||||
$this->Flash->success(__('The product catalog has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
Log::debug('failed to save new product catalog errors next');
|
||||
Log::debug(print_r('$productCatalog->getErrors()', true));
|
||||
Log::debug(print_r($productCatalog->getErrors(), true));
|
||||
|
||||
$this->Flash->error(__('The product catalog could not be saved. Please, try again.'));
|
||||
}
|
||||
$this->set(compact('productCatalog'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit method
|
||||
*
|
||||
* @param string|null $id Product Catalog id.
|
||||
* @return Response|null|void Redirects on successful edit, renders view otherwise.
|
||||
* @throws RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function edit($id = null)
|
||||
{
|
||||
$productCatalog = $this->ProductCatalogs->get($id, contain: []);
|
||||
if ($this->request->is(['patch', 'post', 'put'])) {
|
||||
$productCatalog = $this->ProductCatalogs->patchEntity($productCatalog, $this->request->getData());
|
||||
if ($this->ProductCatalogs->save($productCatalog)) {
|
||||
$this->Flash->success(__('The product catalog has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
$this->Flash->error(__('The product catalog could not be saved. Please, try again.'));
|
||||
}
|
||||
$this->set(compact('productCatalog'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete method
|
||||
*
|
||||
* @param string|null $id Product Catalog id.
|
||||
* @return Response|null Redirects to index.
|
||||
* @throws RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
$this->request->allowMethod(['post', 'delete']);
|
||||
$productCatalog = $this->ProductCatalogs->get($id);
|
||||
if ($this->ProductCatalogs->delete($productCatalog)) {
|
||||
$this->Flash->success(__('The product catalog has been deleted.'));
|
||||
} else {
|
||||
$this->Flash->error(__('The product catalog could not be deleted. Please, try again.'));
|
||||
}
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
}
|
||||
115
src/Controller/ProductCategoriesController.php
Normal file
115
src/Controller/ProductCategoriesController.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Controller;
|
||||
|
||||
use Cake\Log\Log;
|
||||
use CakeProducts\Controller\AppController;
|
||||
use CakeProducts\Service\InternalCatalogManagerService;
|
||||
|
||||
/**
|
||||
* ProductCategories Controller
|
||||
*
|
||||
* @property \CakeProducts\Model\Table\ProductCategoriesTable $ProductCategories
|
||||
*/
|
||||
class ProductCategoriesController extends AppController
|
||||
{
|
||||
/**
|
||||
* Index method
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Renders view
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$query = $this->ProductCategories->find()
|
||||
->contain(['ProductCatalogs', 'ParentProductCategories']);
|
||||
$productCategories = $this->paginate($query);
|
||||
|
||||
$this->set(compact('productCategories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* View method
|
||||
*
|
||||
* @param string|null $id Product Category id.
|
||||
* @return \Cake\Http\Response|null|void Renders view
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function view(InternalCatalogManagerService $catalogManagerService, $id = null)
|
||||
{
|
||||
$productCategory = $catalogManagerService->getCategory($id);
|
||||
$this->set(compact('productCategory'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add method
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
|
||||
*/
|
||||
public function add(InternalCatalogManagerService $catalogManagerService)
|
||||
{
|
||||
$productCategory = $this->ProductCategories->newEmptyEntity();
|
||||
if ($this->request->is('post')) {
|
||||
$postData = $this->request->getData();
|
||||
if ($this->request->getSession()->read('Auth.User.id')) {
|
||||
$postData['created_by'] = $this->request->getSession()->read('Auth.User.id');
|
||||
}
|
||||
$result = $catalogManagerService->createNewCategory($productCategory, $postData);
|
||||
Log::debug(print_r('$result from createNewCategory', true));
|
||||
Log::debug(print_r($result, true));
|
||||
if ($result['result']) {
|
||||
$this->Flash->success(__('The product category has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
$this->Flash->error(__('The product category could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCatalogs = $this->ProductCategories->ProductCatalogs->find('list', limit: 200)->all();
|
||||
$parentProductCategories = $this->ProductCategories->ParentProductCategories->find('list', limit: 200)->all();
|
||||
$this->set(compact('productCategory', 'productCatalogs', 'parentProductCategories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit method
|
||||
*
|
||||
* @param string|null $id Product Category id.
|
||||
* @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function edit(InternalCatalogManagerService $catalogManagerService, $id = null)
|
||||
{
|
||||
$productCategory = $this->ProductCategories->get($id, contain: []);
|
||||
if ($this->request->is(['patch', 'post', 'put'])) {
|
||||
$productCategory = $this->ProductCategories->patchEntity($productCategory, $this->request->getData());
|
||||
if ($this->ProductCategories->save($productCategory)) {
|
||||
$this->Flash->success(__('The product category has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
$this->Flash->error(__('The product category could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCatalogs = $this->ProductCategories->ProductCatalogs->find('list', limit: 200)->all();
|
||||
$parentProductCategories = $this->ProductCategories->ParentProductCategories->find('list', limit: 200)->all();
|
||||
$this->set(compact('productCategory', 'productCatalogs', 'parentProductCategories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete method
|
||||
*
|
||||
* @param string|null $id Product Category id.
|
||||
* @return \Cake\Http\Response|null Redirects to index.
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
$this->request->allowMethod(['post', 'delete']);
|
||||
$productCategory = $this->ProductCategories->get($id);
|
||||
if ($this->ProductCategories->delete($productCategory)) {
|
||||
$this->Flash->success(__('The product category has been deleted.'));
|
||||
} else {
|
||||
$this->Flash->error(__('The product category could not be deleted. Please, try again.'));
|
||||
}
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
}
|
||||
48
src/Controller/ProductCategoryAttributeOptionsController.php
Normal file
48
src/Controller/ProductCategoryAttributeOptionsController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Controller;
|
||||
|
||||
use Cake\Log\Log;
|
||||
use CakeProducts\Controller\AppController;
|
||||
|
||||
/**
|
||||
* ProductCategoryAttributeOptions Controller
|
||||
*
|
||||
* @property \CakeProducts\Model\Table\ProductCategoryAttributeOptionsTable $ProductCategoryAttributeOptions
|
||||
*/
|
||||
class ProductCategoryAttributeOptionsController extends AppController
|
||||
{
|
||||
/**
|
||||
* Add method
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
Log::debug('inside product category attribute options controller add');
|
||||
|
||||
$productCategoryAttributeOption = $this->ProductCategoryAttributeOptions->newEmptyEntity();
|
||||
$this->set(compact('productCategoryAttributeOption'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete method
|
||||
*
|
||||
* @param string|null $id Product Category Attribute Option id.
|
||||
* @return \Cake\Http\Response|null Redirects to index.
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
$this->request->allowMethod(['post', 'delete']);
|
||||
$productCategoryAttributeOption = $this->ProductCategoryAttributeOptions->get($id);
|
||||
if ($this->ProductCategoryAttributeOptions->delete($productCategoryAttributeOption)) {
|
||||
$this->Flash->success(__('The product category attribute option has been deleted.'));
|
||||
} else {
|
||||
$this->Flash->error(__('The product category attribute option could not be deleted. Please, try again.'));
|
||||
}
|
||||
|
||||
return $this->redirect(['controller' => 'ProductCategoryAttributes', 'action' => 'view', $productCategoryAttributeOption->product_category_attribute_id]);
|
||||
}
|
||||
}
|
||||
144
src/Controller/ProductCategoryAttributesController.php
Normal file
144
src/Controller/ProductCategoryAttributesController.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Controller;
|
||||
|
||||
use Cake\Datasource\Exception\RecordNotFoundException;
|
||||
use Cake\Http\Response;
|
||||
use Cake\Log\Log;
|
||||
use CakeProducts\Controller\AppController;
|
||||
use CakeProducts\Model\Enum\ProductCategoryAttributeTypeId;
|
||||
use CakeProducts\Model\Table\ProductCategoryAttributesTable;
|
||||
|
||||
/**
|
||||
* ProductCategoryAttributes Controller
|
||||
*
|
||||
* @property ProductCategoryAttributesTable $ProductCategoryAttributes
|
||||
*/
|
||||
class ProductCategoryAttributesController extends AppController
|
||||
{
|
||||
/**
|
||||
* Index method
|
||||
*
|
||||
* @return Response|null|void Renders view
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$query = $this->ProductCategoryAttributes->find()
|
||||
->contain(['ProductCategories']);
|
||||
$productCategoryAttributes = $this->paginate($query);
|
||||
|
||||
$this->set(compact('productCategoryAttributes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* View method
|
||||
*
|
||||
* @param string|null $id Product Category Attribute id.
|
||||
* @return Response|null|void Renders view
|
||||
* @throws RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function view($id = null)
|
||||
{
|
||||
$productCategoryAttribute = $this->ProductCategoryAttributes->get($id, contain: [
|
||||
'ProductCategories',
|
||||
'ProductCategoryAttributeOptions',
|
||||
]);
|
||||
$this->set(compact('productCategoryAttribute'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add method
|
||||
*
|
||||
* @return Response|null|void Redirects on successful add, renders view otherwise.
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$productCategoryAttribute = $this->ProductCategoryAttributes->newEmptyEntity();
|
||||
if ($this->request->is('post')) {
|
||||
$postData = $this->request->getData();
|
||||
$saveOptions = [
|
||||
'associated' => ['ProductCategoryAttributeOptions'],
|
||||
];
|
||||
Log::debug(print_r('$postData', true));
|
||||
Log::debug(print_r($postData, true));
|
||||
// if ($this->request->getData('attribute_type_id') != ProductCategoryAttributeTypeId::Constrained) {
|
||||
// $saveOptions['associated'] = [];
|
||||
// $postData['product_category_attribute_options'] = [];
|
||||
// }
|
||||
Log::debug(print_r('$postData', true));
|
||||
Log::debug(print_r($postData, true));
|
||||
$productCategoryAttribute = $this->ProductCategoryAttributes->patchEntity($productCategoryAttribute, $postData, $saveOptions);
|
||||
if ($this->ProductCategoryAttributes->save($productCategoryAttribute, $saveOptions)) {
|
||||
$this->Flash->success(__('The product category attribute has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
Log::debug('failed to save new product category attribute errors next');
|
||||
Log::debug(print_r('$productCategoryAttribute->getErrors()', true));
|
||||
Log::debug(print_r($productCategoryAttribute->getErrors(), true));
|
||||
$this->Flash->error(__('The product category attribute could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCategories = $this->ProductCategoryAttributes->ProductCategories->find('list', limit: 200)->all();
|
||||
$this->set(compact('productCategoryAttribute', 'productCategories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit method
|
||||
*
|
||||
* @param string|null $id Product Category Attribute id.
|
||||
* @return Response|null|void Redirects on successful edit, renders view otherwise.
|
||||
* @throws RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function edit($id = null)
|
||||
{
|
||||
$productCategoryAttribute = $this->ProductCategoryAttributes->get($id, contain: ['ProductCategoryAttributeOptions']);
|
||||
if ($this->request->is(['patch', 'post', 'put'])) {
|
||||
$postData = $this->request->getData();
|
||||
$saveOptions = [
|
||||
'associated' => ['ProductCategoryAttributeOptions'],
|
||||
];
|
||||
Log::debug(print_r('$postData', true));
|
||||
Log::debug(print_r($postData, true));
|
||||
// if ($this->request->getData('attribute_type_id') != ProductCategoryAttributeTypeId::Constrained) {
|
||||
// $saveOptions['associated'] = [];
|
||||
// $postData['product_category_attribute_options'] = [];
|
||||
// }
|
||||
Log::debug(print_r('$postData', true));
|
||||
Log::debug(print_r($postData, true));
|
||||
$productCategoryAttribute = $this->ProductCategoryAttributes->patchEntity($productCategoryAttribute, $postData, $saveOptions);
|
||||
|
||||
if ($this->ProductCategoryAttributes->save($productCategoryAttribute, $saveOptions)) {
|
||||
$this->Flash->success(__('The product category attribute has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
Log::debug('failed to save product category attribute on edit errors next');
|
||||
Log::debug(print_r('$productCategoryAttribute->getErrors()', true));
|
||||
Log::debug(print_r($productCategoryAttribute->getErrors(), true));
|
||||
$this->Flash->error(__('The product category attribute could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCategories = $this->ProductCategoryAttributes->ProductCategories->find('list', limit: 200)->all();
|
||||
$this->set(compact('productCategoryAttribute', 'productCategories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete method
|
||||
*
|
||||
* @param string|null $id Product Category Attribute id.
|
||||
* @return Response|null Redirects to index.
|
||||
* @throws RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
$this->request->allowMethod(['post', 'delete']);
|
||||
$productCategoryAttribute = $this->ProductCategoryAttributes->get($id);
|
||||
if ($this->ProductCategoryAttributes->delete($productCategoryAttribute)) {
|
||||
$this->Flash->success(__('The product category attribute has been deleted.'));
|
||||
} else {
|
||||
$this->Flash->error(__('The product category attribute could not be deleted. Please, try again.'));
|
||||
}
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
}
|
||||
110
src/Controller/ProductsController.php
Normal file
110
src/Controller/ProductsController.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Controller;
|
||||
|
||||
use Cake\Log\Log;
|
||||
use CakeProducts\Controller\AppController;
|
||||
|
||||
/**
|
||||
* Products Controller
|
||||
*
|
||||
* @property \CakeProducts\Model\Table\ProductsTable $Products
|
||||
*/
|
||||
class ProductsController extends AppController
|
||||
{
|
||||
/**
|
||||
* Index method
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Renders view
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$query = $this->Products->find()
|
||||
->contain(['ProductCategories']);
|
||||
$products = $this->paginate($query);
|
||||
|
||||
$this->set(compact('products'));
|
||||
}
|
||||
|
||||
/**
|
||||
* View method
|
||||
*
|
||||
* @param string|null $id Product id.
|
||||
* @return \Cake\Http\Response|null|void Renders view
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function view($id = null)
|
||||
{
|
||||
$product = $this->Products->get($id, contain: ['ProductCategories']);
|
||||
$this->set(compact('product'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add method
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$product = $this->Products->newEmptyEntity();
|
||||
if ($this->request->is('post')) {
|
||||
$product = $this->Products->patchEntity($product, $this->request->getData());
|
||||
if ($this->Products->save($product)) {
|
||||
$this->Flash->success(__('The product has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
Log::debug(print_r('$product->getErrors() next - failed in products/add', true));
|
||||
Log::debug(print_r($product->getErrors(), true));
|
||||
$this->Flash->error(__('The product could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCategories = $this->Products->ProductCategories->find('list', limit: 200)->all();
|
||||
$this->set(compact('product', 'productCategories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit method
|
||||
*
|
||||
* @param string|null $id Product id.
|
||||
* @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function edit($id = null)
|
||||
{
|
||||
$product = $this->Products->get($id, contain: []);
|
||||
if ($this->request->is(['patch', 'post', 'put'])) {
|
||||
$product = $this->Products->patchEntity($product, $this->request->getData());
|
||||
if ($this->Products->save($product)) {
|
||||
$this->Flash->success(__('The product has been saved.'));
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
Log::debug(print_r('$product->getErrors() next - failed in products/edit', true));
|
||||
Log::debug(print_r($product->getErrors(), true));
|
||||
$this->Flash->error(__('The product could not be saved. Please, try again.'));
|
||||
}
|
||||
$productCategories = $this->Products->ProductCategories->find('list', limit: 200)->all();
|
||||
$this->set(compact('product', 'productCategories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete method
|
||||
*
|
||||
* @param string|null $id Product id.
|
||||
* @return \Cake\Http\Response|null Redirects to index.
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
$this->request->allowMethod(['post', 'delete']);
|
||||
$product = $this->Products->get($id);
|
||||
if ($this->Products->delete($product)) {
|
||||
$this->Flash->success(__('The product has been deleted.'));
|
||||
} else {
|
||||
$this->Flash->error(__('The product could not be deleted. Please, try again.'));
|
||||
}
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
}
|
||||
41
src/Model/Entity/ExternalProductCatalog.php
Normal file
41
src/Model/Entity/ExternalProductCatalog.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* ExternalProductCatalog Entity
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $product_catalog_id
|
||||
* @property string $base_url
|
||||
* @property string $api_url
|
||||
* @property \Cake\I18n\DateTime $created
|
||||
* @property \Cake\I18n\DateTime|null $deleted
|
||||
* @property bool $enabled
|
||||
*
|
||||
* @property \CakeProducts\Model\Entity\ProductCatalog $product_catalog
|
||||
*/
|
||||
class ExternalProductCatalog extends Entity
|
||||
{
|
||||
/**
|
||||
* Fields that can be mass assigned using newEntity() or patchEntity().
|
||||
*
|
||||
* Note that when '*' is set to true, this allows all unspecified fields to
|
||||
* be mass assigned. For security purposes, it is advised to set '*' to false
|
||||
* (or remove it), and explicitly make individual fields accessible as needed.
|
||||
*
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
protected array $_accessible = [
|
||||
'product_catalog_id' => true,
|
||||
'base_url' => true,
|
||||
'api_url' => true,
|
||||
'created' => true,
|
||||
'deleted' => true,
|
||||
'enabled' => true,
|
||||
'product_catalog' => true,
|
||||
];
|
||||
}
|
||||
35
src/Model/Entity/Product.php
Normal file
35
src/Model/Entity/Product.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* Product Entity
|
||||
*
|
||||
* @property string $id
|
||||
* @property string $name
|
||||
* @property string $product_category_id
|
||||
* @property \CakeProducts\Model\Enum\ProductProductTypeId $product_type_id
|
||||
*
|
||||
* @property \CakeProducts\Model\Entity\ProductCategory $product_category
|
||||
*/
|
||||
class Product extends Entity
|
||||
{
|
||||
/**
|
||||
* Fields that can be mass assigned using newEntity() or patchEntity().
|
||||
*
|
||||
* Note that when '*' is set to true, this allows all unspecified fields to
|
||||
* be mass assigned. For security purposes, it is advised to set '*' to false
|
||||
* (or remove it), and explicitly make individual fields accessible as needed.
|
||||
*
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
protected array $_accessible = [
|
||||
'name' => true,
|
||||
'product_category_id' => true,
|
||||
'product_type_id' => true,
|
||||
'product_category' => true,
|
||||
];
|
||||
}
|
||||
37
src/Model/Entity/ProductCatalog.php
Normal file
37
src/Model/Entity/ProductCatalog.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* ProductCatalog Entity
|
||||
*
|
||||
* @property string $id
|
||||
* @property string $name
|
||||
* @property string|null $catalog_description
|
||||
* @property bool $enabled
|
||||
*
|
||||
* @property \CakeProducts\Model\Entity\ProductCategory[] $product_categories
|
||||
* @property \CakeProducts\Model\Entity\ExternalProductCatalog[] $external_product_catalogs
|
||||
*/
|
||||
class ProductCatalog extends Entity
|
||||
{
|
||||
/**
|
||||
* Fields that can be mass assigned using newEntity() or patchEntity().
|
||||
*
|
||||
* Note that when '*' is set to true, this allows all unspecified fields to
|
||||
* be mass assigned. For security purposes, it is advised to set '*' to false
|
||||
* (or remove it), and explicitly make individual fields accessible as needed.
|
||||
*
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
protected array $_accessible = [
|
||||
'name' => true,
|
||||
'catalog_description' => true,
|
||||
'enabled' => true,
|
||||
'product_categories' => true,
|
||||
'external_product_catalogs' => true,
|
||||
];
|
||||
}
|
||||
49
src/Model/Entity/ProductCategory.php
Normal file
49
src/Model/Entity/ProductCategory.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* ProductCategory Entity
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $internal_id
|
||||
* @property string $product_catalog_id
|
||||
* @property string $name
|
||||
* @property string|null $category_description
|
||||
* @property int|null $parent_id
|
||||
* @property int $lft
|
||||
* @property int $rght
|
||||
* @property bool $enabled
|
||||
*
|
||||
* @property \CakeProducts\Model\Entity\ProductCatalog $product_catalog
|
||||
* @property \CakeProducts\Model\Entity\ParentProductCategory $parent_product_category
|
||||
* @property \CakeProducts\Model\Entity\ChildProductCategory[] $child_product_categories
|
||||
*/
|
||||
class ProductCategory extends Entity
|
||||
{
|
||||
/**
|
||||
* Fields that can be mass assigned using newEntity() or patchEntity().
|
||||
*
|
||||
* Note that when '*' is set to true, this allows all unspecified fields to
|
||||
* be mass assigned. For security purposes, it is advised to set '*' to false
|
||||
* (or remove it), and explicitly make individual fields accessible as needed.
|
||||
*
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
protected array $_accessible = [
|
||||
'product_catalog_id' => true,
|
||||
'internal_id' => true,
|
||||
'name' => true,
|
||||
'category_description' => true,
|
||||
'parent_id' => true,
|
||||
'lft' => true,
|
||||
'rght' => true,
|
||||
'enabled' => true,
|
||||
'product_catalog' => true,
|
||||
'parent_product_category' => true,
|
||||
'child_product_categories' => true,
|
||||
];
|
||||
}
|
||||
39
src/Model/Entity/ProductCategoryAttribute.php
Normal file
39
src/Model/Entity/ProductCategoryAttribute.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* ProductCategoryAttribute Entity
|
||||
*
|
||||
* @property string $id
|
||||
* @property string $name
|
||||
* @property string|null $product_category_id
|
||||
* @property int $attribute_type_id
|
||||
* @property bool $enabled
|
||||
*
|
||||
* @property ProductCategory $product_category
|
||||
* @property ProductCategoryAttributeOption[] $product_category_attribute_options
|
||||
*/
|
||||
class ProductCategoryAttribute extends Entity
|
||||
{
|
||||
/**
|
||||
* Fields that can be mass assigned using newEntity() or patchEntity().
|
||||
*
|
||||
* Note that when '*' is set to true, this allows all unspecified fields to
|
||||
* be mass assigned. For security purposes, it is advised to set '*' to false
|
||||
* (or remove it), and explicitly make individual fields accessible as needed.
|
||||
*
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
protected array $_accessible = [
|
||||
'name' => true,
|
||||
'product_category_id' => true,
|
||||
'attribute_type_id' => true,
|
||||
'enabled' => true,
|
||||
'product_category' => true,
|
||||
'product_category_attribute_options' => true,
|
||||
];
|
||||
}
|
||||
37
src/Model/Entity/ProductCategoryAttributeOption.php
Normal file
37
src/Model/Entity/ProductCategoryAttributeOption.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* ProductCategoryAttributeOption Entity
|
||||
*
|
||||
* @property string $id
|
||||
* @property string $product_category_attribute_id
|
||||
* @property string $attribute_value
|
||||
* @property string $attribute_label
|
||||
* @property bool $enabled
|
||||
*
|
||||
* @property ProductCategoryAttribute $product_category_attribute
|
||||
*/
|
||||
class ProductCategoryAttributeOption extends Entity
|
||||
{
|
||||
/**
|
||||
* Fields that can be mass assigned using newEntity() or patchEntity().
|
||||
*
|
||||
* Note that when '*' is set to true, this allows all unspecified fields to
|
||||
* be mass assigned. For security purposes, it is advised to set '*' to false
|
||||
* (or remove it), and explicitly make individual fields accessible as needed.
|
||||
*
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
protected array $_accessible = [
|
||||
'product_category_attribute_id' => true,
|
||||
'attribute_value' => true,
|
||||
'attribute_label' => true,
|
||||
'enabled' => true,
|
||||
'product_category_attribute' => true,
|
||||
];
|
||||
}
|
||||
23
src/Model/Enum/ProductCategoryAttributeTypeId.php
Normal file
23
src/Model/Enum/ProductCategoryAttributeTypeId.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace CakeProducts\Model\Enum;
|
||||
|
||||
use Cake\Database\Type\EnumLabelInterface;
|
||||
use Tools\Model\Enum\EnumOptionsTrait;
|
||||
|
||||
enum ProductCategoryAttributeTypeId: int implements EnumLabelInterface
|
||||
{
|
||||
use EnumOptionsTrait;
|
||||
|
||||
case Constrained = 1;
|
||||
case Text = 2;
|
||||
case Integer = 3;
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return match($this) {
|
||||
self::Constrained => 'Constrained',
|
||||
self::Text => 'Text',
|
||||
self::Integer => 'Integer'
|
||||
};
|
||||
}
|
||||
}
|
||||
23
src/Model/Enum/ProductProductTypeId.php
Normal file
23
src/Model/Enum/ProductProductTypeId.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace CakeProducts\Model\Enum;
|
||||
|
||||
use Cake\Database\Type\EnumLabelInterface;
|
||||
use Tools\Model\Enum\EnumOptionsTrait;
|
||||
|
||||
enum ProductProductTypeId: int implements EnumLabelInterface
|
||||
{
|
||||
use EnumOptionsTrait;
|
||||
|
||||
case Service = 1;
|
||||
case Product = 2;
|
||||
case Consumable = 3;
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return match($this) {
|
||||
self::Service => 'Service',
|
||||
self::Product => 'Product',
|
||||
self::Consumable => 'Consumable'
|
||||
};
|
||||
}
|
||||
}
|
||||
115
src/Model/Table/ExternalProductCatalogsTable.php
Normal file
115
src/Model/Table/ExternalProductCatalogsTable.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Table;
|
||||
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\Datasource\ResultSetInterface;
|
||||
use Cake\ORM\Association\BelongsTo;
|
||||
use Cake\ORM\Behavior\TimestampBehavior;
|
||||
use Cake\ORM\Query\SelectQuery;
|
||||
use Cake\ORM\RulesChecker;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use CakeProducts\Model\Entity\ExternalProductCatalog;
|
||||
use Closure;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
/**
|
||||
* ExternalProductCatalogs Model
|
||||
*
|
||||
* @property ProductCatalogsTable&BelongsTo $ProductCatalogs
|
||||
*
|
||||
* @method ExternalProductCatalog newEmptyEntity()
|
||||
* @method ExternalProductCatalog newEntity(array $data, array $options = [])
|
||||
* @method array<ExternalProductCatalog> newEntities(array $data, array $options = [])
|
||||
* @method ExternalProductCatalog get(mixed $primaryKey, array|string $finder = 'all', CacheInterface|string|null $cache = null, Closure|string|null $cacheKey = null, mixed ...$args)
|
||||
* @method ExternalProductCatalog findOrCreate($search, ?callable $callback = null, array $options = [])
|
||||
* @method ExternalProductCatalog patchEntity(EntityInterface $entity, array $data, array $options = [])
|
||||
* @method array<ExternalProductCatalog> patchEntities(iterable $entities, array $data, array $options = [])
|
||||
* @method ExternalProductCatalog|false save(EntityInterface $entity, array $options = [])
|
||||
* @method ExternalProductCatalog saveOrFail(EntityInterface $entity, array $options = [])
|
||||
* @method iterable<ExternalProductCatalog>|ResultSetInterface<ExternalProductCatalog>|false saveMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ExternalProductCatalog>|ResultSetInterface<ExternalProductCatalog> saveManyOrFail(iterable $entities, array $options = [])
|
||||
* @method iterable<ExternalProductCatalog>|ResultSetInterface<ExternalProductCatalog>|false deleteMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ExternalProductCatalog>|ResultSetInterface<ExternalProductCatalog> deleteManyOrFail(iterable $entities, array $options = [])
|
||||
*
|
||||
* @mixin TimestampBehavior
|
||||
*/
|
||||
class ExternalProductCatalogsTable extends Table
|
||||
{
|
||||
/**
|
||||
* Initialize method
|
||||
*
|
||||
* @param array<string, mixed> $config The configuration for the Table.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
|
||||
$this->setTable('external_product_catalogs');
|
||||
$this->setDisplayField('base_url');
|
||||
$this->setPrimaryKey('id');
|
||||
|
||||
$this->addBehavior('Timestamp');
|
||||
|
||||
$this->belongsTo('ProductCatalogs', [
|
||||
'foreignKey' => 'product_catalog_id',
|
||||
'joinType' => 'INNER',
|
||||
'className' => 'CakeProducts.ProductCatalogs',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default validation rules.
|
||||
*
|
||||
* @param Validator $validator Validator instance.
|
||||
* @return Validator
|
||||
*/
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
{
|
||||
$validator
|
||||
->uuid('product_catalog_id')
|
||||
->notEmptyString('product_catalog_id');
|
||||
|
||||
$validator
|
||||
->scalar('base_url')
|
||||
->maxLength('base_url', 255)
|
||||
->requirePresence('base_url', 'create')
|
||||
->notEmptyString('base_url');
|
||||
// ->url('base_url');
|
||||
|
||||
$validator
|
||||
->scalar('api_url')
|
||||
->maxLength('api_url', 255)
|
||||
->requirePresence('api_url', 'create')
|
||||
->notEmptyString('api_url');
|
||||
// ->url('api_url');
|
||||
|
||||
$validator
|
||||
->dateTime('deleted')
|
||||
->allowEmptyDateTime('deleted');
|
||||
|
||||
$validator
|
||||
->boolean('enabled')
|
||||
->requirePresence('enabled', 'create')
|
||||
->notEmptyString('enabled');
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rules checker object that will be used for validating
|
||||
* application integrity.
|
||||
*
|
||||
* @param RulesChecker $rules The rules object to be modified.
|
||||
* @return RulesChecker
|
||||
*/
|
||||
public function buildRules(RulesChecker $rules): RulesChecker
|
||||
{
|
||||
$rules->add($rules->existsIn(['product_catalog_id'], 'ProductCatalogs'), ['errorField' => 'product_catalog_id']);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
99
src/Model/Table/ProductCatalogsTable.php
Normal file
99
src/Model/Table/ProductCatalogsTable.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Table;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\Datasource\ResultSetInterface;
|
||||
use Cake\ORM\Query\SelectQuery;
|
||||
use Cake\ORM\RulesChecker;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use CakeProducts\Model\Entity\ProductCatalog;
|
||||
use Closure;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
/**
|
||||
* ProductCatalogs Model
|
||||
*
|
||||
* @method ProductCatalog newEmptyEntity()
|
||||
* @method ProductCatalog newEntity(array $data, array $options = [])
|
||||
* @method array<ProductCatalog> newEntities(array $data, array $options = [])
|
||||
* @method ProductCatalog get(mixed $primaryKey, array|string $finder = 'all', CacheInterface|string|null $cache = null, Closure|string|null $cacheKey = null, mixed ...$args)
|
||||
* @method ProductCatalog findOrCreate($search, ?callable $callback = null, array $options = [])
|
||||
* @method ProductCatalog patchEntity(EntityInterface $entity, array $data, array $options = [])
|
||||
* @method array<ProductCatalog> patchEntities(iterable $entities, array $data, array $options = [])
|
||||
* @method ProductCatalog|false save(EntityInterface $entity, array $options = [])
|
||||
* @method ProductCatalog saveOrFail(EntityInterface $entity, array $options = [])
|
||||
* @method iterable<ProductCatalog>|ResultSetInterface<ProductCatalog>|false saveMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCatalog>|ResultSetInterface<ProductCatalog> saveManyOrFail(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCatalog>|ResultSetInterface<ProductCatalog>|false deleteMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCatalog>|ResultSetInterface<ProductCatalog> deleteManyOrFail(iterable $entities, array $options = [])
|
||||
*/
|
||||
class ProductCatalogsTable extends Table
|
||||
{
|
||||
/**
|
||||
* Initialize method
|
||||
*
|
||||
* @param array<string, mixed> $config The configuration for the Table.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
|
||||
$this->setTable('product_catalogs');
|
||||
$this->setDisplayField('name');
|
||||
$this->setPrimaryKey('id');
|
||||
|
||||
$this->hasMany('ProductCategories', [
|
||||
'className' => 'CakeProducts.ProductCategories',
|
||||
]);
|
||||
$this->hasMany('ExternalProductCatalogs', [
|
||||
'className' => 'CakeProducts.ExternalProductCatalogs',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default validation rules.
|
||||
*
|
||||
* @param Validator $validator Validator instance.
|
||||
* @return Validator
|
||||
*/
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
{
|
||||
$validator
|
||||
->scalar('name')
|
||||
->maxLength('name', 255)
|
||||
->requirePresence('name', 'create')
|
||||
->notEmptyString('name')
|
||||
->add('name', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
|
||||
|
||||
$validator
|
||||
->scalar('catalog_description')
|
||||
->maxLength('catalog_description', 255)
|
||||
->allowEmptyString('catalog_description');
|
||||
|
||||
$validator
|
||||
->boolean('enabled')
|
||||
->requirePresence('enabled', 'create')
|
||||
->notEmptyString('enabled');
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rules checker object that will be used for validating
|
||||
* application integrity.
|
||||
*
|
||||
* @param RulesChecker $rules The rules object to be modified.
|
||||
* @return RulesChecker
|
||||
*/
|
||||
public function buildRules(RulesChecker $rules): RulesChecker
|
||||
{
|
||||
$rules->add($rules->isUnique(['name']), ['errorField' => 'name']);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
164
src/Model/Table/ProductCategoriesTable.php
Normal file
164
src/Model/Table/ProductCategoriesTable.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Table;
|
||||
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\Datasource\ResultSetInterface;
|
||||
use Cake\ORM\Association\BelongsTo;
|
||||
use Cake\ORM\Association\HasMany;
|
||||
use Cake\ORM\Behavior\TreeBehavior;
|
||||
use Cake\ORM\Query\SelectQuery;
|
||||
use Cake\ORM\RulesChecker;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use CakeProducts\Model\Entity\ProductCategory;
|
||||
use Closure;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
/**
|
||||
* ProductCategories Model
|
||||
*
|
||||
* @property ProductCatalogsTable&BelongsTo $ProductCatalogs
|
||||
* @property ProductCategoriesTable&BelongsTo $ParentProductCategories
|
||||
* @property ProductCategoriesTable&HasMany $ChildProductCategories
|
||||
*
|
||||
* @method ProductCategory newEmptyEntity()
|
||||
* @method ProductCategory newEntity(array $data, array $options = [])
|
||||
* @method array<ProductCategory> newEntities(array $data, array $options = [])
|
||||
* @method ProductCategory get(mixed $primaryKey, array|string $finder = 'all', CacheInterface|string|null $cache = null, Closure|string|null $cacheKey = null, mixed ...$args)
|
||||
* @method ProductCategory findOrCreate($search, ?callable $callback = null, array $options = [])
|
||||
* @method ProductCategory patchEntity(EntityInterface $entity, array $data, array $options = [])
|
||||
* @method array<ProductCategory> patchEntities(iterable $entities, array $data, array $options = [])
|
||||
* @method ProductCategory saveOrFail(EntityInterface $entity, array $options = [])
|
||||
* @method iterable<ProductCategory>|ResultSetInterface<ProductCategory>|false saveMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategory>|ResultSetInterface<ProductCategory> saveManyOrFail(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategory>|ResultSetInterface<ProductCategory>|false deleteMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategory>|ResultSetInterface<ProductCategory> deleteManyOrFail(iterable $entities, array $options = [])
|
||||
*
|
||||
* @mixin TreeBehavior
|
||||
*/
|
||||
class ProductCategoriesTable extends Table
|
||||
{
|
||||
/**
|
||||
* Current scope for Tree behavior - per catalog
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $treeCatalogId;
|
||||
|
||||
/**
|
||||
* Initialize method
|
||||
*
|
||||
* @param array<string, mixed> $config The configuration for the Table.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
$this->treeCatalogId = 1;
|
||||
|
||||
$this->setTable('product_categories');
|
||||
$this->setDisplayField('name');
|
||||
$this->setPrimaryKey('id');
|
||||
|
||||
$this->addBehavior('Tree');
|
||||
|
||||
$this->belongsTo('ProductCatalogs', [
|
||||
'foreignKey' => 'product_catalog_id',
|
||||
'joinType' => 'INNER',
|
||||
'className' => 'CakeProducts.ProductCatalogs',
|
||||
]);
|
||||
$this->belongsTo('ParentProductCategories', [
|
||||
'className' => 'CakeProducts.ProductCategories',
|
||||
'foreignKey' => 'parent_id',
|
||||
]);
|
||||
$this->hasMany('ChildProductCategories', [
|
||||
'className' => 'CakeProducts.ProductCategories',
|
||||
'foreignKey' => 'parent_id',
|
||||
]);
|
||||
$this->hasMany('ProductCategoryAttributes', [
|
||||
'foreignKey' => 'product_category_id',
|
||||
'bindingKey' => 'internal_id',
|
||||
'className' => 'CakeProducts.ProductCategoryAttributes',
|
||||
]);
|
||||
$this->behaviors()->Tree->setConfig('scope', ['product_catalog_id' => $this->treeCatalogId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default validation rules.
|
||||
*
|
||||
* @param Validator $validator Validator instance.
|
||||
* @return Validator
|
||||
*/
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
{
|
||||
$validator
|
||||
->uuid('product_catalog_id')
|
||||
->notEmptyString('product_catalog_id');
|
||||
|
||||
$validator
|
||||
->scalar('name')
|
||||
->maxLength('name', 255)
|
||||
->requirePresence('name', 'create')
|
||||
->notEmptyString('name');
|
||||
|
||||
$validator
|
||||
->scalar('category_description')
|
||||
->allowEmptyString('category_description');
|
||||
|
||||
$validator
|
||||
->integer('parent_id')
|
||||
->allowEmptyString('parent_id');
|
||||
|
||||
$validator
|
||||
->boolean('enabled')
|
||||
->notEmptyString('enabled');
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rules checker object that will be used for validating
|
||||
* application integrity.
|
||||
*
|
||||
* @param RulesChecker $rules The rules object to be modified.
|
||||
* @return RulesChecker
|
||||
*/
|
||||
public function buildRules(RulesChecker $rules): RulesChecker
|
||||
{
|
||||
$rules->add($rules->isUnique(['product_catalog_id', 'name']), ['errorField' => 'product_catalog_id']);
|
||||
$rules->add($rules->existsIn(['product_catalog_id'], 'ProductCatalogs'), ['errorField' => 'product_catalog_id']);
|
||||
$rules->add($rules->existsIn(['parent_id'], 'ParentProductCategories'), ['errorField' => 'parent_id']);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $catalogId
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setConfigureCatalogId(string $catalogId)
|
||||
{
|
||||
$this->treeCatalogId = $catalogId;
|
||||
$this->behaviors()->Tree->setConfig('scope', ['product_catalog_id' => $this->treeCatalogId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityInterface $entity
|
||||
* @param array $options
|
||||
*
|
||||
* @return EntityInterface|false
|
||||
*/
|
||||
public function save(EntityInterface $entity, array $options = []): EntityInterface|false
|
||||
{
|
||||
$this->behaviors()->get('Tree')->setConfig([
|
||||
'scope' => [
|
||||
'product_catalog_id' => $entity->product_catalog_id,
|
||||
],
|
||||
]);
|
||||
|
||||
return parent::save($entity, $options);
|
||||
}
|
||||
}
|
||||
103
src/Model/Table/ProductCategoryAttributeOptionsTable.php
Normal file
103
src/Model/Table/ProductCategoryAttributeOptionsTable.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Table;
|
||||
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\Datasource\ResultSetInterface;
|
||||
use Cake\ORM\Association\BelongsTo;
|
||||
use Cake\ORM\Query\SelectQuery;
|
||||
use Cake\ORM\RulesChecker;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use CakeProducts\Model\Entity\ProductCategoryAttributeOption;
|
||||
use Closure;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
/**
|
||||
* ProductCategoryAttributeOptions Model
|
||||
*
|
||||
* @property ProductCategoryAttributesTable&BelongsTo $ProductCategoryAttributes
|
||||
*
|
||||
* @method ProductCategoryAttributeOption newEmptyEntity()
|
||||
* @method ProductCategoryAttributeOption newEntity(array $data, array $options = [])
|
||||
* @method array<ProductCategoryAttributeOption> newEntities(array $data, array $options = [])
|
||||
* @method ProductCategoryAttributeOption get(mixed $primaryKey, array|string $finder = 'all', CacheInterface|string|null $cache = null, Closure|string|null $cacheKey = null, mixed ...$args)
|
||||
* @method ProductCategoryAttributeOption findOrCreate($search, ?callable $callback = null, array $options = [])
|
||||
* @method ProductCategoryAttributeOption patchEntity(EntityInterface $entity, array $data, array $options = [])
|
||||
* @method array<ProductCategoryAttributeOption> patchEntities(iterable $entities, array $data, array $options = [])
|
||||
* @method ProductCategoryAttributeOption|false save(EntityInterface $entity, array $options = [])
|
||||
* @method ProductCategoryAttributeOption saveOrFail(EntityInterface $entity, array $options = [])
|
||||
* @method iterable<ProductCategoryAttributeOption>|ResultSetInterface<ProductCategoryAttributeOption>|false saveMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategoryAttributeOption>|ResultSetInterface<ProductCategoryAttributeOption> saveManyOrFail(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategoryAttributeOption>|ResultSetInterface<ProductCategoryAttributeOption>|false deleteMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategoryAttributeOption>|ResultSetInterface<ProductCategoryAttributeOption> deleteManyOrFail(iterable $entities, array $options = [])
|
||||
*/
|
||||
class ProductCategoryAttributeOptionsTable extends Table
|
||||
{
|
||||
/**
|
||||
* Initialize method
|
||||
*
|
||||
* @param array<string, mixed> $config The configuration for the Table.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
|
||||
$this->setTable('product_category_attribute_options');
|
||||
$this->setDisplayField('attribute_value');
|
||||
$this->setPrimaryKey('id');
|
||||
|
||||
$this->belongsTo('ProductCategoryAttributes', [
|
||||
'foreignKey' => 'product_category_attribute_id',
|
||||
'joinType' => 'INNER',
|
||||
'className' => 'CakeProducts.ProductCategoryAttributes',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default validation rules.
|
||||
*
|
||||
* @param Validator $validator Validator instance.
|
||||
* @return Validator
|
||||
*/
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
{
|
||||
$validator
|
||||
->integer('product_category_attribute_id')
|
||||
->notEmptyString('product_category_attribute_id');
|
||||
|
||||
$validator
|
||||
->scalar('attribute_value')
|
||||
->maxLength('attribute_value', 255)
|
||||
->requirePresence('attribute_value', 'create')
|
||||
->notEmptyString('attribute_value');
|
||||
|
||||
$validator
|
||||
->scalar('attribute_label')
|
||||
->maxLength('attribute_label', 255)
|
||||
->requirePresence('attribute_label', 'create')
|
||||
->notEmptyString('attribute_label');
|
||||
|
||||
$validator
|
||||
->boolean('enabled')
|
||||
->notEmptyString('enabled');
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rules checker object that will be used for validating
|
||||
* application integrity.
|
||||
*
|
||||
* @param RulesChecker $rules The rules object to be modified.
|
||||
* @return RulesChecker
|
||||
*/
|
||||
public function buildRules(RulesChecker $rules): RulesChecker
|
||||
{
|
||||
$rules->add($rules->existsIn(['product_category_attribute_id'], 'ProductCategoryAttributes'), ['errorField' => '0']);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
113
src/Model/Table/ProductCategoryAttributesTable.php
Normal file
113
src/Model/Table/ProductCategoryAttributesTable.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Table;
|
||||
|
||||
use Cake\Database\Type\EnumType;
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\Datasource\ResultSetInterface;
|
||||
use Cake\ORM\Association\BelongsTo;
|
||||
use Cake\ORM\Query\SelectQuery;
|
||||
use Cake\ORM\RulesChecker;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use CakeProducts\Model\Entity\ProductCategoryAttribute;
|
||||
use CakeProducts\Model\Enum\ProductCategoryAttributeTypeId;
|
||||
use Closure;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
/**
|
||||
* ProductCategoryAttributes Model
|
||||
*
|
||||
* @property ProductCategoriesTable&BelongsTo $ProductCategories
|
||||
*
|
||||
* @method ProductCategoryAttribute newEmptyEntity()
|
||||
* @method ProductCategoryAttribute newEntity(array $data, array $options = [])
|
||||
* @method array<ProductCategoryAttribute> newEntities(array $data, array $options = [])
|
||||
* @method ProductCategoryAttribute get(mixed $primaryKey, array|string $finder = 'all', CacheInterface|string|null $cache = null, Closure|string|null $cacheKey = null, mixed ...$args)
|
||||
* @method ProductCategoryAttribute findOrCreate($search, ?callable $callback = null, array $options = [])
|
||||
* @method ProductCategoryAttribute patchEntity(EntityInterface $entity, array $data, array $options = [])
|
||||
* @method array<ProductCategoryAttribute> patchEntities(iterable $entities, array $data, array $options = [])
|
||||
* @method ProductCategoryAttribute|false save(EntityInterface $entity, array $options = [])
|
||||
* @method ProductCategoryAttribute saveOrFail(EntityInterface $entity, array $options = [])
|
||||
* @method iterable<ProductCategoryAttribute>|ResultSetInterface<ProductCategoryAttribute>|false saveMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategoryAttribute>|ResultSetInterface<ProductCategoryAttribute> saveManyOrFail(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategoryAttribute>|ResultSetInterface<ProductCategoryAttribute>|false deleteMany(iterable $entities, array $options = [])
|
||||
* @method iterable<ProductCategoryAttribute>|ResultSetInterface<ProductCategoryAttribute> deleteManyOrFail(iterable $entities, array $options = [])
|
||||
*/
|
||||
class ProductCategoryAttributesTable extends Table
|
||||
{
|
||||
/**
|
||||
* Initialize method
|
||||
*
|
||||
* @param array<string, mixed> $config The configuration for the Table.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
|
||||
$this->setTable('product_category_attributes');
|
||||
$this->setDisplayField('name');
|
||||
$this->setPrimaryKey('id');
|
||||
|
||||
$this->belongsTo('ProductCategories', [
|
||||
'foreignKey' => 'product_category_id',
|
||||
'bindingKey' => 'internal_id',
|
||||
'className' => 'CakeProducts.ProductCategories',
|
||||
]);
|
||||
|
||||
$this->hasMany('ProductCategoryAttributeOptions', [
|
||||
'foreignKey' => 'product_category_attribute_id',
|
||||
'className' => 'CakeProducts.ProductCategoryAttributeOptions',
|
||||
'saveStrategy' => 'replace',
|
||||
]);
|
||||
$this->getSchema()->setColumnType('attribute_type_id', EnumType::from(ProductCategoryAttributeTypeId::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default validation rules.
|
||||
*
|
||||
* @param Validator $validator Validator instance.
|
||||
* @return Validator
|
||||
*/
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
{
|
||||
$validator
|
||||
->scalar('name')
|
||||
->maxLength('name', 255)
|
||||
->requirePresence('name', 'create')
|
||||
->notEmptyString('name');
|
||||
|
||||
$validator
|
||||
->uuid('product_category_id')
|
||||
->allowEmptyString('product_category_id');
|
||||
|
||||
$validator
|
||||
->integer('attribute_type_id')
|
||||
->requirePresence('attribute_type_id', 'create')
|
||||
->notEmptyString('attribute_type_id');
|
||||
|
||||
$validator
|
||||
->boolean('enabled')
|
||||
->requirePresence('enabled', 'create')
|
||||
->notEmptyString('enabled');
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rules checker object that will be used for validating
|
||||
* application integrity.
|
||||
*
|
||||
* @param RulesChecker $rules The rules object to be modified.
|
||||
* @return RulesChecker
|
||||
*/
|
||||
public function buildRules(RulesChecker $rules): RulesChecker
|
||||
{
|
||||
$rules->add($rules->isUnique(['name', 'product_category_id'], ['allowMultipleNulls' => true]), ['errorField' => 'name']);
|
||||
$rules->add($rules->existsIn(['product_category_id'], 'ProductCategories'), ['errorField' => 'product_category_id']);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
105
src/Model/Table/ProductsTable.php
Normal file
105
src/Model/Table/ProductsTable.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CakeProducts\Model\Table;
|
||||
|
||||
use Cake\Database\Type\EnumType;
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\Datasource\ResultSetInterface;
|
||||
use Cake\ORM\Association\BelongsTo;
|
||||
use Cake\ORM\Query\SelectQuery;
|
||||
use Cake\ORM\RulesChecker;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use CakeProducts\Model\Entity\Product;
|
||||
use CakeProducts\Model\Enum\ProductProductTypeId;
|
||||
use Closure;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
/**
|
||||
* Products Model
|
||||
*
|
||||
* @property ProductCategoriesTable&BelongsTo $ProductCategories
|
||||
*
|
||||
* @method Product newEmptyEntity()
|
||||
* @method Product newEntity(array $data, array $options = [])
|
||||
* @method array<Product> newEntities(array $data, array $options = [])
|
||||
* @method Product get(mixed $primaryKey, array|string $finder = 'all', CacheInterface|string|null $cache = null, Closure|string|null $cacheKey = null, mixed ...$args)
|
||||
* @method Product findOrCreate($search, ?callable $callback = null, array $options = [])
|
||||
* @method Product patchEntity(EntityInterface $entity, array $data, array $options = [])
|
||||
* @method array<Product> patchEntities(iterable $entities, array $data, array $options = [])
|
||||
* @method Product|false save(EntityInterface $entity, array $options = [])
|
||||
* @method Product saveOrFail(EntityInterface $entity, array $options = [])
|
||||
* @method iterable<Product>|ResultSetInterface<Product>|false saveMany(iterable $entities, array $options = [])
|
||||
* @method iterable<Product>|ResultSetInterface<Product> saveManyOrFail(iterable $entities, array $options = [])
|
||||
* @method iterable<Product>|ResultSetInterface<Product>|false deleteMany(iterable $entities, array $options = [])
|
||||
* @method iterable<Product>|ResultSetInterface<Product> deleteManyOrFail(iterable $entities, array $options = [])
|
||||
*/
|
||||
class ProductsTable extends Table
|
||||
{
|
||||
/**
|
||||
* Initialize method
|
||||
*
|
||||
* @param array<string, mixed> $config The configuration for the Table.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
|
||||
$this->setTable('products');
|
||||
$this->setDisplayField('name');
|
||||
$this->setPrimaryKey('id');
|
||||
|
||||
$this->belongsTo('ProductCategories', [
|
||||
'foreignKey' => 'product_category_id',
|
||||
'bindingKey' => 'internal_id',
|
||||
'joinType' => 'INNER',
|
||||
'className' => 'CakeProducts.ProductCategories',
|
||||
]);
|
||||
|
||||
$this->getSchema()->setColumnType('product_type_id', EnumType::from(ProductProductTypeId::class));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Default validation rules.
|
||||
*
|
||||
* @param Validator $validator Validator instance.
|
||||
* @return Validator
|
||||
*/
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
{
|
||||
$validator
|
||||
->scalar('name')
|
||||
->maxLength('name', 255)
|
||||
->requirePresence('name', 'create')
|
||||
->notEmptyString('name');
|
||||
|
||||
$validator
|
||||
->uuid('product_category_id')
|
||||
->notEmptyString('product_category_id');
|
||||
|
||||
$validator
|
||||
->integer('product_type_id')
|
||||
->requirePresence('product_type_id', 'create')
|
||||
->notEmptyString('product_type_id');
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rules checker object that will be used for validating
|
||||
* application integrity.
|
||||
*
|
||||
* @param RulesChecker $rules The rules object to be modified.
|
||||
* @return RulesChecker
|
||||
*/
|
||||
public function buildRules(RulesChecker $rules): RulesChecker
|
||||
{
|
||||
$rules->add($rules->isUnique(['product_category_id', 'name']), ['errorField' => '0']);
|
||||
$rules->add($rules->existsIn(['product_category_id'], 'ProductCategories'), ['errorField' => '1']);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
29
src/Service/CatalogManagerServiceProvider.php
Normal file
29
src/Service/CatalogManagerServiceProvider.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace CakeProducts\Service;
|
||||
|
||||
use Cake\Core\ContainerInterface;
|
||||
use Cake\Core\Plugin;
|
||||
use Cake\Core\ServiceConfig;
|
||||
use Cake\Core\ServiceProvider;
|
||||
use Cake\Log\Log;
|
||||
use Cake\ORM\Locator\LocatorAwareTrait;
|
||||
use CakeProducts\Service\InternalCatalogManagerService;
|
||||
|
||||
class CatalogManagerServiceProvider extends ServiceProvider
|
||||
{
|
||||
protected array $provides = [
|
||||
InternalCatalogManagerService::class
|
||||
];
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function services(ContainerInterface $container): void
|
||||
{
|
||||
$container->add(InternalCatalogManagerService::class)
|
||||
->addArgument(new ExternalCatalogManagerService());
|
||||
}
|
||||
}
|
||||
184
src/Service/ExternalCatalogManagerService.php
Normal file
184
src/Service/ExternalCatalogManagerService.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace CakeProducts\Service;
|
||||
|
||||
use Cake\Cache\Cache;
|
||||
use Cake\Core\ServiceConfig;
|
||||
use Cake\Http\Client;
|
||||
use Cake\I18n\FrozenTime;
|
||||
use Cake\I18n\Time;
|
||||
use Cake\Log\Log;
|
||||
use Cake\ORM\Locator\LocatorAwareTrait;
|
||||
use CakeProducts\Model\Entity\ExternalProductCatalog;
|
||||
use CakeProducts\Model\Entity\ProductCategory;
|
||||
use CakeProducts\Model\Table\ProductCatalogsTable;
|
||||
|
||||
class ExternalCatalogManagerService
|
||||
{
|
||||
use LocatorAwareTrait;
|
||||
|
||||
/**
|
||||
* @var ProductCatalogsTable
|
||||
*/
|
||||
protected \Cake\ORM\Table|ProductCatalogsTable $ProductCatalogs;
|
||||
|
||||
/**
|
||||
* @var ServiceConfig
|
||||
*/
|
||||
protected ServiceConfig $serviceConfig;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected Client $httpClient;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->ProductCatalogs = $this->fetchTable('CakeProducts.ProductCatalogs');
|
||||
$this->serviceConfig = new ServiceConfig();
|
||||
$this->httpClient = new Client([
|
||||
// 'host' => $config['base_url'],
|
||||
// 'scheme' => 'https',
|
||||
// 'scheme' => 'http',
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function newCategoryCreated(ProductCategory $productCategory)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
$externalProductCatalogs = $this->_getExternalProductCatalogsForCatalogId($productCategory->product_catalog_id);
|
||||
foreach ($externalProductCatalogs as $externalProductCatalog) {
|
||||
$results[] = $this->_createNewCategoryForExternalProductCatalog($externalProductCatalog, $productCategory);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function _createNewCategoryForExternalProductCatalog(ExternalProductCatalog $externalProductCatalog, ProductCategory $productCategory)
|
||||
{
|
||||
$url = $externalProductCatalog->api_url . '/product-categories';
|
||||
$response = $this->postToUrl($url, $productCategory->toArray());
|
||||
|
||||
Log::debug(print_r('$response->getJson()', true));
|
||||
Log::debug(print_r($response->getJson(), true));
|
||||
Log::debug(print_r('$response->getStatusCode()', true));
|
||||
Log::debug(print_r($response->getStatusCode(), true));
|
||||
|
||||
return $response->getStatusCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getJwtToken()
|
||||
{
|
||||
Log::debug('inside getJwtToken');
|
||||
if (Cache::read('product_catalog_api_token')) {
|
||||
Log::debug('token was cached');
|
||||
// return Cache::read('product_catalog_api_token');
|
||||
} else {
|
||||
Log::debug('token was **NOT** cached');
|
||||
}
|
||||
|
||||
$response = $this->httpClient->post('http://localhost:8766/api/v1/users/token', json_encode([
|
||||
'username' => 'test',
|
||||
'password' => 'test',
|
||||
]), ['headers' => ['Accept' => 'application/json', 'Content-Type' => 'application/json']]);
|
||||
// $this->httpClient->getConfig();
|
||||
if ($response->isOk()) {
|
||||
$json = $response->getJson();
|
||||
$token = array_key_exists('token', $json) ? $json['token'] : null;
|
||||
Cache::write('product_catalog_api_token', $token);
|
||||
Log::debug('$token');
|
||||
Log::debug($token);
|
||||
|
||||
return $token;
|
||||
}
|
||||
Log::debug('$response->getStringBody()');
|
||||
Log::debug($response->getStringBody());
|
||||
Log::debug(print_r('$response->getStatusCode()', true));
|
||||
Log::debug(print_r($response->getStatusCode(), true));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function postToUrl(string $url, array $data, int $tries = 0)
|
||||
{
|
||||
// if (true || !Cache::read('product_catalog_api_token')) {
|
||||
$token = $this->getJwtToken();
|
||||
// }
|
||||
Log::debug('$token inside postToUrl' . $token);
|
||||
|
||||
Log::debug('Cache::read(product_catalog_api_token)');
|
||||
Log::debug(Cache::read('product_catalog_api_token') ? Cache::read('product_catalog_api_token') : 'NULL');
|
||||
Log::debug('ATTEMPT # ' . $tries);
|
||||
|
||||
$response = $this->httpClient->post($url, json_encode($data), [
|
||||
'headers' => [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
// 'Authorization' => 'Bearer ' . base64_encode(Cache::read('product_catalog_api_token'))
|
||||
'Authorization' => 'Bearer ' . $token,
|
||||
]
|
||||
]);
|
||||
|
||||
if (!$response->isOk()) {
|
||||
$tries++;
|
||||
}
|
||||
if ($tries > 3) {
|
||||
return $response;
|
||||
}
|
||||
if ($response->getStatusCode() == 401) {
|
||||
$this->postToUrl($url, $data, $tries);
|
||||
}
|
||||
Log::debug('$response->getJson');
|
||||
Log::debug(print_r($response->getJson(), true));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
* @param int $tries
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function putToUrl(string $url, array $data, int $tries = 0)
|
||||
{
|
||||
if (!Cache::read('product_catalog_api_token')) {
|
||||
$this->getJwtToken();
|
||||
}
|
||||
|
||||
$response = $this->httpClient->put($url, json_encode($data), [
|
||||
'headers' => [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . Cache::read('product_catalog_api_token')
|
||||
],
|
||||
]);
|
||||
|
||||
if (!$response->isOk()) {
|
||||
$tries++;
|
||||
}
|
||||
if ($tries > 3) {
|
||||
return $response;
|
||||
}
|
||||
if ($response->getStatusCode() == 401) {
|
||||
$this->getJwtToken();
|
||||
$this->putToUrl($url, $data, $tries);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function _getExternalProductCatalogsForCatalogId(string $productCatalogId)
|
||||
{
|
||||
return $this->ProductCatalogs->ExternalProductCatalogs->find()->where(['product_catalog_id' => $productCatalogId])->toArray();
|
||||
}
|
||||
}
|
||||
106
src/Service/InternalCatalogManagerService.php
Normal file
106
src/Service/InternalCatalogManagerService.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace CakeProducts\Service;
|
||||
|
||||
use Cake\Core\ServiceConfig;
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\I18n\FrozenTime;
|
||||
use Cake\I18n\Time;
|
||||
use Cake\Log\Log;
|
||||
use Cake\ORM\Locator\LocatorAwareTrait;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Utility\Text;
|
||||
use CakeProducts\Model\Entity\ProductCategory;
|
||||
use CakeProducts\Model\Table\ProductCatalogsTable;
|
||||
|
||||
class InternalCatalogManagerService
|
||||
{
|
||||
use LocatorAwareTrait;
|
||||
|
||||
/**
|
||||
* @var ProductCatalogsTable
|
||||
*/
|
||||
protected Table|ProductCatalogsTable $ProductCatalogs;
|
||||
|
||||
/**
|
||||
* @var ServiceConfig
|
||||
*/
|
||||
protected ServiceConfig $serviceConfig;
|
||||
|
||||
/**
|
||||
* @var ExternalCatalogManagerService|null
|
||||
*/
|
||||
protected ?ExternalCatalogManagerService $externalCatalogManager;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct(ExternalCatalogManagerService $externalCatalogManagerService)
|
||||
{
|
||||
$this->ProductCatalogs = $this->fetchTable('CakeProducts.ProductCatalogs');
|
||||
$this->serviceConfig = new ServiceConfig();
|
||||
|
||||
if ($this->serviceConfig->get('CakeProducts.internal.enabled') && $this->serviceConfig->get('CakeProducts.internal.syncExternally')) {
|
||||
$this->externalCatalogManager = $externalCatalogManagerService;
|
||||
}
|
||||
|
||||
}
|
||||
public function getCatalog(string $id = null)
|
||||
{
|
||||
$contain = ['ProductCategories'];
|
||||
if ($this->serviceConfig->get('CakeProducts.internal.syncExternally')) {
|
||||
$contain[] = 'ExternalProductCatalogs';
|
||||
}
|
||||
|
||||
return $this->ProductCatalogs->get($id, contain: $contain);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $id
|
||||
*
|
||||
* @return \App\Model\Entity\ProductCategory|EntityInterface
|
||||
*/
|
||||
public function getCategory(string $id = null)
|
||||
{
|
||||
$contain = ['ProductCatalogs', 'ParentProductCategories', 'ChildProductCategories'];
|
||||
|
||||
return $this->ProductCatalogs->ProductCategories->get($id, contain: $contain);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProductCategory $productCategory product category entity
|
||||
* @param array $data data to save
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function createNewCategory(ProductCategory $productCategory, array $data = []): array
|
||||
{
|
||||
$now = Time::now();
|
||||
$associated = [];
|
||||
|
||||
Log::info('posted data - adding new ProductCategory');
|
||||
Log::info(print_r($data, true));
|
||||
|
||||
$saveOptions = [
|
||||
'associated' => $associated,
|
||||
];
|
||||
if (!array_key_exists('internal_id', $data) || !$data['internal_id']) {
|
||||
$data['internal_id'] = Text::uuid();
|
||||
}
|
||||
$productCategory = $this->ProductCatalogs->ProductCategories->patchEntity($productCategory, $data, $saveOptions);
|
||||
if ($productCategory->getErrors()) {
|
||||
Log::debug(print_r('$productCategory->getErrors() next - failed to save from create new product category', true));
|
||||
Log::debug(print_r($productCategory->getErrors(), true));
|
||||
}
|
||||
$returnData = [
|
||||
'entity' => $productCategory,
|
||||
'result' => $this->ProductCatalogs->ProductCategories->save($productCategory, $saveOptions),
|
||||
'apiResults' => [],
|
||||
];
|
||||
if ($returnData['result'] && $this->externalCatalogManager) {
|
||||
$returnData['apiResults'] = $this->externalCatalogManager->newCategoryCreated($returnData['result']);
|
||||
}
|
||||
|
||||
return $returnData;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user