From 79b4bad014bd3c5084ed106d95417633fec788d5 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Wed, 11 Apr 2018 19:49:35 +0200 Subject: [PATCH] Reorganize project part 2 --- GrocyPhpHelper.php | 66 -- composer.json | 11 +- composer.lock | 807 +++++++++++++++++- controllers/BaseApiController.php | 11 + controllers/BaseController.php | 18 + controllers/BatteriesApiController.php | 32 + controllers/BatteriesController.php | 65 ++ controllers/CliController.php | 19 + controllers/GenericEntityApiController.php | 40 + controllers/HabitsApiController.php | 32 + controllers/HabitsController.php | 67 ++ controllers/LoginController.php | 73 ++ controllers/StockApiController.php | 77 ++ controllers/StockController.php | 187 ++++ extensions.php | 63 ++ index.php | 583 ++----------- middleware/CliMiddleware.php | 25 + middleware/JsonMiddleware.php | 18 + middleware/SessionMiddleware.php | 32 + services/ApplicationService.php | 16 +- services/BaseService.php | 16 + services/BatteriesService.php | 32 +- .../DatabaseMigrationService.php | 54 +- services/DatabaseService.php | 64 +- .../DemoDataGeneratorService.php | 75 +- services/HabitsService.php | 32 +- services/SessionService.php | 12 +- services/StockService.php | 68 +- views/{batteries.php => batteries.blade.php} | 4 + ...erview.php => batteriesoverview.blade.php} | 19 +- ...{batteryform.php => batteryform.blade.php} | 4 + ...tracking.php => batterytracking.blade.php} | 4 + views/{consume.php => consume.blade.php} | 4 + style.css => views/css/grocy.css | 0 views/{habitform.php => habitform.blade.php} | 4 + views/{habits.php => habits.blade.php} | 4 + ...soverview.php => habitsoverview.blade.php} | 19 +- ...ittracking.php => habittracking.blade.php} | 4 + grocy.png => views/img/grocy.png | Bin views/{inventory.php => inventory.blade.php} | 4 + grocy.js => views/js/grocy.js | 0 .../layout/{default.php => default.blade.php} | 78 +- ...ocationform.php => locationform.blade.php} | 4 + views/{locations.php => locations.blade.php} | 4 + views/{login.php => login.blade.php} | 4 + ...{productform.php => productform.blade.php} | 4 + views/{products.php => products.blade.php} | 10 +- views/{purchase.php => purchase.blade.php} | 4 + ...nitform.php => quantityunitform.blade.php} | 4 + ...ntityunits.php => quantityunits.blade.php} | 4 + ...hoppinglist.php => shoppinglist.blade.php} | 8 +- ...istform.php => shoppinglistform.blade.php} | 4 + ...ckoverview.php => stockoverview.blade.php} | 16 +- views/viewjs/habittracking.js | 2 +- 54 files changed, 1985 insertions(+), 826 deletions(-) delete mode 100644 GrocyPhpHelper.php create mode 100644 controllers/BaseApiController.php create mode 100644 controllers/BaseController.php create mode 100644 controllers/BatteriesApiController.php create mode 100644 controllers/BatteriesController.php create mode 100644 controllers/CliController.php create mode 100644 controllers/GenericEntityApiController.php create mode 100644 controllers/HabitsApiController.php create mode 100644 controllers/HabitsController.php create mode 100644 controllers/LoginController.php create mode 100644 controllers/StockApiController.php create mode 100644 controllers/StockController.php create mode 100644 extensions.php create mode 100644 middleware/CliMiddleware.php create mode 100644 middleware/JsonMiddleware.php create mode 100644 middleware/SessionMiddleware.php create mode 100644 services/BaseService.php rename GrocyDbMigrator.php => services/DatabaseMigrationService.php (78%) rename GrocyDemoDataGenerator.php => services/DemoDataGeneratorService.php (55%) rename views/{batteries.php => batteries.blade.php} (95%) rename views/{batteriesoverview.php => batteriesoverview.blade.php} (51%) rename views/{batteryform.php => batteryform.blade.php} (95%) rename views/{batterytracking.php => batterytracking.blade.php} (96%) rename views/{consume.php => consume.blade.php} (97%) rename style.css => views/css/grocy.css (100%) rename views/{habitform.php => habitform.blade.php} (97%) rename views/{habits.php => habits.blade.php} (95%) rename views/{habitsoverview.php => habitsoverview.blade.php} (50%) rename views/{habittracking.php => habittracking.blade.php} (96%) rename grocy.png => views/img/grocy.png (100%) rename views/{inventory.php => inventory.blade.php} (98%) rename grocy.js => views/js/grocy.js (100%) rename views/layout/{default.php => default.blade.php} (76%) rename views/{locationform.php => locationform.blade.php} (94%) rename views/{locations.php => locations.blade.php} (95%) rename views/{login.php => login.blade.php} (92%) rename views/{productform.php => productform.blade.php} (98%) rename views/{products.php => products.blade.php} (79%) rename views/{purchase.php => purchase.blade.php} (98%) rename views/{quantityunitform.php => quantityunitform.blade.php} (94%) rename views/{quantityunits.php => quantityunits.blade.php} (95%) rename views/{shoppinglist.php => shoppinglist.blade.php} (75%) rename views/{shoppinglistform.php => shoppinglistform.blade.php} (98%) rename views/{stockoverview.php => stockoverview.blade.php} (56%) diff --git a/GrocyPhpHelper.php b/GrocyPhpHelper.php deleted file mode 100644 index e76a762a..00000000 --- a/GrocyPhpHelper.php +++ /dev/null @@ -1,66 +0,0 @@ -{$propertyName} == $propertyValue) - { - return $object; - } - } - - return null; - } - - public static function FindAllObjectsInArrayByPropertyValue($array, $propertyName, $propertyValue, $operator = '==') - { - $returnArray = array(); - - foreach($array as $object) - { - switch($operator) - { - case '==': - if($object->{$propertyName} == $propertyValue) - { - $returnArray[] = $object; - } - break; - case '>': - if($object->{$propertyName} > $propertyValue) - { - $returnArray[] = $object; - } - break; - case '<': - if($object->{$propertyName} < $propertyValue) - { - $returnArray[] = $object; - } - break; - } - } - - return $returnArray; - } - - public static function SumArrayValue($array, $propertyName) - { - $sum = 0; - foreach($array as $object) - { - $sum += $object->{$propertyName}; - } - - return $sum; - } - - public static function GetClassConstants($className) - { - $r = new ReflectionClass($className); - return $r->getConstants(); - } -} diff --git a/composer.json b/composer.json index 771c5dce..fe1bc9f7 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,15 @@ { "require": { "slim/slim": "^3.8", - "slim/php-view": "^2.2", "morris/lessql": "^0.3.4", - "pavlakis/slim-cli": "^1.0" + "pavlakis/slim-cli": "^1.0", + "rubellum/slim-blade-view": "^0.1.1" + }, + "autoload": { + "psr-4": { + "Grocy\\Services\\": "services/", + "Grocy\\Controllers\\": "controllers/", + "Grocy\\Middleware\\": "middleware/" + } } } diff --git a/composer.lock b/composer.lock index b61967df..c3ad7822 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "bf75d2487343249c600746a03f63cfd2", + "content-hash": "12ebab60e283dfdab831d1cc22430d05", "packages": [ { "name": "container-interop/container-interop", @@ -37,6 +37,363 @@ "homepage": "https://github.com/container-interop/container-interop", "time": "2017-02-14T19:40:03+00:00" }, + { + "name": "doctrine/inflector", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2018-01-09T20:05:19+00:00" + }, + { + "name": "illuminate/container", + "version": "v5.6.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/container.git", + "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/container/zipball/4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a", + "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a", + "shasum": "" + }, + "require": { + "illuminate/contracts": "5.6.*", + "php": "^7.1.3", + "psr/container": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Container\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Container package.", + "homepage": "https://laravel.com", + "time": "2018-01-21T02:13:38+00:00" + }, + { + "name": "illuminate/contracts", + "version": "v5.6.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "322ec80498b3bf85bc4025d028e130a9b50242b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/322ec80498b3bf85bc4025d028e130a9b50242b9", + "reference": "322ec80498b3bf85bc4025d028e130a9b50242b9", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/container": "~1.0", + "psr/simple-cache": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "time": "2018-04-07T17:05:26+00:00" + }, + { + "name": "illuminate/events", + "version": "v5.6.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/events.git", + "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/events/zipball/b6e73ed40478cef2ef98d5ddb27f333291606cea", + "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea", + "shasum": "" + }, + "require": { + "illuminate/container": "5.6.*", + "illuminate/contracts": "5.6.*", + "illuminate/support": "5.6.*", + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Events\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Events package.", + "homepage": "https://laravel.com", + "time": "2018-02-26T19:00:55+00:00" + }, + { + "name": "illuminate/filesystem", + "version": "v5.6.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/filesystem.git", + "reference": "c9ab9376076cedd88a374d7281d62b619634d578" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/filesystem/zipball/c9ab9376076cedd88a374d7281d62b619634d578", + "reference": "c9ab9376076cedd88a374d7281d62b619634d578", + "shasum": "" + }, + "require": { + "illuminate/contracts": "5.6.*", + "illuminate/support": "5.6.*", + "php": "^7.1.3", + "symfony/finder": "~4.0" + }, + "suggest": { + "league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", + "league/flysystem-cached-adapter": "Required to use the Flysystem cache (~1.0).", + "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", + "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (~1.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Filesystem\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Filesystem package.", + "homepage": "https://laravel.com", + "time": "2018-04-06T13:15:37+00:00" + }, + { + "name": "illuminate/support", + "version": "v5.6.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "fad0669f858423679497a17f973261cc32f9a5a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/fad0669f858423679497a17f973261cc32f9a5a8", + "reference": "fad0669f858423679497a17f973261cc32f9a5a8", + "shasum": "" + }, + "require": { + "doctrine/inflector": "~1.1", + "ext-mbstring": "*", + "illuminate/contracts": "5.6.*", + "nesbot/carbon": "^1.24.1", + "php": "^7.1.3" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "suggest": { + "illuminate/filesystem": "Required to use the composer class (5.6.*).", + "symfony/process": "Required to use the composer class (~4.0).", + "symfony/var-dumper": "Required to use the dd function (~4.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + }, + "files": [ + "helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Support package.", + "homepage": "https://laravel.com", + "time": "2018-04-05T21:19:22+00:00" + }, + { + "name": "illuminate/view", + "version": "v5.6.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/view.git", + "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/view/zipball/54eaf45ee7946d8f8cde13d5e89c5ea2e997040d", + "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d", + "shasum": "" + }, + "require": { + "illuminate/container": "5.6.*", + "illuminate/contracts": "5.6.*", + "illuminate/events": "5.6.*", + "illuminate/filesystem": "5.6.*", + "illuminate/support": "5.6.*", + "php": "^7.1.3", + "symfony/debug": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\View\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate View package.", + "homepage": "https://laravel.com", + "time": "2018-04-03T12:56:35+00:00" + }, { "name": "morris/lessql", "version": "v0.3.5", @@ -85,6 +442,59 @@ ], "time": "2018-01-27T13:18:21+00:00" }, + { + "name": "nesbot/carbon", + "version": "1.25.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "cbcf13da0b531767e39eb86e9687f5deba9857b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/cbcf13da0b531767e39eb86e9687f5deba9857b4", + "reference": "cbcf13da0b531767e39eb86e9687f5deba9857b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/translation": "~2.6 || ~3.0 || ~4.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2", + "phpunit/phpunit": "^4.8.35 || ^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.23-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2018-03-19T15:50:49+00:00" + }, { "name": "nikic/fast-route", "version": "v1.3.0", @@ -180,6 +590,47 @@ ], "time": "2017-01-30T22:50:06+00:00" }, + { + "name": "philo/laravel-blade", + "version": "v3.1", + "source": { + "type": "git", + "url": "https://github.com/PhiloNL/Laravel-Blade.git", + "reference": "3f0ce2ee198604c53c25188110e6d7b5e887527a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhiloNL/Laravel-Blade/zipball/3f0ce2ee198604c53c25188110e6d7b5e887527a", + "reference": "3f0ce2ee198604c53c25188110e6d7b5e887527a", + "shasum": "" + }, + "require": { + "illuminate/events": "~5", + "illuminate/view": "~5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Philo\\Blade\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Philo Hermans", + "email": "me@philohermans.com" + } + ], + "description": "Use the simple and yet powerful Laravel Blade templating engine as a standalone component.", + "keywords": [ + "blade", + "laravel" + ], + "time": "2015-12-04T09:42:42+00:00" + }, { "name": "pimple/pimple", "version": "v3.2.3", @@ -330,24 +781,121 @@ "time": "2016-08-06T14:39:51+00:00" }, { - "name": "slim/php-view", - "version": "2.2.0", + "name": "psr/log", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/slimphp/PHP-View.git", - "reference": "122ed121a8d9cf91a94020814d2a3ee6c836754f" + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/PHP-View/zipball/122ed121a8d9cf91a94020814d2a3ee6c836754f", - "reference": "122ed121a8d9cf91a94020814d2a3ee6c836754f", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "rubellum/slim-blade-view", + "version": "0.1.1", + "source": { + "type": "git", + "url": "https://github.com/rubellum/Slim-Blade-View.git", + "reference": "9cdea69285acbf712463b38a9bb0b5ce23c4c98c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rubellum/Slim-Blade-View/zipball/9cdea69285acbf712463b38a9bb0b5ce23c4c98c", + "reference": "9cdea69285acbf712463b38a9bb0b5ce23c4c98c", + "shasum": "" + }, + "require": { + "illuminate/view": "5.*", + "philo/laravel-blade": "3.*", "psr/http-message": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^4.8", + "phpunit/phpunit": "^5.0", "slim/slim": "^3.0" }, "type": "library", @@ -362,21 +910,20 @@ ], "authors": [ { - "name": "Glenn Eggleton", - "email": "geggleto@gmail.com" + "name": "Hiroaki Matsuura", + "email": "hiropeke.jp@gmail.com" } ], - "description": "Render PHP view scripts into a PSR-7 Response object.", + "description": "Slim Framework 3 view helper built on the Blade component", "keywords": [ + "blade", "framework", - "php", - "phtml", "renderer", "slim", "template", "view" ], - "time": "2016-10-11T07:43:08+00:00" + "time": "2016-03-11T02:32:00+00:00" }, { "name": "slim/slim", @@ -448,6 +995,238 @@ "router" ], "time": "2017-11-26T19:13:09+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "5961d02d48828671f5d8a7805e06579d692f6ede" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/5961d02d48828671f5d8a7805e06579d692f6ede", + "reference": "5961d02d48828671f5d8a7805e06579d692f6ede", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2018-04-03T05:24:00+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49", + "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2018-04-04T05:10:37+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-01-30T19:27:44+00:00" + }, + { + "name": "symfony/translation", + "version": "v4.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/e20a9b7f9f62cb33a11638b345c248e7d510c938", + "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/intl": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2018-02-22T10:50:29+00:00" } ], "packages-dev": [], diff --git a/controllers/BaseApiController.php b/controllers/BaseApiController.php new file mode 100644 index 00000000..8f3a1887 --- /dev/null +++ b/controllers/BaseApiController.php @@ -0,0 +1,11 @@ +AppContainer = $container; + + $databaseService = new DatabaseService(); + $this->Database = $databaseService->GetDbConnection(); + } + + protected $AppContainer; + protected $Database; +} diff --git a/controllers/BatteriesApiController.php b/controllers/BatteriesApiController.php new file mode 100644 index 00000000..9d6f08b7 --- /dev/null +++ b/controllers/BatteriesApiController.php @@ -0,0 +1,32 @@ +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'])); + } +} diff --git a/controllers/BatteriesController.php b/controllers/BatteriesController.php new file mode 100644 index 00000000..65d245fa --- /dev/null +++ b/controllers/BatteriesController.php @@ -0,0 +1,65 @@ +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' + ]); + } + } +} diff --git a/controllers/CliController.php b/controllers/CliController.php new file mode 100644 index 00000000..8cfa1786 --- /dev/null +++ b/controllers/CliController.php @@ -0,0 +1,19 @@ +IsDemoInstallation()) + { + $databaseMigrationService = new DatabaseMigrationService(); + $databaseMigrationService->RecreateDemo(); + } + } +} diff --git a/controllers/GenericEntityApiController.php b/controllers/GenericEntityApiController.php new file mode 100644 index 00000000..db73146d --- /dev/null +++ b/controllers/GenericEntityApiController.php @@ -0,0 +1,40 @@ +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)); + } +} diff --git a/controllers/HabitsApiController.php b/controllers/HabitsApiController.php new file mode 100644 index 00000000..9f54368d --- /dev/null +++ b/controllers/HabitsApiController.php @@ -0,0 +1,32 @@ +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'])); + } +} diff --git a/controllers/HabitsController.php b/controllers/HabitsController.php new file mode 100644 index 00000000..93c54c81 --- /dev/null +++ b/controllers/HabitsController.php @@ -0,0 +1,67 @@ +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' + ]); + } + } +} diff --git a/controllers/LoginController.php b/controllers/LoginController.php new file mode 100644 index 00000000..8831f2d7 --- /dev/null +++ b/controllers/LoginController.php @@ -0,0 +1,73 @@ +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'); + } +} diff --git a/controllers/StockApiController.php b/controllers/StockApiController.php new file mode 100644 index 00000000..990871db --- /dev/null +++ b/controllers/StockApiController.php @@ -0,0 +1,77 @@ +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)); + } +} diff --git a/controllers/StockController.php b/controllers/StockController.php new file mode 100644 index 00000000..84606c3d --- /dev/null +++ b/controllers/StockController.php @@ -0,0 +1,187 @@ +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' + ]); + } + } +} diff --git a/extensions.php b/extensions.php new file mode 100644 index 00000000..8046b772 --- /dev/null +++ b/extensions.php @@ -0,0 +1,63 @@ +{$propertyName} == $propertyValue) + { + return $object; + } + } + + return null; +} + +function FindAllObjectsInArrayByPropertyValue($array, $propertyName, $propertyValue, $operator = '==') +{ + $returnArray = array(); + + foreach($array as $object) + { + switch($operator) + { + case '==': + if($object->{$propertyName} == $propertyValue) + { + $returnArray[] = $object; + } + break; + case '>': + if($object->{$propertyName} > $propertyValue) + { + $returnArray[] = $object; + } + break; + case '<': + if($object->{$propertyName} < $propertyValue) + { + $returnArray[] = $object; + } + break; + } + } + + return $returnArray; +} + +function SumArrayValue($array, $propertyName) +{ + $sum = 0; + foreach($array as $object) + { + $sum += $object->{$propertyName}; + } + + return $sum; +} + +function GetClassConstants($className) +{ + $r = new ReflectionClass($className); + return $r->getConstants(); +} diff --git a/index.php b/index.php index d7296d7b..48f72b81 100644 --- a/index.php +++ b/index.php @@ -2,22 +2,19 @@ use \Psr\Http\Message\ServerRequestInterface as Request; use \Psr\Http\Message\ResponseInterface as Response; -use Slim\Views\PhpRenderer; + +use Grocy\Middleware\SessionMiddleware; +use Grocy\Middleware\JsonMiddleware; +use Grocy\Middleware\CliMiddleware; + +use Grocy\Services\ApplicationService; require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/data/config.php'; -require_once __DIR__ . '/services/ApplicationService.php'; -require_once __DIR__ . '/services/DatabaseService.php'; -require_once __DIR__ . '/services/SessionService.php'; -require_once __DIR__ . '/GrocyDbMigrator.php'; -require_once __DIR__ . '/GrocyDemoDataGenerator.php'; -require_once __DIR__ . '/services/StockService.php'; -require_once __DIR__ . '/services/HabitsService.php'; -require_once __DIR__ . '/services/BatteriesService.php'; -require_once __DIR__ . '/GrocyPhpHelper.php'; +require_once __DIR__ . '/extensions.php'; +// Setup base application $app = new \Slim\App; - if (PHP_SAPI !== 'cli') { $app = new \Slim\App(new \Slim\Container([ @@ -26,508 +23,92 @@ if (PHP_SAPI !== 'cli') 'determineRouteBeforeAppMiddleware' => true ], ])); + $container = $app->getContainer(); - $container['renderer'] = new PhpRenderer('./views'); -} - -if (PHP_SAPI === 'cli') -{ - $app->add(new \pavlakis\cli\CliRequest()); -} - -if (!ApplicationService::IsDemoInstallation()) -{ - $sessionMiddleware = function(Request $request, Response $response, callable $next) + $container['view'] = function($container) { - $route = $request->getAttribute('route'); - $routeName = $route->getName(); - - if ((!isset($_COOKIE['grocy_session']) || !SessionService::IsValidSession($_COOKIE['grocy_session'])) && $routeName !== 'login') - { - $response = $response->withRedirect('/login'); - } - else - { - $response = $next($request, $response); - } - - return $response; + return new \Slim\Views\Blade(__DIR__ . '/views', __DIR__ . '/data/viewcache'); }; - - $app->add($sessionMiddleware); +} +else +{ + $app->add(\pavlakis\cli\CliRequest::class); } -$db = DatabaseService::GetDbConnection(); - -$app->get('/login', function(Request $request, Response $response) +// Add session handling if this is not a demo installation +$applicationService = new ApplicationService(); +if (!$applicationService->IsDemoInstallation()) { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Login', - 'contentPage' => 'login.php' - ]); -})->setName('login'); + $app->add(SessionMiddleware::class); +} -$app->post('/login', function(Request $request, Response $response) +// Base route +$app->get('/', 'Grocy\Controllers\LoginController:Root'); + +// Login routes +$app->get('/login', 'Grocy\Controllers\LoginController:LoginPage')->setName('login'); +$app->post('/login', 'Grocy\Controllers\LoginController:ProcessLogin')->setName('login'); +$app->get('/logout', 'Grocy\Controllers\LoginController:Logout'); + +// Stock routes +$app->get('/stockoverview', 'Grocy\Controllers\StockController:Overview'); +$app->get('/purchase', 'Grocy\Controllers\StockController:Purchase'); +$app->get('/consume', 'Grocy\Controllers\StockController:Consume'); +$app->get('/inventory', 'Grocy\Controllers\StockController:Inventory'); + +$app->get('/products', 'Grocy\Controllers\StockController:ProductsList'); +$app->get('/product/{productId}', 'Grocy\Controllers\StockController:ProductEditForm'); + +$app->get('/locations', 'Grocy\Controllers\StockController:LocationsList'); +$app->get('/location/{locationId}', 'Grocy\Controllers\StockController:LocationEditForm'); + +$app->get('/quantityunits', 'Grocy\Controllers\StockController:QuantityUnitsList'); +$app->get('/quantityunit/{quantityunitId}', 'Grocy\Controllers\StockController:QuantityUnitEditForm'); + +$app->get('/shoppinglist', 'Grocy\Controllers\StockController:ShoppingList'); +$app->get('/shoppinglistitem/{itemId}', 'Grocy\Controllers\StockController:ShoppingListItemEditForm'); + + +// Habit routes +$app->get('/habitsoverview', 'Grocy\Controllers\HabitsController:Overview'); +$app->get('/habittracking', 'Grocy\Controllers\HabitsController:TrackHabitExecution'); + +$app->get('/habits', 'Grocy\Controllers\HabitsController:HabitsList'); +$app->get('/habit/{habitId}', 'Grocy\Controllers\HabitsController:HabitEditForm'); + +// Batterry routes +$app->get('/batteriesoverview', 'Grocy\Controllers\BatteriesController:Overview'); +$app->get('/batterytracking', 'Grocy\Controllers\BatteriesController:TrackChargeCycle'); + +$app->get('/batteries', 'Grocy\Controllers\BatteriesController:BatteriesList'); +$app->get('/battery/{batteryId}', 'Grocy\Controllers\BatteriesController:BatteryEditForm'); + + +$app->group('/api', function() { - $postParams = $request->getParsedBody(); - if (isset($postParams['username']) && isset($postParams['password'])) - { - if ($postParams['username'] === HTTP_USER && $postParams['password'] === HTTP_PASSWORD) - { - $sessionKey = SessionService::CreateSession(); - setcookie('grocy_session', $sessionKey, time()+2592000); //30 days + $this->get('/get-objects/{entity}', 'Grocy\Controllers\GenericEntityApiController:GetObjects'); + $this->get('/get-object/{entity}/{objectId}', 'Grocy\Controllers\GenericEntityApiController:GetObject'); + $this->post('/add-object/{entity}', 'Grocy\Controllers\GenericEntityApiController:AddObject'); + $this->post('/edit-object/{entity}/{objectId}', 'Grocy\Controllers\GenericEntityApiController:EditObject'); + $this->get('/delete-object/{entity}/{objectId}', 'Grocy\Controllers\GenericEntityApiController:DeleteObject'); - return $response->withRedirect('/'); - } - else - { - return $response->withRedirect('/login?invalid=true'); - } - } - else - { - return $response->withRedirect('/login?invalid=true'); - } -})->setName('login'); + $this->get('/stock/add-product/{productId}/{amount}', 'Grocy\Controllers\StockApiController:AddProduct'); + $this->get('/stock/consume-product/{productId}/{amount}', 'Grocy\Controllers\StockApiController:ConsumeProduct'); + $this->get('/stock/inventory-product/{productId}/{newAmount}', 'Grocy\Controllers\StockApiController:InventoryProduct'); + $this->get('/stock/get-product-details/{productId}', 'Grocy\Controllers\StockApiController:ProductDetails'); + $this->get('/stock/get-current-stock', 'Grocy\Controllers\StockApiController:CurrentStock'); + $this->get('/stock/add-missing-products-to-shoppinglist', 'Grocy\Controllers\StockApiController:AddMissingProductsToShoppingList'); -$app->get('/logout', function(Request $request, Response $response) -{ - SessionService::RemoveSession($_COOKIE['grocy_session']); - return $response->withRedirect('/'); -}); - -$app->get('/', function(Request $request, Response $response) use($db) -{ - $db = DatabaseService::GetDbConnection(true); //For database schema migration - - return $response->withRedirect('/stockoverview'); -}); - -$app->get('/stockoverview', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Stock overview', - 'contentPage' => 'stockoverview.php', - 'products' => $db->products(), - 'quantityunits' => $db->quantity_units(), - 'currentStock' => StockService::GetCurrentStock(), - 'missingProducts' => StockService::GetMissingProducts() - ]); -}); - -$app->get('/habitsoverview', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Habits overview', - 'contentPage' => 'habitsoverview.php', - 'habits' => $db->habits(), - 'currentHabits' => HabitsService::GetCurrentHabits(), - ]); -}); - -$app->get('/batteriesoverview', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Batteries overview', - 'contentPage' => 'batteriesoverview.php', - 'batteries' => $db->batteries(), - 'current' => BatteriesService::GetCurrent(), - ]); -}); - -$app->get('/purchase', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Purchase', - 'contentPage' => 'purchase.php', - 'products' => $db->products() - ]); -}); - -$app->get('/consume', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Consume', - 'contentPage' => 'consume.php', - 'products' => $db->products() - ]); -}); - -$app->get('/inventory', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Inventory', - 'contentPage' => 'inventory.php', - 'products' => $db->products() - ]); -}); - -$app->get('/shoppinglist', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Shopping list', - 'contentPage' => 'shoppinglist.php', - 'listItems' => $db->shopping_list(), - 'products' => $db->products(), - 'quantityunits' => $db->quantity_units(), - 'missingProducts' => StockService::GetMissingProducts() - ]); -}); - -$app->get('/habittracking', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Habit tracking', - 'contentPage' => 'habittracking.php', - 'habits' => $db->habits() - ]); -}); - -$app->get('/batterytracking', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Battery tracking', - 'contentPage' => 'batterytracking.php', - 'batteries' => $db->batteries() - ]); -}); - -$app->get('/products', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Products', - 'contentPage' => 'products.php', - 'products' => $db->products(), - 'locations' => $db->locations(), - 'quantityunits' => $db->quantity_units() - ]); -}); - -$app->get('/locations', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Locations', - 'contentPage' => 'locations.php', - 'locations' => $db->locations() - ]); -}); - -$app->get('/quantityunits', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Quantity units', - 'contentPage' => 'quantityunits.php', - 'quantityunits' => $db->quantity_units() - ]); -}); - -$app->get('/habits', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Habits', - 'contentPage' => 'habits.php', - 'habits' => $db->habits() - ]); -}); - -$app->get('/batteries', function(Request $request, Response $response) use($db) -{ - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Batteries', - 'contentPage' => 'batteries.php', - 'batteries' => $db->batteries() - ]); -}); - - -$app->get('/product/{productId}', function(Request $request, Response $response, $args) use($db) -{ - if ($args['productId'] == 'new') - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Create product', - 'contentPage' => 'productform.php', - 'locations' => $db->locations(), - 'quantityunits' => $db->quantity_units(), - 'mode' => 'create' - ]); - } - else - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Edit product', - 'contentPage' => 'productform.php', - 'product' => $db->products($args['productId']), - 'locations' => $db->locations(), - 'quantityunits' => $db->quantity_units(), - 'mode' => 'edit' - ]); - } -}); - -$app->get('/location/{locationId}', function(Request $request, Response $response, $args) use($db) -{ - if ($args['locationId'] == 'new') - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Create location', - 'contentPage' => 'locationform.php', - 'mode' => 'create' - ]); - } - else - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Edit location', - 'contentPage' => 'locationform.php', - 'location' => $db->locations($args['locationId']), - 'mode' => 'edit' - ]); - } -}); - -$app->get('/quantityunit/{quantityunitId}', function(Request $request, Response $response, $args) use($db) -{ - if ($args['quantityunitId'] == 'new') - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Create quantity unit', - 'contentPage' => 'quantityunitform.php', - 'mode' => 'create' - ]); - } - else - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Edit quantity unit', - 'contentPage' => 'quantityunitform.php', - 'quantityunit' => $db->quantity_units($args['quantityunitId']), - 'mode' => 'edit' - ]); - } -}); - -$app->get('/habit/{habitId}', function(Request $request, Response $response, $args) use($db) -{ - if ($args['habitId'] == 'new') - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Create habit', - 'contentPage' => 'habitform.php', - 'periodTypes' => GrocyPhpHelper::GetClassConstants('HabitsService'), - 'mode' => 'create' - ]); - } - else - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Edit habit', - 'contentPage' => 'habitform.php', - 'habit' => $db->habits($args['habitId']), - 'periodTypes' => GrocyPhpHelper::GetClassConstants('HabitsService'), - 'mode' => 'edit' - ]); - } -}); - -$app->get('/battery/{batteryId}', function(Request $request, Response $response, $args) use($db) -{ - if ($args['batteryId'] == 'new') - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Create battery', - 'contentPage' => 'batteryform.php', - 'mode' => 'create' - ]); - } - else - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Edit battery', - 'contentPage' => 'batteryform.php', - 'battery' => $db->batteries($args['batteryId']), - 'mode' => 'edit' - ]); - } -}); - -$app->get('/shoppinglistitem/{itemId}', function(Request $request, Response $response, $args) use($db) -{ - if ($args['itemId'] == 'new') - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Add shopping list item', - 'contentPage' => 'shoppinglistform.php', - 'products' => $db->products(), - 'mode' => 'create' - ]); - } - else - { - return $this->renderer->render($response, 'layout/default.php', [ - 'title' => 'Edit shopping list item', - 'contentPage' => 'shoppinglistform.php', - 'listItem' => $db->shopping_list($args['itemId']), - 'products' => $db->products(), - 'mode' => 'edit' - ]); - } -}); - -$app->group('/api', function() use($db) -{ - $this->get('/get-objects/{entity}', function(Request $request, Response $response, $args) use($db) - { - echo json_encode($db->{$args['entity']}()); - }); - - $this->get('/get-object/{entity}/{objectId}', function(Request $request, Response $response, $args) use($db) - { - echo json_encode($db->{$args['entity']}($args['objectId'])); - }); - - $this->post('/add-object/{entity}', function(Request $request, Response $response, $args) use($db) - { - $newRow = $db->{$args['entity']}()->createRow($request->getParsedBody()); - $newRow->save(); - $success = $newRow->isClean(); - echo json_encode(array('success' => $success)); - }); - - $this->post('/edit-object/{entity}/{objectId}', function(Request $request, Response $response, $args) use($db) - { - $row = $db->{$args['entity']}($args['objectId']); - $row->update($request->getParsedBody()); - $success = $row->isClean(); - echo json_encode(array('success' => $success)); - }); - - $this->get('/delete-object/{entity}/{objectId}', function(Request $request, Response $response, $args) use($db) - { - $row = $db->{$args['entity']}($args['objectId']); - $row->delete(); - $success = $row->isClean(); - echo json_encode(array('success' => $success)); - }); - - $this->get('/stock/add-product/{productId}/{amount}', function(Request $request, Response $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']; - } - - echo json_encode(array('success' => StockService::AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType))); - }); - - $this->get('/stock/consume-product/{productId}/{amount}', function(Request $request, Response $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']; - } - - echo json_encode(array('success' => StockService::ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType))); - }); - - $this->get('/stock/inventory-product/{productId}/{newAmount}', function(Request $request, Response $response, $args) - { - $bestBeforeDate = date('Y-m-d'); - if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate'])) - { - $bestBeforeDate = $request->getQueryParams()['bestbeforedate']; - } - - echo json_encode(array('success' => StockService::InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate))); - }); - - $this->get('/stock/get-product-details/{productId}', function(Request $request, Response $response, $args) - { - echo json_encode(StockService::GetProductDetails($args['productId'])); - }); - - $this->get('/stock/get-current-stock', function(Request $request, Response $response) - { - echo json_encode(StockService::GetCurrentStock()); - }); - - $this->get('/stock/add-missing-products-to-shoppinglist', function(Request $request, Response $response) - { - StockService::AddMissingProductsToShoppingList(); - echo json_encode(array('success' => true)); - }); - - $this->get('/habits/track-habit/{habitId}', function(Request $request, Response $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']; - } - - echo json_encode(array('success' => HabitsService::TrackHabit($args['habitId'], $trackedTime))); - }); - - $this->get('/habits/get-habit-details/{habitId}', function(Request $request, Response $response, $args) - { - echo json_encode(HabitsService::GetHabitDetails($args['habitId'])); - }); - - $this->get('/batteries/track-charge-cycle/{batteryId}', function(Request $request, Response $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']; - } - - echo json_encode(array('success' => BatteriesService::TrackChargeCycle($args['batteryId'], $trackedTime))); - }); - - $this->get('/batteries/get-battery-details/{batteryId}', function(Request $request, Response $response, $args) - { - echo json_encode(BatteriesService::GetBatteryDetails($args['batteryId'])); - }); -})->add(function($request, $response, $next) -{ - $response = $next($request, $response); - return $response->withHeader('Content-Type', 'application/json'); -}); + $this->get('/habits/track-habit-execution/{habitId}', 'Grocy\Controllers\HabitsApiController:TrackHabitExecution'); + $this->get('/habits/get-habit-details/{habitId}', 'Grocy\Controllers\HabitsApiController:HabitDetails'); + + $this->get('/batteries/track-charge-cycle/{batteryId}', 'Grocy\Controllers\BatteriesApiController:TrackChargeCycle'); + $this->get('/batteries/get-battery-details/{batteryId}', 'Grocy\Controllers\BatteriesApiController:BatteryDetails'); +})->add(JsonMiddleware::class); $app->group('/cli', function() { - $this->get('/recreatedemo', function(Request $request, Response $response) - { - if (ApplicationService::IsDemoInstallation()) - { - GrocyDemoDataGenerator::RecreateDemo(); - } - }); -})->add(function($request, $response, $next) -{ - $response = $next($request, $response); - - if (PHP_SAPI !== 'cli') - { - echo 'Please call this only from CLI'; - return $response->withHeader('Content-Type', 'text/plain')->withStatus(400); - } - - return $response->withHeader('Content-Type', 'text/plain'); -}); + $this->get('/recreatedemo', 'Grocy\Controllers\CliController:RecreateDemo'); +})->add(CliMiddleware::class); $app->run(); diff --git a/middleware/CliMiddleware.php b/middleware/CliMiddleware.php new file mode 100644 index 00000000..c1a4d528 --- /dev/null +++ b/middleware/CliMiddleware.php @@ -0,0 +1,25 @@ +container = $container; + } + + protected $container; + + public function __invoke(\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next) + { + $response = $next($request, $response); + + if (PHP_SAPI !== 'cli') + { + $response->write('Please call this only from CLI'); + return $response->withHeader('Content-Type', 'text/plain')->withStatus(400); + } + + return $response->withHeader('Content-Type', 'text/plain'); + } +} diff --git a/middleware/JsonMiddleware.php b/middleware/JsonMiddleware.php new file mode 100644 index 00000000..57443a4c --- /dev/null +++ b/middleware/JsonMiddleware.php @@ -0,0 +1,18 @@ +container = $container; + } + + protected $container; + + public function __invoke(\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next) + { + $response = $next($request, $response, $next); + return $response->withHeader('Content-Type', 'application/json'); + } +} diff --git a/middleware/SessionMiddleware.php b/middleware/SessionMiddleware.php new file mode 100644 index 00000000..2a04eecb --- /dev/null +++ b/middleware/SessionMiddleware.php @@ -0,0 +1,32 @@ +container = $container; + } + + protected $container; + + public function __invoke(\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next) + { + $route = $request->getAttribute('route'); + $routeName = $route->getName(); + + $sessionService = new SessionService(); + if ((!isset($_COOKIE['grocy_session']) || !$sessionService->IsValidSession($_COOKIE['grocy_session'])) && $routeName !== 'login') + { + $response = $response->withRedirect('/login'); + } + else + { + $response = $next($request, $response); + } + + return $response; + } +} diff --git a/services/ApplicationService.php b/services/ApplicationService.php index 2e80a031..224d07ed 100644 --- a/services/ApplicationService.php +++ b/services/ApplicationService.php @@ -1,26 +1,28 @@ InstalledVersion == null) { - self::$InstalledVersion = preg_replace("/\r|\n/", '', file_get_contents(__DIR__ . '/../version.txt')); + $this->InstalledVersion = preg_replace("/\r|\n/", '', file_get_contents(__DIR__ . '/../version.txt')); } - return self::$InstalledVersion; + return $this->InstalledVersion; } } diff --git a/services/BaseService.php b/services/BaseService.php new file mode 100644 index 00000000..212be5d9 --- /dev/null +++ b/services/BaseService.php @@ -0,0 +1,16 @@ +DatabaseService = new DatabaseService(); + $this->Database = $this->DatabaseService->GetDbConnection(); + } + + protected $DatabaseService; + protected $Database; +} diff --git a/services/BatteriesService.php b/services/BatteriesService.php index 7791f354..7645a1b2 100644 --- a/services/BatteriesService.php +++ b/services/BatteriesService.php @@ -1,19 +1,19 @@ fetchAll(PDO::FETCH_OBJ); + return $this->DatabaseService->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ); } - public static function GetNextChargeTime(int $batteryId) + public function GetNextChargeTime(int $batteryId) { - $db = DatabaseService::GetDbConnection(); - - $battery = $db->batteries($batteryId); - $batteryLastLogRow = DatabaseService::ExecuteDbQuery(DatabaseService::GetDbConnectionRaw(), "SELECT * from batteries_current WHERE battery_id = $batteryId LIMIT 1")->fetch(PDO::FETCH_OBJ); + $battery = $this->Database->batteries($batteryId); + $batteryLastLogRow = $this->DatabaseService->ExecuteDbQuery("SELECT * from batteries_current WHERE battery_id = $batteryId LIMIT 1")->fetch(\PDO::FETCH_OBJ); if ($battery->charge_interval_days > 0) { @@ -27,13 +27,11 @@ class BatteriesService return null; } - public static function GetBatteryDetails(int $batteryId) + public function GetBatteryDetails(int $batteryId) { - $db = DatabaseService::GetDbConnection(); - - $battery = $db->batteries($batteryId); - $batteryChargeCylcesCount = $db->battery_charge_cycles()->where('battery_id', $batteryId)->count(); - $batteryLastChargedTime = $db->battery_charge_cycles()->where('battery_id', $batteryId)->max('tracked_time'); + $battery = $this->Database->batteries($batteryId); + $batteryChargeCylcesCount = $this->Database->battery_charge_cycles()->where('battery_id', $batteryId)->count(); + $batteryLastChargedTime = $this->Database->battery_charge_cycles()->where('battery_id', $batteryId)->max('tracked_time'); return array( 'battery' => $battery, @@ -42,11 +40,9 @@ class BatteriesService ); } - public static function TrackChargeCycle(int $batteryId, string $trackedTime) + public function TrackChargeCycle(int $batteryId, string $trackedTime) { - $db = DatabaseService::GetDbConnection(); - - $logRow = $db->battery_charge_cycles()->createRow(array( + $logRow = $this->Database->battery_charge_cycles()->createRow(array( 'battery_id' => $batteryId, 'tracked_time' => $trackedTime )); diff --git a/GrocyDbMigrator.php b/services/DatabaseMigrationService.php similarity index 78% rename from GrocyDbMigrator.php rename to services/DatabaseMigrationService.php index 3c80565f..f6b31122 100644 --- a/GrocyDbMigrator.php +++ b/services/DatabaseMigrationService.php @@ -1,10 +1,14 @@ DatabaseService->ExecuteDbStatement("CREATE TABLE IF NOT EXISTS migrations (migration INTEGER NOT NULL PRIMARY KEY UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')))"); + + $this->ExecuteMigrationWhenNeeded(1, " CREATE TABLE products ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL UNIQUE, @@ -20,7 +24,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 2, " + $this->ExecuteMigrationWhenNeeded(2, " CREATE TABLE locations ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL UNIQUE, @@ -29,7 +33,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 3, " + $this->ExecuteMigrationWhenNeeded(3, " CREATE TABLE quantity_units ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL UNIQUE, @@ -38,7 +42,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 4, " + $this->ExecuteMigrationWhenNeeded(4, " CREATE TABLE stock ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, product_id INTEGER NOT NULL, @@ -50,7 +54,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 5, " + $this->ExecuteMigrationWhenNeeded(5, " CREATE TABLE stock_log ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, product_id INTEGER NOT NULL, @@ -65,14 +69,14 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 6, " + $this->ExecuteMigrationWhenNeeded(6, " INSERT INTO locations (name, description) VALUES ('DefaultLocation', 'This is the first default location, edit or delete it'); INSERT INTO quantity_units (name, description) VALUES ('DefaultQuantityUnit', 'This is the first default quantity unit, edit or delete it'); INSERT INTO products (name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('DefaultProduct1', 'This is the first default product, edit or delete it', 1, 1, 1, 1); INSERT INTO products (name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('DefaultProduct2', 'This is the second default product, edit or delete it', 1, 1, 1, 1);" ); - self::ExecuteMigrationWhenNeeded($pdo, 7, " + $this->ExecuteMigrationWhenNeeded(7, " CREATE VIEW stock_missing_products AS SELECT p.id, MAX(p.name) AS name, p.min_stock_amount - IFNULL(SUM(s.amount), 0) AS amount_missing @@ -84,7 +88,7 @@ class GrocyDbMigrator HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount;" ); - self::ExecuteMigrationWhenNeeded($pdo, 8, " + $this->ExecuteMigrationWhenNeeded(8, " CREATE VIEW stock_current AS SELECT product_id, SUM(amount) AS amount, MIN(best_before_date) AS best_before_date @@ -93,7 +97,7 @@ class GrocyDbMigrator ORDER BY MIN(best_before_date) ASC;" ); - self::ExecuteMigrationWhenNeeded($pdo, 9, " + $this->ExecuteMigrationWhenNeeded(9, " CREATE TABLE shopping_list ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, product_id INTEGER NOT NULL UNIQUE, @@ -103,7 +107,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 10, " + $this->ExecuteMigrationWhenNeeded(10, " CREATE TABLE habits ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL UNIQUE, @@ -114,7 +118,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 11, " + $this->ExecuteMigrationWhenNeeded(11, " CREATE TABLE habits_log ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, habit_id INTEGER NOT NULL, @@ -123,7 +127,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 12, " + $this->ExecuteMigrationWhenNeeded(12, " CREATE VIEW habits_current AS SELECT habit_id, MAX(tracked_time) AS last_tracked_time @@ -132,7 +136,7 @@ class GrocyDbMigrator ORDER BY MAX(tracked_time) DESC;" ); - self::ExecuteMigrationWhenNeeded($pdo, 13, " + $this->ExecuteMigrationWhenNeeded(13, " CREATE TABLE batteries ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL UNIQUE, @@ -143,7 +147,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 14, " + $this->ExecuteMigrationWhenNeeded(14, " CREATE TABLE battery_charge_cycles ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, battery_id TEXT NOT NULL, @@ -152,7 +156,7 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 15, " + $this->ExecuteMigrationWhenNeeded(15, " CREATE VIEW batteries_current AS SELECT battery_id, MAX(tracked_time) AS last_tracked_time @@ -161,11 +165,11 @@ class GrocyDbMigrator ORDER BY MAX(tracked_time) DESC;" ); - self::ExecuteMigrationWhenNeeded($pdo, 16, " + $this->ExecuteMigrationWhenNeeded(16, " ALTER TABLE shopping_list RENAME TO shopping_list_old;" ); - self::ExecuteMigrationWhenNeeded($pdo, 17, " + $this->ExecuteMigrationWhenNeeded(17, " CREATE TABLE shopping_list ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, product_id INTEGER, @@ -176,25 +180,25 @@ class GrocyDbMigrator )" ); - self::ExecuteMigrationWhenNeeded($pdo, 18, " + $this->ExecuteMigrationWhenNeeded(18, " INSERT INTO shopping_list (product_id, amount, amount_autoadded, row_created_timestamp) SELECT product_id, amount, amount_autoadded, row_created_timestamp FROM shopping_list_old" ); - self::ExecuteMigrationWhenNeeded($pdo, 19, " + $this->ExecuteMigrationWhenNeeded(19, " DROP TABLE shopping_list_old;" ); } - private static function ExecuteMigrationWhenNeeded(PDO $pdo, int $migrationId, string $sql) + private function ExecuteMigrationWhenNeeded(int $migrationId, string $sql) { - $rowCount = DatabaseService::ExecuteDbQuery($pdo, 'SELECT COUNT(*) FROM migrations WHERE migration = ' . $migrationId)->fetchColumn(); + $rowCount = $this->DatabaseService->ExecuteDbQuery('SELECT COUNT(*) FROM migrations WHERE migration = ' . $migrationId)->fetchColumn(); if (intval($rowCount) === 0) { - DatabaseService::ExecuteDbStatement($pdo, $sql); - DatabaseService::ExecuteDbStatement($pdo, 'INSERT INTO migrations (migration) VALUES (' . $migrationId . ')'); + $this->DatabaseService->ExecuteDbStatement($sql); + $this->DatabaseService->ExecuteDbStatement('INSERT INTO migrations (migration) VALUES (' . $migrationId . ')'); } } } diff --git a/services/DatabaseService.php b/services/DatabaseService.php index ff21d4da..f3726655 100644 --- a/services/DatabaseService.php +++ b/services/DatabaseService.php @@ -1,64 +1,47 @@ DbConnectionRaw == null) { - self::$DbConnectionRaw = null; + $pdo = new \PDO('sqlite:' . __DIR__ . '/../data/grocy.db'); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + $this->DbConnectionRaw = $pdo; } - if (self::$DbConnectionRaw == null) - { - $pdo = new PDO('sqlite:' . __DIR__ . '/../data/grocy.db'); - $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - if ($doMigrations === true) - { - self::ExecuteDbStatement($pdo, "CREATE TABLE IF NOT EXISTS migrations (migration INTEGER NOT NULL PRIMARY KEY UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')))"); - GrocyDbMigrator::MigrateDb($pdo); - - if (ApplicationService::IsDemoInstallation()) - { - GrocyDemoDataGenerator::PopulateDemoData($pdo); - } - } - - self::$DbConnectionRaw = $pdo; - } - - return self::$DbConnectionRaw; + return $this->DbConnectionRaw; } - private static $DbConnection; + private $DbConnection; /** - * @return LessQL\Database + * @return \LessQL\Database */ - public static function GetDbConnection($doMigrations = false) + public function GetDbConnection() { - if ($doMigrations === true) + if ($this->DbConnection == null) { - self::$DbConnection = null; + $this->DbConnection = new \LessQL\Database($this->GetDbConnectionRaw()); } - if (self::$DbConnection == null) - { - self::$DbConnection = new LessQL\Database(self::GetDbConnectionRaw($doMigrations)); - } - - return self::$DbConnection; + return $this->DbConnection; } /** * @return boolean */ - public static function ExecuteDbStatement(PDO $pdo, string $sql) + public function ExecuteDbStatement(string $sql) { + $pdo = $this->GetDbConnectionRaw(); if ($pdo->exec($sql) === false) { throw new Exception($pdo->errorInfo()); @@ -68,11 +51,12 @@ class DatabaseService } /** - * @return boolean|PDOStatement + * @return boolean|\PDOStatement */ - public static function ExecuteDbQuery(PDO $pdo, string $sql) + public function ExecuteDbQuery(string $sql) { - if (self::ExecuteDbStatement($pdo, $sql) === true) + $pdo = $this->GetDbConnectionRaw(); + if ($this->ExecuteDbStatement($sql) === true) { return $pdo->query($sql); } diff --git a/GrocyDemoDataGenerator.php b/services/DemoDataGeneratorService.php similarity index 55% rename from GrocyDemoDataGenerator.php rename to services/DemoDataGeneratorService.php index 81d8de7e..bcea126d 100644 --- a/GrocyDemoDataGenerator.php +++ b/services/DemoDataGeneratorService.php @@ -1,10 +1,12 @@ fetchColumn(); + $rowCount = $this->DatabaseService->ExecuteDbQuery('SELECT COUNT(*) FROM migrations WHERE migration = -1')->fetchColumn(); if (intval($rowCount) === 0) { $sql = " @@ -45,46 +47,47 @@ class GrocyDemoDataGenerator INSERT INTO migrations (migration) VALUES (-1); "; - DatabaseService::ExecuteDbStatement($pdo, $sql); + $this->DatabaseService->ExecuteDbStatement($sql); - StockService::AddProduct(3, 5, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(4, 5, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(5, 5, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(6, 5, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(7, 5, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(8, 5, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(9, 5, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(10, 5, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(11, 5, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(12, 5, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(13, 5, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(14, 5, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddProduct(15, 5, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE); - StockService::AddMissingProductsToShoppingList(); + $stockService = new StockService(); + $stockService->AddProduct(3, 5, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(4, 5, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(5, 5, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(6, 5, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(7, 5, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(8, 5, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(9, 5, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(10, 5, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(11, 5, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(12, 5, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(13, 5, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(14, 5, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddProduct(15, 5, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE); + $stockService->AddMissingProductsToShoppingList(); - HabitsService::TrackHabit(1, date('Y-m-d H:i:s', strtotime('-5 days'))); - HabitsService::TrackHabit(1, date('Y-m-d H:i:s', strtotime('-10 days'))); - HabitsService::TrackHabit(1, date('Y-m-d H:i:s', strtotime('-15 days'))); - HabitsService::TrackHabit(2, date('Y-m-d H:i:s', strtotime('-10 days'))); - HabitsService::TrackHabit(2, date('Y-m-d H:i:s', strtotime('-20 days'))); + $habitsService = new HabitsService(); + $habitsService->TrackHabit(1, date('Y-m-d H:i:s', strtotime('-5 days'))); + $habitsService->TrackHabit(1, date('Y-m-d H:i:s', strtotime('-10 days'))); + $habitsService->TrackHabit(1, date('Y-m-d H:i:s', strtotime('-15 days'))); + $habitsService->TrackHabit(2, date('Y-m-d H:i:s', strtotime('-10 days'))); + $habitsService->TrackHabit(2, date('Y-m-d H:i:s', strtotime('-20 days'))); - BatteriesService::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-200 days'))); - BatteriesService::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-150 days'))); - BatteriesService::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-100 days'))); - BatteriesService::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-50 days'))); - BatteriesService::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-200 days'))); - BatteriesService::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-150 days'))); - BatteriesService::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-100 days'))); - BatteriesService::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-50 days'))); - BatteriesService::TrackChargeCycle(3, date('Y-m-d H:i:s', strtotime('-65 days'))); + $batteriesService = new BatteriesService(); + $batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-200 days'))); + $batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-150 days'))); + $batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-100 days'))); + $batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-50 days'))); + $batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-200 days'))); + $batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-150 days'))); + $batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-100 days'))); + $batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-50 days'))); + $batteriesService->TrackChargeCycle(3, date('Y-m-d H:i:s', strtotime('-65 days'))); } } - public static function RecreateDemo() + public function RecreateDemo() { unlink(__DIR__ . '/data/grocy.db'); - - $db = DatabaseService::GetDbConnectionRaw(true); - self::PopulateDemoData($db); + $this->PopulateDemoData($this->DatabaseService->GetDbConnectionRaw(true)); } } diff --git a/services/HabitsService.php b/services/HabitsService.php index 39e08ba8..4db54aff 100644 --- a/services/HabitsService.php +++ b/services/HabitsService.php @@ -1,22 +1,22 @@ fetchAll(PDO::FETCH_OBJ); + return $this->DatabaseService->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ); } - public static function GetNextHabitTime(int $habitId) + public function GetNextHabitTime(int $habitId) { - $db = DatabaseService::GetDbConnection(); - - $habit = $db->habits($habitId); - $habitLastLogRow = DatabaseService::ExecuteDbQuery(DatabaseService::GetDbConnectionRaw(), "SELECT * from habits_current WHERE habit_id = $habitId LIMIT 1")->fetch(PDO::FETCH_OBJ); + $habit = $this->Database->habits($habitId); + $habitLastLogRow = $this->DatabaseService->ExecuteDbQuery("SELECT * from habits_current WHERE habit_id = $habitId LIMIT 1")->fetch(\PDO::FETCH_OBJ); switch ($habit->period_type) { @@ -29,13 +29,11 @@ class HabitsService return null; } - public static function GetHabitDetails(int $habitId) + public function GetHabitDetails(int $habitId) { - $db = DatabaseService::GetDbConnection(); - - $habit = $db->habits($habitId); - $habitTrackedCount = $db->habits_log()->where('habit_id', $habitId)->count(); - $habitLastTrackedTime = $db->habits_log()->where('habit_id', $habitId)->max('tracked_time'); + $habit = $this->Database->habits($habitId); + $habitTrackedCount = $this->Database->habits_log()->where('habit_id', $habitId)->count(); + $habitLastTrackedTime = $this->Database->habits_log()->where('habit_id', $habitId)->max('tracked_time'); return array( 'habit' => $habit, @@ -44,11 +42,9 @@ class HabitsService ); } - public static function TrackHabit(int $habitId, string $trackedTime) + public function TrackHabit(int $habitId, string $trackedTime) { - $db = DatabaseService::GetDbConnection(); - - $logRow = $db->habits_log()->createRow(array( + $logRow = $this->Database->habits_log()->createRow(array( 'habit_id' => $habitId, 'tracked_time' => $trackedTime )); diff --git a/services/SessionService.php b/services/SessionService.php index 257e25d0..e909a734 100644 --- a/services/SessionService.php +++ b/services/SessionService.php @@ -1,11 +1,13 @@ getCTime() >= 2678400) //31 days { @@ -41,7 +43,7 @@ class SessionService return $newSessionKey; } - public static function RemoveSession($sessionKey) + public function RemoveSession($sessionKey) { unlink(__DIR__ . "/../data/sessions/$sessionKey.txt"); } diff --git a/services/StockService.php b/services/StockService.php index ae61bbe7..1e727254 100644 --- a/services/StockService.php +++ b/services/StockService.php @@ -1,33 +1,33 @@ fetchAll(PDO::FETCH_OBJ); + return $this->DatabaseService->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ); } - public static function GetMissingProducts() + public function GetMissingProducts() { $sql = 'SELECT * from stock_missing_products'; - return DatabaseService::ExecuteDbQuery(DatabaseService::GetDbConnectionRaw(), $sql)->fetchAll(PDO::FETCH_OBJ); + return $this->DatabaseService->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ); } - public static function GetProductDetails(int $productId) + public function GetProductDetails(int $productId) { - $db = DatabaseService::GetDbConnection(); - - $product = $db->products($productId); - $productStockAmount = $db->stock()->where('product_id', $productId)->sum('amount'); - $productLastPurchased = $db->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_PURCHASE)->max('purchased_date'); - $productLastUsed = $db->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->max('used_date'); - $quPurchase = $db->quantity_units($product->qu_id_purchase); - $quStock = $db->quantity_units($product->qu_id_stock); + $product = $this->Database->products($productId); + $productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount'); + $productLastPurchased = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_PURCHASE)->max('purchased_date'); + $productLastUsed = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->max('used_date'); + $quPurchase = $this->Database->quantity_units($product->qu_id_purchase); + $quStock = $this->Database->quantity_units($product->qu_id_stock); return array( 'product' => $product, @@ -39,14 +39,13 @@ class StockService ); } - public static function AddProduct(int $productId, int $amount, string $bestBeforeDate, $transactionType) + public function AddProduct(int $productId, int $amount, string $bestBeforeDate, $transactionType) { if ($transactionType === self::TRANSACTION_TYPE_CONSUME || $transactionType === self::TRANSACTION_TYPE_PURCHASE || $transactionType === self::TRANSACTION_TYPE_INVENTORY_CORRECTION) { - $db = DatabaseService::GetDbConnection(); $stockId = uniqid(); - $logRow = $db->stock_log()->createRow(array( + $logRow = $this->Database->stock_log()->createRow(array( 'product_id' => $productId, 'amount' => $amount, 'best_before_date' => $bestBeforeDate, @@ -56,7 +55,7 @@ class StockService )); $logRow->save(); - $stockRow = $db->stock()->createRow(array( + $stockRow = $this->Database->stock()->createRow(array( 'product_id' => $productId, 'amount' => $amount, 'best_before_date' => $bestBeforeDate, @@ -73,14 +72,12 @@ class StockService } } - public static function ConsumeProduct(int $productId, int $amount, bool $spoiled, $transactionType) + public function ConsumeProduct(int $productId, int $amount, bool $spoiled, $transactionType) { if ($transactionType === self::TRANSACTION_TYPE_CONSUME || $transactionType === self::TRANSACTION_TYPE_PURCHASE || $transactionType === self::TRANSACTION_TYPE_INVENTORY_CORRECTION) { - $db = DatabaseService::GetDbConnection(); - - $productStockAmount = $db->stock()->where('product_id', $productId)->sum('amount'); - $potentialStockEntries = $db->stock()->where('product_id', $productId)->orderBy('best_before_date', 'ASC')->orderBy('purchased_date', 'ASC')->fetchAll(); //First expiring first, then first in first out + $productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount'); + $potentialStockEntries = $this->Database->stock()->where('product_id', $productId)->orderBy('best_before_date', 'ASC')->orderBy('purchased_date', 'ASC')->fetchAll(); //First expiring first, then first in first out if ($amount > $productStockAmount) { @@ -96,7 +93,7 @@ class StockService if ($amount >= $stockEntry->amount) //Take the whole stock entry { - $logRow = $db->stock_log()->createRow(array( + $logRow = $this->Database->stock_log()->createRow(array( 'product_id' => $stockEntry->product_id, 'amount' => $stockEntry->amount * -1, 'best_before_date' => $stockEntry->best_before_date, @@ -113,7 +110,7 @@ class StockService } else //Stock entry amount is > than needed amount -> split the stock entry resp. update the amount { - $logRow = $db->stock_log()->createRow(array( + $logRow = $this->Database->stock_log()->createRow(array( 'product_id' => $stockEntry->product_id, 'amount' => $amount * -1, 'best_before_date' => $stockEntry->best_before_date, @@ -142,36 +139,33 @@ class StockService } } - public static function InventoryProduct(int $productId, int $newAmount, string $bestBeforeDate) + public function InventoryProduct(int $productId, int $newAmount, string $bestBeforeDate) { - $db = DatabaseService::GetDbConnection(); - $productStockAmount = $db->stock()->where('product_id', $productId)->sum('amount'); + $productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount'); if ($newAmount > $productStockAmount) { $amountToAdd = $newAmount - $productStockAmount; - self::AddProduct($productId, $amountToAdd, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION); + $this->AddProduct($productId, $amountToAdd, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION); } else if ($newAmount < $productStockAmount) { $amountToRemove = $productStockAmount - $newAmount; - self::ConsumeProduct($productId, $amountToRemove, false, self::TRANSACTION_TYPE_INVENTORY_CORRECTION); + $this->ConsumeProduct($productId, $amountToRemove, false, self::TRANSACTION_TYPE_INVENTORY_CORRECTION); } return true; } - public static function AddMissingProductsToShoppingList() + public function AddMissingProductsToShoppingList() { - $db = DatabaseService::GetDbConnection(); - - $missingProducts = self::GetMissingProducts(); + $missingProducts = $this->GetMissingProducts(); foreach ($missingProducts as $missingProduct) { - $product = $db->products()->where('id', $missingProduct->id)->fetch(); + $product = $this->Database->products()->where('id', $missingProduct->id)->fetch(); $amount = ceil($missingProduct->amount_missing / $product->qu_factor_purchase_to_stock); - $alreadyExistingEntry = $db->shopping_list()->where('product_id', $missingProduct->id)->fetch(); + $alreadyExistingEntry = $this->Database->shopping_list()->where('product_id', $missingProduct->id)->fetch(); if ($alreadyExistingEntry) //Update { $alreadyExistingEntry->update(array( @@ -180,7 +174,7 @@ class StockService } else //Insert { - $shoppinglistRow = $db->shopping_list()->createRow(array( + $shoppinglistRow = $this->Database->shopping_list()->createRow(array( 'product_id' => $missingProduct->id, 'amount_autoadded' => $amount )); diff --git a/views/batteries.php b/views/batteries.blade.php similarity index 95% rename from views/batteries.php rename to views/batteries.blade.php index b46f3600..7ee8d43a 100644 --- a/views/batteries.php +++ b/views/batteries.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -44,3 +47,4 @@

+@stop diff --git a/views/batteriesoverview.php b/views/batteriesoverview.blade.php similarity index 51% rename from views/batteriesoverview.php rename to views/batteriesoverview.blade.php index aca6ca2f..7bf52d65 100644 --- a/views/batteriesoverview.php +++ b/views/batteriesoverview.blade.php @@ -1,3 +1,11 @@ + + +@extends('layout.default') + +@section('content')

Batteries overview

@@ -13,18 +21,18 @@ - + - battery_id)->name; ?> + battery_id)->name; ?> last_tracked_time; ?> - battery_id)->charge_interval_days > 0): ?> - battery_id); ?> - + battery_id)->charge_interval_days > 0): ?> + GetNextChargeTime($curentBatteryEntry->battery_id); ?> + ... @@ -36,3 +44,4 @@
+@stop diff --git a/views/batteryform.php b/views/batteryform.blade.php similarity index 95% rename from views/batteryform.php rename to views/batteryform.blade.php index d39c6729..3140250f 100644 --- a/views/batteryform.php +++ b/views/batteryform.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -31,3 +34,4 @@
+@stop diff --git a/views/batterytracking.php b/views/batterytracking.blade.php similarity index 96% rename from views/batterytracking.php rename to views/batterytracking.blade.php index 1b57ad41..e90d584a 100644 --- a/views/batterytracking.php +++ b/views/batterytracking.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

