mirror of
https://github.com/grocy/grocy.git
synced 2025-08-20 04:12:59 +00:00
Reorganize project part 2
This commit is contained in:
11
controllers/BaseApiController.php
Normal file
11
controllers/BaseApiController.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
class BaseApiController extends BaseController
|
||||
{
|
||||
protected function ApiEncode($response)
|
||||
{
|
||||
return json_encode($response);
|
||||
}
|
||||
}
|
18
controllers/BaseController.php
Normal file
18
controllers/BaseController.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\DatabaseService;
|
||||
|
||||
class BaseController
|
||||
{
|
||||
public function __construct(\Slim\Container $container) {
|
||||
$this->AppContainer = $container;
|
||||
|
||||
$databaseService = new DatabaseService();
|
||||
$this->Database = $databaseService->GetDbConnection();
|
||||
}
|
||||
|
||||
protected $AppContainer;
|
||||
protected $Database;
|
||||
}
|
32
controllers/BatteriesApiController.php
Normal file
32
controllers/BatteriesApiController.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\BatteriesService;
|
||||
|
||||
class BatteriesApiController extends BaseApiController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->BatteriesService = new BatteriesService();
|
||||
}
|
||||
|
||||
protected $BatteriesService;
|
||||
|
||||
public function TrackChargeCycle($request, $response, $args)
|
||||
{
|
||||
$trackedTime = date('Y-m-d H:i:s');
|
||||
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']))
|
||||
{
|
||||
$trackedTime = $request->getQueryParams()['tracked_time'];
|
||||
}
|
||||
|
||||
return $this->ApiEncode(array('success' => $this->BatteriesService->TrackChargeCycle($args['batteryId'], $trackedTime)));
|
||||
}
|
||||
|
||||
public function BatteryDetails($request, $response, $args)
|
||||
{
|
||||
return $this->ApiEncode($this->BatteriesService->GetBatteryDetails($args['batteryId']));
|
||||
}
|
||||
}
|
65
controllers/BatteriesController.php
Normal file
65
controllers/BatteriesController.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\BatteriesService;
|
||||
|
||||
class BatteriesController extends BaseController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->BatteriesService = new BatteriesService();
|
||||
}
|
||||
|
||||
protected $BatteriesService;
|
||||
|
||||
public function Overview($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteriesoverview', [
|
||||
'title' => 'Batteries overview',
|
||||
'contentPage' => 'batteriesoverview.php',
|
||||
'batteries' => $this->Database->batteries(),
|
||||
'current' => $this->BatteriesService->GetCurrent(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function TrackChargeCycle($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batterytracking', [
|
||||
'title' => 'Battery tracking',
|
||||
'contentPage' => 'batterytracking.php',
|
||||
'batteries' => $this->Database->batteries()
|
||||
]);
|
||||
}
|
||||
|
||||
public function BatteriesList($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteries', [
|
||||
'title' => 'Batteries',
|
||||
'contentPage' => 'batteries.php',
|
||||
'batteries' => $this->Database->batteries()
|
||||
]);
|
||||
}
|
||||
|
||||
public function BatteryEditForm($request, $response, $args)
|
||||
{
|
||||
if ($args['batteryId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteryform', [
|
||||
'title' => 'Create battery',
|
||||
'contentPage' => 'batteryform.php',
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteryform', [
|
||||
'title' => 'Edit battery',
|
||||
'contentPage' => 'batteryform.php',
|
||||
'battery' => $this->Database->batteries($args['batteryId']),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
19
controllers/CliController.php
Normal file
19
controllers/CliController.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\ApplicationService;
|
||||
use Grocy\Services\DatabaseMigrationService;
|
||||
|
||||
class CliController extends BaseController
|
||||
{
|
||||
public function RecreateDemo($request, $response, $args)
|
||||
{
|
||||
$applicationService = new ApplicationService();
|
||||
if ($applicationService->IsDemoInstallation())
|
||||
{
|
||||
$databaseMigrationService = new DatabaseMigrationService();
|
||||
$databaseMigrationService->RecreateDemo();
|
||||
}
|
||||
}
|
||||
}
|
40
controllers/GenericEntityApiController.php
Normal file
40
controllers/GenericEntityApiController.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
class GenericEntityApiController extends BaseApiController
|
||||
{
|
||||
public function GetObjects($request, $response, $args)
|
||||
{
|
||||
return $this->ApiEncode($this->Database->{$args['entity']}());
|
||||
}
|
||||
|
||||
public function GetObject($request, $response, $args)
|
||||
{
|
||||
return $this->ApiEncode($this->Database->{$args['entity']}($args['objectId']));
|
||||
}
|
||||
|
||||
public function AddObject($request, $response, $args)
|
||||
{
|
||||
$newRow = $this->Database->{$args['entity']}()->createRow($request->getParsedBody());
|
||||
$newRow->save();
|
||||
$success = $newRow->isClean();
|
||||
return $this->ApiEncode(array('success' => $success));
|
||||
}
|
||||
|
||||
public function EditObject($request, $response, $args)
|
||||
{
|
||||
$row = $this->Database->{$args['entity']}($args['objectId']);
|
||||
$row->update($request->getParsedBody());
|
||||
$success = $row->isClean();
|
||||
return $this->ApiEncode(array('success' => $success));
|
||||
}
|
||||
|
||||
public function DeleteObject($request, $response, $args)
|
||||
{
|
||||
$row = $this->Database->{$args['entity']}($args['objectId']);
|
||||
$row->delete();
|
||||
$success = $row->isClean();
|
||||
return $this->ApiEncode(array('success' => $success));
|
||||
}
|
||||
}
|
32
controllers/HabitsApiController.php
Normal file
32
controllers/HabitsApiController.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\HabitsService;
|
||||
|
||||
class HabitsApiController extends BaseApiController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->HabitsService = new HabitsService();
|
||||
}
|
||||
|
||||
protected $HabitsService;
|
||||
|
||||
public function TrackHabitExecution($request, $response, $args)
|
||||
{
|
||||
$trackedTime = date('Y-m-d H:i:s');
|
||||
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']))
|
||||
{
|
||||
$trackedTime = $request->getQueryParams()['tracked_time'];
|
||||
}
|
||||
|
||||
return $this->ApiEncode(array('success' => $this->HabitsService->TrackHabit($args['habitId'], $trackedTime)));
|
||||
}
|
||||
|
||||
public function HabitDetails($request, $response, $args)
|
||||
{
|
||||
return $this->ApiEncode($this->HabitsService->GetHabitDetails($args['habitId']));
|
||||
}
|
||||
}
|
67
controllers/HabitsController.php
Normal file
67
controllers/HabitsController.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\HabitsService;
|
||||
|
||||
class HabitsController extends BaseController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->HabitsService = new HabitsService();
|
||||
}
|
||||
|
||||
protected $HabitsService;
|
||||
|
||||
public function Overview($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'habitsoverview', [
|
||||
'title' => 'Habits overview',
|
||||
'contentPage' => 'habitsoverview.php',
|
||||
'habits' => $this->Database->habits(),
|
||||
'currentHabits' => $this->HabitsService->GetCurrentHabits(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function TrackHabitExecution($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'habittracking', [
|
||||
'title' => 'Habit tracking',
|
||||
'contentPage' => 'habittracking.php',
|
||||
'habits' => $this->Database->habits()
|
||||
]);
|
||||
}
|
||||
|
||||
public function HabitsList($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'habits', [
|
||||
'title' => 'Habits',
|
||||
'contentPage' => 'habits.php',
|
||||
'habits' => $this->Database->habits()
|
||||
]);
|
||||
}
|
||||
|
||||
public function HabitEditForm($request, $response, $args)
|
||||
{
|
||||
if ($args['habitId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'habitform', [
|
||||
'title' => 'Create habit',
|
||||
'contentPage' => 'habitform.php',
|
||||
'periodTypes' => GetClassConstants('Grocy\Services\HabitsService'),
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'habitform', [
|
||||
'title' => 'Edit habit',
|
||||
'contentPage' => 'habitform.php',
|
||||
'habit' => $this->Database->habits($args['habitId']),
|
||||
'periodTypes' => GetClassConstants('Grocy\Services\HabitsService'),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
73
controllers/LoginController.php
Normal file
73
controllers/LoginController.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\SessionService;
|
||||
use Grocy\Services\DatabaseService;
|
||||
use Grocy\Services\ApplicationService;
|
||||
use Grocy\Services\DatabaseMigrationService;
|
||||
use Grocy\Services\DemoDataGeneratorService;
|
||||
|
||||
class LoginController extends BaseController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->SessionService = new SessionService();
|
||||
}
|
||||
|
||||
protected $SessionService;
|
||||
|
||||
public function ProcessLogin($request, $response, $args)
|
||||
{
|
||||
$postParams = $request->getParsedBody();
|
||||
if (isset($postParams['username']) && isset($postParams['password']))
|
||||
{
|
||||
if ($postParams['username'] === HTTP_USER && $postParams['password'] === HTTP_PASSWORD)
|
||||
{
|
||||
$sessionKey = $this->SessionService->CreateSession();
|
||||
setcookie('grocy_session', $sessionKey, time()+2592000); //30 days
|
||||
|
||||
return $response->withRedirect('/');
|
||||
}
|
||||
else
|
||||
{
|
||||
return $response->withRedirect('/login?invalid=true');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return $response->withRedirect('/login?invalid=true');
|
||||
}
|
||||
}
|
||||
|
||||
public function LoginPage($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'login', [
|
||||
'title' => 'Login',
|
||||
'contentPage' => 'login.php'
|
||||
]);
|
||||
}
|
||||
|
||||
public function Logout($request, $response, $args)
|
||||
{
|
||||
$this->SessionService->RemoveSession($_COOKIE['grocy_session']);
|
||||
return $response->withRedirect('/');
|
||||
}
|
||||
|
||||
public function Root($request, $response, $args)
|
||||
{
|
||||
// Schema migration is done here
|
||||
$databaseMigrationService = new DatabaseMigrationService();
|
||||
$databaseMigrationService->MigrateDatabase();
|
||||
|
||||
$applicationService = new ApplicationService();
|
||||
if ($applicationService->IsDemoInstallation())
|
||||
{
|
||||
$demoDataGeneratorService = new DemoDataGeneratorService();
|
||||
$demoDataGeneratorService->PopulateDemoData();
|
||||
}
|
||||
|
||||
return $response->withRedirect('/stockoverview');
|
||||
}
|
||||
}
|
77
controllers/StockApiController.php
Normal file
77
controllers/StockApiController.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\StockService;
|
||||
|
||||
class StockApiController extends BaseApiController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->StockService = new StockService();
|
||||
}
|
||||
|
||||
protected $StockService;
|
||||
|
||||
public function ProductDetails($request, $response, $args)
|
||||
{
|
||||
return $this->ApiEncode($this->StockService->GetProductDetails($args['productId']));
|
||||
}
|
||||
|
||||
public function AddProduct($request, $response, $args)
|
||||
{
|
||||
$bestBeforeDate = date('Y-m-d');
|
||||
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']))
|
||||
{
|
||||
$bestBeforeDate = $request->getQueryParams()['bestbeforedate'];
|
||||
}
|
||||
|
||||
$transactionType = StockService::TRANSACTION_TYPE_PURCHASE;
|
||||
if (isset($request->getQueryParams()['transactiontype']) && !empty($request->getQueryParams()['transactiontype']))
|
||||
{
|
||||
$transactionType = $request->getQueryParams()['transactiontype'];
|
||||
}
|
||||
|
||||
return $this->ApiEncode(array('success' => $this->StockService->AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType)));
|
||||
}
|
||||
|
||||
public function ConsumeProduct($request, $response, $args)
|
||||
{
|
||||
$spoiled = false;
|
||||
if (isset($request->getQueryParams()['spoiled']) && !empty($request->getQueryParams()['spoiled']) && $request->getQueryParams()['spoiled'] == '1')
|
||||
{
|
||||
$spoiled = true;
|
||||
}
|
||||
|
||||
$transactionType = StockService::TRANSACTION_TYPE_CONSUME;
|
||||
if (isset($request->getQueryParams()['transactiontype']) && !empty($request->getQueryParams()['transactiontype']))
|
||||
{
|
||||
$transactionType = $request->getQueryParams()['transactiontype'];
|
||||
}
|
||||
|
||||
return $this->ApiEncode(array('success' => $this->StockService->ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType)));
|
||||
}
|
||||
|
||||
public function InventoryProduct($request, $response, $args)
|
||||
{
|
||||
$bestBeforeDate = date('Y-m-d');
|
||||
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']))
|
||||
{
|
||||
$bestBeforeDate = $request->getQueryParams()['bestbeforedate'];
|
||||
}
|
||||
|
||||
return $this->ApiEncode(array('success' => $this->StockService->InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate)));
|
||||
}
|
||||
|
||||
public function CurrentStock($request, $response, $args)
|
||||
{
|
||||
return $this->ApiEncode($this->StockService->GetCurrentStock());
|
||||
}
|
||||
|
||||
public function AddmissingProductsToShoppingList($request, $response, $args)
|
||||
{
|
||||
$this->StockService->AddMissingProductsToShoppingList();
|
||||
return $this->ApiEncode(array('success' => true));
|
||||
}
|
||||
}
|
187
controllers/StockController.php
Normal file
187
controllers/StockController.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Services\StockService;
|
||||
|
||||
class StockController extends BaseController
|
||||
{
|
||||
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->StockService = new StockService();
|
||||
}
|
||||
|
||||
protected $StockService;
|
||||
|
||||
public function Overview($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'stockoverview', [
|
||||
'title' => 'Stock overview',
|
||||
'contentPage' => 'stockoverview.php',
|
||||
'products' => $this->Database->products(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'currentStock' => $this->StockService->GetCurrentStock(),
|
||||
'missingProducts' => $this->StockService->GetMissingProducts()
|
||||
]);
|
||||
}
|
||||
|
||||
public function Purchase($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'purchase', [
|
||||
'title' => 'Purchase',
|
||||
'contentPage' => 'purchase.php',
|
||||
'products' => $this->Database->products()
|
||||
]);
|
||||
}
|
||||
|
||||
public function Consume($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'consume', [
|
||||
'title' => 'Consume',
|
||||
'contentPage' => 'consume.php',
|
||||
'products' => $this->Database->products()
|
||||
]);
|
||||
}
|
||||
|
||||
public function Inventory($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'inventory', [
|
||||
'title' => 'Inventory',
|
||||
'contentPage' => 'inventory.php',
|
||||
'products' => $this->Database->products()
|
||||
]);
|
||||
}
|
||||
|
||||
public function ShoppingList($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'shoppinglist', [
|
||||
'title' => 'Shopping list',
|
||||
'contentPage' => 'shoppinglist.php',
|
||||
'listItems' => $this->Database->shopping_list(),
|
||||
'products' => $this->Database->products(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'missingProducts' => $this->StockService->GetMissingProducts()
|
||||
]);
|
||||
}
|
||||
|
||||
public function ProductsList($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'products', [
|
||||
'title' => 'Products',
|
||||
'contentPage' => 'products.php',
|
||||
'products' => $this->Database->products(),
|
||||
'locations' => $this->Database->locations(),
|
||||
'quantityunits' => $this->Database->quantity_units()
|
||||
]);
|
||||
}
|
||||
|
||||
public function LocationsList($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locations', [
|
||||
'title' => 'Locations',
|
||||
'contentPage' => 'locations.php',
|
||||
'locations' => $this->Database->locations()
|
||||
]);
|
||||
}
|
||||
|
||||
public function QuantityUnitsList($request, $response, $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'quantityunits', [
|
||||
'title' => 'Quantity units',
|
||||
'contentPage' => 'quantityunits.php',
|
||||
'quantityunits' => $this->Database->quantity_units()
|
||||
]);
|
||||
}
|
||||
|
||||
public function ProductEditForm($request, $response, $args)
|
||||
{
|
||||
if ($args['productId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'productform', [
|
||||
'title' => 'Create product',
|
||||
'contentPage' => 'productform.php',
|
||||
'locations' => $this->Database->locations(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'productform', [
|
||||
'title' => 'Edit product',
|
||||
'contentPage' => 'productform.php',
|
||||
'product' => $this->Database->products($args['productId']),
|
||||
'locations' => $this->Database->locations(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function LocationEditForm($request, $response, $args)
|
||||
{
|
||||
if ($args['locationId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locationform', [
|
||||
'title' => 'Create location',
|
||||
'contentPage' => 'locationform.php',
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locationform', [
|
||||
'title' => 'Edit location',
|
||||
'contentPage' => 'locationform.php',
|
||||
'location' => $this->Database->locations($args['locationId']),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function QuantityUnitEditForm($request, $response, $args)
|
||||
{
|
||||
if ($args['quantityunitId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'quantityunitform', [
|
||||
'title' => 'Create quantity unit',
|
||||
'contentPage' => 'quantityunitform.php',
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'quantityunitform', [
|
||||
'title' => 'Edit quantity unit',
|
||||
'contentPage' => 'quantityunitform.php',
|
||||
'quantityunit' => $this->Database->quantity_units($args['quantityunitId']),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function ShoppingListItemEditForm($request, $response, $args)
|
||||
{
|
||||
if ($args['itemId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'shoppinglistform', [
|
||||
'title' => 'Add shopping list item',
|
||||
'contentPage' => 'shoppinglistform.php',
|
||||
'products' => $this->Database->products(),
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'shoppinglistform', [
|
||||
'title' => 'Edit shopping list item',
|
||||
'contentPage' => 'shoppinglistform.php',
|
||||
'listItem' => $this->Database->shopping_list($args['itemId']),
|
||||
'products' => $this->Database->products(),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user