diff --git a/assets/css/app.css b/assets/css/app.css index 7d624435..296d0bd5 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -811,7 +811,7 @@ div.dataTables_wrapper div.dataTables_info { padding: 10px 10px; margin: 0 0 10px; font-size: 17.5px; - border-left: 5px solid #eee; + border-left: 5px solid #aaa; } .darkmode-layer { diff --git a/assets/js/app.js b/assets/js/app.js index 24f55eef..73d6b603 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -91,6 +91,11 @@ require('./jquery.tristate.js'); require('darkmode-js'); +//Equation rendering +require('katex'); +window.renderMathInElement = require('katex/contrib/auto-render/auto-render').default; +import 'katex/dist/katex.css'; + window.ClipboardJS = require('clipboard'); window.QRCode = require('qrcode'); diff --git a/assets/ts_src/event_listeners.ts b/assets/ts_src/event_listeners.ts index 503ac074..99a0a032 100644 --- a/assets/ts_src/event_listeners.ts +++ b/assets/ts_src/event_listeners.ts @@ -465,6 +465,19 @@ $(document).on("ajaxUI:start", function () { //Bootstrapify objects $('table', this).addClass('table table-hover table-striped table-bordered'); }); + + //Latex rendering have to be done after markdown parsing + $('.latex').each(function(index, element) { + //@ts-ignore + window.renderMathInElement(element, { + delimiters: [ + {left: "$$", right: "$$", display: true}, + {left: "$", right: "$", display: false}, + {left: "\\(", right: "\\)", display: false}, + {left: "\\[", right: "\\]", display: true} + ] + }); + }); } //Configure markdown @@ -552,6 +565,7 @@ $(document).on("ajaxUI:reload", function() { }) }); + //Need for proper body padding, with every navbar height $(window).resize(function () { let height : number = $('#navbar').height() + 10; diff --git a/composer.json b/composer.json index 52e3969c..fe3f211a 100644 --- a/composer.json +++ b/composer.json @@ -69,7 +69,7 @@ "symfony/maker-bundle": "^1.13", "symfony/profiler-pack": "*", "symfony/test-pack": "^1.0", - "symplify/easy-coding-standard": "^7.1", + "symplify/easy-coding-standard": "7.2.3", "vimeo/psalm": "^3.5" }, "config": { @@ -91,14 +91,6 @@ "App\\Tests\\": "tests/" } }, - "replace": { - "paragonie/random_compat": "2.*", - "symfony/polyfill-ctype": "*", - "symfony/polyfill-iconv": "*", - "symfony/polyfill-php71": "*", - "symfony/polyfill-php70": "*", - "symfony/polyfill-php56": "*" - }, "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd", diff --git a/composer.lock b/composer.lock index f6cf156e..ab403135 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6ebc8e9705e901be6f00f9f6418cf900", + "content-hash": "fd11975fb4135f47bdb119fec531a868", "packages": [ { "name": "beberlei/assert", @@ -1022,16 +1022,16 @@ }, { "name": "doctrine/orm", - "version": "v2.7.1", + "version": "v2.7.2", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "445796af0e873d9bd04f2502d322a7d5009b6846" + "reference": "dafe298ce5d0b995ebe1746670704c0a35868a6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/445796af0e873d9bd04f2502d322a7d5009b6846", - "reference": "445796af0e873d9bd04f2502d322a7d5009b6846", + "url": "https://api.github.com/repos/doctrine/orm/zipball/dafe298ce5d0b995ebe1746670704c0a35868a6a", + "reference": "dafe298ce5d0b995ebe1746670704c0a35868a6a", "shasum": "" }, "require": { @@ -1102,20 +1102,20 @@ "database", "orm" ], - "time": "2020-02-15T14:35:56+00:00" + "time": "2020-03-19T06:41:02+00:00" }, { "name": "doctrine/persistence", - "version": "1.3.6", + "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "5dd3ac5eebef2d0b074daa4440bb18f93132dee4" + "reference": "0af483f91bada1c9ded6c2cfd26ab7d5ab2094e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/5dd3ac5eebef2d0b074daa4440bb18f93132dee4", - "reference": "5dd3ac5eebef2d0b074daa4440bb18f93132dee4", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/0af483f91bada1c9ded6c2cfd26ab7d5ab2094e0", + "reference": "0af483f91bada1c9ded6c2cfd26ab7d5ab2094e0", "shasum": "" }, "require": { @@ -1123,7 +1123,7 @@ "doctrine/cache": "^1.0", "doctrine/collections": "^1.0", "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.1", + "doctrine/reflection": "^1.2", "php": "^7.1" }, "conflict": { @@ -1185,20 +1185,20 @@ "orm", "persistence" ], - "time": "2020-01-16T22:06:23+00:00" + "time": "2020-03-21T15:13:52+00:00" }, { "name": "doctrine/reflection", - "version": "v1.1.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/reflection.git", - "reference": "bc420ead87fdfe08c03ecc3549db603a45b06d4c" + "reference": "55e71912dfcd824b2fdd16f2d9afe15684cfce79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/reflection/zipball/bc420ead87fdfe08c03ecc3549db603a45b06d4c", - "reference": "bc420ead87fdfe08c03ecc3549db603a45b06d4c", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/55e71912dfcd824b2fdd16f2d9afe15684cfce79", + "reference": "55e71912dfcd824b2fdd16f2d9afe15684cfce79", "shasum": "" }, "require": { @@ -1219,7 +1219,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -1263,7 +1263,7 @@ "reflection", "static" ], - "time": "2020-01-08T19:53:19+00:00" + "time": "2020-03-27T11:06:43+00:00" }, { "name": "egulias/email-validator", @@ -2573,6 +2573,51 @@ ], "time": "2019-11-06T19:20:29+00:00" }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-02T15:55:56+00:00" + }, { "name": "php-http/discovery", "version": "1.7.4", @@ -3066,41 +3111,38 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.4", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", - "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", - "webmozart/assert": "^1.0" + "ext-filter": "^7.1", + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1" }, "require-dev": { - "doctrine/instantiator": "^1.0.5", - "mockery/mockery": "^1.0", - "phpdocumentor/type-resolver": "0.4.*", - "phpunit/phpunit": "^6.4" + "doctrine/instantiator": "^1", + "mockery/mockery": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -3111,10 +3153,14 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-12-28T18:55:12+00:00" + "time": "2020-02-22T12:28:44+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -3459,16 +3505,16 @@ }, { "name": "psr/log", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", "shasum": "" }, "require": { @@ -3502,7 +3548,7 @@ "psr", "psr-3" ], - "time": "2019-11-01T11:05:21+00:00" + "time": "2020-03-23T09:12:05+00:00" }, { "name": "psr/simple-cache", @@ -4066,16 +4112,16 @@ }, { "name": "symfony/asset", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "5c1afa35f0ff6a4fa5d037b4a5ef1bf60513e65b" + "reference": "eb7c4595302888ee82b78acb90cc79cf4c3f213e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/5c1afa35f0ff6a4fa5d037b4a5ef1bf60513e65b", - "reference": "5c1afa35f0ff6a4fa5d037b4a5ef1bf60513e65b", + "url": "https://api.github.com/repos/symfony/asset/zipball/eb7c4595302888ee82b78acb90cc79cf4c3f213e", + "reference": "eb7c4595302888ee82b78acb90cc79cf4c3f213e", "shasum": "" }, "require": { @@ -4118,20 +4164,20 @@ ], "description": "Symfony Asset Component", "homepage": "https://symfony.com", - "time": "2020-02-24T13:10:00+00:00" + "time": "2020-03-15T10:05:03+00:00" }, { "name": "symfony/cache", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "28511cbd8c760a19f4b4b70961d2cd957733b3d9" + "reference": "f20dcf48ecee66ab5ad7ccf4b3b55392b660c3d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/28511cbd8c760a19f4b4b70961d2cd957733b3d9", - "reference": "28511cbd8c760a19f4b4b70961d2cd957733b3d9", + "url": "https://api.github.com/repos/symfony/cache/zipball/f20dcf48ecee66ab5ad7ccf4b3b55392b660c3d9", + "reference": "f20dcf48ecee66ab5ad7ccf4b3b55392b660c3d9", "shasum": "" }, "require": { @@ -4197,7 +4243,7 @@ "caching", "psr6" ], - "time": "2020-02-20T16:31:44+00:00" + "time": "2020-03-17T19:51:46+00:00" }, { "name": "symfony/cache-contracts", @@ -4259,16 +4305,16 @@ }, { "name": "symfony/config", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "cbfef5ae91ccd3b06621c18d58cd355c68c87ae9" + "reference": "235e5afffd3a1a1b0dd0221973cbf670bc3be1d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/cbfef5ae91ccd3b06621c18d58cd355c68c87ae9", - "reference": "cbfef5ae91ccd3b06621c18d58cd355c68c87ae9", + "url": "https://api.github.com/repos/symfony/config/zipball/235e5afffd3a1a1b0dd0221973cbf670bc3be1d4", + "reference": "235e5afffd3a1a1b0dd0221973cbf670bc3be1d4", "shasum": "" }, "require": { @@ -4319,20 +4365,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2020-02-04T09:32:40+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/console", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "4fa15ae7be74e53f6ec8c83ed403b97e23b665e9" + "reference": "20bc0c1068565103075359f5ce9e0639b36f92d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/4fa15ae7be74e53f6ec8c83ed403b97e23b665e9", - "reference": "4fa15ae7be74e53f6ec8c83ed403b97e23b665e9", + "url": "https://api.github.com/repos/symfony/console/zipball/20bc0c1068565103075359f5ce9e0639b36f92d1", + "reference": "20bc0c1068565103075359f5ce9e0639b36f92d1", "shasum": "" }, "require": { @@ -4395,7 +4441,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2020-02-24T13:10:00+00:00" + "time": "2020-03-16T08:56:54+00:00" }, { "name": "symfony/contracts", @@ -4470,16 +4516,16 @@ }, { "name": "symfony/css-selector", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "d0a6dd288fa8848dcc3d1f58b94de6a7cc5d2d22" + "reference": "402251c6fd69806a70a2b0e1426d16f8487f0f9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/d0a6dd288fa8848dcc3d1f58b94de6a7cc5d2d22", - "reference": "d0a6dd288fa8848dcc3d1f58b94de6a7cc5d2d22", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/402251c6fd69806a70a2b0e1426d16f8487f0f9a", + "reference": "402251c6fd69806a70a2b0e1426d16f8487f0f9a", "shasum": "" }, "require": { @@ -4519,20 +4565,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2020-02-04T09:01:01+00:00" + "time": "2020-03-16T08:56:54+00:00" }, { "name": "symfony/debug", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "a980d87a659648980d89193fd8b7a7ca89d97d21" + "reference": "f0ae2b4150254b8b4ac578f33d910b9c116618f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/a980d87a659648980d89193fd8b7a7ca89d97d21", - "reference": "a980d87a659648980d89193fd8b7a7ca89d97d21", + "url": "https://api.github.com/repos/symfony/debug/zipball/f0ae2b4150254b8b4ac578f33d910b9c116618f0", + "reference": "f0ae2b4150254b8b4ac578f33d910b9c116618f0", "shasum": "" }, "require": { @@ -4575,20 +4621,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2020-02-23T14:41:43+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "ebb2e882e8c9e2eb990aa61ddcd389848466e342" + "reference": "b4242fc7f18c8bf5427f84d5afe2131c9b323a04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ebb2e882e8c9e2eb990aa61ddcd389848466e342", - "reference": "ebb2e882e8c9e2eb990aa61ddcd389848466e342", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b4242fc7f18c8bf5427f84d5afe2131c9b323a04", + "reference": "b4242fc7f18c8bf5427f84d5afe2131c9b323a04", "shasum": "" }, "require": { @@ -4648,20 +4694,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2020-02-29T09:50:10+00:00" + "time": "2020-03-18T07:51:32+00:00" }, { "name": "symfony/doctrine-bridge", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "1b4564758fe91f5d53dfbdfd9007d15e43fa465f" + "reference": "57a825089b7a9851fe552b08ed83f7625352c9ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/1b4564758fe91f5d53dfbdfd9007d15e43fa465f", - "reference": "1b4564758fe91f5d53dfbdfd9007d15e43fa465f", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/57a825089b7a9851fe552b08ed83f7625352c9ab", + "reference": "57a825089b7a9851fe552b08ed83f7625352c9ab", "shasum": "" }, "require": { @@ -4742,11 +4788,11 @@ ], "description": "Symfony Doctrine Bridge", "homepage": "https://symfony.com", - "time": "2020-02-24T17:16:47+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/dotenv", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", @@ -4803,16 +4849,16 @@ }, { "name": "symfony/error-handler", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "89aa4b9ac6f1f35171b8621b24f60477312085be" + "reference": "3727fe33f578a547e0acecd4034401c99c8ce013" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/89aa4b9ac6f1f35171b8621b24f60477312085be", - "reference": "89aa4b9ac6f1f35171b8621b24f60477312085be", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/3727fe33f578a547e0acecd4034401c99c8ce013", + "reference": "3727fe33f578a547e0acecd4034401c99c8ce013", "shasum": "" }, "require": { @@ -4855,20 +4901,20 @@ ], "description": "Symfony ErrorHandler Component", "homepage": "https://symfony.com", - "time": "2020-02-26T11:45:31+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "4ad8e149799d3128621a3a1f70e92b9897a8930d" + "reference": "cf57788d1ca64ee7e689698dc0295d25c9fe3780" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4ad8e149799d3128621a3a1f70e92b9897a8930d", - "reference": "4ad8e149799d3128621a3a1f70e92b9897a8930d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/cf57788d1ca64ee7e689698dc0295d25c9fe3780", + "reference": "cf57788d1ca64ee7e689698dc0295d25c9fe3780", "shasum": "" }, "require": { @@ -4925,7 +4971,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2020-02-04T09:32:40+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -4987,16 +5033,16 @@ }, { "name": "symfony/expression-language", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "70649e0abcac6ad1109f6243886bca0445e278b9" + "reference": "208ceff59b98b8b38bd4426df49be697a8582240" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/70649e0abcac6ad1109f6243886bca0445e278b9", - "reference": "70649e0abcac6ad1109f6243886bca0445e278b9", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/208ceff59b98b8b38bd4426df49be697a8582240", + "reference": "208ceff59b98b8b38bd4426df49be697a8582240", "shasum": "" }, "require": { @@ -5034,20 +5080,20 @@ ], "description": "Symfony ExpressionLanguage Component", "homepage": "https://symfony.com", - "time": "2020-02-24T13:10:00+00:00" + "time": "2020-03-15T10:05:03+00:00" }, { "name": "symfony/filesystem", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "266c9540b475f26122b61ef8b23dd9198f5d1cfd" + "reference": "6d4fdf28187250f671c1edc9cf921ebfb7fe3809" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/266c9540b475f26122b61ef8b23dd9198f5d1cfd", - "reference": "266c9540b475f26122b61ef8b23dd9198f5d1cfd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/6d4fdf28187250f671c1edc9cf921ebfb7fe3809", + "reference": "6d4fdf28187250f671c1edc9cf921ebfb7fe3809", "shasum": "" }, "require": { @@ -5084,11 +5130,11 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2020-01-21T08:20:44+00:00" + "time": "2020-03-16T08:56:54+00:00" }, { "name": "symfony/finder", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -5186,16 +5232,16 @@ }, { "name": "symfony/form", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "677927dad3b9f93117db62fc1df4de82027dc282" + "reference": "3a287b3b5ecd1a534af62b8b530f181e636e72c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/677927dad3b9f93117db62fc1df4de82027dc282", - "reference": "677927dad3b9f93117db62fc1df4de82027dc282", + "url": "https://api.github.com/repos/symfony/form/zipball/3a287b3b5ecd1a534af62b8b530f181e636e72c9", + "reference": "3a287b3b5ecd1a534af62b8b530f181e636e72c9", "shasum": "" }, "require": { @@ -5266,20 +5312,20 @@ ], "description": "Symfony Form Component", "homepage": "https://symfony.com", - "time": "2020-02-29T10:05:28+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/framework-bundle", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "df5528926e6e1954975f3d73a91f029ba3d9c76b" + "reference": "f0ef822516463bef83625e7d33f8e047093f310e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/df5528926e6e1954975f3d73a91f029ba3d9c76b", - "reference": "df5528926e6e1954975f3d73a91f029ba3d9c76b", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/f0ef822516463bef83625e7d33f8e047093f310e", + "reference": "f0ef822516463bef83625e7d33f8e047093f310e", "shasum": "" }, "require": { @@ -5397,20 +5443,20 @@ ], "description": "Symfony FrameworkBundle", "homepage": "https://symfony.com", - "time": "2020-02-28T13:15:16+00:00" + "time": "2020-03-19T20:46:03+00:00" }, { "name": "symfony/http-client", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "65ccb6ca4a5a7bf7c244b8a28195fa188521b3d2" + "reference": "d24b4bbd62e73dc274cd7c4258e6d7a70167cb31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/65ccb6ca4a5a7bf7c244b8a28195fa188521b3d2", - "reference": "65ccb6ca4a5a7bf7c244b8a28195fa188521b3d2", + "url": "https://api.github.com/repos/symfony/http-client/zipball/d24b4bbd62e73dc274cd7c4258e6d7a70167cb31", + "reference": "d24b4bbd62e73dc274cd7c4258e6d7a70167cb31", "shasum": "" }, "require": { @@ -5465,7 +5511,7 @@ ], "description": "Symfony HttpClient component", "homepage": "https://symfony.com", - "time": "2020-02-25T13:55:11+00:00" + "time": "2020-03-16T16:13:17+00:00" }, { "name": "symfony/http-client-contracts", @@ -5526,16 +5572,16 @@ }, { "name": "symfony/http-foundation", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "7e41b4fcad4619535f45f8bfa7744c4f384e1648" + "reference": "0a3b7711229f816a06fac805f4ed4a8f4641c719" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7e41b4fcad4619535f45f8bfa7744c4f384e1648", - "reference": "7e41b4fcad4619535f45f8bfa7744c4f384e1648", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0a3b7711229f816a06fac805f4ed4a8f4641c719", + "reference": "0a3b7711229f816a06fac805f4ed4a8f4641c719", "shasum": "" }, "require": { @@ -5577,20 +5623,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2020-02-13T19:40:01+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "8c8734486dada83a6041ab744709bdc1651a8462" + "reference": "02ee1d0d616b031fb48a1c9c3e5dc092dd7e448d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8c8734486dada83a6041ab744709bdc1651a8462", - "reference": "8c8734486dada83a6041ab744709bdc1651a8462", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/02ee1d0d616b031fb48a1c9c3e5dc092dd7e448d", + "reference": "02ee1d0d616b031fb48a1c9c3e5dc092dd7e448d", "shasum": "" }, "require": { @@ -5667,11 +5713,11 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2020-02-29T10:31:38+00:00" + "time": "2020-03-27T08:32:28+00:00" }, { "name": "symfony/inflector", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/inflector.git", @@ -5729,16 +5775,16 @@ }, { "name": "symfony/intl", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "f675f139e20b9e0ff05bac662c081fe9ef7b2f88" + "reference": "345aa50278b9d02a9cc75a5f19596c21646aa8d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/f675f139e20b9e0ff05bac662c081fe9ef7b2f88", - "reference": "f675f139e20b9e0ff05bac662c081fe9ef7b2f88", + "url": "https://api.github.com/repos/symfony/intl/zipball/345aa50278b9d02a9cc75a5f19596c21646aa8d8", + "reference": "345aa50278b9d02a9cc75a5f19596c21646aa8d8", "shasum": "" }, "require": { @@ -5800,20 +5846,20 @@ "l10n", "localization" ], - "time": "2020-02-04T09:32:40+00:00" + "time": "2020-03-16T16:04:53+00:00" }, { "name": "symfony/mailer", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "f79a2cc091c14c2d78cade2f8b772f568fb63c43" + "reference": "b7c9b94a8bda86ca0499482ad4e5fb824aede8d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/f79a2cc091c14c2d78cade2f8b772f568fb63c43", - "reference": "f79a2cc091c14c2d78cade2f8b772f568fb63c43", + "url": "https://api.github.com/repos/symfony/mailer/zipball/b7c9b94a8bda86ca0499482ad4e5fb824aede8d8", + "reference": "b7c9b94a8bda86ca0499482ad4e5fb824aede8d8", "shasum": "" }, "require": { @@ -5868,20 +5914,20 @@ ], "description": "Symfony Mailer Component", "homepage": "https://symfony.com", - "time": "2020-02-07T16:56:37+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/mime", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "304db017bafd71c122cd5223a9ac2d03dc24da32" + "reference": "f6be9d809d805ab5bdb12f2d5843ba2c78533c7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/304db017bafd71c122cd5223a9ac2d03dc24da32", - "reference": "304db017bafd71c122cd5223a9ac2d03dc24da32", + "url": "https://api.github.com/repos/symfony/mime/zipball/f6be9d809d805ab5bdb12f2d5843ba2c78533c7e", + "reference": "f6be9d809d805ab5bdb12f2d5843ba2c78533c7e", "shasum": "" }, "require": { @@ -5930,20 +5976,20 @@ "mime", "mime-type" ], - "time": "2020-02-04T09:32:40+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/monolog-bridge", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "b14ee2f0488b3ad879fd000bc3dcce1cd2f6cfff" + "reference": "3386058348b9df26122cc42abc60201c59e8dda6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/b14ee2f0488b3ad879fd000bc3dcce1cd2f6cfff", - "reference": "b14ee2f0488b3ad879fd000bc3dcce1cd2f6cfff", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/3386058348b9df26122cc42abc60201c59e8dda6", + "reference": "3386058348b9df26122cc42abc60201c59e8dda6", "shasum": "" }, "require": { @@ -5997,7 +6043,7 @@ ], "description": "Symfony Monolog Bridge", "homepage": "https://symfony.com", - "time": "2020-02-04T09:32:40+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/monolog-bundle", @@ -6064,7 +6110,7 @@ }, { "name": "symfony/options-resolver", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", @@ -6144,17 +6190,75 @@ "time": "2020-02-10T18:03:48+00:00" }, { - "name": "symfony/polyfill-intl-icu", - "version": "v1.14.0", + "name": "symfony/polyfill-ctype", + "version": "v1.15.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "727b3bb5bfa7ca9eeb86416784cf1c08a6289b86" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/727b3bb5bfa7ca9eeb86416784cf1c08a6289b86", - "reference": "727b3bb5bfa7ca9eeb86416784cf1c08a6289b86", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", + "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2020-02-27T09:26:54+00:00" + }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "9c281272735eb66476e0fa7381e03fb0d4b60197" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/9c281272735eb66476e0fa7381e03fb0d4b60197", + "reference": "9c281272735eb66476e0fa7381e03fb0d4b60197", "shasum": "" }, "require": { @@ -6167,7 +6271,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -6199,20 +6303,20 @@ "portable", "shim" ], - "time": "2020-01-13T11:15:53+00:00" + "time": "2020-02-27T09:26:54+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.14.0", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "6842f1a39cf7d580655688069a03dd7cd83d244a" + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6842f1a39cf7d580655688069a03dd7cd83d244a", - "reference": "6842f1a39cf7d580655688069a03dd7cd83d244a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", "shasum": "" }, "require": { @@ -6226,7 +6330,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -6261,20 +6365,20 @@ "portable", "shim" ], - "time": "2020-01-17T12:01:36+00:00" + "time": "2020-03-09T19:04:49+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.14.0", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2" + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/34094cfa9abe1f0f14f48f490772db7a775559f2", - "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", "shasum": "" }, "require": { @@ -6286,7 +6390,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -6320,20 +6424,20 @@ "portable", "shim" ], - "time": "2020-01-13T11:15:53+00:00" + "time": "2020-03-09T19:04:49+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.14.0", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf" + "reference": "37b0976c78b94856543260ce09b460a7bc852747" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", - "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", + "reference": "37b0976c78b94856543260ce09b460a7bc852747", "shasum": "" }, "require": { @@ -6342,7 +6446,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -6375,20 +6479,20 @@ "portable", "shim" ], - "time": "2020-01-13T11:15:53+00:00" + "time": "2020-02-27T09:26:54+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.14.0", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "5e66a0fa1070bf46bec4bea7962d285108edd675" + "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/5e66a0fa1070bf46bec4bea7962d285108edd675", - "reference": "5e66a0fa1070bf46bec4bea7962d285108edd675", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", + "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", "shasum": "" }, "require": { @@ -6397,7 +6501,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -6433,20 +6537,20 @@ "portable", "shim" ], - "time": "2020-01-13T11:15:53+00:00" + "time": "2020-02-27T09:26:54+00:00" }, { "name": "symfony/process", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "bf9166bac906c9e69fb7a11d94875e7ced97bcd7" + "reference": "b9863d0f7b684d7c4c13e665325b5ff047de0aee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/bf9166bac906c9e69fb7a11d94875e7ced97bcd7", - "reference": "bf9166bac906c9e69fb7a11d94875e7ced97bcd7", + "url": "https://api.github.com/repos/symfony/process/zipball/b9863d0f7b684d7c4c13e665325b5ff047de0aee", + "reference": "b9863d0f7b684d7c4c13e665325b5ff047de0aee", "shasum": "" }, "require": { @@ -6482,20 +6586,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2020-02-07T20:06:44+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/property-access", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "090b4bc92ded1ec512f7e2ed1691210769dffdb3" + "reference": "a35574237897b511e9a30a7bd161d49ec8999661" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/090b4bc92ded1ec512f7e2ed1691210769dffdb3", - "reference": "090b4bc92ded1ec512f7e2ed1691210769dffdb3", + "url": "https://api.github.com/repos/symfony/property-access/zipball/a35574237897b511e9a30a7bd161d49ec8999661", + "reference": "a35574237897b511e9a30a7bd161d49ec8999661", "shasum": "" }, "require": { @@ -6549,11 +6653,11 @@ "property path", "reflection" ], - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-16T16:04:53+00:00" }, { "name": "symfony/property-info", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", @@ -6629,16 +6733,16 @@ }, { "name": "symfony/routing", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "4124d621d0e445732520037f888a0456951bde8c" + "reference": "bd92312650007d29bbabf00795c591b975a0b9a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/4124d621d0e445732520037f888a0456951bde8c", - "reference": "4124d621d0e445732520037f888a0456951bde8c", + "url": "https://api.github.com/repos/symfony/routing/zipball/bd92312650007d29bbabf00795c591b975a0b9a6", + "reference": "bd92312650007d29bbabf00795c591b975a0b9a6", "shasum": "" }, "require": { @@ -6701,20 +6805,20 @@ "uri", "url" ], - "time": "2020-02-25T12:41:09+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/security-bundle", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "21c4270b37f76e6c3c22f92597f397593ed1c9db" + "reference": "3f6e6903960e488dd20b884f13a2ad1b8dff0ac6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/21c4270b37f76e6c3c22f92597f397593ed1c9db", - "reference": "21c4270b37f76e6c3c22f92597f397593ed1c9db", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/3f6e6903960e488dd20b884f13a2ad1b8dff0ac6", + "reference": "3f6e6903960e488dd20b884f13a2ad1b8dff0ac6", "shasum": "" }, "require": { @@ -6784,20 +6888,20 @@ ], "description": "Symfony SecurityBundle", "homepage": "https://symfony.com", - "time": "2020-02-26T10:27:30+00:00" + "time": "2020-03-17T19:48:51+00:00" }, { "name": "symfony/security-core", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "6251c8e432640106e6f2f045ac3b365f1af36d44" + "reference": "77ba37225ddbcc6b34d94a885ad613210d52dd02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/6251c8e432640106e6f2f045ac3b365f1af36d44", - "reference": "6251c8e432640106e6f2f045ac3b365f1af36d44", + "url": "https://api.github.com/repos/symfony/security-core/zipball/77ba37225ddbcc6b34d94a885ad613210d52dd02", + "reference": "77ba37225ddbcc6b34d94a885ad613210d52dd02", "shasum": "" }, "require": { @@ -6857,11 +6961,11 @@ ], "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", - "time": "2020-02-24T13:10:00+00:00" + "time": "2020-03-20T15:02:37+00:00" }, { "name": "symfony/security-csrf", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", @@ -6920,16 +7024,16 @@ }, { "name": "symfony/security-guard", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/security-guard.git", - "reference": "7dcc99e3fa89387a1914496118b4aa0927f282e1" + "reference": "bf61166227b28b642055364e6feaaec7d1199dc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-guard/zipball/7dcc99e3fa89387a1914496118b4aa0927f282e1", - "reference": "7dcc99e3fa89387a1914496118b4aa0927f282e1", + "url": "https://api.github.com/repos/symfony/security-guard/zipball/bf61166227b28b642055364e6feaaec7d1199dc8", + "reference": "bf61166227b28b642055364e6feaaec7d1199dc8", "shasum": "" }, "require": { @@ -6970,20 +7074,20 @@ ], "description": "Symfony Security Component - Guard", "homepage": "https://symfony.com", - "time": "2020-02-24T13:10:00+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/security-http", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "c38fe1cd72360dfaa39c82fcb9e4666b041f8834" + "reference": "dcf596a85d7759a1b82ab844a51a191a409ee306" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/c38fe1cd72360dfaa39c82fcb9e4666b041f8834", - "reference": "c38fe1cd72360dfaa39c82fcb9e4666b041f8834", + "url": "https://api.github.com/repos/symfony/security-http/zipball/dcf596a85d7759a1b82ab844a51a191a409ee306", + "reference": "dcf596a85d7759a1b82ab844a51a191a409ee306", "shasum": "" }, "require": { @@ -7036,20 +7140,20 @@ ], "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", - "time": "2020-02-26T10:27:30+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/serializer", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "bc76d242fea5ff09c3ca34c90f3bb9341a2470a4" + "reference": "f1b7a1d95537d6e3c1e141dddef9831165e1b822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/bc76d242fea5ff09c3ca34c90f3bb9341a2470a4", - "reference": "bc76d242fea5ff09c3ca34c90f3bb9341a2470a4", + "url": "https://api.github.com/repos/symfony/serializer/zipball/f1b7a1d95537d6e3c1e141dddef9831165e1b822", + "reference": "f1b7a1d95537d6e3c1e141dddef9831165e1b822", "shasum": "" }, "require": { @@ -7118,26 +7222,26 @@ ], "description": "Symfony Serializer Component", "homepage": "https://symfony.com", - "time": "2020-02-29T10:05:28+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/serializer-pack", - "version": "v1.0.2", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/symfony/serializer-pack.git", - "reference": "c5f18ba4ff989a42d7d140b7f85406e77cd8c4b2" + "reference": "9bbce72dcad0cca797b678d3bfb764cf923ab28a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer-pack/zipball/c5f18ba4ff989a42d7d140b7f85406e77cd8c4b2", - "reference": "c5f18ba4ff989a42d7d140b7f85406e77cd8c4b2", + "url": "https://api.github.com/repos/symfony/serializer-pack/zipball/9bbce72dcad0cca797b678d3bfb764cf923ab28a", + "reference": "9bbce72dcad0cca797b678d3bfb764cf923ab28a", "shasum": "" }, "require": { "doctrine/annotations": "^1.0", "php": "^7.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "phpdocumentor/reflection-docblock": "*", "symfony/property-access": "*", "symfony/property-info": "*", "symfony/serializer": "*" @@ -7148,7 +7252,7 @@ "MIT" ], "description": "A pack for the Symfony serializer", - "time": "2018-12-10T12:14:14+00:00" + "time": "2020-03-28T16:26:24+00:00" }, { "name": "symfony/service-contracts", @@ -7210,16 +7314,16 @@ }, { "name": "symfony/stopwatch", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "abc08d7c48987829bac301347faa10f7e8bbf4fb" + "reference": "5f03e4ceeab7473c15d95c7a3c2eddc870bd0637" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/abc08d7c48987829bac301347faa10f7e8bbf4fb", - "reference": "abc08d7c48987829bac301347faa10f7e8bbf4fb", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5f03e4ceeab7473c15d95c7a3c2eddc870bd0637", + "reference": "5f03e4ceeab7473c15d95c7a3c2eddc870bd0637", "shasum": "" }, "require": { @@ -7256,20 +7360,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-17T19:51:46+00:00" }, { "name": "symfony/templating", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/templating.git", - "reference": "9995a4f65149d5ab7f0d9cca6d88136ae8bfaa72" + "reference": "bc20806de1332fedf2906aac04714818d49bdf93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/templating/zipball/9995a4f65149d5ab7f0d9cca6d88136ae8bfaa72", - "reference": "9995a4f65149d5ab7f0d9cca6d88136ae8bfaa72", + "url": "https://api.github.com/repos/symfony/templating/zipball/bc20806de1332fedf2906aac04714818d49bdf93", + "reference": "bc20806de1332fedf2906aac04714818d49bdf93", "shasum": "" }, "require": { @@ -7312,20 +7416,20 @@ ], "description": "Symfony Templating Component", "homepage": "https://symfony.com", - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-15T10:05:03+00:00" }, { "name": "symfony/translation", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "0a19a77fba20818a969ef03fdaf1602de0546353" + "reference": "6617bb1548cec764770b719e317299a0270f4c5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/0a19a77fba20818a969ef03fdaf1602de0546353", - "reference": "0a19a77fba20818a969ef03fdaf1602de0546353", + "url": "https://api.github.com/repos/symfony/translation/zipball/6617bb1548cec764770b719e317299a0270f4c5f", + "reference": "6617bb1548cec764770b719e317299a0270f4c5f", "shasum": "" }, "require": { @@ -7388,7 +7492,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2020-02-04T09:32:40+00:00" + "time": "2020-03-17T19:51:46+00:00" }, { "name": "symfony/translation-contracts", @@ -7449,16 +7553,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "e76e963d8aeb1370a1236ca237a8028141402fc0" + "reference": "bd446d8e64ef049dd3afc090794e5b7e4f17d272" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/e76e963d8aeb1370a1236ca237a8028141402fc0", - "reference": "e76e963d8aeb1370a1236ca237a8028141402fc0", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/bd446d8e64ef049dd3afc090794e5b7e4f17d272", + "reference": "bd446d8e64ef049dd3afc090794e5b7e4f17d272", "shasum": "" }, "require": { @@ -7548,20 +7652,20 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com", - "time": "2020-02-14T08:28:51+00:00" + "time": "2020-03-17T19:51:46+00:00" }, { "name": "symfony/twig-bundle", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "d3e3e46e9e683e946746219570299ba07506260a" + "reference": "0b33e802fcd9a10287631d98962ca9164c4ccd45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/d3e3e46e9e683e946746219570299ba07506260a", - "reference": "d3e3e46e9e683e946746219570299ba07506260a", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/0b33e802fcd9a10287631d98962ca9164c4ccd45", + "reference": "0b33e802fcd9a10287631d98962ca9164c4ccd45", "shasum": "" }, "require": { @@ -7623,20 +7727,20 @@ ], "description": "Symfony TwigBundle", "homepage": "https://symfony.com", - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-17T19:51:46+00:00" }, { "name": "symfony/validator", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "3a3a07fe2f42492eccca6771f1a460c9900cd851" + "reference": "b0e5edb15ec6b0a03aea67ad0bc79edea0091eef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/3a3a07fe2f42492eccca6771f1a460c9900cd851", - "reference": "3a3a07fe2f42492eccca6771f1a460c9900cd851", + "url": "https://api.github.com/repos/symfony/validator/zipball/b0e5edb15ec6b0a03aea67ad0bc79edea0091eef", + "reference": "b0e5edb15ec6b0a03aea67ad0bc79edea0091eef", "shasum": "" }, "require": { @@ -7716,20 +7820,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2020-02-29T10:05:28+00:00" + "time": "2020-03-23T12:37:11+00:00" }, { "name": "symfony/var-dumper", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2572839911702b0405479410ea7a1334bfab0b96" + "reference": "6dae4692ac91230b33b70d9a48882ff5c838d67a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2572839911702b0405479410ea7a1334bfab0b96", - "reference": "2572839911702b0405479410ea7a1334bfab0b96", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6dae4692ac91230b33b70d9a48882ff5c838d67a", + "reference": "6dae4692ac91230b33b70d9a48882ff5c838d67a", "shasum": "" }, "require": { @@ -7792,20 +7896,20 @@ "debug", "dump" ], - "time": "2020-02-24T13:10:00+00:00" + "time": "2020-03-18T07:15:43+00:00" }, { "name": "symfony/var-exporter", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "1a76a943f2af334da13bc9f33f49392fa530eec9" + "reference": "982ddfd0d7aeb2be0227c242399c3f29e0403266" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1a76a943f2af334da13bc9f33f49392fa530eec9", - "reference": "1a76a943f2af334da13bc9f33f49392fa530eec9", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/982ddfd0d7aeb2be0227c242399c3f29e0403266", + "reference": "982ddfd0d7aeb2be0227c242399c3f29e0403266", "shasum": "" }, "require": { @@ -7852,20 +7956,20 @@ "instantiate", "serialize" ], - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/web-link", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/web-link.git", - "reference": "dad60d94b2e7f16e1a7d0ebd0f1f460f45a51386" + "reference": "fda0ec7e0999e52e7b6223f59c5c00365f10f88c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/dad60d94b2e7f16e1a7d0ebd0f1f460f45a51386", - "reference": "dad60d94b2e7f16e1a7d0ebd0f1f460f45a51386", + "url": "https://api.github.com/repos/symfony/web-link/zipball/fda0ec7e0999e52e7b6223f59c5c00365f10f88c", + "reference": "fda0ec7e0999e52e7b6223f59c5c00365f10f88c", "shasum": "" }, "require": { @@ -7928,7 +8032,7 @@ "psr13", "push" ], - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-17T19:51:46+00:00" }, { "name": "symfony/webpack-encore-bundle", @@ -7985,16 +8089,16 @@ }, { "name": "symfony/yaml", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "94d005c176db2080e98825d98e01e8b311a97a88" + "reference": "43d7a46b1f80b4fd2ecfac4a9a4cc1f22d029fbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/94d005c176db2080e98825d98e01e8b311a97a88", - "reference": "94d005c176db2080e98825d98e01e8b311a97a88", + "url": "https://api.github.com/repos/symfony/yaml/zipball/43d7a46b1f80b4fd2ecfac4a9a4cc1f22d029fbb", + "reference": "43d7a46b1f80b4fd2ecfac4a9a4cc1f22d029fbb", "shasum": "" }, "require": { @@ -8040,20 +8144,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2020-02-03T10:46:43+00:00" + "time": "2020-03-16T08:56:54+00:00" }, { "name": "thecodingmachine/safe", - "version": "v1.0.3", + "version": "v1.1", "source": { "type": "git", "url": "https://github.com/thecodingmachine/safe.git", - "reference": "6662d0bef91fe5d44178cb2c38d51c5d16b65d23" + "reference": "f440677bad66c0ef42fa3f875bf05718028af5d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/6662d0bef91fe5d44178cb2c38d51c5d16b65d23", - "reference": "6662d0bef91fe5d44178cb2c38d51c5d16b65d23", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/f440677bad66c0ef42fa3f875bf05718028af5d3", + "reference": "f440677bad66c0ef42fa3f875bf05718028af5d3", "shasum": "" }, "require": { @@ -8172,7 +8276,7 @@ "MIT" ], "description": "PHP core functions that throw exceptions instead of returning FALSE on error", - "time": "2020-01-20T08:44:36+00:00" + "time": "2020-03-24T13:59:42+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -10190,16 +10294,16 @@ }, { "name": "phpstan/phpstan", - "version": "0.12.14", + "version": "0.12.18", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "37bdd26a80235d0f9045b49f4151102b7831cbe2" + "reference": "1ce27fe29c8660a27926127d350d53d80c4d4286" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37bdd26a80235d0f9045b49f4151102b7831cbe2", - "reference": "37bdd26a80235d0f9045b49f4151102b7831cbe2", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1ce27fe29c8660a27926127d350d53d80c4d4286", + "reference": "1ce27fe29c8660a27926127d350d53d80c4d4286", "shasum": "" }, "require": { @@ -10225,7 +10329,7 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", - "time": "2020-03-02T22:29:43+00:00" + "time": "2020-03-22T16:51:47+00:00" }, { "name": "phpstan/phpstan-doctrine", @@ -10774,16 +10878,16 @@ }, { "name": "symfony/browser-kit", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "090ce406505149d6852a7c03b0346dec3b8cf612" + "reference": "4e9a171559f5a9018c90ba9e85b4084d4e045186" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/090ce406505149d6852a7c03b0346dec3b8cf612", - "reference": "090ce406505149d6852a7c03b0346dec3b8cf612", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/4e9a171559f5a9018c90ba9e85b4084d4e045186", + "reference": "4e9a171559f5a9018c90ba9e85b4084d4e045186", "shasum": "" }, "require": { @@ -10829,11 +10933,11 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2020-02-23T10:00:59+00:00" + "time": "2020-03-15T10:05:03+00:00" }, { "name": "symfony/debug-bundle", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", @@ -10929,16 +11033,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "11dcf08f12f29981bf770f097a5d64d65bce5929" + "reference": "7e7c7957f6d53757d36b61a1f7408ef0b6683040" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/11dcf08f12f29981bf770f097a5d64d65bce5929", - "reference": "11dcf08f12f29981bf770f097a5d64d65bce5929", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7e7c7957f6d53757d36b61a1f7408ef0b6683040", + "reference": "7e7c7957f6d53757d36b61a1f7408ef0b6683040", "shasum": "" }, "require": { @@ -10986,7 +11090,7 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2020-02-29T10:05:28+00:00" + "time": "2020-03-16T11:24:17+00:00" }, { "name": "symfony/maker-bundle", @@ -11058,16 +11162,16 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v5.0.5", + "version": "v5.0.6", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "b8fee53045a55ccbb9209e453bf6fdcf74381959" + "reference": "cb3f0f5bf8776bccaf8d61e4c91a573db58a19b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/b8fee53045a55ccbb9209e453bf6fdcf74381959", - "reference": "b8fee53045a55ccbb9209e453bf6fdcf74381959", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/cb3f0f5bf8776bccaf8d61e4c91a573db58a19b6", + "reference": "cb3f0f5bf8776bccaf8d61e4c91a573db58a19b6", "shasum": "" }, "require": { @@ -11119,7 +11223,7 @@ ], "description": "Symfony PHPUnit Bridge", "homepage": "https://symfony.com", - "time": "2020-02-24T15:05:31+00:00" + "time": "2020-03-15T14:33:06+00:00" }, { "name": "symfony/profiler-pack", @@ -11179,7 +11283,7 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v4.4.5", + "version": "v4.4.6", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", @@ -11245,16 +11349,16 @@ }, { "name": "symplify/auto-bind-parameter", - "version": "v7.2.4", + "version": "v7.2.8", "source": { "type": "git", "url": "https://github.com/symplify/auto-bind-parameter.git", - "reference": "ff9c5b60aba14f5a91449684f28a52e4411181c3" + "reference": "8b85fc72fddc953feda56c3d06252eb1fafb21ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/auto-bind-parameter/zipball/ff9c5b60aba14f5a91449684f28a52e4411181c3", - "reference": "ff9c5b60aba14f5a91449684f28a52e4411181c3", + "url": "https://api.github.com/repos/symplify/auto-bind-parameter/zipball/8b85fc72fddc953feda56c3d06252eb1fafb21ef", + "reference": "8b85fc72fddc953feda56c3d06252eb1fafb21ef", "shasum": "" }, "require": { @@ -11262,7 +11366,7 @@ "php": "^7.2", "symfony/dependency-injection": "^4.4|^5.0", "symfony/http-kernel": "^4.4|^5.0", - "symplify/package-builder": "^7.2.4" + "symplify/package-builder": "^7.2.8" }, "require-dev": { "phpunit/phpunit": "^8.5|^9.0" @@ -11283,20 +11387,20 @@ "MIT" ], "description": "Auto bind parameters for your Symfony applications", - "time": "2020-03-12T09:43:53+00:00" + "time": "2020-03-18T23:25:54+00:00" }, { "name": "symplify/autowire-array-parameter", - "version": "v7.2.4", + "version": "v7.2.8", "source": { "type": "git", "url": "https://github.com/symplify/autowire-array-parameter.git", - "reference": "3acb60ed2aa469a222f39dd79fcc12d64e30b6d5" + "reference": "53ae1541e9eca16bd5bae95d627a442092933585" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/3acb60ed2aa469a222f39dd79fcc12d64e30b6d5", - "reference": "3acb60ed2aa469a222f39dd79fcc12d64e30b6d5", + "url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/53ae1541e9eca16bd5bae95d627a442092933585", + "reference": "53ae1541e9eca16bd5bae95d627a442092933585", "shasum": "" }, "require": { @@ -11304,7 +11408,7 @@ "nette/utils": "^3.0", "php": "^7.2", "symfony/dependency-injection": "^4.4|^5.0", - "symplify/package-builder": "^7.2.4" + "symplify/package-builder": "^7.2.8" }, "require-dev": { "phpunit/phpunit": "^8.5|^9.0" @@ -11325,20 +11429,20 @@ "MIT" ], "description": "Autowire array parameters for your Symfony applications", - "time": "2020-03-12T09:43:53+00:00" + "time": "2020-03-18T23:25:54+00:00" }, { "name": "symplify/coding-standard", - "version": "v7.2.4", + "version": "v7.2.8", "source": { "type": "git", "url": "https://github.com/symplify/coding-standard.git", - "reference": "9e994e7309cc8f1c80467eb91512538bc938b28a" + "reference": "084c7ba3b6cc62f8a271da3a4192f663bc12ff2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/coding-standard/zipball/9e994e7309cc8f1c80467eb91512538bc938b28a", - "reference": "9e994e7309cc8f1c80467eb91512538bc938b28a", + "url": "https://api.github.com/repos/symplify/coding-standard/zipball/084c7ba3b6cc62f8a271da3a4192f663bc12ff2e", + "reference": "084c7ba3b6cc62f8a271da3a4192f663bc12ff2e", "shasum": "" }, "require": { @@ -11348,15 +11452,15 @@ "php": "^7.2", "phpstan/phpdoc-parser": "^0.4", "squizlabs/php_codesniffer": "^3.5", - "symplify/autowire-array-parameter": "^7.2.4", - "symplify/package-builder": "^7.2.4", - "symplify/smart-file-system": "^7.2.4" + "symplify/autowire-array-parameter": "^7.2.8", + "symplify/package-builder": "^7.2.8", + "symplify/smart-file-system": "^7.2.8" }, "require-dev": { "nette/application": "^3.0", "phpunit/phpunit": "^8.5|^9.0", - "symplify/easy-coding-standard-tester": "^7.2.4", - "symplify/package-builder": "^7.2.4" + "symplify/easy-coding-standard-tester": "^7.2.8", + "symplify/package-builder": "^7.2.8" }, "type": "library", "extra": { @@ -11375,20 +11479,20 @@ "MIT" ], "description": "Set of Symplify rules for PHP_CodeSniffer and PHP CS Fixer.", - "time": "2020-03-12T09:43:53+00:00" + "time": "2020-03-18T23:25:54+00:00" }, { "name": "symplify/easy-coding-standard", - "version": "v7.2.0", + "version": "v7.2.3", "source": { "type": "git", - "url": "https://github.com/Symplify/EasyCodingStandard.git", - "reference": "efa1b57dd454af4d250d8ecd5aacca19a174a3ed" + "url": "https://github.com/symplify/easy-coding-standard.git", + "reference": "9dfbfc09994310ca43cec24ca86044aae7a5fe47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Symplify/EasyCodingStandard/zipball/efa1b57dd454af4d250d8ecd5aacca19a174a3ed", - "reference": "efa1b57dd454af4d250d8ecd5aacca19a174a3ed", + "url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/9dfbfc09994310ca43cec24ca86044aae7a5fe47", + "reference": "9dfbfc09994310ca43cec24ca86044aae7a5fe47", "shasum": "" }, "require": { @@ -11409,16 +11513,19 @@ "symfony/finder": "^4.4|^5.0", "symfony/http-kernel": "^4.4|^5.0", "symfony/yaml": "^4.4|^5.0", - "symplify/auto-bind-parameter": "^7.2", - "symplify/autowire-array-parameter": "^7.2", - "symplify/coding-standard": "^7.2", - "symplify/package-builder": "^7.2", - "symplify/set-config-resolver": "^7.2", - "symplify/smart-file-system": "^7.2" + "symplify/auto-bind-parameter": "^7.2.3", + "symplify/autowire-array-parameter": "^7.2.3", + "symplify/coding-standard": "^7.2.3", + "symplify/package-builder": "^7.2.3", + "symplify/set-config-resolver": "^7.2.3", + "symplify/smart-file-system": "^7.2.3" + }, + "replace": { + "symfony/polyfill-php70": "*" }, "require-dev": { - "phpunit/phpunit": "^8.4", - "symplify/easy-coding-standard-tester": "^7.2" + "phpunit/phpunit": "^8.5|^9.0", + "symplify/easy-coding-standard-tester": "^7.2.3" }, "bin": [ "bin/ecs" @@ -11426,16 +11533,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.2-dev" + "dev-master": "7.3-dev" } }, "autoload": { "psr-4": { "Symplify\\EasyCodingStandard\\": "src", - "Symplify\\EasyCodingStandard\\ChangedFilesDetector\\": "packages/ChangedFilesDetector/src", - "Symplify\\EasyCodingStandard\\Configuration\\": "packages/Configuration/src", - "Symplify\\EasyCodingStandard\\FixerRunner\\": "packages/FixerRunner/src", - "Symplify\\EasyCodingStandard\\SniffRunner\\": "packages/SniffRunner/src" + "Symplify\\EasyCodingStandard\\ChangedFilesDetector\\": "packages/changed-files-detector/src", + "Symplify\\EasyCodingStandard\\Configuration\\": "packages/configuration/src", + "Symplify\\EasyCodingStandard\\FixerRunner\\": "packages/fixer-runner/src", + "Symplify\\EasyCodingStandard\\SniffRunner\\": "packages/sniff-runner/src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11443,20 +11550,20 @@ "MIT" ], "description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.", - "time": "2020-01-05T09:25:47+00:00" + "time": "2020-02-27T16:45:59+00:00" }, { "name": "symplify/package-builder", - "version": "v7.2.4", + "version": "v7.2.8", "source": { "type": "git", "url": "https://github.com/symplify/package-builder.git", - "reference": "819df91cdc61e901429746656acec37ef1f38aac" + "reference": "9d9b5f8f07058aaeb59ba53bfae52226b3b47236" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/package-builder/zipball/819df91cdc61e901429746656acec37ef1f38aac", - "reference": "819df91cdc61e901429746656acec37ef1f38aac", + "url": "https://api.github.com/repos/symplify/package-builder/zipball/9d9b5f8f07058aaeb59ba53bfae52226b3b47236", + "reference": "9d9b5f8f07058aaeb59ba53bfae52226b3b47236", "shasum": "" }, "require": { @@ -11489,20 +11596,20 @@ "MIT" ], "description": "Dependency Injection, Console and Kernel toolkit for Symplify packages.", - "time": "2020-03-12T09:04:14+00:00" + "time": "2020-03-18T23:14:48+00:00" }, { "name": "symplify/set-config-resolver", - "version": "v7.2.4", + "version": "v7.2.8", "source": { "type": "git", "url": "https://github.com/symplify/set-config-resolver.git", - "reference": "04b48cead95bf20d4091b44b71dbb346d70c8e90" + "reference": "561486147349cb07b5692708748ece68c31bf041" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/set-config-resolver/zipball/04b48cead95bf20d4091b44b71dbb346d70c8e90", - "reference": "04b48cead95bf20d4091b44b71dbb346d70c8e90", + "url": "https://api.github.com/repos/symplify/set-config-resolver/zipball/561486147349cb07b5692708748ece68c31bf041", + "reference": "561486147349cb07b5692708748ece68c31bf041", "shasum": "" }, "require": { @@ -11511,7 +11618,7 @@ "symfony/console": "^4.4|^5.0", "symfony/filesystem": "^4.4|^5.0", "symfony/finder": "^4.4|^5.0", - "symplify/smart-file-system": "^7.2.4" + "symplify/smart-file-system": "^7.2.8" }, "require-dev": { "phpunit/phpunit": "^8.5|^9.0" @@ -11532,20 +11639,20 @@ "MIT" ], "description": "Resolve config and sets from configs and cli opptions for CLI applications", - "time": "2020-03-12T09:43:53+00:00" + "time": "2020-03-18T23:25:54+00:00" }, { "name": "symplify/smart-file-system", - "version": "v7.2.4", + "version": "v7.2.8", "source": { "type": "git", "url": "https://github.com/symplify/smart-file-system.git", - "reference": "5e0fa2a90bae6174bc2de2f8a40ab216b0e38e50" + "reference": "9f6320c3b22c81e85f51aabf66c927bbf4d8c20f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/smart-file-system/zipball/5e0fa2a90bae6174bc2de2f8a40ab216b0e38e50", - "reference": "5e0fa2a90bae6174bc2de2f8a40ab216b0e38e50", + "url": "https://api.github.com/repos/symplify/smart-file-system/zipball/9f6320c3b22c81e85f51aabf66c927bbf4d8c20f", + "reference": "9f6320c3b22c81e85f51aabf66c927bbf4d8c20f", "shasum": "" }, "require": { @@ -11575,20 +11682,20 @@ "MIT" ], "description": "Sanitized FileInfo with safe getRealPath() and other handy methods", - "time": "2020-03-02T16:35:33+00:00" + "time": "2020-03-18T23:14:48+00:00" }, { "name": "vimeo/psalm", - "version": "3.9.5", + "version": "3.10.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "0cfe565d0afbcd31eadcc281b9017b5692911661" + "reference": "eeed5ecccc10131397f0eb7ee6da810c0be3a7fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/0cfe565d0afbcd31eadcc281b9017b5692911661", - "reference": "0cfe565d0afbcd31eadcc281b9017b5692911661", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/eeed5ecccc10131397f0eb7ee6da810c0be3a7fc", + "reference": "eeed5ecccc10131397f0eb7ee6da810c0be3a7fc", "shasum": "" }, "require": { @@ -11671,7 +11778,7 @@ "inspection", "php" ], - "time": "2020-03-09T22:59:56+00:00" + "time": "2020-03-23T11:40:30+00:00" }, { "name": "webmozart/glob", diff --git a/config/banner.md b/config/banner.md index 74b1d526..997ca15e 100644 --- a/config/banner.md +++ b/config/banner.md @@ -1,3 +1,14 @@ Welcome to Part-DB. -If you want to change this banner, edit `config/banner.md` file or set the `BANNER` environment variable. \ No newline at end of file +If you want to change this banner, edit `config/banner.md` file or set the `BANNER` environment variable. + +
+

+And God said
+$\nabla \cdot \vec{D} = \rho$, +$\nabla \cdot \vec{B} = 0$, +$\nabla \times \vec{E} = -\frac{\partial \vec{B}}{\partial t}$, +$\nabla \times \vec{H} = \vec{j} + \frac{\partial \vec{D}}{\partial t}$,
+and then there was light. +

+
\ No newline at end of file diff --git a/config/packages/prod/webpack_encore.yaml b/config/packages/prod/webpack_encore.yaml index d0b3ba81..2b75ef57 100644 --- a/config/packages/prod/webpack_encore.yaml +++ b/config/packages/prod/webpack_encore.yaml @@ -1,4 +1,7 @@ -#webpack_encore: +webpack_encore: # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes) # Available in version 1.2 - #cache: true + cache: true + + # Preload in production + preload: false \ No newline at end of file diff --git a/config/packages/webpack_encore.yaml b/config/packages/webpack_encore.yaml index 8eb88a34..1b405d71 100644 --- a/config/packages/webpack_encore.yaml +++ b/config/packages/webpack_encore.yaml @@ -8,7 +8,7 @@ webpack_encore: # crossorigin: 'anonymous' # preload all rendered script and link tags automatically via the http2 Link header - preload: true + #preload: false # Throw an exception if the entrypoints.json file is missing or an entry is missing from the data # strict_mode: false diff --git a/config/permissions.yaml b/config/permissions.yaml index e9e4a450..fc315f7f 100644 --- a/config/permissions.yaml +++ b/config/permissions.yaml @@ -153,6 +153,10 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co <<: *PART_MULTI_ATTRIBUTE label: "perm.part.prices" + parts_parameters: + <<: *PART_MULTI_ATTRIBUTE + label: "perm.part.parameters" + parts_lots: <<: *PART_MULTI_ATTRIBUTE label: "perm.part.lots" diff --git a/ecs.yaml b/ecs.yaml index 3241e701..2eb99600 100644 --- a/ecs.yaml +++ b/ecs.yaml @@ -9,6 +9,10 @@ parameters: # - "symplify" - "symfony" + paths: + - 'src' + - 'tests' + skip: Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer: ~ Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer: ~ \ No newline at end of file diff --git a/package.json b/package.json index 76643546..5f7776e9 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "exports-loader": "^0.7.0", "jquery-form": "^4.2.2", "jszip": "^3.2.0", + "katex": "^0.11.1", "marked": "^0.8.0", "patternfly-bootstrap-treeview": "^2.1.8", "pdfmake": "^0.1.53", diff --git a/src/Command/SetPasswordCommand.php b/src/Command/SetPasswordCommand.php index 2ed0d7ff..2ea14b5e 100644 --- a/src/Command/SetPasswordCommand.php +++ b/src/Command/SetPasswordCommand.php @@ -125,6 +125,7 @@ class SetPasswordCommand extends Command $this->entityManager->flush(); $io->success('Password was set successful! You can now log in using the new password.'); + return 0; } } diff --git a/src/Command/UpdateExchangeRatesCommand.php b/src/Command/UpdateExchangeRatesCommand.php index 88a737c5..9e06669a 100644 --- a/src/Command/UpdateExchangeRatesCommand.php +++ b/src/Command/UpdateExchangeRatesCommand.php @@ -139,6 +139,7 @@ class UpdateExchangeRatesCommand extends Command $this->em->flush(); $io->success(sprintf('%d (of %d) currency exchange rates were updated.', $success_counter, count($candidates))); + return 0; } } diff --git a/src/Controller/AdminPages/AttachmentTypeController.php b/src/Controller/AdminPages/AttachmentTypeController.php index 73a66b91..8a62609b 100644 --- a/src/Controller/AdminPages/AttachmentTypeController.php +++ b/src/Controller/AdminPages/AttachmentTypeController.php @@ -44,6 +44,7 @@ namespace App\Controller\AdminPages; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentTypeAttachment; +use App\Entity\Parameters\AttachmentTypeParameter; use App\Form\AdminPages\AttachmentTypeAdminForm; use App\Services\EntityExporter; use App\Services\EntityImporter; @@ -64,13 +65,11 @@ class AttachmentTypeController extends BaseAdminController protected $form_class = AttachmentTypeAdminForm::class; protected $route_base = 'attachment_type'; protected $attachment_class = AttachmentTypeAttachment::class; + protected $parameter_class = AttachmentTypeParameter::class; /** * @Route("/{id}", name="attachment_type_delete", methods={"DELETE"}) * - * @param Request $request - * @param AttachmentType $entity - * @param StructuralElementRecursionHelper $recursionHelper * @return RedirectResponse */ public function delete(Request $request, AttachmentType $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse @@ -82,9 +81,6 @@ class AttachmentTypeController extends BaseAdminController * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="attachment_type_edit") * @Route("/{id}", requirements={"id"="\d+"}) * - * @param AttachmentType $entity - * @param Request $request - * @param EntityManagerInterface $em * @return Response */ public function edit(AttachmentType $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response @@ -96,9 +92,6 @@ class AttachmentTypeController extends BaseAdminController * @Route("/new", name="attachment_type_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -109,9 +102,6 @@ class AttachmentTypeController extends BaseAdminController /** * @Route("/export", name="attachment_type_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -122,9 +112,6 @@ class AttachmentTypeController extends BaseAdminController /** * @Route("/{id}/export", name="attachment_type_export") * - * @param AttachmentType $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(AttachmentType $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/BaseAdminController.php b/src/Controller/AdminPages/BaseAdminController.php index 011fc4f0..9fb05dea 100644 --- a/src/Controller/AdminPages/BaseAdminController.php +++ b/src/Controller/AdminPages/BaseAdminController.php @@ -77,6 +77,7 @@ abstract class BaseAdminController extends AbstractController protected $twig_template = ''; protected $route_base = ''; protected $attachment_class = ''; + protected $parameter_class = ''; protected $passwordEncoder; protected $translator; @@ -101,6 +102,10 @@ abstract class BaseAdminController extends AbstractController throw new InvalidArgumentException('You have to override the $attachment_class value in your subclass!'); } + if ('' === $this->parameter_class) { + throw new InvalidArgumentException('You have to override the $parameter_class value in your subclass!'); + } + $this->translator = $translator; $this->passwordEncoder = $passwordEncoder; $this->attachmentHelper = $attachmentHelper; @@ -111,14 +116,12 @@ abstract class BaseAdminController extends AbstractController $this->dataTableFactory = $dataTableFactory; } - - protected function _edit(AbstractNamedDBElement $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null) : Response + protected function _edit(AbstractNamedDBElement $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response { $this->denyAccessUnlessGranted('read', $entity); - $timeTravel_timestamp = null; - if ($timestamp !== null) { + if (null !== $timestamp) { $this->denyAccessUnlessGranted('@tools.timetravel'); $this->denyAccessUnlessGranted('show_history', $entity); //If the timestamp only contains numbers interpret it as unix timestamp @@ -131,12 +134,12 @@ abstract class BaseAdminController extends AbstractController $this->timeTravel->revertEntityToTimestamp($entity, $timeTravel_timestamp); } - if ($this->isGranted('show_history', $entity) ) { + if ($this->isGranted('show_history', $entity)) { $table = $this->dataTableFactory->createFromType( LogDataTable::class, [ 'filter_elements' => $this->historyHelper->getAssociatedElements($entity), - 'mode' => 'element_history' + 'mode' => 'element_history', ], ['pageLength' => 10] ) @@ -151,7 +154,8 @@ abstract class BaseAdminController extends AbstractController $form = $this->createForm($this->form_class, $entity, [ 'attachment_class' => $this->attachment_class, - 'disabled' => $timeTravel_timestamp !== null ? true : null + 'parameter_class' => $this->parameter_class, + 'disabled' => null !== $timeTravel_timestamp ? true : null, ]); $form->handleRequest($request); @@ -191,7 +195,10 @@ abstract class BaseAdminController extends AbstractController //Rebuild form, so it is based on the updated data. Important for the parent field! //We can not use dynamic form events here, because the parent entity list is build from database! - $form = $this->createForm($this->form_class, $entity, ['attachment_class' => $this->attachment_class]); + $form = $this->createForm($this->form_class, $entity, [ + 'attachment_class' => $this->attachment_class, + 'parameter_class' => $this->parameter_class + ]); } elseif ($form->isSubmitted() && ! $form->isValid()) { $this->addFlash('error', 'entity.edit_flash.invalid'); } @@ -202,7 +209,7 @@ abstract class BaseAdminController extends AbstractController 'attachment_helper' => $this->attachmentHelper, 'route_base' => $this->route_base, 'datatable' => $table, - 'timeTravel' => $timeTravel_timestamp + 'timeTravel' => $timeTravel_timestamp, ]); } @@ -214,7 +221,10 @@ abstract class BaseAdminController extends AbstractController $this->denyAccessUnlessGranted('read', $new_entity); //Basic edit form - $form = $this->createForm($this->form_class, $new_entity, ['attachment_class' => $this->attachment_class]); + $form = $this->createForm($this->form_class, $new_entity, [ + 'attachment_class' => $this->attachment_class, + 'parameter_class' => $this->parameter_class, + ]); $form->handleRequest($request); @@ -274,9 +284,7 @@ abstract class BaseAdminController extends AbstractController 'csv_separator' => $data['csv_separator'], ]; - $this->commentHelper->setMessage('Import ' . $file->getClientOriginalName()); - - + $this->commentHelper->setMessage('Import '.$file->getClientOriginalName()); $errors = $importer->fileToDBEntities($file, $this->entity_class, $options); @@ -319,7 +327,7 @@ abstract class BaseAdminController extends AbstractController ]); } - protected function _delete(Request $request, AbstractNamedDBElement $entity, StructuralElementRecursionHelper $recursionHelper) : RedirectResponse + protected function _delete(Request $request, AbstractNamedDBElement $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse { $this->denyAccessUnlessGranted('delete', $entity); diff --git a/src/Controller/AdminPages/CategoryController.php b/src/Controller/AdminPages/CategoryController.php index 6bbde77d..05ce64f6 100644 --- a/src/Controller/AdminPages/CategoryController.php +++ b/src/Controller/AdminPages/CategoryController.php @@ -43,6 +43,7 @@ declare(strict_types=1); namespace App\Controller\AdminPages; use App\Entity\Attachments\CategoryAttachment; +use App\Entity\Parameters\CategoryParameter; use App\Entity\Parts\Category; use App\Form\AdminPages\CategoryAdminForm; use App\Services\EntityExporter; @@ -64,13 +65,11 @@ class CategoryController extends BaseAdminController protected $form_class = CategoryAdminForm::class; protected $route_base = 'category'; protected $attachment_class = CategoryAttachment::class; + protected $parameter_class = CategoryParameter::class; /** * @Route("/{id}", name="category_delete", methods={"DELETE"}) * - * @param Request $request - * @param Category $entity - * @param StructuralElementRecursionHelper $recursionHelper * @return RedirectResponse */ public function delete(Request $request, Category $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse @@ -82,9 +81,6 @@ class CategoryController extends BaseAdminController * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="category_edit") * @Route("/{id}", requirements={"id"="\d+"}) * - * @param Category $entity - * @param Request $request - * @param EntityManagerInterface $em * @return Response */ public function edit(Category $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response @@ -96,9 +92,6 @@ class CategoryController extends BaseAdminController * @Route("/new", name="category_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -109,9 +102,6 @@ class CategoryController extends BaseAdminController /** * @Route("/export", name="category_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -122,9 +112,6 @@ class CategoryController extends BaseAdminController /** * @Route("/{id}/export", name="category_export") * - * @param Category $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(Category $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/CurrencyController.php b/src/Controller/AdminPages/CurrencyController.php index 35a72ee3..757c9896 100644 --- a/src/Controller/AdminPages/CurrencyController.php +++ b/src/Controller/AdminPages/CurrencyController.php @@ -43,6 +43,7 @@ declare(strict_types=1); namespace App\Controller\AdminPages; use App\Entity\Attachments\CurrencyAttachment; +use App\Entity\Parameters\CurrencyParameter; use App\Entity\PriceInformations\Currency; use App\Form\AdminPages\CurrencyAdminForm; use App\Services\EntityExporter; @@ -66,13 +67,11 @@ class CurrencyController extends BaseAdminController protected $form_class = CurrencyAdminForm::class; protected $route_base = 'currency'; protected $attachment_class = CurrencyAttachment::class; + protected $parameter_class = CurrencyParameter::class; /** * @Route("/{id}", name="currency_delete", methods={"DELETE"}) * - * @param Request $request - * @param Currency $entity - * @param StructuralElementRecursionHelper $recursionHelper * @return RedirectResponse */ public function delete(Request $request, Currency $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse @@ -84,9 +83,6 @@ class CurrencyController extends BaseAdminController * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="currency_edit") * @Route("/{id}", requirements={"id"="\d+"}) * - * @param Currency $entity - * @param Request $request - * @param EntityManagerInterface $em * @return Response */ public function edit(Currency $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response @@ -98,9 +94,6 @@ class CurrencyController extends BaseAdminController * @Route("/new", name="currency_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -111,9 +104,6 @@ class CurrencyController extends BaseAdminController /** * @Route("/export", name="currency_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -124,9 +114,6 @@ class CurrencyController extends BaseAdminController /** * @Route("/{id}/export", name="currency_export") * - * @param Currency $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(Currency $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/DeviceController.php b/src/Controller/AdminPages/DeviceController.php index e643612e..ad99243b 100644 --- a/src/Controller/AdminPages/DeviceController.php +++ b/src/Controller/AdminPages/DeviceController.php @@ -44,6 +44,7 @@ namespace App\Controller\AdminPages; use App\Entity\Attachments\DeviceAttachment; use App\Entity\Devices\Device; +use App\Entity\Parameters\DeviceParameter; use App\Form\AdminPages\BaseEntityAdminForm; use App\Services\EntityExporter; use App\Services\EntityImporter; @@ -64,13 +65,11 @@ class DeviceController extends BaseAdminController protected $form_class = BaseEntityAdminForm::class; protected $route_base = 'device'; protected $attachment_class = DeviceAttachment::class; + protected $parameter_class = DeviceParameter::class; /** * @Route("/{id}", name="device_delete", methods={"DELETE"}) * - * @param Request $request - * @param Device $entity - * @param StructuralElementRecursionHelper $recursionHelper * @return RedirectResponse */ public function delete(Request $request, Device $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse @@ -82,9 +81,6 @@ class DeviceController extends BaseAdminController * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="device_edit") * @Route("/{id}", requirements={"id"="\d+"}) * - * @param Device $entity - * @param Request $request - * @param EntityManagerInterface $em * @return Response */ public function edit(Device $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response @@ -96,9 +92,6 @@ class DeviceController extends BaseAdminController * @Route("/new", name="device_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -109,9 +102,6 @@ class DeviceController extends BaseAdminController /** * @Route("/export", name="device_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -122,9 +112,6 @@ class DeviceController extends BaseAdminController /** * @Route("/{id}/export", name="device_export") * - * @param Device $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(Device $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/FootprintController.php b/src/Controller/AdminPages/FootprintController.php index ed786b89..e60caba1 100644 --- a/src/Controller/AdminPages/FootprintController.php +++ b/src/Controller/AdminPages/FootprintController.php @@ -44,6 +44,7 @@ namespace App\Controller\AdminPages; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\FootprintAttachment; +use App\Entity\Parameters\FootprintParameter; use App\Entity\Parts\Footprint; use App\Form\AdminPages\FootprintAdminForm; use App\Services\EntityExporter; @@ -64,12 +65,11 @@ class FootprintController extends BaseAdminController protected $form_class = FootprintAdminForm::class; protected $route_base = 'footprint'; protected $attachment_class = FootprintAttachment::class; + protected $parameter_class = FootprintParameter::class; /** * @Route("/{id}", name="footprint_delete", methods={"DELETE"}) - * @param Request $request - * @param Footprint $entity - * @param StructuralElementRecursionHelper $recursionHelper + * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function delete(Request $request, Footprint $entity, StructuralElementRecursionHelper $recursionHelper) @@ -80,9 +80,7 @@ class FootprintController extends BaseAdminController /** * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="footprint_edit") * @Route("/{id}", requirements={"id"="\d+"}) - * @param Footprint $entity - * @param Request $request - * @param EntityManagerInterface $em + * * @return Response */ public function edit(Footprint $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null) @@ -94,9 +92,6 @@ class FootprintController extends BaseAdminController * @Route("/new", name="footprint_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -107,9 +102,6 @@ class FootprintController extends BaseAdminController /** * @Route("/export", name="footprint_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -120,9 +112,6 @@ class FootprintController extends BaseAdminController /** * @Route("/{id}/export", name="footprint_export") * - * @param AttachmentType $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(AttachmentType $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/ManufacturerController.php b/src/Controller/AdminPages/ManufacturerController.php index 672eb1b7..047b9b4f 100644 --- a/src/Controller/AdminPages/ManufacturerController.php +++ b/src/Controller/AdminPages/ManufacturerController.php @@ -43,6 +43,7 @@ declare(strict_types=1); namespace App\Controller\AdminPages; use App\Entity\Attachments\ManufacturerAttachment; +use App\Entity\Parameters\ManufacturerParameter; use App\Entity\Parts\Manufacturer; use App\Form\AdminPages\CompanyForm; use App\Services\EntityExporter; @@ -63,12 +64,11 @@ class ManufacturerController extends BaseAdminController protected $form_class = CompanyForm::class; protected $route_base = 'manufacturer'; protected $attachment_class = ManufacturerAttachment::class; + protected $parameter_class = ManufacturerParameter::class; /** * @Route("/{id}", name="manufacturer_delete", methods={"DELETE"}) - * @param Request $request - * @param Manufacturer $entity - * @param StructuralElementRecursionHelper $recursionHelper + * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function delete(Request $request, Manufacturer $entity, StructuralElementRecursionHelper $recursionHelper) @@ -79,9 +79,7 @@ class ManufacturerController extends BaseAdminController /** * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="manufacturer_edit") * @Route("/{id}", requirements={"id"="\d+"}) - * @param Manufacturer $entity - * @param Request $request - * @param EntityManagerInterface $em + * * @return Response */ public function edit(Manufacturer $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null) @@ -93,9 +91,6 @@ class ManufacturerController extends BaseAdminController * @Route("/new", name="manufacturer_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -106,9 +101,6 @@ class ManufacturerController extends BaseAdminController /** * @Route("/export", name="manufacturer_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -119,10 +111,6 @@ class ManufacturerController extends BaseAdminController /** * @Route("/{id}/export", name="manufacturer_export") * - * @param Manufacturer $entity - * - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(Manufacturer $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/MeasurementUnitController.php b/src/Controller/AdminPages/MeasurementUnitController.php index dd29d7ff..7ada3e31 100644 --- a/src/Controller/AdminPages/MeasurementUnitController.php +++ b/src/Controller/AdminPages/MeasurementUnitController.php @@ -44,6 +44,7 @@ namespace App\Controller\AdminPages; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\MeasurementUnitAttachment; +use App\Entity\Parameters\MeasurementUnitParameter; use App\Entity\Parts\MeasurementUnit; use App\Form\AdminPages\MeasurementUnitAdminForm; use App\Services\EntityExporter; @@ -64,12 +65,11 @@ class MeasurementUnitController extends BaseAdminController protected $form_class = MeasurementUnitAdminForm::class; protected $route_base = 'measurement_unit'; protected $attachment_class = MeasurementUnitAttachment::class; + protected $parameter_class = MeasurementUnitParameter::class; /** * @Route("/{id}", name="measurement_unit_delete", methods={"DELETE"}) - * @param Request $request - * @param MeasurementUnit $entity - * @param StructuralElementRecursionHelper $recursionHelper + * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function delete(Request $request, MeasurementUnit $entity, StructuralElementRecursionHelper $recursionHelper) @@ -80,9 +80,7 @@ class MeasurementUnitController extends BaseAdminController /** * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="measurement_unit_edit") * @Route("/{id}", requirements={"id"="\d+"}) - * @param MeasurementUnit $entity - * @param Request $request - * @param EntityManagerInterface $em + * * @return Response */ public function edit(MeasurementUnit $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null) @@ -94,9 +92,6 @@ class MeasurementUnitController extends BaseAdminController * @Route("/new", name="measurement_unit_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -107,9 +102,6 @@ class MeasurementUnitController extends BaseAdminController /** * @Route("/export", name="measurement_unit_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -120,9 +112,6 @@ class MeasurementUnitController extends BaseAdminController /** * @Route("/{id}/export", name="measurement_unit_export") * - * @param AttachmentType $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(AttachmentType $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/StorelocationController.php b/src/Controller/AdminPages/StorelocationController.php index cddfdcc4..703fe58a 100644 --- a/src/Controller/AdminPages/StorelocationController.php +++ b/src/Controller/AdminPages/StorelocationController.php @@ -42,6 +42,7 @@ declare(strict_types=1); namespace App\Controller\AdminPages; +use App\Entity\Parameters\StorelocationParameter; use App\Entity\Parts\Storelocation; use App\Form\AdminPages\StorelocationAdminForm; use App\Services\EntityExporter; @@ -62,12 +63,11 @@ class StorelocationController extends BaseAdminController protected $form_class = StorelocationAdminForm::class; protected $route_base = 'store_location'; protected $attachment_class = StorelocationAdminForm::class; + protected $parameter_class = StorelocationParameter::class; /** * @Route("/{id}", name="store_location_delete", methods={"DELETE"}) - * @param Request $request - * @param Storelocation $entity - * @param StructuralElementRecursionHelper $recursionHelper + * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function delete(Request $request, Storelocation $entity, StructuralElementRecursionHelper $recursionHelper) @@ -78,9 +78,7 @@ class StorelocationController extends BaseAdminController /** * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="store_location_edit") * @Route("/{id}", requirements={"id"="\d+"}) - * @param Storelocation $entity - * @param Request $request - * @param EntityManagerInterface $em + * * @return Response */ public function edit(Storelocation $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null) @@ -92,9 +90,6 @@ class StorelocationController extends BaseAdminController * @Route("/new", name="store_location_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -105,9 +100,6 @@ class StorelocationController extends BaseAdminController /** * @Route("/export", name="store_location_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -118,10 +110,6 @@ class StorelocationController extends BaseAdminController /** * @Route("/{id}/export", name="store_location_export") * - * @param Storelocation $entity - * - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(Storelocation $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AdminPages/SupplierController.php b/src/Controller/AdminPages/SupplierController.php index 339da87e..8424f137 100644 --- a/src/Controller/AdminPages/SupplierController.php +++ b/src/Controller/AdminPages/SupplierController.php @@ -43,6 +43,7 @@ declare(strict_types=1); namespace App\Controller\AdminPages; use App\Entity\Attachments\SupplierAttachment; +use App\Entity\Parameters\SupplierParameter; use App\Entity\Parts\Supplier; use App\Form\AdminPages\SupplierForm; use App\Services\EntityExporter; @@ -63,12 +64,11 @@ class SupplierController extends BaseAdminController protected $form_class = SupplierForm::class; protected $route_base = 'supplier'; protected $attachment_class = SupplierAttachment::class; + protected $parameter_class = SupplierParameter::class; /** * @Route("/{id}", name="supplier_delete", methods={"DELETE"}) - * @param Request $request - * @param Supplier $entity - * @param StructuralElementRecursionHelper $recursionHelper + * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function delete(Request $request, Supplier $entity, StructuralElementRecursionHelper $recursionHelper) @@ -79,9 +79,7 @@ class SupplierController extends BaseAdminController /** * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="supplier_edit") * @Route("/{id}", requirements={"id"="\d+"}) - * @param Supplier $entity - * @param Request $request - * @param EntityManagerInterface $em + * * @return Response */ public function edit(Supplier $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null) @@ -93,9 +91,6 @@ class SupplierController extends BaseAdminController * @Route("/new", name="supplier_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -106,9 +101,6 @@ class SupplierController extends BaseAdminController /** * @Route("/export", name="supplier_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -119,9 +111,6 @@ class SupplierController extends BaseAdminController /** * @Route("/{id}/export", name="supplier_export") * - * @param Supplier $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(Supplier $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/AttachmentFileController.php b/src/Controller/AttachmentFileController.php index 8f82823a..bf0ab2e3 100644 --- a/src/Controller/AttachmentFileController.php +++ b/src/Controller/AttachmentFileController.php @@ -46,7 +46,6 @@ use App\DataTables\AttachmentDataTable; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\PartAttachment; use App\Services\Attachments\AttachmentManager; -use Exception; use Omines\DataTablesBundle\DataTableFactory; use RuntimeException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -64,8 +63,6 @@ class AttachmentFileController extends AbstractController * * @Route("/attachment/{id}/download", name="attachment_download") * - * @param Attachment $attachment - * @param AttachmentManager $helper * @return BinaryFileResponse */ public function download(Attachment $attachment, AttachmentManager $helper): BinaryFileResponse @@ -94,10 +91,7 @@ class AttachmentFileController extends AbstractController * * @Route("/attachment/{id}/view", name="attachment_view") * - * @param Attachment $attachment - * @param AttachmentManager $helper * @return BinaryFileResponse - * */ public function view(Attachment $attachment, AttachmentManager $helper): BinaryFileResponse { @@ -123,8 +117,6 @@ class AttachmentFileController extends AbstractController /** * @Route("/attachment/list", name="attachment_list") * - * @param DataTableFactory $dataTable - * @param Request $request * @return JsonResponse|Response */ public function attachmentsTable(DataTableFactory $dataTable, Request $request) diff --git a/src/Controller/GroupController.php b/src/Controller/GroupController.php index cdcdd6b9..1bbdf1b0 100644 --- a/src/Controller/GroupController.php +++ b/src/Controller/GroupController.php @@ -44,6 +44,7 @@ namespace App\Controller; use App\Controller\AdminPages\BaseAdminController; use App\Entity\Attachments\GroupAttachment; +use App\Entity\Parameters\GroupParameter; use App\Entity\UserSystem\Group; use App\Form\AdminPages\GroupAdminForm; use App\Services\EntityExporter; @@ -65,14 +66,12 @@ class GroupController extends BaseAdminController protected $form_class = GroupAdminForm::class; protected $route_base = 'group'; protected $attachment_class = GroupAttachment::class; + protected $parameter_class = GroupParameter::class; /** * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="group_edit") * @Route("/{id}/", requirements={"id"="\d+"}) * - * @param Group $entity - * @param Request $request - * @param EntityManagerInterface $em * @return Response */ public function edit(Group $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response @@ -84,9 +83,6 @@ class GroupController extends BaseAdminController * @Route("/new", name="group_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -97,9 +93,6 @@ class GroupController extends BaseAdminController /** * @Route("/{id}", name="group_delete", methods={"DELETE"}) * - * @param Request $request - * @param Group $entity - * @param StructuralElementRecursionHelper $recursionHelper * @return RedirectResponse */ public function delete(Request $request, Group $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse @@ -110,9 +103,6 @@ class GroupController extends BaseAdminController /** * @Route("/export", name="group_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -123,9 +113,6 @@ class GroupController extends BaseAdminController /** * @Route("/{id}/export", name="group_export") * - * @param Group $entity - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(Group $entity, EntityExporter $exporter, Request $request): Response diff --git a/src/Controller/HomepageController.php b/src/Controller/HomepageController.php index 8e6732c0..1430a994 100644 --- a/src/Controller/HomepageController.php +++ b/src/Controller/HomepageController.php @@ -44,11 +44,11 @@ namespace App\Controller; use App\DataTables\LogDataTable; use App\Services\GitVersionInfo; +use const DIRECTORY_SEPARATOR; use Omines\DataTablesBundle\DataTableFactory; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use const DIRECTORY_SEPARATOR; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Annotation\Route; use Symfony\Contracts\Cache\CacheInterface; @@ -81,16 +81,16 @@ class HomepageController extends AbstractController /** * @Route("/", name="homepage") - * @param GitVersionInfo $versionInfo + * * @return \Symfony\Component\HttpFoundation\Response */ public function homepage(Request $request, GitVersionInfo $versionInfo): Response { - if ($this->isGranted("@tools.lastActivity")) { + if ($this->isGranted('@tools.lastActivity')) { $table = $this->dataTable->createFromType( LogDataTable::class, [ - 'mode' => 'last_activity' + 'mode' => 'last_activity', ], ['pageLength' => 10] ) @@ -107,7 +107,7 @@ class HomepageController extends AbstractController 'banner' => $this->getBanner(), 'git_branch' => $versionInfo->getGitBranchName(), 'git_commit' => $versionInfo->getGitCommitHash(), - 'datatable' => $table + 'datatable' => $table, ]); } } diff --git a/src/Controller/LogController.php b/src/Controller/LogController.php index 1db56664..59759747 100644 --- a/src/Controller/LogController.php +++ b/src/Controller/LogController.php @@ -56,7 +56,6 @@ use Omines\DataTablesBundle\DataTableFactory; use phpDocumentor\Reflection\Element; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; @@ -70,7 +69,6 @@ class LogController extends AbstractController protected $timeTravel; protected $dbRepository; - public function __construct(EntityManagerInterface $entityManager, TimeTravel $timeTravel) { $this->entityManager = $entityManager; @@ -81,8 +79,6 @@ class LogController extends AbstractController /** * @Route("/", name="log_view") * - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showLogs(Request $request, DataTableFactory $dataTable) @@ -103,7 +99,6 @@ class LogController extends AbstractController /** * @Route("/undo", name="log_undo", methods={"POST"}) - * @param Request $request */ public function undoRevertLog(Request $request, EventUndoHelper $eventUndoHelper) { @@ -111,13 +106,13 @@ class LogController extends AbstractController $id = $request->request->get('undo'); //If no undo value was set check if a revert was set - if ($id === null) { + if (null === $id) { $id = $request->get('revert'); $mode = EventUndoHelper::MODE_REVERT; } $log_element = $this->entityManager->find(AbstractLogEntry::class, $id); - if ($log_element === null) { + if (null === $log_element) { throw new \InvalidArgumentException('No log entry with the given ID is existing!'); } @@ -126,15 +121,16 @@ class LogController extends AbstractController $eventUndoHelper->setMode($mode); $eventUndoHelper->setUndoneEvent($log_element); - if ($mode === EventUndoHelper::MODE_UNDO) { + if (EventUndoHelper::MODE_UNDO === $mode) { $this->undoLog($log_element); - } elseif ($mode === EventUndoHelper::MODE_REVERT) { + } elseif (EventUndoHelper::MODE_REVERT === $mode) { $this->revertLog($log_element); } $eventUndoHelper->clearUndoneEvent(); $redirect = $request->request->get('redirect_back'); + return $this->redirect($redirect); } @@ -143,15 +139,16 @@ class LogController extends AbstractController $timestamp = $logEntry->getTimestamp(); $element = $this->entityManager->find($logEntry->getTargetClass(), $logEntry->getTargetID()); //If the element is not available in DB try to undelete it - if ($element === null) { + if (null === $element) { $element = $this->timeTravel->undeleteEntity($logEntry->getTargetClass(), $logEntry->getTargetID()); $this->entityManager->persist($element); $this->entityManager->flush(); $this->dbRepository->changeID($element, $logEntry->getTargetID()); } - if (!$element instanceof AbstractDBElement) { + if (! $element instanceof AbstractDBElement) { $this->addFlash('error', 'log.undo.target_not_found'); + return; } @@ -172,7 +169,7 @@ class LogController extends AbstractController } //Check if the element we want to undelete already exits - if ($this->entityManager->find($element_class, $element_id) == null) { + if (null === $this->entityManager->find($element_class, $element_id)) { $undeleted_element = $this->timeTravel->undeleteEntity($element_class, $element_id); $this->entityManager->persist($undeleted_element); $this->entityManager->flush(); @@ -183,7 +180,7 @@ class LogController extends AbstractController } } elseif ($log_element instanceof ElementCreatedLogEntry) { $element = $this->entityManager->find($log_element->getTargetClass(), $log_element->getTargetID()); - if ($element !== null) { + if (null !== $element) { $this->entityManager->remove($element); $this->entityManager->flush(); $this->addFlash('success', 'log.undo.element_delete_success'); diff --git a/src/Controller/PartController.php b/src/Controller/PartController.php index 8c9e695d..c24c09ab 100644 --- a/src/Controller/PartController.php +++ b/src/Controller/PartController.php @@ -53,6 +53,7 @@ use App\Services\Attachments\PartPreviewGenerator; use App\Services\LogSystem\EventCommentHelper; use App\Services\LogSystem\HistoryHelper; use App\Services\LogSystem\TimeTravel; +use App\Services\Parameters\ParameterExtractor; use App\Services\PricedetailHelper; use Doctrine\ORM\EntityManagerInterface; use Omines\DataTablesBundle\DataTableFactory; @@ -87,17 +88,17 @@ class PartController extends AbstractController * @Route("/{id}/info/{timestamp}", name="part_info") * @Route("/{id}", requirements={"id"="\d+"}) * - * @param Part $part * @return Response + * * @throws \Exception */ public function show(Part $part, Request $request, TimeTravel $timeTravel, HistoryHelper $historyHelper, - DataTableFactory $dataTable, ?string $timestamp = null): Response + DataTableFactory $dataTable, ParameterExtractor $parameterExtractor, ?string $timestamp = null): Response { $this->denyAccessUnlessGranted('read', $part); $timeTravel_timestamp = null; - if ($timestamp !== null) { + if (null !== $timestamp) { $this->denyAccessUnlessGranted('@tools.timetravel'); $this->denyAccessUnlessGranted('show_history', $part); //If the timestamp only contains numbers interpret it as unix timestamp @@ -110,10 +111,10 @@ class PartController extends AbstractController $timeTravel->revertEntityToTimestamp($part, $timeTravel_timestamp); } - if ($this->isGranted('show_history', $part) ) { + if ($this->isGranted('show_history', $part)) { $table = $dataTable->createFromType(LogDataTable::class, [ 'filter_elements' => $historyHelper->getAssociatedElements($part), - 'mode' => 'element_history' + 'mode' => 'element_history', ], ['pageLength' => 10]) ->handleRequest($request); @@ -132,7 +133,9 @@ class PartController extends AbstractController 'attachment_helper' => $this->attachmentManager, 'pricedetail_helper' => $this->pricedetailHelper, 'pictures' => $this->partPreviewGenerator->getPreviewAttachments($part), - 'timeTravel' => $timeTravel_timestamp + 'timeTravel' => $timeTravel_timestamp, + 'description_params' => $parameterExtractor->extractParameters($part->getDescription()), + 'comment_params' => $parameterExtractor->extractParameters($part->getComment()) ] ); } @@ -140,11 +143,6 @@ class PartController extends AbstractController /** * @Route("/{id}/edit", name="part_edit") * - * @param Part $part - * @param Request $request - * @param EntityManagerInterface $em - * @param TranslatorInterface $translator - * @param AttachmentSubmitHandler $attachmentSubmitHandler * @return Response */ public function edit(Part $part, Request $request, EntityManagerInterface $em, TranslatorInterface $translator, @@ -197,8 +195,6 @@ class PartController extends AbstractController /** * @Route("/{id}/delete", name="part_delete", methods={"DELETE"}) * - * @param Request $request - * @param Part $part * @return RedirectResponse */ public function delete(Request $request, Part $part): RedirectResponse @@ -226,17 +222,12 @@ class PartController extends AbstractController * @Route("/new", name="part_new") * @Route("/{id}/clone", name="part_clone") * - * @param Request $request - * @param EntityManagerInterface $em - * @param TranslatorInterface $translator - * @param AttachmentManager $attachmentHelper - * @param AttachmentSubmitHandler $attachmentSubmitHandler * @return Response */ public function new(Request $request, EntityManagerInterface $em, TranslatorInterface $translator, AttachmentManager $attachmentHelper, AttachmentSubmitHandler $attachmentSubmitHandler, ?Part $part = null): Response { - if($part === null) { + if (null === $part) { $new_part = new Part(); } else { $new_part = clone $part; @@ -247,7 +238,7 @@ class PartController extends AbstractController $cid = $request->get('cid', 1); $category = $em->find(Category::class, $cid); - if (null !== $category && $new_part->getCategory() === null) { + if (null !== $category && null === $new_part->getCategory()) { $new_part->setCategory($category); } diff --git a/src/Controller/PartListsController.php b/src/Controller/PartListsController.php index 232a7784..e525e0e0 100644 --- a/src/Controller/PartListsController.php +++ b/src/Controller/PartListsController.php @@ -60,9 +60,6 @@ class PartListsController extends AbstractController /** * @Route("/category/{id}/parts", name="part_list_category") * - * @param Category $category - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showCategory(Category $category, Request $request, DataTableFactory $dataTable) @@ -83,9 +80,6 @@ class PartListsController extends AbstractController /** * @Route("/footprint/{id}/parts", name="part_list_footprint") * - * @param Footprint $footprint - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showFootprint(Footprint $footprint, Request $request, DataTableFactory $dataTable) @@ -106,9 +100,6 @@ class PartListsController extends AbstractController /** * @Route("/manufacturer/{id}/parts", name="part_list_manufacturer") * - * @param Manufacturer $manufacturer - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showManufacturer(Manufacturer $manufacturer, Request $request, DataTableFactory $dataTable) @@ -129,9 +120,6 @@ class PartListsController extends AbstractController /** * @Route("/store_location/{id}/parts", name="part_list_store_location") * - * @param Storelocation $storelocation - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showStorelocation(Storelocation $storelocation, Request $request, DataTableFactory $dataTable) @@ -152,9 +140,6 @@ class PartListsController extends AbstractController /** * @Route("/supplier/{id}/parts", name="part_list_supplier") * - * @param Supplier $supplier - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showSupplier(Supplier $supplier, Request $request, DataTableFactory $dataTable) @@ -175,9 +160,6 @@ class PartListsController extends AbstractController /** * @Route("/parts/by_tag/{tag}", name="part_list_tags") * - * @param string $tag - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showTag(string $tag, Request $request, DataTableFactory $dataTable) @@ -197,8 +179,7 @@ class PartListsController extends AbstractController /** * @Route("/parts/search", name="parts_search") - * @param Request $request - * @param DataTableFactory $dataTable + * * @return JsonResponse|Response */ public function showSearch(Request $request, DataTableFactory $dataTable) @@ -218,9 +199,8 @@ class PartListsController extends AbstractController 'regex' => $request->query->getBoolean('regex'), ]; - $table = $dataTable->createFromType(PartsDataTable::class, [ - 'search' => $search, 'search_options' => $search_options + 'search' => $search, 'search_options' => $search_options, ]) ->handleRequest($request); @@ -237,8 +217,6 @@ class PartListsController extends AbstractController /** * @Route("/parts", name="parts_show_all") * - * @param Request $request - * @param DataTableFactory $dataTable * @return JsonResponse|Response */ public function showAll(Request $request, DataTableFactory $dataTable) diff --git a/src/Controller/RedirectController.php b/src/Controller/RedirectController.php index ae798751..b0d9b4ab 100644 --- a/src/Controller/RedirectController.php +++ b/src/Controller/RedirectController.php @@ -70,7 +70,6 @@ class RedirectController extends AbstractController * This function is called whenever a route was not matching the localized routes. * The purpose is to redirect the user to the localized version of the page. * - * @param Request $request * @return RedirectResponse */ public function addLocalePart(Request $request): RedirectResponse diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php index 16e1aade..347ac459 100644 --- a/src/Controller/SecurityController.php +++ b/src/Controller/SecurityController.php @@ -71,7 +71,7 @@ class SecurityController extends AbstractController /** * @Route("/login", name="login", methods={"GET", "POST"}) - * @param AuthenticationUtils $authenticationUtils + * * @return \Symfony\Component\HttpFoundation\Response */ public function login(AuthenticationUtils $authenticationUtils): \Symfony\Component\HttpFoundation\Response @@ -90,8 +90,7 @@ class SecurityController extends AbstractController /** * @Route("/pw_reset/request", name="pw_reset_request") - * @param PasswordResetManager $passwordReset - * @param Request $request + * * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response */ public function requestPwReset(PasswordResetManager $passwordReset, Request $request) @@ -135,10 +134,7 @@ class SecurityController extends AbstractController /** * @Route("/pw_reset/new_pw/{user}/{token}", name="pw_reset_new_pw") - * @param PasswordResetManager $passwordReset - * @param Request $request - * @param string|null $user - * @param string|null $token + * * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response */ public function pwResetNewPw(PasswordResetManager $passwordReset, Request $request, ?string $user = null, ?string $token = null) diff --git a/src/Controller/StatisticsController.php b/src/Controller/StatisticsController.php index 88046cfa..99ff5bd8 100644 --- a/src/Controller/StatisticsController.php +++ b/src/Controller/StatisticsController.php @@ -1,4 +1,7 @@ $helper, ]); } -} \ No newline at end of file +} diff --git a/src/Controller/TreeController.php b/src/Controller/TreeController.php index b11cb288..4443ccdb 100644 --- a/src/Controller/TreeController.php +++ b/src/Controller/TreeController.php @@ -70,7 +70,7 @@ class TreeController extends AbstractController /** * @Route("/tools", name="tree_tools") - * @param ToolsTreeBuilder $builder + * * @return JsonResponse */ public function tools(ToolsTreeBuilder $builder): JsonResponse @@ -83,7 +83,7 @@ class TreeController extends AbstractController /** * @Route("/category/{id}", name="tree_category") * @Route("/categories") - * @param Category|null $category + * * @return JsonResponse */ public function categoryTree(?Category $category = null): JsonResponse @@ -96,7 +96,7 @@ class TreeController extends AbstractController /** * @Route("/footprint/{id}", name="tree_footprint") * @Route("/footprints") - * @param Footprint|null $footprint + * * @return JsonResponse */ public function footprintTree(?Footprint $footprint = null): JsonResponse @@ -109,7 +109,7 @@ class TreeController extends AbstractController /** * @Route("/location/{id}", name="tree_location") * @Route("/locations") - * @param Storelocation|null $location + * * @return JsonResponse */ public function locationTree(?Storelocation $location = null): JsonResponse @@ -122,7 +122,7 @@ class TreeController extends AbstractController /** * @Route("/manufacturer/{id}", name="tree_manufacturer") * @Route("/manufacturers") - * @param Manufacturer|null $manufacturer + * * @return JsonResponse */ public function manufacturerTree(?Manufacturer $manufacturer = null): JsonResponse @@ -135,7 +135,7 @@ class TreeController extends AbstractController /** * @Route("/supplier/{id}", name="tree_supplier") * @Route("/suppliers") - * @param Supplier|null $supplier + * * @return JsonResponse */ public function supplierTree(?Supplier $supplier = null): JsonResponse @@ -148,7 +148,7 @@ class TreeController extends AbstractController /** * @Route("/device/{id}", name="tree_device") * @Route("/devices") - * @param Device|null $device + * * @return JsonResponse */ public function deviceTree(?Device $device = null): JsonResponse diff --git a/src/Controller/TypeaheadController.php b/src/Controller/TypeaheadController.php index 38e280ea..8a8054d0 100644 --- a/src/Controller/TypeaheadController.php +++ b/src/Controller/TypeaheadController.php @@ -61,9 +61,7 @@ class TypeaheadController extends AbstractController { /** * @Route("/builtInResources/search/{query}", name="typeahead_builtInRessources", requirements={"query"= ".+"}) - * @param Request $request - * @param string $query - * @param BuiltinAttachmentsFinder $finder + * * @return JsonResponse */ public function builtInResources(Request $request, string $query, BuiltinAttachmentsFinder $finder) @@ -84,8 +82,7 @@ class TypeaheadController extends AbstractController /** * @Route("/tags/search/{query}", name="typeahead_tags", requirements={"query"= ".+"}) - * @param string $query - * @param TagFinder $finder + * * @return JsonResponse */ public function tags(string $query, TagFinder $finder) diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 68532c12..97738de0 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -43,6 +43,7 @@ declare(strict_types=1); namespace App\Controller; use App\Entity\Attachments\UserAttachment; +use App\Entity\Parameters\PartParameter; use App\Entity\UserSystem\User; use App\Form\Permissions\PermissionsType; use App\Form\UserAdminForm; @@ -67,14 +68,15 @@ class UserController extends AdminPages\BaseAdminController protected $form_class = UserAdminForm::class; protected $route_base = 'user'; protected $attachment_class = UserAttachment::class; + //Just define a value here to prevent error. It is not used. + protected $parameter_class = "not used"; /** * @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="user_edit") * @Route("/{id}/", requirements={"id"="\d+"}) - * @param User $entity - * @param Request $request - * @param EntityManagerInterface $em + * * @return Response + * * @throws \Exception */ public function edit(User $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null) @@ -109,9 +111,6 @@ class UserController extends AdminPages\BaseAdminController * @Route("/new", name="user_new") * @Route("/") * - * @param Request $request - * @param EntityManagerInterface $em - * @param EntityImporter $importer * @return Response */ public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response @@ -121,9 +120,7 @@ class UserController extends AdminPages\BaseAdminController /** * @Route("/{id}", name="user_delete", methods={"DELETE"}, requirements={"id"="\d+"}) - * @param Request $request - * @param User $entity - * @param StructuralElementRecursionHelper $recursionHelper + * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function delete(Request $request, User $entity, StructuralElementRecursionHelper $recursionHelper) @@ -138,9 +135,6 @@ class UserController extends AdminPages\BaseAdminController /** * @Route("/export", name="user_export_all") * - * @param EntityManagerInterface $em - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response @@ -151,10 +145,6 @@ class UserController extends AdminPages\BaseAdminController /** * @Route("/{id}/export", name="user_export") * - * @param User $entity - * - * @param EntityExporter $exporter - * @param Request $request * @return Response */ public function exportEntity(User $entity, EntityExporter $exporter, Request $request): Response @@ -165,8 +155,7 @@ class UserController extends AdminPages\BaseAdminController /** * @Route("/info", name="user_info_self") * @Route("/{id}/info", name="user_info") - * @param User|null $user - * @param Packages $packages + * * @return Response */ public function userInfo(?User $user, Packages $packages): Response @@ -174,7 +163,7 @@ class UserController extends AdminPages\BaseAdminController //If no user id was passed, then we show info about the current user if (null === $user) { $tmp = $this->getUser(); - if(!$tmp instanceof User) { + if (! $tmp instanceof User) { throw new InvalidArgumentException('Userinfo only works for database users!'); } $user = $tmp; diff --git a/src/Controller/UserSettingsController.php b/src/Controller/UserSettingsController.php index ea66d6f5..75df0b2c 100644 --- a/src/Controller/UserSettingsController.php +++ b/src/Controller/UserSettingsController.php @@ -102,9 +102,6 @@ class UserSettingsController extends AbstractController /** * @Route("/u2f_delete", name="u2f_delete", methods={"DELETE"}) * - * @param Request $request - * @param EntityManagerInterface $entityManager - * @param BackupCodeManager $backupCodeManager * @return RedirectResponse */ public function removeU2FToken(Request $request, EntityManagerInterface $entityManager, BackupCodeManager $backupCodeManager): RedirectResponse @@ -155,8 +152,7 @@ class UserSettingsController extends AbstractController /** * @Route("/invalidate_trustedDevices", name="tfa_trustedDevices_invalidate", methods={"DELETE"}) - * @param Request $request - * @param EntityManagerInterface $entityManager + * * @return RuntimeException|RedirectResponse */ public function resetTrustedDevices(Request $request, EntityManagerInterface $entityManager) @@ -187,11 +183,7 @@ class UserSettingsController extends AbstractController /** * @Route("/settings", name="user_settings") - * @param Request $request - * @param EntityManagerInterface $em - * @param UserPasswordEncoderInterface $passwordEncoder - * @param GoogleAuthenticator $googleAuthenticator - * @param BackupCodeManager $backupCodeManager + * * @return RedirectResponse|\Symfony\Component\HttpFoundation\Response */ public function userSettings(Request $request, EntityManagerInterface $em, UserPasswordEncoderInterface $passwordEncoder, GoogleAuthenticator $googleAuthenticator, BackupCodeManager $backupCodeManager) @@ -266,9 +258,9 @@ class UserSettingsController extends AbstractController ], ], 'constraints' => [new Length([ - 'min' => 6, - 'max' => 128, - ])], + 'min' => 6, + 'max' => 128, + ])], ]) ->add('submit', SubmitType::class, ['label' => 'save']) ->getForm(); @@ -297,7 +289,7 @@ class UserSettingsController extends AbstractController } $google_form->handleRequest($request); - if ( ! $this->demo_mode && $google_form->isSubmitted() && $google_form->isValid()) { + if (! $this->demo_mode && $google_form->isSubmitted() && $google_form->isValid()) { if (! $google_enabled) { //Save 2FA settings (save secrets) $user->setGoogleAuthenticatorSecret($google_form->get('googleAuthenticatorSecret')->getData()); diff --git a/src/DataFixtures/PartFixtures.php b/src/DataFixtures/PartFixtures.php index d9d8db9f..b9a8a566 100644 --- a/src/DataFixtures/PartFixtures.php +++ b/src/DataFixtures/PartFixtures.php @@ -1,4 +1,7 @@ em = $entityManager; } - /** - * @inheritDoc - */ - public function load(ObjectManager $manager) + public function load(ObjectManager $manager): void { $table_name = $this->em->getClassMetadata(Part::class)->getTableName(); $this->em->getConnection()->exec("ALTER TABLE `${table_name}` AUTO_INCREMENT = 1;"); @@ -91,16 +89,16 @@ class PartFixtures extends Fixture $orderdetail = new Orderdetail(); $orderdetail->setSupplier($manager->find(Supplier::class, 1)); - $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice(10)); - $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice(15)); + $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice("10.0")); + $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice("15.0")); $part->addOrderdetail($orderdetail); $orderdetail = new Orderdetail(); $orderdetail->setSupplierpartnr('BC 547'); $orderdetail->setObsolete(true); $orderdetail->setSupplier($manager->find(Supplier::class, 1)); - $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice(10)); - $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice(15)); + $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice("10.0")); + $orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice("15.1")); $part->addOrderdetail($orderdetail); $attachment = new PartAttachment(); @@ -119,4 +117,4 @@ class PartFixtures extends Fixture $manager->persist($part); $manager->flush(); } -} \ No newline at end of file +} diff --git a/src/DataTables/Adapter/FetchJoinORMAdapter.php b/src/DataTables/Adapter/FetchJoinORMAdapter.php index 1f0f7bac..a1fc27f2 100644 --- a/src/DataTables/Adapter/FetchJoinORMAdapter.php +++ b/src/DataTables/Adapter/FetchJoinORMAdapter.php @@ -47,7 +47,6 @@ use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\Tools\Pagination\Paginator; use Omines\DataTablesBundle\Adapter\AdapterQuery; use Omines\DataTablesBundle\Adapter\Doctrine\Event\ORMAdapterQueryEvent; -use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapterEvents; use Omines\DataTablesBundle\Column\AbstractColumn; use Symfony\Component\OptionsResolver\OptionsResolver; diff --git a/src/DataTables/Column/EntityColumn.php b/src/DataTables/Column/EntityColumn.php index c02dcf72..52be254f 100644 --- a/src/DataTables/Column/EntityColumn.php +++ b/src/DataTables/Column/EntityColumn.php @@ -90,7 +90,7 @@ class EntityColumn extends AbstractColumn /** @var AbstractDBElement|null $entity */ $entity = $this->accessor->getValue($context, $options['property']); - if ($entity !== null) { + if (null !== $entity) { if (null !== $entity->getID()) { return sprintf( '%s', @@ -101,6 +101,7 @@ class EntityColumn extends AbstractColumn return sprintf('%s', $value); } + return ''; }; }); diff --git a/src/DataTables/Column/IconLinkColumn.php b/src/DataTables/Column/IconLinkColumn.php index 54859e33..7239f6a0 100644 --- a/src/DataTables/Column/IconLinkColumn.php +++ b/src/DataTables/Column/IconLinkColumn.php @@ -1,4 +1,7 @@ setDefaults([ - 'icon' => 'fas fa-fw fa-edit', - 'title' => null, - 'href' => null, - 'disabled' => false, - ]); + 'icon' => 'fas fa-fw fa-edit', + 'title' => null, + 'href' => null, + 'disabled' => false, + ]); $resolver->setAllowedTypes('title', ['null', 'string', 'callable']); $resolver->setAllowedTypes('icon', ['null', 'string', 'callable']); @@ -60,7 +58,7 @@ class IconLinkColumn extends AbstractColumn $title = $this->getTitle($value, $context); $disabled = $this->getDisabled($value, $context); - if ($href !== null) { + if (null !== $href) { return sprintf( '', $disabled ? 'disabled' : '', @@ -70,7 +68,7 @@ class IconLinkColumn extends AbstractColumn ); } - return ""; + return ''; } protected function getDisabled($value, $context): bool @@ -82,6 +80,7 @@ class IconLinkColumn extends AbstractColumn if (is_callable($provider)) { return call_user_func($provider, $value, $context); } + return false; } @@ -123,4 +122,4 @@ class IconLinkColumn extends AbstractColumn return null; } -} \ No newline at end of file +} diff --git a/src/DataTables/Column/LogEntryTargetColumn.php b/src/DataTables/Column/LogEntryTargetColumn.php index c9cd3c5c..d6c69655 100644 --- a/src/DataTables/Column/LogEntryTargetColumn.php +++ b/src/DataTables/Column/LogEntryTargetColumn.php @@ -42,9 +42,15 @@ declare(strict_types=1); namespace App\DataTables\Column; +use App\Entity\Attachments\Attachment; use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractNamedDBElement; +use App\Entity\Contracts\NamedElementInterface; use App\Entity\LogSystem\AbstractLogEntry; +use App\Entity\Parameters\AbstractParameter; +use App\Entity\Parts\PartLot; +use App\Entity\PriceInformations\Orderdetail; +use App\Entity\PriceInformations\Pricedetail; use App\Exceptions\EntityNotSupportedException; use App\Services\ElementTypeNameGenerator; use App\Services\EntityURLGenerator; @@ -80,6 +86,8 @@ class LogEntryTargetColumn extends AbstractColumn public function configureOptions(OptionsResolver $resolver) { parent::configureOptions($resolver); + $resolver->setDefault('show_associated', true); + return $this; } @@ -88,31 +96,27 @@ class LogEntryTargetColumn extends AbstractColumn /** @var AbstractLogEntry $context */ $target = $this->entryRepository->getTargetElement($context); + $tmp = ''; + //The element is existing - if ($target instanceof AbstractNamedDBElement) { + if ($target instanceof NamedElementInterface && !empty($target->getName())) { try { - return sprintf( + $tmp = sprintf( '%s', $this->entityURLGenerator->infoURL($target), $this->elementTypeNameGenerator->getTypeNameCombination($target, true) ); } catch (EntityNotSupportedException $exception) { - return $this->elementTypeNameGenerator->getTypeNameCombination($target, true); + $tmp = $this->elementTypeNameGenerator->getTypeNameCombination($target, true); } - } - - //Target does not have a name - if ($target instanceof AbstractDBElement) { - return sprintf( + } elseif ($target instanceof AbstractDBElement) { //Target does not have a name + $tmp = sprintf( '%s: %s', $this->elementTypeNameGenerator->getLocalizedTypeLabel($target), $target->getID() ); - } - - //Element was deleted - if (null === $target && $context->hasTarget()) { - return sprintf( + } elseif (null === $target && $context->hasTarget()) { //Element was deleted + $tmp = sprintf( '%s: %s [%s]', $this->elementTypeNameGenerator->getLocalizedTypeLabel($context->getTargetClass()), $context->getTargetID(), @@ -120,7 +124,34 @@ class LogEntryTargetColumn extends AbstractColumn ); } + //Add a hint to the associated element if possible + if (null !== $target && $this->options['show_associated']) { + if ($target instanceof Attachment && $target->getElement() !== null) { + $on = $target->getElement(); + } elseif ($target instanceof AbstractParameter && $target->getElement() !== null) { + $on = $target->getElement(); + } elseif ($target instanceof PartLot && $target->getPart() !== null) { + $on = $target->getPart(); + } elseif ($target instanceof Orderdetail && $target->getPart() !== null) { + $on = $target->getPart(); + } elseif ($target instanceof Pricedetail && $target->getOrderdetail() !== null && $target->getOrderdetail()->getPart() !== null) { + $on = $target->getOrderdetail()->getPart(); + } + + if (isset($on) && is_object($on)) { + try { + $tmp .= sprintf( + ' (%s)', + $this->entityURLGenerator->infoURL($on), + $this->elementTypeNameGenerator->getTypeNameCombination($on, true) + ); + } catch (EntityNotSupportedException $exception) { + $tmp .= ' (' . $this->elementTypeNameGenerator->getTypeNameCombination($target, true) .')'; + } + } + } + //Log is not associated with an element - return ''; + return $tmp; } } diff --git a/src/DataTables/Column/PartAttachmentsColumn.php b/src/DataTables/Column/PartAttachmentsColumn.php index ab45d3b1..f3f43cc7 100644 --- a/src/DataTables/Column/PartAttachmentsColumn.php +++ b/src/DataTables/Column/PartAttachmentsColumn.php @@ -112,6 +112,7 @@ class PartAttachmentsColumn extends AbstractColumn public function configureOptions(OptionsResolver $resolver) { parent::configureOptions($resolver); + return $this; } } diff --git a/src/DataTables/Column/RevertLogColumn.php b/src/DataTables/Column/RevertLogColumn.php index 09b78d4c..43b0d3c2 100644 --- a/src/DataTables/Column/RevertLogColumn.php +++ b/src/DataTables/Column/RevertLogColumn.php @@ -1,4 +1,7 @@ security = $security; } - /** - * @inheritDoc - */ public function normalize($value) { return $value; @@ -68,7 +66,7 @@ class RevertLogColumn extends AbstractColumn return ''; } - $disabled = !$this->security->isGranted('revert_element', $context->getTargetClass()); + $disabled = ! $this->security->isGranted('revert_element', $context->getTargetClass()); $tmp = '
'; $tmp .= sprintf( @@ -90,4 +88,4 @@ class RevertLogColumn extends AbstractColumn return $tmp; } -} \ No newline at end of file +} diff --git a/src/DataTables/LogDataTable.php b/src/DataTables/LogDataTable.php index 9ae2b8db..135e9717 100644 --- a/src/DataTables/LogDataTable.php +++ b/src/DataTables/LogDataTable.php @@ -70,7 +70,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; -use Symfony\Flex\Options; class LogDataTable implements DataTableTypeInterface { @@ -92,12 +91,12 @@ class LogDataTable implements DataTableTypeInterface $this->security = $security; } - public function configureOptions(OptionsResolver $optionsResolver) + public function configureOptions(OptionsResolver $optionsResolver): void { $optionsResolver->setDefaults([ - 'mode' => 'system_log', - 'filter_elements' => [], - ]); + 'mode' => 'system_log', + 'filter_elements' => [], + ]); $optionsResolver->setAllowedValues('mode', ['system_log', 'element_history', 'last_activity']); } @@ -108,7 +107,6 @@ class LogDataTable implements DataTableTypeInterface $this->configureOptions($resolver); $options = $resolver->resolve($options); - $dataTable->add('symbol', TextColumn::class, [ 'label' => '', 'render' => function ($value, AbstractLogEntry $context) { @@ -179,7 +177,7 @@ class LogDataTable implements DataTableTypeInterface $dataTable->add('level', TextColumn::class, [ 'label' => $this->translator->trans('log.level'), - 'visible' => $options['mode'] === 'system_log', + 'visible' => 'system_log' === $options['mode'], 'propertyPath' => 'levelString', 'render' => function (string $value, AbstractLogEntry $context) { return $value; @@ -214,13 +212,14 @@ class LogDataTable implements DataTableTypeInterface $dataTable->add('target', LogEntryTargetColumn::class, [ 'label' => $this->translator->trans('log.target'), + 'show_associated' => $options['mode'] !== 'element_history', ]); $dataTable->add('extra', LogEntryExtraColumn::class, [ 'label' => $this->translator->trans('log.extra'), ]); - $dataTable->add('timeTravel', IconLinkColumn::class,[ + $dataTable->add('timeTravel', IconLinkColumn::class, [ 'label' => '', 'icon' => 'fas fa-fw fa-eye', 'href' => function ($value, AbstractLogEntry $context) { @@ -231,26 +230,25 @@ class LogDataTable implements DataTableTypeInterface ) { try { $target = $this->logRepo->getTargetElement($context); - if($target !== null) { - $str = $this->entityURLGenerator->timeTravelURL($target, $context->getTimestamp()); - return $str; + if (null !== $target) { + return $this->entityURLGenerator->timeTravelURL($target, $context->getTimestamp()); } } catch (EntityNotSupportedException $exception) { return null; } } + return null; }, 'disabled' => function ($value, AbstractLogEntry $context) { return - !$this->security->isGranted('@tools.timetravel') - || !$this->security->isGranted('show_history', $context->getTargetClass()); - } - + ! $this->security->isGranted('@tools.timetravel') + || ! $this->security->isGranted('show_history', $context->getTargetClass()); + }, ]); $dataTable->add('actionRevert', RevertLogColumn::class, [ - 'label' => '' + 'label' => '', ]); $dataTable->addOrderBy('timestamp', DataTable::SORT_DESCENDING); @@ -270,12 +268,12 @@ class LogDataTable implements DataTableTypeInterface ->from(AbstractLogEntry::class, 'log') ->leftJoin('log.user', 'user'); - if ($options['mode'] === 'last_activity') { - $builder->where('log INSTANCE OF ' . ElementCreatedLogEntry::class) - ->orWhere('log INSTANCE OF ' . ElementDeletedLogEntry::class) - ->orWhere('log INSTANCE OF ' . ElementEditedLogEntry::class) - ->orWhere('log INSTANCE OF ' . CollectionElementDeleted::class) - ->andWhere('log.target_type NOT IN (:disallowed)');; + if ('last_activity' === $options['mode']) { + $builder->where('log INSTANCE OF '.ElementCreatedLogEntry::class) + ->orWhere('log INSTANCE OF '.ElementDeletedLogEntry::class) + ->orWhere('log INSTANCE OF '.ElementEditedLogEntry::class) + ->orWhere('log INSTANCE OF '.CollectionElementDeleted::class) + ->andWhere('log.target_type NOT IN (:disallowed)'); $builder->setParameter('disallowed', [ AbstractLogEntry::targetTypeClassToID(User::class), @@ -283,13 +281,13 @@ class LogDataTable implements DataTableTypeInterface ]); } - if (!empty($options['filter_elements'])) { + if (! empty($options['filter_elements'])) { foreach ($options['filter_elements'] as $element) { /** @var AbstractDBElement $element */ $target_type = AbstractLogEntry::targetTypeClassToID(get_class($element)); $target_id = $element->getID(); - $builder->orWhere("log.target_type = $target_type AND log.target_id = $target_id"); + $builder->orWhere("log.target_type = ${target_type} AND log.target_id = ${target_id}"); } } } diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php index 01751d2f..34dc669e 100644 --- a/src/DataTables/PartsDataTable.php +++ b/src/DataTables/PartsDataTable.php @@ -93,17 +93,17 @@ final class PartsDataTable implements DataTableTypeInterface $this->attachmentURLGenerator = $attachmentURLGenerator; } - public function configureOptions(OptionsResolver $optionsResolver) + public function configureOptions(OptionsResolver $optionsResolver): void { $optionsResolver->setDefaults([ - 'category' => null, - 'footprint' => null, - 'manufacturer' => null, - 'storelocation' => null, - 'supplier' => null, - 'tag' => null, - 'search' => null, - ]); + 'category' => null, + 'footprint' => null, + 'manufacturer' => null, + 'storelocation' => null, + 'supplier' => null, + 'tag' => null, + 'search' => null, + ]); $optionsResolver->setAllowedTypes('category', ['null', Category::class]); $optionsResolver->setAllowedTypes('footprint', ['null', Footprint::class]); @@ -113,20 +113,20 @@ final class PartsDataTable implements DataTableTypeInterface $optionsResolver->setAllowedTypes('search', ['null', 'string']); //Configure search options - $optionsResolver->setDefault('search_options', function (OptionsResolver $resolver) { + $optionsResolver->setDefault('search_options', function (OptionsResolver $resolver): void { $resolver->setDefaults([ - 'name' => true, - 'category' => true, - 'description' => true, - 'store_location' => true, - 'comment' => true, - 'ordernr' => true, - 'supplier' => false, - 'manufacturer' => false, - 'footprint' => false, - 'tags' => false, - 'regex' => false, - ]); + 'name' => true, + 'category' => true, + 'description' => true, + 'store_location' => true, + 'comment' => true, + 'ordernr' => true, + 'supplier' => false, + 'manufacturer' => false, + 'footprint' => false, + 'tags' => false, + 'regex' => false, + ]); $resolver->setAllowedTypes('name', 'bool'); $resolver->setAllowedTypes('category', 'bool'); $resolver->setAllowedTypes('description', 'bool'); @@ -375,8 +375,8 @@ final class PartsDataTable implements DataTableTypeInterface $builder->andWhere('part.tags LIKE :tag')->setParameter('tag', '%'.$options['tag'].'%'); } - if (!empty($options['search'])) { - if (!$options['search_options']['regex']) { + if (! empty($options['search'])) { + if (! $options['search_options']['regex']) { //Dont show results, if no things are selected $builder->andWhere('0=1'); $defined = false; @@ -463,7 +463,6 @@ final class PartsDataTable implements DataTableTypeInterface if ($defined) { $builder->setParameter('search', $options['search']); } - } } } diff --git a/src/Entity/Attachments/Attachment.php b/src/Entity/Attachments/Attachment.php index 6d97cae7..ff6cc8cd 100644 --- a/src/Entity/Attachments/Attachment.php +++ b/src/Entity/Attachments/Attachment.php @@ -365,7 +365,6 @@ abstract class Attachment extends AbstractNamedDBElement /** * Sets the element that is associated with this attachment. * - * @param AttachmentContainingDBElement $element * @return $this */ public function setElement(AttachmentContainingDBElement $element): self @@ -394,7 +393,6 @@ abstract class Attachment extends AbstractNamedDBElement } /** - * @param AttachmentType $attachement_type * @return $this */ public function setAttachmentType(AttachmentType $attachement_type): self @@ -408,7 +406,6 @@ abstract class Attachment extends AbstractNamedDBElement * Sets the url associated with this attachment. * If the url is empty nothing is changed, to not override the file path. * - * @param string|null $url * @return Attachment */ public function setURL(?string $url): self diff --git a/src/Entity/Attachments/AttachmentContainingDBElement.php b/src/Entity/Attachments/AttachmentContainingDBElement.php index e6df1976..87ca49f4 100644 --- a/src/Entity/Attachments/AttachmentContainingDBElement.php +++ b/src/Entity/Attachments/AttachmentContainingDBElement.php @@ -22,8 +22,8 @@ declare(strict_types=1); namespace App\Entity\Attachments; -use App\Entity\Base\MasterAttachmentTrait; use App\Entity\Base\AbstractNamedDBElement; +use App\Entity\Base\MasterAttachmentTrait; use App\Entity\Contracts\HasAttachmentsInterface; use App\Entity\Contracts\HasMasterAttachmentInterface; use Doctrine\Common\Collections\ArrayCollection; @@ -39,8 +39,8 @@ abstract class AttachmentContainingDBElement extends AbstractNamedDBElement impl /** * @var Attachment[]|Collection - * //TODO - * //@ORM\OneToMany(targetEntity="Attachment", mappedBy="element") + * //TODO + * //@ORM\OneToMany(targetEntity="Attachment", mappedBy="element") * * Mapping is done in sub classes like part */ @@ -51,6 +51,25 @@ abstract class AttachmentContainingDBElement extends AbstractNamedDBElement impl $this->attachments = new ArrayCollection(); } + public function __clone() + { + if ($this->id) { + $attachments = $this->attachments; + $this->attachments = new ArrayCollection(); + //Set master attachment is needed + foreach ($attachments as $attachment) { + $clone = clone $attachment; + if ($attachment === $this->master_picture_attachment) { + $this->setMasterPictureAttachment($clone); + } + $this->addAttachment($clone); + } + } + + //Parent has to be last call, as it resets the ID + parent::__clone(); + } + /******************************************************************************** * * Getters @@ -86,7 +105,6 @@ abstract class AttachmentContainingDBElement extends AbstractNamedDBElement impl /** * Removes the given attachment from this element. * - * @param Attachment $attachment * @return $this */ public function removeAttachment(Attachment $attachment): self @@ -95,23 +113,4 @@ abstract class AttachmentContainingDBElement extends AbstractNamedDBElement impl return $this; } - - public function __clone() - { - if ($this->id) { - $attachments = $this->attachments; - $this->attachments = new ArrayCollection(); - //Set master attachment is needed - foreach ($attachments as $attachment) { - $clone = clone $attachment; - if ($attachment === $this->master_picture_attachment) { - $this->setMasterPictureAttachment($clone); - } - $this->addAttachment($clone); - } - } - - //Parent has to be last call, as it resets the ID - parent::__clone(); - } } diff --git a/src/Entity/Attachments/AttachmentType.php b/src/Entity/Attachments/AttachmentType.php index 865651a1..9971e547 100644 --- a/src/Entity/Attachments/AttachmentType.php +++ b/src/Entity/Attachments/AttachmentType.php @@ -23,10 +23,12 @@ declare(strict_types=1); namespace App\Entity\Attachments; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\Parameters\AttachmentTypeParameter; use App\Validator\Constraints\ValidFileFilter; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; /** * Class AttachmentType. @@ -56,9 +58,17 @@ class AttachmentType extends AbstractStructuralDBElement /** * @var Collection|AttachmentTypeAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\AttachmentTypeAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; + /** @var AttachmentTypeParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\AttachmentTypeParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * @var Collection|Attachment[] * @ORM\OneToMany(targetEntity="Attachment", mappedBy="attachment_type") diff --git a/src/Entity/Base/AbstractCompany.php b/src/Entity/Base/AbstractCompany.php index 4dd214ac..e9912b9b 100644 --- a/src/Entity/Base/AbstractCompany.php +++ b/src/Entity/Base/AbstractCompany.php @@ -173,7 +173,7 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement /** * Set the addres. * - * @param string $new_address the new address (with "\n" as line break) + * @param string $new_address the new address (with "\n" as line break) * * @return $this */ @@ -188,6 +188,7 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement * Set the phone number. * * @param string $new_phone_number the new phone number + * * @return $this */ public function setPhoneNumber(string $new_phone_number): self @@ -201,6 +202,7 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement * Set the fax number. * * @param string $new_fax_number the new fax number + * * @return $this */ public function setFaxNumber(string $new_fax_number): self @@ -214,6 +216,7 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement * Set the e-mail address. * * @param string $new_email_address the new e-mail address + * * @return $this */ public function setEmailAddress(string $new_email_address): self @@ -227,6 +230,7 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement * Set the website. * * @param string $new_website the new website + * * @return $this */ public function setWebsite(string $new_website): self @@ -240,6 +244,7 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement * Set the link to the website of an article. * * @param string $new_url the new URL with the placeholder %PARTNUMBER% for the part number + * * @return $this */ public function setAutoProductUrl(string $new_url): self diff --git a/src/Entity/Base/AbstractNamedDBElement.php b/src/Entity/Base/AbstractNamedDBElement.php index d0531924..9356360e 100644 --- a/src/Entity/Base/AbstractNamedDBElement.php +++ b/src/Entity/Base/AbstractNamedDBElement.php @@ -57,6 +57,15 @@ abstract class AbstractNamedDBElement extends AbstractDBElement implements Named return $this->getName(); } + public function __clone() + { + if ($this->id) { + //We create a new object, so give it a new creation date + $this->addedDate = null; + } + parent::__clone(); // TODO: Change the autogenerated stub + } + /******************************************************************************** * * Getters @@ -89,15 +98,7 @@ abstract class AbstractNamedDBElement extends AbstractDBElement implements Named public function setName(string $new_name): self { $this->name = $new_name; + return $this; } - - public function __clone() - { - if ($this->id) { - //We create a new object, so give it a new creation date - $this->addedDate = null; - } - parent::__clone(); // TODO: Change the autogenerated stub - } } diff --git a/src/Entity/Base/AbstractStructuralDBElement.php b/src/Entity/Base/AbstractStructuralDBElement.php index 687f0c3a..3bb3da16 100644 --- a/src/Entity/Base/AbstractStructuralDBElement.php +++ b/src/Entity/Base/AbstractStructuralDBElement.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace App\Entity\Base; use App\Entity\Attachments\AttachmentContainingDBElement; +use App\Entity\Parameters\ParametersTrait; use App\Validator\Constraints\NoneOfItsChildren; use function count; use Doctrine\Common\Collections\ArrayCollection; @@ -50,6 +51,8 @@ use Symfony\Component\Serializer\Annotation\Groups; */ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement { + use ParametersTrait; + public const ID_ROOT_ELEMENT = 0; /** @@ -101,6 +104,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement { parent::__construct(); $this->children = new ArrayCollection(); + $this->parameters = new ArrayCollection(); } /****************************************************************************** @@ -111,7 +115,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement * Check if this element is a child of another element (recursive). * * @param AbstractStructuralDBElement $another_element the object to compare - * IMPORTANT: both objects to compare must be from the same class (for example two "Device" objects)! + * IMPORTANT: both objects to compare must be from the same class (for example two "Device" objects)! * * @return bool True, if this element is child of $another_element. * @@ -312,13 +316,14 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement } /** - * @param static[]|Collection $elements + * @param static[]|Collection $elements + * * @return $this */ public function setChildren($elements): self { - if (!is_array($elements) && !$elements instanceof Collection) { - throw new InvalidArgumentException('$elements must be an array or Collection!'); + if (! is_array($elements) && ! $elements instanceof Collection) { + throw new InvalidArgumentException('$elements must be an array or Collection!'); } $this->children = $elements; @@ -327,7 +332,6 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement } /** - * @param bool $not_selectable * @return AbstractStructuralDBElement */ public function setNotSelectable(bool $not_selectable): self diff --git a/src/Entity/Base/MasterAttachmentTrait.php b/src/Entity/Base/MasterAttachmentTrait.php index fc81ba02..4f1a2eb2 100644 --- a/src/Entity/Base/MasterAttachmentTrait.php +++ b/src/Entity/Base/MasterAttachmentTrait.php @@ -72,7 +72,6 @@ trait MasterAttachmentTrait /** * Sets the new master picture for this part. * - * @param Attachment|null $new_master_attachment * @return $this */ public function setMasterPictureAttachment(?Attachment $new_master_attachment): self diff --git a/src/Entity/Contracts/HasAttachmentsInterface.php b/src/Entity/Contracts/HasAttachmentsInterface.php index f27d7b46..7214b15d 100644 --- a/src/Entity/Contracts/HasAttachmentsInterface.php +++ b/src/Entity/Contracts/HasAttachmentsInterface.php @@ -1,4 +1,7 @@ Orderdetail::class, self::TARGET_TYPE_PRICEDETAIL => Pricedetail::class, self::TARGET_TYPE_MEASUREMENTUNIT => MeasurementUnit::class, + self::TARGET_TYPE_PARAMETER => AbstractParameter::class, ]; /** @var User The user which has caused this log entry @@ -203,7 +206,6 @@ abstract class AbstractLogEntry extends AbstractDBElement /** * Sets the user that caused the event. * - * @param User $user * @return $this */ public function setUser(User $user): self @@ -226,7 +228,6 @@ abstract class AbstractLogEntry extends AbstractDBElement /** * Sets the timestamp when the event happened. * - * @param DateTime $timestamp * @return $this */ public function setTimestamp(DateTime $timestamp): self @@ -255,7 +256,6 @@ abstract class AbstractLogEntry extends AbstractDBElement /** * Sets the new level of this log entry. * - * @param int $level * @return $this */ public function setLevel(int $level): self @@ -281,7 +281,6 @@ abstract class AbstractLogEntry extends AbstractDBElement /** * Sets the priority level of this log entry as PSR3 compatible string. * - * @param string $level * @return $this */ public function setLevelString(string $level): self @@ -370,12 +369,13 @@ abstract class AbstractLogEntry extends AbstractDBElement /** * Sets the target ID of the element associated with this element. - * @param int $target_id + * * @return $this */ public function setTargetElementID(int $target_id): self { $this->target_id = $target_id; + return $this; } diff --git a/src/Entity/LogSystem/CollectionElementDeleted.php b/src/Entity/LogSystem/CollectionElementDeleted.php index 3d127e41..a37a8c8b 100644 --- a/src/Entity/LogSystem/CollectionElementDeleted.php +++ b/src/Entity/LogSystem/CollectionElementDeleted.php @@ -1,4 +1,7 @@ extra['i']; } - /** - * @inheritDoc - */ public function isUndoEvent(): bool { return isset($this->extra['u']); } - /** - * @inheritDoc - */ public function getUndoEventID(): ?int { return $this->extra['u'] ?? null; } - /** - * @inheritDoc - */ public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface { $this->extra['u'] = $event->getID(); - if ($mode === 'undo') { + if ('undo' === $mode) { $this->extra['um'] = 1; - } elseif ($mode === 'revert') { + } elseif ('revert' === $mode) { $this->extra['um'] = 2; } else { throw new \InvalidArgumentException('Passed invalid $mode!'); @@ -121,16 +118,13 @@ class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventU return $this; } - /** - * @inheritDoc - */ public function getUndoMode(): string { $mode_int = $this->extra['um'] ?? 1; - if ($mode_int === 1) { + if (1 === $mode_int) { return 'undo'; - } else { - return 'revert'; } + + return 'revert'; } -} \ No newline at end of file +} diff --git a/src/Entity/LogSystem/ConfigChangedLogEntry.php b/src/Entity/LogSystem/ConfigChangedLogEntry.php index 480bd85a..19367439 100644 --- a/src/Entity/LogSystem/ConfigChangedLogEntry.php +++ b/src/Entity/LogSystem/ConfigChangedLogEntry.php @@ -55,6 +55,7 @@ class ConfigChangedLogEntry extends AbstractLogEntry public function __construct() { parent::__construct(); + throw new LogEntryObsoleteException(); } } diff --git a/src/Entity/LogSystem/ElementCreatedLogEntry.php b/src/Entity/LogSystem/ElementCreatedLogEntry.php index cc591db3..3cbf53a3 100644 --- a/src/Entity/LogSystem/ElementCreatedLogEntry.php +++ b/src/Entity/LogSystem/ElementCreatedLogEntry.php @@ -88,57 +88,40 @@ class ElementCreatedLogEntry extends AbstractLogEntry implements LogWithCommentI return null !== $this->getCreationInstockValue(); } - /** - * @inheritDoc - */ public function hasComment(): bool { return isset($this->extra['m']); } - /** - * @inheritDoc - */ public function getComment(): ?string { return $this->extra['m'] ?? null; } - /** - * @inheritDoc - */ public function setComment(?string $new_comment): LogWithCommentInterface { $this->extra['m'] = $new_comment; + return $this; } - /** - * @inheritDoc - */ public function isUndoEvent(): bool { return isset($this->extra['u']); } - /** - * @inheritDoc - */ public function getUndoEventID(): ?int { return $this->extra['u'] ?? null; } - /** - * @inheritDoc - */ public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface { $this->extra['u'] = $event->getID(); - if ($mode === 'undo') { + if ('undo' === $mode) { $this->extra['um'] = 1; - } elseif ($mode === 'revert') { + } elseif ('revert' === $mode) { $this->extra['um'] = 2; } else { throw new \InvalidArgumentException('Passed invalid $mode!'); @@ -147,16 +130,13 @@ class ElementCreatedLogEntry extends AbstractLogEntry implements LogWithCommentI return $this; } - /** - * @inheritDoc - */ public function getUndoMode(): string { $mode_int = $this->extra['um'] ?? 1; - if ($mode_int === 1) { + if (1 === $mode_int) { return 'undo'; - } else { - return 'revert'; } + + return 'revert'; } } diff --git a/src/Entity/LogSystem/ElementDeletedLogEntry.php b/src/Entity/LogSystem/ElementDeletedLogEntry.php index c6e6c4f3..d3a7f47b 100644 --- a/src/Entity/LogSystem/ElementDeletedLogEntry.php +++ b/src/Entity/LogSystem/ElementDeletedLogEntry.php @@ -71,7 +71,6 @@ class ElementDeletedLogEntry extends AbstractLogEntry implements TimeTravelInter } /** - * @inheritDoc * @return $this */ public function setTargetElement(?AbstractDBElement $element): AbstractLogEntry @@ -80,12 +79,14 @@ class ElementDeletedLogEntry extends AbstractLogEntry implements TimeTravelInter if ($element instanceof NamedElementInterface) { $this->setOldName($element->getName()); } + return $this; } public function setOldName(string $old_name): self { $this->extra['n'] = $old_name; + return $this; } @@ -96,82 +97,60 @@ class ElementDeletedLogEntry extends AbstractLogEntry implements TimeTravelInter /** * Sets the old data for this entry. - * @param array $old_data + * * @return $this */ public function setOldData(array $old_data): self { $this->extra['o'] = $old_data; + return $this; } - /** - * @inheritDoc - */ public function hasOldDataInformations(): bool { - return !empty($this->extra['o']); + return ! empty($this->extra['o']); } - /** - * @inheritDoc - */ public function getOldData(): array { return $this->extra['o'] ?? []; } - /** - * @inheritDoc - */ public function hasComment(): bool { return isset($this->extra['m']); } - /** - * @inheritDoc - */ public function getComment(): ?string { return $this->extra['m'] ?? null; } - /** - * @inheritDoc - */ public function setComment(?string $new_comment): LogWithCommentInterface { $this->extra['m'] = $new_comment; + return $this; } - /** - * @inheritDoc - */ public function isUndoEvent(): bool { return isset($this->extra['u']); } - /** - * @inheritDoc - */ public function getUndoEventID(): ?int { return $this->extra['u'] ?? null; } - /** - * @inheritDoc - */ public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface { $this->extra['u'] = $event->getID(); - if ($mode === 'undo') { + if ('undo' === $mode) { $this->extra['um'] = 1; - } elseif ($mode === 'revert') { + } elseif ('revert' === $mode) { $this->extra['um'] = 2; } else { throw new \InvalidArgumentException('Passed invalid $mode!'); @@ -180,15 +159,13 @@ class ElementDeletedLogEntry extends AbstractLogEntry implements TimeTravelInter return $this; } - /** - * @inheritDoc - */ public function getUndoMode(): string { $mode_int = $this->extra['um'] ?? 1; - if ($mode_int === 1) { + if (1 === $mode_int) { return 'undo'; } + return 'revert'; } } diff --git a/src/Entity/LogSystem/ElementEditedLogEntry.php b/src/Entity/LogSystem/ElementEditedLogEntry.php index 2d22edc9..2b4011f2 100644 --- a/src/Entity/LogSystem/ElementEditedLogEntry.php +++ b/src/Entity/LogSystem/ElementEditedLogEntry.php @@ -65,6 +65,7 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf /** * Checks if this log contains infos about which fields has changed. + * * @return bool */ public function hasChangedFieldsInfo(): bool @@ -74,6 +75,7 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf /** * Return the names of all fields that were changed during the change. + * * @return string[] */ public function getChangedFields(): array @@ -91,93 +93,74 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf /** * Set the fields that were changed during this element change. - * @param string[] $changed_fields The names of the fields that were changed during the elements + * + * @param string[] $changed_fields The names of the fields that were changed during the elements + * * @return $this */ public function setChangedFields(array $changed_fields): self { $this->extra['f'] = $changed_fields; + return $this; } /** * Sets the old data for this entry. - * @param array $old_data + * * @return $this */ public function setOldData(array $old_data): self { $this->extra['d'] = $old_data; + return $this; } - /** - * @inheritDoc - */ public function hasOldDataInformations(): bool { - return !empty($this->extra['d']); + return ! empty($this->extra['d']); } - /** - * @inheritDoc - */ public function getOldData(): array { return $this->extra['d'] ?? []; } - /** - * @inheritDoc - */ public function hasComment(): bool { return isset($this->extra['m']); } - /** - * @inheritDoc - */ public function getComment(): ?string { return $this->extra['m'] ?? null; } - /** - * @inheritDoc - */ public function setComment(?string $new_comment): LogWithCommentInterface { $this->extra['m'] = $new_comment; + return $this; } - /** - * @inheritDoc - */ public function isUndoEvent(): bool { return isset($this->extra['u']); } - /** - * @inheritDoc - */ public function getUndoEventID(): ?int { return $this->extra['u'] ?? null; } - /** - * @inheritDoc - */ public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface { $this->extra['u'] = $event->getID(); - if ($mode === 'undo') { + if ('undo' === $mode) { $this->extra['um'] = 1; - } elseif ($mode === 'revert') { + } elseif ('revert' === $mode) { $this->extra['um'] = 2; } else { throw new \InvalidArgumentException('Passed invalid $mode!'); @@ -186,16 +169,13 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf return $this; } - /** - * @inheritDoc - */ public function getUndoMode(): string { $mode_int = $this->extra['um'] ?? 1; - if ($mode_int === 1) { + if (1 === $mode_int) { return 'undo'; - } else { - return 'revert'; } + + return 'revert'; } } diff --git a/src/Entity/LogSystem/ExceptionLogEntry.php b/src/Entity/LogSystem/ExceptionLogEntry.php index c21255f2..6f8c7d86 100644 --- a/src/Entity/LogSystem/ExceptionLogEntry.php +++ b/src/Entity/LogSystem/ExceptionLogEntry.php @@ -55,6 +55,7 @@ class ExceptionLogEntry extends AbstractLogEntry public function __construct() { parent::__construct(); + throw new LogEntryObsoleteException(); } diff --git a/src/Entity/Parameters/AbstractParameter.php b/src/Entity/Parameters/AbstractParameter.php new file mode 100644 index 00000000..095df7ee --- /dev/null +++ b/src/Entity/Parameters/AbstractParameter.php @@ -0,0 +1,418 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Base\AbstractDBElement; +use App\Entity\Base\AbstractNamedDBElement; +use Doctrine\ORM\Mapping as ORM; +use InvalidArgumentException; +use LogicException; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Validator\Constraints as Assert; + +/** + * @ORM\Entity() + * @ORM\Table("parameters") + * @ORM\InheritanceType("SINGLE_TABLE") + * @ORM\DiscriminatorColumn(name="type", type="smallint") + * @ORM\DiscriminatorMap({ + * 0 = "CategoryParameter", + * 1 = "CurrencyParameter", + * 2 = "DeviceParameter", + * 3 = "FootprintParameter", + * 4 = "GroupParameter", + * 5 = "ManufacturerParameter", + * 6 = "MeasurementUnitParameter", + * 7 = "PartParameter", + * 8 = "StorelocationParameter", + * 9 = "SupplierParameter", + * 10 = "AttachmentTypeParameter" + * }) + */ +abstract class AbstractParameter extends AbstractNamedDBElement +{ + /** + * @var string The class of the element that can be passed to this attachment. Must be overridden in subclasses. + */ + public const ALLOWED_ELEMENT_CLASS = ''; + + /** + * @var string The mathematical symbol for this specification. Can be rendered pretty later. Should be short + * @Assert\Length(max=20) + * @ORM\Column(type="string", nullable=false) + */ + protected $symbol = ''; + + /** + * @var float|null The guaranteed minimum value of this property. + * @Assert\Type({"float","null"}) + * @Assert\LessThanOrEqual(propertyPath="value_typical", message="parameters.validator.min_lesser_typical") + * @Assert\LessThan(propertyPath="value_max", message="parameters.validator.min_lesser_max") + * @ORM\Column(type="float", nullable=true) + */ + protected $value_min; + + /** + * @var float|null The typical value of this property. + * @Assert\Type({"null", "float"}) + * @ORM\Column(type="float", nullable=true) + */ + protected $value_typical; + + /** + * @var float|null The maximum value of this property. + * @Assert\Type({"float", "null"}) + * @Assert\GreaterThanOrEqual(propertyPath="value_typical", message="parameters.validator.max_greater_typical") + * @ORM\Column(type="float", nullable=true) + */ + protected $value_max; + + /** + * @var string The unit in which the value values are given (e.g. V) + * @Assert\Length(max=5) + * @ORM\Column(type="string", nullable=false) + */ + protected $unit = ''; + + /** + * @var string A text value for the given property. + * @ORM\Column(type="string", nullable=false) + */ + protected $value_text = ''; + + /** + * @var string The group this parameter belongs to. + * @ORM\Column(type="string", nullable=false, name="param_group") + */ + protected $group = ''; + + /** + * Mapping is done in sub classes. + * + * @var AbstractDBElement|null The element to which this parameter belongs to. + */ + protected $element; + + public function __construct() + { + if ('' === static::ALLOWED_ELEMENT_CLASS) { + throw new LogicException('An *Attachment class must override the ALLOWED_ELEMENT_CLASS const!'); + } + } + + /** + * Returns the name of the specification (e.g. "Collector-Base Voltage"). + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Returns the element this parameter belongs to. + * + * @return AbstractDBElement|null + */ + public function getElement(): ?AbstractDBElement + { + return $this->element; + } + + /** + * Return a formatted string version of the values of the string. + * Based on the set values it can return something like this: 34 V (12 V ... 50 V) [Text]. + * + * @return string + */ + public function getFormattedValue(): string + { + //If we just only have text value, return early + if (null === $this->value_typical && null === $this->value_min && null === $this->value_max) { + return $this->value_text; + } + + $str = ''; + $bracket_opened = false; + if ($this->value_typical) { + $str .= $this->getValueTypicalWithUnit(); + if ($this->value_min || $this->value_max) { + $bracket_opened = true; + $str .= ' ('; + } + } + + if ($this->value_max && $this->value_min) { + $str .= $this->getValueMinWithUnit().' ... '.$this->getValueMaxWithUnit(); + } elseif ($this->value_max) { + $str .= 'max. '.$this->getValueMaxWithUnit(); + } elseif ($this->value_min) { + $str .= 'min. '.$this->getValueMinWithUnit(); + } + + //Add closing bracket + if ($bracket_opened) { + $str .= ')'; + } + + if ($this->value_text) { + $str .= ' ['.$this->value_text.']'; + } + + return $str; + } + + /** + * Sets the element to which this parameter belongs to. + * + * @return $this + */ + public function setElement(AbstractDBElement $element): self + { + if (! is_a($element, static::ALLOWED_ELEMENT_CLASS)) { + throw new InvalidArgumentException(sprintf('The element associated with a %s must be a %s!', static::class, static::ALLOWED_ELEMENT_CLASS)); + } + + $this->element = $element; + + return $this; + } + + /** + * Sets the name of the specification. This value is required. + * + * @return $this + */ + public function setName(string $name): AbstractNamedDBElement + { + $this->name = $name; + + return $this; + } + + /** + * Returns the name of the group this parameter is associated to (e.g. Technical Parameters) + * @return string + */ + public function getGroup(): string + { + return $this->group; + } + + /** + * Sets the name of the group this parameter is associated to. + * @param string $group + * @return $this + */ + public function setGroup(string $group): self + { + $this->group = $group; + return $this; + } + + /** + * Returns the mathematical symbol for this specification (e.g. "V_CB"). + * + * @return string + */ + public function getSymbol(): string + { + return $this->symbol; + } + + /** + * Sets the mathematical symbol for this specification (e.g. "V_CB"). + * + * @return $this + */ + public function setSymbol(string $symbol): self + { + $this->symbol = $symbol; + + return $this; + } + + /** + * Returns The guaranteed minimum value of this property. + * + * @return float|null + */ + public function getValueMin(): ?float + { + return $this->value_min; + } + + /** + * Sets the minimum value of this property. + * + * @return $this + */ + public function setValueMin(?float $value_min): self + { + $this->value_min = $value_min; + + return $this; + } + + /** + * Returns the typical value of this property. + * + * @return float|null + */ + public function getValueTypical(): ?float + { + return $this->value_typical; + } + + /** + * Return a formatted version with the minimum value with the unit of this parameter. + * + * @return string + */ + public function getValueTypicalWithUnit(): string + { + return $this->formatWithUnit($this->value_typical); + } + + /** + * Return a formatted version with the maximum value with the unit of this parameter. + * + * @return string + */ + public function getValueMaxWithUnit(): string + { + return $this->formatWithUnit($this->value_max); + } + + /** + * Return a formatted version with the typical value with the unit of this parameter. + * + * @return string + */ + public function getValueMinWithUnit(): string + { + return $this->formatWithUnit($this->value_min); + } + + /** + * Sets the typical value of this property. + * + * @param float $value_typical + * + * @return $this + */ + public function setValueTypical(?float $value_typical): self + { + $this->value_typical = $value_typical; + + return $this; + } + + /** + * Returns the guaranteed maximum value. + * + * @return float|null + */ + public function getValueMax(): ?float + { + return $this->value_max; + } + + /** + * Sets the guaranteed maximum value. + * + * @return $this + */ + public function setValueMax(?float $value_max): self + { + $this->value_max = $value_max; + + return $this; + } + + /** + * Returns the unit used by the value (e.g. "V"). + * + * @return string + */ + public function getUnit(): string + { + return $this->unit; + } + + /** + * Sets the unit used by the value. + * + * @return $this + */ + public function setUnit(string $unit): self + { + $this->unit = $unit; + + return $this; + } + + /** + * Returns the text value. + * + * @return string + */ + public function getValueText(): string + { + return $this->value_text; + } + + /** + * Sets the text value. + * + * @return $this + */ + public function setValueText(string $value_text): self + { + $this->value_text = $value_text; + + return $this; + } + + public function getIDString(): string + { + return 'PM'.sprintf('%09d', $this->getID()); + } + + /** + * Return a string representation and (if possible) with its unit. + * + * @return string + */ + protected function formatWithUnit(float $value, string $format = '%g'): string + { + $str = \sprintf($format, $value); + if (! empty($this->unit)) { + return $str.' '.$this->unit; + } + + return $str; + } +} diff --git a/src/Entity/Parameters/AttachmentTypeParameter.php b/src/Entity/Parameters/AttachmentTypeParameter.php new file mode 100644 index 00000000..d1ad9094 --- /dev/null +++ b/src/Entity/Parameters/AttachmentTypeParameter.php @@ -0,0 +1,43 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Attachments\AttachmentType; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class AttachmentTypeParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = AttachmentType::class; + /** + * @var AttachmentType the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Attachments\AttachmentType", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/CategoryParameter.php b/src/Entity/Parameters/CategoryParameter.php new file mode 100644 index 00000000..86925755 --- /dev/null +++ b/src/Entity/Parameters/CategoryParameter.php @@ -0,0 +1,43 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Parts\Category; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class CategoryParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Category::class; + /** + * @var Category the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Parts\Category", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/CurrencyParameter.php b/src/Entity/Parameters/CurrencyParameter.php new file mode 100644 index 00000000..28f3c934 --- /dev/null +++ b/src/Entity/Parameters/CurrencyParameter.php @@ -0,0 +1,46 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\PriceInformations\Currency; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * A attachment attached to a category element. + * + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class CurrencyParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Currency::class; + + /** + * @var Currency the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\PriceInformations\Currency", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/DeviceParameter.php b/src/Entity/Parameters/DeviceParameter.php new file mode 100644 index 00000000..724ad3be --- /dev/null +++ b/src/Entity/Parameters/DeviceParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Devices\Device; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class DeviceParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Device::class; + + /** + * @var Device the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Devices\Device", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/FootprintParameter.php b/src/Entity/Parameters/FootprintParameter.php new file mode 100644 index 00000000..d92ed8cb --- /dev/null +++ b/src/Entity/Parameters/FootprintParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Parts\Footprint; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class FootprintParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Footprint::class; + + /** + * @var Footprint the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Parts\Footprint", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/GroupParameter.php b/src/Entity/Parameters/GroupParameter.php new file mode 100644 index 00000000..c6b62aa1 --- /dev/null +++ b/src/Entity/Parameters/GroupParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\UserSystem\Group; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class GroupParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Group::class; + + /** + * @var Group the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\UserSystem\Group", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/ManufacturerParameter.php b/src/Entity/Parameters/ManufacturerParameter.php new file mode 100644 index 00000000..b06633f0 --- /dev/null +++ b/src/Entity/Parameters/ManufacturerParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Parts\Manufacturer; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class ManufacturerParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Manufacturer::class; + + /** + * @var Manufacturer the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Parts\Manufacturer", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/MeasurementUnitParameter.php b/src/Entity/Parameters/MeasurementUnitParameter.php new file mode 100644 index 00000000..91ce5809 --- /dev/null +++ b/src/Entity/Parameters/MeasurementUnitParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Parts\MeasurementUnit; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class MeasurementUnitParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = MeasurementUnit::class; + + /** + * @var MeasurementUnit the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Parts\MeasurementUnit", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/ParametersTrait.php b/src/Entity/Parameters/ParametersTrait.php new file mode 100644 index 00000000..34d97a74 --- /dev/null +++ b/src/Entity/Parameters/ParametersTrait.php @@ -0,0 +1,78 @@ +. + */ + +namespace App\Entity\Parameters; + +use Doctrine\Common\Collections\Collection; +use Symfony\Component\Validator\Constraints as Assert; + +trait ParametersTrait +{ + /** + * Mapping done in subclasses. + * + * @var AbstractParameter[]|Collection + * @Assert\Valid() + */ + protected $parameters; + + /** + * Return all associated specifications. + * + * @return AbstractParameter[]|Collection + */ + public function getParameters(): Collection + { + return $this->parameters; + } + + /** + * Add a new parameter information. + * + * @return $this + */ + public function addParameter(AbstractParameter $parameter): self + { + $parameter->setElement($this); + $this->parameters->add($parameter); + + return $this; + } + + public function removeParameter(AbstractParameter $parameter): self + { + $this->parameters->removeElement($parameter); + + return $this; + } + + public function getGroupedParameters(): array + { + $tmp = []; + + foreach ($this->parameters as $parameter) { + $tmp[$parameter->getGroup()][] = $parameter; + } + return $tmp; + } +} diff --git a/src/Entity/Parameters/PartParameter.php b/src/Entity/Parameters/PartParameter.php new file mode 100644 index 00000000..d7d08cfa --- /dev/null +++ b/src/Entity/Parameters/PartParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Parts\Part; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class PartParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Part::class; + + /** + * @var Part the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Parts\Part", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/StorelocationParameter.php b/src/Entity/Parameters/StorelocationParameter.php new file mode 100644 index 00000000..44077d48 --- /dev/null +++ b/src/Entity/Parameters/StorelocationParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Parts\Storelocation; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class StorelocationParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Storelocation::class; + + /** + * @var Storelocation the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Parts\Storelocation", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parameters/SupplierParameter.php b/src/Entity/Parameters/SupplierParameter.php new file mode 100644 index 00000000..e61137a0 --- /dev/null +++ b/src/Entity/Parameters/SupplierParameter.php @@ -0,0 +1,44 @@ +. + */ + +namespace App\Entity\Parameters; + +use App\Entity\Parts\Supplier; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + +/** + * @ORM\Entity() + * @UniqueEntity(fields={"name", "group", "element"}) + */ +class SupplierParameter extends AbstractParameter +{ + public const ALLOWED_ELEMENT_CLASS = Supplier::class; + + /** + * @var Supplier the element this para is associated with + * @ORM\ManyToOne(targetEntity="App\Entity\Parts\Supplier", inversedBy="parameters") + * @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE"). + */ + protected $element; +} diff --git a/src/Entity/Parts/Category.php b/src/Entity/Parts/Category.php index a5c98475..9c0a1a09 100644 --- a/src/Entity/Parts/Category.php +++ b/src/Entity/Parts/Category.php @@ -24,8 +24,10 @@ namespace App\Entity\Parts; use App\Entity\Attachments\CategoryAttachment; use App\Entity\Base\AbstractPartsContainingDBElement; +use App\Entity\Parameters\CategoryParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; /** * Class AttachmentType. @@ -101,9 +103,17 @@ class Category extends AbstractPartsContainingDBElement /** * @var Collection|CategoryAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\CategoryAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; + /** @var CategoryParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\CategoryParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * Returns the ID as an string, defined by the element class. * This should have a form like P000014, for a part with ID 14. @@ -121,7 +131,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param string $partname_hint * @return Category */ public function setPartnameHint(string $partname_hint): self @@ -137,7 +146,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param string $partname_regex * @return Category */ public function setPartnameRegex(string $partname_regex): self @@ -153,7 +161,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param bool $disable_footprints * @return Category */ public function setDisableFootprints(bool $disable_footprints): self @@ -169,7 +176,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param bool $disable_manufacturers * @return Category */ public function setDisableManufacturers(bool $disable_manufacturers): self @@ -185,7 +191,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param bool $disable_autodatasheets * @return Category */ public function setDisableAutodatasheets(bool $disable_autodatasheets): self @@ -201,7 +206,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param bool $disable_properties * @return Category */ public function setDisableProperties(bool $disable_properties): self @@ -217,7 +221,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param string $default_description * @return Category */ public function setDefaultDescription(string $default_description): self @@ -233,7 +236,6 @@ class Category extends AbstractPartsContainingDBElement } /** - * @param string $default_comment * @return Category */ public function setDefaultComment(string $default_comment): self diff --git a/src/Entity/Parts/Footprint.php b/src/Entity/Parts/Footprint.php index 8fb7b9bb..666aa95f 100644 --- a/src/Entity/Parts/Footprint.php +++ b/src/Entity/Parts/Footprint.php @@ -52,8 +52,10 @@ namespace App\Entity\Parts; use App\Entity\Attachments\FootprintAttachment; use App\Entity\Base\AbstractPartsContainingDBElement; +use App\Entity\Parameters\FootprintParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; /** * Class Footprint. @@ -81,6 +83,7 @@ class Footprint extends AbstractPartsContainingDBElement /** * @var Collection|FootprintAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\FootprintAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; @@ -91,6 +94,13 @@ class Footprint extends AbstractPartsContainingDBElement */ protected $footprint_3d; + /** @var FootprintParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\FootprintParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})@ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * Returns the ID as an string, defined by the element class. * This should have a form like P000014, for a part with ID 14. diff --git a/src/Entity/Parts/Manufacturer.php b/src/Entity/Parts/Manufacturer.php index 113e0a03..e61e3063 100644 --- a/src/Entity/Parts/Manufacturer.php +++ b/src/Entity/Parts/Manufacturer.php @@ -52,8 +52,10 @@ namespace App\Entity\Parts; use App\Entity\Attachments\ManufacturerAttachment; use App\Entity\Base\AbstractCompany; +use App\Entity\Parameters\ManufacturerParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; /** * Class Manufacturer. @@ -81,9 +83,17 @@ class Manufacturer extends AbstractCompany /** * @var Collection|ManufacturerAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\ManufacturerAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; + /** @var ManufacturerParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\ManufacturerParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * Returns the ID as an string, defined by the element class. * This should have a form like P000014, for a part with ID 14. diff --git a/src/Entity/Parts/MeasurementUnit.php b/src/Entity/Parts/MeasurementUnit.php index 0a5213aa..78a4180d 100644 --- a/src/Entity/Parts/MeasurementUnit.php +++ b/src/Entity/Parts/MeasurementUnit.php @@ -44,6 +44,7 @@ namespace App\Entity\Parts; use App\Entity\Attachments\MeasurementUnitAttachment; use App\Entity\Base\AbstractPartsContainingDBElement; +use App\Entity\Parameters\MeasurementUnitParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; @@ -99,9 +100,17 @@ class MeasurementUnit extends AbstractPartsContainingDBElement /** * @var Collection|MeasurementUnitAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\MeasurementUnitAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; + /** @var MeasurementUnitParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\MeasurementUnitParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * Returns the ID as an string, defined by the element class. * This should have a form like P000014, for a part with ID 14. @@ -139,7 +148,6 @@ class MeasurementUnit extends AbstractPartsContainingDBElement } /** - * @param bool $isInteger * @return MeasurementUnit */ public function setIsInteger(bool $isInteger): self @@ -155,7 +163,6 @@ class MeasurementUnit extends AbstractPartsContainingDBElement } /** - * @param bool $usesSIPrefixes * @return MeasurementUnit */ public function setUseSIPrefix(bool $usesSIPrefixes): self diff --git a/src/Entity/Parts/Part.php b/src/Entity/Parts/Part.php index e2cd7623..749c8af2 100644 --- a/src/Entity/Parts/Part.php +++ b/src/Entity/Parts/Part.php @@ -53,6 +53,8 @@ namespace App\Entity\Parts; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Devices\Device; +use App\Entity\Parameters\ParametersTrait; +use App\Entity\Parameters\PartParameter; use App\Entity\Parts\PartTraits\AdvancedPropertyTrait; use App\Entity\Parts\PartTraits\BasicPropertyTrait; use App\Entity\Parts\PartTraits\InstockTrait; @@ -81,12 +83,21 @@ class Part extends AttachmentContainingDBElement use InstockTrait; use ManufacturerTrait; use OrderTrait; + use ParametersTrait; /** * TODO. */ protected $devices = []; + /** @var PartParameter[] + * @Assert\Valid() + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\PartParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + */ + protected $parameters; + /** * @ColumnSecurity(type="datetime") * @ORM\Column(type="datetime", name="datetime_added", options={"default"="CURRENT_TIMESTAMP"}) @@ -132,6 +143,27 @@ class Part extends AttachmentContainingDBElement parent::__construct(); $this->partLots = new ArrayCollection(); $this->orderdetails = new ArrayCollection(); + $this->parameters = new ArrayCollection(); + } + + public function __clone() + { + if ($this->id) { + //Deep clone part lots + $lots = $this->partLots; + $this->partLots = new ArrayCollection(); + foreach ($lots as $lot) { + $this->addPartLot(clone $lot); + } + + //Deep clone order details + $orderdetails = $this->orderdetails; + $this->orderdetails = new ArrayCollection(); + foreach ($orderdetails as $orderdetail) { + $this->addOrderdetail(clone $orderdetail); + } + } + parent::__clone(); } /** @@ -156,24 +188,4 @@ class Part extends AttachmentContainingDBElement { return $this->devices; } - - public function __clone() - { - if ($this->id) { - //Deep clone part lots - $lots = $this->partLots; - $this->partLots = new ArrayCollection(); - foreach ($lots as $lot) { - $this->addPartLot(clone $lot); - } - - //Deep clone order details - $orderdetails = $this->orderdetails; - $this->orderdetails = new ArrayCollection(); - foreach ($orderdetails as $orderdetail) { - $this->addOrderdetail(clone $orderdetail); - } - } - parent::__clone(); - } } diff --git a/src/Entity/Parts/PartLot.php b/src/Entity/Parts/PartLot.php index e1fb6cc1..2b8676dd 100644 --- a/src/Entity/Parts/PartLot.php +++ b/src/Entity/Parts/PartLot.php @@ -44,6 +44,7 @@ namespace App\Entity\Parts; use App\Entity\Base\AbstractDBElement; use App\Entity\Base\TimestampTrait; +use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\TimeStampableInterface; use App\Validator\Constraints\Selectable; use App\Validator\Constraints\ValidPartLot; @@ -61,7 +62,7 @@ use Symfony\Component\Validator\Constraints as Assert; * @ORM\HasLifecycleCallbacks() * @ValidPartLot() */ -class PartLot extends AbstractDBElement implements TimeStampableInterface +class PartLot extends AbstractDBElement implements TimeStampableInterface, NamedElementInterface { use TimestampTrait; @@ -119,6 +120,14 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface */ protected $part; + public function __clone() + { + if ($this->id) { + $this->addedDate = null; + } + parent::__clone(); + } + /** * Returns the ID as an string, defined by the element class. * This should have a form like P000014, for a part with ID 14. @@ -161,7 +170,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface /** * Sets the description of the part lot. * - * @param string $description * @return PartLot */ public function setDescription(string $description): self @@ -184,7 +192,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface /** * Sets the comment for this part lot. * - * @param string $comment * @return PartLot */ public function setComment(string $comment): self @@ -231,7 +238,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface /** * Sets the storage location, where this part lot is stored. * - * @param Storelocation|null $storage_location * @return PartLot */ public function setStorageLocation(?Storelocation $storage_location): self @@ -254,8 +260,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface /** * Sets the part that is stored in this part lot. * - * @param Part $part - * * @return PartLot */ public function setPart(Part $part): self @@ -278,7 +282,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface /** * Set the unknown instock status of this part lot. * - * @param bool $instock_unknown * @return PartLot */ public function setInstockUnknown(bool $instock_unknown): self @@ -316,7 +319,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface } /** - * @param bool $needs_refill * @return PartLot */ public function setNeedsRefill(bool $needs_refill): self @@ -326,11 +328,11 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface return $this; } - public function __clone() + /** + * @inheritDoc + */ + public function getName(): string { - if($this->id) { - $this->addedDate = null; - } - parent::__clone(); + return $this->description; } } diff --git a/src/Entity/Parts/PartTraits/AdvancedPropertyTrait.php b/src/Entity/Parts/PartTraits/AdvancedPropertyTrait.php index aeebd92a..111f92dc 100644 --- a/src/Entity/Parts/PartTraits/AdvancedPropertyTrait.php +++ b/src/Entity/Parts/PartTraits/AdvancedPropertyTrait.php @@ -106,6 +106,7 @@ trait AdvancedPropertyTrait * Sets a comma separated list of tags, that are assigned to this part. * * @param string $tags The new tags + * * @return $this */ public function setTags(string $tags): self @@ -129,6 +130,7 @@ trait AdvancedPropertyTrait * Sett to null, if the mass is unknown. * * @param float|null $mass the new mass + * * @return $this */ public function setMass(?float $mass): self diff --git a/src/Entity/Parts/PartTraits/BasicPropertyTrait.php b/src/Entity/Parts/PartTraits/BasicPropertyTrait.php index db66b460..9eeab4ee 100644 --- a/src/Entity/Parts/PartTraits/BasicPropertyTrait.php +++ b/src/Entity/Parts/PartTraits/BasicPropertyTrait.php @@ -164,6 +164,7 @@ trait BasicPropertyTrait * Sets the description of this part. * * @param string $new_description the new description + * * @return $this */ public function setDescription(?string $new_description): self @@ -177,6 +178,7 @@ trait BasicPropertyTrait * Sets the comment property of this part. * * @param string $new_comment the new comment + * * @return $this */ public function setComment(string $new_comment): self @@ -191,6 +193,7 @@ trait BasicPropertyTrait * The category property is required for every part, so you can not pass null like the other properties (footprints). * * @param Category $category The new category of this part + * * @return $this */ public function setCategory(Category $category): self @@ -205,6 +208,7 @@ trait BasicPropertyTrait * * @param Footprint|null $new_footprint The new footprint of this part. Set to null, if this part should not have * a footprint. + * * @return $this */ public function setFootprint(?Footprint $new_footprint): self @@ -219,6 +223,7 @@ trait BasicPropertyTrait * * @param bool $new_favorite_status The new favorite status, that should be applied on this part. * Set this to true, when the part should be a favorite. + * * @return $this */ public function setFavorite(bool $new_favorite_status): self diff --git a/src/Entity/Parts/PartTraits/InstockTrait.php b/src/Entity/Parts/PartTraits/InstockTrait.php index 65423864..9678ac96 100644 --- a/src/Entity/Parts/PartTraits/InstockTrait.php +++ b/src/Entity/Parts/PartTraits/InstockTrait.php @@ -90,7 +90,7 @@ trait InstockTrait /** * Adds the given part lot, to the list of part lots. * The part lot is assigned to this part. - * @param PartLot $lot + * * @return $this */ public function addPartLot(PartLot $lot): self @@ -105,6 +105,7 @@ trait InstockTrait * Removes the given part lot from the list of part lots. * * @param PartLot $lot the part lot that should be deleted + * * @return $this */ public function removePartLot(PartLot $lot): self @@ -126,7 +127,7 @@ trait InstockTrait /** * Sets the measurement unit in which the part's amount should be measured. * Set to null, if the part should be measured in quantities. - * @param MeasurementUnit|null $partUnit + * * @return $this */ public function setPartUnit(?MeasurementUnit $partUnit): self @@ -172,7 +173,6 @@ trait InstockTrait * Part Lots that have unknown value or are expired, are not used for this value. * * @return float The amount of parts given in partUnit - * */ public function getAmountSum(): float { @@ -199,6 +199,7 @@ trait InstockTrait * See getPartUnit() for the associated unit. * * @param float $new_minamount the new count of parts which should be in stock at least + * * @return $this */ public function setMinAmount(float $new_minamount): self diff --git a/src/Entity/Parts/PartTraits/ManufacturerTrait.php b/src/Entity/Parts/PartTraits/ManufacturerTrait.php index b393c843..0717e45e 100644 --- a/src/Entity/Parts/PartTraits/ManufacturerTrait.php +++ b/src/Entity/Parts/PartTraits/ManufacturerTrait.php @@ -136,7 +136,6 @@ trait ManufacturerTrait * Sets the manufacturing status for this part * See getManufacturingStatus() for valid values. * - * @param string $manufacturing_status * @return Part */ public function setManufacturingStatus(string $manufacturing_status): self @@ -167,7 +166,6 @@ trait ManufacturerTrait /** * Sets the manufacturer product number (MPN) for this part. * - * @param string $manufacturer_product_number * @return Part */ public function setManufacturerProductNumber(string $manufacturer_product_number): self @@ -182,6 +180,7 @@ trait ManufacturerTrait * Set to "" if this part should use the automatically URL based on its manufacturer. * * @param string $new_url The new url + * * @return $this */ public function setManufacturerProductURL(string $new_url): self @@ -196,6 +195,7 @@ trait ManufacturerTrait * * @param Manufacturer|null $new_manufacturer The new Manufacturer of this part. Set to null, if this part should * not have a manufacturer. + * * @return $this */ public function setManufacturer(?Manufacturer $new_manufacturer): self diff --git a/src/Entity/Parts/PartTraits/OrderTrait.php b/src/Entity/Parts/PartTraits/OrderTrait.php index 20eb71dd..8b022e67 100644 --- a/src/Entity/Parts/PartTraits/OrderTrait.php +++ b/src/Entity/Parts/PartTraits/OrderTrait.php @@ -144,6 +144,7 @@ trait OrderTrait * The orderdetail is assigned to this part. * * @param Orderdetail $orderdetail the orderdetail that should be added + * * @return $this */ public function addOrderdetail(Orderdetail $orderdetail): self @@ -156,7 +157,7 @@ trait OrderTrait /** * Removes the given orderdetail from the list of orderdetails. - * @param Orderdetail $orderdetail + * * @return $this */ public function removeOrderdetail(Orderdetail $orderdetail): self @@ -177,6 +178,7 @@ trait OrderTrait * (if the part has exactly one orderdetails, * set this orderdetails as order orderdetails. * Otherwise, set "no order orderdetails") + * * @return $this */ public function setManualOrder(bool $new_manual_order, int $new_order_quantity = 1, ?Orderdetail $new_order_orderdetail = null): self diff --git a/src/Entity/Parts/Storelocation.php b/src/Entity/Parts/Storelocation.php index 6efe730f..3af60cbd 100644 --- a/src/Entity/Parts/Storelocation.php +++ b/src/Entity/Parts/Storelocation.php @@ -52,8 +52,10 @@ namespace App\Entity\Parts; use App\Entity\Attachments\StorelocationAttachment; use App\Entity\Base\AbstractPartsContainingDBElement; +use App\Entity\Parameters\StorelocationParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; /** * Class Store location. @@ -85,11 +87,18 @@ class Storelocation extends AbstractPartsContainingDBElement * @ORM\ManyToMany(targetEntity="Part", fetch="EXTRA_LAZY") * @ORM\JoinTable(name="part_lots", * joinColumns={@ORM\JoinColumn(name="id_store_location", referencedColumnName="id")}, - * inverseJoinColumns={@ORM\JoinColumn(name="id_part", referencedColumnName="id")} + * inverseJoinColumns={@ORM\JoinColumn(name="id_part", referencedColumnName="id")} * ) */ protected $parts; + /** @var StorelocationParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\StorelocationParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * @var bool * @ORM\Column(type="boolean") @@ -110,6 +119,7 @@ class Storelocation extends AbstractPartsContainingDBElement /** * @var Collection|StorelocationAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\StorelocationAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; @@ -143,7 +153,6 @@ class Storelocation extends AbstractPartsContainingDBElement } /** - * @param bool $only_single_part * @return Storelocation */ public function setOnlySinglePart(bool $only_single_part): self @@ -164,7 +173,6 @@ class Storelocation extends AbstractPartsContainingDBElement } /** - * @param bool $limit_to_existing_parts * @return Storelocation */ public function setLimitToExistingParts(bool $limit_to_existing_parts): self @@ -183,7 +191,6 @@ class Storelocation extends AbstractPartsContainingDBElement } /** - * @param MeasurementUnit|null $storage_type * @return Storelocation */ public function setStorageType(?MeasurementUnit $storage_type): self diff --git a/src/Entity/Parts/Supplier.php b/src/Entity/Parts/Supplier.php index 263b55f2..0c35d768 100644 --- a/src/Entity/Parts/Supplier.php +++ b/src/Entity/Parts/Supplier.php @@ -52,6 +52,7 @@ namespace App\Entity\Parts; use App\Entity\Attachments\SupplierAttachment; use App\Entity\Base\AbstractCompany; +use App\Entity\Parameters\SupplierParameter; use App\Entity\PriceInformations\Currency; use App\Validator\Constraints\Selectable; use Doctrine\Common\Collections\Collection; @@ -109,9 +110,17 @@ class Supplier extends AbstractCompany /** * @var Collection|SupplierAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\SupplierAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; + /** @var SupplierParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\SupplierParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * Gets the currency that should be used by default, when creating a orderdetail with this supplier. * @@ -125,7 +134,6 @@ class Supplier extends AbstractCompany /** * Sets the default currency. * - * @param Currency|null $default_currency * @return Supplier */ public function setDefaultCurrency(?Currency $default_currency): self @@ -154,7 +162,10 @@ class Supplier extends AbstractCompany */ public function setShippingCosts(?string $shipping_costs): self { - $this->shipping_costs = $shipping_costs; + /* Just a little hack to ensure that price has 5 digits after decimal point, + so that DB does not detect changes, when something like 0.4 is passed + Third parameter must have the scale value of decimal column. */ + $this->shipping_costs = bcmul($shipping_costs, '1.0', 5); return $this; } diff --git a/src/Entity/PriceInformations/Currency.php b/src/Entity/PriceInformations/Currency.php index a3dc0d62..3a985ce1 100644 --- a/src/Entity/PriceInformations/Currency.php +++ b/src/Entity/PriceInformations/Currency.php @@ -44,6 +44,7 @@ namespace App\Entity\PriceInformations; use App\Entity\Attachments\CurrencyAttachment; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\Parameters\CurrencyParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; @@ -89,9 +90,17 @@ class Currency extends AbstractStructuralDBElement /** * @var Collection|CurrencyAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\CurrencyAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; + /** @var CurrencyParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\CurrencyParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + /** * Returns the 3 letter ISO code of this currency. * diff --git a/src/Entity/PriceInformations/Orderdetail.php b/src/Entity/PriceInformations/Orderdetail.php index 72962a37..d938bfa3 100644 --- a/src/Entity/PriceInformations/Orderdetail.php +++ b/src/Entity/PriceInformations/Orderdetail.php @@ -52,6 +52,7 @@ namespace App\Entity\PriceInformations; use App\Entity\Base\AbstractDBElement; use App\Entity\Base\TimestampTrait; +use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\TimeStampableInterface; use App\Entity\Parts\Part; use App\Entity\Parts\Supplier; @@ -67,7 +68,7 @@ use Symfony\Component\Validator\Constraints as Assert; * @ORM\Entity() * @ORM\HasLifecycleCallbacks() */ -class Orderdetail extends AbstractDBElement implements TimeStampableInterface +class Orderdetail extends AbstractDBElement implements TimeStampableInterface, NamedElementInterface { use TimestampTrait; @@ -117,6 +118,20 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface $this->pricedetails = new ArrayCollection(); } + public function __clone() + { + if ($this->id) { + $this->addedDate = null; + $pricedetails = $this->pricedetails; + $this->pricedetails = new ArrayCollection(); + //Set master attachment is needed + foreach ($pricedetails as $pricedetail) { + $this->addPricedetail(clone $pricedetail); + } + } + parent::__clone(); + } + /** * Returns the ID as an string, defined by the element class. * This should have a form like P000014, for a part with ID 14. @@ -228,7 +243,6 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface /** * Removes an pricedetail from this orderdetail. * - * @param Pricedetail $pricedetail * @return Orderdetail */ public function removePricedetail(Pricedetail $pricedetail): self @@ -276,7 +290,6 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface /** * Sets a new part with which this orderdetail is associated. * - * @param Part $part * @return Orderdetail */ public function setPart(Part $part): self @@ -289,7 +302,6 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface /** * Sets the new supplier associated with this orderdetail. * - * @param Supplier $new_supplier * @return Orderdetail */ public function setSupplier(Supplier $new_supplier): self @@ -349,17 +361,11 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface return $this; } - public function __clone() + /** + * @inheritDoc + */ + public function getName(): string { - if ($this->id) { - $this->addedDate = null; - $pricedetails = $this->pricedetails; - $this->pricedetails = new ArrayCollection(); - //Set master attachment is needed - foreach ($pricedetails as $pricedetail) { - $this->addPricedetail(clone $pricedetail); - } - } - parent::__clone(); + return $this->getSupplierPartNr(); } } diff --git a/src/Entity/PriceInformations/Pricedetail.php b/src/Entity/PriceInformations/Pricedetail.php index 234bac54..2ecf5cf8 100644 --- a/src/Entity/PriceInformations/Pricedetail.php +++ b/src/Entity/PriceInformations/Pricedetail.php @@ -121,6 +121,14 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface bcscale(static::PRICE_PRECISION); } + public function __clone() + { + if ($this->id) { + $this->addedDate = null; + } + parent::__clone(); + } + /******************************************************************************** * * Getters @@ -230,7 +238,6 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface /** * Sets the orderdetail to which this pricedetail belongs to. * - * @param Orderdetail $orderdetail * @return $this */ public function setOrderdetail(Orderdetail $orderdetail): self @@ -244,7 +251,6 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface * Sets the currency associated with the price informations. * Set to null, to use the global base currency. * - * @param Currency|null $currency * @return Pricedetail */ public function setCurrency(?Currency $currency): self @@ -262,13 +268,17 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface * * This is the price for "price_related_quantity" parts!! * * Example: if "price_related_quantity" is '10', * you have to set here the price for 10 parts! + * * @return $this */ public function setPrice(string $new_price): self { //Assert::natural($new_price, 'The new price must be positive! Got %s!'); - $this->price = $new_price; + /* Just a little hack to ensure that price has 5 digits after decimal point, + so that DB does not detect changes, when something like 0.4 is passed + Third parameter must have the scale value of decimal column. */ + $this->price = bcmul($new_price, '1.0', static::PRICE_PRECISION); return $this; } @@ -309,6 +319,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface * So the orderdetails would have three Pricedetails for one supplier.) * * @param float $new_min_discount_quantity the minimum discount quantity + * * @return $this */ public function setMinDiscountQuantity(float $new_min_discount_quantity): self @@ -328,12 +339,4 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface { return 'PD'.sprintf('%06d', $this->getID()); } - - public function __clone() - { - if ($this->id) { - $this->addedDate = null; - } - parent::__clone(); - } } diff --git a/src/Entity/UserSystem/Group.php b/src/Entity/UserSystem/Group.php index 3da256ec..8ef9ec2a 100644 --- a/src/Entity/UserSystem/Group.php +++ b/src/Entity/UserSystem/Group.php @@ -44,10 +44,12 @@ namespace App\Entity\UserSystem; use App\Entity\Attachments\GroupAttachment; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\Parameters\GroupParameter; use App\Security\Interfaces\HasPermissionsInterface; use App\Validator\Constraints\ValidPermission; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; /** * This entity represents an user group. @@ -81,6 +83,7 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa /** * @var Collection|GroupAttachment[] * @ORM\OneToMany(targetEntity="App\Entity\Attachments\ManufacturerAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @Assert\Valid() */ protected $attachments; @@ -90,6 +93,13 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa */ protected $permissions; + /** @var GroupParameter[] + * @ORM\OneToMany(targetEntity="App\Entity\Parameters\GroupParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) + * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) + * @Assert\Valid() + */ + protected $parameters; + public function __construct() { parent::__construct(); diff --git a/src/Entity/UserSystem/PermissionsEmbed.php b/src/Entity/UserSystem/PermissionsEmbed.php index c6b01782..63fed4d8 100644 --- a/src/Entity/UserSystem/PermissionsEmbed.php +++ b/src/Entity/UserSystem/PermissionsEmbed.php @@ -235,6 +235,12 @@ class PermissionsEmbed */ protected $parts_prices = 0; + /** + * @var int + * @ORM\Column(type="smallint") + */ + protected $parts_parameters = 0; + /** * @var int * @ORM\Column(type="smallint", name="parts_attachements") diff --git a/src/Entity/UserSystem/U2FKey.php b/src/Entity/UserSystem/U2FKey.php index ea4ee32d..151fa980 100644 --- a/src/Entity/UserSystem/U2FKey.php +++ b/src/Entity/UserSystem/U2FKey.php @@ -123,6 +123,7 @@ class U2FKey implements TwoFactorKeyInterface public function setKeyHandle($keyHandle): self { $this->keyHandle = $keyHandle; + return $this; } @@ -134,6 +135,7 @@ class U2FKey implements TwoFactorKeyInterface public function setPublicKey($publicKey): self { $this->publicKey = $publicKey; + return $this; } @@ -145,6 +147,7 @@ class U2FKey implements TwoFactorKeyInterface public function setCertificate($certificate): self { $this->certificate = $certificate; + return $this; } @@ -156,6 +159,7 @@ class U2FKey implements TwoFactorKeyInterface public function setCounter($counter): self { $this->counter = $counter; + return $this; } @@ -167,6 +171,7 @@ class U2FKey implements TwoFactorKeyInterface public function setName($name): self { $this->name = $name; + return $this; } @@ -193,7 +198,6 @@ class U2FKey implements TwoFactorKeyInterface /** * Sets the user this U2F key belongs to. * - * @param User $new_user * @return $this */ public function setUser(User $new_user): self diff --git a/src/Entity/UserSystem/User.php b/src/Entity/UserSystem/User.php index 63f003ec..1389711a 100644 --- a/src/Entity/UserSystem/User.php +++ b/src/Entity/UserSystem/User.php @@ -52,8 +52,8 @@ namespace App\Entity\UserSystem; use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\UserAttachment; -use App\Entity\Base\MasterAttachmentTrait; use App\Entity\Base\AbstractNamedDBElement; +use App\Entity\Base\MasterAttachmentTrait; use App\Entity\PriceInformations\Currency; use App\Security\Interfaces\HasPermissionsInterface; use App\Validator\Constraints\Selectable; @@ -338,7 +338,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Sets the password hash for this user. * - * @param string $password * @return User */ public function setPassword(string $password): self @@ -378,7 +377,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Sets the currency the users prefers to see prices in. * - * @param Currency|null $currency * @return User */ public function setCurrency(?Currency $currency): self @@ -441,7 +439,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Set the status, if the user needs a password change. * - * @param bool $need_pw_change * @return User */ public function setNeedPwChange(bool $need_pw_change): self @@ -464,7 +461,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Sets the encrypted password reset token. * - * @param string|null $pw_reset_token * @return User */ public function setPwResetToken(?string $pw_reset_token): self @@ -487,7 +483,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Sets the datetime when the password reset token expires. * - * @param DateTime $pw_reset_expires * @return User */ public function setPwResetExpires(DateTime $pw_reset_expires): self @@ -671,7 +666,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Change the timezone of this user. * - * @param string|null $timezone * @return $this */ public function setTimezone(?string $timezone): self @@ -764,7 +758,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Sets the secret used for Google Authenticator. Set to null to disable Google Authenticator. * - * @param string|null $googleAuthenticatorSecret * @return $this */ public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): self @@ -881,7 +874,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Add a U2F key to this user. - * @param TwoFactorKeyInterface $key */ public function addU2FKey(TwoFactorKeyInterface $key): void { @@ -890,7 +882,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Remove a U2F key from this user. - * @param TwoFactorKeyInterface $key */ public function removeU2FKey(TwoFactorKeyInterface $key): void { diff --git a/src/EventSubscriber/EventLoggerSubscriber.php b/src/EventSubscriber/EventLoggerSubscriber.php index 0053f688..f6c89e14 100644 --- a/src/EventSubscriber/EventLoggerSubscriber.php +++ b/src/EventSubscriber/EventLoggerSubscriber.php @@ -1,4 +1,7 @@ ['part'], Pricedetail::class => ['orderdetail'], Attachment::class => ['element'], + AbstractParameter::class => ['element'] ]; protected const MAX_STRING_LENGTH = 2000; @@ -87,7 +89,7 @@ class EventLoggerSubscriber implements EventSubscriber $this->save_removed_data = $save_removed_data; } - public function onFlush(OnFlushEventArgs $eventArgs) + public function onFlush(OnFlushEventArgs $eventArgs): void { $em = $eventArgs->getEntityManager(); $uow = $em->getUnitOfWork(); @@ -112,7 +114,7 @@ class EventLoggerSubscriber implements EventSubscriber $uow->computeChangeSets(); } - public function postPersist(LifecycleEventArgs $args) + public function postPersist(LifecycleEventArgs $args): void { //Create an log entry, we have to do this post persist, cause we have to know the ID @@ -129,10 +131,10 @@ class EventLoggerSubscriber implements EventSubscriber $log->setUndoneEvent($undoEvent, $this->eventUndoHelper->getMode()); - if($undoEvent instanceof ElementDeletedLogEntry && $undoEvent->getTargetClass() === $log->getTargetClass()) { + if ($undoEvent instanceof ElementDeletedLogEntry && $undoEvent->getTargetClass() === $log->getTargetClass()) { $log->setTargetElementID($undoEvent->getTargetID()); } - if($undoEvent instanceof CollectionElementDeleted && $undoEvent->getDeletedElementClass() === $log->getTargetClass()) { + if ($undoEvent instanceof CollectionElementDeleted && $undoEvent->getDeletedElementClass() === $log->getTargetClass()) { $log->setTargetElementID($undoEvent->getDeletedElementID()); } } @@ -140,7 +142,7 @@ class EventLoggerSubscriber implements EventSubscriber } } - public function postFlush(PostFlushEventArgs $args) + public function postFlush(PostFlushEventArgs $args): void { $em = $args->getEntityManager(); $uow = $em->getUnitOfWork(); @@ -154,6 +156,48 @@ class EventLoggerSubscriber implements EventSubscriber $this->eventUndoHelper->clearUndoneEvent(); } + /** + * Check if the given element class has restrictions to its fields. + * + * @return bool True if there are restrictions, and further checking is needed + */ + public function hasFieldRestrictions(AbstractDBElement $element): bool + { + foreach (static::FIELD_BLACKLIST as $class => $blacklist) { + if (is_a($element, $class)) { + return true; + } + } + + return false; + } + + /** + * Checks if the field of the given element should be saved (if it is not blacklisted). + * + * @return bool + */ + public function shouldFieldBeSaved(AbstractDBElement $element, string $field_name): bool + { + foreach (static::FIELD_BLACKLIST as $class => $blacklist) { + if (is_a($element, $class) && in_array($field_name, $blacklist, true)) { + return false; + } + } + + //By default allow every field. + return true; + } + + public function getSubscribedEvents() + { + return[ + Events::onFlush, + Events::postPersist, + Events::postFlush, + ]; + } + protected function logElementDeleted(AbstractDBElement $entity, EntityManagerInterface $em): void { $log = new ElementDeletedLogEntry($entity); @@ -179,7 +223,7 @@ class EventLoggerSubscriber implements EventSubscriber if (is_a($entity, $class)) { //Check names foreach ($mappings as $field => $mapping) { - if (in_array($field, $whitelist)) { + if (in_array($field, $whitelist, true)) { $changed = $this->propertyAccessor->getValue($entity, $field); $log = new CollectionElementDeleted($changed, $mapping['inversedBy'], $entity); if ($this->eventUndoHelper->isUndo()) { @@ -216,33 +260,16 @@ class EventLoggerSubscriber implements EventSubscriber $this->logger->log($log); } - /** - * Check if the given element class has restrictions to its fields - * @param AbstractDBElement $element - * @return bool True if there are restrictions, and further checking is needed - */ - public function hasFieldRestrictions(AbstractDBElement $element): bool - { - foreach (static::FIELD_BLACKLIST as $class => $blacklist) { - if (is_a($element, $class)) { - return true; - } - } - - return false; - } - /** * Filter out every forbidden field and return the cleaned array. - * @param AbstractDBElement $element - * @param array $fields + * * @return array */ protected function filterFieldRestrictions(AbstractDBElement $element, array $fields): array { unset($fields['lastModified']); - if (!$this->hasFieldRestrictions($element)) { + if (! $this->hasFieldRestrictions($element)) { return $fields; } @@ -256,29 +283,11 @@ class EventLoggerSubscriber implements EventSubscriber }, ARRAY_FILTER_USE_BOTH); } - /** - * Checks if the field of the given element should be saved (if it is not blacklisted). - * @param AbstractDBElement $element - * @param string $field_name - * @return bool - */ - public function shouldFieldBeSaved(AbstractDBElement $element, string $field_name): bool - { - foreach (static::FIELD_BLACKLIST as $class => $blacklist) { - if (is_a($element, $class) && in_array($field_name, $blacklist)) { - return false; - } - } - - //By default allow every field. - return true; - } - protected function saveChangeSet(AbstractDBElement $entity, AbstractLogEntry $logEntry, EntityManagerInterface $em, $element_deleted = false): void { $uow = $em->getUnitOfWork(); - if (!$logEntry instanceof ElementEditedLogEntry && !$logEntry instanceof ElementDeletedLogEntry) { + if (! $logEntry instanceof ElementEditedLogEntry && ! $logEntry instanceof ElementDeletedLogEntry) { throw new \InvalidArgumentException('$logEntry must be ElementEditedLogEntry or ElementDeletedLogEntry!'); } @@ -304,28 +313,16 @@ class EventLoggerSubscriber implements EventSubscriber /** * Check if the given entity can be logged. - * @param object $entity + * * @return bool True, if the given entity can be logged. */ protected function validEntity(object $entity): bool { //Dont log logentries itself! - if ($entity instanceof AbstractDBElement && !$entity instanceof AbstractLogEntry) { + if ($entity instanceof AbstractDBElement && ! $entity instanceof AbstractLogEntry) { return true; } return false; } - - /** - * @inheritDoc - */ - public function getSubscribedEvents() - { - return[ - Events::onFlush, - Events::postPersist, - Events::postFlush - ]; - } -} \ No newline at end of file +} diff --git a/src/EventSubscriber/U2FRegistrationSubscriber.php b/src/EventSubscriber/U2FRegistrationSubscriber.php index 3a9014fc..12a70185 100644 --- a/src/EventSubscriber/U2FRegistrationSubscriber.php +++ b/src/EventSubscriber/U2FRegistrationSubscriber.php @@ -82,8 +82,8 @@ final class U2FRegistrationSubscriber implements EventSubscriberInterface //Skip adding of U2F key on demo mode if (! $this->demo_mode) { $user = $event->getUser(); - if (!$user instanceof User) { - throw new \InvalidArgumentException("Only User objects can be registered for U2F!"); + if (! $user instanceof User) { + throw new \InvalidArgumentException('Only User objects can be registered for U2F!'); } $registration = $event->getRegistration(); diff --git a/src/Form/AdminPages/BaseEntityAdminForm.php b/src/Form/AdminPages/BaseEntityAdminForm.php index da9dfcfe..d1e029b9 100644 --- a/src/Form/AdminPages/BaseEntityAdminForm.php +++ b/src/Form/AdminPages/BaseEntityAdminForm.php @@ -45,7 +45,9 @@ namespace App\Form\AdminPages; use App\Entity\Attachments\Attachment; use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\Parameters\PartParameter; use App\Form\AttachmentFormType; +use App\Form\ParameterType; use App\Form\Type\MasterPictureAttachmentType; use App\Form\Type\StructuralEntityType; use FOS\CKEditorBundle\Form\Type\CKEditorType; @@ -74,8 +76,9 @@ class BaseEntityAdminForm extends AbstractType public function configureOptions(OptionsResolver $resolver): void { - parent::configureOptions($resolver); // TODO: Change the autogenerated stub + parent::configureOptions($resolver); $resolver->setRequired('attachment_class'); + $resolver->setRequired('parameter_class'); } public function buildForm(FormBuilderInterface $builder, array $options): void @@ -151,6 +154,19 @@ class BaseEntityAdminForm extends AbstractType 'empty_data' => null, ]); + $builder->add('parameters', CollectionType::class, [ + 'entry_type' => ParameterType::class, + 'allow_add' => $this->security->isGranted($is_new ? 'create' : 'edit', $entity), + 'allow_delete' => $this->security->isGranted($is_new ? 'create' : 'edit', $entity), + 'disabled' => ! $this->security->isGranted($is_new ? 'create' : 'edit', $entity), + 'label' => false, + 'by_reference' => false, + 'prototype_data' => new $options['parameter_class'](), + 'entry_options' => [ + 'data_class' => $options['parameter_class'], + ], + ]); + //Buttons $builder->add('save', SubmitType::class, [ 'label' => $is_new ? 'entity.create' : 'entity.edit.save', diff --git a/src/Form/ParameterType.php b/src/Form/ParameterType.php new file mode 100644 index 00000000..8cd66abd --- /dev/null +++ b/src/Form/ParameterType.php @@ -0,0 +1,126 @@ +. + */ + +namespace App\Form; + +use App\Entity\Parameters\AbstractParameter; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\NumberType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class ParameterType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder->add('name', TextType::class, [ + 'label' => false, + 'empty_data' => '', + 'attr' => [ + 'placeholder' => 'parameters.name.placeholder', + 'class' => 'form-control-sm', + ], + ]); + $builder->add('symbol', TextType::class, [ + 'label' => false, + 'required' => false, + 'empty_data' => '', + 'attr' => [ + 'placeholder' => 'parameters.symbol.placeholder', + 'class' => 'form-control-sm', + 'style' => 'max-width: 12ch;', + ], + ]); + $builder->add('value_text', TextType::class, [ + 'label' => false, + 'required' => false, + 'empty_data' => '', + 'attr' => [ + 'placeholder' => 'parameters.text.placeholder', + 'class' => 'form-control-sm', + ], + ]); + + $builder->add('value_max', NumberType::class, [ + 'label' => false, + 'required' => false, + 'html5' => true, + 'attr' => [ + 'step' => 'any', + 'placeholder' => 'parameters.max.placeholder', + 'class' => 'form-control-sm', + 'style' => 'max-width: 12ch;', + ], + ]); + $builder->add('value_min', NumberType::class, [ + 'label' => false, + 'required' => false, + 'html5' => true, + 'attr' => [ + 'step' => 'any', + 'placeholder' => 'parameters.min.placeholder', + 'class' => 'form-control-sm', + 'style' => 'max-width: 12ch;', + ], + ]); + $builder->add('value_typical', NumberType::class, [ + 'label' => false, + 'required' => false, + 'html5' => true, + 'attr' => [ + 'step' => 'any', + 'placeholder' => 'parameters.typical.placeholder', + 'class' => 'form-control-sm', + 'style' => 'max-width: 12ch;', + ], + ]); + $builder->add('unit', TextType::class, [ + 'label' => false, + 'required' => false, + 'empty_data' => '', + 'attr' => [ + 'placeholder' => 'parameters.unit.placeholder', + 'class' => 'form-control-sm', + 'style' => 'max-width: 8ch;', + ], + ]); + + $builder->add('group', TextType::class, [ + 'label' => false, + 'required' => false, + 'empty_data' => '', + 'attr' => [ + 'placeholder' => 'parameter.group.placeholder', + 'class' => 'form-control-sm', + ] + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => AbstractParameter::class, + ]); + } +} diff --git a/src/Form/Part/PartBaseType.php b/src/Form/Part/PartBaseType.php index cf30f988..1610afcf 100644 --- a/src/Form/Part/PartBaseType.php +++ b/src/Form/Part/PartBaseType.php @@ -44,6 +44,7 @@ namespace App\Form\Part; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\PartAttachment; +use App\Entity\Parameters\PartParameter; use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; @@ -51,6 +52,8 @@ use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\Part; use App\Entity\PriceInformations\Orderdetail; use App\Form\AttachmentFormType; +use App\Form\ParameterGroupType; +use App\Form\ParameterType; use App\Form\Type\MasterPictureAttachmentType; use App\Form\Type\SIUnitType; use App\Form\Type\StructuralEntityType; @@ -264,6 +267,19 @@ class PartBaseType extends AbstractType ], ]); + $builder->add('parameters', CollectionType::class, [ + 'entry_type' => ParameterType::class, + 'allow_add' => $this->security->isGranted('parameters.create', $part), + 'allow_delete' => $this->security->isGranted('parameters.delete', $part), + 'label' => false, + 'by_reference' => false, + 'prototype_data' => new PartParameter(), + 'entry_options' => [ + 'disabled' => ! $this->security->isGranted('parameters.edit', $part), + 'data_class' => PartParameter::class, + ], + ]); + $builder->add('log_comment', TextType::class, [ 'label' => 'edit.log_comment', 'mapped' => false, diff --git a/src/Form/Type/CurrencyEntityType.php b/src/Form/Type/CurrencyEntityType.php index 2a992a5a..4e955316 100644 --- a/src/Form/Type/CurrencyEntityType.php +++ b/src/Form/Type/CurrencyEntityType.php @@ -67,6 +67,7 @@ class CurrencyEntityType extends StructuralEntityType $resolver->setDefault('class', Currency::class); $resolver->setDefault('disable_not_selectable', true); + $resolver->setDefault('choice_translation_domain', false); // This options allows you to override the currency shown for the null value $resolver->setDefault('base_currency', null); @@ -87,7 +88,7 @@ class CurrencyEntityType extends StructuralEntityType { //Similar to StructuralEntityType, but we use the currency symbol instead if available - if (!$choice instanceof Currency) { + if (! $choice instanceof Currency) { throw new \InvalidArgumentException('$choice must be an currency object!'); } diff --git a/src/Form/Type/MasterPictureAttachmentType.php b/src/Form/Type/MasterPictureAttachmentType.php index 10dddd78..070bb80d 100644 --- a/src/Form/Type/MasterPictureAttachmentType.php +++ b/src/Form/Type/MasterPictureAttachmentType.php @@ -43,7 +43,6 @@ declare(strict_types=1); namespace App\Form\Type; use App\Entity\Attachments\Attachment; -use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Contracts\HasMasterAttachmentInterface; use Doctrine\ORM\EntityRepository; use ReflectionClass; @@ -61,6 +60,7 @@ class MasterPictureAttachmentType extends AbstractType $resolver->setDefaults([ 'filter' => 'picture', + 'choice_translation_domain' => false, 'attr' => [ 'class' => 'selectpicker', ], diff --git a/src/Form/Type/SIUnitType.php b/src/Form/Type/SIUnitType.php index 4b3493d9..1e14cf09 100644 --- a/src/Form/Type/SIUnitType.php +++ b/src/Form/Type/SIUnitType.php @@ -145,6 +145,7 @@ final class SIUnitType extends AbstractType implements DataMapperInterface 'm' => -3, 'µ' => -6, ], + 'choice_translation_domain' => false, ]); } diff --git a/src/Form/Type/StructuralEntityType.php b/src/Form/Type/StructuralEntityType.php index bdbc0a08..73454038 100644 --- a/src/Form/Type/StructuralEntityType.php +++ b/src/Form/Type/StructuralEntityType.php @@ -108,6 +108,7 @@ class StructuralEntityType extends AbstractType 'choice_attr' => function ($choice, $key, $value) { return $this->generateChoiceAttr($choice, $key, $value); }, + 'choice_translation_domain' => false, //Don't translate the entity names ]); $resolver->setDefault('empty_message', null); diff --git a/src/Form/UserAdminForm.php b/src/Form/UserAdminForm.php index ec356710..e7ede3b1 100644 --- a/src/Form/UserAdminForm.php +++ b/src/Form/UserAdminForm.php @@ -79,6 +79,7 @@ class UserAdminForm extends AbstractType { parent::configureOptions($resolver); // TODO: Change the autogenerated stub $resolver->setRequired('attachment_class'); + $resolver->setDefault('parameter_class', false); } public function buildForm(FormBuilderInterface $builder, array $options): void diff --git a/src/Migrations/Version20200311204104.php b/src/Migrations/Version20200311204104.php new file mode 100644 index 00000000..0cd173d8 --- /dev/null +++ b/src/Migrations/Version20200311204104.php @@ -0,0 +1,51 @@ +abortIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE parameters (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, symbol VARCHAR(255) NOT NULL, value_min DOUBLE PRECISION DEFAULT NULL, value_typical DOUBLE PRECISION DEFAULT NULL, value_max DOUBLE PRECISION DEFAULT NULL, unit VARCHAR(255) NOT NULL, value_text VARCHAR(255) NOT NULL, param_group VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, type SMALLINT NOT NULL, element_id INT NOT NULL, INDEX IDX_69348FE1F1F2A24 (element_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE `groups` ADD perms_parts_parameters SMALLINT NOT NULL'); + $this->addSql('ALTER TABLE `users` ADD perms_parts_parameters SMALLINT NOT NULL'); + $this->addSql('ALTER TABLE log CHANGE level level TINYINT'); + + $sql = 'UPDATE `groups`' . + 'SET perms_parts_parameters = 341 WHERE (id = 1 AND name = "admins") OR (id = 3 AND name = "users");'; + $this->addSql($sql); + + $sql = 'UPDATE `groups`' . + 'SET perms_parts_parameters = 681 WHERE (id = 2 AND name = "readonly");'; + $this->addSql($sql); + + $this->write('[!!!] Permissions were updated! Please check if they fit your expectations!'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE parameters'); + $this->addSql('ALTER TABLE `groups` DROP perms_parts_parameters'); + $this->addSql('ALTER TABLE `users` DROP perms_parts_parameters'); + $this->addSql('ALTER TABLE log CHANGE level level TINYINT(1) DEFAULT NULL'); + } +} diff --git a/src/Repository/AttachmentRepository.php b/src/Repository/AttachmentRepository.php index f8b78e41..76a14589 100644 --- a/src/Repository/AttachmentRepository.php +++ b/src/Repository/AttachmentRepository.php @@ -1,4 +1,7 @@ where('attachment.path LIKE :like'); $qb->setParameter('like', '\\%SECURE\\%%'); $query = $qb->getQuery(); + return (int) $query->getSingleScalarResult(); } /** - * Gets the count of all external attachments (attachments only containing an URL) + * Gets the count of all external attachments (attachments only containing an URL). + * * @return int + * * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException */ @@ -54,12 +58,15 @@ class AttachmentRepository extends DBElementRepository $qb->setParameter('http', 'http://%'); $qb->setParameter('https', 'https://%'); $query = $qb->getQuery(); + return (int) $query->getSingleScalarResult(); } /** * Gets the count of all attachments where an user uploaded an file. + * * @return int + * * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException */ @@ -74,6 +81,7 @@ class AttachmentRepository extends DBElementRepository $qb->setParameter('base', '\\%BASE\\%%'); $qb->setParameter('media', '\\%MEDIA\\%%'); $query = $qb->getQuery(); + return (int) $query->getSingleScalarResult(); } -} \ No newline at end of file +} diff --git a/src/Repository/DBElementRepository.php b/src/Repository/DBElementRepository.php index 94b19ec2..ae7a9da9 100644 --- a/src/Repository/DBElementRepository.php +++ b/src/Repository/DBElementRepository.php @@ -1,4 +1,7 @@ setField($element, 'id', $new_id); } - protected function setField(AbstractDBElement $element, string $field, $new_value) + protected function setField(AbstractDBElement $element, string $field, $new_value): void { $reflection = new \ReflectionClass(get_class($element)); $property = $reflection->getProperty($field); $property->setAccessible(true); $property->setValue($element, $new_value); } -} \ No newline at end of file +} diff --git a/src/Repository/LogEntryRepository.php b/src/Repository/LogEntryRepository.php index 53c9b4d9..313a57be 100644 --- a/src/Repository/LogEntryRepository.php +++ b/src/Repository/LogEntryRepository.php @@ -49,8 +49,6 @@ use App\Entity\LogSystem\ElementCreatedLogEntry; use App\Entity\LogSystem\ElementDeletedLogEntry; use App\Entity\LogSystem\ElementEditedLogEntry; use App\Entity\UserSystem\User; -use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\QueryBuilder; class LogEntryRepository extends DBElementRepository { @@ -72,9 +70,9 @@ class LogEntryRepository extends DBElementRepository * Find log entries associated with the given element (the history of the element). * * @param AbstractDBElement $element The element for which the history should be generated - * @param string $order By default newest entries are shown first. Change this to ASC to show oldest entries first. - * @param null $limit - * @param null $offset + * @param string $order By default newest entries are shown first. Change this to ASC to show oldest entries first. + * @param null $limit + * @param null $offset * * @return AbstractLogEntry[] */ @@ -84,9 +82,11 @@ class LogEntryRepository extends DBElementRepository } /** - * Try to get a log entry that contains the information to undete a given element - * @param string $class The class of the element that should be undeleted - * @param int $id The ID of the element that should be deleted + * Try to get a log entry that contains the information to undete a given element. + * + * @param string $class The class of the element that should be undeleted + * @param int $id The ID of the element that should be deleted + * * @return ElementDeletedLogEntry */ public function getUndeleteDataForElement(string $class, int $id): ElementDeletedLogEntry @@ -94,31 +94,34 @@ class LogEntryRepository extends DBElementRepository $qb = $this->createQueryBuilder('log'); $qb->select('log') //->where('log INSTANCE OF App\Entity\LogSystem\ElementEditedLogEntry') - ->where('log INSTANCE OF ' . ElementDeletedLogEntry::class) + ->where('log INSTANCE OF '.ElementDeletedLogEntry::class) ->andWhere('log.target_type = :target_type') ->andWhere('log.target_id = :target_id') ->orderBy('log.timestamp', 'DESC') ->setMaxResults(1); $qb->setParameters([ - 'target_type' => AbstractLogEntry::targetTypeClassToID($class), - 'target_id' => $id, - ]); + 'target_type' => AbstractLogEntry::targetTypeClassToID($class), + 'target_id' => $id, + ]); - $query = $qb->getQuery(); + $query = $qb->getQuery(); $results = $query->execute(); if (empty($results)) { - throw new \RuntimeException("No undelete data could be found for this element"); + throw new \RuntimeException('No undelete data could be found for this element'); } + return $results[0]; } /** - * Gets all log entries that are related to time travelling - * @param AbstractDBElement $element The element for which the time travel data should be retrieved - * @param \DateTime $until Back to which timestamp should the data be get (including the timestamp) + * Gets all log entries that are related to time travelling. + * + * @param AbstractDBElement $element The element for which the time travel data should be retrieved + * @param \DateTime $until Back to which timestamp should the data be get (including the timestamp) + * * @return AbstractLogEntry[] */ public function getTimetravelDataForElement(AbstractDBElement $element, \DateTime $until): array @@ -126,48 +129,49 @@ class LogEntryRepository extends DBElementRepository $qb = $this->createQueryBuilder('log'); $qb->select('log') //->where('log INSTANCE OF App\Entity\LogSystem\ElementEditedLogEntry') - ->where('log INSTANCE OF ' . ElementEditedLogEntry::class) - ->orWhere('log INSTANCE OF ' . CollectionElementDeleted::class) + ->where('log INSTANCE OF '.ElementEditedLogEntry::class) + ->orWhere('log INSTANCE OF '.CollectionElementDeleted::class) ->andWhere('log.target_type = :target_type') ->andWhere('log.target_id = :target_id') ->andWhere('log.timestamp >= :until') ->orderBy('log.timestamp', 'DESC'); $qb->setParameters([ - 'target_type' => AbstractLogEntry::targetTypeClassToID(get_class($element)), - 'target_id' => $element->getID(), - 'until' => $until - ]); + 'target_type' => AbstractLogEntry::targetTypeClassToID(get_class($element)), + 'target_id' => $element->getID(), + 'until' => $until, + ]); $query = $qb->getQuery(); + return $query->execute(); } /** - * Check if the given element has existed at the given timestamp - * @param AbstractDBElement $element - * @param \DateTime $timestamp + * Check if the given element has existed at the given timestamp. + * * @return bool True if the element existed at the given timestamp */ public function getElementExistedAtTimestamp(AbstractDBElement $element, \DateTime $timestamp): bool { $qb = $this->createQueryBuilder('log'); $qb->select('count(log)') - ->where('log INSTANCE OF ' . ElementCreatedLogEntry::class) + ->where('log INSTANCE OF '.ElementCreatedLogEntry::class) ->andWhere('log.target_type = :target_type') ->andWhere('log.target_id = :target_id') ->andWhere('log.timestamp >= :until') ->orderBy('log.timestamp', 'DESC'); $qb->setParameters([ - 'target_type' => AbstractLogEntry::targetTypeClassToID(get_class($element)), - 'target_id' => $element->getID(), - 'until' => $timestamp - ]); + 'target_type' => AbstractLogEntry::targetTypeClassToID(get_class($element)), + 'target_id' => $element->getID(), + 'until' => $timestamp, + ]); $query = $qb->getQuery(); $count = $query->getSingleScalarResult(); - return !($count > 0); + + return ! ($count > 0); } /** @@ -187,9 +191,9 @@ class LogEntryRepository extends DBElementRepository /** * Gets the target element associated with the logentry. * - * @param AbstractLogEntry $logEntry * @return AbstractDBElement|null Returns the associated DBElement or null if the log either has no target or the element - * was deleted from DB. + * was deleted from DB. + * * @throws \Doctrine\ORM\ORMException * @throws \Doctrine\ORM\OptimisticLockException * @throws \Doctrine\ORM\TransactionRequiredException @@ -206,34 +210,9 @@ class LogEntryRepository extends DBElementRepository return $this->getEntityManager()->find($class, $id); } - protected function getLastUser(AbstractDBElement $element, string $class) - { - $qb = $this->createQueryBuilder('log'); - $qb->select('log') - //->where('log INSTANCE OF App\Entity\LogSystem\ElementEditedLogEntry') - ->where('log INSTANCE OF ' . $class) - ->andWhere('log.target_type = :target_type') - ->andWhere('log.target_id = :target_id') - ->orderBy('log.timestamp', 'DESC'); - - $qb->setParameters([ - 'target_type' => AbstractLogEntry::targetTypeClassToID(get_class($element)), - 'target_id' => $element->getID() - ]); - - $query = $qb->getQuery(); - $query->setMaxResults(1); - /** @var AbstractLogEntry[] $results */ - $results = $query->execute(); - if (isset($results[0])) { - return $results[0]->getUser(); - } - return null; - } - /** * Returns the last user that has edited the given element. - * @param AbstractDBElement $element + * * @return User|null A user object, or null if no user could be determined. */ public function getLastEditingUser(AbstractDBElement $element): ?User @@ -243,11 +222,37 @@ class LogEntryRepository extends DBElementRepository /** * Returns the user that has created the given element. - * @param AbstractDBElement $element + * * @return User|null A user object, or null if no user could be determined. */ public function getCreatingUser(AbstractDBElement $element): ?User { return $this->getLastUser($element, ElementCreatedLogEntry::class); } + + protected function getLastUser(AbstractDBElement $element, string $class) + { + $qb = $this->createQueryBuilder('log'); + $qb->select('log') + //->where('log INSTANCE OF App\Entity\LogSystem\ElementEditedLogEntry') + ->where('log INSTANCE OF '.$class) + ->andWhere('log.target_type = :target_type') + ->andWhere('log.target_id = :target_id') + ->orderBy('log.timestamp', 'DESC'); + + $qb->setParameters([ + 'target_type' => AbstractLogEntry::targetTypeClassToID(get_class($element)), + 'target_id' => $element->getID(), + ]); + + $query = $qb->getQuery(); + $query->setMaxResults(1); + /** @var AbstractLogEntry[] $results */ + $results = $query->execute(); + if (isset($results[0])) { + return $results[0]->getUser(); + } + + return null; + } } diff --git a/src/Repository/NamedDBElementRepository.php b/src/Repository/NamedDBElementRepository.php index 404efed0..eb2348e4 100644 --- a/src/Repository/NamedDBElementRepository.php +++ b/src/Repository/NamedDBElementRepository.php @@ -44,7 +44,6 @@ namespace App\Repository; use App\Entity\Base\AbstractNamedDBElement; use App\Helpers\Trees\TreeViewNode; -use Doctrine\ORM\EntityRepository; class NamedDBElementRepository extends DBElementRepository { diff --git a/src/Repository/PartRepository.php b/src/Repository/PartRepository.php index 0ac94932..8b21d0b8 100644 --- a/src/Repository/PartRepository.php +++ b/src/Repository/PartRepository.php @@ -43,14 +43,15 @@ declare(strict_types=1); namespace App\Repository; use App\Entity\Parts\PartLot; -use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; class PartRepository extends NamedDBElementRepository { /** - * Gets the summed up instock of all parts (only parts without an measurent unit) + * Gets the summed up instock of all parts (only parts without an measurent unit). + * * @return string + * * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException */ @@ -63,12 +64,15 @@ class PartRepository extends NamedDBElementRepository ->where('part.partUnit IS NULL'); $query = $qb->getQuery(); + return $query->getSingleScalarResult(); } /** * Gets the number of parts that has price informations. + * * @return int + * * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException */ @@ -81,6 +85,7 @@ class PartRepository extends NamedDBElementRepository ->where('pricedetail.price > 0.0'); $query = $qb->getQuery(); + return (int) $query->getSingleScalarResult(); } } diff --git a/src/Security/EntityListeners/ElementPermissionListener.php b/src/Security/EntityListeners/ElementPermissionListener.php index 4c6c0c82..80e51aa1 100644 --- a/src/Security/EntityListeners/ElementPermissionListener.php +++ b/src/Security/EntityListeners/ElementPermissionListener.php @@ -198,9 +198,9 @@ class ElementPermissionListener * Checks if access to the property of the given element is granted. * This function adds an additional cache layer, where the voters are called only once (to improve performance). * - * @param string $mode What operation should be checked. Must be 'read' or 'edit' - * @param ColumnSecurity $annotation The annotation of the property that should be checked - * @param AbstractDBElement $element The element that should for which should be checked + * @param string $mode What operation should be checked. Must be 'read' or 'edit' + * @param ColumnSecurity $annotation The annotation of the property that should be checked + * @param AbstractDBElement $element The element that should for which should be checked * * @return bool True if the user is allowed to read that property */ diff --git a/src/Security/Voter/AttachmentVoter.php b/src/Security/Voter/AttachmentVoter.php index 07cc9c25..01b86fe5 100644 --- a/src/Security/Voter/AttachmentVoter.php +++ b/src/Security/Voter/AttachmentVoter.php @@ -53,7 +53,7 @@ class AttachmentVoter extends ExtendedVoter * The current user (or the anonymous user) is passed by $user. * * @param string $attribute - * @param mixed $subject + * * @return bool */ protected function voteOnUser($attribute, $subject, User $user): bool diff --git a/src/Security/Voter/ExtendedVoter.php b/src/Security/Voter/ExtendedVoter.php index 2e612ed8..8630373b 100644 --- a/src/Security/Voter/ExtendedVoter.php +++ b/src/Security/Voter/ExtendedVoter.php @@ -91,7 +91,7 @@ abstract class ExtendedVoter extends Voter * The current user (or the anonymous user) is passed by $user. * * @param string $attribute - * @param mixed $subject + * * @return bool */ abstract protected function voteOnUser($attribute, $subject, User $user): bool; diff --git a/src/Security/Voter/GroupVoter.php b/src/Security/Voter/GroupVoter.php index 0201cbe5..c6eb405f 100644 --- a/src/Security/Voter/GroupVoter.php +++ b/src/Security/Voter/GroupVoter.php @@ -52,7 +52,7 @@ class GroupVoter extends ExtendedVoter * The current user (or the anonymous user) is passed by $user. * * @param string $attribute - * @param mixed $subject + * * @return bool */ protected function voteOnUser($attribute, $subject, User $user): bool diff --git a/src/Security/Voter/OrderdetailVoter.php b/src/Security/Voter/OrderdetailVoter.php index f214685e..256d406f 100644 --- a/src/Security/Voter/OrderdetailVoter.php +++ b/src/Security/Voter/OrderdetailVoter.php @@ -1,4 +1,7 @@ resolver->inherit($user, 'parts_orderdetails', $attribute) ?? false; } - /** - * @inheritDoc - */ protected function supports($attribute, $subject) { if (is_a($subject, Orderdetail::class, true)) { @@ -56,4 +51,4 @@ class OrderdetailVoter extends ExtendedVoter return false; } -} \ No newline at end of file +} diff --git a/src/Security/Voter/PartLotVoter.php b/src/Security/Voter/PartLotVoter.php index cf022a73..0e985e48 100644 --- a/src/Security/Voter/PartLotVoter.php +++ b/src/Security/Voter/PartLotVoter.php @@ -1,4 +1,7 @@ resolver->inherit($user, 'parts_lots', $attribute) ?? false; } - /** - * @inheritDoc - */ protected function supports($attribute, $subject) { if (is_a($subject, PartLot::class, true)) { @@ -55,4 +51,4 @@ class PartLotVoter extends ExtendedVoter return false; } -} \ No newline at end of file +} diff --git a/src/Security/Voter/PartVoter.php b/src/Security/Voter/PartVoter.php index f829f557..ed29cdba 100644 --- a/src/Security/Voter/PartVoter.php +++ b/src/Security/Voter/PartVoter.php @@ -83,6 +83,5 @@ class PartVoter extends ExtendedVoter //Null concealing operator means, that no return $this->resolver->inherit($user, 'parts', $attribute) ?? false; - } } diff --git a/src/Security/Voter/PermissionVoter.php b/src/Security/Voter/PermissionVoter.php index 5564349f..32383a80 100644 --- a/src/Security/Voter/PermissionVoter.php +++ b/src/Security/Voter/PermissionVoter.php @@ -56,7 +56,6 @@ class PermissionVoter extends ExtendedVoter * The current user (or the anonymous user) is passed by $user. * * @param string $attribute - * @param mixed $subject */ protected function voteOnUser($attribute, $subject, User $user): bool { diff --git a/src/Security/Voter/PricedetailVoter.php b/src/Security/Voter/PricedetailVoter.php index e4ec0251..d222df54 100644 --- a/src/Security/Voter/PricedetailVoter.php +++ b/src/Security/Voter/PricedetailVoter.php @@ -1,4 +1,7 @@ resolver->inherit($user, 'parts_prices', $attribute) ?? false; } - /** - * @inheritDoc - */ protected function supports($attribute, $subject) { if (is_a($subject, Pricedetail::class, true)) { @@ -56,4 +51,4 @@ class PricedetailVoter extends ExtendedVoter return false; } -} \ No newline at end of file +} diff --git a/src/Security/Voter/StructureVoter.php b/src/Security/Voter/StructureVoter.php index d5d6eb51..af01b75a 100644 --- a/src/Security/Voter/StructureVoter.php +++ b/src/Security/Voter/StructureVoter.php @@ -43,13 +43,11 @@ declare(strict_types=1); namespace App\Security\Voter; use App\Entity\Attachments\AttachmentType; -use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Devices\Device; use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; use App\Entity\Parts\MeasurementUnit; -use App\Entity\Parts\Part; use App\Entity\Parts\Storelocation; use App\Entity\Parts\Supplier; use App\Entity\PriceInformations\Currency; @@ -87,7 +85,7 @@ class StructureVoter extends ExtendedVoter */ protected function instanceToPermissionName($subject): ?string { - if (!is_string($subject)) { + if (! is_string($subject)) { $class_name = get_class($subject); } else { $class_name = $subject; @@ -121,7 +119,7 @@ class StructureVoter extends ExtendedVoter * The current user (or the anonymous user) is passed by $user. * * @param string $attribute - * @param mixed $subject + * * @return bool */ protected function voteOnUser($attribute, $subject, User $user): bool diff --git a/src/Security/Voter/UserVoter.php b/src/Security/Voter/UserVoter.php index de7d165b..333c365d 100644 --- a/src/Security/Voter/UserVoter.php +++ b/src/Security/Voter/UserVoter.php @@ -73,7 +73,7 @@ class UserVoter extends ExtendedVoter * The current user (or the anonymous user) is passed by $user. * * @param string $attribute - * @param mixed $subject + * * @return bool */ protected function voteOnUser($attribute, $subject, User $user): bool diff --git a/src/Services/ElementTypeNameGenerator.php b/src/Services/ElementTypeNameGenerator.php index 319d504d..64362435 100644 --- a/src/Services/ElementTypeNameGenerator.php +++ b/src/Services/ElementTypeNameGenerator.php @@ -45,9 +45,9 @@ namespace App\Services; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentType; use App\Entity\Base\AbstractDBElement; -use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Contracts\NamedElementInterface; use App\Entity\Devices\Device; +use App\Entity\Parameters\AbstractParameter; use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; @@ -92,6 +92,7 @@ class ElementTypeNameGenerator Pricedetail::class => $this->translator->trans('pricedetail.label'), Group::class => $this->translator->trans('group.label'), User::class => $this->translator->trans('user.label'), + AbstractParameter::class => $this->translator->trans('parameter.label'), ]; } @@ -124,7 +125,7 @@ class ElementTypeNameGenerator } //When nothing was found throw an exception - throw new EntityNotSupportedException(sprintf('No localized label for the element with type %s was found!', get_class($entity))); + throw new EntityNotSupportedException(sprintf('No localized label for the element with type %s was found!', is_object($entity) ? get_class($entity) : (string) $entity)); } /** @@ -133,7 +134,7 @@ class ElementTypeNameGenerator * It uses getLocalizedLabel to determine the type. * * @param NamedElementInterface $entity the entity for which the string should be generated - * @param bool $use_html If set to true, a html string is returned, where the type is set italic + * @param bool $use_html If set to true, a html string is returned, where the type is set italic * * @return string The localized string * diff --git a/src/Services/EntityExporter.php b/src/Services/EntityExporter.php index d55e09ba..8afb3b8e 100644 --- a/src/Services/EntityExporter.php +++ b/src/Services/EntityExporter.php @@ -43,14 +43,6 @@ declare(strict_types=1); namespace App\Services; use App\Entity\Base\AbstractNamedDBElement; -use Symfony\Component\Serializer\Encoder\CsvEncoder; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\Encoder\XmlEncoder; -use Symfony\Component\Serializer\Encoder\YamlEncoder; -use Symfony\Component\Serializer\Normalizer\DataUriNormalizer; -use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; use function in_array; use InvalidArgumentException; use function is_array; @@ -59,6 +51,13 @@ use ReflectionException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Serializer\Encoder\CsvEncoder; +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Symfony\Component\Serializer\Encoder\XmlEncoder; +use Symfony\Component\Serializer\Encoder\YamlEncoder; +use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; +use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; +use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; /** diff --git a/src/Services/EntityImporter.php b/src/Services/EntityImporter.php index 475b63db..f65aff3e 100644 --- a/src/Services/EntityImporter.php +++ b/src/Services/EntityImporter.php @@ -43,7 +43,6 @@ declare(strict_types=1); namespace App\Services; use App\Entity\Base\AbstractStructuralDBElement; -use Symfony\Bundle\MakerBundle\Str; use function count; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; @@ -70,10 +69,10 @@ class EntityImporter * Creates many entries at once, based on a (text) list of name. * The created enties are not persisted to database yet, so you have to do it yourself. * - * @param string $lines The list of names seperated by \n - * @param string $class_name The name of the class for which the entities should be created + * @param string $lines The list of names seperated by \n + * @param string $class_name The name of the class for which the entities should be created * @param AbstractStructuralDBElement|null $parent the element which will be used as parent element for new elements - * @param array $errors an associative array containing all validation errors + * @param array $errors an associative array containing all validation errors * * @return AbstractStructuralDBElement[] An array containing all valid imported entities (with the type $class_name) */ @@ -228,8 +227,8 @@ class EntityImporter /** * This functions corrects the parent setting based on the children value of the parent. * - * @param iterable $entities the list of entities that should be fixed - * @param null|AbstractStructuralDBElement $parent the parent, to which the entity should be set + * @param iterable $entities the list of entities that should be fixed + * @param AbstractStructuralDBElement|null $parent the parent, to which the entity should be set */ protected function correctParentEntites(iterable $entities, $parent = null): void { diff --git a/src/Services/EntityURLGenerator.php b/src/Services/EntityURLGenerator.php index 28d691e6..0f54e960 100644 --- a/src/Services/EntityURLGenerator.php +++ b/src/Services/EntityURLGenerator.php @@ -125,9 +125,8 @@ class EntityURLGenerator } /** - * Gets the URL to view the given element at a given timestamp - * @param AbstractDBElement $entity - * @param \DateTime $dateTime + * Gets the URL to view the given element at a given timestamp. + * * @return string */ public function timeTravelURL(AbstractDBElement $entity, \DateTime $dateTime): string @@ -154,32 +153,32 @@ class EntityURLGenerator $this->mapToController($map, $entity), [ 'id' => $entity->getID(), - 'timestamp' => $dateTime->getTimestamp() + 'timestamp' => $dateTime->getTimestamp(), ] ); } catch (EntityNotSupportedException $exception) { if ($entity instanceof PartLot) { return $this->urlGenerator->generate('part_info', [ 'id' => $entity->getPart()->getID(), - 'timestamp' => $dateTime->getTimestamp() + 'timestamp' => $dateTime->getTimestamp(), ]); } if ($entity instanceof PartAttachment) { return $this->urlGenerator->generate('part_info', [ 'id' => $entity->getElement()->getID(), - 'timestamp' => $dateTime->getTimestamp() + 'timestamp' => $dateTime->getTimestamp(), ]); } if ($entity instanceof Orderdetail) { return $this->urlGenerator->generate('part_info', [ 'id' => $entity->getPart()->getID(), - 'timestamp' => $dateTime->getTimestamp() + 'timestamp' => $dateTime->getTimestamp(), ]); } if ($entity instanceof Pricedetail) { return $this->urlGenerator->generate('part_info', [ 'id' => $entity->getOrderdetail()->getPart()->getID(), - 'timestamp' => $dateTime->getTimestamp() + 'timestamp' => $dateTime->getTimestamp(), ]); } } diff --git a/src/Services/LogSystem/EventCommentHelper.php b/src/Services/LogSystem/EventCommentHelper.php index 6a7b25fc..04d8ce0a 100644 --- a/src/Services/LogSystem/EventCommentHelper.php +++ b/src/Services/LogSystem/EventCommentHelper.php @@ -1,4 +1,7 @@ message = mb_strimwidth($message, 0, self::MAX_MESSAGE_LENGTH, '...'); + if ($message) { + $this->message = mb_strimwidth($message, 0, self::MAX_MESSAGE_LENGTH, '...'); + } else { + $this->message = null; + } } /** * Returns the currently set message, or null if no message is set yet. + * * @return string|null */ public function getMessage(): ?string @@ -63,10 +69,11 @@ class EventCommentHelper /** * Check if a message is currently set. + * * @return bool */ public function isMessageSet(): bool { return is_string($this->message); } -} \ No newline at end of file +} diff --git a/src/Services/LogSystem/EventUndoHelper.php b/src/Services/LogSystem/EventUndoHelper.php index f61171e9..a9714f17 100644 --- a/src/Services/LogSystem/EventUndoHelper.php +++ b/src/Services/LogSystem/EventUndoHelper.php @@ -1,4 +1,7 @@ mode = $mode; @@ -55,7 +57,6 @@ class EventUndoHelper /** * Set which event log is currently undone. * After the flush this message is cleared. - * @param AbstractLogEntry|null $undone_event */ public function setUndoneEvent(?AbstractLogEntry $undone_event): void { @@ -64,6 +65,7 @@ class EventUndoHelper /** * Returns event that is currently undone. + * * @return AbstractLogEntry|null */ public function getUndoneEvent(): ?AbstractLogEntry @@ -80,11 +82,12 @@ class EventUndoHelper } /** - * Check if a event is undone + * Check if a event is undone. + * * @return bool */ public function isUndo(): bool { - return ($this->undone_event instanceof AbstractLogEntry); + return $this->undone_event instanceof AbstractLogEntry; } -} \ No newline at end of file +} diff --git a/src/Services/LogSystem/HistoryHelper.php b/src/Services/LogSystem/HistoryHelper.php index 32ee98b8..88a209e4 100644 --- a/src/Services/LogSystem/HistoryHelper.php +++ b/src/Services/LogSystem/HistoryHelper.php @@ -1,4 +1,7 @@ getParameters()->toArray()); + } + return $array; } -} \ No newline at end of file +} diff --git a/src/Services/LogSystem/LogEntryExtraFormatter.php b/src/Services/LogSystem/LogEntryExtraFormatter.php index b28623d8..74402f3c 100644 --- a/src/Services/LogSystem/LogEntryExtraFormatter.php +++ b/src/Services/LogSystem/LogEntryExtraFormatter.php @@ -56,7 +56,6 @@ use App\Entity\LogSystem\UserLoginLogEntry; use App\Entity\LogSystem\UserLogoutLogEntry; use App\Entity\LogSystem\UserNotAllowedLogEntry; use App\Services\ElementTypeNameGenerator; -use Doctrine\ORM\EntityManagerInterface; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -64,12 +63,11 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ class LogEntryExtraFormatter { + protected const CONSOLE_SEARCH = ['', '', '', '', '']; + protected const CONSOLE_REPLACE = ['→', '', '', '', '']; protected $translator; protected $elementTypeNameGenerator; - protected const CONSOLE_SEARCH = ['', '', '', '', '', ]; - protected const CONSOLE_REPLACE = ['→', '', '', '', '']; - public function __construct(TranslatorInterface $translator, ElementTypeNameGenerator $elementTypeNameGenerator) { $this->translator = $translator; @@ -90,15 +88,40 @@ class LogEntryExtraFormatter foreach ($arr as $key => $value) { $str = ''; if (is_string($key)) { - $str .= '' . $this->translator->trans($key) . ': '; + $str .= ''.$this->translator->trans($key).': '; } $str .= $value; - if (!empty($str)) { + if (! empty($str)) { $tmp[] = $str; } } - return str_replace(static::CONSOLE_SEARCH, static::CONSOLE_REPLACE, implode("; ", $tmp)); + return str_replace(static::CONSOLE_SEARCH, static::CONSOLE_REPLACE, implode('; ', $tmp)); + } + + /** + * Return a HTML formatted string containing a user viewable form of the Extra data. + * + * @return string + */ + public function format(AbstractLogEntry $context): string + { + $arr = $this->getInternalFormat($context); + $tmp = []; + + //Make an array with entries in the form "Key: Value" + foreach ($arr as $key => $value) { + $str = ''; + if (is_string($key)) { + $str .= ''.$this->translator->trans($key).': '; + } + $str .= $value; + if (! empty($str)) { + $tmp[] = $str; + } + } + + return implode('; ', $tmp); } protected function getInternalFormat(AbstractLogEntry $context): array @@ -129,9 +152,9 @@ class LogEntryExtraFormatter if ($context instanceof LogWithEventUndoInterface) { if ($context->isUndoEvent()) { - if ($context->getUndoMode() === 'undo') { + if ('undo' === $context->getUndoMode()) { $array['log.undo_mode.undo'] = (string) $context->getUndoEventID(); - } elseif ($context->getUndoMode() === 'revert') { + } elseif ('revert' === $context->getUndoMode()) { $array['log.undo_mode.revert'] = (string) $context->getUndoEventID(); } } @@ -146,7 +169,7 @@ class LogEntryExtraFormatter } if ($context instanceof ElementDeletedLogEntry) { - if ($context->getOldName() !== null) { + if (null !== $context->getOldName()) { $array['log.element_deleted.old_name'] = htmlspecialchars($context->getOldName()); } else { $array['log.element_deleted.old_name'] = $this->translator->trans('log.element_deleted.old_name.unknown'); @@ -183,29 +206,4 @@ class LogEntryExtraFormatter return $array; } - - /** - * Return a HTML formatted string containing a user viewable form of the Extra data. - * - * @return string - */ - public function format(AbstractLogEntry $context): string - { - $arr = $this->getInternalFormat($context); - $tmp = []; - - //Make an array with entries in the form "Key: Value" - foreach ($arr as $key => $value) { - $str = ''; - if (is_string($key)) { - $str .= '' . $this->translator->trans($key) . ': '; - } - $str .= $value; - if (!empty($str)) { - $tmp[] = $str; - } - } - - return implode("; ", $tmp); - } } diff --git a/src/Services/LogSystem/TimeTravel.php b/src/Services/LogSystem/TimeTravel.php index 54e9fa72..f8548e83 100644 --- a/src/Services/LogSystem/TimeTravel.php +++ b/src/Services/LogSystem/TimeTravel.php @@ -1,4 +1,7 @@ setField($element, 'id', $id); //Let database determine when it will be created - $this->setField($element,'addedDate', null); + $this->setField($element, 'addedDate', null); return $element; } /** - * Revert the given element to the state it has on the given timestamp - * @param AbstractDBElement $element - * @param \DateTime $timestamp - * @param AbstractLogEntry[] $reverted_elements + * Revert the given element to the state it has on the given timestamp. + * + * @param AbstractLogEntry[] $reverted_elements + * * @throws \Exception */ - public function revertEntityToTimestamp(AbstractDBElement $element, \DateTime $timestamp, array $reverted_elements = []) + public function revertEntityToTimestamp(AbstractDBElement $element, \DateTime $timestamp, array $reverted_elements = []): void { - if (!$element instanceof TimeStampableInterface) { + if (! $element instanceof TimeStampableInterface) { throw new \InvalidArgumentException('$element must have a Timestamp!'); } @@ -84,7 +88,7 @@ class TimeTravel } //Skip this process if already were reverted... - if (in_array($element, $reverted_elements)) { + if (in_array($element, $reverted_elements, true)) { return; } $reverted_elements[] = $element; @@ -122,35 +126,34 @@ class TimeTravel $associations = $metadata->getAssociationMappings(); foreach ($associations as $field => $mapping) { if ( - ($element instanceof AbstractStructuralDBElement && ($field === 'parts' || $field === 'children')) - || ($element instanceof AttachmentType && $field === 'attachments') + ($element instanceof AbstractStructuralDBElement && ('parts' === $field || 'children' === $field)) + || ($element instanceof AttachmentType && 'attachments' === $field) ) { continue; } - //Revert many to one association (one element in property) if ( - $mapping['type'] === ClassMetadata::MANY_TO_ONE - || $mapping['type'] === ClassMetadata::ONE_TO_ONE + ClassMetadata::MANY_TO_ONE === $mapping['type'] + || ClassMetadata::ONE_TO_ONE === $mapping['type'] ) { $target_element = $this->getField($element, $field); - if ($target_element !== null && $element->getLastModified() > $timestamp) { + if (null !== $target_element && $element->getLastModified() > $timestamp) { $this->revertEntityToTimestamp($target_element, $timestamp, $reverted_elements); } } elseif ( //Revert *_TO_MANY associations (collection properties) - ($mapping['type'] === ClassMetadata::MANY_TO_MANY - || $mapping['type'] === ClassMetadata::ONE_TO_MANY) - && $mapping['isOwningSide'] === false + (ClassMetadata::MANY_TO_MANY === $mapping['type'] + || ClassMetadata::ONE_TO_MANY === $mapping['type']) + && false === $mapping['isOwningSide'] ) { $target_elements = $this->getField($element, $field); - if ($target_elements === null || count($target_elements) > 10) { + if (null === $target_elements || count($target_elements) > 10) { continue; } foreach ($target_elements as $target_element) { - if ($target_element !== null && $element->getLastModified() >= $timestamp) { + if (null !== $target_element && $element->getLastModified() >= $timestamp) { //Remove the element from collection, if it did not existed at $timestamp - if (!$this->repo->getElementExistedAtTimestamp($target_element, $timestamp)) { + if (! $this->repo->getElementExistedAtTimestamp($target_element, $timestamp)) { if ($target_elements instanceof Collection) { $target_elements->removeElement($target_element); } @@ -159,23 +162,21 @@ class TimeTravel } } } - } } /** - * Apply the changeset in the given LogEntry to the element - * @param AbstractDBElement $element - * @param TimeTravelInterface $logEntry + * Apply the changeset in the given LogEntry to the element. + * * @throws \Doctrine\ORM\Mapping\MappingException */ public function applyEntry(AbstractDBElement $element, TimeTravelInterface $logEntry): void { //Skip if this does not provide any info... - if (!$logEntry->hasOldDataInformations()) { + if (! $logEntry->hasOldDataInformations()) { return; } - if (!$element instanceof TimeStampableInterface) { + if (! $element instanceof TimeStampableInterface) { return; } $metadata = $this->em->getClassMetadata(get_class($element)); @@ -204,14 +205,15 @@ class TimeTravel $reflection = new \ReflectionClass(get_class($element)); $property = $reflection->getProperty($field); $property->setAccessible(true); + return $property->getValue($element); } - protected function setField(AbstractDBElement $element, string $field, $new_value) + protected function setField(AbstractDBElement $element, string $field, $new_value): void { $reflection = new \ReflectionClass(get_class($element)); $property = $reflection->getProperty($field); $property->setAccessible(true); $property->setValue($element, $new_value); } -} \ No newline at end of file +} diff --git a/src/Services/Parameters/ParameterExtractor.php b/src/Services/Parameters/ParameterExtractor.php new file mode 100644 index 00000000..a01ce327 --- /dev/null +++ b/src/Services/Parameters/ParameterExtractor.php @@ -0,0 +1,97 @@ +. + */ + +namespace App\Services\Parameters; + + +use App\Entity\Parameters\AbstractParameter; +use App\Entity\Parameters\PartParameter; + +class ParameterExtractor +{ + protected const ALLOWED_PARAM_SEPARATORS = [", ", "\n"]; + + protected const CHAR_LIMIT = 1000; + + /** + * Tries to extract parameters from the given string. + * Useful for extraction from part description and comment. + * @param string $input + * @param string $class + * @return AbstractParameter[] + */ + public function extractParameters(string $input, string $class = PartParameter::class): array + { + if (!is_a($class, AbstractParameter::class, true)) { + throw new \InvalidArgumentException('$class must be a child class of AbstractParameter!'); + } + + //Restrict search length + $input = mb_strimwidth($input,0,self::CHAR_LIMIT); + + $parameters = []; + + //Try to split the input string into different sub strings each containing a single parameter + $split = $this->splitString($input); + foreach ($split as $param_string) { + $tmp = $this->stringToParam($param_string, $class); + if ($tmp !== null) { + $parameters[] = $tmp; + } + } + + return $parameters; + } + + protected function stringToParam(string $input, string $class): ?AbstractParameter + { + $input = trim($input); + $regex = '/^(.*) *(?:=|:) *(.+)/u'; + + $matches = []; + \preg_match($regex, $input, $matches); + dump($matches); + if (!empty($matches)) { + [$raw, $name, $value] = $matches; + $value = trim($value); + + //Dont allow empty names or values (these are a sign of an invalid extracted string) + if (empty($name) || empty($value)) { + return null; + } + + /** @var AbstractParameter $parameter */ + $parameter = new $class(); + $parameter->setName(trim($name)); + $parameter->setValueText($value); + + return $parameter; + } + + return null; + } + + protected function splitString(string $input): array + { + //Allow comma as limiter (include space, to prevent splitting in german style numbers) + $input = str_replace(static::ALLOWED_PARAM_SEPARATORS, ";", $input); + return explode(";", $input); + } +} \ No newline at end of file diff --git a/src/Services/PermissionResolver.php b/src/Services/PermissionResolver.php index e26e06e8..15cb5845 100644 --- a/src/Services/PermissionResolver.php +++ b/src/Services/PermissionResolver.php @@ -50,7 +50,6 @@ use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Yaml\Yaml; class PermissionResolver diff --git a/src/Services/StatisticsHelper.php b/src/Services/StatisticsHelper.php index c9305128..f5174bce 100644 --- a/src/Services/StatisticsHelper.php +++ b/src/Services/StatisticsHelper.php @@ -1,4 +1,7 @@ Currency::class, ]; - if (!isset($arr[$type])) { + if (! isset($arr[$type])) { throw new \InvalidArgumentException('No count for the given type available!'); } /** @var EntityRepository $repo */ $repo = $this->em->getRepository($arr[$type]); + return $repo->count([]); } /** * Gets the count of all attachments. + * * @return int */ public function getAttachmentsCount(): int @@ -116,7 +124,8 @@ class StatisticsHelper } /** - * Gets the count of all private/secure attachments + * Gets the count of all private/secure attachments. + * * @return int */ public function getPrivateAttachmentsCount(): int @@ -125,8 +134,10 @@ class StatisticsHelper } /** - * Gets the count of all external (only containing an URL) attachments + * Gets the count of all external (only containing an URL) attachments. + * * @return int + * * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException */ @@ -137,7 +148,9 @@ class StatisticsHelper /** * Gets the count of all attachments where the user uploaded an file. + * * @return int + * * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException */ @@ -145,4 +158,4 @@ class StatisticsHelper { return $this->attachment_repo->getUserUploadedAttachments(); } -} \ No newline at end of file +} diff --git a/src/Services/StructuralElementRecursionHelper.php b/src/Services/StructuralElementRecursionHelper.php index f22c027c..23ad2f84 100644 --- a/src/Services/StructuralElementRecursionHelper.php +++ b/src/Services/StructuralElementRecursionHelper.php @@ -58,12 +58,12 @@ class StructuralElementRecursionHelper * Executes an function (callable) recursivly for $element and every of its children. * * @param AbstractStructuralDBElement $element The element on which the func should be executed - * @param callable $func The function which should be executed for each element. - * $func has the signature function(StructuralDBElement $element) : void - * @param int $max_depth The maximum depth for which should be recursivly called. So if this is set to 5, after the - * 5th level the execution is stopped. - * @param bool $call_from_bottom If set to true the bottom elements (elements with high level) will be called first. - * Set to false if you want to call the top elements first. + * @param callable $func The function which should be executed for each element. + * $func has the signature function(StructuralDBElement $element) : void + * @param int $max_depth The maximum depth for which should be recursivly called. So if this is set to 5, after the + * 5th level the execution is stopped. + * @param bool $call_from_bottom If set to true the bottom elements (elements with high level) will be called first. + * Set to false if you want to call the top elements first. */ public function execute(AbstractStructuralDBElement $element, callable $func, int $max_depth = -1, $call_from_bottom = true): void { @@ -94,8 +94,8 @@ class StructuralElementRecursionHelper * Deletes the $element and all its subelements recursivly. * * @param AbstractStructuralDBElement $element the element which should be deleted - * @param bool $flush When set to true the changes will also be flushed to DB. Set to false if you want to flush - * later. + * @param bool $flush When set to true the changes will also be flushed to DB. Set to false if you want to flush + * later. */ public function delete(AbstractStructuralDBElement $element, bool $flush = true): void { diff --git a/src/Services/Trees/NodesListBuilder.php b/src/Services/Trees/NodesListBuilder.php index 361b4e0d..b108b315 100644 --- a/src/Services/Trees/NodesListBuilder.php +++ b/src/Services/Trees/NodesListBuilder.php @@ -69,7 +69,7 @@ class NodesListBuilder * Gets a flattened hierachical tree. Useful for generating option lists. * In difference to the Repository Function, the results here are cached. * - * @param string $class_name The class name of the entity you want to retrieve. + * @param string $class_name The class name of the entity you want to retrieve. * @param AbstractStructuralDBElement|null $parent This entity will be used as root element. Set to null, to use global root * * @return AbstractStructuralDBElement[] A flattened list containing the tree elements. diff --git a/src/Services/Trees/TreeViewGenerator.php b/src/Services/Trees/TreeViewGenerator.php index e98a7f46..44334cf9 100644 --- a/src/Services/Trees/TreeViewGenerator.php +++ b/src/Services/Trees/TreeViewGenerator.php @@ -76,10 +76,10 @@ class TreeViewGenerator /** * Gets a TreeView list for the entities of the given class. * - * @param string $class The class for which the treeView should be generated + * @param string $class The class for which the treeView should be generated * @param AbstractStructuralDBElement|null $parent The root nodes in the tree should have this element as parent (use null, if you want to get all entities) - * @param string $href_type The link type that will be generated for the hyperlink section of each node (see EntityURLGenerator for possible values). - * Set to empty string, to disable href field. + * @param string $href_type The link type that will be generated for the hyperlink section of each node (see EntityURLGenerator for possible values). + * Set to empty string, to disable href field. * @param AbstractDBElement|null $selectedElement The element that should be selected. If set to null, no element will be selected. * * @return TreeViewNode[] An array of TreeViewNode[] elements of the root elements. @@ -132,7 +132,7 @@ class TreeViewGenerator * Gets a tree of TreeViewNode elements. The root elements has $parent as parent. * The treeview is generic, that means the href are null and ID values are set. * - * @param string $class The class for which the tree should be generated + * @param string $class The class for which the tree should be generated * @param AbstractStructuralDBElement|null $parent The parent the root elements should have. * * @return TreeViewNode[] diff --git a/src/Twig/LastUserExtension.php b/src/Twig/LastUserExtension.php index 25e4833f..524e8bad 100644 --- a/src/Twig/LastUserExtension.php +++ b/src/Twig/LastUserExtension.php @@ -1,4 +1,7 @@ repo, 'getLastEditingUser']), - new TwigFunction('getCreatingUser', [$this->repo, 'getCreatingUser']) + new TwigFunction('getCreatingUser', [$this->repo, 'getCreatingUser']), ]; } -} \ No newline at end of file +} diff --git a/symfony.lock b/symfony.lock index c1cc58e0..eca9c54a 100644 --- a/symfony.lock +++ b/symfony.lock @@ -277,6 +277,9 @@ "paragonie/constant_time_encoding": { "version": "v2.3.0" }, + "paragonie/random_compat": { + "version": "v9.99.99" + }, "php": { "version": "7.2.5" }, @@ -650,6 +653,9 @@ "./tests/.gitignore" ] }, + "symfony/polyfill-ctype": { + "version": "v1.14.0" + }, "symfony/polyfill-intl-icu": { "version": "v1.10.0" }, diff --git a/templates/AdminPages/EntityAdminBase.html.twig b/templates/AdminPages/EntityAdminBase.html.twig index f298b841..ef4d335c 100644 --- a/templates/AdminPages/EntityAdminBase.html.twig +++ b/templates/AdminPages/EntityAdminBase.html.twig @@ -85,6 +85,11 @@ + {% if entity.parameters is defined %} + + {% endif %} @@ -113,6 +118,12 @@ {{ form_row(form.master_picture_attachment) }} {% endblock %}
+ + {% if entity.parameters is defined %} +
+ {% include "AdminPages/_parameters.html.twig" %} +
+ {% endif %}
@@ -176,13 +187,7 @@ {% endif %} - -
- - - - diff --git a/templates/AdminPages/_parameters.html.twig b/templates/AdminPages/_parameters.html.twig new file mode 100644 index 00000000..75f63cbf --- /dev/null +++ b/templates/AdminPages/_parameters.html.twig @@ -0,0 +1,54 @@ +{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %} + + + + + + + + + + + + + + + + + {% for param in form.parameters %} + {{ form_widget(param) }} + {% endfor %} + +
{% trans %}specifications.property{% endtrans %}{% trans %}specifications.symbol{% endtrans %}{% trans %}specifications.value_min{% endtrans %}{% trans %}specifications.value_typ{% endtrans %}{% trans %}specifications.value_max{% endtrans %}{% trans %}specifications.unit{% endtrans %}{% trans %}specifications.text{% endtrans %}{% trans %}specifications.group{% endtrans %}
+ + + + \ No newline at end of file diff --git a/templates/Parts/edit/_specifications.html.twig b/templates/Parts/edit/_specifications.html.twig new file mode 100644 index 00000000..dd5af0fd --- /dev/null +++ b/templates/Parts/edit/_specifications.html.twig @@ -0,0 +1,54 @@ +{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %} + + + + + + + + + + + + + + + + + {% for param in form.parameters %} + {{ form_widget(param) }} + {% endfor %} + +
{% trans %}specifications.property{% endtrans %}{% trans %}specifications.symbol{% endtrans %}{% trans %}specifications.value_min{% endtrans %}{% trans %}specifications.value_typ{% endtrans %}{% trans %}specifications.value_max{% endtrans %}{% trans %}specifications.unit{% endtrans %}{% trans %}specifications.text{% endtrans %}{% trans %}specifications.group{% endtrans %}
+ + + + \ No newline at end of file diff --git a/templates/Parts/edit/edit_form_styles.html.twig b/templates/Parts/edit/edit_form_styles.html.twig index 0d357a18..27e289ef 100644 --- a/templates/Parts/edit/edit_form_styles.html.twig +++ b/templates/Parts/edit/edit_form_styles.html.twig @@ -62,4 +62,23 @@ {{ form_errors(form) }} +{% endblock %} + +{% block parameter_widget %} + + {{ form_widget(form.name) }}{{ form_errors(form.name) }} + {{ form_widget(form.symbol) }}{{ form_errors(form.symbol) }} + {{ form_widget(form.value_min) }}{{ form_errors(form.value_min) }} + {{ form_widget(form.value_typical) }}{{ form_errors(form.value_typical) }} + {{ form_widget(form.value_max) }}{{ form_errors(form.value_max) }} + {{ form_widget(form.unit) }}{{ form_errors(form.unit) }} + {{ form_widget(form.value_text) }}{{ form_errors(form.value_text) }} + {{ form_widget(form.group) }}{{ form_errors(form.group) }} + + + {{ form_errors(form) }} + + {% endblock %} \ No newline at end of file diff --git a/templates/Parts/edit/edit_part_info.html.twig b/templates/Parts/edit/edit_part_info.html.twig index b57e7653..3a437a32 100644 --- a/templates/Parts/edit/edit_part_info.html.twig +++ b/templates/Parts/edit/edit_part_info.html.twig @@ -52,6 +52,12 @@ {% trans %}part.edit.tab.orderdetails{% endtrans %} + {% endif %} - - + {% if part.parameters is not empty or description_params is not empty or comment_params is not empty %} + + {% endif %} + {% if part.attachments is not empty %} + + {% endif %} + {% if part.orderdetails is not empty %} + + {% endif %}