Battery tracking

@@ -40,3 +43,4 @@ Last charged:

+@stop diff --git a/views/consume.php b/views/consume.blade.php similarity index 97% rename from views/consume.php rename to views/consume.blade.php index 0340de35..10aca9fb 100644 --- a/views/consume.php +++ b/views/consume.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

Consume

@@ -43,3 +46,4 @@ Last used:

+@stop diff --git a/style.css b/views/css/grocy.css similarity index 100% rename from style.css rename to views/css/grocy.css diff --git a/views/habitform.php b/views/habitform.blade.php similarity index 97% rename from views/habitform.php rename to views/habitform.blade.php index 5a7159c1..24e5938b 100644 --- a/views/habitform.php +++ b/views/habitform.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -44,3 +47,4 @@
+@stop diff --git a/views/habits.php b/views/habits.blade.php similarity index 95% rename from views/habits.php rename to views/habits.blade.php index 1b5d2fc6..7a6127e3 100644 --- a/views/habits.php +++ b/views/habits.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -48,3 +51,4 @@

+@stop diff --git a/views/habitsoverview.php b/views/habitsoverview.blade.php similarity index 50% rename from views/habitsoverview.php rename to views/habitsoverview.blade.php index 8d342be1..75fc865e 100644 --- a/views/habitsoverview.php +++ b/views/habitsoverview.blade.php @@ -1,3 +1,11 @@ + + +@extends('layout.default') + +@section('content')

