Compare commits

...

222 Commits

Author SHA1 Message Date
Igor Scheller fc8d335ea2 Fix ics escaping and IDs 2023-06-05 08:28:07 +02:00
Igor Scheller ab5f6a270c Replace `Please select...` with translation key 2023-06-05 08:28:07 +02:00
Igor Scheller b07f879d64 macros: arguments are mostly defined, cleanup 2023-06-05 08:28:07 +02:00
Igor Scheller 2e26f41964 Profile settings: Fix shiftinfo email text 2023-06-05 08:28:07 +02:00
Igor Scheller fa95bca673 Fixed code spacing 2023-05-19 16:16:46 +02:00
xuwhite 9bd3978257
Fix user sorting on angeltype page (#1144) 2023-05-19 16:09:25 +02:00
Xu 063e9a8ec2 delete all comments in translation files 2023-05-13 18:16:37 +02:00
Michael Weimann c4f65bfbdb Fix spinner button 2023-05-11 18:54:55 +02:00
Michael Weimann c5317e2536 Add ShirtSize validation 2023-05-11 18:48:28 +02:00
Igor Scheller 8bb8837e38 Shifts filter: Only show rooms with shifts 2023-05-03 16:04:39 +02:00
Igor Scheller 983fb988b4 Make profile page layout and shifts renderer less worse for normal users 2023-05-03 16:04:39 +02:00
Igor Scheller 72d48de3ae Add ETag to FeedController 2023-05-03 16:04:39 +02:00
Michael Weimann dc216a0464 Move optional twig form macro attributes to opt 2023-05-01 16:59:26 +02:00
dependabot[bot] c0957955fd Bump nyholm/psr7 from 1.5.1 to 1.6.1
Bumps [nyholm/psr7](https://github.com/Nyholm/psr7) from 1.5.1 to 1.6.1.
- [Release notes](https://github.com/Nyholm/psr7/releases)
- [Changelog](https://github.com/Nyholm/psr7/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Nyholm/psr7/compare/1.5.1...1.6.1)

---
updated-dependencies:
- dependency-name: nyholm/psr7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-26 11:31:37 +02:00
dependabot[bot] 93d3d46be7 Bump guzzlehttp/psr7 from 2.4.3 to 2.5.0
Bumps [guzzlehttp/psr7](https://github.com/guzzle/psr7) from 2.4.3 to 2.5.0.
- [Release notes](https://github.com/guzzle/psr7/releases)
- [Changelog](https://github.com/guzzle/psr7/blob/2.5/CHANGELOG.md)
- [Commits](https://github.com/guzzle/psr7/compare/2.4.3...2.5.0)

---
updated-dependencies:
- dependency-name: guzzlehttp/psr7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-21 15:23:12 +02:00
Thomas Rupprecht 79519aaa07
Update node to v20 (#1075)
* uppercase keywords
* update node to v20
2023-04-21 15:10:26 +02:00
Michael Weimann 3901cdbf2a
Tweak navbar collapse as guest and fix language dropdown position (#1128)
* Fix language switcher position
* Tweak navbar collapse as guest
2023-04-19 21:19:22 +02:00
Igor Scheller 16632706e0 menu: Don't scroll to top when clicking info 2023-04-19 20:11:38 +02:00
Igor Scheller a0c879948d shifts: Add additional filter button on mobile devices 2023-04-19 20:11:38 +02:00
Igor Scheller 683d4a0e62 Config: Load more values from env variables 2023-04-19 20:11:38 +02:00
Igor Scheller e359d93db6 CI: Added build cache 2023-04-19 20:11:38 +02:00
Igor Scheller 24765902a2 Profile edit: Add rows to fix layout 2023-04-19 20:11:38 +02:00
Igor Scheller ca6e0813ba RouteDispatcher: Fixed string conversion 2023-04-19 20:11:38 +02:00
Igor Scheller c85eb2f3d2 Migrations: Fix migration name 2023-04-19 20:11:38 +02:00
Michael Weimann 1292722ac3 Add Username validation 2023-04-17 23:09:08 +02:00
Thomas Rupprecht 57940cf570 fix mailto link of angeltypes in about page 2023-04-16 18:57:36 +02:00
Thomas Rupprecht aafc01b01e fix radius of card on questions page 2023-04-13 15:47:15 +02:00
Igor Scheller 6e8dc642de Catch Exception when sending emails to users 2023-04-08 19:55:54 +02:00
Igor Scheller bf4a818e01 Make session cleanup more robust and tests explicit 2023-04-08 14:14:57 +02:00
Igor Scheller 9f35ebc482 Use app configured session lifetime for garbage collection 2023-04-08 00:34:43 +02:00
Igor Scheller 6da0c8a835 Fixed public dashboard stats and sorting 2023-04-07 23:48:07 +02:00
Thomas Rupprecht 460a449a8b
use angle macro (#1121) 2023-04-03 19:05:35 +02:00
Thomas Rupprecht 84c1cc36e5
Improve javascript (#1077) 2023-04-01 15:14:32 +02:00
Thomas Rupprecht d4104850be
phpstan fixes (partial level 3) (#1091) 2023-04-01 14:39:25 +02:00
Igor Scheller 131c6af6a2 Updated contributing guidelines: Clarified includes 2023-03-31 14:30:51 +02:00
Thomas Rupprecht 3f0a5a5b73 hide language/theme menu if not more than 1 selection is available 2023-03-30 21:55:28 +02:00
Thomas Rupprecht 21d8c27c92 improve profile layout 2023-03-30 17:25:19 +02:00
Thomas Rupprecht 14ff157a12
uppercase DISPLAY_FULL_NAME env var
improve default config #1118
2023-03-30 13:30:41 +02:00
bk-debug ebed5acd5a
Add Room import to shifts controller 2023-03-25 20:54:06 +01:00
dependabot[bot] ad775cc37c
Bump webpack from 5.75.0 to 5.76.0
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-15 08:28:00 +00:00
Johannes Rudolph c67fbbad73 Add option to show user first and last name instead of nickname 2023-03-13 17:33:17 +01:00
Igor Scheller 031e1a08fe
Fix button types and remove unused classes
Co-authored-by: Thomas Rupprecht <rupprecht.thomas@gmail.com>
2023-03-10 15:53:54 +01:00
xuwhite 668a9e86f5
refactor goodie config option as enum (#1100)
* goodie config as enum
* Unified goodie check, updated test
* Changed tshirt to goodie in url

---------

Co-authored-by: Igor Scheller <igor.scheller@igorshp.de>
2023-03-05 03:00:38 +01:00
Igor Scheller 523e984122 Added git HEAD to version parsing 2023-02-28 16:12:01 +01:00
Igor Scheller fb8c05edad Added email notification on new private messages 2023-02-26 16:59:48 +01:00
Igor Scheller a464682b47 Reimplemented admin room pages 2023-02-26 16:55:04 +01:00
Igor Scheller baca49c53b Fixed quotest 2023-02-26 16:32:02 +01:00
Igor Scheller 34e9d01c18 Translate more date / time outputs 2023-02-26 14:10:02 +01:00
Igor Scheller 6b15e6b86e Fixed news test 2023-02-26 13:49:13 +01:00
Igor Scheller 09e6e9d239 Basic maintenance page styling 2023-02-26 13:49:13 +01:00
Igor Scheller cf18f058b5 Moved logging tests from feature to unit 2023-02-26 13:49:13 +01:00
Igor Scheller b35a5af515 Added code coverage hint to development doc 2023-02-26 13:49:13 +01:00
Igor Scheller 642a49aefe Show dropdowns above sticky shifts headers 2023-02-26 13:49:13 +01:00
Igor Scheller e2f387d111 Remove type="text/javascript" from <script> tags 2023-02-26 13:49:13 +01:00
Igor Scheller e0a702ec3b Fixed stats test 2023-02-26 13:49:13 +01:00
Michael Weimann 920fa7feb9 Add composer phpunit:coverage script 2023-02-17 22:12:41 +01:00
Igor Scheller 98a0937b82 Reimplemented angeltypes about page 2023-02-15 18:05:30 +01:00
Thomas Rupprecht 0e033256f0
improve webpack.config.js 2023-02-15 17:51:15 +01:00
xuwhite 6fcb656299
Added important news (#1096) 2023-02-13 21:19:45 +01:00
Igor Scheller 713f8222e4 Unified user notifications 2023-02-13 19:38:29 +01:00
Thomas Rupprecht 1fe30fc82f update libs 2023-02-09 18:37:35 +01:00
Bot ad360a70fb Require comma at last array element and no single line space 2023-02-09 18:19:38 +01:00
Igor Scheller 216185b65c Don't use double-quoted strings if not needed 2023-02-09 18:19:38 +01:00
Thomas Rupprecht a1a1cf6f93
Unify migration style and cleanup (#1037)
* unify helper methods access type to private
* unify codestyle
* remove unused down methods
2023-02-08 21:53:58 +01:00
Thomas Rupprecht 2ff953ef89 fix php docs types 2023-02-07 15:37:20 +01:00
Thomas Rupprecht c147f06b91 rename `docker-compose` to `docker compose` 2023-02-04 01:35:10 +01:00
Thomas Rupprecht cbdee7a9f3 language fixes 2023-02-03 21:06:40 +01:00
Bot f9d22f9bda Set strict types everywhere (except includes) 2023-02-03 20:55:58 +01:00
Michael Weimann 3c6a5bb385 Fix strict types errors 2023-02-03 20:55:58 +01:00
Thomas Rupprecht 4dde4cd9fa update libs and move bootstrap-icons to dependencies 2023-02-03 14:36:18 +01:00
Igor Scheller 7eccf2c535 Reimplemented shifts json export 2023-02-02 20:01:31 +01:00
Igor Scheller b0b4cb54ec Reimplemented shifts ical export 2023-02-02 20:01:31 +01:00
Igor Scheller 3d0d5067fd Reimplemented news Atom feed, added RSS feed 2023-02-02 20:01:31 +01:00
Igor Scheller 8223193330 Added uuid/uuidBy twig functions 2023-02-02 20:01:31 +01:00
Igor Scheller a9cd00c37a Authenticator: Improve auth methods handling, esp. for api endpoints 2023-02-02 20:01:31 +01:00
Igor Scheller ac97413f3f Add public/fahrplan.xml to .gitignore 2023-01-31 15:20:09 +01:00
Michael Weimann 321fbc82fc Add git to dev container 2023-01-31 14:57:21 +01:00
Xu 21eafb7d26 restructure of DEVELOPMENT.md and adding the new port 5080 localhost to it 2023-01-31 02:06:44 +01:00
Xu ccdf1aa8d5 add config option for other goodies 2023-01-31 01:51:31 +01:00
Igor Scheller 3ca39dc8e1 Fixed shifts bulk deletion 2023-01-25 01:00:42 +01:00
Igor Scheller 0188ed5562 Fixed StringInputLength validation 2023-01-24 23:28:15 +01:00
Xu b99e6ed8c1 add hint on how many shifts to be created 2023-01-24 21:33:13 +01:00
Igor Scheller 99ab7853da Added time input to /design 2023-01-24 20:49:31 +01:00
Igor Scheller bfa0d91704 Fix empty checks 2023-01-24 20:49:31 +01:00
Igor Scheller 37a26c123e Validation: Fixed worklog comment: ... 2023-01-24 20:49:31 +01:00
Igor Scheller f5a7598a45 tests: Removed exception handler registration because it has side effects 2023-01-24 20:49:31 +01:00
Thomas Rupprecht 733586dfd5 replace sticky-headers javascript impl with css 2023-01-24 20:13:13 +01:00
Thomas Rupprecht 3412ed2924
invert input time icon color for chrome based browsers in dark themes (#1060) 2023-01-24 19:45:48 +01:00
Thomas Rupprecht e844c98871
Convert class const's to enum's (#1050)
* convert `Migrate::(UP|DOWN)` class const to `MigrateDirection` enum
* convert `Handler::(ENV_PRODUCTION|ENV_DEVELOPMENT)` class const to `Environment` enum
* convert `ShiftSignupState::(FREE|...|NOT_ARRIVED)` class const to `ShiftSignupStatus::(FREE|...|NOT_ARRIVED)` enum
2023-01-24 19:23:57 +01:00
Michael Weimann 2db70c96ed
Add pre-commit hook (#1071) 2023-01-24 14:26:10 +01:00
Thomas Rupprecht 5a2b8f7ff9
Improve navbar 2023-01-22 19:16:33 +01:00
Igor Scheller 96f703bf22
Migrate NeededAngelType model 2023-01-22 18:43:09 +01:00
Igor Scheller 89dc85c3d5
Add ShiftEntry model 2023-01-18 13:02:11 +01:00
xuwhite 89f9b423b1
room view & angeltype view: show all shifts (#1067) 2023-01-17 20:01:29 +01:00
Johannes Rudolph 64be48c646 Add Possibility for Custom Translations: config/[locale]/custom.po 2023-01-17 19:22:59 +01:00
Thomas Rupprecht d18185f49e
Improve alerts and conversation (#1062)
* add role="alert"
* improve conversation styling
* replace alert with card for conversation
2023-01-17 15:05:47 +01:00
Michael Weimann 01373cb192 Replace select 2 with choices.js and kill jQuery 2023-01-17 14:27:38 +01:00
Igor Scheller 2be8e565bf Refactored UUID generation: use pseudo unique named UUID for schedules 2023-01-06 14:16:41 +01:00
Igor Scheller 23424830e7 Removed unused reference 2023-01-03 22:42:50 +01:00
Igor Scheller 3115870ec4
Added Shift model 2023-01-03 22:19:03 +01:00
Michael Weimann 1d1618836b
Fix frontend formatting 2023-01-03 20:20:46 +01:00
Thomas Rupprecht 30f50dab6d
Extract shifts filter JavaScript and improve HTML structure 2023-01-02 18:54:32 +01:00
Michael Weimann c2e3902c53
Update frontend deps 2023-01-02 17:59:06 +01:00
Igor Scheller 26b5a6e1f0 Fix shifts edit page 2022-12-28 12:31:31 +01:00
Igor Scheller 9409b320f0 CI: Improve GitLab k8s deployment for agents support 2022-12-28 11:54:47 +01:00
Michael Weimann 59cfce0c76
Enable space after cast sniff and remove .git-blame-ignore-revs 2022-12-25 11:59:45 +01:00
Michael Weimann 86cc0a238d
Remove function-paren-newline from ESLint, covered by prettier 2022-12-23 19:21:02 +01:00
Michael Weimann 43993aaba5
Fix JS code style 2022-12-23 19:15:03 +01:00
Thomas Rupprecht 2bab370221
enable/disable all html-tags corresponding to a radio button checked state (#1046) 2022-12-23 18:31:26 +01:00
Johannes Rudolph b1b08afd23
Make user view columns dynamic by config 2022-12-23 04:46:32 +01:00
Johannes Rudolph 92e0b8be65
Hide dect, voucher and t-shirt options shown to users when disabled via config 2022-12-23 04:22:39 +01:00
Johannes Rudolph 737066414e
Fix i18n on User Edit Page 2022-12-23 03:20:10 +01:00
Michael Weimann 0ae10471d1 Add prettier 2022-12-23 02:20:43 +01:00
Igor Scheller b024650eaf Fix formatting 2022-12-22 00:35:07 +01:00
Thomas Rupprecht 3d88ae7916
convert `switch` to `match` 2022-12-22 00:08:54 +01:00
Thomas Rupprecht fdddd63aae
fix input radio id and default to multi on shift creation 2022-12-21 23:53:47 +01:00
Igor Scheller 559517e017 Ignore the timezone configured in php.ini, better cleanup after feature tests 2022-12-21 17:22:45 +01:00
Igor Scheller d1b7b6886e Fix tests coverage 2022-12-21 15:11:37 +01:00
Thomas Rupprecht f24d31b928
Improve countdown logic
use `Intl.RelativeTimeFormat` to support different l10n add week as possible duration
2022-12-21 14:18:21 +01:00
Igor Scheller 98a3187899
Use native types where possible + ctor prop promotion 💣 2022-12-21 12:46:40 +01:00
Igor Scheller d92733f658 Schedule: Make URLs klickable on overview and handle connection errors 2022-12-21 12:08:48 +01:00
Igor Scheller 700d841a87 Fix atom, ical and json exports 2022-12-21 11:42:55 +01:00
Michael Weimann 6dac44d67f
Rename class props to match ctor param 2022-12-20 22:19:52 +01:00
Michael Weimann 202eae5136
Specify PHP version for PHPCS
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-20 22:19:52 +01:00
Michael Weimann 2532e87029
Add git-blame-ignore-revs 2022-12-20 22:19:51 +01:00
Michael Weimann 2ad4203dd3
Add useless comment phpcs sniff 2022-12-20 22:19:49 +01:00
Michael Weimann 61139e03c3
Use constructor property promotion
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-20 22:18:34 +01:00
Michael Weimann b004f865b4
Set native property types
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-15 20:13:50 +01:00
Michael Weimann aff8826c99
Set native return types
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-15 20:13:31 +01:00
Michael Weimann 2b88322c0c
Set native parameter types
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-15 20:13:30 +01:00
Igor Scheller f835a7538c Tests: Improved execution time, test more factories 2022-12-13 22:59:56 +01:00
Igor Scheller 93b30dcbdf OAuth2 event: refactoring 2022-12-13 22:46:16 +01:00
Igor Scheller 5b8805f884 Moved OAuth2 event helper and added tests 2022-12-13 22:46:16 +01:00
Igor Scheller 7f78f59840 Added UserAngelType model 2022-12-13 22:46:16 +01:00
Igor Scheller 99e7a088b0 Use PHP 8.2 for builds and fixed warning in email validation rule 2022-12-13 22:03:08 +01:00
Igor Scheller b4402a5b59 Update PHP dependencies (major version bumps) 2022-12-13 22:03:08 +01:00
Igor Scheller 6c4e92baf2 Bump minimum PHP version to 8.1 and update packages 2022-12-13 22:03:08 +01:00
Thomas Rupprecht 2d454ca8ae move js code for spinner into js file
now the code is needed only once for all spinners
2022-12-11 18:44:58 +01:00
Thomas Rupprecht f12f8a1b3b set autocomplete attribute for password inputs 2022-12-11 18:17:42 +01:00
Thomas Rupprecht ce0ac6f823
Use specific ID parameter names in routes (#1023) 2022-12-11 18:01:34 +01:00
Thomas Rupprecht 61cff64d96 cast timestamp to number 2022-12-11 10:21:47 +01:00
Thomas Rupprecht 5da586bc2c add JsDoc for `formatFromNow` 2022-12-11 10:21:47 +01:00
Thomas Rupprecht f446f0da7d fix wrong param name in JSDoc 2022-12-11 10:21:47 +01:00
Thomas Rupprecht fef5d77443 add JSDoc for `ready` function 2022-12-11 10:21:47 +01:00
Thomas Rupprecht 5bd922d109 code improvements
unify lowercase variant of form method post
remove duplicate class selector
improve comments
2022-12-11 10:21:47 +01:00
Michael Weimann 4c3dc1e081 Fix shift creation
Regression introduced by changing the angeltype count field IDs
2022-12-11 10:20:44 +01:00
Thomas Rupprecht 5604176675 fix mailto link 2022-12-11 10:14:07 +01:00
Michael Weimann 0633f8f335 Enable PHPCS cache 2022-12-11 10:12:05 +01:00
Igor Scheller 147a40e581 Docker: Dev: Install linux-headers for xdebug 2022-12-11 10:10:06 +01:00
Thomas Rupprecht cafbddabbf change form submit button text to "save" 2022-12-10 17:28:50 +01:00
Thomas Rupprecht c906af1010 use int instead of float for spinner value 2022-12-10 17:25:04 +01:00
Thomas Rupprecht ece4d261c4 add comment about css rules to hide the arrows in the input field 2022-12-10 17:25:04 +01:00
Thomas Rupprecht 59e623c938 add function parameter types for form_spinner 2022-12-10 17:25:04 +01:00
Thomas Rupprecht fbe52117ed improve spinner control
use input type `number` with `min` and `step`
use `.stepDown()` and `.stepUp()` to change value
hide browser controls
2022-12-10 17:25:04 +01:00
Thomas Rupprecht 3bcbca97ab improve spinner ids 2022-12-10 17:25:04 +01:00
Thomas Rupprecht 7a376399b8 use better and more icons 2022-12-10 17:22:11 +01:00
Igor Scheller 3e22315caa CI: Fixed php version 2022-12-10 00:44:16 +01:00
Igor Scheller 31afc07d22 Ignore code coverage (parent::boot is not registered) 2022-12-08 19:23:44 +01:00
Igor Scheller 6686d58c06 Implemented AngelTypes model 2022-12-08 18:35:22 +01:00
frischler bdc62eaac3
Worklog Refactoring 2022-12-08 17:40:24 +01:00
Michael Weimann 9396a49412 Add phpstan 2022-12-08 16:32:04 +01:00
Thomas Rupprecht 0e3d47f2e1
replace md5 with random_bytes and use 64 chars for api_key 2022-12-08 15:57:13 +01:00
Thomas Rupprecht 1d158da441 remove self closing tag 2022-12-08 15:43:34 +01:00
Thomas Rupprecht 3b8a275e1c remove unused `form_multi_checkboxes` function 2022-12-08 15:43:34 +01:00
Thomas Rupprecht e8ccbd7c5e style checkboxes with bootstrap classes 2022-12-08 15:43:34 +01:00
Thomas Rupprecht 0a1014496a fix tag nesting 2022-12-08 15:36:44 +01:00
Thomas Rupprecht 2b5ffca1b0
Use template literals instead of string concatenation (#1003)
* use template literals instead of string concatenation
* extract function call out of template literals
* add contributing hint to don't put function calls in template-literals
2022-12-04 12:00:18 +01:00
Thomas Rupprecht d4a9861751
Add function-paren-newline ESLint rule; align config code style (#1000)
* unify indentation in config.default.php

* add eslint rule `function-paren-newline`

* fix `function-param-newline` lint rule
2022-12-04 11:33:25 +01:00
Michael Weimann 282f4b45ac
Replace jQuery with VanillaJS 2022-12-02 17:07:12 +01:00
Michael Weimann 7bbdb95885
Replace jQuery ready 2022-12-02 17:07:11 +01:00
Joshua Bachmeier 6917f7805b Add support for oauth scopes
As defined in RFC6749:
* https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
* https://www.rfc-editor.org/rfc/rfc6749#section-3.3

Scopes can be configured per-provider in engelsystem config.
2022-12-02 15:35:10 +01:00
Joshua Bachmeier 44821019b6 Add error handling to oauth provider response processing 2022-12-02 15:35:10 +01:00
Igor Scheller 7a92ea077f ShiftType test: Fix test 2022-12-02 15:07:29 +01:00
Thomas Rupprecht 65dca1cebd improve admin-shifts ui
on larger screens put start & end next to each other
size of the "needed angles" fit on more screen sizes
2022-12-02 14:49:14 +01:00
Thomas Rupprecht 6d5748f9f8
fix label to input link for `form_spinner`, `form_date` and `form_datetime` 2022-12-02 14:45:23 +01:00
Thomas Rupprecht 9c3c2cc2ac select2 width should be 100% to scale if the browser width changes 2022-12-02 14:25:57 +01:00
Thomas Rupprecht 4ccceb271c style input radios with bootstrap classes 2022-12-02 14:19:45 +01:00
Thomas Rupprecht 0002585de4 fix border radius on time input in shift filter 2022-12-02 13:58:30 +01:00
Thomas Rupprecht 37c7b876f3 fix select_array. needed for a correct format for select2
if `$data` is a `Collection` than the return format is `[{"key":["value"]}]` and not `[{"key":"value"}]`
2022-12-02 13:53:29 +01:00
Thomas Rupprecht 47b80b504c documentation improvements
remove trailing whitspaces
use single backticks
2022-12-02 13:27:10 +01:00
Thomas Rupprecht d952dfe262 update libs 2022-11-28 22:13:09 +01:00
Michael Weimann 1b83d0bb77
Add yarn check CI 2022-11-27 17:04:06 +01:00
Michael Weimann 9d9211c054 Format JS code 2022-11-27 16:31:32 +01:00
Michael Weimann 4752c9306c Add eslint 2022-11-27 16:31:32 +01:00
Igor Scheller 992e708276 Replaced ShiftTypes with shift_types / ShiftType model 2022-11-27 14:17:02 +01:00
Igor Scheller ac162f4411 Removed referenced angeltype from shift type 2022-11-27 14:17:02 +01:00
Igor Scheller 354ec084eb Show driver's license button on user page when angeltype requires it 2022-11-27 12:14:14 +01:00
Igor Scheller cdc218e116 db factories: More unique constrains 2022-11-26 13:36:47 +01:00
Thomas Rupprecht 23d7e8632b javascript improvements
use `const` instead of `var`/`let`
use `$(function () { ... })` instead of `$(document).ready(function () { ... })`
unify codestyle
2022-11-25 13:44:39 +01:00
Thomas Rupprecht 887add83f6 `<head>` optimizations
lowercase charset utf-8
move `<title>` after `<meta charset="utf-8"/>`
charset should be in the first 1024 bytes and the title after the charset definition
unify self closing tags
2022-11-25 12:41:43 +01:00
Michael Weimann 4f504e98f1 Update frontend deps 2022-11-25 12:32:06 +01:00
Igor Scheller 99afe3f651
Permissions refactoring
* Migration: Added groups, privileges, user_groups, group_privileges, improved references
* Models: Added Group, Privilege and integrated it into User
* Replaced old permission handling with new models
2022-11-06 12:41:52 +01:00
frischler 35815b0838 Settings Modernization: Applied suggested changed from #972 2022-11-01 16:55:23 +01:00
frischler dba7bc29f9 Settings Modernization: Added mobile_show setting to /settings/profile page. 2022-11-01 16:55:23 +01:00
frischler 63f1c12429 Settings Modernization: Refactoring
Settings Modernization: Fixing Date issue

Settings Modernization: Reroute

Settings Modernization: Reroute settings to /settings/profile, Cleanup and Refactoring
2022-11-01 16:55:23 +01:00
frischler d6899d37d9 Settings Modernization: Applying buildup and teardown time, add localization 2022-11-01 16:55:23 +01:00
frischler 203531629f Settings Modernization: Creating /settings/profile page with Controller methods and tests 2022-11-01 16:55:23 +01:00
Igor Scheller 96f4e1b3a8 Fix typo in config, default group on registration and edit comparison 2022-10-24 00:07:05 +02:00
Igor Scheller 74be132f47 Improve `/design`: Add section links and disable in-text-links 2022-10-22 20:31:41 +02:00
Igor Scheller 4d9f4694ae Groups: Fix naming and update IDs 2022-10-22 17:49:20 +02:00
Michael Weimann 968f0141cb
Remove moment 2022-10-22 17:22:59 +02:00
Michael Weimann 00eb800f96
Replace moment date format with vanilla JS 2022-10-22 17:22:59 +02:00
Michael Weimann 7049a08bcd
Replace moment-countdown with countdown function 2022-10-22 17:22:53 +02:00
Michael Weimann a81992ca04
Add countdowns to /design 2022-10-22 17:11:55 +02:00
Xu b860b37ba9 add option to hide angeltype at registration 2022-10-21 22:30:17 +02:00
Igor Scheller ff1dfd5a18 Use config for session tests 2022-10-21 19:49:18 +02:00
Xu 2391415969 make session lifetime configurable 2022-10-21 19:42:10 +02:00
Igor Scheller c0a39cb2a1 Migrations: Removed references to models to prevent further migration issues 2022-10-21 16:11:27 +02:00
Igor Scheller 3964982db0 Fixed migrations 2022-10-18 22:22:54 +02:00
Igor Scheller 855d3535db Fixed formatting 2022-10-18 22:08:49 +02:00
Xu f9da096308 add option to show mobile number of user in users view 2022-10-18 22:06:08 +02:00
Xu 4d6da1894a added dect option for rooms 2022-10-18 21:22:37 +02:00
Michael Weimann 88c727bf8e
Manually migrate /includes code to be phpcs compliant 2022-10-18 19:30:43 +02:00
Michael Weimann f7d499b362
Include phpcs for /includes 2022-10-18 19:15:22 +02:00
Igor Scheller 1af185c7ac Updated contributing guidelines 2022-10-14 16:46:03 +02:00
Igor Scheller 7cd4befdfa Refactored shift entry deletion: Use event for notification and worklog creation 2022-10-14 16:27:51 +02:00
Igor Scheller 870a92efd5 Move NightShiftMultiplier calculation to Shifts helper 2022-10-14 16:27:51 +02:00
Igor Scheller 20e389fccd k8s: Use traefik as default ingress, added improved app url handling to support subpath deployments 2022-10-14 13:36:11 +02:00
Igor Scheller f2c9e4a3d6 Change "delete" to "sign off" when removing user from shift 2022-10-01 19:53:44 +02:00
Igor Scheller 2ec61a6db2 Fixed composer.lock hash 2022-10-01 19:41:43 +02:00
dependabot[bot] cb65bcb79c Bump moment-timezone from 0.5.34 to 0.5.35
Bumps [moment-timezone](https://github.com/moment/moment-timezone) from 0.5.34 to 0.5.35.
- [Release notes](https://github.com/moment/moment-timezone/releases)
- [Changelog](https://github.com/moment/moment-timezone/blob/develop/changelog.md)
- [Commits](https://github.com/moment/moment-timezone/compare/0.5.34...0.5.35)

---
updated-dependencies:
- dependency-name: moment-timezone
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-01 19:39:34 +02:00
Igor Scheller 7450fe87d0 Update twig 2022-10-01 19:30:14 +02:00
670 changed files with 20800 additions and 16684 deletions

View File

@ -13,7 +13,7 @@ insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
max_line_length = 120 max_line_length = 120
[{.babelrc,package.json}] [{.babelrc,package.json,.eslintrc.json,.prettierrc.json}]
indent_size = 2 indent_size = 2
[docker/**.conf] [docker/**.conf]

3
.eslintignore Normal file
View File

@ -0,0 +1,3 @@
/public
/node_modules
/vendor

17
.eslintrc.json Normal file
View File

@ -0,0 +1,17 @@
{
"parser": "@babel/eslint-parser",
"extends": [ "plugin:editorconfig/all" ],
"plugins": [ "editorconfig" ],
"rules": {
"prefer-arrow-callback": "error",
"prefer-template": "error",
"no-var": "error",
"quotes": [
"error",
"single",
{
"avoidEscape": true
}
]
}
}

5
.gitignore vendored
View File

@ -26,8 +26,10 @@ _vimrc_local.vim
# Project files # Project files
/config/config.php /config/config.php
/test/coverage /config/lang/
/public/*.xml
/public/coverage /public/coverage
/test/coverage
/coverage /coverage
/unittests.xml /unittests.xml
/resources/lang/*/*.mo /resources/lang/*/*.mo
@ -40,3 +42,4 @@ _vimrc_local.vim
/public/assets /public/assets
/package-lock.json /package-lock.json
/yarn-error.log /yarn-error.log
/.yarn-cache

View File

@ -12,6 +12,7 @@ variables:
DOCROOT: /var/www/ DOCROOT: /var/www/
stages: stages:
- prepare
- validate - validate
- build - build
- test - test
@ -20,44 +21,90 @@ stages:
- deploy-production - deploy-production
- stop - stop
# .use_cache: &use_cache
# Validation cache:
# key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- .yarn-cache/
- vendor/
check-style: # for jobs that depend on composer
image: composer:latest .use_composer: &use_composer
stage: validate <<: *use_cache
needs:
- composer install
before_script: before_script:
- composer --no-ansi global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true - composer install --no-ansi --no-progress
- composer --no-ansi global require slevomat/coding-standard squizlabs/php_codesniffer
- export PATH=$PATH:$COMPOSER_HOME/vendor/bin
script:
- phpcs -p --no-colors --basepath="$PWD"
check-editorconfig: # for jobs that depend on yarn
image: mstruebing/editorconfig-checker .use_yarn: &use_yarn
stage: validate <<: *use_cache
script: needs:
- ec -v - yarn install
before_script:
- yarn install --check-frontend --cache-folder .yarn-cache
validate-composer: #
# Preparation
#
composer validate:
image: composer:latest image: composer:latest
stage: validate stage: prepare
script: script:
- composer --no-ansi validate --strict - composer --no-ansi validate --strict
validate-yarn: composer install:
<<: *use_cache
image: composer:latest
stage: prepare
needs:
- composer audit
- composer validate
script:
- composer install --no-ansi --no-progress
composer audit:
image: php:latest
stage: prepare
needs:
- composer validate
before_script:
- curl -Ls https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64.gz | gzip -d > /bin/symfony
- chmod +x /bin/symfony
script:
- symfony check:security --no-ansi
yarn-validate:
image: node:alpine image: node:alpine
stage: validate stage: prepare
before_script: before_script:
- yarn global add package-json-validator - yarn global add package-json-validator
- export PATH=$PATH:~/.yarn/bin - export PATH=$PATH:~/.yarn/bin
script: script:
- pjv - pjv
yarn install:
<<: *use_cache
image: node:alpine
stage: prepare
needs:
- yarn-validate
- yarn audit
script:
- yarn install --check-frontend --cache-folder .yarn-cache
yarn audit:
image: node:alpine
stage: prepare
needs:
- yarn-validate
script:
- yarn audit
generate-version: generate-version:
image: alpine image: alpine
stage: validate stage: prepare
artifacts: artifacts:
name: "${CI_JOB_NAME}_${CI_JOB_ID}_version" name: "${CI_JOB_NAME}_${CI_JOB_ID}_version"
expire_in: 1 day expire_in: 1 day
@ -70,6 +117,44 @@ generate-version:
- echo "${VERSION}" - echo "${VERSION}"
- echo -n "${VERSION}" > storage/app/VERSION - echo -n "${VERSION}" > storage/app/VERSION
#
# Validation
#
phpcs:
<<: *use_composer
image: composer:latest
stage: validate
script:
# tell phpcs the PHP version to check against
# we are using the min suppported version here
- ./vendor/bin/phpcs --config-set php_version 80100
- ./vendor/bin/phpcs -p --no-colors --basepath="$PWD"
phpstan:
<<: *use_composer
image: composer:latest
stage: validate
script:
- ./vendor/bin/phpstan --no-progress
yarn check:
<<: *use_yarn
image: node:alpine
stage: validate
script:
- yarn check
yarn lint:
<<: *use_yarn
image: node:alpine
stage: validate
script:
# Install git, so that tools can use .gitignore.
# Not done in before_script because of <<: *use_yarn.
- apk add --no-cache git
- yarn lint
# #
# Build # Build
# #
@ -87,39 +172,24 @@ build-image:
<<: *container_definition <<: *container_definition
stage: build stage: build
needs: needs:
- check-editorconfig - phpcs
- check-style - phpstan
- composer validate
- yarn check
- yarn lint
- generate-version - generate-version
- validate-composer
- validate-yarn
dependencies: dependencies:
- generate-version - generate-version
script: script:
- /kaniko/executor --context ${CI_PROJECT_DIR} - /kaniko/executor --context ${CI_PROJECT_DIR}
--dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile --dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile
--destination "${TEST_IMAGE}" --destination "${TEST_IMAGE}"
--cache=true
# #
# Test # Test
# #
audit-composer:
image: php:latest
stage: test
needs: [ ]
before_script:
- curl -Ls https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64.gz | gzip -d > /bin/symfony
- chmod +x /bin/symfony
script:
- symfony check:security --no-ansi
audit-yarn:
image: node:alpine
stage: test
needs: [ ]
script:
- yarn audit
test: test:
image: image:
name: ${TEST_IMAGE} name: ${TEST_IMAGE}
@ -148,7 +218,7 @@ test:
- ./bin/migrate - ./bin/migrate
script: script:
- >- - >-
php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit -vvv --colors=never php -d memory_limit=1024M -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit -vvv --colors=never
--coverage-text --coverage-html "${HOMEDIR}/coverage/" --coverage-text --coverage-html "${HOMEDIR}/coverage/"
--log-junit "${HOMEDIR}/unittests.xml" --log-junit "${HOMEDIR}/unittests.xml"
after_script: after_script:
@ -201,7 +271,11 @@ release-image:
- test - test
dependencies: [ ] dependencies: [ ]
script: script:
- echo -e "FROM ${TEST_IMAGE}" | /kaniko/executor --dockerfile /dev/stdin --destination "${RELEASE_IMAGE}" - echo -e "FROM ${TEST_IMAGE}"
| /kaniko/executor
--dockerfile /dev/stdin
--destination "${RELEASE_IMAGE}"
--cache=true
only: only:
- main - main
@ -218,8 +292,8 @@ build-release-file:
stage: release stage: release
needs: needs:
- build-image - build-image
- audit-yarn - yarn audit
- audit-composer - composer audit
- test - test
- dump-database - dump-database
- generate-assets - generate-assets
@ -274,6 +348,7 @@ deploy:
dependencies: *deploy_needs dependencies: *deploy_needs
environment: environment:
name: rsync-staging name: rsync-staging
deployment_tier: development
only: only:
- main - main
script: script:
@ -296,7 +371,10 @@ deploy:
- test - test
- build-image - build-image
before_script: before_script:
- &kubectl_deployment_script if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi - &kubectl_deployment_script |-
if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi
if [[ -n "${KUBE_CONTEXT}" ]]; then kubectl config use-context "${KUBE_CONTEXT}"; fi
if [[ -z "${KUBE_NAMESPACE}" ]]; then export KUBE_NAMESPACE=${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}; fi
.deploy_k8s: &deploy_k8s .deploy_k8s: &deploy_k8s
<<: *kubectl_deployment <<: *kubectl_deployment
@ -311,8 +389,12 @@ deploy:
# CI_ENVIRONMENT_URL is the URL configured in the GitLab environment # CI_ENVIRONMENT_URL is the URL configured in the GitLab environment
- export CI_ENVIRONMENT_URL="${CI_ENVIRONMENT_URL:-https://${CI_PROJECT_PATH_SLUG}.${KUBE_INGRESS_BASE_DOMAIN}/}" - export CI_ENVIRONMENT_URL="${CI_ENVIRONMENT_URL:-https://${CI_PROJECT_PATH_SLUG}.${KUBE_INGRESS_BASE_DOMAIN}/}"
- export CI_IMAGE=$RELEASE_IMAGE - export CI_IMAGE=$RELEASE_IMAGE
- export CI_INGRESS_CLASS=${CI_INGRESS_CLASS:-traefik}
- export CI_INGRESS_MATCH=${CI_INGRESS_MATCH:-$( if [[ "$CI_INGRESS_CLASS" == "nginx" ]]; then echo '/?(.*)'; fi )}
- export CI_INGRESS_TRAEFIK_ENTRYPOINT=${CI_INGRESS_TRAEFIK_ENTRYPOINT:-websecure}
- export CI_INGRESS_DOMAIN=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?\K([^/]+)' | head -n1) - export CI_INGRESS_DOMAIN=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?\K([^/]+)' | head -n1)
- export CI_INGRESS_PATH=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?(?:[^/])+\K(.*)') - export CI_INGRESS_PATH=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?(?:[^/])+\K(.*)')
- '[[ "${CI_INGRESS_PATH}" == /* ]] || export CI_INGRESS_PATH="/${CI_INGRESS_PATH}"'
- export CI_KUBE_NAMESPACE=$KUBE_NAMESPACE - export CI_KUBE_NAMESPACE=$KUBE_NAMESPACE
# Any available storage class like default, local-path (if you know what you are doing ;), longhorn etc. # Any available storage class like default, local-path (if you know what you are doing ;), longhorn etc.
- export CI_PVC_SC=${CI_PVC_SC:-"${CI_PVC_SC_LOCAL:-local-path}"} - export CI_PVC_SC=${CI_PVC_SC:-"${CI_PVC_SC_LOCAL:-local-path}"}
@ -321,19 +403,24 @@ deploy:
- export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt} - export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt}
- export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD} - export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD}
- echo "Generating config"
- cp deployment.tpl.yaml deployment.yaml - cp deployment.tpl.yaml deployment.yaml
- >- - >-
for env in ${!CI_*}; do for env in ${!CI_*}; do
sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml; sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml;
done done
- echo "Checking namespace ${CI_KUBE_NAMESPACE}"
- kubectl get namespace "${CI_KUBE_NAMESPACE}" > /dev/null 2>&1 || kubectl create namespace "${CI_KUBE_NAMESPACE}"
- echo "Deploying to ${CI_ENVIRONMENT_URL}" - echo "Deploying to ${CI_ENVIRONMENT_URL}"
- kubectl apply -f deployment.yaml - kubectl -n "${CI_KUBE_NAMESPACE}" diff -f deployment.yaml || true
- kubectl -n "${CI_KUBE_NAMESPACE}" apply -f deployment.yaml
- >- - >-
kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m kubectl -n "${CI_KUBE_NAMESPACE}" wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=database -l app=$CI_PROJECT_PATH_SLUG -l tier=database
- >- - >-
kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m kubectl -n "${CI_KUBE_NAMESPACE}" wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=application -l commit=$CI_COMMIT_SHORT_SHA -l app=$CI_PROJECT_PATH_SLUG -l tier=application -l commit=$CI_COMMIT_SHORT_SHA
.deploy_k8s_stop: &deploy_k8s_stop .deploy_k8s_stop: &deploy_k8s_stop
@ -353,6 +440,7 @@ deploy-k8s-review:
on_stop: stop-k8s-review on_stop: stop-k8s-review
auto_stop_in: 1 week auto_stop_in: 1 week
url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG} url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG}
deployment_tier: development
variables: variables:
CI_REPLICAS_REVIEW: 1 CI_REPLICAS_REVIEW: 1
CI_APP_NAME: review/${CI_COMMIT_REF_NAME} CI_APP_NAME: review/${CI_COMMIT_REF_NAME}
@ -366,6 +454,7 @@ stop-k8s-review:
environment: environment:
name: review/${CI_COMMIT_REF_NAME} name: review/${CI_COMMIT_REF_NAME}
action: stop action: stop
deployment_tier: development
# #
# Deploy production # Deploy production
@ -376,8 +465,8 @@ deploy-production:
stage: deploy-production stage: deploy-production
needs: needs:
- test - test
- audit-yarn - yarn audit
- audit-composer - composer audit
- build-image - build-image
- generate-assets - generate-assets
dependencies: dependencies:
@ -385,6 +474,7 @@ deploy-production:
- generate-assets - generate-assets
environment: environment:
name: rsync-production name: rsync-production
deployment_tier: production
when: manual when: manual
only: only:
- main - main
@ -404,8 +494,8 @@ deploy-k8s-production:
stage: deploy-production stage: deploy-production
needs: needs:
- release-image - release-image
- audit-yarn - yarn audit
- audit-composer - composer audit
environment: environment:
name: production name: production
on_stop: stop-k8s-production on_stop: stop-k8s-production

View File

@ -4,9 +4,11 @@
<file>config</file> <file>config</file>
<file>db</file> <file>db</file>
<file>includes</file>
<file>public/index.php</file> <file>public/index.php</file>
<file>src</file> <file>src</file>
<file>tests</file> <file>tests</file>
<exclude-pattern>/config/config.php</exclude-pattern>
<rule ref="PSR12" /> <rule ref="PSR12" />
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses"> <rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
@ -19,4 +21,32 @@
<property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" /> <property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" />
</properties> </properties>
</rule> </rule>
<rule ref="Generic.Files.LineLength.TooLong">
<exclude-pattern>/includes</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.Classes.RequireConstructorPropertyPromotion" />
<rule ref="SlevomatCodingStandard.Commenting.EmptyComment" />
<rule ref="SlevomatCodingStandard.Commenting.UselessFunctionDocComment" />
<rule ref="Generic.Formatting.SpaceAfterCast" />
<rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma"/>
<rule ref="SlevomatCodingStandard.Arrays.SingleLineArrayWhitespace"/>
<rule ref="Squiz.Strings.DoubleQuoteUsage" />
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
<exclude-pattern>/includes</exclude-pattern>
<properties>
<property name="spacesCountAroundEqualsSign" value="0" />
</properties>
</rule>
</ruleset> </ruleset>

5
.prettierrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"printWidth": 120,
"tabWidth": 2,
"singleQuote": true
}

View File

@ -2,12 +2,30 @@
## Coding guide lines ## Coding guide lines
* Make sure your code follows the [PSR-12](https://www.php-fig.org/psr/psr-12/) code style and is [.editorconfig](.editorconfig) valid. * Make sure your code follows the [PSR-12](https://www.php-fig.org/psr/psr-12/) code style and is [.editorconfig](.editorconfig) valid.
You may use `composer run phpcs` and [Editorconfig-Checker](https://editorconfig-checker.github.io) to verify that. You may use `composer run phpcs` and [Editorconfig-Checker](https://editorconfig-checker.github.io) to verify that.
* You should use an [editorconfig plugin for your editor](https://editorconfig.org/#pre-installed) for automatic basic code formatting.
* Use `use` statements wherever possible instead of writing the fully qualified name. * Use `use` statements wherever possible instead of writing the fully qualified name.
* Code must pass PHPStan checks (`composer phpstan`)
* Order the composer/npm dependencies alphabetically. * Order the composer/npm dependencies alphabetically.
* Do not use code from the [includes](./includes) directory anywhere else. * Do not use code from the [includes](includes) directory anywhere else.
* Please cover your code by unit tests. Code under `includes` does not require tests. * Don't refactor [includes](includes) code just for the sake of change, it is legacy code that must only be replaced.
* Please cover your code by unit tests, our goal is to stay at 100% line coverage.
Code under `includes` does not require tests as it's mostly not testable and needs to be rewritten.
* Do not use vendor prefixes like `-webkit` in styles. * Do not use vendor prefixes like `-webkit` in styles.
This is done by PostCSS + Autoprefixer according to the [`.browserslistrc`](./.browserslistrc). This is done by PostCSS + Autoprefixer according to the [`.browserslistrc`](.browserslistrc).
* Translations must be abbreviated, for example `form.save`.
The `default.po` files contain translations that can be auto-detected using Poedit, `additional.po` contains generated messages like validations.
* JavaScript code must pass the checks `yarn lint`.
Auto-fixing is supported via `yarn lint:fix`.
* Don't put function calls in a template-literal (template-strings).
## Pull requests ## Pull requests
Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite. * The PR should contain a short overview of the changes.
* Before implementing bigger changes, please open an issue to discuss the feature and possible implementation options.
* Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite.
* Squash similar commits to make the review easier.
* For visual changes, include both before and after screenshots to easily compare and discuss changes.
## Commits
* The commit message must be meaningful. It should serve as a short overview of the changes.
If needed, an additional description can be provided.
* A commit should be self-contained and result in a working Engelsystem.

View File

@ -8,7 +8,86 @@ Please also read the [CONTRIBUTING.md](CONTRIBUTING.md).
* Yarn (Development/Building only) * Yarn (Development/Building only)
* PHP Composer (Development/Building only) * PHP Composer (Development/Building only)
## Local build ## Code style
Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.org/psr/psr-12/) coding style guide.
You can check that by running
```bash
composer run phpcs
```
You may auto fix reported issues by running
```bash
composer run phpcbf
```
## Pre-commit hooks
You should set up the pre-commit hook to check the code style and run tests on commit:
Docker (recommended):
```sh
echo "docker exec engelsystem_dev-es_workspace-1 bin/pre-commit" > .git/hooks/pre-commit
chmod u+x .git/hooks/pre-commit
```
Host machine:
```sh
ln -s ../../bin/pre-commit .git/hooks/pre-commit
```
## Docker
We suggest using Docker for the Development local build.
If unspecific issues appear try using Docker version >= 20.10.14.
This repo [ships a docker setup](docker/dev) for a quick development start.
If you use another uid/gid than 1000 on your machine you have to adjust it in [docker/dev/.env](docker/dev/.env).
Run this once
```bash
cd docker/dev
docker compose up
```
Run these commands once initially and then as required after changes
```bash
# Install composer dependencies
docker compose exec es_workspace composer i
# Install node packages
docker compose exec es_workspace yarn install
# Run a full front-end build
docker compose exec es_workspace yarn build
# Or run a front-end build for specific themes only, e.g.
docker compose exec -e THEMES=0,1 es_workspace yarn build
# Update the translation files
docker compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
# Run the migrations
docker compose exec es_workspace bin/migrate
```
While developing you may use the watch mode to rebuild the system on changes
```bash
# Run a front-end build and update on change
docker compose exec es_workspace yarn build:watch
# Or run a front-end build and update on change for specific themes only, e.g.
docker compose exec -e THEMES=0,1 es_workspace yarn build:watch
```
## Localhost
You can find your local Engelsystem on [http://localhost:5080](http://localhost:5080).
## Local build without Docker
The following instructions explain how to get, build and run the latest Engelsystem version directly from the git main branch (may be unstable!). The following instructions explain how to get, build and run the latest Engelsystem version directly from the git main branch (may be unstable!).
* Clone the main branch: `git clone https://github.com/engelsystem/engelsystem.git` * Clone the main branch: `git clone https://github.com/engelsystem/engelsystem.git`
@ -39,32 +118,47 @@ The following instructions explain how to get, build and run the latest Engelsys
``` ```
## Testing ## Testing
To run the unit tests use To run only unit tests (tests that should not change the Engelsystem state) use
```bash ```bash
vendor/bin/phpunit --testsuite Unit vendor/bin/phpunit --testsuite Unit
``` ```
If a database is configured and the Engelsystem is allowed to mess around with some files, you can run feature tests. If a database is configured and the Engelsystem is allowed to mess around with some files, you can run feature tests.
The tests can potentially delete some database entries, so they should never be run on a production system! The tests can potentially delete some database entries, so they should never be run on a production system!
```bash ```bash
vendor/bin/phpunit --testsuite Feature vendor/bin/phpunit --testsuite Feature
# or for unit- and feature tests: ```
vendor/bin/phpunit
```
To run code coverage reports its highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or When you want to run unit and feature tests at once:
```bash
vendor/bin/phpunit
```
To generate code coverage reports it's highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or
at least `phpdbg -qrr`(which has problems with switch case statements) as using Xdebug slows down execution. at least `phpdbg -qrr`(which has problems with switch case statements) as using Xdebug slows down execution.
```bash ```bash
php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit --testsuite Unit --coverage-text php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit --coverage-text
``` ```
For better debug output, adding `-vvv` might be helpful.
Adding `--coverage-html public/coverage/` exports the coverage reports to the `public/` dir which then can be viewed at [localhost:5080/coverage/index.html](http://localhost:5080/coverage/index.html).
### Docker
If using the Docker-based development environment you can run the following script to retrieve a coverage report.
```sh
docker compose exec es_workspace composer phpunit:coverage
```
A browsable HTML version is available at http://localhost:5080/coverage/index.html .
### Var Dump server ### Var Dump server
Symfony Var Dump server is configured to allow for easier debugging. It is not meant as a replacement for xdebug but can actually be used together with xdebug. Symfony Var Dump server is configured to allow for easier debugging. It is not meant as a replacement for xdebug but can actually be used together with xdebug.
This Var Dump Server is especially useful for when you want to debug a request without messing up the output e.g API calls ot HTML layout. The Var Dump Server is especially useful if you want to debug a request without messing up the output e.g. of API calls or the HTML layout.
To use simply call the method `dump` and pass the arguments in exactly the same way you would when using `var_dump`. To use simply call the method `dump` and pass the arguments in exactly the same way you would when using `var_dump`.
This will send the output to the Var Dump server which can be viewed in the terminal. This will send the output to the Var Dump server which can be viewed in the terminal.
This does however require that you start the var-dump-server otherwise the output will be printed in your browser This does however require that you start the var-dump-server otherwise the output will be printed in your browser
You can also `dump` and `die` if you wish to not let your code continue any further by calling the `dd` method You can also `dump` and `die` if you wish to not let your code continue any further by calling the `dd` method
@ -74,7 +168,7 @@ To view the output of `dump` call the following commands:
```bash ```bash
vendor/bin/var-dump-server vendor/bin/var-dump-server
# or for running in docker # or for running in docker
docker-compose exec es_server vendor/bin/var-dump-server docker compose exec es_server vendor/bin/var-dump-server
``` ```
For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper) For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper)
@ -83,16 +177,6 @@ For more information check out the Var Dump Server documentation: [Symfony VarDu
We use gettext. You may use POEdit to extract new texts from the sourcecode. We use gettext. You may use POEdit to extract new texts from the sourcecode.
Please config POEdit to extract also the twig template files using the following settings: https://gist.github.com/jlambe/a868d9b63d70902a12254ce47069d0e6 Please config POEdit to extract also the twig template files using the following settings: https://gist.github.com/jlambe/a868d9b63d70902a12254ce47069d0e6
## Code style
Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.org/psr/psr-12/) coding style guide.
You can check that by running
```bash
composer run phpcs
```
You may auto fix reported issues by running
```bash
composer run phpcbf
```
## CI & Build Pipeline ## CI & Build Pipeline
@ -108,51 +192,12 @@ PRODUCTION_REMOTE # Same as STAGING_REMOTE but for the production environm
PRODUCTION_REMOTE_PATH # Same as STAGING_REMOTE_PATH but for the production environment PRODUCTION_REMOTE_PATH # Same as STAGING_REMOTE_PATH but for the production environment
``` ```
## Docker ## Static code analysis
If unspecific issues appear try using Docker version >= 20.10.14. You can run a static code analysis with this command:
This repo [ships a docker setup](docker/dev) for a quick development start.
If you use another uid/gid than 1000 on your machine you have to adjust it in [docker/dev/.env](docker/dev/.env).
Run this once
```bash ```bash
cd docker/dev composer phpstan
docker-compose up
```
Run these commands once initially and then as required after changes
```bash
# Install composer dependencies
docker-compose exec es_workspace composer i
# Install node packages
docker-compose exec es_workspace yarn install
# Run a full front-end build
docker-compose exec es_workspace yarn build
# Or run a front-end build for specific themes only, e.g.
docker-compose exec -e THEMES=0,1 es_workspace yarn build
# Update the translation files
docker-compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
# Run the migrations
docker-compose exec es_workspace bin/migrate
```
While developing you may use the watch mode to rebuild the system on changes
```bash
# Run a front-end build and update on change
docker-compose exec es_workspace yarn build:watch
# Or run a front-end build and update on change for specific themes only, e.g.
docker-compose exec -e THEMES=0,1 es_workspace yarn build:watch
``` ```
**Hint for using Xdebug with *PhpStorm*** **Hint for using Xdebug with *PhpStorm***

View File

@ -15,7 +15,7 @@ Please read the [CONTRIBUTING.md](CONTRIBUTING.md) and [DEVELOPMENT.md](DEVELOPM
The Engelsystem may be installed manually or by using the provided [docker setup](#docker). The Engelsystem may be installed manually or by using the provided [docker setup](#docker).
### Requirements ### Requirements
* PHP >= 7.4 * PHP >= 8.1
* Required modules: * Required modules:
* dom * dom
* json * json
@ -33,16 +33,16 @@ The Engelsystem may be installed manually or by using the provided [docker setup
* Extract the files to your webroot and continue with the directions for configurations and setup. * Extract the files to your webroot and continue with the directions for configurations and setup.
### Configuration and Setup ### Configuration and Setup
* The webserver must have write access to the ```storage``` directory and read access for all other directories * The webserver must have write access to the `storage` directory and read access for all other directories
* The webserver must point to the ```public``` directory. * The webserver must point to the `public` directory.
* The webserver must read the ```.htaccess``` file and ```mod_rewrite``` must be enabled * The webserver must read the `.htaccess` file and `mod_rewrite` must be enabled
* Recommended: Directory Listing should be disabled. * Recommended: Directory Listing should be disabled.
* There must be a MySQL database set up with a user who has full rights to that database. * There must be a MySQL database set up with a user who has full rights to that database.
* If necessary, create a ```config/config.php``` to override values from ```config/config.default.php```. * If necessary, create a `config/config.php` to override values from `config/config.default.php`.
* To edit values from the `footer_items`, `themes`, `locales`, `tshirt_sizes` or `headers` lists, directly modify the ```config/config.default.php``` file or rename it to ```config/config.php```. * To edit values from the `footer_items`, `themes`, `locales`, `tshirt_sizes` or `headers` lists, directly modify the `config/config.default.php` file or rename it to `config/config.php`.
* To import the database, the ```bin/migrate``` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip. * To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
* In the browser, login with credentials ```admin``` : ```asdfasdf``` and change the password. * In the browser, login with credentials `admin` : `asdfasdf` and change the password.
The Engelsystem can now be used. The Engelsystem can now be used.
@ -55,7 +55,7 @@ The Engelsystem can now be used.
To build the `es_server` container: To build the `es_server` container:
```bash ```bash
cd docker cd docker
docker-compose build docker compose build
``` ```
or to build the container by its own: or to build the container by its own:
@ -67,14 +67,14 @@ docker build -f docker/Dockerfile . -t es_server
Start the Engelsystem Start the Engelsystem
```bash ```bash
cd docker cd docker
docker-compose up -d docker compose up -d
``` ```
#### Migrate #### Migrate
Import database changes to migrate it to the newest version Import database changes to migrate it to the newest version
```bash ```bash
cd docker cd docker
docker-compose exec es_server bin/migrate docker compose exec es_server bin/migrate
``` ```
### Scripts ### Scripts

View File

@ -4,7 +4,9 @@
use Composer\Autoload\ClassLoader; use Composer\Autoload\ClassLoader;
use Engelsystem\Application; use Engelsystem\Application;
use Engelsystem\Database\Migration\Migrate; use Engelsystem\Database\Migration\Migrate;
use Engelsystem\Database\Migration\Direction;
use Engelsystem\Database\Migration\MigrationServiceProvider; use Engelsystem\Database\Migration\MigrationServiceProvider;
use Engelsystem\Environment;
use Engelsystem\Exceptions\Handler; use Engelsystem\Exceptions\Handler;
use Engelsystem\Exceptions\Handlers\NullHandler; use Engelsystem\Exceptions\Handlers\NullHandler;
@ -19,7 +21,7 @@ $app->register(MigrationServiceProvider::class);
/** @var Handler $errorHandler */ /** @var Handler $errorHandler */
$errorHandler = $app->get(Handler::class); $errorHandler = $app->get(Handler::class);
$errorHandler->setHandler(Handler::ENV_PRODUCTION, new NullHandler()); $errorHandler->setHandler(Environment::PRODUCTION, new NullHandler());
/** @var Migrate $migration */ /** @var Migrate $migration */
$migration = $app->get('db.migration'); $migration = $app->get('db.migration');
@ -32,10 +34,10 @@ if (in_array('help', $argv) || in_array('--help', $argv) || in_array('-h', $argv
exit; exit;
} }
$method = Migrate::UP; $direction = Direction::UP;
if (in_array('down', $argv)) { if (in_array('down', $argv)) {
$argv = array_values($argv); $argv = array_values($argv);
$method = Migrate::DOWN; $direction = Direction::DOWN;
} }
$oneStep = false; $oneStep = false;
@ -48,4 +50,4 @@ if (in_array('force', $argv) || in_array('--force', $argv) || in_array('-f', $ar
$force = true; $force = true;
} }
$migration->run($baseDir, $method, $oneStep, $force); $migration->run($baseDir, $direction, $oneStep, $force);

12
bin/pre-commit Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env sh
# immediate exit after an error
set -e
yarn check
yarn lint
composer validate
composer phpcs
composer phpstan
./vendor/bin/phpunit

View File

@ -14,47 +14,59 @@
} }
], ],
"scripts": { "scripts": {
"phpcs": "phpcs -p", "phpcs:setup": "phpcs --config-set php_version 80100",
"phpcbf": "phpcbf -p" "phpcs": [
"composer phpcs:setup",
"phpcs -p --cache"
],
"phpcbf": [
"composer phpcs:setup",
"phpcbf -p"
],
"phpstan": "phpstan",
"phpunit": "phpunit",
"phpunit:coverage": "phpunit --coverage-text --coverage-html ./public/coverage/"
}, },
"require": { "require": {
"php": ">=7.4.0", "php": ">=8.1.0",
"ext-json": "*", "ext-json": "*",
"ext-libxml": "*", "ext-libxml": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-xml": "*", "ext-xml": "*",
"doctrine/dbal": "^3.2", "doctrine/dbal": "^3.5",
"erusev/parsedown": "^1.7", "erusev/parsedown": "^1.7",
"gettext/gettext": "^5.6", "gettext/gettext": "^5.7",
"gettext/translator": "^1.0", "gettext/translator": "^1.1",
"guzzlehttp/guzzle": "^7.4", "guzzlehttp/guzzle": "^7.5",
"illuminate/container": "^8.76", "illuminate/container": "^9.43",
"illuminate/database": "^8.76", "illuminate/database": "^9.43",
"illuminate/support": "^8.76", "illuminate/support": "^9.43",
"league/oauth2-client": "^2.6", "league/oauth2-client": "^2.6",
"nikic/fast-route": "^1.3", "nikic/fast-route": "^1.3",
"nyholm/psr7": "^1.4", "nyholm/psr7": "^1.5",
"psr/container": "^1.1", "psr/container": "^2.0",
"psr/http-server-middleware": "^1.0", "psr/http-server-middleware": "^1.0",
"psr/log": "^1.1", "psr/log": "^3.0",
"rcrowe/twigbridge": "^0.14.0", "rcrowe/twigbridge": "^0.14.0",
"respect/validation": "^1.1", "respect/validation": "^1.1",
"symfony/http-foundation": "^5.4", "symfony/http-foundation": "^6.2",
"symfony/mailer": "^5.4", "symfony/mailer": "^6.2",
"symfony/psr-http-message-bridge": "^2.1", "symfony/psr-http-message-bridge": "^2.1",
"twig/twig": "^3.3", "twig/twig": "^3.4",
"vlucas/phpdotenv": "^5.4" "vlucas/phpdotenv": "^5.5"
}, },
"require-dev": { "require-dev": {
"dms/phpunit-arraysubset-asserts": "^0.3.1", "dms/phpunit-arraysubset-asserts": "^0.4",
"fakerphp/faker": "^1.17", "fakerphp/faker": "^1.20",
"fig/log-test": "^1.1",
"filp/whoops": "^2.14", "filp/whoops": "^2.14",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5",
"slevomat/coding-standard": "^7.1", "slevomat/coding-standard": "^8.6",
"squizlabs/php_codesniffer": "^3.6", "squizlabs/php_codesniffer": "^3.7",
"symfony/var-dumper": "^5.4" "symfony/var-dumper": "^6.2"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

2260
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
// Application config // Application config
return [ return [
@ -46,6 +48,7 @@ return [
// Changes of request/response parameters // Changes of request/response parameters
\Engelsystem\Middleware\SetLocale::class, \Engelsystem\Middleware\SetLocale::class,
\Engelsystem\Middleware\ETagHandler::class,
\Engelsystem\Middleware\AddHeaders::class, \Engelsystem\Middleware\AddHeaders::class,
// The application code // The application code
@ -64,11 +67,19 @@ return [
// a list of // a list of
// 'Class@method' or 'Class' (which uses @handle), // 'Class@method' or 'Class' (which uses @handle),
// ['Class', 'method'], // ['Class', 'method'],
// callable like [$instance, 'method] or 'function' // callable like [$instance, 'method'] or 'function'
// or $function // or $function
// ] // ]
'message.created' => \Engelsystem\Events\Listener\Messages::class . '@created',
'news.created' => \Engelsystem\Events\Listener\News::class . '@created', 'news.created' => \Engelsystem\Events\Listener\News::class . '@created',
'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login', 'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login',
'shift.entry.deleting' => [
\Engelsystem\Events\Listener\Shift::class . '@deletedEntryCreateWorklog',
\Engelsystem\Events\Listener\Shift::class . '@deletedEntrySendEmail',
],
], ],
]; ];

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
// To change settings create a config.php // To change settings create a config.php
return [ return [
@ -11,19 +13,19 @@ return [
'password' => env('MYSQL_PASSWORD', ''), 'password' => env('MYSQL_PASSWORD', ''),
], ],
// For accessing stats // For accessing /metrics (and /stats)
'api_key' => '', 'api_key' => env('API_KEY', ''),
// Enable maintenance mode (show a static page) // Enable maintenance mode (show a static page)
'maintenance' => (bool)env('MAINTENANCE', false), 'maintenance' => (bool) env('MAINTENANCE', false),
// Application name (not the event name!) // Application name (not the event name)
'app_name' => env('APP_NAME', 'Engelsystem'), 'app_name' => env('APP_NAME', 'Engelsystem'),
// Set to development to enable debugging messages // Set to development to enable debugging messages
'environment' => env('ENVIRONMENT', 'production'), 'environment' => env('ENVIRONMENT', 'production'),
// Application URL and base path to use instead of the auto detected one // Application URL and base path to use instead of the auto-detected one
'url' => env('APP_URL', null), 'url' => env('APP_URL', null),
// Header links // Header links
@ -45,7 +47,7 @@ return [
'faq_text' => env('FAQ_TEXT', null), 'faq_text' => env('FAQ_TEXT', null),
// Link to documentation/help // Link to documentation/help
'documentation_url' => 'https://engelsystem.de/doc/', 'documentation_url' => env('DOCUMENTATION_URL', 'https://engelsystem.de/doc/'),
// Email config // Email config
'email' => [ 'email' => [
@ -67,7 +69,7 @@ return [
], ],
# Your privacy@ contact address # Your privacy@ contact address
'privacy_email' => '', 'privacy_email' => env('PRIVACY_EMAIL', null),
// Initial admin password // Initial admin password
'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null), 'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null),
@ -88,6 +90,8 @@ return [
'url_token' => '[generated by provider]', 'url_token' => '[generated by provider]',
// User info URL which provides userdata // User info URL which provides userdata
'url_info' => '[generated by provider]', 'url_info' => '[generated by provider]',
// OAuth Scopes
// 'scope' => ['openid'],
// Info unique user id field // Info unique user id field
'id' => 'uuid', 'id' => 'uuid',
// The following fields are used for registration // The following fields are used for registration
@ -214,17 +218,17 @@ return [
// Must be one of news, meetings, user_shifts, angeltypes, questions // Must be one of news, meetings, user_shifts, angeltypes, questions
'home_site' => env('HOME_SITE', 'news'), 'home_site' => env('HOME_SITE', 'news'),
// Number of News shown on one site // Number of News shown on one site and for feed readers (minimum 1)
'display_news' => env('DISPLAY_NEWS', 10), 'display_news' => env('DISPLAY_NEWS', 10),
// Users are able to sign up // Users are able to sign up
'registration_enabled' => (bool)env('REGISTRATION_ENABLED', true), 'registration_enabled' => (bool) env('REGISTRATION_ENABLED', true),
// Only arrived angels can sign up for shifts // Only arrived angels can sign up for shifts
'signup_requires_arrival' => (bool)env('SIGNUP_REQUIRES_ARRIVAL', false), 'signup_requires_arrival' => (bool) env('SIGNUP_REQUIRES_ARRIVAL', false),
// Whether newly-registered user should automatically be marked as arrived // Whether newly-registered user should automatically be marked as arrived
'autoarrive' => (bool)env('ANGEL_AUTOARRIVE', false), 'autoarrive' => (bool) env('ANGEL_AUTOARRIVE', false),
// Only allow shift signup this number of hours in advance // Only allow shift signup this number of hours in advance
// Setting this to 0 disables the feature // Setting this to 0 disables the feature
@ -246,7 +250,7 @@ return [
// Define the algorithm to use for `password_verify()` // Define the algorithm to use for `password_verify()`
// If the user uses an old algorithm the password will be converted to the new format // If the user uses an old algorithm the password will be converted to the new format
// See https://secure.php.net/manual/en/password.constants.php for a complete list // See https://secure.php.net/manual/en/password.constants.php for a complete list
'password_algorithm' => PASSWORD_DEFAULT, 'password_algorithm' => env('PASSWORD_ALGORITHM', PASSWORD_DEFAULT),
// The minimum length for passwords // The minimum length for passwords
'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8), 'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8),
@ -254,38 +258,52 @@ return [
// Whether the Password field should be enabled on registration. // Whether the Password field should be enabled on registration.
// This is useful when using oauth, disabling it also disables normal // This is useful when using oauth, disabling it also disables normal
// registration without oauth. // registration without oauth.
'enable_password' => (bool)env('ENABLE_PASSWORD', true), 'enable_password' => (bool) env('ENABLE_PASSWORD', true),
// Whether the DECT field should be enabled // Whether the DECT field should be enabled
'enable_dect' => (bool)env('ENABLE_DECT', true), 'enable_dect' => (bool) env('ENABLE_DECT', true),
// Enables prename and lastname // Whether the mobile number can be shown to other users
'enable_user_name' => (bool)env('ENABLE_USER_NAME', false), 'enable_mobile_show' => (bool) env('ENABLE_MOBILE_SHOW', false),
// Regular expression describing a FALSE username.
// Per default usernames must only contain alphanumeric chars, "-", "_" or ".".
'username_regex' => (string) env('USERNAME_REGEX', '/([^\p{L}\p{N}\-_.]+)/ui'),
// Enables first name and last name
'enable_user_name' => (bool) env('ENABLE_USER_NAME', false),
// Show a users first name and last name instead of username
'display_full_name' => env('DISPLAY_FULL_NAME', false)
&& env('ENABLE_USER_NAME', false),
// Enable displaying the pronoun fields // Enable displaying the pronoun fields
'enable_pronoun' => (bool)env('ENABLE_PRONOUN', true), 'enable_pronoun' => (bool) env('ENABLE_PRONOUN', true),
// Enables the planned arrival/leave date // Enables the planned arrival/leave date
'enable_planned_arrival' => (bool)env('ENABLE_PLANNED_ARRIVAL', true), 'enable_planned_arrival' => (bool) env('ENABLE_PLANNED_ARRIVAL', true),
// Enables the T-Shirt configuration on signup and profile // Resembles the Goodie Type. There are three options:
'enable_tshirt_size' => (bool)env('ENABLE_TSHIRT_SIZE', true), // 'none' => no goodie at all
// 'goodie' => a goodie which has no sizing options
// Enables the goody configuration on signup and profile // 'tshirt' => goodie that is called tshirt and has sizing options
'enable_goody' => (bool)env('ENABLE_GOODY', false), 'goodie_type' => env('GOODIE_TYPE', 'goodie'),
// Enables the food voucher in the user profile // Enables the food voucher in the user profile
'enable_voucher' => (bool)env('ENABLE_VOUCHER', true), 'enable_voucher' => (bool) env('ENABLE_VOUCHER', true),
// Number of shifts to freeload until angel is locked for shift signup. // Number of shifts to freeload until angel is locked for shift signup.
'max_freeloadable_shifts' => env('MAX_FREELOADABLE_SHIFTS', 2), 'max_freeloadable_shifts' => env('MAX_FREELOADABLE_SHIFTS', 2),
// Hide columns in backend user view. Possible values are any sortable parameters of the table.
'disabled_user_view_columns' => [],
// Local timezone // Local timezone
'timezone' => env('TIMEZONE', ini_get('date.timezone') ?: 'Europe/Berlin'), 'timezone' => env('TIMEZONE', 'Europe/Berlin'),
// Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 6 exclusive) by 2 // Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 6 exclusive) by 2
'night_shifts' => [ 'night_shifts' => [
'enabled' => (bool)env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same 'enabled' => (bool) env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same
'start' => env('NIGHT_SHIFTS_START', 2), 'start' => env('NIGHT_SHIFTS_START', 2),
'end' => env('NIGHT_SHIFTS_END', 6), 'end' => env('NIGHT_SHIFTS_END', 6),
'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2), 'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2),
@ -342,13 +360,16 @@ return [
// Cookie name // Cookie name
'name' => env('SESSION_NAME', 'session'), 'name' => env('SESSION_NAME', 'session'),
// Lifetime in days
'lifetime' => env('SESSION_LIFETIME', 30),
], ],
// IP addresses of reverse proxies that are trusted, can be an array or a comma separated list // IP addresses of reverse proxies that are trusted, can be an array or a comma separated list
'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']), 'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']),
// Add additional headers // Add additional headers
'add_headers' => (bool)env('ADD_HEADERS', true), 'add_headers' => (bool) env('ADD_HEADERS', true),
'headers' => [ 'headers' => [
'X-Content-Type-Options' => 'nosniff', 'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'sameorigin', 'X-Frame-Options' => 'sameorigin',
@ -364,7 +385,7 @@ return [
'credits' => [ 'credits' => [
'Contribution' => 'Please visit [engelsystem/engelsystem](https://github.com/engelsystem/engelsystem) if ' 'Contribution' => 'Please visit [engelsystem/engelsystem](https://github.com/engelsystem/engelsystem) if '
. 'you want to contribute, have found any [bugs](https://github.com/engelsystem/engelsystem/issues) ' . 'you want to contribute, have found any [bugs](https://github.com/engelsystem/engelsystem/issues) '
. 'or need help.' . 'or need help.',
], ],
// var dump server // var dump server

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use FastRoute\RouteCollector; use FastRoute\RouteCollector;
/** @var RouteCollector $route */ /** @var RouteCollector $route */
@ -15,114 +17,195 @@ $route->post('/login', 'AuthController@postLogin');
$route->get('/logout', 'AuthController@logout'); $route->get('/logout', 'AuthController@logout');
// OAuth // OAuth
$route->get('/oauth/{provider}', 'OAuthController@index'); $route->addGroup(
$route->post('/oauth/{provider}/connect', 'OAuthController@connect'); '/oauth/{provider}',
$route->post('/oauth/{provider}/disconnect', 'OAuthController@disconnect'); function (RouteCollector $route): void {
$route->get('', 'OAuthController@index');
$route->post('/connect', 'OAuthController@connect');
$route->post('/disconnect', 'OAuthController@disconnect');
}
);
// User settings // User settings
$route->get('/settings/password', 'SettingsController@password'); $route->addGroup(
$route->post('/settings/password', 'SettingsController@savePassword'); '/settings',
$route->get('/settings/theme', 'SettingsController@theme'); function (RouteCollector $route): void {
$route->post('/settings/theme', 'SettingsController@saveTheme'); $route->get('/profile', 'SettingsController@profile');
$route->get('/settings/language', 'SettingsController@language'); $route->post('/profile', 'SettingsController@saveProfile');
$route->post('/settings/language', 'SettingsController@saveLanguage'); $route->get('/password', 'SettingsController@password');
$route->get('/settings/oauth', 'SettingsController@oauth'); $route->post('/password', 'SettingsController@savePassword');
$route->get('/theme', 'SettingsController@theme');
$route->post('/theme', 'SettingsController@saveTheme');
$route->get('/language', 'SettingsController@language');
$route->post('/language', 'SettingsController@saveLanguage');
$route->get('/oauth', 'SettingsController@oauth');
}
);
// Password recovery // Password recovery
$route->get('/password/reset', 'PasswordResetController@reset'); $route->addGroup(
$route->post('/password/reset', 'PasswordResetController@postReset'); '/password/reset',
$route->get('/password/reset/{token:.+}', 'PasswordResetController@resetPassword'); function (RouteCollector $route): void {
$route->post('/password/reset/{token:.+}', 'PasswordResetController@postResetPassword'); $route->get('', 'PasswordResetController@reset');
$route->post('', 'PasswordResetController@postReset');
$route->get('/{token:.+}', 'PasswordResetController@resetPassword');
$route->post('/{token:.+}', 'PasswordResetController@postResetPassword');
}
);
// Stats // Stats
$route->get('/metrics', 'Metrics\\Controller@metrics'); $route->get('/metrics', 'Metrics\\Controller@metrics');
$route->get('/stats', 'Metrics\\Controller@stats'); $route->get('/stats', 'Metrics\\Controller@stats');
// Angeltypes
$route->addGroup('/angeltypes', function (RouteCollector $route): void {
$route->get('/about', 'AngelTypesController@about');
});
// News // News
$route->get('/news', 'NewsController@index');
$route->get('/meetings', 'NewsController@meetings'); $route->get('/meetings', 'NewsController@meetings');
$route->get('/news/{id:\d+}', 'NewsController@show'); $route->addGroup(
$route->post('/news/{id:\d+}', 'NewsController@comment'); '/news',
$route->post('/news/comment/{id:\d+}', 'NewsController@deleteComment'); function (RouteCollector $route): void {
$route->get('', 'NewsController@index');
$route->get('/{news_id:\d+}', 'NewsController@show');
$route->post('/{news_id:\d+}', 'NewsController@comment');
$route->post('/comment/{comment_id:\d+}', 'NewsController@deleteComment');
}
);
// FAQ // FAQ
$route->get('/faq', 'FaqController@index'); $route->get('/faq', 'FaqController@index');
// Questions // Questions
$route->get('/questions', 'QuestionsController@index'); $route->addGroup(
$route->post('/questions', 'QuestionsController@delete'); '/questions',
$route->get('/questions/new', 'QuestionsController@add'); function (RouteCollector $route): void {
$route->post('/questions/new', 'QuestionsController@save'); $route->get('', 'QuestionsController@index');
$route->post('', 'QuestionsController@delete');
$route->get('/new', 'QuestionsController@add');
$route->post('/new', 'QuestionsController@save');
}
);
// Messages // Messages
$route->get('/messages', 'MessagesController@index'); $route->addGroup(
$route->post('/messages', 'MessagesController@redirectToConversation'); '/messages',
$route->get('/messages/{user_id:\d+}', 'MessagesController@messagesOfConversation'); function (RouteCollector $route): void {
$route->post('/messages/{user_id:\d+}', 'MessagesController@send'); $route->get('', 'MessagesController@index');
$route->post('/messages/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete'); $route->post('', 'MessagesController@redirectToConversation');
$route->get('/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->post('/{user_id:\d+}', 'MessagesController@send');
$route->post('/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
}
);
// API // API
$route->get('/api[/{resource:.+}]', 'ApiController@index'); $route->get('/api[/{resource:.+}]', 'ApiController@index');
// Feeds
$route->get('/atom', 'FeedController@atom');
$route->get('/ical', 'FeedController@ical');
$route->get('/rss', 'FeedController@rss');
$route->get('/shifts-json-export', 'FeedController@shifts');
// Design // Design
$route->get('/design', 'DesignController@index'); $route->get('/design', 'DesignController@index');
// Administration // Administration
$route->addGroup( $route->addGroup(
'/admin', '/admin',
function (RouteCollector $route) { function (RouteCollector $route): void {
// FAQ // FAQ
$route->addGroup( $route->addGroup(
'/faq', '/faq',
function (RouteCollector $route) { function (RouteCollector $route): void {
$route->get('[/{id:\d+}]', 'Admin\\FaqController@edit'); $route->get('[/{faq_id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{id:\d+}]', 'Admin\\FaqController@save'); $route->post('[/{faq_id:\d+}]', 'Admin\\FaqController@save');
} }
); );
// Log // Log
$route->get('/logs', 'Admin\\LogsController@index'); $route->addGroup(
$route->post('/logs', 'Admin\\LogsController@index'); '/logs',
function (RouteCollector $route): void {
$route->get('', 'Admin\\LogsController@index');
$route->post('', 'Admin\\LogsController@index');
}
);
// Schedule // Schedule
$route->addGroup( $route->addGroup(
'/schedule', '/schedule',
function (RouteCollector $route) { function (RouteCollector $route): void {
$route->get('', 'Admin\\Schedule\\ImportSchedule@index'); $route->get('', 'Admin\\Schedule\\ImportSchedule@index');
$route->get('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit'); $route->get('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit');
$route->post('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save'); $route->post('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save');
$route->get('/load/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule'); $route->get('/load/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule');
$route->post('/import/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule'); $route->post('/import/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule');
} }
); );
// Questions // Questions
$route->addGroup( $route->addGroup(
'/questions', '/questions',
function (RouteCollector $route) { function (RouteCollector $route): void {
$route->get('', 'Admin\\QuestionsController@index'); $route->get('', 'Admin\\QuestionsController@index');
$route->post('', 'Admin\\QuestionsController@delete'); $route->post('', 'Admin\\QuestionsController@delete');
$route->get('/{id:\d+}', 'Admin\\QuestionsController@edit'); $route->get('/{question_id:\d+}', 'Admin\\QuestionsController@edit');
$route->post('/{id:\d+}', 'Admin\\QuestionsController@save'); $route->post('/{question_id:\d+}', 'Admin\\QuestionsController@save');
}
);
// Rooms
$route->addGroup(
'/rooms',
function (RouteCollector $route): void {
$route->get('', 'Admin\\RoomsController@index');
$route->post('', 'Admin\\RoomsController@delete');
$route->get('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@edit');
$route->post('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@save');
} }
); );
// User // User
$route->addGroup( $route->addGroup(
'/user/{id:\d+}', '/user/{user_id:\d+}',
// Shirts function (RouteCollector $route): void {
function (RouteCollector $route) { // Shirts
$route->get('/shirt', 'Admin\\UserShirtController@editShirt'); $route->addGroup(
$route->post('/shirt', 'Admin\\UserShirtController@saveShirt'); '/goodie',
function (RouteCollector $route): void {
$route->get('', 'Admin\\UserShirtController@editShirt');
$route->post('', 'Admin\\UserShirtController@saveShirt');
}
);
// Worklogs
$route->addGroup(
'/worklog',
function (RouteCollector $route): void {
$route->get('[/{worklog_id:\d+}]', 'Admin\\UserWorkLogController@editWorklog');
$route->post('[/{worklog_id:\d+}]', 'Admin\\UserWorkLogController@saveWorklog');
$route->get(
'/{worklog_id:\d+}/delete',
'Admin\\UserWorkLogController@showDeleteWorklog'
);
$route->post(
'/{worklog_id:\d+}/delete',
'Admin\\UserWorkLogController@deleteWorklog'
);
}
);
} }
); );
// News // News
$route->addGroup( $route->addGroup(
'/news', '/news',
function (RouteCollector $route) { function (RouteCollector $route): void {
$route->get('[/{id:\d+}]', 'Admin\\NewsController@edit'); $route->get('[/{news_id:\d+}]', 'Admin\\NewsController@edit');
$route->post('[/{id:\d+}]', 'Admin\\NewsController@save'); $route->post('[/{news_id:\d+}]', 'Admin\\NewsController@save');
} }
); );
} }

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\AngelType;
use Illuminate\Database\Eloquent\Factories\Factory;
class AngelTypeFactory extends Factory
{
/** @var string */
protected $model = AngelType::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->firstName(),
'description' => $this->faker->text(),
'contact_name' => $this->faker->firstName(),
'contact_dect' => $this->faker->randomNumber(4),
'contact_email' => $this->faker->email(),
'restricted' => $this->faker->boolean(),
'requires_driver_license' => $this->faker->boolean(),
'no_self_signup' => $this->faker->boolean(),
'show_on_dashboard' => $this->faker->boolean(),
'hide_register' => $this->faker->boolean(),
];
}
}

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Faq; use Engelsystem\Models\Faq;
@ -8,12 +10,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class FaqFactory extends Factory class FaqFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Faq::class; protected $model = Faq::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'question' => $this->faker->text(100), 'question' => $this->faker->text(100),

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Group;
use Illuminate\Database\Eloquent\Factories\Factory;
class GroupFactory extends Factory
{
/** @var string */
protected $model = Group::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->word(),
];
}
}

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Message; use Engelsystem\Models\Message;
@ -9,12 +11,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class MessageFactory extends Factory class MessageFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Message::class; protected $model = Message::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -10,12 +12,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsCommentFactory extends Factory class NewsCommentFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = NewsComment::class; protected $model = NewsComment::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'news_id' => News::factory(), 'news_id' => News::factory(),

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -9,19 +11,17 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsFactory extends Factory class NewsFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = News::class; protected $model = News::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'title' => $this->faker->text(50), 'title' => $this->faker->text(50),
'text' => $this->faker->realText(), 'text' => $this->faker->realText(),
'is_meeting' => $this->faker->boolean(), 'is_meeting' => $this->faker->boolean(),
'is_pinned' => $this->faker->boolean(.1), 'is_pinned' => $this->faker->boolean(.1),
'user_id' => User::factory(), 'is_important' => $this->faker->boolean(.1),
'user_id' => User::factory(),
]; ];
} }
} }

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Privilege;
use Illuminate\Database\Eloquent\Factories\Factory;
class PrivilegeFactory extends Factory
{
/** @var string */
protected $model = Privilege::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->word(),
'description' => $this->faker->text(),
];
}
}

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Carbon\Carbon; use Carbon\Carbon;
@ -10,12 +12,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class QuestionFactory extends Factory class QuestionFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Question::class; protected $model = Question::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Room; use Engelsystem\Models\Room;
@ -8,12 +10,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class RoomFactory extends Factory class RoomFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Room::class; protected $model = Room::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->firstName(), 'name' => $this->faker->unique()->firstName(),

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Factories\Factory;
class NeededAngelTypeFactory extends Factory
{
/** @var string */
protected $model = NeededAngelType::class; // phpcs:ignore
public function definition(): array
{
$forRoom = $this->faker->boolean();
return [
'room_id' => $forRoom ? Room::factory() : null,
'shift_id' => $forRoom ? null : Shift::factory(),
'angel_type_id' => AngelType::factory(),
'count' => $this->faker->numberBetween(1, 5),
];
}
}

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts; namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Shifts\Schedule; use Engelsystem\Models\Shifts\Schedule;
@ -8,15 +10,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class ScheduleFactory extends Factory class ScheduleFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Schedule::class; protected $model = Schedule::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->words(4, true), 'name' => $this->faker->unique()->words(4, true),
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'), 'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
'shift_type' => $this->faker->numberBetween(1, 5), 'shift_type' => $this->faker->numberBetween(1, 5),
'minutes_before' => 15, 'minutes_before' => 15,

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftEntryFactory extends Factory
{
/** @var string */
protected $model = ShiftEntry::class; // phpcs:ignore
public function definition(): array
{
$freeloaded = $this->faker->optional(.01, false)->boolean();
return [
'shift_id' => Shift::factory(),
'angel_type_id' => AngelType::factory(),
'user_id' => User::factory(),
'user_comment' => $this->faker->optional(.05, '')->text(),
'freeloaded' => $freeloaded,
'freeloaded_comment' => $freeloaded ? $this->faker->text() : '',
];
}
}

View File

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftType;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftFactory extends Factory
{
/** @var string */
protected $model = Shift::class; // phpcs:ignore
public function definition(): array
{
$start = $this->faker->dateTimeThisMonth('2 weeks');
return [
'title' => $this->faker->unique()->text(15),
'description' => $this->faker->text(),
'url' => $this->faker->url(),
'start' => $start,
'end' => $this->faker->dateTimeInInterval($start, '+3 hours'),
'shift_type_id' => ShiftType::factory(),
'room_id' => Room::factory(),
'transaction_id' => $this->faker->optional()->uuid(),
'created_by' => User::factory(),
'updated_by' => $this->faker->optional(.3)->boolean() ? User::factory() : null,
];
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Shifts\ShiftType;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftTypeFactory extends Factory
{
/** @var string */
protected $model = ShiftType::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->firstName(),
'description' => $this->faker->text(),
];
}
}

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Contact; use Engelsystem\Models\User\Contact;
@ -8,12 +10,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class ContactFactory extends Factory class ContactFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Contact::class; protected $model = Contact::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'dect' => $this->faker->optional()->numberBetween(1000, 9999), 'dect' => $this->faker->optional()->numberBetween(1000, 9999),

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\License; use Engelsystem\Models\User\License;
@ -8,12 +10,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class LicenseFactory extends Factory class LicenseFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = License::class; protected $model = License::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
$drive_car = $this->faker->boolean(.8); $drive_car = $this->faker->boolean(.8);
$drive_3_5t = $drive_car && $this->faker->boolean(.7); $drive_3_5t = $drive_car && $this->faker->boolean(.7);

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\PasswordReset; use Engelsystem\Models\User\PasswordReset;
@ -8,15 +10,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class PasswordResetFactory extends Factory class PasswordResetFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = PasswordReset::class; protected $model = PasswordReset::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'token' => md5($this->faker->unique()->password()), 'token' => bin2hex(random_bytes(16)),
]; ];
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
@ -9,12 +11,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class PersonalDataFactory extends Factory class PersonalDataFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = PersonalData::class; protected $model = PersonalData::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
$arrival = $this->faker->optional()->dateTimeThisMonth('2 weeks'); $arrival = $this->faker->optional()->dateTimeThisMonth('2 weeks');
$departure = $this->faker->optional()->dateTimeThisMonth('2 weeks'); $departure = $this->faker->optional()->dateTimeThisMonth('2 weeks');

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\Settings;
@ -8,20 +10,19 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class SettingsFactory extends Factory class SettingsFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Settings::class; protected $model = Settings::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'language' => $this->faker->locale(), 'language' => $this->faker->locale(),
'theme' => $this->faker->numberBetween(1, 20), 'theme' => $this->faker->numberBetween(1, 20),
'email_human' => $this->faker->boolean(), 'email_human' => $this->faker->boolean(),
'email_messages' => $this->faker->boolean(),
'email_goody' => $this->faker->boolean(), 'email_goody' => $this->faker->boolean(),
'email_shiftinfo' => $this->faker->boolean(), 'email_shiftinfo' => $this->faker->boolean(),
'email_news' => $this->faker->boolean(), 'email_news' => $this->faker->boolean(),
'mobile_show' => $this->faker->boolean(),
]; ];
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
@ -9,17 +11,14 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class StateFactory extends Factory class StateFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = State::class; protected $model = State::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
$arrival = $this->faker->optional()->dateTimeThisMonth(); $arrival = $this->faker->optional()->dateTimeThisMonth();
return [ return [
'arrived' => (bool)$arrival, 'arrived' => (bool) $arrival,
'arrival_date' => $arrival ? Carbon::instance($arrival) : null, 'arrival_date' => $arrival ? Carbon::instance($arrival) : null,
'active' => $this->faker->boolean(.3), 'active' => $this->faker->boolean(.3),
'force_active' => $this->faker->boolean(.1), 'force_active' => $this->faker->boolean(.1),
@ -30,10 +29,8 @@ class StateFactory extends Factory
/** /**
* Indicate that the user is arrived * Indicate that the user is arrived
*
* @return self
*/ */
public function arrived() public function arrived(): self
{ {
return $this->state( return $this->state(
function (array $attributes) { function (array $attributes) {

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
@ -8,18 +10,15 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory class UserFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = User::class; protected $model = User::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->userName(), 'name' => $this->faker->unique()->userName(),
'password' => password_hash($this->faker->password(), PASSWORD_DEFAULT), 'password' => crypt(random_bytes(16), '$1$salt$'),
'email' => $this->faker->unique()->safeEmail(), 'email' => $this->faker->unique()->safeEmail(),
'api_key' => md5($this->faker->unique()->password()), 'api_key' => bin2hex(random_bytes(32)),
]; ];
} }
} }

View File

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserAngelTypeFactory extends Factory
{
/** @var string */
protected $model = UserAngelType::class; // phpcs:ignore
public function definition(): array
{
return [
'user_id' => User::factory(),
'angel_type_id' => AngelType::factory(),
'confirm_user_id' => $this->faker->optional()->passthrough(User::factory()),
'supporter' => $this->faker->boolean(),
];
}
}

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
@ -9,12 +11,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class WorklogFactory extends Factory class WorklogFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Worklog::class; protected $model = Worklog::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,12 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
class ImportInstallSql extends Migration class ImportInstallSql extends Migration
{ {
protected $oldTables = [ /** @var array<string> */
protected array $oldTables = [
'AngelTypes', 'AngelTypes',
'EventConfig', 'EventConfig',
'GroupPrivileges', 'GroupPrivileges',
@ -31,7 +34,7 @@ class ImportInstallSql extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
foreach ($this->oldTables as $table) { foreach ($this->oldTables as $table) {
if ($this->schema->hasTable($table)) { if ($this->schema->hasTable($table)) {
@ -47,7 +50,7 @@ class ImportInstallSql extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;'); $this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;');

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class ImportUpdateSql extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if ($this->schema->hasTable('UserWorkLog')) { if ($this->schema->hasTable('UserWorkLog')) {
return; return;
@ -22,7 +24,7 @@ class ImportUpdateSql extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->dropIfExists('UserWorkLog'); $this->schema->dropIfExists('UserWorkLog');
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,7 +12,7 @@ class FixOldTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -29,16 +31,9 @@ class FixOldTables extends Migration
->where($column, '<', '0001-01-01 00:00:00') ->where($column, '<', '0001-01-01 00:00:00')
->update([$column => '0001-01-01 00:00:00']); ->update([$column => '0001-01-01 00:00:00']);
$this->schema->table($table, function (Blueprint $table) use ($column) { $this->schema->table($table, function (Blueprint $table) use ($column): void {
$table->dateTime($column)->default('0001-01-01 00:00:00')->change(); $table->dateTime($column)->default('0001-01-01 00:00:00')->change();
}); });
} }
} }
/**
* Reverse the migration
*/
public function down()
{
}
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -43,7 +45,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -7,7 +9,7 @@ use Engelsystem\Database\Migration\Migration;
class AddAngelSupporterPermissions extends Migration class AddAngelSupporterPermissions extends Migration
{ {
/** @var string[] */ /** @var string[] */
protected $data = [ protected array $data = [
'2-Engel', '2-Engel',
'shiftentry_edit_angeltype_supporter', 'shiftentry_edit_angeltype_supporter',
]; ];
@ -15,7 +17,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -39,7 +41,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -52,11 +54,7 @@ class AddAngelSupporterPermissions extends Migration
); );
} }
/** private function getQuery(string $type): string
* @param string $type
* @return string
*/
protected function getQuery($type)
{ {
return sprintf(' return sprintf('
%s FROM GroupPrivileges %s FROM GroupPrivileges

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,9 +12,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->create('log_entries', function (Blueprint $table) { $this->schema->create('log_entries', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');
@ -32,9 +34,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->create('LogEntries', function (Blueprint $table) { $this->schema->create('LogEntries', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,9 +12,9 @@ class CreateSessionsTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->create('sessions', function (Blueprint $table) { $this->schema->create('sessions', function (Blueprint $table): void {
$table->string('id')->unique(); $table->string('id')->unique();
$table->text('payload'); $table->text('payload');
$table->dateTime('last_activity')->useCurrent(); $table->dateTime('last_activity')->useCurrent();
@ -22,7 +24,7 @@ class CreateSessionsTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->dropIfExists('sessions'); $this->schema->dropIfExists('sessions');
} }

View File

@ -1,16 +1,18 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\EventConfig;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;
class CreateEventConfigTable extends Migration class CreateEventConfigTable extends Migration
{ {
protected $mapping = [ protected array $mapping = [
'buildup_start_date' => 'buildup_start', 'buildup_start_date' => 'buildup_start',
'event_start_date' => 'event_start', 'event_start_date' => 'event_start',
'event_end_date' => 'event_end', 'event_end_date' => 'event_end',
@ -20,11 +22,11 @@ class CreateEventConfigTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
foreach (['json', 'text'] as $type) { foreach (['json', 'text'] as $type) {
try { try {
$this->schema->create('event_config', function (Blueprint $table) use ($type) { $this->schema->create('event_config', function (Blueprint $table) use ($type): void {
$table->string('name')->index()->unique(); $table->string('name')->index()->unique();
$table->{$type}('value'); $table->{$type}('value');
$table->timestamps(); $table->timestamps();
@ -41,26 +43,24 @@ class CreateEventConfigTable extends Migration
} }
if ($this->schema->hasTable('EventConfig')) { if ($this->schema->hasTable('EventConfig')) {
$config = $this->schema->getConnection() $connection = $this->schema->getConnection();
$config = $connection
->table('EventConfig') ->table('EventConfig')
->first(); ->first();
if (!empty($config)) { if (!empty($config)) {
(new EventConfig([ $connection->table('event_config')
'name' => 'name', ->insert([
'value' => $config->event_name, ['name' => 'name', 'value' => $config->event_name],
]))->save(); ['name' => 'welcome_msg', 'value' => $config->event_welcome_msg],
]);
(new EventConfig([
'name' => 'welcome_msg',
'value' => $config->event_welcome_msg,
]))->save();
foreach ($this->mapping as $old => $new) { foreach ($this->mapping as $old => $new) {
(new EventConfig([ $connection->table('event_config')
'name' => $new, ->insert([
'value' => (new Carbon())->setTimestamp($config->{$old}), 'name' => $new,
]))->save(); 'value' => (new Carbon())->setTimestamp($config->{$old}),
]);
} }
} }
@ -71,9 +71,11 @@ class CreateEventConfigTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->create('EventConfig', function (Blueprint $table) { $connection = $this->schema->getConnection();
$this->schema->create('EventConfig', function (Blueprint $table): void {
$table->string('event_name')->nullable(); $table->string('event_name')->nullable();
$table->integer('buildup_start_date')->nullable(); $table->integer('buildup_start_date')->nullable();
$table->integer('event_start_date')->nullable(); $table->integer('event_start_date')->nullable();
@ -82,19 +84,19 @@ class CreateEventConfigTable extends Migration
$table->string('event_welcome_msg')->nullable(); $table->string('event_welcome_msg')->nullable();
}); });
$config = new EventConfig(); $config = $connection->table('event_config')->get();
$data = [ $data = [
'event_name' => $config->findOrNew('name')->value, 'event_name' => $this->getConfigValue($config, 'name'),
'event_welcome_msg' => $config->findOrNew('welcome_msg')->value, 'event_welcome_msg' => $this->getConfigValue($config, 'welcome_msg'),
]; ];
foreach ($this->mapping as $new => $old) { foreach ($this->mapping as $new => $old) {
/** @var Carbon $value */ $value = $this->getConfigValue($config, $old);
$value = $config->findOrNew($old)->value;
if (!$value) { if (!$value) {
continue; continue;
} }
$value = Carbon::make($value);
$data[$new] = $value->getTimestamp(); $data[$new] = $value->getTimestamp();
} }
@ -111,4 +113,11 @@ class CreateEventConfigTable extends Migration
$this->schema->dropIfExists('event_config'); $this->schema->dropIfExists('event_config');
} }
private function getConfigValue(Collection $config, string $name): mixed
{
$value = $config->where('name', $name)->first('value', (object) ['value' => null])->value;
return $value ? json_decode($value, true) : null;
}
} }

View File

@ -1,15 +1,11 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\User\Contact;
use Engelsystem\Models\User\PasswordReset;
use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -21,9 +17,9 @@ class CreateUsersTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->create('users', function (Blueprint $table) { $this->schema->create('users', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('name', 24)->unique(); $table->string('name', 24)->unique();
@ -35,7 +31,7 @@ class CreateUsersTables extends Migration
$table->timestamps(); $table->timestamps();
}); });
$this->schema->create('users_personal_data', function (Blueprint $table) { $this->schema->create('users_personal_data', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('first_name', 64)->nullable(); $table->string('first_name', 64)->nullable();
@ -46,7 +42,7 @@ class CreateUsersTables extends Migration
$table->date('planned_departure_date')->nullable(); $table->date('planned_departure_date')->nullable();
}); });
$this->schema->create('users_contact', function (Blueprint $table) { $this->schema->create('users_contact', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('dect', 5)->nullable(); $table->string('dect', 5)->nullable();
@ -54,7 +50,7 @@ class CreateUsersTables extends Migration
$table->string('email', 254)->nullable(); $table->string('email', 254)->nullable();
}); });
$this->schema->create('users_settings', function (Blueprint $table) { $this->schema->create('users_settings', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('language', 64); $table->string('language', 64);
@ -63,7 +59,7 @@ class CreateUsersTables extends Migration
$table->boolean('email_shiftinfo')->default(false); $table->boolean('email_shiftinfo')->default(false);
}); });
$this->schema->create('users_state', function (Blueprint $table) { $this->schema->create('users_state', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('arrived')->default(false); $table->boolean('arrived')->default(false);
@ -74,7 +70,7 @@ class CreateUsersTables extends Migration
$table->integer('got_voucher')->default(0); $table->integer('got_voucher')->default(0);
}); });
$this->schema->create('password_resets', function (Blueprint $table) { $this->schema->create('password_resets', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->text('token'); $table->text('token');
@ -83,33 +79,33 @@ class CreateUsersTables extends Migration
}); });
if ($this->schema->hasTable('User')) { if ($this->schema->hasTable('User')) {
$connection = $this->schema->getConnection();
$emptyDates = ['0000-00-00 00:00:00', '0001-01-01 00:00:00', '1000-01-01 00:00:00']; $emptyDates = ['0000-00-00 00:00:00', '0001-01-01 00:00:00', '1000-01-01 00:00:00'];
/** @var stdClass[] $users */ /** @var stdClass[] $users */
$users = $this->schema->getConnection()->table('User')->get(); $users = $connection->table('User')->get();
foreach ($users as $data) { foreach ($users as $data) {
$user = new User([ $user = [
'id' => $data->UID,
'name' => $data->Nick, 'name' => $data->Nick,
'password' => $data->Passwort, 'password' => $data->Passwort,
'email' => $data->email, 'email' => $data->email,
'api_key' => $data->api_key, 'api_key' => $data->api_key,
'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null, 'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null,
]); ];
$user->setAttribute('id', $data->UID);
if (!in_array($data->CreateDate, $emptyDates)) { if (!in_array($data->CreateDate, $emptyDates)) {
$user->setAttribute('created_at', new Carbon($data->CreateDate)); $user['created_at'] = new Carbon($data->CreateDate);
} }
$user->save(); $connection->table('users')->insert($user);
$contact = new Contact([ $connection->table('users_contact')->insert([
'dect' => $data->DECT ? $data->DECT : null, 'user_id' => $data->UID,
'mobile' => $data->Handy ?: ($data->Telefon ?: null), 'dect' => $data->DECT ?: null,
'mobile' => $data->Handy ?: ($data->Telefon ?: null),
]); ]);
$contact->user()
->associate($user)
->save();
$personalData = new PersonalData([ $connection->table('users_personal_data')->insert([
'user_id' => $data->UID,
'first_name' => $data->Vorname ?: null, 'first_name' => $data->Vorname ?: null,
'last_name' => $data->Name ?: null, 'last_name' => $data->Name ?: null,
'shirt_size' => $data->Size ?: null, 'shirt_size' => $data->Size ?: null,
@ -120,24 +116,17 @@ class CreateUsersTables extends Migration
? Carbon::createFromTimestamp($data->planned_departure_date) ? Carbon::createFromTimestamp($data->planned_departure_date)
: null, : null,
]); ]);
$personalData->user()
->associate($user)
->save();
$settings = new Settings([ $connection->table('users_settings')->insert([
'user_id' => $data->UID,
'language' => $data->Sprache, 'language' => $data->Sprache,
'theme' => $data->color, 'theme' => $data->color,
'email_human' => $data->email_by_human_allowed, 'email_human' => $data->email_by_human_allowed,
'email_shiftinfo' => $data->email_shiftinfo, 'email_shiftinfo' => $data->email_shiftinfo,
]); ]);
unset($settings->email_news);
unset($settings->email_goody);
$settings->user() $connection->table('users_state')->insert([
->associate($user) 'user_id' => $data->UID,
->save();
$state = new State([
'arrived' => $data->Gekommen, 'arrived' => $data->Gekommen,
'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null, 'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null,
'active' => $data->Aktiv, 'active' => $data->Aktiv,
@ -145,17 +134,12 @@ class CreateUsersTables extends Migration
'got_shirt' => $data->Tshirt, 'got_shirt' => $data->Tshirt,
'got_voucher' => $data->got_voucher, 'got_voucher' => $data->got_voucher,
]); ]);
$state->user()
->associate($user)
->save();
if ($data->password_recovery_token) { if ($data->password_recovery_token) {
$passwordReset = new PasswordReset([ $connection->table('password_resets')->insert([
'token' => $data->password_recovery_token, 'user_id' => $data->UID,
'token' => $data->password_recovery_token,
]); ]);
$passwordReset->user()
->associate($user)
->save();
} }
} }
@ -173,10 +157,12 @@ class CreateUsersTables extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->create('User', function (Blueprint $table) { $connection = $this->schema->getConnection();
$table->integer('UID', true, false);
$this->schema->create('User', function (Blueprint $table): void {
$table->integer('UID', true);
$table->string('Nick', 23)->unique()->default(''); $table->string('Nick', 23)->unique()->default('');
$table->string('Name', 23)->nullable(); $table->string('Name', 23)->nullable();
@ -217,12 +203,16 @@ class CreateUsersTables extends Migration
$table->index('planned_departure_date', 'planned_departure_date'); $table->index('planned_departure_date', 'planned_departure_date');
}); });
foreach (User::all() as $user) { foreach ($connection->table('users')->get() as $user) {
/** @var User $user */ /** @var stdClass $user */
$contact = $user->contact; /** @var stdClass $contact */
$personal = $user->personalData; $contact = $connection->table('users_contact')->where('user_id', $user->id)->first();
$settings = $user->settings; /** @var stdClass $personal */
$state = $user->state; $personal = $connection->table('users_personal_data')->where('user_id', $user->id)->first();
/** @var stdClass $settings */
$settings = $connection->table('users_settings')->where('user_id', $user->id)->first();
/** @var stdClass $state */
$state = $connection->table('users_state')->where('user_id', $user->id)->first();
$this->schema $this->schema
->getConnection() ->getConnection()
@ -244,23 +234,28 @@ class CreateUsersTables extends Migration
'Tshirt' => $state->got_shirt, 'Tshirt' => $state->got_shirt,
'color' => $settings->theme, 'color' => $settings->theme,
'Sprache' => $settings->language, 'Sprache' => $settings->language,
'lastLogIn' => $user->last_login_at ? $user->last_login_at->getTimestamp() : null, 'lastLogIn' => $user->last_login_at
'CreateDate' => $user->created_at ? $user->created_at->toDateTimeString() : null, ? Carbon::make($user->last_login_at)->getTimestamp()
: null,
'CreateDate' => $user->created_at
? Carbon::make($user->created_at)->toDateTimeString()
: '0001-01-01 00:00:00',
'api_key' => $user->api_key, 'api_key' => $user->api_key,
'got_voucher' => $state->got_voucher, 'got_voucher' => $state->got_voucher,
'arrival_date' => $state->arrival_date ? $state->arrival_date->getTimestamp() : null, 'arrival_date' => $state->arrival_date
'planned_arrival_date' => $personal->planned_arrival_date ? Carbon::make($state->arrival_date)->getTimestamp()
? $personal->planned_arrival_date->getTimestamp()
: null, : null,
'planned_arrival_date' => $personal->planned_arrival_date
? Carbon::make($personal->planned_arrival_date)->getTimestamp()
: 0,
'planned_departure_date' => $personal->planned_departure_date 'planned_departure_date' => $personal->planned_departure_date
? $personal->planned_departure_date->getTimestamp() ? Carbon::make($personal->planned_departure_date)->getTimestamp()
: null, : null,
'email_by_human_allowed' => $settings->email_human, 'email_by_human_allowed' => $settings->email_human,
]); ]);
} }
foreach (PasswordReset::all() as $passwordReset) { foreach ($connection->table('password_resets')->get() as $passwordReset) {
/** @var PasswordReset $passwordReset */
$this->schema->getConnection() $this->schema->getConnection()
->table('User') ->table('User')
->where('UID', '=', $passwordReset->user_id) ->where('UID', '=', $passwordReset->user_id)

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -8,7 +10,7 @@ use Illuminate\Database\Schema\Blueprint;
class ChangeUsersContactDectFieldSize extends Migration class ChangeUsersContactDectFieldSize extends Migration
{ {
/** @var array */ /** @var array */
protected $tables = [ protected array $tables = [
'AngelTypes' => 'contact_dect', 'AngelTypes' => 'contact_dect',
'users_contact' => 'dect', 'users_contact' => 'dect',
]; ];
@ -16,7 +18,7 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->changeDectTo(40); $this->changeDectTo(40);
} }
@ -24,22 +26,19 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->changeDectTo(5); $this->changeDectTo(5);
} }
/** private function changeDectTo(int $length): void
* @param int $length
*/
protected function changeDectTo(int $length)
{ {
foreach ($this->tables as $table => $column) { foreach ($this->tables as $table => $column) {
if (!$this->schema->hasTable($table)) { if (!$this->schema->hasTable($table)) {
continue; continue;
} }
$this->schema->table($table, function (Blueprint $table) use ($column, $length) { $this->schema->table($table, function (Blueprint $table) use ($column, $length): void {
$table->string($column, $length)->change(); $table->string($column, $length)->change();
}); });
} }

View File

@ -1,28 +1,37 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\User\State; use stdClass;
class FixMissingArrivalDates extends Migration class FixMissingArrivalDates extends Migration
{ {
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$states = State::whereArrived(true)->whereArrivalDate(null)->get(); $connection = $this->schema->getConnection();
/** @var stdClass[] $states */
$states = $connection
->table('users_state')
->where('arrived', true)
->where('arrival_date', null)
->get();
foreach ($states as $state) { foreach ($states as $state) {
$state->arrival_date = $state->user->personalData->planned_arrival_date; /** @var stdClass $personalData */
$state->save(); $personalData = $connection
->table('users_personal_data')
->where('user_id', $state->user_id)
->first();
$state->arrival_date = $personalData->planned_arrival_date;
$connection->table('users_state')
->update((array) $state);
} }
} }
/**
* Down is not possible and not needed since this is a bugfix.
*/
public function down()
{
}
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,26 +11,26 @@ class FixUserLanguages extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update([ ->update([
'language' => $connection->raw('REPLACE(language, ".UTF-8", "")') 'language' => $connection->raw('REPLACE(language, ".UTF-8", "")'),
]); ]);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update([ ->update([
'language' => $connection->raw('CONCAT(language, ".UTF-8")') 'language' => $connection->raw('CONCAT(language, ".UTF-8")'),
]); ]);
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;
@ -29,7 +31,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,76 +14,55 @@ class CreateScheduleShiftTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->create( $this->schema->create('schedules', function (Blueprint $table): void {
'schedules', $table->increments('id');
function (Blueprint $table) { $table->string('url');
$table->increments('id'); });
$table->string('url');
}
);
$this->schema->create( $this->schema->create('schedule_shift', function (Blueprint $table): void {
'schedule_shift', $table->integer('shift_id')->index()->unique();
function (Blueprint $table) { if ($this->schema->hasTable('Shifts')) {
$table->integer('shift_id')->index()->unique(); // Legacy table access
if ($this->schema->hasTable('Shifts')) { $table->foreign('shift_id')
// Legacy table access ->references('SID')->on('Shifts')
$table->foreign('shift_id') ->onUpdate('cascade')
->references('SID')->on('Shifts') ->onDelete('cascade');
->onUpdate('cascade')
->onDelete('cascade');
}
$this->references($table, 'schedules');
$table->uuid('guid');
} }
);
$this->references($table, 'schedules');
$table->uuid('guid');
});
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
$this->schema->table( $this->schema->table('Shifts', function (Blueprint $table): void {
'Shifts', $table->dropColumn('PSID');
function (Blueprint $table) { });
$table->dropColumn('PSID');
}
);
} }
if ($this->schema->hasTable('Room')) { if ($this->schema->hasTable('Room')) {
$this->schema->table( $this->schema->table('Room', function (Blueprint $table): void {
'Room', $table->dropColumn('from_frab');
function (Blueprint $table) { });
$table->dropColumn('from_frab');
}
);
} }
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if ($this->schema->hasTable('Room')) { if ($this->schema->hasTable('Room')) {
$this->schema->table( $this->schema->table('Room', function (Blueprint $table): void {
'Room', $table->boolean('from_frab')->default(false);
function (Blueprint $table) { });
$table->boolean('from_frab')
->default(false);
}
);
} }
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
$this->schema->table( $this->schema->table('Shifts', function (Blueprint $table): void {
'Shifts', $table->integer('PSID')->nullable()->default(null)->unique();
function (Blueprint $table) { });
$table->integer('PSID')
->nullable()->default(null)
->unique();
}
);
} }
$this->schema->drop('schedule_shift'); $this->schema->drop('schedule_shift');

View File

@ -64,12 +64,9 @@ class CreateNewsTable extends Migration
$this->schema->drop('new_news'); $this->schema->drop('new_news');
} }
/**
* @return void
*/
private function createNewNewsTable(): void private function createNewNewsTable(): void
{ {
$this->schema->create('news', function (Blueprint $table) { $this->schema->create('news', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('title', 150); $table->string('title', 150);
$table->text('text'); $table->text('text');
@ -79,9 +76,6 @@ class CreateNewsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsTable(): void private function copyPreviousToNewNewsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -104,25 +98,18 @@ class CreateNewsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsTable(): void private function createPreviousNewsTable(): void
{ {
$this->schema->create('News', function (Blueprint $table) { $this->schema->create('News', function (Blueprint $table): void {
$table->increments('ID'); $table->increments('ID');
$table->integer('Datum'); $table->integer('Datum');
$table->string('Betreff', 150) $table->string('Betreff', 150)->default('');
->default('');
$table->text('Text'); $table->text('Text');
$this->references($table, 'users', 'UID'); $this->references($table, 'users', 'UID');
$table->boolean('Treffen')->default(false); $table->boolean('Treffen')->default(false);
}); });
} }
/**
* @return void
*/
private function copyNewToPreviousNewsTable(): void private function copyNewToPreviousNewsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -53,12 +53,9 @@ class CreateNewsCommentsTable extends Migration
$this->schema->drop('news_comments'); $this->schema->drop('news_comments');
} }
/**
* @return void
*/
private function createNewNewsCommentsTable(): void private function createNewNewsCommentsTable(): void
{ {
$this->schema->create('news_comments', function (Blueprint $table) { $this->schema->create('news_comments', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->references($table, 'news', 'news_id'); $this->references($table, 'news', 'news_id');
$table->text('text'); $table->text('text');
@ -67,9 +64,6 @@ class CreateNewsCommentsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsCommentsTable(): void private function copyPreviousToNewNewsCommentsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -90,12 +84,9 @@ class CreateNewsCommentsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsCommentsTable(): void private function createPreviousNewsCommentsTable(): void
{ {
$this->schema->create('NewsComments', function (Blueprint $table) { $this->schema->create('NewsComments', function (Blueprint $table): void {
$table->increments('ID'); $table->increments('ID');
$this->references($table, 'news', 'Refid'); $this->references($table, 'news', 'Refid');
$table->dateTime('Datum'); $table->dateTime('Datum');
@ -104,9 +95,6 @@ class CreateNewsCommentsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyNewToPreviousNewsCommentsTable(): void private function copyNewToPreviousNewsCommentsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -64,27 +64,18 @@ class CreateMessagesTable extends Migration
$this->schema->drop('new_messages'); $this->schema->drop('new_messages');
} }
/**
* @return void
*/
private function createNewMessagesTable(): void private function createNewMessagesTable(): void
{ {
$this->schema->create( $this->schema->create('messages', function (Blueprint $table): void {
'messages', $table->increments('id');
function (Blueprint $table) { $this->referencesUser($table);
$table->increments('id'); $this->references($table, 'users', 'receiver_id');
$this->referencesUser($table); $table->boolean('read')->default(0);
$this->references($table, 'users', 'receiver_id'); $table->text('text');
$table->boolean('read')->default(0); $table->timestamps();
$table->text('text'); });
$table->timestamps();
}
);
} }
/**
* @return void
*/
private function copyPreviousToNewMessagesTable(): void private function copyPreviousToNewMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -109,28 +100,18 @@ class CreateMessagesTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousMessagesTable(): void private function createPreviousMessagesTable(): void
{ {
$this->schema->create( $this->schema->create('Messages', function (Blueprint $table): void {
'Messages', $table->increments('id');
function (Blueprint $table) { $table->integer('Datum');
$table->increments('id'); $this->references($table, 'users', 'SUID');
$table->integer('Datum'); $this->references($table, 'users', 'RUID');
$this->references($table, 'users', 'SUID'); $table->char('isRead')->default('N');
$this->references($table, 'users', 'RUID'); $table->text('Text');
$table->char('isRead') });
->default('N');
$table->text('Text');
}
);
} }
/**
* @return void
*/
private function copyNewToPreviousMessagesTable(): void private function copyNewToPreviousMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -17,9 +17,6 @@ class CreateQuestionsTable extends Migration
use ChangesReferences; use ChangesReferences;
use Reference; use Reference;
/**
* @return void
*/
public function up(): void public function up(): void
{ {
$hasPreviousQuestionsTable = $this->schema->hasTable('Questions'); $hasPreviousQuestionsTable = $this->schema->hasTable('Questions');
@ -43,9 +40,6 @@ class CreateQuestionsTable extends Migration
} }
} }
/**
* @return void
*/
public function down(): void public function down(): void
{ {
// Rename as some SQL DBMS handle identifiers case insensitive // Rename as some SQL DBMS handle identifiers case insensitive
@ -63,28 +57,17 @@ class CreateQuestionsTable extends Migration
$this->schema->drop('new_questions'); $this->schema->drop('new_questions');
} }
/**
* @return void
*/
private function createNewQuestionsTable(): void private function createNewQuestionsTable(): void
{ {
$this->schema->create( $this->schema->create('questions', function (Blueprint $table): void {
'questions', $table->increments('id');
function (Blueprint $table) { $this->referencesUser($table);
$table->increments('id'); $table->text('text');
$this->referencesUser($table); $table->text('answer')->nullable();
$table->text('text'); $this->references($table, 'users', 'answerer_id')->nullable();
$table->text('answer') });
->nullable();
$this->references($table, 'users', 'answerer_id')
->nullable();
}
);
} }
/**
* @return void
*/
private function copyPreviousToNewQuestionsTable(): void private function copyPreviousToNewQuestionsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -104,28 +87,17 @@ class CreateQuestionsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousQuestionsTable(): void private function createPreviousQuestionsTable(): void
{ {
$this->schema->create( $this->schema->create('Questions', function (Blueprint $table): void {
'Questions', $table->increments('QID');
function (Blueprint $table) { $this->references($table, 'users', 'UID');
$table->increments('QID'); $table->text('Question');
$this->references($table, 'users', 'UID'); $this->references($table, 'users', 'AID')->nullable();
$table->text('Question'); $table->text('Answer')->nullable();
$this->references($table, 'users', 'AID') });
->nullable();
$table->text('Answer')
->nullable();
}
);
} }
/**
* @return void
*/
private function copyNewToPreviousQuestionsTable(): void private function copyNewToPreviousQuestionsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -14,11 +14,8 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table) { $this->schema->table('users_personal_data', function (Blueprint $table): void {
$table->string('pronoun', 15) $table->string('pronoun', 15)->nullable()->default(null)->after('last_name');
->nullable()
->default(null)
->after('last_name');
}); });
} }
@ -27,7 +24,7 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table) { $this->schema->table('users_personal_data', function (Blueprint $table): void {
$table->dropColumn('pronoun'); $table->dropColumn('pronoun');
}); });
} }

View File

@ -28,11 +28,5 @@ class ChangeMysqlDatabaseEncodingToUtf8mb4 extends Migration
} }
} }
/** // As utf8mb4 is a superset of utf8, there is nothing to do in the downgrade
* Reverse the migration
*/
public function down(): void
{
// As utf8mb4 is a superset of utf8, there is nothing to do here
}
} }

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Room;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -19,7 +18,7 @@ class CreateRoomsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('rooms', function (Blueprint $table) { $this->schema->create('rooms', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('name', 35)->unique(); $table->string('name', 35)->unique();
$table->string('map_url', 300)->nullable(); $table->string('map_url', 300)->nullable();
@ -35,13 +34,13 @@ class CreateRoomsTable extends Migration
->get(); ->get();
foreach ($previousRecords as $previousRecord) { foreach ($previousRecords as $previousRecord) {
$room = new Room([ $connection->table('rooms')
'name' => $previousRecord->Name, ->insert([
'map_url' => $previousRecord->map_url ?: null, 'id' => $previousRecord->RID,
'description' => $previousRecord->description ?: null, 'name' => $previousRecord->Name,
]); 'map_url' => $previousRecord->map_url ?: null,
$room->setAttribute('id', $previousRecord->RID); 'description' => $previousRecord->description ?: null,
$room->save(); ]);
} }
$this->changeReferences( $this->changeReferences(
@ -60,16 +59,18 @@ class CreateRoomsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->create('Room', function (Blueprint $table) { $connection = $this->schema->getConnection();
$this->schema->create('Room', function (Blueprint $table): void {
$table->increments('RID'); $table->increments('RID');
$table->string('Name', 35)->unique(); $table->string('Name', 35)->unique();
$table->string('map_url', 300)->nullable(); $table->string('map_url', 300)->nullable();
$table->mediumText('description')->nullable(); $table->mediumText('description')->nullable();
}); });
foreach (Room::all() as $room) { foreach ($connection->table('rooms')->get() as $room) {
$this->schema /** @var stdClass $room */
->getConnection() $connection
->table('Room') ->table('Room')
->insert([ ->insert([
'RID' => $room->id, 'RID' => $room->id,

View File

@ -6,7 +6,6 @@ namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -20,7 +19,7 @@ class CreateWorklogsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('worklogs', function (Blueprint $table) { $this->schema->create('worklogs', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$this->references($table, 'users', 'creator_id'); $this->references($table, 'users', 'creator_id');
@ -38,18 +37,19 @@ class CreateWorklogsTable extends Migration
->get(); ->get();
foreach ($previousRecords as $previousRecord) { foreach ($previousRecords as $previousRecord) {
$room = new Worklog([
'user_id' => $previousRecord->user_id,
'creator_id' => $previousRecord->created_user_id,
'worked_at' => $previousRecord->work_timestamp,
'hours' => $previousRecord->work_hours,
'comment' => $previousRecord->comment,
]);
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp); $created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
$room->setAttribute('id', $previousRecord->id); $this->schema->getConnection()
$room->setAttribute('created_at', $created_at); ->table('worklogs')
$room->setAttribute('updated_at', $created_at); ->insert([
$room->save(); 'id' => $previousRecord->id,
'user_id' => $previousRecord->user_id,
'creator_id' => $previousRecord->created_user_id,
'worked_at' => $previousRecord->work_timestamp,
'hours' => $previousRecord->work_hours,
'comment' => $previousRecord->comment,
'created_at' => $created_at,
'updated_at' => $created_at,
]);
} }
$this->changeReferences( $this->changeReferences(
@ -68,7 +68,9 @@ class CreateWorklogsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->create('UserWorkLog', function (Blueprint $table) { $connection = $this->schema->getConnection();
$this->schema->create('UserWorkLog', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->integer('work_timestamp'); $table->integer('work_timestamp');
@ -78,10 +80,9 @@ class CreateWorklogsTable extends Migration
$table->integer('created_timestamp')->index(); $table->integer('created_timestamp')->index();
}); });
foreach (Worklog::all() as $record) { foreach ($connection->table('worklogs')->get() as $record) {
/** @var Worklog $record */ /** @var stdClass $record */
$this->schema $connection
->getConnection()
->table('UserWorkLog') ->table('UserWorkLog')
->insert([ ->insert([
'id' => $record->id, 'id' => $record->id,

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('Groups')) { if (!$this->schema->hasTable('Groups')) {
return; return;
@ -38,7 +40,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('Groups')) { if (!$this->schema->hasTable('Groups')) {
return; return;

View File

@ -1,10 +1,11 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Question;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
class AddTimestampsToQuestions extends Migration class AddTimestampsToQuestions extends Migration
@ -16,17 +17,20 @@ class AddTimestampsToQuestions extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->table('questions', function (Blueprint $table) { $connection = $this->schema->getConnection();
$now = Carbon::now();
$this->schema->table('questions', function (Blueprint $table): void {
$table->timestamp('answered_at')->after('answerer_id')->nullable(); $table->timestamp('answered_at')->after('answerer_id')->nullable();
$table->timestamps(); $table->timestamps();
}); });
$now = Carbon::now(); $connection->table('questions')
Question::query()->update([ ->update([
'created_at' => $now, 'created_at' => $now,
'updated_at' => $now, 'updated_at' => $now,
]); ]);
Question::query() $connection->table('questions')
->whereNotNull('answerer_id') ->whereNotNull('answerer_id')
->update([ ->update([
'answered_at' => $now, 'answered_at' => $now,
@ -38,7 +42,7 @@ class AddTimestampsToQuestions extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('questions', function (Blueprint $table) { $this->schema->table('questions', function (Blueprint $table): void {
$table->dropColumn('answered_at'); $table->dropColumn('answered_at');
$table->dropTimestamps(); $table->dropTimestamps();
}); });

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,9 +12,9 @@ class CreateFaqTableAndPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->create('faq', function (Blueprint $table) { $this->schema->create('faq', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('question'); $table->string('question');
$table->text('text'); $table->text('text');
@ -46,7 +48,7 @@ class CreateFaqTableAndPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->drop('faq'); $this->schema->drop('faq');

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if ($this->schema->hasTable('Privileges')) { if ($this->schema->hasTable('Privileges')) {
$db = $this->schema->getConnection(); $db = $this->schema->getConnection();
@ -36,7 +38,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -16,7 +16,7 @@ class CreateOauthTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('oauth', function (Blueprint $table) { $this->schema->create('oauth', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->string('provider'); $table->string('provider');

View File

@ -1,10 +1,11 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Shifts\Schedule;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
class AddNameMinutesAndTimestampsToSchedules extends Migration class AddNameMinutesAndTimestampsToSchedules extends Migration
@ -14,39 +15,34 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table( $connection = $this->schema->getConnection();
'schedules',
function (Blueprint $table) {
$table->string('name')->default('')->after('id');
$table->integer('shift_type')->default(0)->after('name');
$table->integer('minutes_before')->default(0)->after('shift_type');
$table->integer('minutes_after')->default(0)->after('minutes_before');
$table->timestamps();
}
);
Schedule::query() $this->schema->table('schedules', function (Blueprint $table): void {
$table->string('name')->default('')->after('id');
$table->integer('shift_type')->default(0)->after('name');
$table->integer('minutes_before')->default(0)->after('shift_type');
$table->integer('minutes_after')->default(0)->after('minutes_before');
$table->timestamps();
});
$connection->table('schedules')
->update([ ->update([
'created_at' => Carbon::now(), 'created_at' => Carbon::now(),
'minutes_before' => 15, 'minutes_before' => 15,
'minutes_after' => 15, 'minutes_after' => 15,
]); ]);
$this->schema->table( $this->schema->table('schedules', function (Blueprint $table): void {
'schedules', $table->string('name')->default(null)->change();
function (Blueprint $table) { $table->integer('shift_type')->default(null)->change();
$table->string('name')->default(null)->change(); $table->integer('minutes_before')->default(null)->change();
$table->integer('shift_type')->default(null)->change(); $table->integer('minutes_after')->default(null)->change();
$table->integer('minutes_before')->default(null)->change(); });
$table->integer('minutes_after')->default(null)->change();
}
);
// Add legacy reference // Add legacy reference
if ($this->schema->hasTable('ShiftTypes')) { if ($this->schema->hasTable('ShiftTypes')) {
$connection = $this->schema->getConnection();
$query = $connection $query = $connection
->table('Shifts') ->table('Shifts')
->select('Shifts.shifttype_id') ->select('Shifts.shifttype_id')
@ -54,33 +50,29 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
->where('schedule_shift.schedule_id', $connection->raw('schedules.id')) ->where('schedule_shift.schedule_id', $connection->raw('schedules.id'))
->limit(1); ->limit(1);
Schedule::query() $connection->table('schedules')
->update(['shift_type' => $connection->raw('(' . $query->toSql() . ')')]); ->update([
'shift_type' => $connection->raw('(' . $query->toSql() . ')'),
]);
$this->schema->table( $this->schema->table('schedules', function (Blueprint $table): void {
'schedules', $this->addReference($table, 'shift_type', 'ShiftTypes');
function (Blueprint $table) { });
$this->addReference($table, 'shift_type', 'ShiftTypes');
}
);
} }
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table( $this->schema->table('schedules', function (Blueprint $table): void {
'schedules', $table->dropForeign('schedules_shift_type_foreign');
function (Blueprint $table) { $table->dropColumn('name');
$table->dropForeign('schedules_shift_type_foreign'); $table->dropColumn('shift_type');
$table->dropColumn('name'); $table->dropColumn('minutes_before');
$table->dropColumn('shift_type'); $table->dropColumn('minutes_after');
$table->dropColumn('minutes_before'); $table->dropTimestamps();
$table->dropColumn('minutes_after'); });
$table->dropTimestamps();
}
);
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,26 +14,20 @@ class AddEmailNewsToUsersSettings extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table( $this->schema->table('users_settings', function (Blueprint $table): void {
'users_settings', $table->boolean('email_news')->default(false)->after('email_shiftinfo');
function (Blueprint $table) { });
$table->boolean('email_news')->default(false)->after('email_shiftinfo');
}
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table( $this->schema->table('users_settings', function (Blueprint $table): void {
'users_settings', $table->dropColumn('email_news');
function (Blueprint $table) { });
$table->dropColumn('email_news');
}
);
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,30 +14,24 @@ class OauthAddTokens extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table( $this->schema->table('oauth', function (Blueprint $table): void {
'oauth', $table->string('access_token')->nullable()->default(null)->after('identifier');
function (Blueprint $table) { $table->string('refresh_token')->nullable()->default(null)->after('access_token');
$table->string('access_token')->nullable()->default(null)->after('identifier'); $table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token');
$table->string('refresh_token')->nullable()->default(null)->after('access_token'); });
$table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token');
}
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table( $this->schema->table('oauth', function (Blueprint $table): void {
'oauth', $table->dropColumn('access_token');
function (Blueprint $table) { $table->dropColumn('refresh_token');
$table->dropColumn('access_token'); $table->dropColumn('expires_at');
$table->dropColumn('refresh_token'); });
$table->dropColumn('expires_at');
}
);
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,26 +14,20 @@ class NewsAddIsPinned extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table( $this->schema->table('news', function (Blueprint $table): void {
'news', $table->boolean('is_pinned')->default(false)->after('is_meeting');
function (Blueprint $table) { });
$table->boolean('is_pinned')->default(false)->after('is_meeting');
}
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table( $this->schema->table('news', function (Blueprint $table): void {
'news', $table->dropColumn('is_pinned');
function (Blueprint $table) { });
$table->dropColumn('is_pinned');
}
);
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,28 +14,22 @@ class OauthChangeTokensToText extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table( $this->schema->table('oauth', function (Blueprint $table): void {
'oauth', $table->text('access_token')->change();
function (Blueprint $table) { $table->text('refresh_token')->change();
$table->text('access_token')->change(); });
$table->text('refresh_token')->change();
}
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table( $this->schema->table('oauth', function (Blueprint $table): void {
'oauth', $table->string('access_token')->change();
function (Blueprint $table) { $table->string('refresh_token')->change();
$table->string('access_token')->change(); });
$table->string('refresh_token')->change();
}
);
} }
} }

View File

@ -1,42 +1,28 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Config\Config; use Engelsystem\Config\Config;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Authenticator; use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
use Illuminate\Database\Schema\Builder as SchemaBuilder; use Illuminate\Database\Schema\Builder as SchemaBuilder;
class SetAdminPassword extends Migration class SetAdminPassword extends Migration
{ {
use Reference; use Reference;
/** @var Authenticator */ public function __construct(SchemaBuilder $schemaBuilder, protected Authenticator $auth, protected Config $config)
protected $auth;
/** @var Config */
protected $config;
/**
* @param SchemaBuilder $schemaBuilder
* @param Authenticator $auth
* @param Config $config
*/
public function __construct(SchemaBuilder $schemaBuilder, Authenticator $auth, Config $config)
{ {
parent::__construct($schemaBuilder); parent::__construct($schemaBuilder);
$this->auth = $auth;
$this->config = $config;
} }
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
/** @var User $admin */
$admin = $this->auth->authenticate('admin', 'asdfasdf'); $admin = $this->auth->authenticate('admin', 'asdfasdf');
$setupPassword = $this->config->get('setup_admin_password'); $setupPassword = $this->config->get('setup_admin_password');
if (!$admin || !$setupPassword) { if (!$admin || !$setupPassword) {

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class AddShirtEditPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -40,7 +42,7 @@ class AddShirtEditPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,34 +14,28 @@ class AddShiftsDescription extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('Shifts')) { if (!$this->schema->hasTable('Shifts')) {
return; return;
} }
$this->schema->table( $this->schema->table('Shifts', function (Blueprint $table): void {
'Shifts', $table->text('description')->nullable()->after('shifttype_id');
function (Blueprint $table) { });
$table->text('description')->nullable()->after('shifttype_id');
}
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('Shifts')) { if (!$this->schema->hasTable('Shifts')) {
return; return;
} }
$this->schema->table( $this->schema->table('Shifts', function (Blueprint $table): void {
'Shifts', $table->dropColumn('description');
function (Blueprint $table) { });
$table->dropColumn('description');
}
);
} }
} }

View File

@ -16,7 +16,7 @@ class CreateUserLicensesTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('users_licenses', function (Blueprint $table) { $this->schema->create('users_licenses', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('has_car')->default(false); $table->boolean('has_car')->default(false);
$table->boolean('drive_forklift')->default(false); $table->boolean('drive_forklift')->default(false);
@ -54,7 +54,7 @@ class CreateUserLicensesTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->create('UserDriverLicenses', function (Blueprint $table) { $this->schema->create('UserDriverLicenses', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('has_car'); $table->boolean('has_car');
$table->boolean('has_license_car'); $table->boolean('has_license_car');

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,9 +12,9 @@ class IncreaseSessionsTablePayloadSize extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table('sessions', function (Blueprint $table) { $this->schema->table('sessions', function (Blueprint $table): void {
$table->mediumText('payload')->change(); $table->mediumText('payload')->change();
}); });
} }
@ -20,9 +22,9 @@ class IncreaseSessionsTablePayloadSize extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table('sessions', function (Blueprint $table) { $this->schema->table('sessions', function (Blueprint $table): void {
$table->text('payload')->change(); $table->text('payload')->change();
}); });
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,16 +14,14 @@ class UsersSettingsAddEmailGoody extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table(
'users_settings',
function (Blueprint $table) {
$table->boolean('email_goody')->default(false)->after('email_human');
}
);
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->boolean('email_goody')->default(false)->after('email_human');
});
$connection $connection
->table('users_settings') ->table('users_settings')
->update(['email_goody' => $connection->raw('email_human')]); ->update(['email_goody' => $connection->raw('email_human')]);
@ -30,13 +30,10 @@ class UsersSettingsAddEmailGoody extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table( $this->schema->table('users_settings', function (Blueprint $table): void {
'users_settings', $table->dropColumn('email_goody');
function (Blueprint $table) { });
$table->dropColumn('email_goody');
}
);
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class RemoveAdminNewsHtmlPrivilege extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -27,7 +29,7 @@ class RemoveAdminNewsHtmlPrivilege extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -13,9 +15,9 @@ class IncreaseTshirtFieldWidth extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table) { $this->schema->table('users_personal_data', function (Blueprint $table): void {
$table->string('shirt_size', 10)->change(); $table->string('shirt_size', 10)->change();
}); });
} }
@ -23,9 +25,9 @@ class IncreaseTshirtFieldWidth extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table) { $this->schema->table('users_personal_data', function (Blueprint $table): void {
$table->string('shirt_size', 4)->change(); $table->string('shirt_size', 4)->change();
}); });
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class CreateVoucherEditPermission extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;
@ -36,7 +38,7 @@ class CreateVoucherEditPermission extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -18,7 +18,7 @@ class ShiftsAddTransactionId extends Migration
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table) { $this->schema->table('Shifts', function (Blueprint $table): void {
$table->uuid('transaction_id')->index()->nullable()->default(null); $table->uuid('transaction_id')->index()->nullable()->default(null);
}); });
} }
@ -32,7 +32,7 @@ class ShiftsAddTransactionId extends Migration
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table) { $this->schema->table('Shifts', function (Blueprint $table): void {
$table->dropColumn('transaction_id'); $table->dropColumn('transaction_id');
}); });
} }

View File

@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class FixOldGroupsTableIdAndName extends Migration
{
/** @var string[] */
protected array $naming = [
'1-Gast' => 'Guest',
'2-Engel' => 'Angel',
'Shirt-Manager' => 'Shirt Manager',
'3-Shift Coordinator' => 'Shift Coordinator',
'4-Team Coordinator' => 'Team Coordinator',
'5-Bürokrat' => 'Bureaucrat',
'6-Developer' => 'Developer',
];
/** @var int[] */
protected array $ids = [
-25 => -30,
-26 => -35,
-30 => -50,
-40 => -60,
-50 => -65,
-60 => -80,
-65 => -85,
-70 => -90,
];
/**
* Run the migration
*/
public function up(): void
{
$this->migrate($this->naming, $this->ids);
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->migrate(array_flip($this->naming), array_flip($this->ids));
}
/**
* @param string[] $naming
* @param int[] $ids
*/
private function migrate(array $naming, array $ids): void
{
if (!$this->schema->hasTable('Groups')) {
return;
}
$connection = $this->schema->getConnection();
foreach ($connection->table('Groups')->orderByDesc('UID')->get() as $data) {
if (isset($naming[$data->Name])) {
$data->Name = $naming[$data->Name];
}
$data->oldId = $data->UID;
if (isset($ids[$data->oldId])) {
$data->UID = $ids[$data->oldId];
} elseif (isset($ids[$data->oldId * -1])) {
$data->UID = $ids[$data->oldId * -1] * -1;
}
$connection
->table('Groups')
->where('UID', $data->oldId)
->update([
'UID' => $data->UID * -1,
'Name' => $data->Name,
]);
}
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddMobileShowToUsersSettings extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->boolean('mobile_show')->default(false)->after('email_news');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->dropColumn('mobile_show');
});
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddDectToRooms extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('rooms', function (Blueprint $table): void {
$table->text('dect')->nullable()->after('description');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('rooms', function (Blueprint $table): void {
$table->dropColumn('dect');
});
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddHideRegisterToAngeltypes extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
$this->schema->table('AngelTypes', function (Blueprint $table): void {
$table->boolean('hide_register')->default(false)->after('show_on_dashboard');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
$this->schema->table('AngelTypes', function (Blueprint $table): void {
$table->dropColumn('hide_register');
});
}
}

View File

@ -0,0 +1,262 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreatePrivilegesAndGroupsRelatedTables extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one.
*/
public function up(): void
{
$hasPrevious = $this->schema->hasTable('Privileges');
if ($hasPrevious) {
// Rename because some DBMS handle identifiers case-insensitive
$this->schema->rename('Groups', 'groups_old');
$this->schema->rename('Privileges', 'privileges_old');
}
$this->createNew();
if ($hasPrevious) {
$this->copyOldToNew();
$this->changeReferences(
'groups_old',
'UID',
'groups',
'id'
);
$this->changeReferences(
'privileges_old',
'id',
'privileges',
'id'
);
$this->changeReferences(
'UserGroups',
'id',
'users_groups',
'id'
);
$this->changeReferences(
'GroupPrivileges',
'id',
'group_privileges',
'id'
);
$this->schema->drop('UserGroups');
$this->schema->drop('GroupPrivileges');
$this->schema->drop('groups_old');
$this->schema->drop('privileges_old');
}
}
/**
* Recreates the previous table, copies the data and drops the new one.
*/
public function down(): void
{
// Rename because some DBMS handle identifiers case-insensitive
$this->schema->rename('groups', 'groups_new');
$this->schema->rename('privileges', 'privileges_new');
$this->createOldTable();
$this->copyNewToOld();
$this->changeReferences(
'groups_new',
'id',
'Groups',
'UID',
'integer'
);
$this->changeReferences(
'privileges_new',
'id',
'Privileges',
'id'
);
$this->changeReferences(
'users_groups',
'id',
'UserGroups',
'id'
);
$this->changeReferences(
'group_privileges',
'id',
'GroupPrivileges',
'id'
);
$this->schema->drop('users_groups');
$this->schema->drop('group_privileges');
$this->schema->drop('groups_new');
$this->schema->drop('privileges_new');
}
private function createNew(): void
{
$this->schema->create('groups', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 35)->unique();
});
$this->schema->create('privileges', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 128)->unique();
$table->string('description', 1024);
});
$this->schema->create('users_groups', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table)->index();
$this->references($table, 'groups')->index();
});
$this->schema->create('group_privileges', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'groups')->index();
$this->references($table, 'privileges')->index();
});
}
private function createOldTable(): void
{
$this->schema->create('Groups', function (Blueprint $table): void {
$table->string('Name', 35);
$table->integer('UID')->primary();
});
$this->schema->create('Privileges', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 128)->unique();
$table->string('desc', 1024);
});
$this->schema->create('UserGroups', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'users', 'uid');
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer')->index();
$table->index(['uid', 'group_id']);
});
$this->schema->create('GroupPrivileges', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer');
$this->references($table, 'Privileges', 'privilege_id')->index();
$table->index(['group_id', 'privilege_id']);
});
}
private function copyOldToNew(): void
{
$connection = $this->schema->getConnection();
/** @var stdClass[] $records */
$records = $connection
->table('groups_old')
->get();
foreach ($records as $record) {
$connection->table('groups')->insert([
'id' => $record->UID,
'name' => $record->Name,
]);
}
$records = $connection
->table('privileges_old')
->get();
foreach ($records as $record) {
$connection->table('privileges')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->desc,
]);
}
$records = $connection
->table('UserGroups')
->get();
foreach ($records as $record) {
$connection->table('users_groups')->insert([
'id' => $record->id,
'user_id' => $record->uid,
'group_id' => $record->group_id,
]);
}
$records = $connection
->table('GroupPrivileges')
->get();
foreach ($records as $record) {
$connection->table('group_privileges')->insert([
'id' => $record->id,
'group_id' => $record->group_id,
'privilege_id' => $record->privilege_id,
]);
}
}
private function copyNewToOld(): void
{
$connection = $this->schema->getConnection();
/** @var Collection|stdClass[] $records */
$records = $connection
->table('groups_new')
->get();
foreach ($records as $record) {
$connection->table('Groups')->insert([
'Name' => $record->name,
'UID' => $record->id,
]);
}
$records = $connection
->table('privileges_new')
->get();
foreach ($records as $record) {
$connection->table('Privileges')->insert([
'id' => $record->id,
'name' => $record->name,
'desc' => $record->description,
]);
}
$records = $connection
->table('users_groups')
->get();
foreach ($records as $record) {
$connection->table('UserGroups')->insert([
'id' => $record->id,
'uid' => $record->user_id,
'group_id' => $record->group_id,
]);
}
$records = $connection
->table('group_privileges')
->get();
foreach ($records as $record) {
$connection->table('GroupPrivileges')->insert([
'id' => $record->id,
'group_id' => $record->group_id,
'privilege_id' => $record->privilege_id,
]);
}
}
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class ShifttypeRemoveAngeltype extends Migration
{
use Reference;
/**
* Run the migration
*/
public function up(): void
{
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
$this->schema->table('ShiftTypes', function (Blueprint $table): void {
$table->dropForeign('shifttypes_ibfk_1');
$table->dropColumn('angeltype_id');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
$this->schema->table('ShiftTypes', function (Blueprint $table): void {
$table->integer('angeltype_id')->after('name')->index()->nullable();
$this->addReference($table, 'angeltype_id', 'AngelTypes', null, 'shifttypes_ibfk_1');
});
}
}

View File

@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftTypesTable extends Migration
{
use ChangesReferences;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('shift_types', function (Blueprint $table): void {
$table->increments('id');
$table->string('name')->unique();
$table->text('description');
});
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('ShiftTypes')
->get();
foreach ($records as $record) {
$connection->table('shift_types')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
]);
}
$this->changeReferences(
'ShiftTypes',
'id',
'shift_types',
'id'
);
$this->schema->drop('ShiftTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('ShiftTypes', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 255);
$table->mediumText('description');
});
/** @var stdClass[] $records */
$records = $connection
->table('shift_types')
->get();
foreach ($records as $record) {
$connection->table('ShiftTypes')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
]);
}
$this->changeReferences(
'shift_types',
'id',
'ShiftTypes',
'id'
);
$this->schema->drop('shift_types');
}
}

View File

@ -0,0 +1,126 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Support\Collection;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateAngelTypesTable extends Migration
{
use ChangesReferences;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('angel_types', function (Blueprint $table): void {
$table->increments('id');
$table->string('name')->unique();
$table->text('description')->default('');
$table->string('contact_name')->default('');
$table->string('contact_dect')->default('');
$table->string('contact_email')->default('');
$table->boolean('restricted')->default(false);
$table->boolean('requires_driver_license')->default(false);
$table->boolean('no_self_signup')->default(false);
$table->boolean('show_on_dashboard')->default(true);
$table->boolean('hide_register')->default(false);
});
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
/** @var Collection|stdClass[] $records */
$records = $connection
->table('AngelTypes')
->get();
foreach ($records as $record) {
$connection->table('angel_types')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
'contact_name' => (string) $record->contact_name,
'contact_dect' => (string) $record->contact_dect,
'contact_email' => (string) $record->contact_email,
'restricted' => $record->restricted,
'requires_driver_license' => $record->requires_driver_license,
'no_self_signup' => $record->no_self_signup,
'show_on_dashboard' => $record->show_on_dashboard,
'hide_register' => $record->hide_register,
]);
}
$this->changeReferences(
'AngelTypes',
'id',
'angel_types',
'id'
);
$this->schema->drop('AngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('AngelTypes', function (Blueprint $table): void {
$table->integer('id', true);
$table->string('name', 50)->default('')->unique();
$table->boolean('restricted');
$table->mediumText('description');
$table->boolean('requires_driver_license');
$table->boolean('no_self_signup');
$table->string('contact_name', 250)->nullable();
$table->string('contact_dect', 40)->nullable();
$table->string('contact_email', 250)->nullable();
$table->boolean('show_on_dashboard');
$table->boolean('hide_register')->default(false);
});
/** @var Collection|stdClass[] $records */
$records = $connection
->table('angel_types')
->get();
foreach ($records as $record) {
$connection->table('AngelTypes')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
'contact_name' => $record->contact_name ?: null,
'contact_dect' => $record->contact_dect ?: null,
'contact_email' => $record->contact_email ?: null,
'restricted' => $record->restricted,
'requires_driver_license' => $record->requires_driver_license,
'no_self_signup' => $record->no_self_signup,
'show_on_dashboard' => $record->show_on_dashboard,
'hide_register' => $record->hide_register,
]);
}
$this->changeReferences(
'angel_types',
'id',
'AngelTypes',
'id',
'integer'
);
$this->schema->drop('angel_types');
}
}

View File

@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateUserAngelTypesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('user_angel_type', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types')->index();
$this->references($table, 'users', 'confirm_user_id')->nullable()->default(null)->index();
$table->boolean('supporter')->default(false)->index();
$table->index(['user_id', 'angel_type_id', 'confirm_user_id']);
$table->unique(['user_id', 'angel_type_id']);
});
if (!$this->schema->hasTable('UserAngelTypes')) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('UserAngelTypes')
->get();
foreach ($records as $record) {
$connection->table('user_angel_type')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angel_type_id' => $record->angeltype_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool) $record->supporter,
]);
}
$this->changeReferences(
'UserAngelTypes',
'id',
'user_angel_type',
'id'
);
$this->schema->drop('UserAngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('UserAngelTypes', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types', 'angeltype_id')->index('angeltype_id');
$this->references($table, 'users', 'confirm_user_id')->nullable()->index('confirm_user_id');
$table->boolean('supporter')->nullable()->index('coordinator');
$table->index(['user_id', 'angeltype_id', 'confirm_user_id'], 'user_id');
});
/** @var stdClass[] $records */
$records = $connection
->table('user_angel_type')
->get();
foreach ($records as $record) {
$connection->table('UserAngelTypes')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angeltype_id' => $record->angel_type_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool) $record->supporter,
]);
}
$this->changeReferences(
'user_angel_type',
'id',
'UserAngelTypes',
'id',
'integer'
);
$this->schema->drop('user_angel_type');
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class ChangeApiKeyLength extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users', function (Blueprint $table): void {
$table->string('api_key', 64)->change();
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('users', function (Blueprint $table): void {
$table->string('api_key', 32)->change();
});
}
}

View File

@ -0,0 +1,149 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Carbon;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftsTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('Shifts');
if ($previous) {
$this->schema->rename('Shifts', 'shifts_old');
}
$this->schema->create('shifts', function (Blueprint $table): void {
$table->increments('id');
$table->string('title');
$table->text('description')->default('');
$table->string('url')->default('');
$table->dateTime('start')->index();
$table->dateTime('end');
$this->references($table, 'shift_types');
$this->references($table, 'rooms');
$table->uuid('transaction_id')->nullable()->default(null)->index();
$this->references($table, 'users', 'created_by');
$this->references($table, 'users', 'updated_by')->nullable()->default(null);
$table->timestamps();
});
if (!$previous) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('shifts_old')
->get();
foreach ($records as $record) {
$isUpdated = !empty($record->edited_at_timestamp)
&& $record->edited_at_timestamp != $record->created_at_timestamp;
$connection->table('shifts')->insert([
'id' => $record->SID,
'title' => (string) $record->title,
'description' => (string) $record->description,
'url' => (string) $record->URL,
'start' => Carbon::createFromTimestamp($record->start),
'end' => Carbon::createFromTimestamp($record->end),
'shift_type_id' => $record->shifttype_id,
'room_id' => $record->RID,
'transaction_id' => $record->transaction_id,
'created_by' => $record->created_by_user_id,
'updated_by' => $isUpdated ? $record->edited_by_user_id : null,
'created_at' => Carbon::createFromTimestamp($record->created_at_timestamp),
'updated_at' => $isUpdated ? Carbon::createFromTimestamp($record->edited_at_timestamp) : null,
]);
}
$this->changeReferences(
'shifts_old',
'SID',
'shifts',
'id'
);
$this->schema->drop('shifts_old');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->rename('shifts', 'shifts_old');
$this->schema->create('Shifts', function (Blueprint $table): void {
$table->increments('SID');
$table->mediumText('title')->nullable()->default(null);
$this->references($table, 'shift_types', 'shifttype_id');
$table->text('description')->nullable()->default(null);
$table->integer('start')->index();
$table->integer('end');
$this->references($table, 'rooms', 'RID')->default(0);
$table->mediumText('URL')->nullable()->default(null);
$this->references($table, 'users', 'created_by_user_id')->nullable()->default(null);
$table->integer('created_at_timestamp');
$this->references($table, 'users', 'edited_by_user_id')->nullable()->default(null);
$table->integer('edited_at_timestamp');
$table->uuid('transaction_id')->nullable()->default(null)->index();
});
/** @var stdClass[] $records */
$records = $connection
->table('shifts_old')
->get();
$now = Carbon::now()->getTimestamp();
foreach ($records as $record) {
$createdAt = $record->created_at ? Carbon::make($record->created_at)->getTimestamp() : $now;
$updatedAt = $record->updated_at ? Carbon::make($record->updated_at)->getTimestamp() : $createdAt;
$connection->table('Shifts')->insert([
'SID' => $record->id,
'title' => $record->title,
'shifttype_id' => $record->shift_type_id,
'description' => $record->description ?: null,
'start' => Carbon::make($record->start)->getTimestamp(),
'end' => Carbon::make($record->end)->getTimestamp(),
'RID' => $record->room_id,
'URL' => $record->url ?: null,
'created_by_user_id' => $record->created_by,
'created_at_timestamp' => $createdAt,
'edited_by_user_id' => $record->updated_by,
'edited_at_timestamp' => $updatedAt,
'transaction_id' => $record->transaction_id,
]);
}
$this->changeReferences(
'shifts_old',
'id',
'Shifts',
'SID'
);
$this->schema->drop('shifts_old');
}
}

View File

@ -0,0 +1,114 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftEntriesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('ShiftEntry');
$this->schema->create('shift_entries', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'shifts');
$this->references($table, 'angel_types');
$this->referencesUser($table);
$table->mediumText('user_comment')->default('');
$table->boolean('freeloaded')->default(false)->index();
$table->mediumText('freeloaded_comment')->default('');
$table->index(['angel_type_id', 'shift_id']);
});
if (!$previous) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('ShiftEntry')
->get();
foreach ($records as $record) {
$connection->table('shift_entries')->insert([
'id' => $record->id,
'shift_id' => $record->SID,
'angel_type_id' => $record->TID,
'user_id' => $record->UID,
'user_comment' => $record->Comment,
'freeloaded' => (bool) $record->freeloaded,
'freeloaded_comment' => $record->freeload_comment,
]);
}
$this->changeReferences(
'ShiftEntry',
'id',
'shift_entries',
'id'
);
$this->schema->drop('ShiftEntry');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('ShiftEntry', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'shifts', 'SID')->default(0);
$this->references($table, 'angel_types', 'TID')->default(0);
$this->references($table, 'users', 'UID')->default(0);
$table->mediumText('Comment')->nullable();
$table->mediumText('freeload_comment')->nullable()->default(null);
$table->boolean('freeloaded')->index();
$table->index(['SID', 'TID']);
});
/** @var stdClass[] $records */
$records = $connection
->table('shift_entries')
->get();
foreach ($records as $record) {
$connection->table('ShiftEntry')->insert([
'id' => $record->id,
'SID' => $record->shift_id,
'TID' => $record->angel_type_id,
'UID' => $record->user_id,
'Comment' => $record->user_comment,
'freeloaded' => (bool) $record->freeloaded,
'freeload_comment' => $record->freeloaded_comment,
]);
}
$this->changeReferences(
'shift_entries',
'id',
'ShiftEntry',
'id'
);
$this->schema->drop('shift_entries');
}
}

View File

@ -0,0 +1,108 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateNeededAngelTypesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('NeededAngelTypes');
$this->schema->create('needed_angel_types', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'rooms')->nullable();
$this->references($table, 'shifts')->nullable();
$this->references($table, 'angel_types');
$table->integer('count')->index();
$table->index(['room_id', 'angel_type_id']);
});
if (!$previous) {
return;
}
// Delete old entries which don't need angels
$connection
->table('NeededAngelTypes')
->where('count', 0)
->delete();
/** @var stdClass[] $records */
$records = $connection
->table('NeededAngelTypes')
->get();
foreach ($records as $record) {
$connection->table('needed_angel_types')->insert([
'id' => $record->id,
'room_id' => $record->room_id,
'shift_id' => $record->shift_id,
'angel_type_id' => $record->angel_type_id,
'count' => $record->count,
]);
}
$this->changeReferences(
'NeededAngelTypes',
'id',
'needed_angel_types',
'id'
);
$this->schema->drop('NeededAngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('NeededAngelTypes', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'rooms')->nullable();
$this->references($table, 'shifts')->nullable();
$this->references($table, 'angel_types');
$table->integer('count')->index();
$table->index(['room_id', 'angel_type_id']);
});
/** @var stdClass[] $records */
$records = $connection
->table('needed_angel_types')
->get();
foreach ($records as $record) {
$connection->table('NeededAngelTypes')->insert([
'id' => $record->id,
'room_id' => $record->room_id,
'shift_id' => $record->shift_id,
'angel_type_id' => $record->angel_type_id,
'count' => $record->count,
]);
}
$this->changeReferences(
'needed_angel_types',
'id',
'NeededAngelTypes',
'id'
);
$this->schema->drop('needed_angel_types');
}
}

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class AddSetNewsFlagImportantPermissions extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$db = $this->schema->getConnection();
$db->table('privileges')
->insert(['name' => 'news.important', 'description' => 'Make News Important']);
$newsImportant = $db->table('privileges')
->where('name', 'news.important')
->get(['id'])
->first();
$buerocrat = 80;
$db->table('group_privileges')
->insertOrIgnore([
['group_id' => $buerocrat, 'privilege_id' => $newsImportant->id],
]);
}
/**
* Reverse the migration
*/
public function down(): void
{
$db = $this->schema->getConnection();
$db->table('privileges')
->where(['name' => 'news.important'])
->delete();
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddIsImportantToNews extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('news', function (Blueprint $table): void {
$table->boolean('is_important')->default(false)->after('is_pinned');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('news', function (Blueprint $table): void {
$table->dropColumn('is_important');
});
}
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class FixEmailMessagesMigrationName extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->getConnection()
->table('migrations')
->where('migration', '2023_02_26_000000_AddEmailMessagesToUsersSettings')
->update([
'migration' => '2023_02_26_000000_add_email_messages_to_users_settings',
]);
}
// Down migration not needed when on same version
}

View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddEmailMessagesToUsersSettings extends Migration
{
use Reference;
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->boolean('email_messages')->default(false)->after('email_human');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->dropColumn('email_messages');
});
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class RenameShirtManager extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$db = $this->schema->getConnection();
$db->table('groups')
->where('name', 'Shirt Manager')
->update(['name' => 'Goodie Manager']);
}
/**
* Reverse the migration
*/
public function down(): void
{
$db = $this->schema->getConnection();
$db->table('groups')
->where('name', 'Goodie Manager')
->update(['name' => 'Shirt Manager']);
}
}

Some files were not shown because too many files have changed in this diff Show More