Squashed commit

Always execute migration 9999 (can be used to fix things manually)
Optimized meal plan navigation / date range filtering
Prepared next release
Pulled translations from Transifex
Various code optimizations
This commit is contained in:
Bernd Bestel
2021-07-16 17:32:08 +02:00
parent 2d1d5d46f6
commit edfa404ed6
58 changed files with 312 additions and 513 deletions

View File

@@ -6,18 +6,13 @@ use LessQL\Result;
class BaseApiController extends BaseController
{
protected $OpenApiSpec = null;
const PATTERN_FIELD = '[A-Za-z_][A-Za-z0-9_]+';
const PATTERN_OPERATOR = '!?(=|~|<|>|(>=)|(<=)|(§))';
const PATTERN_VALUE = '[A-Za-z\x{0400}-\x{04FF}_0-9.$#^|-]+';
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
protected $OpenApiSpec = null;
protected function ApiResponse(\Psr\Http\Message\ResponseInterface $response, $data, $cache = false)
{

View File

@@ -21,14 +21,14 @@ use Grocy\Services\UsersService;
class BaseController
{
protected $AppContainer;
public function __construct(\DI\Container $container)
{
$this->AppContainer = $container;
$this->View = $container->get('view');
}
protected $AppContainer;
protected function getApiKeyService()
{
return ApiKeyService::getInstance();

View File

@@ -34,7 +34,6 @@ class BatteriesApiController extends BaseApiController
try
{
$trackedTime = date('Y-m-d H:i:s');
if (array_key_exists('tracked_time', $requestBody) && IsIsoDateTime($requestBody['tracked_time']))
{
$trackedTime = $requestBody['tracked_time'];
@@ -87,9 +86,4 @@ class BatteriesApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -3,11 +3,11 @@
namespace Grocy\Controllers;
use Grocy\Helpers\Grocycode;
use jucksearm\barcode\lib\BarcodeFactory;
use jucksearm\barcode\lib\DatamatrixFactory;
class BatteriesController extends BaseController
{
use GrocycodeTrait;
public function BatteriesList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
if (isset($request->getQueryParams()['include_disabled']))
@@ -98,40 +98,7 @@ class BatteriesController extends BaseController
public function BatteryGrocycodeImage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
$size = $request->getQueryParam('size', null);
$gc = new Grocycode(Grocycode::BATTERY, $args['batteryId']);
if (GROCY_GROCYCODE_TYPE == '2D')
{
$png = (new DatamatrixFactory())->setCode((string) $gc)->setSize($size)->getDatamatrixPngData();
}
else
{
$png = (new BarcodeFactory())->setType('C128')->setCode((string) $gc)->setHeight($size)->getBarcodePngData();
}
$isDownload = $request->getQueryParam('download', false);
if ($isDownload)
{
$response = $response->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment; filename=grocycode.png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
else
{
$response = $response->withHeader('Content-Type', 'image/png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
$response->getBody()->write($png);
return $response;
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
return $this->ServeGrocycodeImage($request, $response, $gc);
}
}

View File

@@ -72,9 +72,4 @@ class CalendarApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -10,9 +10,4 @@ class CalendarController extends BaseController
'fullcalendarEventSources' => $this->getCalendarService()->GetEvents()
]);
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -68,14 +68,12 @@ class ChoresApiController extends BaseApiController
User::checkPermission($request, User::PERMISSION_CHORE_TRACK_EXECUTION);
$trackedTime = date('Y-m-d H:i:s');
if (array_key_exists('tracked_time', $requestBody) && (IsIsoDateTime($requestBody['tracked_time']) || IsIsoDate($requestBody['tracked_time'])))
{
$trackedTime = $requestBody['tracked_time'];
}
$doneBy = GROCY_USER_ID;
if (array_key_exists('done_by', $requestBody) && !empty($requestBody['done_by']))
{
$doneBy = $requestBody['done_by'];
@@ -133,9 +131,4 @@ class ChoresApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -3,11 +3,11 @@
namespace Grocy\Controllers;
use Grocy\Helpers\Grocycode;
use jucksearm\barcode\lib\BarcodeFactory;
use jucksearm\barcode\lib\DatamatrixFactory;
class ChoresController extends BaseController
{
use GrocycodeTrait;
public function ChoreEditForm(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
$usersService = $this->getUsersService();
@@ -115,40 +115,7 @@ class ChoresController extends BaseController
public function ChoreGrocycodeImage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
$size = $request->getQueryParam('size', null);
$gc = new Grocycode(Grocycode::CHORE, $args['choreId']);
if (GROCY_GROCYCODE_TYPE == '2D')
{
$png = (new DatamatrixFactory())->setCode((string) $gc)->setSize($size)->getDatamatrixPngData();
}
else
{
$png = (new BarcodeFactory())->setType('C128')->setCode((string) $gc)->setHeight($size)->getBarcodePngData();
}
$isDownload = $request->getQueryParam('download', false);
if ($isDownload)
{
$response = $response->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment; filename=grocycode.png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
else
{
$response = $response->withHeader('Content-Type', 'image/png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
$response->getBody()->write($png);
return $response;
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
return $this->ServeGrocycodeImage($request, $response, $gc);
}
}

View File

@@ -33,9 +33,4 @@ class EquipmentController extends BaseController
'userfieldValues' => $this->getUserfieldsService()->GetAllValues('equipment')
]);
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -11,17 +11,17 @@ use Throwable;
class ExceptionController extends BaseApiController
{
/**
* @var \Slim\App
*/
private $app;
public function __construct(\Slim\App $app, \DI\Container $container)
{
parent::__construct($container);
$this->app = $app;
}
/**
* @var \Slim\App
*/
private $app;
public function __invoke(ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails, bool $logErrors, bool $logErrorDetails, ?LoggerInterface $logger = null)
{
$response = $this->app->getResponseFactory()->createResponse();
@@ -59,7 +59,10 @@ class ExceptionController extends BaseApiController
if ($exception instanceof HttpNotFoundException)
{
define('GROCY_AUTHENTICATED', false);
if (!defined('GROCY_AUTHENTICATED'))
{
define('GROCY_AUTHENTICATED', false);
}
return $this->renderPage($response->withStatus(404), 'errors/404', [
'exception' => $exception

View File

@@ -118,11 +118,6 @@ class FilesApiController extends BaseApiController
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
/**
* @param string $fileName base64-encoded file-name
* @return false|string the decoded file-name
@@ -151,7 +146,6 @@ class FilesApiController extends BaseApiController
protected function getFilePath(string $group, string $fileName, array $queryParams = [])
{
$forceServeAs = null;
if (isset($queryParams['force_serve_as']) && !empty($queryParams['force_serve_as']))
{
$forceServeAs = $queryParams['force_serve_as'];
@@ -160,14 +154,12 @@ class FilesApiController extends BaseApiController
if ($forceServeAs == FilesService::FILE_SERVE_TYPE_PICTURE)
{
$bestFitHeight = null;
if (isset($queryParams['best_fit_height']) && !empty($queryParams['best_fit_height']) && is_numeric($queryParams['best_fit_height']))
{
$bestFitHeight = $queryParams['best_fit_height'];
}
$bestFitWidth = null;
if (isset($queryParams['best_fit_width']) && !empty($queryParams['best_fit_width']) && is_numeric($queryParams['best_fit_width']))
{
$bestFitWidth = $queryParams['best_fit_width'];

View File

@@ -213,11 +213,6 @@ class GenericEntityApiController extends BaseApiController
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
private function IsEntityWithEditRequiresAdmin($entity)
{
return in_array($entity, $this->getOpenApiSpec()->components->schemas->ExposedEntityEditRequiresAdmin->enum);

View File

@@ -91,9 +91,4 @@ class GenericEntityController extends BaseController
'userfieldValues' => $this->getUserfieldsService()->GetAllValues('userentity-' . $args['userentityName'])
]);
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Grocy\Controllers;
use Grocy\Helpers\Grocycode;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use jucksearm\barcode\lib\BarcodeFactory;
use jucksearm\barcode\lib\DatamatrixFactory;
trait GrocycodeTrait
{
public function ServeGrocycodeImage(ServerRequestInterface $request, ResponseInterface $response, Grocycode $grocycode)
{
$size = $request->getQueryParam('size', null);
if (GROCY_GROCYCODE_TYPE == '2D')
{
$png = (new DatamatrixFactory())->setCode((string) $grocycode)->setSize($size)->getDatamatrixPngData();
}
else
{
$png = (new BarcodeFactory())->setType('C128')->setCode((string) $grocycode)->setHeight($size)->getBarcodePngData();
}
$isDownload = $request->getQueryParam('download', false);
if ($isDownload)
{
$response = $response->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment; filename=grocycode.png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
else
{
$response = $response->withHeader('Content-Type', 'image/png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
$response->getBody()->write($png);
return $response;
}
}

View File

@@ -6,11 +6,6 @@ use Grocy\Services\SessionService;
class LoginController extends BaseController
{
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
public function LoginPage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
return $this->renderPage($response, 'login');

View File

@@ -85,9 +85,4 @@ class OpenApiController extends BaseApiController
{
return $this->render($response, 'openapiui');
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -34,9 +34,4 @@ class PrintApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -76,9 +76,4 @@ class RecipesApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -8,19 +8,21 @@ class RecipesController extends BaseController
{
public function MealPlan(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
// Given date is always the first day of the week => load the coming week / 7 days
if (isset($request->getQueryParams()['week']) && IsIsoDate($request->getQueryParams()['week']))
$start = date('Y-m-d');
if (isset($request->getQueryParams()['start']) && IsIsoDate($request->getQueryParams()['start']))
{
$week = $request->getQueryParams()['week'];
$mealPlanWhereTimespan = "day BETWEEN DATE('$week') AND DATE('$week', '+7 days')";
$start = $request->getQueryParams()['start'];
}
else
$days = 6;
if (isset($request->getQueryParams()['days']) && filter_var($request->getQueryParams()['days'], FILTER_VALIDATE_INT) !== false)
{
$mealPlanWhereTimespan = "day BETWEEN DATE('now', 'localtime', 'weekday 0', '-7 days') AND DATE(DATE('now', 'localtime', 'weekday 0', '-7 days'), '+7 days')";
$days = $request->getQueryParams()['days'];
}
$mealPlanWhereTimespan = "day BETWEEN DATE('$start') AND DATE('$start', '+$days days')";
$recipes = $this->getDatabase()->recipes()->where('type', RecipesService::RECIPE_TYPE_NORMAL)->fetchAll();
$events = [];
foreach ($this->getDatabase()->meal_plan()->where($mealPlanWhereTimespan) as $mealPlanEntry)
{
@@ -214,9 +216,4 @@ class RecipesController extends BaseController
'mealplanSections' => $this->getDatabase()->meal_plan_sections()->where('id > 0')->orderBy('sort_number')
]);
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -862,9 +862,4 @@ class StockApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -4,11 +4,11 @@ namespace Grocy\Controllers;
use Grocy\Helpers\Grocycode;
use Grocy\Services\RecipesService;
use jucksearm\barcode\lib\BarcodeFactory;
use jucksearm\barcode\lib\DatamatrixFactory;
class StockController extends BaseController
{
use GrocycodeTrait;
public function Consume(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
return $this->renderPage($response, 'consume', [
@@ -192,36 +192,8 @@ class StockController extends BaseController
public function ProductGrocycodeImage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
$size = $request->getQueryParam('size', null);
$gc = new Grocycode(Grocycode::PRODUCT, $args['productId']);
if (GROCY_GROCYCODE_TYPE == '2D')
{
$png = (new DatamatrixFactory())->setCode((string) $gc)->setSize($size)->getDatamatrixPngData();
}
else
{
$png = (new BarcodeFactory())->setType('C128')->setCode((string) $gc)->setHeight($size)->getBarcodePngData();
}
$isDownload = $request->getQueryParam('download', false);
if ($isDownload)
{
$response = $response->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment; filename=grocycode.png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
else
{
$response = $response->withHeader('Content-Type', 'image/png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
$response->getBody()->write($png);
return $response;
return $this->ServeGrocycodeImage($request, $response, $gc);
}
public function ProductGroupEditForm(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
@@ -488,38 +460,9 @@ class StockController extends BaseController
public function StockEntryGrocycodeImage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
$size = $request->getQueryParam('size', null);
$stockEntry = $this->getDatabase()->stock()->where('id', $args['entryId'])->fetch();
$gc = new Grocycode(Grocycode::PRODUCT, $stockEntry->product_id, [$stockEntry->stock_id]);
if (GROCY_GROCYCODE_TYPE == '2D')
{
$png = (new DatamatrixFactory())->setCode((string) $gc)->setSize($size)->getDatamatrixPngData();
}
else
{
$png = (new BarcodeFactory())->setType('C128')->setCode((string) $gc)->setHeight($size)->getBarcodePngData();
}
$isDownload = $request->getQueryParam('download', false);
if ($isDownload)
{
$response = $response->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment; filename=grocycode.png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
else
{
$response = $response->withHeader('Content-Type', 'image/png')
->withHeader('Content-Length', strlen($png))
->withHeader('Cache-Control', 'no-cache')
->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
}
$response->getBody()->write($png);
return $response;
return $this->ServeGrocycodeImage($request, $response, $gc);
}
public function StockEntryGrocycodeLabel(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
@@ -569,11 +512,6 @@ class StockController extends BaseController
]);
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
public function JournalSummary(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
$entries = $this->getDatabase()->uihelper_stock_journal_summary();

View File

@@ -89,9 +89,4 @@ class SystemApiController extends BaseApiController
{
return $this->ApiResponse($response, json_decode($this->getLocalizationService()->GetPoAsJsonString()), true);
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -35,11 +35,6 @@ class SystemController extends BaseController
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl($this->GetEntryPageRelative()));
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
/**
* Get the entry page of the application based on the value of the entry page setting.
*

View File

@@ -49,9 +49,4 @@ class TasksApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -83,9 +83,4 @@ class TasksController extends BaseController
{
return $this->renderPage($response, 'taskssettings');
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}

View File

@@ -67,6 +67,11 @@ class User
const PERMISSION_USERS_READ = 'USERS_READ';
public function __construct()
{
$this->db = DatabaseService::getInstance()->GetDbConnection();
}
/**
* @var \LessQL\Database|null
*/
@@ -78,11 +83,6 @@ class User
return $user->getPermissionList();
}
public function __construct()
{
$this->db = DatabaseService::getInstance()->GetDbConnection();
}
public static function checkPermission($request, string ...$permissions): void
{
$user = new self();

View File

@@ -231,9 +231,4 @@ class UsersApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function __construct(\DI\Container $container)
{
parent::__construct($container);
}
}