Habits overview

@@ -13,14 +21,14 @@ - + - habit_id)->name; ?> + habit_id)->name; ?> - habit_id)->period_type === HabitsService::HABIT_TYPE_DYNAMIC_REGULAR): ?> - habit_id); ?> - + habit_id)->period_type === HabitsService::HABIT_TYPE_DYNAMIC_REGULAR): ?> + GetNextHabitTime($curentHabitEntry->habit_id); ?> + ... @@ -36,3 +44,4 @@
+@stop diff --git a/views/habittracking.php b/views/habittracking.blade.php similarity index 96% rename from views/habittracking.php rename to views/habittracking.blade.php index 3e8a0038..7d3ec587 100644 --- a/views/habittracking.php +++ b/views/habittracking.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

Habit tracking

@@ -40,3 +43,4 @@ Last tracked:

+@stop diff --git a/grocy.png b/views/img/grocy.png similarity index 100% rename from grocy.png rename to views/img/grocy.png diff --git a/views/inventory.php b/views/inventory.blade.php similarity index 98% rename from views/inventory.php rename to views/inventory.blade.php index a9e75567..70402b9b 100644 --- a/views/inventory.php +++ b/views/inventory.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

Inventory

@@ -50,3 +53,4 @@ Last used:

+@stop diff --git a/grocy.js b/views/js/grocy.js similarity index 100% rename from grocy.js rename to views/js/grocy.js diff --git a/views/layout/default.php b/views/layout/default.blade.php similarity index 76% rename from views/layout/default.php rename to views/layout/default.blade.php index c9776763..3d72ce30 100644 --- a/views/layout/default.php +++ b/views/layout/default.blade.php @@ -1,3 +1,10 @@ + + @@ -9,24 +16,24 @@ - + <?php echo $title; ?> | grocy - - - - - - - - - - - + + + + + + + + + + + - - + + @@ -116,7 +123,7 @@
Created with passion since 2017
- Version + Version GetInstalledVersion(); ?>
Life runs on code
@@ -193,7 +200,7 @@
Created with passion since 2017
- Version + Version GetInstalledVersion(); ?>
Life runs on code
@@ -204,30 +211,31 @@ - - + + @section('content') + @show - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + diff --git a/views/locationform.php b/views/locationform.blade.php similarity index 94% rename from views/locationform.php rename to views/locationform.blade.php index 96de08cf..3464e8fb 100644 --- a/views/locationform.php +++ b/views/locationform.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -26,3 +29,4 @@
+@stop diff --git a/views/locations.php b/views/locations.blade.php similarity index 95% rename from views/locations.php rename to views/locations.blade.php index 1f4fc107..2ced76a8 100644 --- a/views/locations.php +++ b/views/locations.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -40,3 +43,4 @@

+@stop diff --git a/views/login.php b/views/login.blade.php similarity index 92% rename from views/login.php rename to views/login.blade.php index acde3e11..941d18b7 100644 --- a/views/login.php +++ b/views/login.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

Login

@@ -21,3 +24,4 @@
+@stop diff --git a/views/productform.php b/views/productform.blade.php similarity index 98% rename from views/productform.php rename to views/productform.blade.php index a7341f42..5855ea03 100644 --- a/views/productform.php +++ b/views/productform.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -81,3 +84,4 @@
+@stop diff --git a/views/products.php b/views/products.blade.php similarity index 79% rename from views/products.php rename to views/products.blade.php index 93fc7cab..cc541f41 100644 --- a/views/products.php +++ b/views/products.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -36,16 +39,16 @@ name; ?> - location_id)->name; ?> + location_id)->name; ?> min_stock_amount; ?> - qu_id_purchase)->name; ?> + qu_id_purchase)->name; ?> - qu_id_stock)->name; ?> + qu_id_stock)->name; ?> qu_factor_purchase_to_stock; ?> @@ -60,3 +63,4 @@

+@stop diff --git a/views/purchase.php b/views/purchase.blade.php similarity index 98% rename from views/purchase.php rename to views/purchase.blade.php index 70943719..519a887d 100644 --- a/views/purchase.php +++ b/views/purchase.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

Purchase

@@ -49,3 +52,4 @@ Last used:

+@stop diff --git a/views/quantityunitform.php b/views/quantityunitform.blade.php similarity index 94% rename from views/quantityunitform.php rename to views/quantityunitform.blade.php index 52a8dc86..1b11a62c 100644 --- a/views/quantityunitform.php +++ b/views/quantityunitform.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -26,3 +29,4 @@
+@stop diff --git a/views/quantityunits.php b/views/quantityunits.blade.php similarity index 95% rename from views/quantityunits.php rename to views/quantityunits.blade.php index 7b9350c0..41fde780 100644 --- a/views/quantityunits.php +++ b/views/quantityunits.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -40,3 +43,4 @@

+@stop diff --git a/views/shoppinglist.php b/views/shoppinglist.blade.php similarity index 75% rename from views/shoppinglist.php rename to views/shoppinglist.blade.php index fa85fc84..0fc1b0bc 100644 --- a/views/shoppinglist.php +++ b/views/shoppinglist.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -31,10 +34,10 @@ - product_id)) echo GrocyPhpHelper::FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name . '
'; ?>note; ?> + product_id)) echo FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name . '
'; ?>note; ?> - amount + $listItem->amount_autoadded; if (!empty($listItem->product_id)) echo ' ' . GrocyPhpHelper::FindObjectInArrayByPropertyValue($quantityunits, 'id', GrocyPhpHelper::FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name; ?> + amount + $listItem->amount_autoadded; if (!empty($listItem->product_id)) echo ' ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name; ?> @@ -43,3 +46,4 @@

+@stop diff --git a/views/shoppinglistform.php b/views/shoppinglistform.blade.php similarity index 98% rename from views/shoppinglistform.php rename to views/shoppinglistform.blade.php index 93e6a512..d1e71d94 100644 --- a/views/shoppinglistform.php +++ b/views/shoppinglistform.blade.php @@ -1,3 +1,6 @@ +@extends('layout.default') + +@section('content')

@@ -48,3 +51,4 @@ Last used:

+@stop diff --git a/views/stockoverview.php b/views/stockoverview.blade.php similarity index 56% rename from views/stockoverview.php rename to views/stockoverview.blade.php index 6df144a5..fe0da5b6 100644 --- a/views/stockoverview.php +++ b/views/stockoverview.blade.php @@ -1,11 +1,14 @@ +@extends('layout.default') + +@section('content')
-

Stock overview products with units in stock

+

Stock overview products with units in stock

-

products expiring within the next 5 days

-

products are already expired

+

products expiring within the next 5 days

+

products are already expired

products are below defined min. stock amount

@@ -23,12 +26,12 @@ - + - product_id)->name; ?> + product_id)->name; ?> - amount . ' ' . GrocyPhpHelper::FindObjectInArrayByPropertyValue($quantityunits, 'id', GrocyPhpHelper::FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name; ?> + amount . ' ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name; ?> best_before_date; ?> @@ -41,3 +44,4 @@
+@stop diff --git a/views/viewjs/habittracking.js b/views/viewjs/habittracking.js index b3fca302..135f034f 100644 --- a/views/viewjs/habittracking.js +++ b/views/viewjs/habittracking.js @@ -7,7 +7,7 @@ Grocy.FetchJson('/api/habits/get-habit-details/' + jsonForm.habit_id, function (habitDetails) { - Grocy.FetchJson('/api/habits/track-habit/' + jsonForm.habit_id + '?tracked_time=' + $('#tracked_time').val(), + Grocy.FetchJson('/api/habits/track-habit-exeuction/' + jsonForm.habit_id + '?tracked_time=' + $('#tracked_time').val(), function(result) { toastr.success('Tracked execution of habit ' + habitDetails.habit.name + ' on ' + $('#tracked_time').val());