mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Compare commits
428 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c44535990b | ||
|
b8d5b83eee | ||
|
00da2dedc3 | ||
|
4ce1de079e | ||
|
6b9c125de4 | ||
|
2c4f44e808 | ||
|
2b694731ad | ||
|
7e34535e62 | ||
|
0bb831fe88 | ||
|
42a32ce142 | ||
|
23f58b7bf4 | ||
|
4e9101fded | ||
|
9c700c77a8 | ||
|
cb1f674332 | ||
|
6823d94ffb | ||
|
60ab992360 | ||
|
f9e769a6e3 | ||
|
f802c6c176 | ||
|
dedadf0c10 | ||
|
c8375def1a | ||
|
62ebcde2de | ||
|
594a5779dc | ||
|
c0ef64fb64 | ||
|
48c70c3bb4 | ||
|
68124a340b | ||
|
0b5003fcf6 | ||
|
956ece60af | ||
|
53da45d7d7 | ||
|
57f0432a87 | ||
|
fb535ec6f7 | ||
|
4e1b1a4ffa | ||
|
5b111d80f1 | ||
|
03e1105a8e | ||
|
059a9683db | ||
|
1daf6f01f4 | ||
|
d3b225771c | ||
|
7275db27e7 | ||
|
49ee9131d0 | ||
|
e75e0c4c0b | ||
|
e94d4a7752 | ||
|
95206f427d | ||
|
2d7f88522a | ||
|
f5c17bc7c8 | ||
|
63e222ed40 | ||
|
6963ee3b8d | ||
|
bb5e42bf63 | ||
|
c48f778648 | ||
|
616aad6403 | ||
|
bcc7547d6f | ||
|
5a1a6e9217 | ||
|
eae1fcecab | ||
|
b53989bb9d | ||
|
467d50bd31 | ||
|
1935258978 | ||
|
2b5030c69f | ||
|
6537502696 | ||
|
0ba352ab0b | ||
|
5d3f861728 | ||
|
319b69f6c7 | ||
|
c4ba28e3a0 | ||
|
b38ef8ecea | ||
|
cb0817666d | ||
|
a54c2db9b9 | ||
|
17caf476bf | ||
|
42cb590c75 | ||
|
6fd05e1456 | ||
|
bec45d60e5 | ||
|
019e67a676 | ||
|
f146d88aa5 | ||
|
48be9a8098 | ||
|
29f92d9bd3 | ||
|
ebb977e99f | ||
|
94bcd3d2d3 | ||
|
a9bd4c5606 | ||
|
8d9dde0032 | ||
|
b2d4333fff | ||
|
afd5e2b95b | ||
|
085adf8d71 | ||
|
9b35b60d61 | ||
|
742e57cc5c | ||
|
a5961668fe | ||
|
e7394c165a | ||
|
7be966122f | ||
|
d176b68fd2 | ||
|
1e80be1376 | ||
|
3585b08d4b | ||
|
c51e0eb68f | ||
|
d05c0579a2 | ||
|
5e40519bc5 | ||
|
d13752114c | ||
|
90e1b809fe | ||
|
32b4e6812d | ||
|
a798aa9c24 | ||
|
f1c28b9f46 | ||
|
39bc400376 | ||
|
e287918121 | ||
|
e0bf8e5fbc | ||
|
376c7e7a6f | ||
|
5612a790fb | ||
|
80527e35c3 | ||
|
f592ab6395 | ||
|
d7c741c652 | ||
|
9502f30e1b | ||
|
7286c4bbef | ||
|
a976f97dbb | ||
|
2c9b8c7dea | ||
|
787decf4e2 | ||
|
2fc70b8bdd | ||
|
64491a9772 | ||
|
b724b05de6 | ||
|
d94c4af1be | ||
|
8f0f5a5eb4 | ||
|
edf50a71d1 | ||
|
d0937218b9 | ||
|
3247a97217 | ||
|
edd254ee06 | ||
|
42ecb83155 | ||
|
56f801c058 | ||
|
2d3d05e956 | ||
|
4321e51bf5 | ||
|
be04730906 | ||
|
aa06e1df04 | ||
|
fd7a0156bc | ||
|
1e19ff24ba | ||
|
0f4238291f | ||
|
03a2a10efd | ||
|
04310aa2f8 | ||
|
e8ca11a5cf | ||
|
24137b30a5 | ||
|
4421917333 | ||
|
25c8660c2e | ||
|
190e87390d | ||
|
c9aefdd862 | ||
|
3ad088663f | ||
|
a29e87e5ac | ||
|
de0832bece | ||
|
614697ba84 | ||
|
6bdf3d891a | ||
|
f75704f77c | ||
|
9d09543eb9 | ||
|
a6116398a8 | ||
|
39763b84d5 | ||
|
8502df08fa | ||
|
bf2a776403 | ||
|
052190c69b | ||
|
8826ba6729 | ||
|
39b5240934 | ||
|
ddc1c286d9 | ||
|
22fba37d28 | ||
|
0c627a5636 | ||
|
53dcd24216 | ||
|
4b09a321ad | ||
|
9e85b70c17 | ||
|
9c99217dee | ||
|
afc1dbdd4b | ||
|
20f58fc07d | ||
|
e6b78dd213 | ||
|
63893ffabe | ||
|
c9e519d0b5 | ||
|
273bde90f2 | ||
|
92e4976396 | ||
|
e9efbff912 | ||
|
41089c08f8 | ||
|
9e23e606f8 | ||
|
b3f0fd368a | ||
|
12bd5472e2 | ||
|
ef64779759 | ||
|
b3d8076ddf | ||
|
f775203608 | ||
|
a6083688e4 | ||
|
50689cd4e6 | ||
|
255fcbac1c | ||
|
7f8ffa56e5 | ||
|
9a2a5f30a3 | ||
|
a9f444cbb4 | ||
|
164efb0551 | ||
|
a37b8cbb15 | ||
|
946032a101 | ||
|
a273acbecd | ||
|
0ceee1582e | ||
|
04a0369d56 | ||
|
31a288b44d | ||
|
502dc3aa1c | ||
|
6874d7ca55 | ||
|
da8f669aed | ||
|
0f92a69b03 | ||
|
8faa3251c4 | ||
|
56fc14003c | ||
|
b3499e4ea5 | ||
|
07b1ff9bf5 | ||
|
5bbf24c92e | ||
|
eea8b3e679 | ||
|
e223078af9 | ||
|
b554d0d851 | ||
|
b1ba26e0b9 | ||
|
ca8ad760d7 | ||
|
80129c0a88 | ||
|
7530e62dfa | ||
|
baf8977578 | ||
|
c7bf843312 | ||
|
ce6fee1682 | ||
|
2653fad488 | ||
|
dd54c46a29 | ||
|
724a0e21d3 | ||
|
578277d11f | ||
|
22258e3183 | ||
|
0234463b68 | ||
|
ef412eef92 | ||
|
76ebd22eab | ||
|
5b0ca8e346 | ||
|
0b6b10c27b | ||
|
6225d2c9b3 | ||
|
01fc6524a4 | ||
|
2575e6a160 | ||
|
484ba5ebd7 | ||
|
b42d98e9f8 | ||
|
65b2f045ac | ||
|
5e76451d46 | ||
|
a873ad3316 | ||
|
b1e03f49ee | ||
|
011e23f8e6 | ||
|
646cd8cf22 | ||
|
52ac8a70d5 | ||
|
e020334b73 | ||
|
7698e83f0b | ||
|
dd56f5e0c8 | ||
|
92c32eef74 | ||
|
08770c7dc5 | ||
|
808a94e4df | ||
|
490086d531 | ||
|
2ef3fbb81b | ||
|
7d834ac8d7 | ||
|
15ad0ec9c0 | ||
|
f0b78e8b2c | ||
|
e616faa76f | ||
|
8159f4d8ee | ||
|
021c576468 | ||
|
1b2339a82c | ||
|
2b6bb3f773 | ||
|
abc5c61a06 | ||
|
7145bce605 | ||
|
bb92e5e9ee | ||
|
0c47aa226c | ||
|
76e945bbbd | ||
|
4a6ec2581d | ||
|
3d75bf5f9f | ||
|
c27648b89b | ||
|
ccf67c0662 | ||
|
ca116cae91 | ||
|
a29d933f99 | ||
|
49acf3e0cf | ||
|
234b5abb96 | ||
|
839bcf91d6 | ||
|
58ed57fab7 | ||
|
fa42997733 | ||
|
ac416141d0 | ||
|
c629a85b14 | ||
|
7ccfea208f | ||
|
f3c802bcff | ||
|
574583bd6a | ||
|
84c54d0b25 | ||
|
86d3f87694 | ||
|
ddd7252051 | ||
|
b4e8136618 | ||
|
c2638991f2 | ||
|
8554be9abd | ||
|
87a518703f | ||
|
dd03ca943d | ||
|
6997861811 | ||
|
1cc1530b20 | ||
|
98597fb3aa | ||
|
283a445198 | ||
|
7db44f0ec5 | ||
|
abb5395cae | ||
|
8c8b44baef | ||
|
7366a33fe5 | ||
|
ad02d7e525 | ||
|
b5a0189f29 | ||
|
756152dd68 | ||
|
173a8ee680 | ||
|
b99777cde1 | ||
|
8193e7a68e | ||
|
f18c024daa | ||
|
f6577a8f33 | ||
|
7fc3153dde | ||
|
5231dbd6e7 | ||
|
77671550a7 | ||
|
e231404128 | ||
|
6650e2da3d | ||
|
fd521acaa4 | ||
|
a169623866 | ||
|
21c3c45150 | ||
|
1aee0a91c0 | ||
|
27a28d4adc | ||
|
d6ff22fc44 | ||
|
5ede61118c | ||
|
228549ff51 | ||
|
1ec5cbc301 | ||
|
3011cb8fae | ||
|
ff78c3c9a7 | ||
|
d5980b7620 | ||
|
a8e1171108 | ||
|
19e5d302f4 | ||
|
22e2480feb | ||
|
88ef1788ac | ||
|
a54ce939ca | ||
|
528d0c7a26 | ||
|
c68a647e75 | ||
|
e0e4b74b6f | ||
|
204178740c | ||
|
8fdf37261d | ||
|
06c8e584a4 | ||
|
bbf7222a6a | ||
|
f6e955b487 | ||
|
32a72bfd23 | ||
|
25e0c22de9 | ||
|
2dd1843aac | ||
|
f3bf4ca838 | ||
|
b88e5e27d8 | ||
|
6f91ff1f28 | ||
|
b7b941e3a1 | ||
|
64414fe105 | ||
|
701713e298 | ||
|
445229976f | ||
|
eb02404d49 | ||
|
c780c0bd92 | ||
|
8f631cae63 | ||
|
07afff8db5 | ||
|
a4f440656a | ||
|
235d572f8c | ||
|
eebc373734 | ||
|
002d29a53e | ||
|
5074e2beac | ||
|
d898ca736c | ||
|
af325612aa | ||
|
590c2c3b0a | ||
|
20f32c7f12 | ||
|
4106bcef5f | ||
|
0e3b8a2a28 | ||
|
272608b4ec | ||
|
7a389469b9 | ||
|
9650969c94 | ||
|
6821e668e4 | ||
|
43a68b96ae | ||
|
1f6e3db09e | ||
|
2fabcabcc0 | ||
|
22855b077d | ||
|
2cad7a67ea | ||
|
8ce93a028a | ||
|
028307b63c | ||
|
7bd6cd7cec | ||
|
8c45a40f9e | ||
|
70c62dab77 | ||
|
b4d8d31c2d | ||
|
bc15135f6b | ||
|
16baccc2cb | ||
|
bb2559edc1 | ||
|
f6f736a91f | ||
|
9f477676e2 | ||
|
6cba6ba52e | ||
|
d29dbc9385 | ||
|
cb01302ada | ||
|
e3dfbf0e95 | ||
|
3f471d0c73 | ||
|
4a706ab707 | ||
|
4946a9ab0d | ||
|
123372d93f | ||
|
272fe0516b | ||
|
289c9126d0 | ||
|
0a482da93e | ||
|
8bb8118d9f | ||
|
9db822eabd | ||
|
8a42dfa154 | ||
|
d7a7e22e5a | ||
|
4f75e2641b | ||
|
d3dcefb645 | ||
|
6d1553e8d8 | ||
|
740985d68f | ||
|
7ad2fab53d | ||
|
6e9b337b49 | ||
|
c58ff5861d | ||
|
33a5e70b70 | ||
|
07f1ce5822 | ||
|
d41996b365 | ||
|
d3c9b7eae1 | ||
|
373a1ab0f4 | ||
|
58dd56a89f | ||
|
d7eadd9294 | ||
|
853e29dd83 | ||
|
0c1c46c045 | ||
|
be97ea08a2 | ||
|
1c8b81ca2c | ||
|
8266f230d7 | ||
|
0b53542716 | ||
|
eab1c7096c | ||
|
8ee3aaf4f4 | ||
|
427b8659c9 | ||
|
3c3af824cf | ||
|
d40ce470d3 | ||
|
07c7f07c35 | ||
|
fe732ecf45 | ||
|
971bb92a8c | ||
|
777f6ba738 | ||
|
4d927c5870 | ||
|
1830e9da3d | ||
|
5eb29746af | ||
|
afb816cc41 | ||
|
bd640c19a4 | ||
|
0d445b6a21 | ||
|
78671b0bfe | ||
|
60325e797d | ||
|
7d9be5ae76 | ||
|
777bfed813 | ||
|
43ca543651 | ||
|
205d5f8f58 | ||
|
ee37852a72 | ||
|
dc14b58d73 | ||
|
a88a2e04cf | ||
|
c620beb965 | ||
|
92cb9f70a1 | ||
|
b2059b6910 | ||
|
0b21effb13 | ||
|
02acafc348 | ||
|
d202ecf06f | ||
|
5402d7bedb | ||
|
39247f1ece | ||
|
55b824d777 | ||
|
4eb223c401 |
502 changed files with 53572 additions and 16207 deletions
|
@ -39,8 +39,50 @@ if [ -d /var/www/html/var/db ]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start PHP-FPM
|
# Start PHP-FPM (the PHP_VERSION is replaced by the configured version in the Dockerfile)
|
||||||
service php8.1-fpm start
|
service phpPHP_VERSION-fpm start
|
||||||
|
|
||||||
|
|
||||||
|
# Run migrations if automigration is enabled via env variable DB_AUTOMIGRATE
|
||||||
|
if [ "$DB_AUTOMIGRATE" = "true" ]; then
|
||||||
|
echo "Waiting for database to be ready..."
|
||||||
|
ATTEMPTS_LEFT_TO_REACH_DATABASE=60
|
||||||
|
until [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ] || DATABASE_ERROR=$(sudo -E -u www-data php bin/console dbal:run-sql -q "SELECT 1" 2>&1); do
|
||||||
|
if [ $? -eq 255 ]; then
|
||||||
|
# If the Doctrine command exits with 255, an unrecoverable error occurred
|
||||||
|
ATTEMPTS_LEFT_TO_REACH_DATABASE=0
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
ATTEMPTS_LEFT_TO_REACH_DATABASE=$((ATTEMPTS_LEFT_TO_REACH_DATABASE - 1))
|
||||||
|
echo "Still waiting for database to be ready... Or maybe the database is not reachable. $ATTEMPTS_LEFT_TO_REACH_DATABASE attempts left."
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ]; then
|
||||||
|
echo "The database is not up or not reachable:"
|
||||||
|
echo "$DATABASE_ERROR"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "The database is now ready and reachable"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if there are any available migrations to do, by executing doctrine:migrations:up-to-date
|
||||||
|
# and checking if the exit code is 0 (up to date) or 1 (not up to date)
|
||||||
|
if sudo -E -u www-data php bin/console doctrine:migrations:up-to-date --no-interaction; then
|
||||||
|
echo "Database is up to date, no migrations necessary."
|
||||||
|
else
|
||||||
|
echo "Migrations available..."
|
||||||
|
echo "Do backup of database..."
|
||||||
|
|
||||||
|
sudo -E -u www-data mkdir -p /var/www/html/uploads/.automigration-backup/
|
||||||
|
# Backup the database
|
||||||
|
sudo -E -u www-data php bin/console partdb:backup -n --database /var/www/html/uploads/.automigration-backup/backup-$(date +%Y-%m-%d_%H-%M-%S).zip
|
||||||
|
|
||||||
|
# Check if there are any migration files
|
||||||
|
sudo -E -u www-data php bin/console doctrine:migrations:migrate --no-interaction
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
# first arg is `-f` or `--some-option` (taken from https://github.com/docker-library/php/blob/master/8.2/bullseye/apache/docker-php-entrypoint)
|
# first arg is `-f` or `--some-option` (taken from https://github.com/docker-library/php/blob/master/8.2/bullseye/apache/docker-php-entrypoint)
|
||||||
if [ "${1#-}" != "$1" ]; then
|
if [ "${1#-}" != "$1" ]; then
|
||||||
|
|
|
@ -43,6 +43,9 @@
|
||||||
PassEnv PROVIDER_OCTOPART_CLIENT_ID PROVIDER_OCTOPART_SECRET PROVIDER_OCTOPART_CURRENCY PROVIDER_OCTOPART_COUNTRY PROVIDER_OCTOPART_SEARCH_LIMIT PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS
|
PassEnv PROVIDER_OCTOPART_CLIENT_ID PROVIDER_OCTOPART_SECRET PROVIDER_OCTOPART_CURRENCY PROVIDER_OCTOPART_COUNTRY PROVIDER_OCTOPART_SEARCH_LIMIT PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS
|
||||||
PassEnv PROVIDER_MOUSER_KEY PROVIDER_MOUSER_SEARCH_OPTION PROVIDER_MOUSER_SEARCH_LIMIT PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE
|
PassEnv PROVIDER_MOUSER_KEY PROVIDER_MOUSER_SEARCH_OPTION PROVIDER_MOUSER_SEARCH_LIMIT PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE
|
||||||
PassEnv PROVIDER_LCSC_ENABLED PROVIDER_LCSC_CURRENCY
|
PassEnv PROVIDER_LCSC_ENABLED PROVIDER_LCSC_CURRENCY
|
||||||
|
PassEnv PROVIDER_OEMSECRETS_KEY PROVIDER_OEMSECRETS_COUNTRY_CODE PROVIDER_OEMSECRETS_CURRENCY PROVIDER_OEMSECRETS_ZERO_PRICE PROVIDER_OEMSECRETS_SET_PARAM PROVIDER_OEMSECRETS_SORT_CRITERIA
|
||||||
|
PassEnv PROVIDER_REICHELT_ENABLED PROVIDER_REICHELT_CURRENCY PROVIDER_REICHELT_COUNTRY PROVIDER_REICHELT_LANGUAGE PROVIDER_REICHELT_INCLUDE_VAT
|
||||||
|
PassEnv PROVIDER_POLLIN_ENABLED
|
||||||
PassEnv EDA_KICAD_CATEGORY_DEPTH
|
PassEnv EDA_KICAD_CATEGORY_DEPTH
|
||||||
|
|
||||||
# For most configuration files from conf-available/, which are
|
# For most configuration files from conf-available/, which are
|
||||||
|
|
62
.env
62
.env
|
@ -23,6 +23,10 @@ DATABASE_MYSQL_USE_SSL_CA=0
|
||||||
# Only do this, if you know what you are doing!
|
# Only do this, if you know what you are doing!
|
||||||
DATABASE_MYSQL_SSL_VERIFY_CERT=1
|
DATABASE_MYSQL_SSL_VERIFY_CERT=1
|
||||||
|
|
||||||
|
# Emulate natural sorting of strings even on databases that do not support it (like SQLite, MySQL or MariaDB < 10.7)
|
||||||
|
# This can be slow on big databases and might have some problems and quirks, so use it with caution
|
||||||
|
DATABASE_EMULATE_NATURAL_SORT=0
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
# General settings
|
# General settings
|
||||||
###################################################################################
|
###################################################################################
|
||||||
|
@ -139,7 +143,8 @@ PROVIDER_TME_CURRENCY=EUR
|
||||||
PROVIDER_TME_LANGUAGE=en
|
PROVIDER_TME_LANGUAGE=en
|
||||||
# The country to get results for
|
# The country to get results for
|
||||||
PROVIDER_TME_COUNTRY=DE
|
PROVIDER_TME_COUNTRY=DE
|
||||||
# Set this to 1 to get gross prices (including VAT) instead of net prices
|
# [DEPRECATED] Set this to 1 to get gross prices (including VAT) instead of net prices
|
||||||
|
# With private API keys, this option cannot be used anymore is ignored by Part-DB. The VAT inclusion depends on your TME account settings.
|
||||||
PROVIDER_TME_GET_GROSS_PRICES=1
|
PROVIDER_TME_GET_GROSS_PRICES=1
|
||||||
|
|
||||||
# Octopart / Nexar Provider:
|
# Octopart / Nexar Provider:
|
||||||
|
@ -177,6 +182,61 @@ PROVIDER_LCSC_ENABLED=0
|
||||||
# The currency to get prices in (e.g. EUR, USD, etc.)
|
# The currency to get prices in (e.g. EUR, USD, etc.)
|
||||||
PROVIDER_LCSC_CURRENCY=EUR
|
PROVIDER_LCSC_CURRENCY=EUR
|
||||||
|
|
||||||
|
# Oemsecrets Provider API 3.0.1:
|
||||||
|
# You can get your API key from https://www.oemsecrets.com/api
|
||||||
|
PROVIDER_OEMSECRETS_KEY=
|
||||||
|
# The country you want the output for
|
||||||
|
PROVIDER_OEMSECRETS_COUNTRY_CODE=DE
|
||||||
|
# Available country code are:
|
||||||
|
# AD, AE, AQ, AR, AT, AU, BE, BO, BR, BV, BY, CA, CH, CL, CN, CO, CZ, DE, DK, EC, EE, EH,
|
||||||
|
# ES, FI, FK, FO, FR, GB, GE, GF, GG, GI, GL, GR, GS, GY, HK, HM, HR, HU, IE, IM, IN, IS,
|
||||||
|
# IT, JM, JP, KP, KR, KZ, LI, LK, LT, LU, MC, MD, ME, MK, MT, NL, NO, NZ, PE, PH, PL, PT,
|
||||||
|
# PY, RO, RS, RU, SB, SD, SE, SG, SI, SJ, SK, SM, SO, SR, SY, SZ, TC, TF, TG, TH, TJ, TK,
|
||||||
|
# TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VE, VG, VI, VN, VU, WF, YE,
|
||||||
|
# ZA, ZM, ZW
|
||||||
|
#
|
||||||
|
# The currency you want the prices to be displayed in
|
||||||
|
PROVIDER_OEMSECRETS_CURRENCY=EUR
|
||||||
|
# Available currency are:AUD, CAD, CHF, CNY, DKK, EUR, GBP, HKD, ILS, INR, JPY, KRW, NOK,
|
||||||
|
# NZD, RUB, SEK, SGD, TWD, USD
|
||||||
|
#
|
||||||
|
# If PROVIDER_OEMSECRETS_ZERO_PRICE is set to 0, distributors with zero prices
|
||||||
|
# will be discarded from the creation of a new part (set to 1 otherwise)
|
||||||
|
PROVIDER_OEMSECRETS_ZERO_PRICE=0
|
||||||
|
#
|
||||||
|
# When PROVIDER_OEMSECRETS_SET_PARAM is set to 1 the parameters for the part are generated
|
||||||
|
# from the description transforming unstructured descriptions into structured parameters;
|
||||||
|
# each parameter in description should have the form: "...;name1:value1;name2:value2"
|
||||||
|
PROVIDER_OEMSECRETS_SET_PARAM=1
|
||||||
|
#
|
||||||
|
# This environment variable determines the sorting criteria for product results.
|
||||||
|
# The sorting process first arranges items based on the provided keyword.
|
||||||
|
# Then, if set to 'C', it further sorts by completeness (prioritizing items with the most
|
||||||
|
# detailed information). If set to 'M', it further sorts by manufacturer name.
|
||||||
|
#If unset or set to any other value, no sorting is performed.
|
||||||
|
PROVIDER_OEMSECRETS_SORT_CRITERIA=C
|
||||||
|
|
||||||
|
|
||||||
|
# Reichelt provider:
|
||||||
|
# Reichelt.com offers no official API, so this info provider webscrapes the website to extract info
|
||||||
|
# It could break at any time, use it at your own risk
|
||||||
|
# We dont require an API key for Reichelt, just set this to 1 to enable Reichelt support
|
||||||
|
PROVIDER_REICHELT_ENABLED=0
|
||||||
|
# The country to get prices for
|
||||||
|
PROVIDER_REICHELT_COUNTRY=DE
|
||||||
|
# The language to get results in (en, de, fr, nl, pl, it, es)
|
||||||
|
PROVIDER_REICHELT_LANGUAGE=en
|
||||||
|
# Include VAT in prices (set to 1 to include VAT, 0 to exclude VAT)
|
||||||
|
PROVIDER_REICHELT_INCLUDE_VAT=1
|
||||||
|
# The currency to get prices in (only for countries with countries other than EUR)
|
||||||
|
PROVIDER_REICHELT_CURRENCY=EUR
|
||||||
|
|
||||||
|
# Pollin provider:
|
||||||
|
# Pollin.de offers no official API, so this info provider webscrapes the website to extract info
|
||||||
|
# It could break at any time, use it at your own risk
|
||||||
|
# We dont require an API key for Pollin, just set this to 1 to enable Pollin support
|
||||||
|
PROVIDER_POLLIN_ENABLED=0
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
# EDA integration related settings
|
# EDA integration related settings
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
|
0
.env.dev
Normal file
0
.env.dev
Normal file
2
.github/workflows/docker_build.yml
vendored
2
.github/workflows/docker_build.yml
vendored
|
@ -65,7 +65,7 @@ jobs:
|
||||||
|
|
||||||
-
|
-
|
||||||
name: Build and push
|
name: Build and push
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
|
2
.github/workflows/docker_frankenphp.yml
vendored
2
.github/workflows/docker_frankenphp.yml
vendored
|
@ -65,7 +65,7 @@ jobs:
|
||||||
|
|
||||||
-
|
-
|
||||||
name: Build and push
|
name: Build and push
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: Dockerfile-frankenphp
|
file: Dockerfile-frankenphp
|
||||||
|
|
37
.github/workflows/tests.yml
vendored
37
.github/workflows/tests.yml
vendored
|
@ -16,9 +16,10 @@ jobs:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php-versions: [ '8.1', '8.2', '8.3' ]
|
php-versions: [ '8.1', '8.2', '8.3', '8.4' ]
|
||||||
db-type: [ 'mysql', 'sqlite' ]
|
db-type: [ 'mysql', 'sqlite', 'postgres' ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Note that we set DATABASE URL later based on our db-type matrix value
|
# Note that we set DATABASE URL later based on our db-type matrix value
|
||||||
|
@ -30,13 +31,17 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set Database env for MySQL
|
- name: Set Database env for MySQL
|
||||||
run: echo "DATABASE_URL=mysql://root:root@127.0.0.1:3306/test" >> $GITHUB_ENV
|
run: echo "DATABASE_URL=mysql://root:root@127.0.0.1:3306/partdb?serverVersion=8.0.35" >> $GITHUB_ENV
|
||||||
if: matrix.db-type == 'mysql'
|
if: matrix.db-type == 'mysql'
|
||||||
|
|
||||||
- name: Set Database env for SQLite
|
- name: Set Database env for SQLite
|
||||||
run: echo "DATABASE_URL="sqlite:///%kernel.project_dir%/var/app_test.db"" >> $GITHUB_ENV
|
run: echo "DATABASE_URL="sqlite:///%kernel.project_dir%/var/app_test.db"" >> $GITHUB_ENV
|
||||||
if: matrix.db-type == 'sqlite'
|
if: matrix.db-type == 'sqlite'
|
||||||
|
|
||||||
|
- name: Set Database env for PostgreSQL
|
||||||
|
run: echo "DATABASE_URL=postgresql://postgres:postgres @127.0.0.1:5432/partdb?serverVersion=14&charset=utf8" >> $GITHUB_ENV
|
||||||
|
if: matrix.db-type == 'postgres'
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
@ -50,8 +55,17 @@ jobs:
|
||||||
|
|
||||||
- name: Start MySQL
|
- name: Start MySQL
|
||||||
run: sudo systemctl start mysql.service
|
run: sudo systemctl start mysql.service
|
||||||
|
if: matrix.db-type == 'mysql'
|
||||||
|
|
||||||
#- name: Setup MySQL
|
# Replace the scram-sha-256 with trust for host connections, to avoid password authentication
|
||||||
|
- name: Start PostgreSQL
|
||||||
|
run: |
|
||||||
|
sudo sed -i 's/^\(host.*all.*all.*\)scram-sha-256/\1trust/' /etc/postgresql/14/main/pg_hba.conf
|
||||||
|
sudo systemctl start postgresql.service
|
||||||
|
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
|
||||||
|
if: matrix.db-type == 'postgres'
|
||||||
|
|
||||||
|
#- name: Setup MySQL
|
||||||
# uses: mirromutth/mysql-action@v1.1
|
# uses: mirromutth/mysql-action@v1.1
|
||||||
# with:
|
# with:
|
||||||
# mysql version: 5.7
|
# mysql version: 5.7
|
||||||
|
@ -99,12 +113,7 @@ jobs:
|
||||||
|
|
||||||
- name: Create DB
|
- name: Create DB
|
||||||
run: php bin/console --env test doctrine:database:create --if-not-exists -n
|
run: php bin/console --env test doctrine:database:create --if-not-exists -n
|
||||||
if: matrix.db-type == 'mysql'
|
if: matrix.db-type == 'mysql' || matrix.db-type == 'postgres'
|
||||||
|
|
||||||
# Checkinf for existance is not supported for sqlite, so do it without it
|
|
||||||
- name: Create DB
|
|
||||||
run: php bin/console --env test doctrine:database:create -n
|
|
||||||
if: matrix.db-type == 'sqlite'
|
|
||||||
|
|
||||||
- name: Do migrations
|
- name: Do migrations
|
||||||
run: php bin/console --env test doctrine:migrations:migrate -n
|
run: php bin/console --env test doctrine:migrations:migrate -n
|
||||||
|
@ -117,7 +126,7 @@ jobs:
|
||||||
run: ./bin/phpunit --coverage-clover=coverage.xml
|
run: ./bin/phpunit --coverage-clover=coverage.xml
|
||||||
|
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
env_vars: PHP_VERSION,DB_TYPE
|
env_vars: PHP_VERSION,DB_TYPE
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
@ -135,11 +144,11 @@ jobs:
|
||||||
- name: Test check-requirements command
|
- name: Test check-requirements command
|
||||||
run: php bin/console partdb:check-requirements -n
|
run: php bin/console partdb:check-requirements -n
|
||||||
|
|
||||||
|
- name: Test partdb:backup command
|
||||||
|
run: php bin/console partdb:backup -n --full /tmp/test_backup.zip
|
||||||
|
|
||||||
- name: Test legacy Part-DB import
|
- name: Test legacy Part-DB import
|
||||||
run: bash .github/assets/legacy_import/test_legacy_import.sh
|
run: bash .github/assets/legacy_import/test_legacy_import.sh
|
||||||
if: matrix.db-type == 'mysql' && matrix.php-versions == '8.2'
|
if: matrix.db-type == 'mysql' && matrix.php-versions == '8.2'
|
||||||
env:
|
env:
|
||||||
DATABASE_URL: mysql://root:root@localhost:3306/legacy_db
|
DATABASE_URL: mysql://root:root@localhost:3306/legacy_db
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
187
Dockerfile
187
Dockerfile
|
@ -1,22 +1,64 @@
|
||||||
FROM debian:bullseye-slim
|
ARG BASE_IMAGE=debian:bookworm-slim
|
||||||
|
ARG PHP_VERSION=8.3
|
||||||
|
|
||||||
|
FROM ${BASE_IMAGE} AS base
|
||||||
|
ARG PHP_VERSION
|
||||||
|
|
||||||
# Install needed dependencies for PHP build
|
# Install needed dependencies for PHP build
|
||||||
#RUN apt-get update && apt-get install -y pkg-config curl libcurl4-openssl-dev libicu-dev \
|
#RUN apt-get update && apt-get install -y pkg-config curl libcurl4-openssl-dev libicu-dev \
|
||||||
# libpng-dev libjpeg-dev libfreetype6-dev gnupg zip libzip-dev libjpeg62-turbo-dev libonig-dev libxslt-dev libwebp-dev vim \
|
# libpng-dev libjpeg-dev libfreetype6-dev gnupg zip libzip-dev libjpeg62-turbo-dev libonig-dev libxslt-dev libwebp-dev vim \
|
||||||
# && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
# && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN apt-get update && apt-get -y install apt-transport-https lsb-release ca-certificates curl zip mariadb-client \
|
RUN apt-get update && apt-get -y install \
|
||||||
|
apt-transport-https \
|
||||||
|
lsb-release \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
zip \
|
||||||
|
mariadb-client \
|
||||||
|
postgresql-client \
|
||||||
&& curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg \
|
&& curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg \
|
||||||
&& sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list' \
|
&& sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list' \
|
||||||
&& apt-get update && apt-get upgrade -y \
|
&& apt-get update && apt-get upgrade -y \
|
||||||
&& apt-get install -y apache2 php8.1 php8.1-fpm php8.1-opcache php8.1-curl php8.1-gd php8.1-mbstring php8.1-xml php8.1-bcmath php8.1-intl php8.1-zip php8.1-xsl php8.1-sqlite3 php8.1-mysql gpg sudo \
|
&& apt-get install -y \
|
||||||
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*;
|
apache2 \
|
||||||
|
php${PHP_VERSION} \
|
||||||
ENV APACHE_CONFDIR /etc/apache2
|
php${PHP_VERSION}-fpm \
|
||||||
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
|
php${PHP_VERSION}-opcache \
|
||||||
|
php${PHP_VERSION}-curl \
|
||||||
|
php${PHP_VERSION}-gd \
|
||||||
|
php${PHP_VERSION}-mbstring \
|
||||||
|
php${PHP_VERSION}-xml \
|
||||||
|
php${PHP_VERSION}-bcmath \
|
||||||
|
php${PHP_VERSION}-intl \
|
||||||
|
php${PHP_VERSION}-zip \
|
||||||
|
php${PHP_VERSION}-xsl \
|
||||||
|
php${PHP_VERSION}-sqlite3 \
|
||||||
|
php${PHP_VERSION}-mysql \
|
||||||
|
php${PHP_VERSION}-pgsql \
|
||||||
|
gpg \
|
||||||
|
sudo \
|
||||||
|
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/* \
|
||||||
# Create workdir and set permissions if directory does not exists
|
# Create workdir and set permissions if directory does not exists
|
||||||
RUN mkdir -p /var/www/html && chown -R www-data:www-data /var/www/html
|
&& mkdir -p /var/www/html \
|
||||||
|
&& chown -R www-data:www-data /var/www/html \
|
||||||
|
# delete the "index.html" that installing Apache drops in here
|
||||||
|
&& rm -rvf /var/www/html/*
|
||||||
|
|
||||||
|
# Install node and yarn
|
||||||
|
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
||||||
|
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
||||||
|
curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
|
||||||
|
apt-get update && apt-get install -y \
|
||||||
|
nodejs \
|
||||||
|
yarn \
|
||||||
|
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install composer
|
||||||
|
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
ENV APACHE_CONFDIR=/etc/apache2
|
||||||
|
ENV APACHE_ENVVARS=$APACHE_CONFDIR/envvars
|
||||||
|
|
||||||
# Configure apache 2 (taken from https://github.com/docker-library/php/blob/master/8.2/bullseye/apache/Dockerfile)
|
# Configure apache 2 (taken from https://github.com/docker-library/php/blob/master/8.2/bullseye/apache/Dockerfile)
|
||||||
# generically convert lines like
|
# generically convert lines like
|
||||||
|
@ -27,8 +69,6 @@ RUN mkdir -p /var/www/html && chown -R www-data:www-data /var/www/html
|
||||||
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
|
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
|
||||||
RUN sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
|
RUN sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
|
||||||
set -eux; . "$APACHE_ENVVARS"; \
|
set -eux; . "$APACHE_ENVVARS"; \
|
||||||
# delete the "index.html" that installing Apache drops in here
|
|
||||||
rm -rvf /var/www/html/*; \
|
|
||||||
\
|
\
|
||||||
# logs should go to stdout / stderr
|
# logs should go to stdout / stderr
|
||||||
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
|
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
|
||||||
|
@ -36,82 +76,87 @@ RUN sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"
|
||||||
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
|
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
|
||||||
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR";
|
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR";
|
||||||
|
|
||||||
# Enable php-fpm
|
# ---
|
||||||
RUN a2enmod proxy_fcgi setenvif && a2enconf php8.1-fpm
|
|
||||||
|
|
||||||
|
FROM scratch AS apache-config
|
||||||
|
ARG PHP_VERSION
|
||||||
# Configure php-fpm to log to stdout of the container (stdout of PID 1)
|
# Configure php-fpm to log to stdout of the container (stdout of PID 1)
|
||||||
# We have to use /proc/1/fd/1 because /dev/stdout or /proc/self/fd/1 does not point to the container stdout (because we use apache as entrypoint)
|
# We have to use /proc/1/fd/1 because /dev/stdout or /proc/self/fd/1 does not point to the container stdout (because we use apache as entrypoint)
|
||||||
# We also disable the clear_env option to allow the use of environment variables in php-fpm
|
# We also disable the clear_env option to allow the use of environment variables in php-fpm
|
||||||
RUN { \
|
COPY <<EOF /etc/php/${PHP_VERSION}/fpm/pool.d/zz-docker.conf
|
||||||
echo '[global]'; \
|
[global]
|
||||||
echo 'error_log = /proc/1/fd/1'; \
|
error_log = /proc/1/fd/1
|
||||||
echo; \
|
|
||||||
echo '[www]'; \
|
[www]
|
||||||
echo 'access.log = /proc/1/fd/1'; \
|
access.log = /proc/1/fd/1
|
||||||
echo 'catch_workers_output = yes'; \
|
catch_workers_output = yes
|
||||||
echo 'decorate_workers_output = no'; \
|
decorate_workers_output = no
|
||||||
echo 'clear_env = no'; \
|
clear_env = no
|
||||||
} | tee "/etc/php/8.1/fpm/pool.d/zz-docker.conf"
|
EOF
|
||||||
|
|
||||||
# PHP files should be handled by PHP, and should be preferred over any other file type
|
# PHP files should be handled by PHP, and should be preferred over any other file type
|
||||||
RUN { \
|
COPY <<EOF /etc/apache2/conf-available/docker-php.conf
|
||||||
echo '<FilesMatch \.php$>'; \
|
<FilesMatch \\.php$>
|
||||||
echo '\tSetHandler application/x-httpd-php'; \
|
SetHandler application/x-httpd-php
|
||||||
echo '</FilesMatch>'; \
|
</FilesMatch>
|
||||||
echo; \
|
|
||||||
echo 'DirectoryIndex disabled'; \
|
DirectoryIndex disabled
|
||||||
echo 'DirectoryIndex index.php index.html'; \
|
DirectoryIndex index.php index.html
|
||||||
echo; \
|
|
||||||
echo '<Directory /var/www/>'; \
|
<Directory /var/www/>
|
||||||
echo '\tOptions -Indexes'; \
|
Options -Indexes
|
||||||
echo '\tAllowOverride All'; \
|
AllowOverride All
|
||||||
echo '</Directory>'; \
|
</Directory>
|
||||||
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
|
EOF
|
||||||
&& a2enconf docker-php
|
|
||||||
|
|
||||||
# Enable opcache and configure it recommended for symfony (see https://symfony.com/doc/current/performance.html)
|
# Enable opcache and configure it recommended for symfony (see https://symfony.com/doc/current/performance.html)
|
||||||
RUN \
|
COPY <<EOF /etc/php/${PHP_VERSION}/fpm/conf.d/symfony-recommended.ini
|
||||||
{ \
|
opcache.memory_consumption=256
|
||||||
echo 'opcache.memory_consumption=256'; \
|
opcache.max_accelerated_files=20000
|
||||||
echo 'opcache.max_accelerated_files=20000'; \
|
opcache.validate_timestamp=0
|
||||||
echo 'opcache.validate_timestamp=0'; \
|
# Configure Realpath cache for performance
|
||||||
# Configure Realpath cache for performance
|
realpath_cache_size=4096K
|
||||||
echo 'realpath_cache_size=4096K'; \
|
realpath_cache_ttl=600
|
||||||
echo 'realpath_cache_ttl=600'; \
|
EOF
|
||||||
} > /etc/php/8.1/fpm/conf.d/symfony-recommended.ini
|
|
||||||
|
|
||||||
# Increase upload limit and enable preloading
|
# Increase upload limit and enable preloading
|
||||||
RUN \
|
COPY <<EOF /etc/php/${PHP_VERSION}/fpm/conf.d/partdb.ini
|
||||||
{ \
|
upload_max_filesize=256M
|
||||||
echo 'upload_max_filesize=256M'; \
|
post_max_size=300M
|
||||||
echo 'post_max_size=300M'; \
|
opcache.preload_user=www-data
|
||||||
echo 'opcache.preload_user=www-data'; \
|
opcache.preload=/var/www/html/config/preload.php
|
||||||
echo 'opcache.preload=/var/www/html/config/preload.php'; \
|
log_limit=8096
|
||||||
} > /etc/php/8.1/fpm/conf.d/partdb.ini
|
EOF
|
||||||
|
|
||||||
# Install node and yarn
|
COPY ./.docker/symfony.conf /etc/apache2/sites-available/symfony.conf
|
||||||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
|
||||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - && apt-get update && apt-get install -y nodejs yarn && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install composer
|
# ---
|
||||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
|
||||||
|
|
||||||
|
FROM base
|
||||||
|
ARG PHP_VERSION
|
||||||
|
|
||||||
# Set working dir
|
# Set working dir
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
|
COPY --from=apache-config / /
|
||||||
COPY --chown=www-data:www-data . .
|
COPY --chown=www-data:www-data . .
|
||||||
|
|
||||||
# Setup apache2
|
# Setup apache2
|
||||||
RUN a2dissite 000-default.conf
|
RUN a2dissite 000-default.conf && \
|
||||||
COPY ./.docker/symfony.conf /etc/apache2/sites-available/symfony.conf
|
a2ensite symfony.conf && \
|
||||||
RUN a2ensite symfony.conf
|
# Enable php-fpm
|
||||||
RUN a2enmod rewrite
|
a2enmod proxy_fcgi setenvif && \
|
||||||
|
a2enconf php${PHP_VERSION}-fpm && \
|
||||||
|
a2enconf docker-php && \
|
||||||
|
a2enmod rewrite
|
||||||
|
|
||||||
# Install composer and yarn dependencies for Part-DB
|
# Install composer and yarn dependencies for Part-DB
|
||||||
USER www-data
|
USER www-data
|
||||||
RUN composer install -a --no-dev && composer clear-cache
|
RUN composer install -a --no-dev && \
|
||||||
RUN yarn install --network-timeout 600000 && yarn build && yarn cache clean && rm -rf node_modules/
|
composer clear-cache
|
||||||
|
RUN yarn install --network-timeout 600000 && \
|
||||||
|
yarn build && \
|
||||||
|
yarn cache clean && \
|
||||||
|
rm -rf node_modules/
|
||||||
|
|
||||||
# Use docker env to output logs to stdout
|
# Use docker env to output logs to stdout
|
||||||
ENV APP_ENV=docker
|
ENV APP_ENV=docker
|
||||||
|
@ -119,10 +164,12 @@ ENV DATABASE_URL="sqlite:///%kernel.project_dir%/uploads/app.db"
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
# Copy entrypoint to /usr/local/bin and make it executable
|
# Replace the php version placeholder in the entry point, with our php version
|
||||||
RUN cp ./.docker/partdb-entrypoint.sh /usr/local/bin/partdb-entrypoint.sh && chmod +x /usr/local/bin/partdb-entrypoint.sh
|
RUN sed -i "s/PHP_VERSION/${PHP_VERSION}/g" ./.docker/partdb-entrypoint.sh
|
||||||
# Copy apache2-foreground to /usr/local/bin and make it executable
|
|
||||||
RUN cp ./.docker/apache2-foreground /usr/local/bin/apache2-foreground && chmod +x /usr/local/bin/apache2-foreground
|
# Copy entrypoint and apache2-foreground to /usr/local/bin and make it executable
|
||||||
|
RUN install ./.docker/partdb-entrypoint.sh /usr/local/bin && \
|
||||||
|
install ./.docker/apache2-foreground /usr/local/bin
|
||||||
ENTRYPOINT ["partdb-entrypoint.sh"]
|
ENTRYPOINT ["partdb-entrypoint.sh"]
|
||||||
CMD ["apache2-foreground"]
|
CMD ["apache2-foreground"]
|
||||||
|
|
||||||
|
@ -130,4 +177,4 @@ CMD ["apache2-foreground"]
|
||||||
STOPSIGNAL SIGWINCH
|
STOPSIGNAL SIGWINCH
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
VOLUME ["/var/www/html/uploads", "/var/www/html/public/media"]
|
VOLUME ["/var/www/html/uploads", "/var/www/html/public/media"]
|
||||||
|
|
|
@ -1,11 +1,25 @@
|
||||||
FROM dunglas/frankenphp:1-php8.3 AS frankenphp_upstream
|
FROM dunglas/frankenphp:1-php8.3 AS frankenphp_upstream
|
||||||
|
|
||||||
RUN apt-get update && apt-get -y install curl zip mariadb-client file acl git gettext ca-certificates gnupg \
|
RUN apt-get update && apt-get -y install \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
mariadb-client \
|
||||||
|
postgresql-client \
|
||||||
|
file \
|
||||||
|
acl \
|
||||||
|
git \
|
||||||
|
gettext \
|
||||||
|
gnupg \
|
||||||
|
zip \
|
||||||
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*;
|
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*;
|
||||||
|
|
||||||
# Create workdir and set permissions if directory does not exists
|
# Install node and yarn
|
||||||
RUN mkdir -p /app
|
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
||||||
WORKDIR /app
|
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
||||||
|
curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
|
||||||
|
apt-get update && apt-get install -y \
|
||||||
|
nodejs yarn \
|
||||||
|
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Install PHP
|
# Install PHP
|
||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
|
@ -17,6 +31,7 @@ RUN set -eux; \
|
||||||
zip \
|
zip \
|
||||||
pdo_mysql \
|
pdo_mysql \
|
||||||
pdo_sqlite \
|
pdo_sqlite \
|
||||||
|
pdo_pgsql \
|
||||||
gd \
|
gd \
|
||||||
bcmath \
|
bcmath \
|
||||||
xsl \
|
xsl \
|
||||||
|
@ -32,15 +47,13 @@ ENV FRANKENPHP_CONFIG="import worker.Caddyfile"
|
||||||
|
|
||||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||||
|
|
||||||
# Install node and yarn
|
|
||||||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
|
||||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_20.x | bash - && apt-get update && apt-get install -y nodejs yarn && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install composer
|
# Install composer
|
||||||
ENV COMPOSER_ALLOW_SUPERUSER=1
|
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||||
#COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
#COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
# Create workdir and set permissions if directory does not exists
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
# prevent the reinstallation of vendors at every changes in the source code
|
# prevent the reinstallation of vendors at every changes in the source code
|
||||||
COPY --link composer.* symfony.* ./
|
COPY --link composer.* symfony.* ./
|
||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
|
@ -57,7 +70,10 @@ RUN set -eux; \
|
||||||
composer run-script --no-dev post-install-cmd; \
|
composer run-script --no-dev post-install-cmd; \
|
||||||
chmod +x bin/console; sync;
|
chmod +x bin/console; sync;
|
||||||
|
|
||||||
RUN yarn install --network-timeout 600000 && yarn build && yarn cache clean && rm -rf node_modules/
|
RUN yarn install --network-timeout 600000 && \
|
||||||
|
yarn build && \
|
||||||
|
yarn cache clean && \
|
||||||
|
rm -rf node_modules/
|
||||||
|
|
||||||
# Use docker env to output logs to stdout
|
# Use docker env to output logs to stdout
|
||||||
ENV APP_ENV=docker
|
ENV APP_ENV=docker
|
||||||
|
@ -82,4 +98,4 @@ ENV XDG_DATA_HOME /data
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
EXPOSE 443
|
EXPOSE 443
|
||||||
EXPOSE 443/udp
|
EXPOSE 443/udp
|
||||||
EXPOSE 2019
|
EXPOSE 2019
|
||||||
|
|
|
@ -55,7 +55,7 @@ for the first time.
|
||||||
* Event log: Track what changes happen to your inventory, track which user does what. Revert your parts to older
|
* Event log: Track what changes happen to your inventory, track which user does what. Revert your parts to older
|
||||||
versions.
|
versions.
|
||||||
* Responsive design: You can use Part-DB on your PC, your tablet, and your smartphone using the same interface.
|
* Responsive design: You can use Part-DB on your PC, your tablet, and your smartphone using the same interface.
|
||||||
* MySQL and SQLite are supported as database backends
|
* MySQL, SQLite and PostgreSQL are supported as database backends
|
||||||
* Support for rich text descriptions and comments in parts
|
* Support for rich text descriptions and comments in parts
|
||||||
* Support for multiple currencies and automatic update of exchange rates supported
|
* Support for multiple currencies and automatic update of exchange rates supported
|
||||||
* Powerful search and filter function, including parametric search (search for parts according to some specifications)
|
* Powerful search and filter function, including parametric search (search for parts according to some specifications)
|
||||||
|
@ -74,10 +74,10 @@ Part-DB is also used by small companies and universities for managing their inve
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* A **web server** (like Apache2 or nginx) that is capable of
|
* A **web server** (like Apache2 or nginx) that is capable of
|
||||||
running [Symfony 5](https://symfony.com/doc/current/reference/requirements.html),
|
running [Symfony 6](https://symfony.com/doc/current/reference/requirements.html),
|
||||||
this includes a minimum PHP version of **PHP 8.1**
|
this includes a minimum PHP version of **PHP 8.1**
|
||||||
* A **MySQL** (at least 5.7) /**MariaDB** (at least 10.2.2) database server if you do not want to use SQLite.
|
* A **MySQL** (at least 5.7) /**MariaDB** (at least 10.4) database server, or **PostgreSQL** 10+ if you do not want to use SQLite.
|
||||||
* Shell access to your server is highly suggested!
|
* Shell access to your server is highly recommended!
|
||||||
* For building the client-side assets **yarn** and **nodejs** (>= 18.0) is needed.
|
* For building the client-side assets **yarn** and **nodejs** (>= 18.0) is needed.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
1.12.0
|
1.17.1
|
||||||
|
|
|
@ -128,6 +128,8 @@ const PLACEHOLDERS = [
|
||||||
['[[BARCODE_QR]]', 'QR code linking to this element'],
|
['[[BARCODE_QR]]', 'QR code linking to this element'],
|
||||||
['[[BARCODE_C128]]', 'Code 128 barcode linking to this element'],
|
['[[BARCODE_C128]]', 'Code 128 barcode linking to this element'],
|
||||||
['[[BARCODE_C39]]', 'Code 39 barcode linking to this element'],
|
['[[BARCODE_C39]]', 'Code 39 barcode linking to this element'],
|
||||||
|
['[[BARCODE_C93]]', 'Code 93 barcode linking to this element'],
|
||||||
|
['[[BARCODE_DATAMATRIX]]', 'Datamatrix code linking to this element'],
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,8 @@ Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
|
||||||
'QR code linking to this element': 'QR Code verknüpft mit diesem Element',
|
'QR code linking to this element': 'QR Code verknüpft mit diesem Element',
|
||||||
'Code 128 barcode linking to this element': 'Code 128 Barcode verknüpft mit diesem Element',
|
'Code 128 barcode linking to this element': 'Code 128 Barcode verknüpft mit diesem Element',
|
||||||
'Code 39 barcode linking to this element': 'Code 39 Barcode verknüpft mit diesem Element',
|
'Code 39 barcode linking to this element': 'Code 39 Barcode verknüpft mit diesem Element',
|
||||||
|
'Code 93 barcode linking to this element': 'Code 93 Barcode verknüpft mit diesem Element',
|
||||||
|
'Datamatrix code linking to this element': 'Datamatrix Code verknüpft mit diesem Element',
|
||||||
|
|
||||||
'Location ID': 'Lagerort ID',
|
'Location ID': 'Lagerort ID',
|
||||||
'Name': 'Name',
|
'Name': 'Name',
|
||||||
|
|
|
@ -88,5 +88,8 @@ export default class extends Controller {
|
||||||
} else {
|
} else {
|
||||||
this.hideSidebar();
|
this.hideSidebar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Hide the tootip on the button
|
||||||
|
this._toggle_button.blur();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,6 +23,12 @@ import "tom-select/dist/css/tom-select.bootstrap5.css";
|
||||||
import '../../css/components/tom-select_extensions.css';
|
import '../../css/components/tom-select_extensions.css';
|
||||||
import TomSelect from "tom-select";
|
import TomSelect from "tom-select";
|
||||||
|
|
||||||
|
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||||
|
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||||
|
|
||||||
|
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||||
|
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
_tomSelect;
|
_tomSelect;
|
||||||
|
|
||||||
|
@ -46,6 +52,12 @@ export default class extends Controller {
|
||||||
}
|
}
|
||||||
return '<div>' + escape(data.label) + '</div>';
|
return '<div>' + escape(data.label) + '</div>';
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
'autoselect_typed': {},
|
||||||
|
'click_to_edit': {},
|
||||||
|
'clear_button': {},
|
||||||
|
"restore_on_backspace": {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ export default class extends Controller {
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
language: language,
|
language: language,
|
||||||
|
licenseKey: "GPL",
|
||||||
}
|
}
|
||||||
|
|
||||||
const watchdog = new EditorWatchdog();
|
const watchdog = new EditorWatchdog();
|
||||||
|
|
|
@ -186,5 +186,15 @@ export default class extends Controller {
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Try to find the input field and register a defocus handler. This is necessarry, as by default the autocomplete
|
||||||
|
//lib has problems when multiple inputs are present on the page. (see https://github.com/algolia/autocomplete/issues/1216)
|
||||||
|
const inputs = this.element.getElementsByClassName('aa-Input');
|
||||||
|
for (const input of inputs) {
|
||||||
|
input.addEventListener('blur', () => {
|
||||||
|
this._autocomplete.setIsOpen(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,6 +23,12 @@ import "tom-select/dist/css/tom-select.bootstrap5.css";
|
||||||
import '../../css/components/tom-select_extensions.css';
|
import '../../css/components/tom-select_extensions.css';
|
||||||
import TomSelect from "tom-select";
|
import TomSelect from "tom-select";
|
||||||
|
|
||||||
|
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||||
|
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||||
|
|
||||||
|
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||||
|
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the frontend controller for StaticFileAutocompleteType form element.
|
* This is the frontend controller for StaticFileAutocompleteType form element.
|
||||||
* Basically it loads a text file from the given url (via data-url) and uses it as a source for the autocomplete.
|
* Basically it loads a text file from the given url (via data-url) and uses it as a source for the autocomplete.
|
||||||
|
@ -46,7 +52,13 @@ export default class extends Controller {
|
||||||
orderField: 'text',
|
orderField: 'text',
|
||||||
|
|
||||||
//This a an ugly solution to disable the delimiter parsing of the TomSelect plugin
|
//This a an ugly solution to disable the delimiter parsing of the TomSelect plugin
|
||||||
delimiter: 'VERY_L0NG_D€LIMITER_WHICH_WILL_NEVER_BE_ENCOUNTERED_IN_A_STRING'
|
delimiter: 'VERY_L0NG_D€LIMITER_WHICH_WILL_NEVER_BE_ENCOUNTERED_IN_A_STRING',
|
||||||
|
plugins: {
|
||||||
|
'autoselect_typed': {},
|
||||||
|
'click_to_edit': {},
|
||||||
|
'clear_button': {},
|
||||||
|
'restore_on_backspace': {}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.element.dataset.url) {
|
if (this.element.dataset.url) {
|
||||||
|
|
|
@ -24,6 +24,8 @@ import {Controller} from "@hotwired/stimulus";
|
||||||
|
|
||||||
import {trans, ENTITY_SELECT_GROUP_NEW_NOT_ADDED_TO_DB} from '../../translator.js'
|
import {trans, ENTITY_SELECT_GROUP_NEW_NOT_ADDED_TO_DB} from '../../translator.js'
|
||||||
|
|
||||||
|
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||||
|
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
_tomSelect;
|
_tomSelect;
|
||||||
|
@ -38,11 +40,15 @@ export default class extends Controller {
|
||||||
const allowAdd = this.element.getAttribute("data-allow-add") === "true";
|
const allowAdd = this.element.getAttribute("data-allow-add") === "true";
|
||||||
const addHint = this.element.getAttribute("data-add-hint") ?? "";
|
const addHint = this.element.getAttribute("data-add-hint") ?? "";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let settings = {
|
let settings = {
|
||||||
allowEmptyOption: true,
|
allowEmptyOption: true,
|
||||||
selectOnTab: true,
|
selectOnTab: true,
|
||||||
maxOptions: null,
|
maxOptions: null,
|
||||||
create: allowAdd ? this.createItem.bind(this) : false,
|
create: allowAdd ? this.createItem.bind(this) : false,
|
||||||
|
createFilter: this.createFilter.bind(this),
|
||||||
|
|
||||||
// This three options allow us to paste element names with commas: (see issue #538)
|
// This three options allow us to paste element names with commas: (see issue #538)
|
||||||
maxItems: 1,
|
maxItems: 1,
|
||||||
|
@ -58,7 +64,21 @@ export default class extends Controller {
|
||||||
render: {
|
render: {
|
||||||
item: this.renderItem.bind(this),
|
item: this.renderItem.bind(this),
|
||||||
option: this.renderOption.bind(this),
|
option: this.renderOption.bind(this),
|
||||||
option_create: function(data, escape) {
|
option_create: (data, escape) => {
|
||||||
|
//If the input starts with "->", we prepend the current selected value, for easier extension of existing values
|
||||||
|
//This here handles the display part, while the createItem function handles the actual creation
|
||||||
|
if (data.input.startsWith("->")) {
|
||||||
|
//Get current selected value
|
||||||
|
const current = this._tomSelect.getItem(this._tomSelect.getValue()).textContent.replaceAll("→", "->").trim();
|
||||||
|
//Prepend it to the input
|
||||||
|
if (current) {
|
||||||
|
data.input = current + " " + data.input;
|
||||||
|
} else {
|
||||||
|
//If there is no current value, we remove the "->"
|
||||||
|
data.input = data.input.substring(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return '<div class="create"><i class="fa-solid fa-plus fa-fw"></i> <strong>' + escape(data.input) + '</strong>… ' +
|
return '<div class="create"><i class="fa-solid fa-plus fa-fw"></i> <strong>' + escape(data.input) + '</strong>… ' +
|
||||||
'<small class="text-muted float-end">(' + addHint +')</small>' +
|
'<small class="text-muted float-end">(' + addHint +')</small>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
|
@ -68,14 +88,39 @@ export default class extends Controller {
|
||||||
//Add callbacks to update validity
|
//Add callbacks to update validity
|
||||||
onInitialize: this.updateValidity.bind(this),
|
onInitialize: this.updateValidity.bind(this),
|
||||||
onChange: this.updateValidity.bind(this),
|
onChange: this.updateValidity.bind(this),
|
||||||
|
|
||||||
|
plugins: {
|
||||||
|
"autoselect_typed": {},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Add clear button plugin, if an empty option is present
|
||||||
|
if (this.element.querySelector("option[value='']") !== null) {
|
||||||
|
settings.plugins["clear_button"] = {};
|
||||||
|
}
|
||||||
|
|
||||||
this._tomSelect = new TomSelect(this.element, settings);
|
this._tomSelect = new TomSelect(this.element, settings);
|
||||||
//Do not do a sync here as this breaks the initial rendering of the empty option
|
//Do not do a sync here as this breaks the initial rendering of the empty option
|
||||||
//this._tomSelect.sync();
|
//this._tomSelect.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
createItem(input, callback) {
|
createItem(input, callback) {
|
||||||
|
|
||||||
|
//If the input starts with "->", we prepend the current selected value, for easier extension of existing values
|
||||||
|
if (input.startsWith("->")) {
|
||||||
|
//Get current selected value
|
||||||
|
let current = this._tomSelect.getItem(this._tomSelect.getValue()).textContent.replaceAll("→", "->").trim();
|
||||||
|
//Replace no break spaces with normal spaces
|
||||||
|
current = current.replaceAll("\u00A0", " ");
|
||||||
|
//Prepend it to the input
|
||||||
|
if (current) {
|
||||||
|
input = current + " " + input;
|
||||||
|
} else {
|
||||||
|
//If there is no current value, we remove the "->"
|
||||||
|
input = input.substring(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
callback({
|
callback({
|
||||||
//$%$ is a special value prefix, that is used to identify items, that are not yet in the DB
|
//$%$ is a special value prefix, that is used to identify items, that are not yet in the DB
|
||||||
value: '$%$' + input,
|
value: '$%$' + input,
|
||||||
|
@ -84,6 +129,31 @@ export default class extends Controller {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createFilter(input) {
|
||||||
|
|
||||||
|
//Normalize the input (replace spacing around arrows)
|
||||||
|
if (input.includes("->")) {
|
||||||
|
const inputs = input.split("->");
|
||||||
|
inputs.forEach((value, index) => {
|
||||||
|
inputs[index] = value.trim();
|
||||||
|
});
|
||||||
|
input = inputs.join("->");
|
||||||
|
} else {
|
||||||
|
input = input.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = this._tomSelect.options;
|
||||||
|
//Iterate over all options and check if the input is already present
|
||||||
|
for (let index in options) {
|
||||||
|
const option = options[index];
|
||||||
|
if (option.path === input) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
updateValidity() {
|
updateValidity() {
|
||||||
//Mark this input as invalid, if the selected option is disabled
|
//Mark this input as invalid, if the selected option is disabled
|
||||||
|
|
|
@ -23,14 +23,21 @@ import "tom-select/dist/css/tom-select.bootstrap5.css";
|
||||||
import '../../css/components/tom-select_extensions.css';
|
import '../../css/components/tom-select_extensions.css';
|
||||||
import TomSelect from "tom-select";
|
import TomSelect from "tom-select";
|
||||||
|
|
||||||
|
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||||
|
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||||
|
|
||||||
|
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||||
|
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
_tomSelect;
|
_tomSelect;
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
let settings = {
|
let settings = {
|
||||||
plugins: {
|
plugins: {
|
||||||
remove_button:{
|
remove_button:{},
|
||||||
}
|
'autoselect_typed': {},
|
||||||
|
'click_to_edit': {},
|
||||||
},
|
},
|
||||||
persistent: false,
|
persistent: false,
|
||||||
selectOnTab: true,
|
selectOnTab: true,
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
import {Controller} from "@hotwired/stimulus";
|
import {Controller} from "@hotwired/stimulus";
|
||||||
//import * as ZXing from "@zxing/library";
|
//import * as ZXing from "@zxing/library";
|
||||||
|
|
||||||
import {Html5QrcodeScanner, Html5Qrcode} from "html5-qrcode";
|
import {Html5QrcodeScanner, Html5Qrcode} from "@part-db/html5-qrcode";
|
||||||
|
|
||||||
/* stimulusFetch: 'lazy' */
|
/* stimulusFetch: 'lazy' */
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
|
@ -50,7 +50,7 @@ export default class extends Controller {
|
||||||
});
|
});
|
||||||
|
|
||||||
this._scanner = new Html5QrcodeScanner(this.element.id, {
|
this._scanner = new Html5QrcodeScanner(this.element.id, {
|
||||||
fps: 2,
|
fps: 10,
|
||||||
qrbox: qrboxFunction,
|
qrbox: qrboxFunction,
|
||||||
experimentalFeatures: {
|
experimentalFeatures: {
|
||||||
//This option improves reading quality on android chrome
|
//This option improves reading quality on android chrome
|
||||||
|
@ -61,6 +61,11 @@ export default class extends Controller {
|
||||||
this._scanner.render(this.onScanSuccess.bind(this));
|
this._scanner.render(this.onScanSuccess.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this._scanner.pause();
|
||||||
|
this._scanner.clear();
|
||||||
|
}
|
||||||
|
|
||||||
onScanSuccess(decodedText, decodedResult) {
|
onScanSuccess(decodedText, decodedResult) {
|
||||||
//Put our decoded Text into the input box
|
//Put our decoded Text into the input box
|
||||||
document.getElementById('scan_dialog_input').value = decodedText;
|
document.getElementById('scan_dialog_input').value = decodedText;
|
||||||
|
|
|
@ -25,9 +25,20 @@ import "katex/dist/katex.css";
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ["input", "preview"];
|
static targets = ["input", "preview"];
|
||||||
|
|
||||||
|
static values = {
|
||||||
|
unit: {type: Boolean, default: false} //Render as upstanding (non-italic) text, useful for units
|
||||||
|
}
|
||||||
|
|
||||||
updatePreview()
|
updatePreview()
|
||||||
{
|
{
|
||||||
katex.render(this.inputTarget.value, this.previewTarget, {
|
let value = "";
|
||||||
|
if (this.unitValue) {
|
||||||
|
value = "\\mathrm{" + this.inputTarget.value + "}";
|
||||||
|
} else {
|
||||||
|
value = this.inputTarget.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
katex.render(value, this.previewTarget, {
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,13 @@ import TomSelect from "tom-select";
|
||||||
import katex from "katex";
|
import katex from "katex";
|
||||||
import "katex/dist/katex.css";
|
import "katex/dist/katex.css";
|
||||||
|
|
||||||
|
|
||||||
|
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||||
|
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||||
|
|
||||||
|
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||||
|
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||||
|
|
||||||
/* stimulusFetch: 'lazy' */
|
/* stimulusFetch: 'lazy' */
|
||||||
export default class extends Controller
|
export default class extends Controller
|
||||||
{
|
{
|
||||||
|
@ -53,7 +60,10 @@ export default class extends Controller
|
||||||
connect() {
|
connect() {
|
||||||
const settings = {
|
const settings = {
|
||||||
plugins: {
|
plugins: {
|
||||||
clear_button:{}
|
'autoselect_typed': {},
|
||||||
|
'click_to_edit': {},
|
||||||
|
'clear_button': {},
|
||||||
|
'restore_on_backspace': {}
|
||||||
},
|
},
|
||||||
persistent: false,
|
persistent: false,
|
||||||
maxItems: 1,
|
maxItems: 1,
|
||||||
|
|
|
@ -111,4 +111,11 @@ ul.structural_link li a:hover {
|
||||||
.permission-checkbox:checked {
|
.permission-checkbox:checked {
|
||||||
background-color: var(--bs-success);
|
background-color: var(--bs-success);
|
||||||
border-color: var(--bs-success);
|
border-color: var(--bs-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
* Katex rendering with same height as text
|
||||||
|
***********************************************/
|
||||||
|
.katex-same-height-as-text .katex {
|
||||||
|
font-size: 1.0em;
|
||||||
}
|
}
|
|
@ -51,7 +51,6 @@
|
||||||
.part-table-image {
|
.part-table-image {
|
||||||
max-height: 40px;
|
max-height: 40px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.part-info-image {
|
.part-info-image {
|
||||||
|
@ -61,4 +60,4 @@
|
||||||
|
|
||||||
.object-fit-cover {
|
.object-fit-cover {
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,8 +108,8 @@ body {
|
||||||
.back-to-top {
|
.back-to-top {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 20px;
|
bottom: 60px;
|
||||||
right: 20px;
|
right: 40px;
|
||||||
display:none;
|
display:none;
|
||||||
z-index: 1030;
|
z-index: 1030;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,6 @@ table.dataTable > tbody > tr.selected > td > a {
|
||||||
margin-block-end: 0;
|
margin-block-end: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-footer-table {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.dataTable {
|
table.dataTable {
|
||||||
margin-top: 0 !important;
|
margin-top: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,8 @@
|
||||||
/** Should be the same settings, as in label_style.css */
|
/** Should be the same settings, as in label_style.css */
|
||||||
.ck-html-label .ck-content {
|
.ck-html-label .ck-content {
|
||||||
font-family: "DejaVu Sans Mono", monospace;
|
font-family: "DejaVu Sans Mono", monospace;
|
||||||
font-size: 12px;
|
font-size: 12pt;
|
||||||
line-height: 1.0;
|
line-height: 1.0;
|
||||||
font-size-adjust: 1.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck-html-label .ck-content p {
|
.ck-html-label .ck-content p {
|
||||||
|
|
|
@ -44,4 +44,18 @@ import "./register_events";
|
||||||
import "./tristate_checkboxes";
|
import "./tristate_checkboxes";
|
||||||
|
|
||||||
//Define jquery globally
|
//Define jquery globally
|
||||||
window.$ = window.jQuery = require("jquery")
|
window.$ = window.jQuery = require("jquery");
|
||||||
|
|
||||||
|
//Use the local WASM file for the ZXing library
|
||||||
|
import {
|
||||||
|
setZXingModuleOverrides,
|
||||||
|
} from "barcode-detector/pure";
|
||||||
|
import wasmFile from "../../node_modules/zxing-wasm/dist/reader/zxing_reader.wasm";
|
||||||
|
setZXingModuleOverrides({
|
||||||
|
locateFile: (path, prefix) => {
|
||||||
|
if (path.endsWith(".wasm")) {
|
||||||
|
return wasmFile;
|
||||||
|
}
|
||||||
|
return prefix + path;
|
||||||
|
},
|
||||||
|
});
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
import {Dropdown} from "bootstrap";
|
import {Dropdown} from "bootstrap";
|
||||||
import ClipboardJS from "clipboard";
|
import ClipboardJS from "clipboard";
|
||||||
|
import {Modal} from "bootstrap";
|
||||||
|
|
||||||
class RegisterEventHelper {
|
class RegisterEventHelper {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -31,9 +32,11 @@ class RegisterEventHelper {
|
||||||
//Initialize ClipboardJS
|
//Initialize ClipboardJS
|
||||||
this.registerLoadHandler(() => {
|
this.registerLoadHandler(() => {
|
||||||
new ClipboardJS('.btn');
|
new ClipboardJS('.btn');
|
||||||
})
|
});
|
||||||
|
|
||||||
this.registerModalDropRemovalOnFormSubmit();
|
this.registerModalDropRemovalOnFormSubmit();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registerModalDropRemovalOnFormSubmit() {
|
registerModalDropRemovalOnFormSubmit() {
|
||||||
|
@ -43,6 +46,15 @@ class RegisterEventHelper {
|
||||||
if (back_drop) {
|
if (back_drop) {
|
||||||
back_drop.remove();
|
back_drop.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Remove scroll-lock if it is still active
|
||||||
|
if (document.body.classList.contains('modal-open')) {
|
||||||
|
document.body.classList.remove('modal-open');
|
||||||
|
|
||||||
|
//Remove the padding-right and overflow:hidden from the body
|
||||||
|
document.body.style.paddingRight = '';
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
63
assets/tomselect/autoselect_typed/autoselect_typed.js
Normal file
63
assets/tomselect/autoselect_typed/autoselect_typed.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* Autoselect Typed plugin for Tomselect
|
||||||
|
*
|
||||||
|
* This plugin allows automatically selecting an option matching the typed text when the Tomselect element goes out of
|
||||||
|
* focus (is blurred) and/or when the delimiter is typed.
|
||||||
|
*
|
||||||
|
* #select_on_blur option
|
||||||
|
* Tomselect natively supports the "createOnBlur" option. This option picks up any remaining text in the input field
|
||||||
|
* and uses it to create a new option and selects that option. It does behave a bit strangely though, in that it will
|
||||||
|
* not select an already existing option when the input is blurred, so if you typed something that matches an option in
|
||||||
|
* the list and then click outside the box (without pressing enter) the entered text is just removed (unless you have
|
||||||
|
* allow duplicates on in which case it will create a new option).
|
||||||
|
* This plugin fixes that, such that Tomselect will first try to select an option matching the remaining uncommitted
|
||||||
|
* text and only when no matching option is found tries to create a new one (if createOnBlur and create is on)
|
||||||
|
*
|
||||||
|
* #select_on_delimiter option
|
||||||
|
* Normally when typing the delimiter (space by default) Tomselect will try to create a new option (and select it) (if
|
||||||
|
* create is on), but if the typed text matches an option (and allow duplicates is off) it refuses to react at all until
|
||||||
|
* you press enter. With this option, the delimiter will also allow selecting an option, not just creating it.
|
||||||
|
*/
|
||||||
|
function select_current_input(self){
|
||||||
|
if(self.isLocked){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const val = self.inputValue()
|
||||||
|
//Do nothing if the input is empty
|
||||||
|
if (!val) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.options[val]) {
|
||||||
|
self.addItem(val)
|
||||||
|
self.setTextboxValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(plugin_options_) {
|
||||||
|
const plugin_options = Object.assign({
|
||||||
|
//Autoselect the typed text when the input element goes out of focus
|
||||||
|
select_on_blur: true,
|
||||||
|
//Autoselect the typed text when the delimiter is typed
|
||||||
|
select_on_delimiter: true,
|
||||||
|
}, plugin_options_);
|
||||||
|
|
||||||
|
const self = this
|
||||||
|
|
||||||
|
if(plugin_options.select_on_blur) {
|
||||||
|
this.hook("before", "onBlur", function () {
|
||||||
|
select_current_input(self)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(plugin_options.select_on_delimiter) {
|
||||||
|
this.hook("before", "onKeyPress", function (e) {
|
||||||
|
const character = String.fromCharCode(e.keyCode || e.which);
|
||||||
|
if (self.settings.mode === 'multi' && character === self.settings.delimiter) {
|
||||||
|
select_current_input(self)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
93
assets/tomselect/click_to_edit/click_to_edit.js
Normal file
93
assets/tomselect/click_to_edit/click_to_edit.js
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* click_to_edit plugin for Tomselect
|
||||||
|
*
|
||||||
|
* This plugin allows editing (and selecting text in) any selected item by clicking it.
|
||||||
|
*
|
||||||
|
* Usually, when the user typed some text and created an item in Tomselect that item cannot be edited anymore. To make
|
||||||
|
* a change, the item has to be deleted and retyped completely. There is also generally no way to copy text out of a
|
||||||
|
* tomselect item. The "restore_on_backspace" plugin improves that somewhat, by allowing the user to edit an item after
|
||||||
|
* pressing backspace. However, it is somewhat confusing to first have to focus the field an then hit backspace in order
|
||||||
|
* to copy a piece of text. It may also not be immediately obvious for editing.
|
||||||
|
* This plugin transforms an item into editable text when it is clicked, e.g. when the user tries to place the caret
|
||||||
|
* within an item or when they try to drag across the text to highlight it.
|
||||||
|
* It also plays nice with the remove_button plugin which still removes (deselects) an option entirely.
|
||||||
|
*
|
||||||
|
* It is recommended to also enable the autoselect_typed plugin when using this plugin. Without it, the text in the
|
||||||
|
* input field (i.e. the item that was just clicked) is lost when the user clicks outside the field. Also, when the user
|
||||||
|
* clicks an option (making it text) and then tries to enter another one by entering the delimiter (e.g. space) nothing
|
||||||
|
* happens until enter is pressed or the text is changed from what it was.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a dom element from either a dom query string, jQuery object, a dom element or html string
|
||||||
|
* https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518
|
||||||
|
*
|
||||||
|
* param query should be {}
|
||||||
|
*/
|
||||||
|
const getDom = query => {
|
||||||
|
if (query.jquery) {
|
||||||
|
return query[0];
|
||||||
|
}
|
||||||
|
if (query instanceof HTMLElement) {
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
if (isHtmlString(query)) {
|
||||||
|
var tpl = document.createElement('template');
|
||||||
|
tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result
|
||||||
|
return tpl.content.firstChild;
|
||||||
|
}
|
||||||
|
return document.querySelector(query);
|
||||||
|
};
|
||||||
|
const isHtmlString = arg => {
|
||||||
|
if (typeof arg === 'string' && arg.indexOf('<') > -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
function plugin(plugin_options_) {
|
||||||
|
const self = this
|
||||||
|
|
||||||
|
const plugin_options = Object.assign({
|
||||||
|
//If there is unsubmitted text in the input field, should that text be automatically used to select a matching
|
||||||
|
//element? If this is off, clicking on item1 and then clicking on item2 will result in item1 being deselected
|
||||||
|
auto_select_before_edit: true,
|
||||||
|
//If there is unsubmitted text in the input field, should that text be automatically used to create a matching
|
||||||
|
//element if no matching element was found or auto_select_before_edit is off?
|
||||||
|
auto_create_before_edit: true,
|
||||||
|
//customize this function to change which text the item is replaced with when clicking on it
|
||||||
|
text: option => {
|
||||||
|
return option[self.settings.labelField];
|
||||||
|
}
|
||||||
|
}, plugin_options_);
|
||||||
|
|
||||||
|
|
||||||
|
self.hook('after', 'setupTemplates', () => {
|
||||||
|
const orig_render_item = self.settings.render.item;
|
||||||
|
self.settings.render.item = (data, escape) => {
|
||||||
|
const item = getDom(orig_render_item.call(self, data, escape));
|
||||||
|
|
||||||
|
item.addEventListener('click', evt => {
|
||||||
|
if (self.isLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const val = self.inputValue();
|
||||||
|
|
||||||
|
if (self.options[val]) {
|
||||||
|
self.addItem(val)
|
||||||
|
} else if (self.settings.create) {
|
||||||
|
self.createItem();
|
||||||
|
}
|
||||||
|
const option = self.options[item.dataset.value]
|
||||||
|
self.setTextboxValue(plugin_options.text.call(self, option));
|
||||||
|
self.focus();
|
||||||
|
self.removeItem(item);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
export { plugin as default };
|
|
@ -4,6 +4,10 @@
|
||||||
use App\Kernel;
|
use App\Kernel;
|
||||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||||
|
|
||||||
|
if (!is_dir(dirname(__DIR__).'/vendor')) {
|
||||||
|
throw new LogicException('Dependencies are missing. Try running "composer install".');
|
||||||
|
}
|
||||||
|
|
||||||
//Increase xdebug.max_nesting_level to 1000 if required (see issue #411)
|
//Increase xdebug.max_nesting_level to 1000 if required (see issue #411)
|
||||||
//Check if xdebug extension is active, and xdebug.max_nesting_level is set to 256 or lower
|
//Check if xdebug extension is active, and xdebug.max_nesting_level is set to 256 or lower
|
||||||
if (extension_loaded('xdebug') && ((int) ini_get('xdebug.max_nesting_level')) <= 256) {
|
if (extension_loaded('xdebug') && ((int) ini_get('xdebug.max_nesting_level')) <= 256) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"name": "part-db/part-db-server",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -10,18 +11,18 @@
|
||||||
"ext-intl": "*",
|
"ext-intl": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
|
"amphp/http-client": "^5.1",
|
||||||
"api-platform/core": "^3.1",
|
"api-platform/core": "^3.1",
|
||||||
"beberlei/doctrineextensions": "^1.2",
|
"beberlei/doctrineextensions": "^1.2",
|
||||||
"brick/math": "0.12.1 as 0.11.0",
|
"brick/math": "0.12.1 as 0.11.0",
|
||||||
"composer/ca-bundle": "^1.3",
|
"composer/ca-bundle": "^1.5",
|
||||||
"composer/package-versions-deprecated": "^1.11.99.5",
|
"composer/package-versions-deprecated": "^1.11.99.5",
|
||||||
"doctrine/annotations": "1.14.3",
|
"doctrine/data-fixtures": "^2.0.0",
|
||||||
"doctrine/data-fixtures": "^1.6.6",
|
"doctrine/dbal": "^4.0.0",
|
||||||
"doctrine/dbal": "^3.4.6",
|
|
||||||
"doctrine/doctrine-bundle": "^2.0",
|
"doctrine/doctrine-bundle": "^2.0",
|
||||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||||
"doctrine/orm": "^2.16",
|
"doctrine/orm": "^3.2.0",
|
||||||
"dompdf/dompdf": "dev-master#c9cf4be933e2406a51990bd4eb9e70612e790cc0 as v2.0.4",
|
"dompdf/dompdf": "^v3.0.0",
|
||||||
"erusev/parsedown": "^1.7",
|
"erusev/parsedown": "^1.7",
|
||||||
"florianv/swap": "^4.0",
|
"florianv/swap": "^4.0",
|
||||||
"florianv/swap-bundle": "dev-master",
|
"florianv/swap-bundle": "dev-master",
|
||||||
|
@ -39,12 +40,10 @@
|
||||||
"nelmio/cors-bundle": "^2.3",
|
"nelmio/cors-bundle": "^2.3",
|
||||||
"nelmio/security-bundle": "^3.0",
|
"nelmio/security-bundle": "^3.0",
|
||||||
"nyholm/psr7": "^1.1",
|
"nyholm/psr7": "^1.1",
|
||||||
"ocramius/proxy-manager": "2.2.*",
|
"omines/datatables-bundle": "^0.9.1",
|
||||||
"omines/datatables-bundle": "^0.8.0",
|
"paragonie/sodium_compat": "^1.21",
|
||||||
"part-db/label-fonts": "^1.0",
|
"part-db/label-fonts": "^1.0",
|
||||||
"php-translation/symfony-bundle": "^0.14.0",
|
"rhukster/dom-sanitizer": "^1.0",
|
||||||
"phpdocumentor/reflection-docblock": "^5.2",
|
|
||||||
"phpstan/phpdoc-parser": "^1.23",
|
|
||||||
"runtime/frankenphp-symfony": "^0.2.0",
|
"runtime/frankenphp-symfony": "^0.2.0",
|
||||||
"s9e/text-formatter": "^2.1",
|
"s9e/text-formatter": "^2.1",
|
||||||
"scheb/2fa-backup-code": "^6.8.0",
|
"scheb/2fa-backup-code": "^6.8.0",
|
||||||
|
@ -56,6 +55,8 @@
|
||||||
"symfony/apache-pack": "^1.0",
|
"symfony/apache-pack": "^1.0",
|
||||||
"symfony/asset": "6.4.*",
|
"symfony/asset": "6.4.*",
|
||||||
"symfony/console": "6.4.*",
|
"symfony/console": "6.4.*",
|
||||||
|
"symfony/css-selector": "6.4.*",
|
||||||
|
"symfony/dom-crawler": "6.4.*",
|
||||||
"symfony/dotenv": "6.4.*",
|
"symfony/dotenv": "6.4.*",
|
||||||
"symfony/expression-language": "6.4.*",
|
"symfony/expression-language": "6.4.*",
|
||||||
"symfony/flex": "^v2.3.1",
|
"symfony/flex": "^v2.3.1",
|
||||||
|
@ -69,7 +70,6 @@
|
||||||
"symfony/process": "6.4.*",
|
"symfony/process": "6.4.*",
|
||||||
"symfony/property-access": "6.4.*",
|
"symfony/property-access": "6.4.*",
|
||||||
"symfony/property-info": "6.4.*",
|
"symfony/property-info": "6.4.*",
|
||||||
"symfony/proxy-manager-bridge": "6.4.*",
|
|
||||||
"symfony/rate-limiter": "6.4.*",
|
"symfony/rate-limiter": "6.4.*",
|
||||||
"symfony/runtime": "6.4.*",
|
"symfony/runtime": "6.4.*",
|
||||||
"symfony/security-bundle": "6.4.*",
|
"symfony/security-bundle": "6.4.*",
|
||||||
|
@ -91,31 +91,28 @@
|
||||||
"twig/intl-extra": "^3.8",
|
"twig/intl-extra": "^3.8",
|
||||||
"twig/markdown-extra": "^3.8",
|
"twig/markdown-extra": "^3.8",
|
||||||
"twig/string-extra": "^3.8",
|
"twig/string-extra": "^3.8",
|
||||||
"web-auth/webauthn-symfony-bundle": "^4.0.0",
|
"web-auth/webauthn-symfony-bundle": "^4.0.0"
|
||||||
"webmozart/assert": "^1.4"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"dama/doctrine-test-bundle": "^v8.0.0",
|
"dama/doctrine-test-bundle": "^v8.0.0",
|
||||||
"doctrine/doctrine-fixtures-bundle": "^3.2",
|
"doctrine/doctrine-fixtures-bundle": "^4.0.0",
|
||||||
"ekino/phpstan-banned-code": "^v1.0.0",
|
"ekino/phpstan-banned-code": "^v3.0.0",
|
||||||
|
"jbtronics/translation-editor-bundle": "^1.0",
|
||||||
"phpstan/extension-installer": "^1.0",
|
"phpstan/extension-installer": "^1.0",
|
||||||
"phpstan/phpstan": "^1.4.7",
|
"phpstan/phpstan": "^2.0.4",
|
||||||
"phpstan/phpstan-doctrine": "^1.2.11",
|
"phpstan/phpstan-doctrine": "^2.0.1",
|
||||||
"phpstan/phpstan-strict-rules": "^1.5",
|
"phpstan/phpstan-strict-rules": "^2.0.1",
|
||||||
"phpstan/phpstan-symfony": "^1.1.7",
|
"phpstan/phpstan-symfony": "^2.0.0",
|
||||||
"phpunit/phpunit": "^9.5",
|
"phpunit/phpunit": "^9.5",
|
||||||
"psalm/plugin-symfony": "^v5.0.1",
|
"rector/rector": "^2.0.4",
|
||||||
"rector/rector": "^0.18.0",
|
|
||||||
"roave/security-advisories": "dev-latest",
|
"roave/security-advisories": "dev-latest",
|
||||||
"symfony/browser-kit": "6.4.*",
|
"symfony/browser-kit": "6.4.*",
|
||||||
"symfony/css-selector": "6.4.*",
|
|
||||||
"symfony/debug-bundle": "6.4.*",
|
"symfony/debug-bundle": "6.4.*",
|
||||||
"symfony/maker-bundle": "^1.13",
|
"symfony/maker-bundle": "^1.13",
|
||||||
"symfony/phpunit-bridge": "6.4.*",
|
"symfony/phpunit-bridge": "6.4.*",
|
||||||
"symfony/stopwatch": "6.4.*",
|
"symfony/stopwatch": "6.4.*",
|
||||||
"symfony/web-profiler-bundle": "6.4.*",
|
"symfony/web-profiler-bundle": "6.4.*",
|
||||||
"symplify/easy-coding-standard": "^12.0",
|
"symplify/easy-coding-standard": "^12.0"
|
||||||
"vimeo/psalm": "^5.6.0"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-bcmath": "Used to improve price calculation performance",
|
"ext-bcmath": "Used to improve price calculation performance",
|
||||||
|
|
7203
composer.lock
generated
7203
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -18,7 +18,6 @@ return [
|
||||||
DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true],
|
DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true],
|
||||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||||
Gregwar\CaptchaBundle\GregwarCaptchaBundle::class => ['all' => true],
|
Gregwar\CaptchaBundle\GregwarCaptchaBundle::class => ['all' => true],
|
||||||
Translation\Bundle\TranslationBundle::class => ['all' => true],
|
|
||||||
Florianv\SwapBundle\FlorianvSwapBundle::class => ['all' => true],
|
Florianv\SwapBundle\FlorianvSwapBundle::class => ['all' => true],
|
||||||
Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
|
Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
|
||||||
Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
|
Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
|
||||||
|
@ -32,4 +31,5 @@ return [
|
||||||
KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true],
|
KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true],
|
||||||
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||||
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||||
|
Jbtronics\TranslationEditorBundle\JbtronicsTranslationEditorBundle::class => ['dev' => true],
|
||||||
];
|
];
|
||||||
|
|
|
@ -33,4 +33,9 @@ api_platform:
|
||||||
pagination_client_items_per_page: true # Allow clients to override the default items per page
|
pagination_client_items_per_page: true # Allow clients to override the default items per page
|
||||||
|
|
||||||
keep_legacy_inflector: false
|
keep_legacy_inflector: false
|
||||||
event_listeners_backward_compatibility_layer: false
|
# Need to be true, or some tests will fail
|
||||||
|
use_symfony_listeners: true
|
||||||
|
|
||||||
|
serializer:
|
||||||
|
# Change this to false later, to remove the hydra prefix on the API
|
||||||
|
hydra_prefix: true
|
|
@ -8,15 +8,14 @@ datatables:
|
||||||
|
|
||||||
# Set options, as documented at https://datatables.net/reference/option/
|
# Set options, as documented at https://datatables.net/reference/option/
|
||||||
options:
|
options:
|
||||||
lengthMenu : [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]]
|
lengthMenu : [[10, 25, 50, 100], [10, 25, 50, 100]] # We add the "All" option, when part tables are generated
|
||||||
pageLength: '%partdb.table.default_page_size%' # Set to -1 to disable pagination (i.e. show all rows) by default
|
pageLength: '%partdb.table.default_page_size%' # Set to -1 to disable pagination (i.e. show all rows) by default
|
||||||
#dom: "<'row' <'col-sm-12' tr>><'row' <'col-sm-6'l><'col-sm-6 text-right'pif>>"
|
dom: " <'row' <'col mb-2 input-group flex-nowrap' B l > <'col-auto mb-2' < p >>>
|
||||||
dom: " <'row'<'col mb-2 input-group' B l> <'col mb-2' <'pull-end' p>>>
|
<'card'
|
||||||
<'card'
|
rt
|
||||||
rt
|
<'card-footer card-footer-table text-muted' i >
|
||||||
<'card-footer card-footer-table text-muted' i >
|
>
|
||||||
>
|
<'row' <'col mt-2 input-group flex-nowrap' B l > <'col-auto mt-2' < p >>>"
|
||||||
<'row'<'col mt-2 input-group' B l> <'col mt-2' <'pull-right' p>>>"
|
|
||||||
pagingType: 'simple_numbers'
|
pagingType: 'simple_numbers'
|
||||||
searching: true
|
searching: true
|
||||||
stateSave: true
|
stateSave: true
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
translation:
|
|
||||||
symfony_profiler:
|
|
||||||
enabled: true
|
|
||||||
webui:
|
|
||||||
enabled: true
|
|
|
@ -9,14 +9,25 @@ doctrine:
|
||||||
# either here or in the DATABASE_URL env var (see .env file)
|
# either here or in the DATABASE_URL env var (see .env file)
|
||||||
|
|
||||||
types:
|
types:
|
||||||
|
# UTC datetimes
|
||||||
datetime:
|
datetime:
|
||||||
class: App\Doctrine\Types\UTCDateTimeType
|
class: App\Doctrine\Types\UTCDateTimeType
|
||||||
date:
|
date:
|
||||||
class: App\Doctrine\Types\UTCDateTimeType
|
class: App\Doctrine\Types\UTCDateTimeType
|
||||||
|
|
||||||
|
datetime_immutable:
|
||||||
|
class: App\Doctrine\Types\UTCDateTimeImmutableType
|
||||||
|
date_immutable:
|
||||||
|
class: App\Doctrine\Types\UTCDateTimeImmutableType
|
||||||
|
|
||||||
big_decimal:
|
big_decimal:
|
||||||
class: App\Doctrine\Types\BigDecimalType
|
class: App\Doctrine\Types\BigDecimalType
|
||||||
tinyint:
|
tinyint:
|
||||||
class: App\Doctrine\Types\TinyIntType
|
class: App\Doctrine\Types\TinyIntType
|
||||||
|
|
||||||
|
# This was removed in doctrine/orm 4.0 but we need it for the WebauthnKey entity
|
||||||
|
array:
|
||||||
|
class: App\Doctrine\Types\ArrayType
|
||||||
|
|
||||||
schema_filter: ~^(?!internal)~
|
schema_filter: ~^(?!internal)~
|
||||||
# Only enable this when needed
|
# Only enable this when needed
|
||||||
|
@ -29,6 +40,8 @@ doctrine:
|
||||||
validate_xml_mapping: true
|
validate_xml_mapping: true
|
||||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||||
auto_mapping: true
|
auto_mapping: true
|
||||||
|
controller_resolver:
|
||||||
|
auto_mapping: true
|
||||||
mappings:
|
mappings:
|
||||||
App:
|
App:
|
||||||
type: attribute
|
type: attribute
|
||||||
|
@ -39,10 +52,12 @@ doctrine:
|
||||||
|
|
||||||
dql:
|
dql:
|
||||||
string_functions:
|
string_functions:
|
||||||
regexp: DoctrineExtensions\Query\Mysql\Regexp
|
regexp: App\Doctrine\Functions\Regexp
|
||||||
ifnull: DoctrineExtensions\Query\Mysql\IfNull
|
|
||||||
field: DoctrineExtensions\Query\Mysql\Field
|
field: DoctrineExtensions\Query\Mysql\Field
|
||||||
field2: App\Doctrine\Functions\Field2
|
field2: App\Doctrine\Functions\Field2
|
||||||
|
natsort: App\Doctrine\Functions\Natsort
|
||||||
|
array_position: App\Doctrine\Functions\ArrayPosition
|
||||||
|
ilike: App\Doctrine\Functions\ILike
|
||||||
|
|
||||||
when@test:
|
when@test:
|
||||||
doctrine:
|
doctrine:
|
||||||
|
|
|
@ -50,7 +50,6 @@ when@prod:
|
||||||
type: stream
|
type: stream
|
||||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
level: debug
|
level: debug
|
||||||
formatter: monolog.formatter.json
|
|
||||||
console:
|
console:
|
||||||
type: console
|
type: console
|
||||||
process_psr_3_messages: false
|
process_psr_3_messages: false
|
||||||
|
@ -74,7 +73,6 @@ when@docker:
|
||||||
type: stream
|
type: stream
|
||||||
path: "php://stderr"
|
path: "php://stderr"
|
||||||
level: debug
|
level: debug
|
||||||
formatter: monolog.formatter.json
|
|
||||||
console:
|
console:
|
||||||
type: console
|
type: console
|
||||||
process_psr_3_messages: false
|
process_psr_3_messages: false
|
||||||
|
|
|
@ -51,12 +51,16 @@ nelmio_security:
|
||||||
img-src:
|
img-src:
|
||||||
- '*'
|
- '*'
|
||||||
- 'data:'
|
- 'data:'
|
||||||
|
# Required for be able to load pictures in the QR code scanner
|
||||||
|
- 'blob:'
|
||||||
style-src:
|
style-src:
|
||||||
- 'self'
|
- 'self'
|
||||||
- 'unsafe-inline'
|
- 'unsafe-inline'
|
||||||
- 'data:'
|
- 'data:'
|
||||||
script-src:
|
script-src:
|
||||||
- 'self'
|
- 'self'
|
||||||
|
# Required for loading the Wasm for the barcode scanner:
|
||||||
|
- 'wasm-unsafe-eval'
|
||||||
object-src:
|
object-src:
|
||||||
- 'self'
|
- 'self'
|
||||||
- 'data:'
|
- 'data:'
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
translation:
|
|
||||||
locales: ["en", "de"]
|
|
||||||
edit_in_place:
|
|
||||||
enabled: false
|
|
||||||
config_name: app
|
|
||||||
configs:
|
|
||||||
app:
|
|
||||||
dirs: ["%kernel.project_dir%/templates", "%kernel.project_dir%/src"]
|
|
||||||
output_dir: "%kernel.project_dir%/translations"
|
|
||||||
excluded_names: ["*TestCase.php", "*Test.php"]
|
|
||||||
excluded_dirs: [cache, data, logs]
|
|
|
@ -11,11 +11,13 @@ parameters:
|
||||||
partdb.banner: '%env(trim:string:BANNER)%' # The info text shown in the homepage, if empty config/banner.md is used
|
partdb.banner: '%env(trim:string:BANNER)%' # The info text shown in the homepage, if empty config/banner.md is used
|
||||||
partdb.default_currency: '%env(string:BASE_CURRENCY)%' # The currency that is used inside the DB (and is assumed when no currency is set). This can not be changed later, so be sure to set it the currency used in your country
|
partdb.default_currency: '%env(string:BASE_CURRENCY)%' # The currency that is used inside the DB (and is assumed when no currency is set). This can not be changed later, so be sure to set it the currency used in your country
|
||||||
partdb.global_theme: '' # The theme to use globally (see public/build/themes/ for choices, use name without .css). Set to '' for default bootstrap theme
|
partdb.global_theme: '' # The theme to use globally (see public/build/themes/ for choices, use name without .css). Set to '' for default bootstrap theme
|
||||||
partdb.locale_menu: ['en', 'de', 'it', 'fr', 'ru', 'ja', 'cs', 'da', 'zh'] # The languages that are shown in user drop down menu
|
partdb.locale_menu: ['en', 'de', 'it', 'fr', 'ru', 'ja', 'cs', 'da', 'zh', 'pl'] # The languages that are shown in user drop down menu
|
||||||
partdb.enforce_change_comments_for: '%env(csv:ENFORCE_CHANGE_COMMENTS_FOR)%' # The actions for which a change comment is required (e.g. "part_edit", "part_create", etc.). If this is empty, change comments are not required at all.
|
partdb.enforce_change_comments_for: '%env(csv:ENFORCE_CHANGE_COMMENTS_FOR)%' # The actions for which a change comment is required (e.g. "part_edit", "part_create", etc.). If this is empty, change comments are not required at all.
|
||||||
|
|
||||||
partdb.default_uri: '%env(string:DEFAULT_URI)%' # The default URI to use for the Part-DB instance (e.g. https://part-db.example.com/). This is used for generating links in emails
|
partdb.default_uri: '%env(string:DEFAULT_URI)%' # The default URI to use for the Part-DB instance (e.g. https://part-db.example.com/). This is used for generating links in emails
|
||||||
|
|
||||||
|
partdb.db.emulate_natural_sort: '%env(bool:DATABASE_EMULATE_NATURAL_SORT)%' # If this is set to true, natural sorting is emulated on platforms that do not support it natively. This can be slow on large datasets.
|
||||||
|
|
||||||
######################################################################################################################
|
######################################################################################################################
|
||||||
# Users and Privacy
|
# Users and Privacy
|
||||||
######################################################################################################################
|
######################################################################################################################
|
||||||
|
@ -145,3 +147,5 @@ parameters:
|
||||||
env(HISTORY_SAVE_NEW_DATA): 1
|
env(HISTORY_SAVE_NEW_DATA): 1
|
||||||
|
|
||||||
env(EDA_KICAD_CATEGORY_DEPTH): 0
|
env(EDA_KICAD_CATEGORY_DEPTH): 0
|
||||||
|
|
||||||
|
env(DATABASE_EMULATE_NATURAL_SORT): 0
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
_translation_webui:
|
|
||||||
resource: '@TranslationBundle/Resources/config/routing_webui.yaml'
|
|
||||||
prefix: /admin
|
|
||||||
|
|
||||||
_translation_profiler:
|
|
||||||
resource: '@TranslationBundle/Resources/config/routing_symfony_profiler.yaml'
|
|
3
config/routes/jbtronics_translation_editor.yaml
Normal file
3
config/routes/jbtronics_translation_editor.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
when@dev:
|
||||||
|
translation_editor:
|
||||||
|
resource: '@JbtronicsTranslationEditorBundle/config/routes.php'
|
|
@ -1,3 +0,0 @@
|
||||||
_translation_edit_in_place:
|
|
||||||
resource: '@TranslationBundle/Resources/config/routing_edit_in_place.yaml'
|
|
||||||
prefix: /admin
|
|
|
@ -76,18 +76,12 @@ services:
|
||||||
# Only the event classes specified here are saved to DB (set to []) to log all events
|
# Only the event classes specified here are saved to DB (set to []) to log all events
|
||||||
$whitelist: []
|
$whitelist: []
|
||||||
|
|
||||||
App\EventSubscriber\LogSystem\EventLoggerSubscriber:
|
App\EventListener\LogSystem\EventLoggerListener:
|
||||||
arguments:
|
arguments:
|
||||||
$save_changed_fields: '%env(bool:HISTORY_SAVE_CHANGED_FIELDS)%'
|
$save_changed_fields: '%env(bool:HISTORY_SAVE_CHANGED_FIELDS)%'
|
||||||
$save_changed_data: '%env(bool:HISTORY_SAVE_CHANGED_DATA)%'
|
$save_changed_data: '%env(bool:HISTORY_SAVE_CHANGED_DATA)%'
|
||||||
$save_removed_data: '%env(bool:HISTORY_SAVE_REMOVED_DATA)%'
|
$save_removed_data: '%env(bool:HISTORY_SAVE_REMOVED_DATA)%'
|
||||||
$save_new_data: '%env(bool:HISTORY_SAVE_NEW_DATA)%'
|
$save_new_data: '%env(bool:HISTORY_SAVE_NEW_DATA)%'
|
||||||
tags:
|
|
||||||
- { name: 'doctrine.event_subscriber' }
|
|
||||||
|
|
||||||
App\EventSubscriber\LogSystem\LogDBMigrationSubscriber:
|
|
||||||
tags:
|
|
||||||
- { name: 'doctrine.event_subscriber' }
|
|
||||||
|
|
||||||
App\Form\AttachmentFormType:
|
App\Form\AttachmentFormType:
|
||||||
arguments:
|
arguments:
|
||||||
|
@ -312,6 +306,16 @@ services:
|
||||||
$enabled: '%env(bool:PROVIDER_LCSC_ENABLED)%'
|
$enabled: '%env(bool:PROVIDER_LCSC_ENABLED)%'
|
||||||
$currency: '%env(string:PROVIDER_LCSC_CURRENCY)%'
|
$currency: '%env(string:PROVIDER_LCSC_CURRENCY)%'
|
||||||
|
|
||||||
|
App\Services\InfoProviderSystem\Providers\OEMSecretsProvider:
|
||||||
|
arguments:
|
||||||
|
$api_key: '%env(string:PROVIDER_OEMSECRETS_KEY)%'
|
||||||
|
$country_code: '%env(string:PROVIDER_OEMSECRETS_COUNTRY_CODE)%'
|
||||||
|
$currency: '%env(PROVIDER_OEMSECRETS_CURRENCY)%'
|
||||||
|
$zero_price: '%env(PROVIDER_OEMSECRETS_ZERO_PRICE)%'
|
||||||
|
$set_param: '%env(PROVIDER_OEMSECRETS_SET_PARAM)%'
|
||||||
|
$sort_criteria: '%env(PROVIDER_OEMSECRETS_SORT_CRITERIA)%'
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
# API system
|
# API system
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
|
@ -406,4 +410,4 @@ when@test:
|
||||||
arguments:
|
arguments:
|
||||||
- '@doctrine.fixtures.loader'
|
- '@doctrine.fixtures.loader'
|
||||||
- '@doctrine'
|
- '@doctrine'
|
||||||
- { default: '@App\Doctrine\Purger\DoNotUsePurgerFactory' }
|
- { default: '@App\Doctrine\Purger\DoNotUsePurgerFactory' }
|
||||||
|
|
|
@ -23,7 +23,7 @@ each other so that it does not matter which one of your 1000 things of Part you
|
||||||
A part entity has many fields, which can be used to describe it better. Most of the fields are optional:
|
A part entity has many fields, which can be used to describe it better. Most of the fields are optional:
|
||||||
|
|
||||||
* **Name** (Required): The name of the part or how you want to call it. This could be a manufacturer-provided name, or a
|
* **Name** (Required): The name of the part or how you want to call it. This could be a manufacturer-provided name, or a
|
||||||
name you thought of yourself. The name have to be unique in a single category.
|
name you thought of yourself. Each name needs to be unique and must exist in a single category.
|
||||||
* **Description**: A short (single-line) description of what this part is/does. For longer information, you should use
|
* **Description**: A short (single-line) description of what this part is/does. For longer information, you should use
|
||||||
the comment field or the specifications
|
the comment field or the specifications
|
||||||
* **Category** (Required): The category (see there) to which this part belongs to.
|
* **Category** (Required): The category (see there) to which this part belongs to.
|
||||||
|
@ -239,4 +239,4 @@ replaced with data for the actual thing.
|
||||||
|
|
||||||
You do not have to define a label profile to generate labels (you can just set the settings on the fly in the label
|
You do not have to define a label profile to generate labels (you can just set the settings on the fly in the label
|
||||||
dialog), however, if you want to generate many labels, it is recommended to save the settings as a label profile, to save
|
dialog), however, if you want to generate many labels, it is recommended to save the settings as a label profile, to save
|
||||||
it for later usage. This ensures that all generated labels look the same.
|
it for later usage. This ensures that all generated labels look the same.
|
||||||
|
|
|
@ -32,14 +32,22 @@ options listed, see `.env` file for the full list of possible env variables.
|
||||||
|
|
||||||
### General options
|
### General options
|
||||||
|
|
||||||
* `DATABASE_URL`: Configures the database which Part-DB uses. For mysql use a string in the form
|
* `DATABASE_URL`: Configures the database which Part-DB uses:
|
||||||
of `mysql://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<TABLE_NAME>` here
|
* For MySQL (or MariaDB) use a string in the form of `mysql://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<TABLE_NAME>` here
|
||||||
(e.g. `DATABASE_URL=mysql://user:password@127.0.0.1:3306/part-db`). For SQLite use the following format to specify the
|
(e.g. `DATABASE_URL=mysql://user:password@127.0.0.1:3306/part-db`).
|
||||||
|
* For SQLite use the following format to specify the
|
||||||
absolute path where it should be located `sqlite:///path/part/app.db`. You can use `%kernel.project_dir%` as
|
absolute path where it should be located `sqlite:///path/part/app.db`. You can use `%kernel.project_dir%` as
|
||||||
placeholder for the Part-DB root folder (e.g. `sqlite:///%kernel.project_dir%/var/app.db`)
|
placeholder for the Part-DB root folder (e.g. `sqlite:///%kernel.project_dir%/var/app.db`)
|
||||||
|
* For Postgresql use a string in the form of `DATABASE_URL=postgresql://user:password@127.0.0.1:5432/part-db?serverVersion=x.y`.
|
||||||
|
|
||||||
|
Please note that **`serverVersion=x.y`** variable is required due to dependency of Symfony framework.
|
||||||
|
|
||||||
* `DATABASE_MYSQL_USE_SSL_CA`: If this value is set to `1` or `true` and a MySQL connection is used, then the connection
|
* `DATABASE_MYSQL_USE_SSL_CA`: If this value is set to `1` or `true` and a MySQL connection is used, then the connection
|
||||||
is encrypted by SSL/TLS and the server certificate is verified against the system CA certificates or the CA certificate
|
is encrypted by SSL/TLS and the server certificate is verified against the system CA certificates or the CA certificate
|
||||||
bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept all certificates.
|
bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept all certificates.
|
||||||
|
* `DATABASE_EMULATE_NATURAL_SORT` (default 0): If set to 1, Part-DB will emulate natural sorting, even if the database
|
||||||
|
does not support it natively. However this is much slower than the native sorting, and contain bugs or quirks, so use
|
||||||
|
it only, if you have to.
|
||||||
* `DEFAULT_LANG`: The default language to use server-wide (when no language is explicitly specified by a user or via
|
* `DEFAULT_LANG`: The default language to use server-wide (when no language is explicitly specified by a user or via
|
||||||
language chooser). Must be something like `en`, `de`, `fr`, etc.
|
language chooser). Must be something like `en`, `de`, `fr`, etc.
|
||||||
* `DEFAULT_TIMEZONE`: The default timezone to use globally, when a user has no timezone specified. Must be something
|
* `DEFAULT_TIMEZONE`: The default timezone to use globally, when a user has no timezone specified. Must be something
|
||||||
|
@ -83,6 +91,10 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
||||||
* `datastructure_create`: Creation of a new datastructure (e.g. category, manufacturer, ...)
|
* `datastructure_create`: Creation of a new datastructure (e.g. category, manufacturer, ...)
|
||||||
* `CHECK_FOR_UPDATES` (default `1`): Set this to 0, if you do not want Part-DB to connect to GitHub to check for new
|
* `CHECK_FOR_UPDATES` (default `1`): Set this to 0, if you do not want Part-DB to connect to GitHub to check for new
|
||||||
versions, or if your server can not connect to the internet.
|
versions, or if your server can not connect to the internet.
|
||||||
|
* `APP_SECRET`: This variable is a configuration parameter used for various security-related purposes,
|
||||||
|
particularly for securing and protecting various aspects of your application. It's a secret key that is used for
|
||||||
|
cryptographic operations and security measures (session management, CSRF protection, etc..). Therefore this
|
||||||
|
value should be handled as confidential data and not shared publicly.
|
||||||
|
|
||||||
### E-Mail settings
|
### E-Mail settings
|
||||||
|
|
||||||
|
@ -240,4 +252,4 @@ The following options are available:
|
||||||
number of sidebar panels by changing the number of items in this list.
|
number of sidebar panels by changing the number of items in this list.
|
||||||
* `partdb.sidebar.root_node_enable`: Show a root node in the sidebar trees, of which all nodes are children of
|
* `partdb.sidebar.root_node_enable`: Show a root node in the sidebar trees, of which all nodes are children of
|
||||||
* `partdb.sidebar.root_expanded`: Expand the root node in the sidebar trees by default
|
* `partdb.sidebar.root_expanded`: Expand the root node in the sidebar trees by default
|
||||||
* `partdb.available_themes`: The list of available themes a user can choose from.
|
* `partdb.available_themes`: The list of available themes a user can choose from.
|
||||||
|
|
|
@ -41,7 +41,7 @@ It is installed on a web server and so can be accessed with any browser without
|
||||||
* Event log: Track what changes happens to your inventory, track which user does what. Revert your parts to older
|
* Event log: Track what changes happens to your inventory, track which user does what. Revert your parts to older
|
||||||
versions.
|
versions.
|
||||||
* Responsive design: You can use Part-DB on your PC, your tablet and your smartphone using the same interface.
|
* Responsive design: You can use Part-DB on your PC, your tablet and your smartphone using the same interface.
|
||||||
* MySQL and SQLite supported as database backends
|
* MySQL, SQLite and PostgreSQL are supported as database backends
|
||||||
* Support for rich text descriptions and comments in parts
|
* Support for rich text descriptions and comments in parts
|
||||||
* Support for multiple currencies and automatic update of exchange rates supported
|
* Support for multiple currencies and automatic update of exchange rates supported
|
||||||
* Powerful search and filter function, including parametric search (search for parts according to some specifications)
|
* Powerful search and filter function, including parametric search (search for parts according to some specifications)
|
||||||
|
|
|
@ -7,10 +7,18 @@ nav_order: 1
|
||||||
|
|
||||||
# Choosing database: SQLite or MySQL
|
# Choosing database: SQLite or MySQL
|
||||||
|
|
||||||
Part-DB saves its data in a [relational (SQL) database](https://en.wikipedia.org/wiki/Relational_database). Part-DB
|
Part-DB saves its data in a [relational (SQL) database](https://en.wikipedia.org/wiki/Relational_database).
|
||||||
supports either the use of [SQLite](https://www.sqlite.org/index.html)
|
|
||||||
or [MySQL](https://www.mysql.com/) / [MariaDB](https://mariadb.org/) (which are mostly the same, except for some minor
|
For this multiple database types are supported, currently these are:
|
||||||
differences).
|
|
||||||
|
* [SQLite](https://www.sqlite.org/index.html)
|
||||||
|
* [MySQL](https://www.mysql.com/) / [MariaDB](https://mariadb.org/) (which are mostly the same, except for some minor
|
||||||
|
differences)
|
||||||
|
* [PostgreSQL](https://www.postgresql.org/)
|
||||||
|
|
||||||
|
All these database types allow for the same basic functionality and allow Part-DB to run. However, there are some minor
|
||||||
|
differences between them, which might be important for you. Therefore the pros and cons of the different database types
|
||||||
|
are listed here.
|
||||||
|
|
||||||
{: .important }
|
{: .important }
|
||||||
You have to choose between the database types before you start using Part-DB and **you can not change it (easily) after
|
You have to choose between the database types before you start using Part-DB and **you can not change it (easily) after
|
||||||
|
@ -18,29 +26,157 @@ you have started creating data**. So you should choose the database type for you
|
||||||
|
|
||||||
## Comparison
|
## Comparison
|
||||||
|
|
||||||
**SQLite** is the default database type which is configured out of the box. All data is saved in a single file (
|
### SQLite
|
||||||
normally `var/app.db` in the Part-DB folder) and no additional installation or configuration besides Part-DB is needed.
|
|
||||||
To use **MySQL/MariaDB** as database, you have to install and configure the MySQL server, configure it and create a
|
|
||||||
database and user for Part-DB, which needs some additional work. When using docker you need an additional docker
|
|
||||||
container, and volume for the data
|
|
||||||
|
|
||||||
When using **SQLite** The database can be backuped easily by just copying the SQLite file to a safe place. Ideally, the *
|
#### Pros
|
||||||
*MySQL** database has to be dumped to a SQL file (using `mysqldump`). The `console partdb:backup` command can do this
|
|
||||||
automatically
|
|
||||||
|
|
||||||
However, SQLite does not support certain operations like regex search, which has to be emulated by PHP and therefore is
|
* **Easy to use**: No additional installation or configuration is needed, just start Part-DB and it will work out of the box
|
||||||
pretty slow compared to the same operation at MySQL. In the future, there might be features that may only be available, when
|
* **Easy backup**: Just copy the SQLite file to a safe place, and you have a backup, which you can restore by copying it
|
||||||
using MySQL. Also, SQLite has limitations in comparisons and sorting of Unicode characters, which might lead to unexpected
|
back. No need to work with SQL dumps
|
||||||
behavior when using non-ASCII characters in your data. For example `µ` (micro sign) is not seen as equal to `μ(greek minuscule mu),
|
|
||||||
therefore searching for `µ` (micro sign) will not find parts containing `μ` (mu) and vice versa. In MySQL identical-looking characters are seen as equal, which is more intuitive in most cases.
|
|
||||||
|
|
||||||
In general MySQL might perform better for big Part-DB instances with many entries, lots of users and high activity, than
|
#### Cons
|
||||||
SQLite.
|
|
||||||
|
|
||||||
## Conclusion and Suggestion
|
* **Performance**: SQLite is not as fast as MySQL or PostgreSQL, especially when using complex queries or many users.
|
||||||
|
* **Emulated RegEx search**: SQLite does not support RegEx search natively. Part-DB can emulate it, however that is pretty slow.
|
||||||
|
* **Emualted natural sorting**: SQLite does not support natural sorting natively. Part-DB can emulate it, but it is pretty slow.
|
||||||
|
* **Limitations with Unicode**: SQLite has limitations in comparisons and sorting of Unicode characters, which might lead to
|
||||||
|
unexpected behavior when using non-ASCII characters in your data. For example `µ` (micro sign) is not seen as equal to
|
||||||
|
`μ` (greek minuscule mu), therefore searching for `µ` (micro sign) will not find parts containing `μ` (mu) and vice versa.
|
||||||
|
The other databases behave more intuitive in this case.
|
||||||
|
* **No advanced features**: SQLite do no support many of the advanced features of MySQL or PostgreSQL, which might be utilized
|
||||||
|
in future versions of Part-DB
|
||||||
|
|
||||||
|
|
||||||
|
### MySQL/MariaDB
|
||||||
|
|
||||||
|
**If possible, it is recommended to use MariaDB 10.7+ (instead of MySQL), as it supports natural sorting of columns natively.**
|
||||||
|
|
||||||
|
#### Pros
|
||||||
|
|
||||||
|
* **Performance**: Compared to SQLite, MySQL/MariaDB will probably perform better, especially in large databases with many
|
||||||
|
users and high activity.
|
||||||
|
* **Natural Sorting**: MariaDB 10.7+ supports natural sorting of columns. On other databases it has to be emulated, which is pretty
|
||||||
|
slow.
|
||||||
|
* **Native RegEx search**: MySQL supports RegEx search natively, which is faster than emulating it in PHP.
|
||||||
|
* **Advanced features**: MySQL/MariaDB supports many advanced features, which might be utilized in future versions of Part-DB.
|
||||||
|
* **Full Unicode support**: MySQL/MariaDB has better support for Unicode characters, which makes it more intuitive to use
|
||||||
|
non-ASCII characters in your data.
|
||||||
|
|
||||||
|
#### Cons
|
||||||
|
|
||||||
|
* **Additional installation and configuration**: You have to install and configure the MySQL server, create a database and
|
||||||
|
user for Part-DB, which needs some additional work compared to SQLite.
|
||||||
|
* **Backup**: The MySQL database has to be dumped to a SQL file (using `mysqldump`). The `console partdb:backup` command can automate this.
|
||||||
|
|
||||||
|
|
||||||
|
### PostgreSQL
|
||||||
|
|
||||||
|
#### Pros
|
||||||
|
* **Performance**: PostgreSQL is known for its performance, especially in large databases with many users and high activity.
|
||||||
|
* **Advanced features**: PostgreSQL supports many advanced features, which might be utilized in future versions of Part-DB.
|
||||||
|
* **Full Unicode support**: PostgreSQL has better support for Unicode characters, which makes it more intuitive to use
|
||||||
|
non-ASCII characters in your data.
|
||||||
|
* **Native RegEx search**: PostgreSQL supports RegEx search natively, which is faster than emulating it in PHP.
|
||||||
|
* **Native Natural Sorting**: PostgreSQL supports natural sorting of columns natively in all versions and in general the support for it
|
||||||
|
is better than on MariaDB.
|
||||||
|
* **Support of transactional DDL**: PostgreSQL supports transactional DDL, which means that if you encounter a problem during a schema change,
|
||||||
|
the database will automatically rollback the changes. On MySQL/MariaDB you have to manually rollback the changes, by restoring from a database backup.
|
||||||
|
|
||||||
|
#### Cons
|
||||||
|
* **New backend**: The support of postgresql is new, and it was not tested as much as the other backends. There might be some bugs caused by this.
|
||||||
|
* **Additional installation and configuration**: You have to install and configure the PostgreSQL server, create a database and
|
||||||
|
user for Part-DB, which needs some additional work compared to SQLite.
|
||||||
|
* **Backup**: The PostgreSQL database has to be dumped to a SQL file (using `pg_dump`). The `console partdb:backup` command can automate this.
|
||||||
|
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
When you are a hobbyist and use Part-DB for your own small inventory management with only you as user (or maybe sometimes
|
When you are a hobbyist and use Part-DB for your own small inventory management with only you as user (or maybe sometimes
|
||||||
a few other people), then the easy-to-use SQLite database will be fine.
|
a few other people), then the easy-to-use SQLite database will be fine, as long as you can live with the limitations, stated above.
|
||||||
|
However using MariaDB (or PostgreSQL), has no disadvantages in that situation (besides the initial setup requirements), so you might
|
||||||
|
want to use it, to be prepared for future use cases.
|
||||||
|
|
||||||
When you are planning to have a very big database, with a lot of entries and many users which regularly (and
|
When you are planning to have a very big database, with a lot of entries and many users which regularly using Part-DB, then you should
|
||||||
concurrently) using Part-DB you should maybe use MySQL as this will scale better.
|
use MariaDB or PostgreSQL, as they will perform better in that situation and allow for more advanced features.
|
||||||
|
If you should use MariaDB or PostgreSQL depends on your personal preference and what you already have installed on your servers and
|
||||||
|
what you are familiar with.
|
||||||
|
|
||||||
|
## Using the different databases
|
||||||
|
|
||||||
|
The only difference in using the different databases, is a different value in the `DATABASE_URL` environment variable in the `.env.local` file
|
||||||
|
or in the `DATABASE_URL` environment variable in your server or container configuration. It has the shape of a URL, where the scheme (the part before `://`)
|
||||||
|
is the database type, and the rest is connection information.
|
||||||
|
|
||||||
|
**The env var format below is for the `env.local` file. It might work differently for other env configuration. E.g. in a docker-compose file you have to remove the quotes!**
|
||||||
|
|
||||||
|
### SQLite
|
||||||
|
|
||||||
|
```shell
|
||||||
|
DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db"
|
||||||
|
```
|
||||||
|
|
||||||
|
Here you just need to configure the path to the SQLite file, which is created by Part-DB when performing the database migrations.
|
||||||
|
The `%kernel.project_dir%` is a placeholder for the path to the project directory, which is replaced by the actual path by Symfony, so that you do not
|
||||||
|
need to specify the path manually. In the example the database will be created as `app.db` in the `var` directory of your Part-DB installation folder.
|
||||||
|
|
||||||
|
### MySQL/MariaDB
|
||||||
|
|
||||||
|
```shell
|
||||||
|
DATABASE_URL="mysql://user:password@127.0.0.1:3306/database?serverVersion=8.0.37"
|
||||||
|
```
|
||||||
|
|
||||||
|
Here you have to replace `user`, `password` and `database` with the credentials of the MySQL/MariaDB user and the database name you want to use.
|
||||||
|
The host (here 127.0.0.1) and port should also be specified according to your MySQL/MariaDB server configuration.
|
||||||
|
|
||||||
|
In the `serverVersion` parameter you can specify the version of the MySQL/MariaDB server you are using, in the way the server returns it
|
||||||
|
(e.g. `8.0.37` for MySQL and `10.4.14-MariaDB`). If you do not know it, you can leave the default value.
|
||||||
|
|
||||||
|
If you want to use a unix socket for the connection instead of a TCP connnection, you can specify the socket path in the `unix_socket` parameter.
|
||||||
|
```shell
|
||||||
|
DATABASE_URL="mysql://user:password@localhost/database?serverVersion=8.0.37&unix_socket=/var/run/mysqld/mysqld.sock"
|
||||||
|
```
|
||||||
|
|
||||||
|
### PostgreSQL
|
||||||
|
|
||||||
|
```shell
|
||||||
|
DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=12.19&charset=utf8"
|
||||||
|
```
|
||||||
|
|
||||||
|
Here you have to replace `db_user`, `db_password` and `db_name` with the credentials of the PostgreSQL user and the database name you want to use.
|
||||||
|
The host (here 127.0.0.1) and port should also be specified according to your PostgreSQL server configuration.
|
||||||
|
|
||||||
|
In the `serverVersion` parameter you can specify the version of the PostgreSQL server you are using, in the way the server returns it
|
||||||
|
(e.g. `12.19 (Debian 12.19-1.pgdg120+1)`). If you do not know it, you can leave the default value.
|
||||||
|
|
||||||
|
The `charset` parameter specify the character set of the database. It should be set to `utf8` to ensure that all characters are stored correctly.
|
||||||
|
|
||||||
|
If you want to use a unix socket for the connection instead of a TCP connnection, you can specify the socket path in the `host` parameter.
|
||||||
|
```shell
|
||||||
|
DATABASE_URL="postgresql://db_user@localhost/db_name?serverVersion=16.6&charset=utf8&host=/var/run/postgresql"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Natural Sorting
|
||||||
|
|
||||||
|
Natural sorting is the sorting of strings in a way that numbers are sorted by their numerical value, not by their ASCII value.
|
||||||
|
|
||||||
|
For example in the classical binary sorting the string `DIP-4`, `DIP-8`, `DIP-16`, `DIP-28` would be sorted as following:
|
||||||
|
|
||||||
|
* `DIP-16`
|
||||||
|
* `DIP-28`
|
||||||
|
* `DIP-4`
|
||||||
|
* `DIP-8`
|
||||||
|
|
||||||
|
In natural sorting, it would be sorted as:
|
||||||
|
|
||||||
|
* `DIP-4`
|
||||||
|
* `DIP-8`
|
||||||
|
* `DIP-16`
|
||||||
|
* `DIP-28`
|
||||||
|
|
||||||
|
Part-DB can sort names in part tables and tree views naturally. PostgreSQL and MariaDB 10.7+ support natural sorting natively,
|
||||||
|
and it is automatically used if available.
|
||||||
|
|
||||||
|
For SQLite and MySQL < 10.7 it has to be emulated if wanted, which is pretty slow. Therefore it has to be explicity enabled by setting the
|
||||||
|
`DATABASE_EMULATE_NATURAL_SORT` environment variable to `1`. If it is 0 the classical binary sorting is used, on these databases. The emulations
|
||||||
|
might have some quirks and issues, so it is recommended to use a database which supports natural sorting natively, if you want to use it.
|
||||||
|
|
|
@ -6,4 +6,6 @@ has_children: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
Below you can find some guides to install Part-DB.
|
Below you can find some guides to install Part-DB.
|
||||||
|
|
||||||
|
For the hobbyists without much experience, we recommend the docker installation or direct installation on debian.
|
|
@ -47,6 +47,12 @@ services:
|
||||||
- DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db
|
- DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db
|
||||||
# In docker env logs will be redirected to stderr
|
# In docker env logs will be redirected to stderr
|
||||||
- APP_ENV=docker
|
- APP_ENV=docker
|
||||||
|
|
||||||
|
# Uncomment this, if you want to use the automatic database migration feature. With this you have you do not have to
|
||||||
|
# run the doctrine:migrations:migrate commands on installation or upgrade. A database backup is written to the uploads/
|
||||||
|
# folder (under .automigration-backup), so you can restore it, if the migration fails.
|
||||||
|
# This feature is currently experimental, so use it at your own risk!
|
||||||
|
# - DB_AUTOMIGRATE=true
|
||||||
|
|
||||||
# You can configure Part-DB using environment variables
|
# You can configure Part-DB using environment variables
|
||||||
# Below you can find the most essential ones predefined
|
# Below you can find the most essential ones predefined
|
||||||
|
@ -130,6 +136,12 @@ services:
|
||||||
# In docker env logs will be redirected to stderr
|
# In docker env logs will be redirected to stderr
|
||||||
- APP_ENV=docker
|
- APP_ENV=docker
|
||||||
|
|
||||||
|
# Uncomment this, if you want to use the automatic database migration feature. With this you have you do not have to
|
||||||
|
# run the doctrine:migrations:migrate commands on installation or upgrade. A database backup is written to the uploads/
|
||||||
|
# folder (under .automigration-backup), so you can restore it, if the migration fails.
|
||||||
|
# This feature is currently experimental, so use it at your own risk!
|
||||||
|
# - DB_AUTOMIGRATE=true
|
||||||
|
|
||||||
# You can configure Part-DB using environment variables
|
# You can configure Part-DB using environment variables
|
||||||
# Below you can find the most essential ones predefined
|
# Below you can find the most essential ones predefined
|
||||||
# However you can add add any other environment configuration you want here
|
# However you can add add any other environment configuration you want here
|
||||||
|
@ -158,7 +170,7 @@ services:
|
||||||
container_name: partdb_database
|
container_name: partdb_database
|
||||||
image: mysql:8.0
|
image: mysql:8.0
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
command: --default-authentication-plugin=mysql_native_password --log-bin-trust-function-creators=1
|
||||||
environment:
|
environment:
|
||||||
# Change this Password
|
# Change this Password
|
||||||
MYSQL_ROOT_PASSWORD: SECRET_ROOT_PASSWORD
|
MYSQL_ROOT_PASSWORD: SECRET_ROOT_PASSWORD
|
||||||
|
@ -201,6 +213,10 @@ You also have to create the database as described above in step 4.
|
||||||
You can run the console commands described in README by
|
You can run the console commands described in README by
|
||||||
executing `docker exec --user=www-data -it partdb bin/console [command]`
|
executing `docker exec --user=www-data -it partdb bin/console [command]`
|
||||||
|
|
||||||
|
{: .warning }
|
||||||
|
> If you run a root console inside the container, and wanna execute commands on the webserver behalf, be sure to use `sudo -E` command (with the `-E` flag) to preserve env variables from the current shell.
|
||||||
|
> Otherwise Part-DB console might use the wrong configuration to execute commands.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
*Login is not possible. Login page is just reloading and no error message is shown or something like "CSFR token invalid"*:
|
*Login is not possible. Login page is just reloading and no error message is shown or something like "CSFR token invalid"*:
|
||||||
|
|
42
docs/installation/kubernetes.md
Normal file
42
docs/installation/kubernetes.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
title: Kubernetes / Helm
|
||||||
|
layout: default
|
||||||
|
parent: Installation
|
||||||
|
nav_order: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
# Kubernetes / Helm Charts
|
||||||
|
|
||||||
|
If you are using Kubernetes, you can use the [helm charts](https://helm.sh/) provided in this [repository](https://github.com/Part-DB/helm-charts).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
[Helm](https://helm.sh) must be installed to use the charts. Please refer to
|
||||||
|
Helm's [documentation](https://helm.sh/docs) to get started.
|
||||||
|
|
||||||
|
Once Helm has been set up correctly, add the repo as follows:
|
||||||
|
|
||||||
|
`helm repo add part-db https://part-db.github.io/helm-charts`
|
||||||
|
|
||||||
|
If you had already added this repo earlier, run `helm repo update` to retrieve
|
||||||
|
the latest versions of the packages. You can then run `helm search repo
|
||||||
|
part-db` to see the charts.
|
||||||
|
|
||||||
|
To install the part-db chart:
|
||||||
|
|
||||||
|
helm install my-part-db part-db/part-db
|
||||||
|
|
||||||
|
To uninstall the chart:
|
||||||
|
|
||||||
|
helm delete my-part-db
|
||||||
|
|
||||||
|
This repository is also available at [ArtifactHUB](https://artifacthub.io/packages/search?repo=part-db).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
See the README in the [chart directory](https://github.com/Part-DB/helm-charts/tree/main/charts/part-db) for more
|
||||||
|
information on the available configuration options.
|
||||||
|
|
||||||
|
## Bugreports
|
||||||
|
|
||||||
|
If you find issues related to the helm charts, please open an issue in the [helm-charts repository](https://github.com/Part-DB/helm-charts).
|
|
@ -52,6 +52,11 @@ server {
|
||||||
location ~ \.php$ {
|
location ~ \.php$ {
|
||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Set Content-Security-Policy for svg files, to block embedded javascript in there
|
||||||
|
location ~* \.svg$ {
|
||||||
|
add_header Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none';";
|
||||||
|
}
|
||||||
|
|
||||||
error_log /var/log/nginx/parts.error.log;
|
error_log /var/log/nginx/parts.error.log;
|
||||||
access_log /var/log/nginx/parts.access.log;
|
access_log /var/log/nginx/parts.access.log;
|
||||||
|
|
31
docs/installation/proxmox.md
Normal file
31
docs/installation/proxmox.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
title: Proxmox VE LXC
|
||||||
|
layout: default
|
||||||
|
parent: Installation
|
||||||
|
nav_order: 6
|
||||||
|
---
|
||||||
|
|
||||||
|
# Proxmox VE LXC
|
||||||
|
|
||||||
|
{: .warning }
|
||||||
|
> The proxmox VE LXC script for Part-DB is developed and maintained by [Proxmox VE Helper-Scripts](https://community-scripts.github.io/ProxmoxVE/)
|
||||||
|
> and not by the Part-DB developers. Keep in mind that the script is not officially supported by the Part-DB developers.
|
||||||
|
|
||||||
|
If you are using Proxmox VE you can use the scripts provided by [Proxmox VE Helper-Scripts community](https://community-scripts.github.io/ProxmoxVE/scripts?id=part-db)
|
||||||
|
to easily install Part-DB in a LXC container.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To create a new LXC container with Part-DB, you can use the following command in the Proxmox VE shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/ct/part-db.sh)"
|
||||||
|
```
|
||||||
|
|
||||||
|
The same command can be used to update an existing Part-DB container.
|
||||||
|
|
||||||
|
See the [helper script website](https://community-scripts.github.io/ProxmoxVE/scripts?id=part-db) for more information.
|
||||||
|
|
||||||
|
## Bugreports
|
||||||
|
|
||||||
|
If you find issues related to the proxmox VE LXC script, please open an issue in the [Proxmox VE Helper-Scripts repository](https://github.com/community-scripts/ProxmoxVE).
|
|
@ -25,6 +25,12 @@ is named `partdb`, you can execute the command `php bin/console cache:clear` wit
|
||||||
docker exec --user=www-data partdb php bin/console cache:clear
|
docker exec --user=www-data partdb php bin/console cache:clear
|
||||||
```
|
```
|
||||||
|
|
||||||
|
{: .warning }
|
||||||
|
> If you run a root console inside the docker container, and wanna execute commands on the webserver behalf, be sure to use `sudo -E` command (with the `-E` flag) to preserve env variables from the current shell.
|
||||||
|
> Otherwise Part-DB console might use the wrong configuration to execute commands.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
## User management commands
|
## User management commands
|
||||||
|
|
||||||
* `php bin/console partdb:users:list`: List all users of this Part-DB instance
|
* `php bin/console partdb:users:list`: List all users of this Part-DB instance
|
||||||
|
@ -64,4 +70,10 @@ docker exec --user=www-data partdb php bin/console cache:clear
|
||||||
## Database commands
|
## Database commands
|
||||||
|
|
||||||
* `php bin/console doctrine:migrations:migrate`: Migrate the database to the latest version
|
* `php bin/console doctrine:migrations:migrate`: Migrate the database to the latest version
|
||||||
* `php bin/console doctrine:migrations:up-to-date`: Check if the database is up-to-date
|
* `php bin/console doctrine:migrations:up-to-date`: Check if the database is up-to-date
|
||||||
|
|
||||||
|
## Attachment commands
|
||||||
|
|
||||||
|
* `php bin/console partdb:attachments:download`: Download all attachments, which are not already downloaded, to the
|
||||||
|
local filesystem. This is useful to create local backups of the attachments, no matter what happens on the remote and
|
||||||
|
also makes pictures thumbnails available for the frontend for them
|
|
@ -107,7 +107,7 @@ The following env configuration options are available:
|
||||||
default: `EUR`). If an offer is only available in a certain currency,
|
default: `EUR`). If an offer is only available in a certain currency,
|
||||||
Part-DB will save the prices in their native currency, and you can use Part-DB currency conversion feature to convert
|
Part-DB will save the prices in their native currency, and you can use Part-DB currency conversion feature to convert
|
||||||
it to your preferred currency.
|
it to your preferred currency.
|
||||||
* `PROVIDER_OCOTPART_COUNTRY`: The country you want to get prices in if available (optional, 2 letter ISO-code,
|
* `PROVIDER_OCTOPART_COUNTRY`: The country you want to get prices in if available (optional, 2 letter ISO-code,
|
||||||
default: `DE`). To get the correct prices, you have to set this and the currency setting to the correct value.
|
default: `DE`). To get the correct prices, you have to set this and the currency setting to the correct value.
|
||||||
* `PROVIDER_OCTOPART_SEARCH_LIMIT`: The maximum number of results to return per search (optional, default: `10`). This
|
* `PROVIDER_OCTOPART_SEARCH_LIMIT`: The maximum number of results to return per search (optional, default: `10`). This
|
||||||
affects how quickly your monthly limit is used up.
|
affects how quickly your monthly limit is used up.
|
||||||
|
@ -212,6 +212,46 @@ An API key is not required, it is enough to enable the provider using the follow
|
||||||
* `PROVIDER_LCSC_ENABLED`: Set this to `1` to enable the LCSC provider
|
* `PROVIDER_LCSC_ENABLED`: Set this to `1` to enable the LCSC provider
|
||||||
* `PROVIDER_LCSC_CURRENCY`: The currency you want to get prices in (see LCSC webshop for available currencies, default: `EUR`)
|
* `PROVIDER_LCSC_CURRENCY`: The currency you want to get prices in (see LCSC webshop for available currencies, default: `EUR`)
|
||||||
|
|
||||||
|
### OEMsecrets
|
||||||
|
|
||||||
|
The oemsecrets provider uses the [oemsecrets API](https://www.oemsecrets.com/) to search for parts and getting shopping
|
||||||
|
information from them. Similar to octopart it aggregates offers from different distributors.
|
||||||
|
|
||||||
|
You can apply for a free API key on the [oemsecrets API page](https://www.oemsecrets.com/api/) and put the key you get
|
||||||
|
in the Part-DB env configuration (see below).
|
||||||
|
|
||||||
|
The following env configuration options are available:
|
||||||
|
|
||||||
|
* `PROVIDER_OEMSECRETS_KEY`: The API key you got from oemsecrets (mandatory)
|
||||||
|
* `PROVIDER_OEMSECRETS_COUNTRY_CODE`: The two-letter code of the country you want to get the prices for
|
||||||
|
* `PROVIDER_OEMSECRETS_CURRENCY`: The currency you want to get prices in (optional, default: `EUR`)
|
||||||
|
* `PROVIDER_OEMSECRETS_ZERO_PRICE`: If set to `1`, parts with a price of 0 will be included in the search results, otherwise
|
||||||
|
they will be excluded (optional, default: `0`)
|
||||||
|
* `PROVIDER_OEMSECRETS_SET_PARAM`: If set to `1`, the provider will try to extract parameters from the part description
|
||||||
|
* `PROVIDER_OEMSECRETS_SORT_CRITERIA`: The criteria to sort the search results by. If set to 'C', it further sorts by
|
||||||
|
completeness (prioritizing items with the most detailed information). If set to 'M', it further sorts by manufacturer name.
|
||||||
|
If set to any other value, no sorting is performed.
|
||||||
|
|
||||||
|
### Reichelt
|
||||||
|
|
||||||
|
The reichelt provider uses webscraping from [reichelt.com](https://reichelt.com/) to get part information.
|
||||||
|
This is not an official API and could break at any time. So use it at your own risk.
|
||||||
|
|
||||||
|
The following env configuration options are available:
|
||||||
|
* `PROVIDER_REICHELT_ENABLED`: Set this to `1` to enable the Reichelt provider
|
||||||
|
* `PROVIDER_REICHELT_CURRENCY`: The currency you want to get prices in. Only possible for countries which use Non-EUR (optional, default: `EUR`)
|
||||||
|
* `PROVIDER_REICHELT_COUNTRY`: The country you want to get the prices for (optional, default: `DE`)
|
||||||
|
* `PROVIDER_REICHELT_LANGUAGE`: The language you want to get the descriptions in (optional, default: `en`)
|
||||||
|
* `PROVIDER_REICHELT_INCLUDE_VAT`: If set to `1`, the prices will be gross prices (including tax), otherwise net prices (optional, default: `1`)
|
||||||
|
|
||||||
|
### Pollin
|
||||||
|
|
||||||
|
The pollin provider uses webscraping from [pollin.de](https://www.pollin.de/) to get part information.
|
||||||
|
This is not an official API and could break at any time. So use it at your own risk.
|
||||||
|
|
||||||
|
The following env configuration options are available:
|
||||||
|
* `PROVIDER_POLLIN_ENABLED`: Set this to `1` to enable the Pollin provider
|
||||||
|
|
||||||
### Custom provider
|
### Custom provider
|
||||||
|
|
||||||
To create a custom provider, you have to create a new class implementing the `InfoProviderInterface` interface. As long
|
To create a custom provider, you have to create a new class implementing the `InfoProviderInterface` interface. As long
|
||||||
|
|
|
@ -117,6 +117,6 @@ For a German keyboard layout, replace `[` with `0`, and `]` with `´`.
|
||||||
| Key | Character |
|
| Key | Character |
|
||||||
|--------------------------------|--------------------|
|
|--------------------------------|--------------------|
|
||||||
| **Alt + [** (code 219) | © (Copyright char) |
|
| **Alt + [** (code 219) | © (Copyright char) |
|
||||||
| **Alt + Shift + [** (code 219) | (Registered char) |
|
| **Alt + Shift + [** (code 219) | ® (Registered char) |
|
||||||
| **Alt + ]** (code 221) | ™ (Trademark char) |
|
| **Alt + ]** (code 221) | ™ (Trademark char) |
|
||||||
| **Alt + Shift + ]** (code 221) | (Degree char) |
|
| **Alt + Shift + ]** (code 221) | ° (Degree char) |
|
||||||
|
|
|
@ -235,4 +235,14 @@ EOD;
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,4 +380,14 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,4 +88,14 @@ final class Version20190913141126 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,4 +179,14 @@ final class Version20190924113252 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,4 +65,14 @@ final class Version20191214153125 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,4 +68,14 @@ final class Version20200126191823 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,4 +56,14 @@ final class Version20200311204104 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,4 +42,14 @@ final class Version20200409130946 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,4 +163,14 @@ EOD;
|
||||||
$this->addSql('DROP TABLE u2f_keys');
|
$this->addSql('DROP TABLE u2f_keys');
|
||||||
$this->addSql('DROP TABLE "users"');
|
$this->addSql('DROP TABLE "users"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -535,4 +535,14 @@ final class Version20220925162725 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX IDX_1483A5E938248176 ON "users" (currency_id)');
|
$this->addSql('CREATE INDEX IDX_1483A5E938248176 ON "users" (currency_id)');
|
||||||
$this->addSql('CREATE INDEX IDX_1483A5E96DEDCEC2 ON "users" (id_preview_attachement)');
|
$this->addSql('CREATE INDEX IDX_1483A5E96DEDCEC2 ON "users" (id_preview_attachement)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,4 +47,14 @@ final class Version20221003212851 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->addSql('DROP TABLE webauthn_keys');
|
$this->addSql('DROP TABLE webauthn_keys');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,20 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace DoctrineMigrations;
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
use App\Entity\UserSystem\PermissionData;
|
|
||||||
use App\Migration\AbstractMultiPlatformMigration;
|
use App\Migration\AbstractMultiPlatformMigration;
|
||||||
use App\Security\Interfaces\HasPermissionsInterface;
|
use App\Migration\WithPermPresetsTrait;
|
||||||
use App\Services\UserSystem\PermissionPresetsHelper;
|
use App\Services\UserSystem\PermissionPresetsHelper;
|
||||||
use Doctrine\DBAL\Connection;
|
use Doctrine\DBAL\Connection;
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-generated Migration: Please modify to your needs!
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
*/
|
*/
|
||||||
final class Version20221114193325 extends AbstractMultiPlatformMigration implements ContainerAwareInterface
|
final class Version20221114193325 extends AbstractMultiPlatformMigration implements ContainerAwareInterface
|
||||||
{
|
{
|
||||||
private ?ContainerInterface $container = null;
|
use WithPermPresetsTrait;
|
||||||
private ?PermissionPresetsHelper $permission_presets_helper = null;
|
|
||||||
|
|
||||||
public function __construct(Connection $connection, LoggerInterface $logger)
|
public function __construct(Connection $connection, LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
|
@ -33,34 +29,6 @@ final class Version20221114193325 extends AbstractMultiPlatformMigration impleme
|
||||||
return 'Update the permission system to the new system. Please note that all permissions will be reset!';
|
return 'Update the permission system to the new system. Please note that all permissions will be reset!';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getJSONPermDataFromPreset(string $preset): string
|
|
||||||
{
|
|
||||||
if ($this->permission_presets_helper === null) {
|
|
||||||
throw new \RuntimeException('PermissionPresetsHelper not set! There seems to be some issue with the dependency injection!');
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create a virtual user on which we can apply the preset
|
|
||||||
$user = new class implements HasPermissionsInterface {
|
|
||||||
|
|
||||||
public PermissionData $perm_data;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->perm_data = new PermissionData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPermissions(): PermissionData
|
|
||||||
{
|
|
||||||
return $this->perm_data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//Apply the preset to the virtual user
|
|
||||||
$this->permission_presets_helper->applyPreset($user, $preset);
|
|
||||||
|
|
||||||
//And return the json data
|
|
||||||
return json_encode($user->getPermissions());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function addDataMigrationAndWarning(): void
|
private function addDataMigrationAndWarning(): void
|
||||||
{
|
{
|
||||||
|
@ -164,11 +132,15 @@ final class Version20221114193325 extends AbstractMultiPlatformMigration impleme
|
||||||
$this->addSql('CREATE INDEX user_idx_username ON "users" (name)');
|
$this->addSql('CREATE INDEX user_idx_username ON "users" (name)');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setContainer(ContainerInterface $container = null)
|
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
{
|
{
|
||||||
if ($container) {
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
$this->container = $container;
|
}
|
||||||
$this->permission_presets_helper = $container->get(PermissionPresetsHelper::class);
|
|
||||||
}
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,4 +55,14 @@ final class Version20221204004815 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX parts_idx_datet_name_last_id_needs ON "parts" (datetime_added, name, last_modified, id, needs_review)');
|
$this->addSql('CREATE INDEX parts_idx_datet_name_last_id_needs ON "parts" (datetime_added, name, last_modified, id, needs_review)');
|
||||||
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,15 @@ final class Version20221216224745 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX log_idx_type ON log (type)');
|
$this->addSql('CREATE INDEX log_idx_type ON log (type)');
|
||||||
$this->addSql('CREATE INDEX log_idx_type_target ON log (type, target_type, target_id)');
|
$this->addSql('CREATE INDEX log_idx_type_target ON log (type, target_type, target_id)');
|
||||||
$this->addSql('CREATE INDEX log_idx_datetime ON log (datetime)');
|
$this->addSql('CREATE INDEX log_idx_datetime ON log (datetime)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,4 +320,14 @@ final class Version20230108165410 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('ALTER TABLE projects RENAME TO devices');
|
$this->addSql('ALTER TABLE projects RENAME TO devices');
|
||||||
$this->addSql('ALTER TABLE project_bom_entries RENAME TO device_parts');
|
$this->addSql('ALTER TABLE project_bom_entries RENAME TO device_parts');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -521,4 +521,14 @@ final class Version20230219225340 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,4 +37,14 @@ final class Version20230220221024 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->addSql('ALTER TABLE `users` DROP saml_user');
|
$this->addSql('ALTER TABLE `users` DROP saml_user');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,4 +297,14 @@ final class Version20230402170923 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
||||||
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,4 +49,14 @@ final class Version20230408170059 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX IDX_1483A5E9EA7100A1 ON "users" (id_preview_attachment)');
|
$this->addSql('CREATE INDEX IDX_1483A5E9EA7100A1 ON "users" (id_preview_attachment)');
|
||||||
$this->addSql('CREATE INDEX user_idx_username ON "users" (name)');
|
$this->addSql('CREATE INDEX user_idx_username ON "users" (name)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -434,4 +434,14 @@ final class Version20230408213957 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
||||||
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,14 @@ final class Version20230417211732 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
//As we done nothing, we don't need to implement this method.
|
//As we done nothing, we don't need to implement this method.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,4 +62,14 @@ final class Version20230528000149 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
||||||
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,4 +348,14 @@ final class Version20230716184033 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
||||||
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,4 +99,14 @@ final class Version20230730131708 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
||||||
$this->addSql('CREATE INDEX parts_idx_ipn ON "parts" (ipn)');
|
$this->addSql('CREATE INDEX parts_idx_ipn ON "parts" (ipn)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,4 +41,14 @@ final class Version20230816213201 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
$this->addSql('DROP TABLE api_tokens');
|
$this->addSql('DROP TABLE api_tokens');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,4 +68,14 @@ final class Version20231114223101 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX part_lots_idx_instock_un_expiration_id_part ON part_lots (instock_unknown, expiration_date, id_part)');
|
$this->addSql('CREATE INDEX part_lots_idx_instock_un_expiration_id_part ON part_lots (instock_unknown, expiration_date, id_part)');
|
||||||
$this->addSql('CREATE INDEX part_lots_idx_needs_refill ON part_lots (needs_refill)');
|
$this->addSql('CREATE INDEX part_lots_idx_needs_refill ON part_lots (needs_refill)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,4 +85,14 @@ final class Version20231130180903 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
||||||
$this->addSql('CREATE INDEX parts_idx_ipn ON "parts" (ipn)');
|
$this->addSql('CREATE INDEX parts_idx_ipn ON "parts" (ipn)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,4 +62,14 @@ final class Version20240427222442 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
||||||
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
654
migrations/Version20240606203053.php
Normal file
654
migrations/Version20240606203053.php
Normal file
|
@ -0,0 +1,654 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use App\Migration\AbstractMultiPlatformMigration;
|
||||||
|
use App\Migration\WithPermPresetsTrait;
|
||||||
|
use App\Services\UserSystem\PermissionPresetsHelper;
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20240606203053 extends AbstractMultiPlatformMigration implements ContainerAwareInterface
|
||||||
|
{
|
||||||
|
use WithPermPresetsTrait;
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Initial schema for Postgres and apply changes to MySQL and SQLite caused by the doctrine upgrade';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Create a collation for natural sorting
|
||||||
|
$this->addSql("CREATE COLLATION numeric (provider = icu, locale = 'en-u-kn-true');");
|
||||||
|
|
||||||
|
$this->addSql('CREATE TABLE api_tokens (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, valid_until TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, token VARCHAR(68) NOT NULL, level SMALLINT NOT NULL, last_time_used TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_2CAD560E5F37A13B ON api_tokens (token)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_2CAD560EA76ED395 ON api_tokens (user_id)');
|
||||||
|
$this->addSql('CREATE TABLE "attachment_types" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, filetype_filter TEXT NOT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_EFAED719727ACA70 ON "attachment_types" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_EFAED719EA7100A1 ON "attachment_types" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX attachment_types_idx_name ON "attachment_types" (name)');
|
||||||
|
$this->addSql('CREATE INDEX attachment_types_idx_parent_name ON "attachment_types" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE "attachments" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, original_filename VARCHAR(255) DEFAULT NULL, path VARCHAR(255) NOT NULL, show_in_table BOOLEAN NOT NULL, type_id INT NOT NULL, class_name VARCHAR(255) NOT NULL, element_id INT NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_47C4FAD6C54C8C93 ON "attachments" (type_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_47C4FAD61F1F2A24 ON "attachments" (element_id)');
|
||||||
|
$this->addSql('CREATE INDEX attachments_idx_id_element_id_class_name ON "attachments" (id, element_id, class_name)');
|
||||||
|
$this->addSql('CREATE INDEX attachments_idx_class_name_id ON "attachments" (class_name, id)');
|
||||||
|
$this->addSql('CREATE INDEX attachment_name_idx ON "attachments" (name)');
|
||||||
|
$this->addSql('CREATE INDEX attachment_element_idx ON "attachments" (class_name, element_id)');
|
||||||
|
$this->addSql('CREATE TABLE "categories" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, partname_hint TEXT NOT NULL, partname_regex TEXT NOT NULL, disable_footprints BOOLEAN NOT NULL, disable_manufacturers BOOLEAN NOT NULL, disable_autodatasheets BOOLEAN NOT NULL, disable_properties BOOLEAN NOT NULL, default_description TEXT NOT NULL, default_comment TEXT NOT NULL, eda_info_reference_prefix VARCHAR(255) DEFAULT NULL, eda_info_invisible BOOLEAN DEFAULT NULL, eda_info_exclude_from_bom BOOLEAN DEFAULT NULL, eda_info_exclude_from_board BOOLEAN DEFAULT NULL, eda_info_exclude_from_sim BOOLEAN DEFAULT NULL, eda_info_kicad_symbol VARCHAR(255) DEFAULT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_3AF34668727ACA70 ON "categories" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_3AF34668EA7100A1 ON "categories" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX category_idx_name ON "categories" (name)');
|
||||||
|
$this->addSql('CREATE INDEX category_idx_parent_name ON "categories" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE currencies (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, exchange_rate NUMERIC(11, 5) DEFAULT NULL, iso_code VARCHAR(255) NOT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_37C44693727ACA70 ON currencies (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_37C44693EA7100A1 ON currencies (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX currency_idx_name ON currencies (name)');
|
||||||
|
$this->addSql('CREATE INDEX currency_idx_parent_name ON currencies (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE "footprints" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, eda_info_kicad_footprint VARCHAR(255) DEFAULT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, id_footprint_3d INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_A34D68A2727ACA70 ON "footprints" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_A34D68A2EA7100A1 ON "footprints" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_A34D68A232A38C34 ON "footprints" (id_footprint_3d)');
|
||||||
|
$this->addSql('CREATE INDEX footprint_idx_name ON "footprints" (name)');
|
||||||
|
$this->addSql('CREATE INDEX footprint_idx_parent_name ON "footprints" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE "groups" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, enforce_2fa BOOLEAN NOT NULL, permissions_data JSON NOT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F06D3970727ACA70 ON "groups" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F06D3970EA7100A1 ON "groups" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX group_idx_name ON "groups" (name)');
|
||||||
|
$this->addSql('CREATE INDEX group_idx_parent_name ON "groups" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE label_profiles (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, show_in_dropdown BOOLEAN NOT NULL, options_width DOUBLE PRECISION NOT NULL, options_height DOUBLE PRECISION NOT NULL, options_barcode_type VARCHAR(255) NOT NULL, options_picture_type VARCHAR(255) NOT NULL, options_supported_element VARCHAR(255) NOT NULL, options_additional_css TEXT NOT NULL, options_lines_mode VARCHAR(255) NOT NULL, options_lines TEXT NOT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_C93E9CF5EA7100A1 ON label_profiles (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE TABLE log (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, username VARCHAR(255) NOT NULL, datetime TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, level SMALLINT NOT NULL, target_id INT NOT NULL, target_type SMALLINT NOT NULL, extra JSON NOT NULL, id_user INT DEFAULT NULL, type SMALLINT NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_8F3F68C56B3CA4B ON log (id_user)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_type ON log (type)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_type_target ON log (type, target_type, target_id)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_datetime ON log (datetime)');
|
||||||
|
$this->addSql('CREATE TABLE "manufacturers" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, address VARCHAR(255) NOT NULL, phone_number VARCHAR(255) NOT NULL, fax_number VARCHAR(255) NOT NULL, email_address VARCHAR(255) NOT NULL, website VARCHAR(255) NOT NULL, auto_product_url VARCHAR(255) NOT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_94565B12727ACA70 ON "manufacturers" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_94565B12EA7100A1 ON "manufacturers" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX manufacturer_name ON "manufacturers" (name)');
|
||||||
|
$this->addSql('CREATE INDEX manufacturer_idx_parent_name ON "manufacturers" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE "measurement_units" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, unit VARCHAR(255) DEFAULT NULL, is_integer BOOLEAN NOT NULL, use_si_prefix BOOLEAN NOT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F5AF83CF727ACA70 ON "measurement_units" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F5AF83CFEA7100A1 ON "measurement_units" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX unit_idx_name ON "measurement_units" (name)');
|
||||||
|
$this->addSql('CREATE INDEX unit_idx_parent_name ON "measurement_units" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE oauth_tokens (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, token TEXT DEFAULT NULL, expires_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, refresh_token TEXT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX oauth_tokens_unique_name ON oauth_tokens (name)');
|
||||||
|
$this->addSql('CREATE TABLE "orderdetails" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, supplierpartnr VARCHAR(255) NOT NULL, obsolete BOOLEAN NOT NULL, supplier_product_url TEXT NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, part_id INT NOT NULL, id_supplier INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_489AFCDC4CE34BEC ON "orderdetails" (part_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_489AFCDCCBF180EB ON "orderdetails" (id_supplier)');
|
||||||
|
$this->addSql('CREATE INDEX orderdetails_supplier_part_nr ON "orderdetails" (supplierpartnr)');
|
||||||
|
$this->addSql('CREATE TABLE parameters (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, symbol VARCHAR(255) NOT NULL, value_min DOUBLE PRECISION DEFAULT NULL, value_typical DOUBLE PRECISION DEFAULT NULL, value_max DOUBLE PRECISION DEFAULT NULL, unit VARCHAR(255) NOT NULL, value_text VARCHAR(255) NOT NULL, param_group VARCHAR(255) NOT NULL, type SMALLINT NOT NULL, element_id INT NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_69348FE1F1F2A24 ON parameters (element_id)');
|
||||||
|
$this->addSql('CREATE INDEX parameter_name_idx ON parameters (name)');
|
||||||
|
$this->addSql('CREATE INDEX parameter_group_idx ON parameters (param_group)');
|
||||||
|
$this->addSql('CREATE INDEX parameter_type_element_idx ON parameters (type, element_id)');
|
||||||
|
$this->addSql('CREATE TABLE part_association (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, type SMALLINT NOT NULL, other_type VARCHAR(255) DEFAULT NULL, comment TEXT DEFAULT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, owner_id INT NOT NULL, other_id INT NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_61B952E07E3C61F9 ON part_association (owner_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_61B952E0998D9879 ON part_association (other_id)');
|
||||||
|
$this->addSql('CREATE TABLE part_lots (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, description TEXT NOT NULL, comment TEXT NOT NULL, expiration_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, instock_unknown BOOLEAN NOT NULL, amount DOUBLE PRECISION NOT NULL, needs_refill BOOLEAN NOT NULL, vendor_barcode VARCHAR(255) DEFAULT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, id_store_location INT DEFAULT NULL, id_part INT NOT NULL, id_owner INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_EBC8F9435D8F4B37 ON part_lots (id_store_location)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_EBC8F943C22F6CC4 ON part_lots (id_part)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_EBC8F94321E5A74C ON part_lots (id_owner)');
|
||||||
|
$this->addSql('CREATE INDEX part_lots_idx_instock_un_expiration_id_part ON part_lots (instock_unknown, expiration_date, id_part)');
|
||||||
|
$this->addSql('CREATE INDEX part_lots_idx_needs_refill ON part_lots (needs_refill)');
|
||||||
|
$this->addSql('CREATE INDEX part_lots_idx_barcode ON part_lots (vendor_barcode)');
|
||||||
|
$this->addSql('CREATE TABLE "parts" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, needs_review BOOLEAN NOT NULL, tags TEXT NOT NULL, mass DOUBLE PRECISION DEFAULT NULL, ipn VARCHAR(100) DEFAULT NULL, description TEXT NOT NULL, comment TEXT NOT NULL, visible BOOLEAN NOT NULL, favorite BOOLEAN NOT NULL, minamount DOUBLE PRECISION NOT NULL, manufacturer_product_url TEXT NOT NULL, manufacturer_product_number VARCHAR(255) NOT NULL, manufacturing_status VARCHAR(255) DEFAULT NULL, order_quantity INT NOT NULL, manual_order BOOLEAN NOT NULL, provider_reference_provider_key VARCHAR(255) DEFAULT NULL, provider_reference_provider_id VARCHAR(255) DEFAULT NULL, provider_reference_provider_url VARCHAR(255) DEFAULT NULL, provider_reference_last_updated TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, eda_info_reference_prefix VARCHAR(255) DEFAULT NULL, eda_info_value VARCHAR(255) DEFAULT NULL, eda_info_invisible BOOLEAN DEFAULT NULL, eda_info_exclude_from_bom BOOLEAN DEFAULT NULL, eda_info_exclude_from_board BOOLEAN DEFAULT NULL, eda_info_exclude_from_sim BOOLEAN DEFAULT NULL, eda_info_kicad_symbol VARCHAR(255) DEFAULT NULL, eda_info_kicad_footprint VARCHAR(255) DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, id_category INT NOT NULL, id_footprint INT DEFAULT NULL, id_part_unit INT DEFAULT NULL, id_manufacturer INT DEFAULT NULL, order_orderdetails_id INT DEFAULT NULL, built_project_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_6940A7FE3D721C14 ON "parts" (ipn)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_6940A7FEEA7100A1 ON "parts" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_6940A7FE5697F554 ON "parts" (id_category)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_6940A7FE7E371A10 ON "parts" (id_footprint)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_6940A7FE2626CEF9 ON "parts" (id_part_unit)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_6940A7FE1ECB93AE ON "parts" (id_manufacturer)');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_6940A7FE81081E9B ON "parts" (order_orderdetails_id)');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_6940A7FEE8AE70D9 ON "parts" (built_project_id)');
|
||||||
|
$this->addSql('CREATE INDEX parts_idx_datet_name_last_id_needs ON "parts" (datetime_added, name, last_modified, id, needs_review)');
|
||||||
|
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
||||||
|
$this->addSql('CREATE INDEX parts_idx_ipn ON "parts" (ipn)');
|
||||||
|
$this->addSql('CREATE TABLE "pricedetails" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, price NUMERIC(11, 5) NOT NULL, price_related_quantity DOUBLE PRECISION NOT NULL, min_discount_quantity DOUBLE PRECISION NOT NULL, manual_input BOOLEAN NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, id_currency INT DEFAULT NULL, orderdetails_id INT NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_C68C4459398D64AA ON "pricedetails" (id_currency)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_C68C44594A01DDC7 ON "pricedetails" (orderdetails_id)');
|
||||||
|
$this->addSql('CREATE INDEX pricedetails_idx_min_discount ON "pricedetails" (min_discount_quantity)');
|
||||||
|
$this->addSql('CREATE INDEX pricedetails_idx_min_discount_price_qty ON "pricedetails" (min_discount_quantity, price_related_quantity)');
|
||||||
|
$this->addSql('CREATE TABLE project_bom_entries (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, quantity DOUBLE PRECISION NOT NULL, mountnames TEXT NOT NULL, name VARCHAR(255) DEFAULT NULL, comment TEXT NOT NULL, price NUMERIC(11, 5) DEFAULT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, id_device INT DEFAULT NULL, id_part INT DEFAULT NULL, price_currency_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD312F180363 ON project_bom_entries (id_device)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD31C22F6CC4 ON project_bom_entries (id_part)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD313FFDCD60 ON project_bom_entries (price_currency_id)');
|
||||||
|
$this->addSql('CREATE TABLE projects (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, order_quantity INT NOT NULL, status VARCHAR(64) DEFAULT NULL, order_only_missing_parts BOOLEAN NOT NULL, description TEXT NOT NULL, parent_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_5C93B3A4727ACA70 ON projects (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_5C93B3A4EA7100A1 ON projects (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE TABLE "storelocations" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, is_full BOOLEAN NOT NULL, only_single_part BOOLEAN NOT NULL, limit_to_existing_parts BOOLEAN NOT NULL, part_owner_must_match BOOLEAN DEFAULT false NOT NULL, parent_id INT DEFAULT NULL, storage_type_id INT DEFAULT NULL, id_owner INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_7517020727ACA70 ON "storelocations" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_7517020B270BFF1 ON "storelocations" (storage_type_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_751702021E5A74C ON "storelocations" (id_owner)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_7517020EA7100A1 ON "storelocations" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX location_idx_name ON "storelocations" (name)');
|
||||||
|
$this->addSql('CREATE INDEX location_idx_parent_name ON "storelocations" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE "suppliers" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, comment TEXT NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names TEXT DEFAULT NULL, address VARCHAR(255) NOT NULL, phone_number VARCHAR(255) NOT NULL, fax_number VARCHAR(255) NOT NULL, email_address VARCHAR(255) NOT NULL, website VARCHAR(255) NOT NULL, auto_product_url VARCHAR(255) NOT NULL, shipping_costs NUMERIC(11, 5) DEFAULT NULL, parent_id INT DEFAULT NULL, default_currency_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95C727ACA70 ON "suppliers" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95CECD792C0 ON "suppliers" (default_currency_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95CEA7100A1 ON "suppliers" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX supplier_idx_name ON "suppliers" (name)');
|
||||||
|
$this->addSql('CREATE INDEX supplier_idx_parent_name ON "suppliers" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TABLE u2f_keys (key_handle VARCHAR(128) NOT NULL, public_key VARCHAR(255) NOT NULL, certificate TEXT NOT NULL, counter VARCHAR(255) NOT NULL, id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_4F4ADB4BA76ED395 ON u2f_keys (user_id)');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX user_unique ON u2f_keys (user_id, key_handle)');
|
||||||
|
$this->addSql('CREATE TABLE "users" (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, disabled BOOLEAN NOT NULL, config_theme VARCHAR(255) DEFAULT NULL, pw_reset_token VARCHAR(255) DEFAULT NULL, config_instock_comment_a TEXT NOT NULL, config_instock_comment_w TEXT NOT NULL, about_me TEXT NOT NULL, trusted_device_cookie_version INT NOT NULL, backup_codes JSON NOT NULL, google_authenticator_secret VARCHAR(255) DEFAULT NULL, config_timezone VARCHAR(255) DEFAULT NULL, config_language VARCHAR(255) DEFAULT NULL, email VARCHAR(255) DEFAULT NULL, show_email_on_profile BOOLEAN DEFAULT false NOT NULL, department VARCHAR(255) DEFAULT NULL, last_name VARCHAR(255) DEFAULT NULL, first_name VARCHAR(255) DEFAULT NULL, need_pw_change BOOLEAN NOT NULL, password VARCHAR(255) DEFAULT NULL, settings JSON NOT NULL, backup_codes_generation_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, pw_reset_expires TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, saml_user BOOLEAN NOT NULL, name VARCHAR(180) NOT NULL, permissions_data JSON NOT NULL, group_id INT DEFAULT NULL, id_preview_attachment INT DEFAULT NULL, currency_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_1483A5E95E237E06 ON "users" (name)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E9FE54D947 ON "users" (group_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E9EA7100A1 ON "users" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E938248176 ON "users" (currency_id)');
|
||||||
|
$this->addSql('CREATE INDEX user_idx_username ON "users" (name)');
|
||||||
|
$this->addSql('CREATE TABLE webauthn_keys (public_key_credential_id TEXT NOT NULL, type VARCHAR(255) NOT NULL, transports TEXT NOT NULL, attestation_type VARCHAR(255) NOT NULL, trust_path JSON NOT NULL, aaguid TEXT NOT NULL, credential_public_key TEXT NOT NULL, user_handle VARCHAR(255) NOT NULL, counter INT NOT NULL, other_ui TEXT DEFAULT NULL, backup_eligible BOOLEAN DEFAULT NULL, backup_status BOOLEAN DEFAULT NULL, uv_initialized BOOLEAN DEFAULT NULL, id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255) NOT NULL, last_time_used TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
|
$this->addSql('ALTER TABLE api_tokens ADD CONSTRAINT FK_2CAD560EA76ED395 FOREIGN KEY (user_id) REFERENCES "users" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "attachment_types" ADD CONSTRAINT FK_EFAED719727ACA70 FOREIGN KEY (parent_id) REFERENCES "attachment_types" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "attachment_types" ADD CONSTRAINT FK_EFAED719EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "attachments" ADD CONSTRAINT FK_47C4FAD6C54C8C93 FOREIGN KEY (type_id) REFERENCES "attachment_types" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "categories" ADD CONSTRAINT FK_3AF34668727ACA70 FOREIGN KEY (parent_id) REFERENCES "categories" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "categories" ADD CONSTRAINT FK_3AF34668EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE currencies ADD CONSTRAINT FK_37C44693727ACA70 FOREIGN KEY (parent_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE currencies ADD CONSTRAINT FK_37C44693EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "footprints" ADD CONSTRAINT FK_A34D68A2727ACA70 FOREIGN KEY (parent_id) REFERENCES "footprints" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "footprints" ADD CONSTRAINT FK_A34D68A2EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "footprints" ADD CONSTRAINT FK_A34D68A232A38C34 FOREIGN KEY (id_footprint_3d) REFERENCES "attachments" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "groups" ADD CONSTRAINT FK_F06D3970727ACA70 FOREIGN KEY (parent_id) REFERENCES "groups" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "groups" ADD CONSTRAINT FK_F06D3970EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE label_profiles ADD CONSTRAINT FK_C93E9CF5EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE log ADD CONSTRAINT FK_8F3F68C56B3CA4B FOREIGN KEY (id_user) REFERENCES "users" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "manufacturers" ADD CONSTRAINT FK_94565B12727ACA70 FOREIGN KEY (parent_id) REFERENCES "manufacturers" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "manufacturers" ADD CONSTRAINT FK_94565B12EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "measurement_units" ADD CONSTRAINT FK_F5AF83CF727ACA70 FOREIGN KEY (parent_id) REFERENCES "measurement_units" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "measurement_units" ADD CONSTRAINT FK_F5AF83CFEA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "orderdetails" ADD CONSTRAINT FK_489AFCDC4CE34BEC FOREIGN KEY (part_id) REFERENCES "parts" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "orderdetails" ADD CONSTRAINT FK_489AFCDCCBF180EB FOREIGN KEY (id_supplier) REFERENCES "suppliers" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE part_association ADD CONSTRAINT FK_61B952E07E3C61F9 FOREIGN KEY (owner_id) REFERENCES "parts" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE part_association ADD CONSTRAINT FK_61B952E0998D9879 FOREIGN KEY (other_id) REFERENCES "parts" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F9435D8F4B37 FOREIGN KEY (id_store_location) REFERENCES "storelocations" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F943C22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F94321E5A74C FOREIGN KEY (id_owner) REFERENCES "users" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" ADD CONSTRAINT FK_6940A7FEEA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" ADD CONSTRAINT FK_6940A7FE5697F554 FOREIGN KEY (id_category) REFERENCES "categories" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" ADD CONSTRAINT FK_6940A7FE7E371A10 FOREIGN KEY (id_footprint) REFERENCES "footprints" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" ADD CONSTRAINT FK_6940A7FE2626CEF9 FOREIGN KEY (id_part_unit) REFERENCES "measurement_units" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" ADD CONSTRAINT FK_6940A7FE1ECB93AE FOREIGN KEY (id_manufacturer) REFERENCES "manufacturers" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" ADD CONSTRAINT FK_6940A7FE81081E9B FOREIGN KEY (order_orderdetails_id) REFERENCES "orderdetails" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" ADD CONSTRAINT FK_6940A7FEE8AE70D9 FOREIGN KEY (built_project_id) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "pricedetails" ADD CONSTRAINT FK_C68C4459398D64AA FOREIGN KEY (id_currency) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "pricedetails" ADD CONSTRAINT FK_C68C44594A01DDC7 FOREIGN KEY (orderdetails_id) REFERENCES "orderdetails" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries ADD CONSTRAINT FK_1AA2DD312F180363 FOREIGN KEY (id_device) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries ADD CONSTRAINT FK_1AA2DD31C22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries ADD CONSTRAINT FK_1AA2DD313FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE projects ADD CONSTRAINT FK_5C93B3A4727ACA70 FOREIGN KEY (parent_id) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE projects ADD CONSTRAINT FK_5C93B3A4EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" ADD CONSTRAINT FK_7517020727ACA70 FOREIGN KEY (parent_id) REFERENCES "storelocations" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" ADD CONSTRAINT FK_7517020B270BFF1 FOREIGN KEY (storage_type_id) REFERENCES "measurement_units" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" ADD CONSTRAINT FK_751702021E5A74C FOREIGN KEY (id_owner) REFERENCES "users" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" ADD CONSTRAINT FK_7517020EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "suppliers" ADD CONSTRAINT FK_AC28B95C727ACA70 FOREIGN KEY (parent_id) REFERENCES "suppliers" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "suppliers" ADD CONSTRAINT FK_AC28B95CECD792C0 FOREIGN KEY (default_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "suppliers" ADD CONSTRAINT FK_AC28B95CEA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE u2f_keys ADD CONSTRAINT FK_4F4ADB4BA76ED395 FOREIGN KEY (user_id) REFERENCES "users" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "users" ADD CONSTRAINT FK_1483A5E9FE54D947 FOREIGN KEY (group_id) REFERENCES "groups" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "users" ADD CONSTRAINT FK_1483A5E9EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "users" ADD CONSTRAINT FK_1483A5E938248176 FOREIGN KEY (currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE webauthn_keys ADD CONSTRAINT FK_799FD143A76ED395 FOREIGN KEY (user_id) REFERENCES "users" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
|
||||||
|
//Create the initial groups and users
|
||||||
|
//Retrieve the json representations of the presets
|
||||||
|
$admin = $this->getJSONPermDataFromPreset(PermissionPresetsHelper::PRESET_ADMIN);
|
||||||
|
$editor = $this->getJSONPermDataFromPreset(PermissionPresetsHelper::PRESET_EDITOR);
|
||||||
|
$read_only = $this->getJSONPermDataFromPreset(PermissionPresetsHelper::PRESET_READ_ONLY);
|
||||||
|
|
||||||
|
|
||||||
|
$sql = <<<EOD
|
||||||
|
INSERT INTO "groups" ("id", "parent_id", "comment", "not_selectable", "name", "permissions_data", "enforce_2fa") VALUES
|
||||||
|
(1, NULL, 'Users of this group can do everything: Read, Write and Administrative actions.', FALSE, 'admins', '$admin', FALSE),
|
||||||
|
(2, NULL, 'Users of this group can only read informations, use tools, and do not have access to administrative tools.', FALSE, 'readonly', '$read_only', FALSE),
|
||||||
|
(3, NULL, 'Users of this group, can edit part informations, create new ones, etc. but are not allowed to use administrative tools. (But can read current configuration, and see Server status)', FALSE, 'users', '$editor', FALSE);
|
||||||
|
|
||||||
|
EOD;
|
||||||
|
$this->addSql($sql);
|
||||||
|
|
||||||
|
//Increase the sequence for the groups, to avoid conflicts later
|
||||||
|
$this->addSql('SELECT setval(\'groups_id_seq\', 4)');
|
||||||
|
|
||||||
|
|
||||||
|
$admin_pw = $this->getInitalAdminPW();
|
||||||
|
|
||||||
|
$sql = <<<EOD
|
||||||
|
INSERT INTO "users" ("id", "group_id", "name", "password", "need_pw_change", "first_name", "last_name", "department", "email",
|
||||||
|
"config_language", "config_timezone", "config_theme", "config_instock_comment_w", "config_instock_comment_a",
|
||||||
|
"currency_id", "settings", "disabled", "backup_codes", "trusted_device_cookie_version",
|
||||||
|
"permissions_data", "saml_user", "about_me"
|
||||||
|
) VALUES
|
||||||
|
(1, 2, 'anonymous', '', FALSE, '', '', '', '', NULL, NULL, NULL, '', '', NULL, '{}', FALSE, 'null', 0, 'null', FALSE, ''),
|
||||||
|
(2, 1, 'admin', '{$admin_pw}', TRUE, '', '', '', '', NULL, NULL, NULL, '', '', NULL, '{}', FALSE, 'null', 0, '{$admin}', FALSE, '')
|
||||||
|
EOD;
|
||||||
|
$this->addSql($sql);
|
||||||
|
|
||||||
|
//Increase the sequence for the users, to avoid conflicts later
|
||||||
|
$this->addSql('SELECT setval(\'users_id_seq\', 3)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('ALTER TABLE api_tokens DROP CONSTRAINT FK_2CAD560EA76ED395');
|
||||||
|
$this->addSql('ALTER TABLE "attachment_types" DROP CONSTRAINT FK_EFAED719727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "attachment_types" DROP CONSTRAINT FK_EFAED719EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "attachments" DROP CONSTRAINT FK_47C4FAD6C54C8C93');
|
||||||
|
$this->addSql('ALTER TABLE "categories" DROP CONSTRAINT FK_3AF34668727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "categories" DROP CONSTRAINT FK_3AF34668EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE currencies DROP CONSTRAINT FK_37C44693727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE currencies DROP CONSTRAINT FK_37C44693EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "footprints" DROP CONSTRAINT FK_A34D68A2727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "footprints" DROP CONSTRAINT FK_A34D68A2EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "footprints" DROP CONSTRAINT FK_A34D68A232A38C34');
|
||||||
|
$this->addSql('ALTER TABLE "groups" DROP CONSTRAINT FK_F06D3970727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "groups" DROP CONSTRAINT FK_F06D3970EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE label_profiles DROP CONSTRAINT FK_C93E9CF5EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE log DROP CONSTRAINT FK_8F3F68C56B3CA4B');
|
||||||
|
$this->addSql('ALTER TABLE "manufacturers" DROP CONSTRAINT FK_94565B12727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "manufacturers" DROP CONSTRAINT FK_94565B12EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "measurement_units" DROP CONSTRAINT FK_F5AF83CF727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "measurement_units" DROP CONSTRAINT FK_F5AF83CFEA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "orderdetails" DROP CONSTRAINT FK_489AFCDC4CE34BEC');
|
||||||
|
$this->addSql('ALTER TABLE "orderdetails" DROP CONSTRAINT FK_489AFCDCCBF180EB');
|
||||||
|
$this->addSql('ALTER TABLE part_association DROP CONSTRAINT FK_61B952E07E3C61F9');
|
||||||
|
$this->addSql('ALTER TABLE part_association DROP CONSTRAINT FK_61B952E0998D9879');
|
||||||
|
$this->addSql('ALTER TABLE part_lots DROP CONSTRAINT FK_EBC8F9435D8F4B37');
|
||||||
|
$this->addSql('ALTER TABLE part_lots DROP CONSTRAINT FK_EBC8F943C22F6CC4');
|
||||||
|
$this->addSql('ALTER TABLE part_lots DROP CONSTRAINT FK_EBC8F94321E5A74C');
|
||||||
|
$this->addSql('ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FEEA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FE5697F554');
|
||||||
|
$this->addSql('ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FE7E371A10');
|
||||||
|
$this->addSql('ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FE2626CEF9');
|
||||||
|
$this->addSql('ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FE1ECB93AE');
|
||||||
|
$this->addSql('ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FE81081E9B');
|
||||||
|
$this->addSql('ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FEE8AE70D9');
|
||||||
|
$this->addSql('ALTER TABLE "pricedetails" DROP CONSTRAINT FK_C68C4459398D64AA');
|
||||||
|
$this->addSql('ALTER TABLE "pricedetails" DROP CONSTRAINT FK_C68C44594A01DDC7');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries DROP CONSTRAINT FK_1AA2DD312F180363');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries DROP CONSTRAINT FK_1AA2DD31C22F6CC4');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries DROP CONSTRAINT FK_1AA2DD313FFDCD60');
|
||||||
|
$this->addSql('ALTER TABLE projects DROP CONSTRAINT FK_5C93B3A4727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE projects DROP CONSTRAINT FK_5C93B3A4EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" DROP CONSTRAINT FK_7517020727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" DROP CONSTRAINT FK_7517020B270BFF1');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" DROP CONSTRAINT FK_751702021E5A74C');
|
||||||
|
$this->addSql('ALTER TABLE "storelocations" DROP CONSTRAINT FK_7517020EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "suppliers" DROP CONSTRAINT FK_AC28B95C727ACA70');
|
||||||
|
$this->addSql('ALTER TABLE "suppliers" DROP CONSTRAINT FK_AC28B95CECD792C0');
|
||||||
|
$this->addSql('ALTER TABLE "suppliers" DROP CONSTRAINT FK_AC28B95CEA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE u2f_keys DROP CONSTRAINT FK_4F4ADB4BA76ED395');
|
||||||
|
$this->addSql('ALTER TABLE "users" DROP CONSTRAINT FK_1483A5E9FE54D947');
|
||||||
|
$this->addSql('ALTER TABLE "users" DROP CONSTRAINT FK_1483A5E9EA7100A1');
|
||||||
|
$this->addSql('ALTER TABLE "users" DROP CONSTRAINT FK_1483A5E938248176');
|
||||||
|
$this->addSql('ALTER TABLE webauthn_keys DROP CONSTRAINT FK_799FD143A76ED395');
|
||||||
|
$this->addSql('DROP TABLE api_tokens');
|
||||||
|
$this->addSql('DROP TABLE "attachment_types"');
|
||||||
|
$this->addSql('DROP TABLE "attachments"');
|
||||||
|
$this->addSql('DROP TABLE "categories"');
|
||||||
|
$this->addSql('DROP TABLE currencies');
|
||||||
|
$this->addSql('DROP TABLE "footprints"');
|
||||||
|
$this->addSql('DROP TABLE "groups"');
|
||||||
|
$this->addSql('DROP TABLE label_profiles');
|
||||||
|
$this->addSql('DROP TABLE log');
|
||||||
|
$this->addSql('DROP TABLE "manufacturers"');
|
||||||
|
$this->addSql('DROP TABLE "measurement_units"');
|
||||||
|
$this->addSql('DROP TABLE oauth_tokens');
|
||||||
|
$this->addSql('DROP TABLE "orderdetails"');
|
||||||
|
$this->addSql('DROP TABLE parameters');
|
||||||
|
$this->addSql('DROP TABLE part_association');
|
||||||
|
$this->addSql('DROP TABLE part_lots');
|
||||||
|
$this->addSql('DROP TABLE "parts"');
|
||||||
|
$this->addSql('DROP TABLE "pricedetails"');
|
||||||
|
$this->addSql('DROP TABLE project_bom_entries');
|
||||||
|
$this->addSql('DROP TABLE projects');
|
||||||
|
$this->addSql('DROP TABLE "storelocations"');
|
||||||
|
$this->addSql('DROP TABLE "suppliers"');
|
||||||
|
$this->addSql('DROP TABLE u2f_keys');
|
||||||
|
$this->addSql('DROP TABLE "users"');
|
||||||
|
$this->addSql('DROP TABLE webauthn_keys');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mySQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE currencies CHANGE exchange_rate exchange_rate NUMERIC(11, 5) DEFAULT NULL');
|
||||||
|
//Set empty JSON fields to "{}" to avoid issues with failing JSON validation
|
||||||
|
$this->addSql('UPDATE `groups` SET permissions_data = "{}" WHERE permissions_data = ""');
|
||||||
|
$this->addSql('ALTER TABLE `groups` CHANGE permissions_data permissions_data JSON NOT NULL');
|
||||||
|
//Set the empty JSON fields to "{}" to avoid issues with failing JSON validation
|
||||||
|
$this->addSql('UPDATE `log` SET extra = "{}" WHERE extra = ""');
|
||||||
|
$this->addSql('ALTER TABLE `log` CHANGE level level TINYINT NOT NULL, CHANGE extra extra JSON NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE oauth_tokens CHANGE expires_at expires_at DATETIME DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE pricedetails CHANGE price price NUMERIC(11, 5) NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries CHANGE price price NUMERIC(11, 5) DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE suppliers CHANGE shipping_costs shipping_costs NUMERIC(11, 5) DEFAULT NULL');
|
||||||
|
//Set the empty JSON fields to "{}" to avoid issues with failing JSON validation
|
||||||
|
$this->addSql('UPDATE `users` SET settings = "{}" WHERE settings = ""');
|
||||||
|
$this->addSql('UPDATE `users` SET backup_codes = "{}" WHERE backup_codes = ""');
|
||||||
|
$this->addSql('UPDATE `users` SET permissions_data = "{}" WHERE permissions_data = ""');
|
||||||
|
$this->addSql('ALTER TABLE `users` CHANGE settings settings JSON NOT NULL, CHANGE backup_codes backup_codes JSON NOT NULL, CHANGE permissions_data permissions_data JSON NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE webauthn_keys CHANGE public_key_credential_id public_key_credential_id LONGTEXT NOT NULL, CHANGE transports transports LONGTEXT NOT NULL, CHANGE trust_path trust_path JSON NOT NULL, CHANGE aaguid aaguid TINYTEXT NOT NULL, CHANGE credential_public_key credential_public_key LONGTEXT NOT NULL, CHANGE other_ui other_ui LONGTEXT DEFAULT NULL, CHANGE last_time_used last_time_used DATETIME DEFAULT NULL');
|
||||||
|
|
||||||
|
// Add the natural sort emulation function to the database (based on this stackoverflow: https://stackoverflow.com/questions/153633/natural-sort-in-mysql/58154535#58154535)
|
||||||
|
//This version here is wrong, and will be replaced by the correct version in the next migration (we need to use nowdoc instead of heredoc, otherwise the slashes will be wrongly escaped!!)
|
||||||
|
$this->addSql(<<<EOD
|
||||||
|
CREATE DEFINER=CURRENT_USER FUNCTION `NatSortKey`(`s` VARCHAR(1000) CHARSET utf8mb4, `n` INT) RETURNS varchar(3500) CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci
|
||||||
|
DETERMINISTIC
|
||||||
|
SQL SECURITY INVOKER
|
||||||
|
BEGIN
|
||||||
|
/****
|
||||||
|
Converts numbers in the input string s into a format such that sorting results in a nat-sort.
|
||||||
|
Numbers of up to 359 digits (before the decimal point, if one is present) are supported. Sort results are undefined if the input string contains numbers longer than this.
|
||||||
|
For n>0, only the first n numbers in the input string will be converted for nat-sort (so strings that differ only after the first n numbers will not nat-sort amongst themselves).
|
||||||
|
Total sort-ordering is preserved, i.e. if s1!=s2, then NatSortKey(s1,n)!=NatSortKey(s2,n), for any given n.
|
||||||
|
Numbers may contain ',' as a thousands separator, and '.' as a decimal point. To reverse these (as appropriate for some European locales), the code would require modification.
|
||||||
|
Numbers preceded by '+' sort with numbers not preceded with either a '+' or '-' sign.
|
||||||
|
Negative numbers (preceded with '-') sort before positive numbers, but are sorted in order of ascending absolute value (so -7 sorts BEFORE -1001).
|
||||||
|
Numbers with leading zeros sort after the same number with no (or fewer) leading zeros.
|
||||||
|
Decimal-part-only numbers (like .75) are recognised, provided the decimal point is not immediately preceded by either another '.', or by a letter-type character.
|
||||||
|
Numbers with thousand separators sort after the same number without them.
|
||||||
|
Thousand separators are only recognised in numbers with no leading zeros that don't immediately follow a ',', and when they format the number correctly.
|
||||||
|
(When not recognised as a thousand separator, a ',' will instead be treated as separating two distinct numbers).
|
||||||
|
Version-number-like sequences consisting of 3 or more numbers separated by '.' are treated as distinct entities, and each component number will be nat-sorted.
|
||||||
|
The entire entity will sort after any number beginning with the first component (so e.g. 10.2.1 sorts after both 10 and 10.995, but before 11)
|
||||||
|
Note that The first number component in an entity like this is also permitted to contain thousand separators.
|
||||||
|
|
||||||
|
To achieve this, numbers within the input string are prefixed and suffixed according to the following format:
|
||||||
|
- The number is prefixed by a 2-digit base-36 number representing its length, excluding leading zeros. If there is a decimal point, this length only includes the integer part of the number.
|
||||||
|
- A 3-character suffix is appended after the number (after the decimals if present).
|
||||||
|
- The first character is a space, or a '+' sign if the number was preceded by '+'. Any preceding '+' sign is also removed from the front of the number.
|
||||||
|
- This is followed by a 2-digit base-36 number that encodes the number of leading zeros and whether the number was expressed in comma-separated form (e.g. 1,000,000.25 vs 1000000.25)
|
||||||
|
- The value of this 2-digit number is: (number of leading zeros)*2 + (1 if comma-separated, 0 otherwise)
|
||||||
|
- For version number sequences, each component number has the prefix in front of it, and the separating dots are removed.
|
||||||
|
Then there is a single suffix that consists of a ' ' or '+' character, followed by a pair base-36 digits for each number component in the sequence.
|
||||||
|
|
||||||
|
e.g. here is how some simple sample strings get converted:
|
||||||
|
'Foo055' --> 'Foo0255 02'
|
||||||
|
'Absolute zero is around -273 centigrade' --> 'Absolute zero is around -03273 00 centigrade'
|
||||||
|
'The $1,000,000 prize' --> 'The $071000000 01 prize'
|
||||||
|
'+99.74 degrees' --> '0299.74+00 degrees'
|
||||||
|
'I have 0 apples' --> 'I have 00 02 apples'
|
||||||
|
'.5 is the same value as 0000.5000' --> '00.5 00 is the same value as 00.5000 08'
|
||||||
|
'MariaDB v10.3.0018' --> 'MariaDB v02100130218 000004'
|
||||||
|
|
||||||
|
The restriction to numbers of up to 359 digits comes from the fact that the first character of the base-36 prefix MUST be a decimal digit, and so the highest permitted prefix value is '9Z' or 359 decimal.
|
||||||
|
The code could be modified to handle longer numbers by increasing the size of (both) the prefix and suffix.
|
||||||
|
A higher base could also be used (by replacing CONV() with a custom function), provided that the collation you are using sorts the "digits" of the base in the correct order, starting with 0123456789.
|
||||||
|
However, while the maximum number length may be increased this way, note that the technique this function uses is NOT applicable where strings may contain numbers of unlimited length.
|
||||||
|
|
||||||
|
The function definition does not specify the charset or collation to be used for string-type parameters or variables: The default database charset & collation at the time the function is defined will be used.
|
||||||
|
This is to make the function code more portable. However, there are some important restrictions:
|
||||||
|
|
||||||
|
- Collation is important here only when comparing (or storing) the output value from this function, but it MUST order the characters " +0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" in that order for the natural sort to work.
|
||||||
|
This is true for most collations, but not all of them, e.g. in Lithuanian 'Y' comes before 'J' (according to Wikipedia).
|
||||||
|
To adapt the function to work with such collations, replace CONV() in the function code with a custom function that emits "digits" above 9 that are characters ordered according to the collation in use.
|
||||||
|
|
||||||
|
- For efficiency, the function code uses LENGTH() rather than CHAR_LENGTH() to measure the length of strings that consist only of digits 0-9, '.', and ',' characters.
|
||||||
|
This works for any single-byte charset, as well as any charset that maps standard ASCII characters to single bytes (such as utf8 or utf8mb4).
|
||||||
|
If using a charset that maps these characters to multiple bytes (such as, e.g. utf16 or utf32), you MUST replace all instances of LENGTH() in the function definition with CHAR_LENGTH()
|
||||||
|
|
||||||
|
Length of the output:
|
||||||
|
|
||||||
|
Each number converted adds 5 characters (2 prefix + 3 suffix) to the length of the string. n is the maximum count of numbers to convert;
|
||||||
|
This parameter is provided as a means to limit the maximum output length (to input length + 5*n).
|
||||||
|
If you do not require the total-ordering property, you could edit the code to use suffixes of 1 character (space or plus) only; this would reduce the maximum output length for any given n.
|
||||||
|
Since a string of length L has at most ((L+1) DIV 2) individual numbers in it (every 2nd character a digit), for n<=0 the maximum output length is (inputlength + 5*((inputlength+1) DIV 2))
|
||||||
|
So for the current input length of 100, the maximum output length is 350.
|
||||||
|
If changing the input length, the output length must be modified according to the above formula. The DECLARE statements for x,y,r, and suf must also be modified, as the code comments indicate.
|
||||||
|
****/
|
||||||
|
|
||||||
|
DECLARE x,y varchar(1000); # need to be same length as input s
|
||||||
|
DECLARE r varchar(3500) DEFAULT ''; # return value: needs to be same length as return type
|
||||||
|
DECLARE suf varchar(1001); # suffix for a number or version string. Must be (((inputlength+1) DIV 2)*2 + 1) chars to support version strings (e.g. '1.2.33.5'), though it's usually just 3 chars. (Max version string e.g. 1.2. ... .5 has ((length of input + 1) DIV 2) numeric components)
|
||||||
|
DECLARE i,j,k int UNSIGNED;
|
||||||
|
IF n<=0 THEN SET n := -1; END IF; # n<=0 means "process all numbers"
|
||||||
|
LOOP
|
||||||
|
SET i := REGEXP_INSTR(s,'\\d'); # find position of next digit
|
||||||
|
IF i=0 OR n=0 THEN RETURN CONCAT(r,s); END IF; # no more numbers to process -> we're done
|
||||||
|
SET n := n-1, suf := ' ';
|
||||||
|
IF i>1 THEN
|
||||||
|
IF SUBSTRING(s,i-1,1)='.' AND (i=2 OR SUBSTRING(s,i-2,1) RLIKE '[^.\\p{L}\\p{N}\\p{M}\\x{608}\\x{200C}\\x{200D}\\x{2100}-\\x{214F}\\x{24B6}-\\x{24E9}\\x{1F130}-\\x{1F149}\\x{1F150}-\\x{1F169}\\x{1F170}-\\x{1F189}]') AND (SUBSTRING(s,i) NOT RLIKE '^\\d++\\.\\d') THEN SET i:=i-1; END IF; # Allow decimal number (but not version string) to begin with a '.', provided preceding char is neither another '.', nor a member of the unicode character classes: "Alphabetic", "Letter", "Block=Letterlike Symbols" "Number", "Mark", "Join_Control"
|
||||||
|
IF i>1 AND SUBSTRING(s,i-1,1)='+' THEN SET suf := '+', j := i-1; ELSE SET j := i; END IF; # move any preceding '+' into the suffix, so equal numbers with and without preceding "+" signs sort together
|
||||||
|
SET r := CONCAT(r,SUBSTRING(s,1,j-1)); SET s = SUBSTRING(s,i); # add everything before the number to r and strip it from the start of s; preceding '+' is dropped (not included in either r or s)
|
||||||
|
END IF;
|
||||||
|
SET x := REGEXP_SUBSTR(s,IF(SUBSTRING(s,1,1) IN ('0','.') OR (SUBSTRING(r,-1)=',' AND suf=' '),'^\\d*+(?:\\.\\d++)*','^(?:[1-9]\\d{0,2}(?:,\\d{3}(?!\\d))++|\\d++)(?:\\.\\d++)*+')); # capture the number + following decimals (including multiple consecutive '.<digits>' sequences)
|
||||||
|
SET s := SUBSTRING(s,CHAR_LENGTH(x)+1); # NOTE: CHAR_LENGTH() can be safely used instead of CHAR_LENGTH() here & below PROVIDED we're using a charset that represents digits, ',' and '.' characters using single bytes (e.g. latin1, utf8)
|
||||||
|
SET i := INSTR(x,'.');
|
||||||
|
IF i=0 THEN SET y := ''; ELSE SET y := SUBSTRING(x,i); SET x := SUBSTRING(x,1,i-1); END IF; # move any following decimals into y
|
||||||
|
SET i := CHAR_LENGTH(x);
|
||||||
|
SET x := REPLACE(x,',','');
|
||||||
|
SET j := CHAR_LENGTH(x);
|
||||||
|
SET x := TRIM(LEADING '0' FROM x); # strip leading zeros
|
||||||
|
SET k := CHAR_LENGTH(x);
|
||||||
|
SET suf := CONCAT(suf,LPAD(CONV(LEAST((j-k)*2,1294) + IF(i=j,0,1),10,36),2,'0')); # (j-k)*2 + IF(i=j,0,1) = (count of leading zeros)*2 + (1 if there are thousands-separators, 0 otherwise) Note the first term is bounded to <= base-36 'ZY' as it must fit within 2 characters
|
||||||
|
SET i := LOCATE('.',y,2);
|
||||||
|
IF i=0 THEN
|
||||||
|
SET r := CONCAT(r,LPAD(CONV(LEAST(k,359),10,36),2,'0'),x,y,suf); # k = count of digits in number, bounded to be <= '9Z' base-36
|
||||||
|
ELSE # encode a version number (like 3.12.707, etc)
|
||||||
|
SET r := CONCAT(r,LPAD(CONV(LEAST(k,359),10,36),2,'0'),x); # k = count of digits in number, bounded to be <= '9Z' base-36
|
||||||
|
WHILE CHAR_LENGTH(y)>0 AND n!=0 DO
|
||||||
|
IF i=0 THEN SET x := SUBSTRING(y,2); SET y := ''; ELSE SET x := SUBSTRING(y,2,i-2); SET y := SUBSTRING(y,i); SET i := LOCATE('.',y,2); END IF;
|
||||||
|
SET j := CHAR_LENGTH(x);
|
||||||
|
SET x := TRIM(LEADING '0' FROM x); # strip leading zeros
|
||||||
|
SET k := CHAR_LENGTH(x);
|
||||||
|
SET r := CONCAT(r,LPAD(CONV(LEAST(k,359),10,36),2,'0'),x); # k = count of digits in number, bounded to be <= '9Z' base-36
|
||||||
|
SET suf := CONCAT(suf,LPAD(CONV(LEAST((j-k)*2,1294),10,36),2,'0')); # (j-k)*2 = (count of leading zeros)*2, bounded to fit within 2 base-36 digits
|
||||||
|
SET n := n-1;
|
||||||
|
END WHILE;
|
||||||
|
SET r := CONCAT(r,y,suf);
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
END
|
||||||
|
EOD
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mySQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE currencies CHANGE exchange_rate exchange_rate NUMERIC(11, 5) DEFAULT NULL COMMENT \'(DC2Type:big_decimal)\'');
|
||||||
|
$this->addSql('ALTER TABLE `groups` CHANGE permissions_data permissions_data LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\'');
|
||||||
|
$this->addSql('ALTER TABLE log CHANGE level level TINYINT(1) NOT NULL COMMENT \'(DC2Type:tinyint)\', CHANGE extra extra LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\'');
|
||||||
|
$this->addSql('ALTER TABLE oauth_tokens CHANGE expires_at expires_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('ALTER TABLE `pricedetails` CHANGE price price NUMERIC(11, 5) NOT NULL COMMENT \'(DC2Type:big_decimal)\'');
|
||||||
|
$this->addSql('ALTER TABLE project_bom_entries CHANGE price price NUMERIC(11, 5) DEFAULT NULL COMMENT \'(DC2Type:big_decimal)\'');
|
||||||
|
$this->addSql('ALTER TABLE `suppliers` CHANGE shipping_costs shipping_costs NUMERIC(11, 5) DEFAULT NULL COMMENT \'(DC2Type:big_decimal)\'');
|
||||||
|
$this->addSql('ALTER TABLE `users` CHANGE backup_codes backup_codes LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\', CHANGE settings settings LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\', CHANGE permissions_data permissions_data LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\'');
|
||||||
|
$this->addSql('ALTER TABLE webauthn_keys CHANGE public_key_credential_id public_key_credential_id LONGTEXT NOT NULL COMMENT \'(DC2Type:base64)\', CHANGE transports transports LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\', CHANGE trust_path trust_path LONGTEXT NOT NULL COMMENT \'(DC2Type:trust_path)\', CHANGE aaguid aaguid TINYTEXT NOT NULL COMMENT \'(DC2Type:aaguid)\', CHANGE credential_public_key credential_public_key LONGTEXT NOT NULL COMMENT \'(DC2Type:base64)\', CHANGE other_ui other_ui LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', CHANGE last_time_used last_time_used DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\'');
|
||||||
|
|
||||||
|
//Drop custom function
|
||||||
|
$this->addSql('DROP FUNCTION IF EXISTS NatSortKey');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sqLiteUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__currencies AS SELECT id, parent_id, id_preview_attachment, exchange_rate, iso_code, comment, not_selectable, name, last_modified, datetime_added, alternative_names FROM currencies');
|
||||||
|
$this->addSql('DROP TABLE currencies');
|
||||||
|
$this->addSql('CREATE TABLE currencies (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, parent_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, exchange_rate NUMERIC(11, 5) DEFAULT NULL, iso_code VARCHAR(255) NOT NULL, comment CLOB NOT NULL, not_selectable BOOLEAN NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, alternative_names CLOB DEFAULT NULL, CONSTRAINT FK_37C44693727ACA70 FOREIGN KEY (parent_id) REFERENCES currencies (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_37C44693EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES attachments (id) ON UPDATE NO ACTION ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO currencies (id, parent_id, id_preview_attachment, exchange_rate, iso_code, comment, not_selectable, name, last_modified, datetime_added, alternative_names) SELECT id, parent_id, id_preview_attachment, exchange_rate, iso_code, comment, not_selectable, name, last_modified, datetime_added, alternative_names FROM __temp__currencies');
|
||||||
|
$this->addSql('DROP TABLE __temp__currencies');
|
||||||
|
$this->addSql('CREATE INDEX IDX_37C44693EA7100A1 ON currencies (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX currency_idx_parent_name ON currencies (parent_id, name)');
|
||||||
|
$this->addSql('CREATE INDEX currency_idx_name ON currencies (name)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_37C44693727ACA70 ON currencies (parent_id)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__groups AS SELECT id, parent_id, id_preview_attachment, enforce_2fa, comment, not_selectable, name, last_modified, datetime_added, permissions_data, alternative_names FROM groups');
|
||||||
|
$this->addSql('DROP TABLE groups');
|
||||||
|
$this->addSql('CREATE TABLE groups (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, parent_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, enforce_2fa BOOLEAN NOT NULL, comment CLOB NOT NULL, not_selectable BOOLEAN NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, permissions_data CLOB NOT NULL, alternative_names CLOB DEFAULT NULL, CONSTRAINT FK_F06D3970727ACA70 FOREIGN KEY (parent_id) REFERENCES groups (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_F06D3970EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES attachments (id) ON UPDATE NO ACTION ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO groups (id, parent_id, id_preview_attachment, enforce_2fa, comment, not_selectable, name, last_modified, datetime_added, permissions_data, alternative_names) SELECT id, parent_id, id_preview_attachment, enforce_2fa, comment, not_selectable, name, last_modified, datetime_added, permissions_data, alternative_names FROM __temp__groups');
|
||||||
|
$this->addSql('DROP TABLE __temp__groups');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F06D3970EA7100A1 ON groups (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F06D3970727ACA70 ON groups (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX group_idx_name ON groups (name)');
|
||||||
|
$this->addSql('CREATE INDEX group_idx_parent_name ON groups (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__log AS SELECT id, id_user, datetime, level, target_id, target_type, extra, type, username FROM log');
|
||||||
|
$this->addSql('DROP TABLE log');
|
||||||
|
$this->addSql('CREATE TABLE log (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id_user INTEGER DEFAULT NULL, datetime DATETIME NOT NULL, level SMALLINT NOT NULL, target_id INTEGER NOT NULL, target_type SMALLINT NOT NULL, extra CLOB NOT NULL, type SMALLINT NOT NULL, username VARCHAR(255) NOT NULL, CONSTRAINT FK_8F3F68C56B3CA4B FOREIGN KEY (id_user) REFERENCES users (id) ON UPDATE NO ACTION ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO log (id, id_user, datetime, level, target_id, target_type, extra, type, username) SELECT id, id_user, datetime, level, target_id, target_type, extra, type, username FROM __temp__log');
|
||||||
|
$this->addSql('DROP TABLE __temp__log');
|
||||||
|
$this->addSql('CREATE INDEX IDX_8F3F68C56B3CA4B ON log (id_user)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_type ON log (type)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_type_target ON log (type, target_type, target_id)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_datetime ON log (datetime)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__oauth_tokens AS SELECT id, token, expires_at, refresh_token, name, last_modified, datetime_added FROM oauth_tokens');
|
||||||
|
$this->addSql('DROP TABLE oauth_tokens');
|
||||||
|
$this->addSql('CREATE TABLE oauth_tokens (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, token CLOB DEFAULT NULL, expires_at DATETIME DEFAULT NULL, refresh_token CLOB DEFAULT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL)');
|
||||||
|
$this->addSql('INSERT INTO oauth_tokens (id, token, expires_at, refresh_token, name, last_modified, datetime_added) SELECT id, token, expires_at, refresh_token, name, last_modified, datetime_added FROM __temp__oauth_tokens');
|
||||||
|
$this->addSql('DROP TABLE __temp__oauth_tokens');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX oauth_tokens_unique_name ON oauth_tokens (name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__pricedetails AS SELECT id, id_currency, orderdetails_id, price, price_related_quantity, min_discount_quantity, manual_input, last_modified, datetime_added FROM pricedetails');
|
||||||
|
$this->addSql('DROP TABLE pricedetails');
|
||||||
|
$this->addSql('CREATE TABLE pricedetails (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id_currency INTEGER DEFAULT NULL, orderdetails_id INTEGER NOT NULL, price NUMERIC(11, 5) NOT NULL, price_related_quantity DOUBLE PRECISION NOT NULL, min_discount_quantity DOUBLE PRECISION NOT NULL, manual_input BOOLEAN NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, CONSTRAINT FK_C68C4459398D64AA FOREIGN KEY (id_currency) REFERENCES currencies (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_C68C44594A01DDC7 FOREIGN KEY (orderdetails_id) REFERENCES orderdetails (id) ON UPDATE NO ACTION ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO pricedetails (id, id_currency, orderdetails_id, price, price_related_quantity, min_discount_quantity, manual_input, last_modified, datetime_added) SELECT id, id_currency, orderdetails_id, price, price_related_quantity, min_discount_quantity, manual_input, last_modified, datetime_added FROM __temp__pricedetails');
|
||||||
|
$this->addSql('DROP TABLE __temp__pricedetails');
|
||||||
|
$this->addSql('CREATE INDEX pricedetails_idx_min_discount_price_qty ON pricedetails (min_discount_quantity, price_related_quantity)');
|
||||||
|
$this->addSql('CREATE INDEX pricedetails_idx_min_discount ON pricedetails (min_discount_quantity)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_C68C4459398D64AA ON pricedetails (id_currency)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_C68C44594A01DDC7 ON pricedetails (orderdetails_id)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__project_bom_entries AS SELECT id, id_device, id_part, price_currency_id, quantity, mountnames, name, comment, price, last_modified, datetime_added FROM project_bom_entries');
|
||||||
|
$this->addSql('DROP TABLE project_bom_entries');
|
||||||
|
$this->addSql('CREATE TABLE project_bom_entries (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id_device INTEGER DEFAULT NULL, id_part INTEGER DEFAULT NULL, price_currency_id INTEGER DEFAULT NULL, quantity DOUBLE PRECISION NOT NULL, mountnames CLOB NOT NULL, name VARCHAR(255) DEFAULT NULL, comment CLOB NOT NULL, price NUMERIC(11, 5) DEFAULT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, CONSTRAINT FK_AFC547992F180363 FOREIGN KEY (id_device) REFERENCES projects (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_AFC54799C22F6CC4 FOREIGN KEY (id_part) REFERENCES parts (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1AA2DD313FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO project_bom_entries (id, id_device, id_part, price_currency_id, quantity, mountnames, name, comment, price, last_modified, datetime_added) SELECT id, id_device, id_part, price_currency_id, quantity, mountnames, name, comment, price, last_modified, datetime_added FROM __temp__project_bom_entries');
|
||||||
|
$this->addSql('DROP TABLE __temp__project_bom_entries');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD313FFDCD60 ON project_bom_entries (price_currency_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD312F180363 ON project_bom_entries (id_device)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD31C22F6CC4 ON project_bom_entries (id_part)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__suppliers AS SELECT id, parent_id, default_currency_id, id_preview_attachment, shipping_costs, address, phone_number, fax_number, email_address, website, auto_product_url, comment, not_selectable, name, last_modified, datetime_added, alternative_names FROM suppliers');
|
||||||
|
$this->addSql('DROP TABLE suppliers');
|
||||||
|
$this->addSql('CREATE TABLE suppliers (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, parent_id INTEGER DEFAULT NULL, default_currency_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, shipping_costs NUMERIC(11, 5) DEFAULT NULL, address VARCHAR(255) NOT NULL, phone_number VARCHAR(255) NOT NULL, fax_number VARCHAR(255) NOT NULL, email_address VARCHAR(255) NOT NULL, website VARCHAR(255) NOT NULL, auto_product_url VARCHAR(255) NOT NULL, comment CLOB NOT NULL, not_selectable BOOLEAN NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, alternative_names CLOB DEFAULT NULL, CONSTRAINT FK_AC28B95C727ACA70 FOREIGN KEY (parent_id) REFERENCES suppliers (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_AC28B95CECD792C0 FOREIGN KEY (default_currency_id) REFERENCES currencies (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_AC28B95CEA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES attachments (id) ON UPDATE NO ACTION ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO suppliers (id, parent_id, default_currency_id, id_preview_attachment, shipping_costs, address, phone_number, fax_number, email_address, website, auto_product_url, comment, not_selectable, name, last_modified, datetime_added, alternative_names) SELECT id, parent_id, default_currency_id, id_preview_attachment, shipping_costs, address, phone_number, fax_number, email_address, website, auto_product_url, comment, not_selectable, name, last_modified, datetime_added, alternative_names FROM __temp__suppliers');
|
||||||
|
$this->addSql('DROP TABLE __temp__suppliers');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95CEA7100A1 ON suppliers (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX supplier_idx_parent_name ON suppliers (parent_id, name)');
|
||||||
|
$this->addSql('CREATE INDEX supplier_idx_name ON suppliers (name)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95C727ACA70 ON suppliers (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95CECD792C0 ON suppliers (default_currency_id)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__users AS SELECT id, group_id, currency_id, id_preview_attachment, disabled, config_theme, pw_reset_token, config_instock_comment_a, config_instock_comment_w, trusted_device_cookie_version, backup_codes, google_authenticator_secret, config_timezone, config_language, email, department, last_name, first_name, need_pw_change, password, name, settings, backup_codes_generation_date, pw_reset_expires, last_modified, datetime_added, permissions_data, saml_user, about_me, show_email_on_profile FROM users');
|
||||||
|
$this->addSql('DROP TABLE users');
|
||||||
|
$this->addSql('CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, group_id INTEGER DEFAULT NULL, currency_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, disabled BOOLEAN NOT NULL, config_theme VARCHAR(255) DEFAULT NULL, pw_reset_token VARCHAR(255) DEFAULT NULL, config_instock_comment_a CLOB NOT NULL, config_instock_comment_w CLOB NOT NULL, trusted_device_cookie_version INTEGER NOT NULL, backup_codes CLOB NOT NULL, google_authenticator_secret VARCHAR(255) DEFAULT NULL, config_timezone VARCHAR(255) DEFAULT NULL, config_language VARCHAR(255) DEFAULT NULL, email VARCHAR(255) DEFAULT NULL, department VARCHAR(255) DEFAULT NULL, last_name VARCHAR(255) DEFAULT NULL, first_name VARCHAR(255) DEFAULT NULL, need_pw_change BOOLEAN NOT NULL, password VARCHAR(255) DEFAULT NULL, name VARCHAR(180) NOT NULL, settings CLOB NOT NULL, backup_codes_generation_date DATETIME DEFAULT NULL, pw_reset_expires DATETIME DEFAULT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, permissions_data CLOB NOT NULL, saml_user BOOLEAN NOT NULL, about_me CLOB NOT NULL, show_email_on_profile BOOLEAN DEFAULT 0 NOT NULL, CONSTRAINT FK_1483A5E9FE54D947 FOREIGN KEY (group_id) REFERENCES groups (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1483A5E938248176 FOREIGN KEY (currency_id) REFERENCES currencies (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1483A5E9EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES attachments (id) ON UPDATE NO ACTION ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO users (id, group_id, currency_id, id_preview_attachment, disabled, config_theme, pw_reset_token, config_instock_comment_a, config_instock_comment_w, trusted_device_cookie_version, backup_codes, google_authenticator_secret, config_timezone, config_language, email, department, last_name, first_name, need_pw_change, password, name, settings, backup_codes_generation_date, pw_reset_expires, last_modified, datetime_added, permissions_data, saml_user, about_me, show_email_on_profile) SELECT id, group_id, currency_id, id_preview_attachment, disabled, config_theme, pw_reset_token, config_instock_comment_a, config_instock_comment_w, trusted_device_cookie_version, backup_codes, google_authenticator_secret, config_timezone, config_language, email, department, last_name, first_name, need_pw_change, password, name, settings, backup_codes_generation_date, pw_reset_expires, last_modified, datetime_added, permissions_data, saml_user, about_me, show_email_on_profile FROM __temp__users');
|
||||||
|
$this->addSql('DROP TABLE __temp__users');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E9EA7100A1 ON users (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E938248176 ON users (currency_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E9FE54D947 ON users (group_id)');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_1483A5E95E237E06 ON users (name)');
|
||||||
|
$this->addSql('CREATE INDEX user_idx_username ON users (name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__webauthn_keys AS SELECT id, user_id, public_key_credential_id, type, transports, attestation_type, trust_path, aaguid, credential_public_key, user_handle, counter, name, last_modified, datetime_added, other_ui, backup_eligible, backup_status, uv_initialized, last_time_used FROM webauthn_keys');
|
||||||
|
$this->addSql('DROP TABLE webauthn_keys');
|
||||||
|
$this->addSql('CREATE TABLE webauthn_keys (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, user_id INTEGER DEFAULT NULL, public_key_credential_id CLOB NOT NULL, type VARCHAR(255) NOT NULL, transports CLOB NOT NULL, attestation_type VARCHAR(255) NOT NULL, trust_path CLOB NOT NULL, aaguid CLOB NOT NULL, credential_public_key CLOB NOT NULL, user_handle VARCHAR(255) NOT NULL, counter INTEGER NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, other_ui CLOB DEFAULT NULL, backup_eligible BOOLEAN DEFAULT NULL, backup_status BOOLEAN DEFAULT NULL, uv_initialized BOOLEAN DEFAULT NULL, last_time_used DATETIME DEFAULT NULL, CONSTRAINT FK_799FD143A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO webauthn_keys (id, user_id, public_key_credential_id, type, transports, attestation_type, trust_path, aaguid, credential_public_key, user_handle, counter, name, last_modified, datetime_added, other_ui, backup_eligible, backup_status, uv_initialized, last_time_used) SELECT id, user_id, public_key_credential_id, type, transports, attestation_type, trust_path, aaguid, credential_public_key, user_handle, counter, name, last_modified, datetime_added, other_ui, backup_eligible, backup_status, uv_initialized, last_time_used FROM __temp__webauthn_keys');
|
||||||
|
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
||||||
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sqLiteDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__currencies AS SELECT id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, exchange_rate, iso_code, parent_id, id_preview_attachment FROM currencies');
|
||||||
|
$this->addSql('DROP TABLE currencies');
|
||||||
|
$this->addSql('CREATE TABLE currencies (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, comment CLOB NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names CLOB DEFAULT NULL, exchange_rate NUMERIC(11, 5) DEFAULT NULL --(DC2Type:big_decimal)
|
||||||
|
, iso_code VARCHAR(255) NOT NULL, parent_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, CONSTRAINT FK_37C44693727ACA70 FOREIGN KEY (parent_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_37C44693EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO currencies (id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, exchange_rate, iso_code, parent_id, id_preview_attachment) SELECT id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, exchange_rate, iso_code, parent_id, id_preview_attachment FROM __temp__currencies');
|
||||||
|
$this->addSql('DROP TABLE __temp__currencies');
|
||||||
|
$this->addSql('CREATE INDEX IDX_37C44693727ACA70 ON currencies (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_37C44693EA7100A1 ON currencies (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX currency_idx_name ON currencies (name)');
|
||||||
|
$this->addSql('CREATE INDEX currency_idx_parent_name ON currencies (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__groups AS SELECT id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, enforce_2fa, permissions_data, parent_id, id_preview_attachment FROM "groups"');
|
||||||
|
$this->addSql('DROP TABLE "groups"');
|
||||||
|
$this->addSql('CREATE TABLE "groups" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, comment CLOB NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names CLOB DEFAULT NULL, enforce_2fa BOOLEAN NOT NULL, permissions_data CLOB NOT NULL --(DC2Type:json)
|
||||||
|
, parent_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, CONSTRAINT FK_F06D3970727ACA70 FOREIGN KEY (parent_id) REFERENCES "groups" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_F06D3970EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO "groups" (id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, enforce_2fa, permissions_data, parent_id, id_preview_attachment) SELECT id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, enforce_2fa, permissions_data, parent_id, id_preview_attachment FROM __temp__groups');
|
||||||
|
$this->addSql('DROP TABLE __temp__groups');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F06D3970727ACA70 ON "groups" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_F06D3970EA7100A1 ON "groups" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX group_idx_name ON "groups" (name)');
|
||||||
|
$this->addSql('CREATE INDEX group_idx_parent_name ON "groups" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__log AS SELECT id, username, datetime, level, target_id, target_type, extra, id_user, type FROM log');
|
||||||
|
$this->addSql('DROP TABLE log');
|
||||||
|
$this->addSql('CREATE TABLE log (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(255) NOT NULL, datetime DATETIME NOT NULL, level BOOLEAN NOT NULL --(DC2Type:tinyint)
|
||||||
|
, target_id INTEGER NOT NULL, target_type SMALLINT NOT NULL, extra CLOB NOT NULL --(DC2Type:json)
|
||||||
|
, id_user INTEGER DEFAULT NULL, type SMALLINT NOT NULL, CONSTRAINT FK_8F3F68C56B3CA4B FOREIGN KEY (id_user) REFERENCES "users" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO log (id, username, datetime, level, target_id, target_type, extra, id_user, type) SELECT id, username, datetime, level, target_id, target_type, extra, id_user, type FROM __temp__log');
|
||||||
|
$this->addSql('DROP TABLE __temp__log');
|
||||||
|
$this->addSql('CREATE INDEX IDX_8F3F68C56B3CA4B ON log (id_user)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_type ON log (type)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_type_target ON log (type, target_type, target_id)');
|
||||||
|
$this->addSql('CREATE INDEX log_idx_datetime ON log (datetime)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__oauth_tokens AS SELECT id, name, last_modified, datetime_added, token, expires_at, refresh_token FROM oauth_tokens');
|
||||||
|
$this->addSql('DROP TABLE oauth_tokens');
|
||||||
|
$this->addSql('CREATE TABLE oauth_tokens (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, token CLOB DEFAULT NULL, expires_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
|
||||||
|
, refresh_token CLOB DEFAULT NULL)');
|
||||||
|
$this->addSql('INSERT INTO oauth_tokens (id, name, last_modified, datetime_added, token, expires_at, refresh_token) SELECT id, name, last_modified, datetime_added, token, expires_at, refresh_token FROM __temp__oauth_tokens');
|
||||||
|
$this->addSql('DROP TABLE __temp__oauth_tokens');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX oauth_tokens_unique_name ON oauth_tokens (name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__pricedetails AS SELECT id, price, price_related_quantity, min_discount_quantity, manual_input, last_modified, datetime_added, id_currency, orderdetails_id FROM "pricedetails"');
|
||||||
|
$this->addSql('DROP TABLE "pricedetails"');
|
||||||
|
$this->addSql('CREATE TABLE "pricedetails" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, price NUMERIC(11, 5) NOT NULL --(DC2Type:big_decimal)
|
||||||
|
, price_related_quantity DOUBLE PRECISION NOT NULL, min_discount_quantity DOUBLE PRECISION NOT NULL, manual_input BOOLEAN NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, id_currency INTEGER DEFAULT NULL, orderdetails_id INTEGER NOT NULL, CONSTRAINT FK_C68C4459398D64AA FOREIGN KEY (id_currency) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_C68C44594A01DDC7 FOREIGN KEY (orderdetails_id) REFERENCES "orderdetails" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO "pricedetails" (id, price, price_related_quantity, min_discount_quantity, manual_input, last_modified, datetime_added, id_currency, orderdetails_id) SELECT id, price, price_related_quantity, min_discount_quantity, manual_input, last_modified, datetime_added, id_currency, orderdetails_id FROM __temp__pricedetails');
|
||||||
|
$this->addSql('DROP TABLE __temp__pricedetails');
|
||||||
|
$this->addSql('CREATE INDEX IDX_C68C4459398D64AA ON "pricedetails" (id_currency)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_C68C44594A01DDC7 ON "pricedetails" (orderdetails_id)');
|
||||||
|
$this->addSql('CREATE INDEX pricedetails_idx_min_discount ON "pricedetails" (min_discount_quantity)');
|
||||||
|
$this->addSql('CREATE INDEX pricedetails_idx_min_discount_price_qty ON "pricedetails" (min_discount_quantity, price_related_quantity)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__project_bom_entries AS SELECT id, quantity, mountnames, name, comment, price, last_modified, datetime_added, id_device, id_part, price_currency_id FROM project_bom_entries');
|
||||||
|
$this->addSql('DROP TABLE project_bom_entries');
|
||||||
|
$this->addSql('CREATE TABLE project_bom_entries (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, quantity DOUBLE PRECISION NOT NULL, mountnames CLOB NOT NULL, name VARCHAR(255) DEFAULT NULL, comment CLOB NOT NULL, price NUMERIC(11, 5) DEFAULT NULL --(DC2Type:big_decimal)
|
||||||
|
, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, id_device INTEGER DEFAULT NULL, id_part INTEGER DEFAULT NULL, price_currency_id INTEGER DEFAULT NULL, CONSTRAINT FK_1AA2DD312F180363 FOREIGN KEY (id_device) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1AA2DD31C22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1AA2DD313FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO project_bom_entries (id, quantity, mountnames, name, comment, price, last_modified, datetime_added, id_device, id_part, price_currency_id) SELECT id, quantity, mountnames, name, comment, price, last_modified, datetime_added, id_device, id_part, price_currency_id FROM __temp__project_bom_entries');
|
||||||
|
$this->addSql('DROP TABLE __temp__project_bom_entries');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD312F180363 ON project_bom_entries (id_device)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD31C22F6CC4 ON project_bom_entries (id_part)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1AA2DD313FFDCD60 ON project_bom_entries (price_currency_id)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__suppliers AS SELECT id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, address, phone_number, fax_number, email_address, website, auto_product_url, shipping_costs, parent_id, default_currency_id, id_preview_attachment FROM "suppliers"');
|
||||||
|
$this->addSql('DROP TABLE "suppliers"');
|
||||||
|
$this->addSql('CREATE TABLE "suppliers" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, comment CLOB NOT NULL, not_selectable BOOLEAN NOT NULL, alternative_names CLOB DEFAULT NULL, address VARCHAR(255) NOT NULL, phone_number VARCHAR(255) NOT NULL, fax_number VARCHAR(255) NOT NULL, email_address VARCHAR(255) NOT NULL, website VARCHAR(255) NOT NULL, auto_product_url VARCHAR(255) NOT NULL, shipping_costs NUMERIC(11, 5) DEFAULT NULL --(DC2Type:big_decimal)
|
||||||
|
, parent_id INTEGER DEFAULT NULL, default_currency_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, CONSTRAINT FK_AC28B95C727ACA70 FOREIGN KEY (parent_id) REFERENCES "suppliers" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_AC28B95CECD792C0 FOREIGN KEY (default_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_AC28B95CEA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO "suppliers" (id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, address, phone_number, fax_number, email_address, website, auto_product_url, shipping_costs, parent_id, default_currency_id, id_preview_attachment) SELECT id, name, last_modified, datetime_added, comment, not_selectable, alternative_names, address, phone_number, fax_number, email_address, website, auto_product_url, shipping_costs, parent_id, default_currency_id, id_preview_attachment FROM __temp__suppliers');
|
||||||
|
$this->addSql('DROP TABLE __temp__suppliers');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95C727ACA70 ON "suppliers" (parent_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95CECD792C0 ON "suppliers" (default_currency_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_AC28B95CEA7100A1 ON "suppliers" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX supplier_idx_name ON "suppliers" (name)');
|
||||||
|
$this->addSql('CREATE INDEX supplier_idx_parent_name ON "suppliers" (parent_id, name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__users AS SELECT id, last_modified, datetime_added, disabled, config_theme, pw_reset_token, config_instock_comment_a, config_instock_comment_w, about_me, trusted_device_cookie_version, backup_codes, google_authenticator_secret, config_timezone, config_language, email, show_email_on_profile, department, last_name, first_name, need_pw_change, password, settings, backup_codes_generation_date, pw_reset_expires, saml_user, name, permissions_data, group_id, id_preview_attachment, currency_id FROM "users"');
|
||||||
|
$this->addSql('DROP TABLE "users"');
|
||||||
|
$this->addSql('CREATE TABLE "users" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, disabled BOOLEAN NOT NULL, config_theme VARCHAR(255) DEFAULT NULL, pw_reset_token VARCHAR(255) DEFAULT NULL, config_instock_comment_a CLOB NOT NULL, config_instock_comment_w CLOB NOT NULL, about_me CLOB NOT NULL, trusted_device_cookie_version INTEGER NOT NULL, backup_codes CLOB NOT NULL --(DC2Type:json)
|
||||||
|
, google_authenticator_secret VARCHAR(255) DEFAULT NULL, config_timezone VARCHAR(255) DEFAULT NULL, config_language VARCHAR(255) DEFAULT NULL, email VARCHAR(255) DEFAULT NULL, show_email_on_profile BOOLEAN DEFAULT 0 NOT NULL, department VARCHAR(255) DEFAULT NULL, last_name VARCHAR(255) DEFAULT NULL, first_name VARCHAR(255) DEFAULT NULL, need_pw_change BOOLEAN NOT NULL, password VARCHAR(255) DEFAULT NULL, settings CLOB NOT NULL --(DC2Type:json)
|
||||||
|
, backup_codes_generation_date DATETIME DEFAULT NULL, pw_reset_expires DATETIME DEFAULT NULL, saml_user BOOLEAN NOT NULL, name VARCHAR(180) NOT NULL, permissions_data CLOB NOT NULL --(DC2Type:json)
|
||||||
|
, group_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, currency_id INTEGER DEFAULT NULL, CONSTRAINT FK_1483A5E9FE54D947 FOREIGN KEY (group_id) REFERENCES "groups" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1483A5E9EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1483A5E938248176 FOREIGN KEY (currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO "users" (id, last_modified, datetime_added, disabled, config_theme, pw_reset_token, config_instock_comment_a, config_instock_comment_w, about_me, trusted_device_cookie_version, backup_codes, google_authenticator_secret, config_timezone, config_language, email, show_email_on_profile, department, last_name, first_name, need_pw_change, password, settings, backup_codes_generation_date, pw_reset_expires, saml_user, name, permissions_data, group_id, id_preview_attachment, currency_id) SELECT id, last_modified, datetime_added, disabled, config_theme, pw_reset_token, config_instock_comment_a, config_instock_comment_w, about_me, trusted_device_cookie_version, backup_codes, google_authenticator_secret, config_timezone, config_language, email, show_email_on_profile, department, last_name, first_name, need_pw_change, password, settings, backup_codes_generation_date, pw_reset_expires, saml_user, name, permissions_data, group_id, id_preview_attachment, currency_id FROM __temp__users');
|
||||||
|
$this->addSql('DROP TABLE __temp__users');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_1483A5E95E237E06 ON "users" (name)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E9FE54D947 ON "users" (group_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E9EA7100A1 ON "users" (id_preview_attachment)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1483A5E938248176 ON "users" (currency_id)');
|
||||||
|
$this->addSql('CREATE INDEX user_idx_username ON "users" (name)');
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__webauthn_keys AS SELECT public_key_credential_id, type, transports, attestation_type, trust_path, aaguid, credential_public_key, user_handle, counter, other_ui, backup_eligible, backup_status, uv_initialized, id, name, last_time_used, last_modified, datetime_added, user_id FROM webauthn_keys');
|
||||||
|
$this->addSql('DROP TABLE webauthn_keys');
|
||||||
|
$this->addSql('CREATE TABLE webauthn_keys (public_key_credential_id CLOB NOT NULL --(DC2Type:base64)
|
||||||
|
, type VARCHAR(255) NOT NULL, transports CLOB NOT NULL --(DC2Type:array)
|
||||||
|
, attestation_type VARCHAR(255) NOT NULL, trust_path CLOB NOT NULL --(DC2Type:trust_path)
|
||||||
|
, aaguid CLOB NOT NULL --(DC2Type:aaguid)
|
||||||
|
, credential_public_key CLOB NOT NULL --(DC2Type:base64)
|
||||||
|
, user_handle VARCHAR(255) NOT NULL, counter INTEGER NOT NULL, other_ui CLOB DEFAULT NULL --(DC2Type:array)
|
||||||
|
, backup_eligible BOOLEAN DEFAULT NULL, backup_status BOOLEAN DEFAULT NULL, uv_initialized BOOLEAN DEFAULT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, last_time_used DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
|
||||||
|
, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, user_id INTEGER DEFAULT NULL, CONSTRAINT FK_799FD143A76ED395 FOREIGN KEY (user_id) REFERENCES "users" (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
||||||
|
$this->addSql('INSERT INTO webauthn_keys (public_key_credential_id, type, transports, attestation_type, trust_path, aaguid, credential_public_key, user_handle, counter, other_ui, backup_eligible, backup_status, uv_initialized, id, name, last_time_used, last_modified, datetime_added, user_id) SELECT public_key_credential_id, type, transports, attestation_type, trust_path, aaguid, credential_public_key, user_handle, counter, other_ui, backup_eligible, backup_status, uv_initialized, id, name, last_time_used, last_modified, datetime_added, user_id FROM __temp__webauthn_keys');
|
||||||
|
$this->addSql('DROP TABLE __temp__webauthn_keys');
|
||||||
|
$this->addSql('CREATE INDEX IDX_799FD143A76ED395 ON webauthn_keys (user_id)');
|
||||||
|
}
|
||||||
|
}
|
165
migrations/Version20240728145604.php
Normal file
165
migrations/Version20240728145604.php
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use App\Migration\AbstractMultiPlatformMigration;
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20240728145604 extends AbstractMultiPlatformMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Update the Natural Sorting function for MySQL';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function mySQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Remove the old function
|
||||||
|
$this->addSql('DROP FUNCTION IF EXISTS NatSortKey');
|
||||||
|
|
||||||
|
//The difference to the original function is the correct length of the suf variable and correct escaping
|
||||||
|
//We now use heredoc syntax to avoid escaping issues with the \ (which resulted in "range out of order in character class").
|
||||||
|
$this->addSql(<<<'EOD'
|
||||||
|
CREATE DEFINER=CURRENT_USER FUNCTION `NatSortKey`(`s` VARCHAR(1000) CHARSET utf8mb4, `n` INT) RETURNS varchar(3500) CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci
|
||||||
|
DETERMINISTIC
|
||||||
|
SQL SECURITY INVOKER
|
||||||
|
BEGIN
|
||||||
|
/****
|
||||||
|
Converts numbers in the input string s into a format such that sorting results in a nat-sort.
|
||||||
|
Numbers of up to 359 digits (before the decimal point, if one is present) are supported. Sort results are undefined if the input string contains numbers longer than this.
|
||||||
|
For n>0, only the first n numbers in the input string will be converted for nat-sort (so strings that differ only after the first n numbers will not nat-sort amongst themselves).
|
||||||
|
Total sort-ordering is preserved, i.e. if s1!=s2, then NatSortKey(s1,n)!=NatSortKey(s2,n), for any given n.
|
||||||
|
Numbers may contain ',' as a thousands separator, and '.' as a decimal point. To reverse these (as appropriate for some European locales), the code would require modification.
|
||||||
|
Numbers preceded by '+' sort with numbers not preceded with either a '+' or '-' sign.
|
||||||
|
Negative numbers (preceded with '-') sort before positive numbers, but are sorted in order of ascending absolute value (so -7 sorts BEFORE -1001).
|
||||||
|
Numbers with leading zeros sort after the same number with no (or fewer) leading zeros.
|
||||||
|
Decimal-part-only numbers (like .75) are recognised, provided the decimal point is not immediately preceded by either another '.', or by a letter-type character.
|
||||||
|
Numbers with thousand separators sort after the same number without them.
|
||||||
|
Thousand separators are only recognised in numbers with no leading zeros that don't immediately follow a ',', and when they format the number correctly.
|
||||||
|
(When not recognised as a thousand separator, a ',' will instead be treated as separating two distinct numbers).
|
||||||
|
Version-number-like sequences consisting of 3 or more numbers separated by '.' are treated as distinct entities, and each component number will be nat-sorted.
|
||||||
|
The entire entity will sort after any number beginning with the first component (so e.g. 10.2.1 sorts after both 10 and 10.995, but before 11)
|
||||||
|
Note that The first number component in an entity like this is also permitted to contain thousand separators.
|
||||||
|
|
||||||
|
To achieve this, numbers within the input string are prefixed and suffixed according to the following format:
|
||||||
|
- The number is prefixed by a 2-digit base-36 number representing its length, excluding leading zeros. If there is a decimal point, this length only includes the integer part of the number.
|
||||||
|
- A 3-character suffix is appended after the number (after the decimals if present).
|
||||||
|
- The first character is a space, or a '+' sign if the number was preceded by '+'. Any preceding '+' sign is also removed from the front of the number.
|
||||||
|
- This is followed by a 2-digit base-36 number that encodes the number of leading zeros and whether the number was expressed in comma-separated form (e.g. 1,000,000.25 vs 1000000.25)
|
||||||
|
- The value of this 2-digit number is: (number of leading zeros)*2 + (1 if comma-separated, 0 otherwise)
|
||||||
|
- For version number sequences, each component number has the prefix in front of it, and the separating dots are removed.
|
||||||
|
Then there is a single suffix that consists of a ' ' or '+' character, followed by a pair base-36 digits for each number component in the sequence.
|
||||||
|
|
||||||
|
e.g. here is how some simple sample strings get converted:
|
||||||
|
'Foo055' --> 'Foo0255 02'
|
||||||
|
'Absolute zero is around -273 centigrade' --> 'Absolute zero is around -03273 00 centigrade'
|
||||||
|
'The $1,000,000 prize' --> 'The $071000000 01 prize'
|
||||||
|
'+99.74 degrees' --> '0299.74+00 degrees'
|
||||||
|
'I have 0 apples' --> 'I have 00 02 apples'
|
||||||
|
'.5 is the same value as 0000.5000' --> '00.5 00 is the same value as 00.5000 08'
|
||||||
|
'MariaDB v10.3.0018' --> 'MariaDB v02100130218 000004'
|
||||||
|
|
||||||
|
The restriction to numbers of up to 359 digits comes from the fact that the first character of the base-36 prefix MUST be a decimal digit, and so the highest permitted prefix value is '9Z' or 359 decimal.
|
||||||
|
The code could be modified to handle longer numbers by increasing the size of (both) the prefix and suffix.
|
||||||
|
A higher base could also be used (by replacing CONV() with a custom function), provided that the collation you are using sorts the "digits" of the base in the correct order, starting with 0123456789.
|
||||||
|
However, while the maximum number length may be increased this way, note that the technique this function uses is NOT applicable where strings may contain numbers of unlimited length.
|
||||||
|
|
||||||
|
The function definition does not specify the charset or collation to be used for string-type parameters or variables: The default database charset & collation at the time the function is defined will be used.
|
||||||
|
This is to make the function code more portable. However, there are some important restrictions:
|
||||||
|
|
||||||
|
- Collation is important here only when comparing (or storing) the output value from this function, but it MUST order the characters " +0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" in that order for the natural sort to work.
|
||||||
|
This is true for most collations, but not all of them, e.g. in Lithuanian 'Y' comes before 'J' (according to Wikipedia).
|
||||||
|
To adapt the function to work with such collations, replace CONV() in the function code with a custom function that emits "digits" above 9 that are characters ordered according to the collation in use.
|
||||||
|
|
||||||
|
- For efficiency, the function code uses LENGTH() rather than CHAR_LENGTH() to measure the length of strings that consist only of digits 0-9, '.', and ',' characters.
|
||||||
|
This works for any single-byte charset, as well as any charset that maps standard ASCII characters to single bytes (such as utf8 or utf8mb4).
|
||||||
|
If using a charset that maps these characters to multiple bytes (such as, e.g. utf16 or utf32), you MUST replace all instances of LENGTH() in the function definition with CHAR_LENGTH()
|
||||||
|
|
||||||
|
Length of the output:
|
||||||
|
|
||||||
|
Each number converted adds 5 characters (2 prefix + 3 suffix) to the length of the string. n is the maximum count of numbers to convert;
|
||||||
|
This parameter is provided as a means to limit the maximum output length (to input length + 5*n).
|
||||||
|
If you do not require the total-ordering property, you could edit the code to use suffixes of 1 character (space or plus) only; this would reduce the maximum output length for any given n.
|
||||||
|
Since a string of length L has at most ((L+1) DIV 2) individual numbers in it (every 2nd character a digit), for n<=0 the maximum output length is (inputlength + 5*((inputlength+1) DIV 2))
|
||||||
|
So for the current input length of 100, the maximum output length is 350.
|
||||||
|
If changing the input length, the output length must be modified according to the above formula. The DECLARE statements for x,y,r, and suf must also be modified, as the code comments indicate.
|
||||||
|
****/
|
||||||
|
|
||||||
|
DECLARE x,y varchar(1000); # need to be same length as input s
|
||||||
|
DECLARE r varchar(3500) DEFAULT ''; # return value: needs to be same length as return type
|
||||||
|
DECLARE suf varchar(1001); # suffix for a number or version string. Must be (((inputlength+1) DIV 2)*2 + 1) chars to support version strings (e.g. '1.2.33.5'), though it's usually just 3 chars. (Max version string e.g. 1.2. ... .5 has ((length of input + 1) DIV 2) numeric components)
|
||||||
|
DECLARE i,j,k int UNSIGNED;
|
||||||
|
IF n<=0 THEN SET n := -1; END IF; # n<=0 means "process all numbers"
|
||||||
|
LOOP
|
||||||
|
SET i := REGEXP_INSTR(s,'\\d'); # find position of next digit
|
||||||
|
IF i=0 OR n=0 THEN RETURN CONCAT(r,s); END IF; # no more numbers to process -> we're done
|
||||||
|
SET n := n-1, suf := ' ';
|
||||||
|
IF i>1 THEN
|
||||||
|
IF SUBSTRING(s,i-1,1)='.' AND (i=2 OR SUBSTRING(s,i-2,1) RLIKE '[^.\\p{L}\\p{N}\\p{M}\\x{608}\\x{200C}\\x{200D}\\x{2100}-\\x{214F}\\x{24B6}-\\x{24E9}\\x{1F130}-\\x{1F149}\\x{1F150}-\\x{1F169}\\x{1F170}-\\x{1F189}]') AND (SUBSTRING(s,i) NOT RLIKE '^\\d++\\.\\d') THEN SET i:=i-1; END IF; # Allow decimal number (but not version string) to begin with a '.', provided preceding char is neither another '.', nor a member of the unicode character classes: "Alphabetic", "Letter", "Block=Letterlike Symbols" "Number", "Mark", "Join_Control"
|
||||||
|
IF i>1 AND SUBSTRING(s,i-1,1)='+' THEN SET suf := '+', j := i-1; ELSE SET j := i; END IF; # move any preceding '+' into the suffix, so equal numbers with and without preceding "+" signs sort together
|
||||||
|
SET r := CONCAT(r,SUBSTRING(s,1,j-1)); SET s = SUBSTRING(s,i); # add everything before the number to r and strip it from the start of s; preceding '+' is dropped (not included in either r or s)
|
||||||
|
END IF;
|
||||||
|
SET x := REGEXP_SUBSTR(s,IF(SUBSTRING(s,1,1) IN ('0','.') OR (SUBSTRING(r,-1)=',' AND suf=' '),'^\\d*+(?:\\.\\d++)*','^(?:[1-9]\\d{0,2}(?:,\\d{3}(?!\\d))++|\\d++)(?:\\.\\d++)*+')); # capture the number + following decimals (including multiple consecutive '.<digits>' sequences)
|
||||||
|
SET s := SUBSTRING(s,CHAR_LENGTH(x)+1); # NOTE: CHAR_LENGTH() can be safely used instead of CHAR_LENGTH() here & below PROVIDED we're using a charset that represents digits, ',' and '.' characters using single bytes (e.g. latin1, utf8)
|
||||||
|
SET i := INSTR(x,'.');
|
||||||
|
IF i=0 THEN SET y := ''; ELSE SET y := SUBSTRING(x,i); SET x := SUBSTRING(x,1,i-1); END IF; # move any following decimals into y
|
||||||
|
SET i := CHAR_LENGTH(x);
|
||||||
|
SET x := REPLACE(x,',','');
|
||||||
|
SET j := CHAR_LENGTH(x);
|
||||||
|
SET x := TRIM(LEADING '0' FROM x); # strip leading zeros
|
||||||
|
SET k := CHAR_LENGTH(x);
|
||||||
|
SET suf := CONCAT(suf,LPAD(CONV(LEAST((j-k)*2,1294) + IF(i=j,0,1),10,36),2,'0')); # (j-k)*2 + IF(i=j,0,1) = (count of leading zeros)*2 + (1 if there are thousands-separators, 0 otherwise) Note the first term is bounded to <= base-36 'ZY' as it must fit within 2 characters
|
||||||
|
SET i := LOCATE('.',y,2);
|
||||||
|
IF i=0 THEN
|
||||||
|
SET r := CONCAT(r,LPAD(CONV(LEAST(k,359),10,36),2,'0'),x,y,suf); # k = count of digits in number, bounded to be <= '9Z' base-36
|
||||||
|
ELSE # encode a version number (like 3.12.707, etc)
|
||||||
|
SET r := CONCAT(r,LPAD(CONV(LEAST(k,359),10,36),2,'0'),x); # k = count of digits in number, bounded to be <= '9Z' base-36
|
||||||
|
WHILE CHAR_LENGTH(y)>0 AND n!=0 DO
|
||||||
|
IF i=0 THEN SET x := SUBSTRING(y,2); SET y := ''; ELSE SET x := SUBSTRING(y,2,i-2); SET y := SUBSTRING(y,i); SET i := LOCATE('.',y,2); END IF;
|
||||||
|
SET j := CHAR_LENGTH(x);
|
||||||
|
SET x := TRIM(LEADING '0' FROM x); # strip leading zeros
|
||||||
|
SET k := CHAR_LENGTH(x);
|
||||||
|
SET r := CONCAT(r,LPAD(CONV(LEAST(k,359),10,36),2,'0'),x); # k = count of digits in number, bounded to be <= '9Z' base-36
|
||||||
|
SET suf := CONCAT(suf,LPAD(CONV(LEAST((j-k)*2,1294),10,36),2,'0')); # (j-k)*2 = (count of leading zeros)*2, bounded to fit within 2 base-36 digits
|
||||||
|
SET n := n-1;
|
||||||
|
END WHILE;
|
||||||
|
SET r := CONCAT(r,y,suf);
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
END
|
||||||
|
EOD
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mySQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Not needed
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sqLiteUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Not needed
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sqLiteDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Not needed
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Not needed
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Not needed
|
||||||
|
}
|
||||||
|
}
|
42
migrations/Version20250220215048.php
Normal file
42
migrations/Version20250220215048.php
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20250220215048 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Split $path property for attachments into $internal_path and $external_path';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Create the new columns as nullable (that is easier modifying them)
|
||||||
|
$this->addSql('ALTER TABLE attachments ADD internal_path VARCHAR(255) DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE attachments ADD external_path VARCHAR(255) DEFAULT NULL');
|
||||||
|
|
||||||
|
//Copy the data from path to external_path and remove the path column
|
||||||
|
$this->addSql('UPDATE attachments SET external_path=path');
|
||||||
|
$this->addSql('ALTER TABLE attachments DROP COLUMN path');
|
||||||
|
|
||||||
|
|
||||||
|
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%MEDIA#%%\' ESCAPE \'#\'');
|
||||||
|
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%BASE#%%\' ESCAPE \'#\'');
|
||||||
|
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%SECURE#%%\' ESCAPE \'#\'');
|
||||||
|
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%FOOTPRINTS#%%\' ESCAPE \'#\'');
|
||||||
|
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%FOOTPRINTS3D#%%\' ESCAPE \'#\'');
|
||||||
|
$this->addSql('UPDATE attachments SET external_path=NULL WHERE internal_path IS NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('UPDATE attachments SET external_path=internal_path WHERE internal_path IS NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE attachments DROP COLUMN internal_path');
|
||||||
|
$this->addSql('ALTER TABLE attachments RENAME COLUMN external_path TO path');
|
||||||
|
}
|
||||||
|
}
|
31
migrations/Version20250222165240.php
Normal file
31
migrations/Version20250222165240.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250222165240 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Migrate the old attachment class discriminator values from legacy Part-DB to the modern format, so that there is just one unified value';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
//Change the old discriminator values to the new ones
|
||||||
|
$this->addSql("UPDATE attachments SET class_name = 'Part' WHERE class_name = 'PartDB\Part'");
|
||||||
|
$this->addSql("UPDATE attachments SET class_name = 'Device' WHERE class_name = 'PartDB\Device'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
//No down required, as the new format can also be read by older Part-DB version
|
||||||
|
}
|
||||||
|
}
|
81
package.json
81
package.json
|
@ -9,7 +9,7 @@
|
||||||
"@symfony/stimulus-bridge": "^3.2.0",
|
"@symfony/stimulus-bridge": "^3.2.0",
|
||||||
"@symfony/ux-translator": "file:vendor/symfony/ux-translator/assets",
|
"@symfony/ux-translator": "file:vendor/symfony/ux-translator/assets",
|
||||||
"@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/assets",
|
"@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/assets",
|
||||||
"@symfony/webpack-encore": "^4.1.0",
|
"@symfony/webpack-encore": "^5.0.0",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.1.3",
|
||||||
"core-js": "^3.23.0",
|
"core-js": "^3.23.0",
|
||||||
"intl-messageformat": "^10.2.5",
|
"intl-messageformat": "^10.2.5",
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
"regenerator-runtime": "^0.13.9",
|
"regenerator-runtime": "^0.13.9",
|
||||||
"webpack": "^5.74.0",
|
"webpack": "^5.74.0",
|
||||||
"webpack-bundle-analyzer": "^4.3.0",
|
"webpack-bundle-analyzer": "^4.3.0",
|
||||||
"webpack-cli": "^4.10.0",
|
"webpack-cli": "^5.1.0",
|
||||||
"webpack-notifier": "^1.15.0"
|
"webpack-notifier": "^1.15.0"
|
||||||
},
|
},
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
|
@ -33,50 +33,52 @@
|
||||||
"@algolia/autocomplete-js": "^1.17.0",
|
"@algolia/autocomplete-js": "^1.17.0",
|
||||||
"@algolia/autocomplete-plugin-recent-searches": "^1.17.0",
|
"@algolia/autocomplete-plugin-recent-searches": "^1.17.0",
|
||||||
"@algolia/autocomplete-theme-classic": "^1.17.0",
|
"@algolia/autocomplete-theme-classic": "^1.17.0",
|
||||||
"@ckeditor/ckeditor5-alignment": "^41.0.0",
|
"@ckeditor/ckeditor5-alignment": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-autoformat": "^41.0.0",
|
"@ckeditor/ckeditor5-autoformat": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-basic-styles": "^41.0.0",
|
"@ckeditor/ckeditor5-basic-styles": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-block-quote": "^41.0.0",
|
"@ckeditor/ckeditor5-block-quote": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-code-block": "^41.0.0",
|
"@ckeditor/ckeditor5-code-block": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-dev-translations": "^39.1.0",
|
"@ckeditor/ckeditor5-dev-translations": "^43.0.1",
|
||||||
"@ckeditor/ckeditor5-dev-utils": "^39.1.0",
|
"@ckeditor/ckeditor5-dev-utils": "^43.0.1",
|
||||||
"@ckeditor/ckeditor5-editor-classic": "^41.0.0",
|
"@ckeditor/ckeditor5-editor-classic": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-essentials": "^41.0.0",
|
"@ckeditor/ckeditor5-essentials": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-find-and-replace": "^41.0.0",
|
"@ckeditor/ckeditor5-find-and-replace": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-font": "^41.0.0",
|
"@ckeditor/ckeditor5-font": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-heading": "^41.0.0",
|
"@ckeditor/ckeditor5-heading": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-highlight": "^41.0.0",
|
"@ckeditor/ckeditor5-highlight": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-horizontal-line": "^41.0.0",
|
"@ckeditor/ckeditor5-horizontal-line": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-html-embed": "^41.0.0",
|
"@ckeditor/ckeditor5-html-embed": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-html-support": "^41.0.0",
|
"@ckeditor/ckeditor5-html-support": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-image": "^41.0.0",
|
"@ckeditor/ckeditor5-image": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-indent": "^41.0.0",
|
"@ckeditor/ckeditor5-indent": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-link": "^41.0.0",
|
"@ckeditor/ckeditor5-link": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-list": "^41.0.0",
|
"@ckeditor/ckeditor5-list": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-markdown-gfm": "^41.0.0",
|
"@ckeditor/ckeditor5-markdown-gfm": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-media-embed": "^41.0.0",
|
"@ckeditor/ckeditor5-media-embed": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-paragraph": "^41.0.0",
|
"@ckeditor/ckeditor5-paragraph": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-paste-from-office": "^41.0.0",
|
"@ckeditor/ckeditor5-paste-from-office": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-remove-format": "^41.0.0",
|
"@ckeditor/ckeditor5-remove-format": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-source-editing": "^41.0.0",
|
"@ckeditor/ckeditor5-source-editing": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-special-characters": "^41.0.0",
|
"@ckeditor/ckeditor5-special-characters": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-table": "^41.0.0",
|
"@ckeditor/ckeditor5-table": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-theme-lark": "^41.0.0",
|
"@ckeditor/ckeditor5-theme-lark": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-upload": "^41.0.0",
|
"@ckeditor/ckeditor5-upload": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-watchdog": "^41.0.0",
|
"@ckeditor/ckeditor5-watchdog": "^44.0.0",
|
||||||
"@ckeditor/ckeditor5-word-count": "^41.0.0",
|
"@ckeditor/ckeditor5-word-count": "^44.0.0",
|
||||||
"@jbtronics/bs-treeview": "^1.0.1",
|
"@jbtronics/bs-treeview": "^1.0.1",
|
||||||
|
"@part-db/html5-qrcode": "^3.1.0",
|
||||||
"@zxcvbn-ts/core": "^3.0.2",
|
"@zxcvbn-ts/core": "^3.0.2",
|
||||||
"@zxcvbn-ts/language-common": "^3.0.3",
|
"@zxcvbn-ts/language-common": "^3.0.3",
|
||||||
"@zxcvbn-ts/language-de": "^3.0.1",
|
"@zxcvbn-ts/language-de": "^3.0.1",
|
||||||
"@zxcvbn-ts/language-en": "^3.0.1",
|
"@zxcvbn-ts/language-en": "^3.0.1",
|
||||||
"@zxcvbn-ts/language-fr": "^3.0.1",
|
"@zxcvbn-ts/language-fr": "^3.0.1",
|
||||||
"@zxcvbn-ts/language-ja": "^3.0.1",
|
"@zxcvbn-ts/language-ja": "^3.0.1",
|
||||||
|
"barcode-detector": "^2.3.1",
|
||||||
"bootbox": "^6.0.0",
|
"bootbox": "^6.0.0",
|
||||||
"bootswatch": "^5.1.3",
|
"bootswatch": "^5.1.3",
|
||||||
"bs-custom-file-input": "^1.3.4",
|
"bs-custom-file-input": "^1.3.4",
|
||||||
"clipboard": "^2.0.4",
|
"clipboard": "^2.0.4",
|
||||||
"compression-webpack-plugin": "^10.0.0",
|
"compression-webpack-plugin": "^11.1.0",
|
||||||
"datatables.net": "^2.0.0",
|
"datatables.net": "^2.0.0",
|
||||||
"datatables.net-bs5": "^2.0.0",
|
"datatables.net-bs5": "^2.0.0",
|
||||||
"datatables.net-buttons-bs5": "^3.0.0",
|
"datatables.net-buttons-bs5": "^3.0.0",
|
||||||
|
@ -86,18 +88,17 @@
|
||||||
"datatables.net-select-bs5": "^2.0.0",
|
"datatables.net-select-bs5": "^2.0.0",
|
||||||
"dompurify": "^3.0.3",
|
"dompurify": "^3.0.3",
|
||||||
"emoji.json": "^15.0.0",
|
"emoji.json": "^15.0.0",
|
||||||
"exports-loader": "^3.0.0",
|
"exports-loader": "^5.0.0",
|
||||||
"html5-qrcode": "^2.2.1",
|
|
||||||
"json-formatter-js": "^2.3.4",
|
"json-formatter-js": "^2.3.4",
|
||||||
"jszip": "^3.2.0",
|
"jszip": "^3.2.0",
|
||||||
"katex": "^0.16.0",
|
"katex": "^0.16.0",
|
||||||
"marked": "^12.0.0",
|
"marked": "^15.0.4",
|
||||||
"marked-gfm-heading-id": "^3.0.4",
|
"marked-gfm-heading-id": "^4.1.1",
|
||||||
"marked-mangle": "^1.0.1",
|
"marked-mangle": "^1.0.1",
|
||||||
"pdfmake": "^0.2.2",
|
"pdfmake": "^0.2.2",
|
||||||
"stimulus-use": "^0.52.0",
|
"stimulus-use": "^0.52.0",
|
||||||
"tom-select": "^2.1.0",
|
"tom-select": "^2.1.0",
|
||||||
"ts-loader": "^9.2.6",
|
"ts-loader": "^9.2.6",
|
||||||
"typescript": "^4.0.2"
|
"typescript": "^5.7.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ parameters:
|
||||||
- src/Configuration/*
|
- src/Configuration/*
|
||||||
- src/Doctrine/Purger/*
|
- src/Doctrine/Purger/*
|
||||||
- src/DataTables/Adapters/TwoStepORMAdapter.php
|
- src/DataTables/Adapters/TwoStepORMAdapter.php
|
||||||
|
- src/Form/Fixes/*
|
||||||
|
- src/Translation/Fixes/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +20,7 @@ parameters:
|
||||||
treatPhpDocTypesAsCertain: false
|
treatPhpDocTypesAsCertain: false
|
||||||
|
|
||||||
symfony:
|
symfony:
|
||||||
container_xml_path: '%rootDir%/../../../var/cache/dev/App_KernelDevDebugContainer.xml'
|
containerXmlPath: '%rootDir%/../../../var/cache/dev/App_KernelDevDebugContainer.xml'
|
||||||
|
|
||||||
doctrine:
|
doctrine:
|
||||||
objectManagerLoader: tests/object-manager.php
|
objectManagerLoader: tests/object-manager.php
|
||||||
|
@ -28,11 +30,6 @@ parameters:
|
||||||
|
|
||||||
checkFunctionNameCase: false
|
checkFunctionNameCase: false
|
||||||
|
|
||||||
checkAlwaysTrueInstanceof: false
|
|
||||||
checkAlwaysTrueCheckTypeFunctionCall: false
|
|
||||||
checkAlwaysTrueStrictComparison: false
|
|
||||||
reportAlwaysTrueInLastCondition: false
|
|
||||||
|
|
||||||
reportMaybesInPropertyPhpDocTypes: false
|
reportMaybesInPropertyPhpDocTypes: false
|
||||||
reportMaybesInMethodSignatures: false
|
reportMaybesInMethodSignatures: false
|
||||||
|
|
||||||
|
@ -41,14 +38,14 @@ parameters:
|
||||||
booleansInConditions: false
|
booleansInConditions: false
|
||||||
uselessCast: false
|
uselessCast: false
|
||||||
requireParentConstructorCall: true
|
requireParentConstructorCall: true
|
||||||
disallowedConstructs: false
|
|
||||||
overwriteVariablesWithLoop: false
|
overwriteVariablesWithLoop: false
|
||||||
closureUsesThis: false
|
closureUsesThis: false
|
||||||
matchingInheritedMethodNames: true
|
matchingInheritedMethodNames: true
|
||||||
numericOperandsInArithmeticOperators: true
|
numericOperandsInArithmeticOperators: true
|
||||||
strictCalls: true
|
|
||||||
switchConditionsMatchingType: false
|
switchConditionsMatchingType: false
|
||||||
noVariableVariables: false
|
noVariableVariables: false
|
||||||
|
disallowedEmpty: false
|
||||||
|
disallowedShortTernary: false
|
||||||
|
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
# Ignore errors caused by complex mapping with AbstractStructuralDBElement
|
# Ignore errors caused by complex mapping with AbstractStructuralDBElement
|
||||||
|
@ -60,4 +57,7 @@ parameters:
|
||||||
- '#Part::getParameters\(\) should return .*AbstractParameter#'
|
- '#Part::getParameters\(\) should return .*AbstractParameter#'
|
||||||
|
|
||||||
# Ignore doctrine type mapping mismatch
|
# Ignore doctrine type mapping mismatch
|
||||||
- '#Property .* type mapping mismatch: property can contain .* but database expects .*#'
|
- '#Property .* type mapping mismatch: property can contain .* but database expects .*#'
|
||||||
|
|
||||||
|
# Ignore error of unused WithPermPresetsTrait, as it is used in the migrations which are not analyzed by Phpstan
|
||||||
|
- '#Trait App\\Migration\\WithPermPresetsTrait is used zero times and is not analysed#'
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<server name="SHELL_VERBOSITY" value="-1"/>
|
<server name="SHELL_VERBOSITY" value="-1"/>
|
||||||
<server name="SYMFONY_PHPUNIT_REMOVE" value=""/>
|
<server name="SYMFONY_PHPUNIT_REMOVE" value=""/>
|
||||||
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5"/>
|
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5"/>
|
||||||
<ini name="memory_limit" value="512M"/>
|
<ini name="memory_limit" value="1G"/>
|
||||||
<ini name="display_errors" value="1"/>
|
<ini name="display_errors" value="1"/>
|
||||||
</php>
|
</php>
|
||||||
<coverage processUncoveredFiles="true">
|
<coverage processUncoveredFiles="true">
|
||||||
|
|
55
psalm.xml
55
psalm.xml
|
@ -1,55 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<psalm
|
|
||||||
errorLevel="5"
|
|
||||||
totallyTyped="false"
|
|
||||||
resolveFromConfigFile="true"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xmlns="https://getpsalm.org/schema/config"
|
|
||||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
|
||||||
>
|
|
||||||
<projectFiles>
|
|
||||||
<directory name="src"/>
|
|
||||||
<ignoreFiles>
|
|
||||||
<directory name="vendor"/>
|
|
||||||
</ignoreFiles>
|
|
||||||
</projectFiles>
|
|
||||||
|
|
||||||
<issueHandlers>
|
|
||||||
<LessSpecificReturnType errorLevel="info"/>
|
|
||||||
|
|
||||||
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
|
|
||||||
|
|
||||||
<DeprecatedMethod errorLevel="info"/>
|
|
||||||
<DeprecatedProperty errorLevel="info"/>
|
|
||||||
<DeprecatedClass errorLevel="info"/>
|
|
||||||
<DeprecatedConstant errorLevel="info"/>
|
|
||||||
<DeprecatedFunction errorLevel="info"/>
|
|
||||||
<DeprecatedInterface errorLevel="info"/>
|
|
||||||
<DeprecatedTrait errorLevel="info"/>
|
|
||||||
|
|
||||||
<InternalMethod errorLevel="info"/>
|
|
||||||
<InternalProperty errorLevel="info"/>
|
|
||||||
<InternalClass errorLevel="info"/>
|
|
||||||
|
|
||||||
<MissingClosureReturnType errorLevel="info"/>
|
|
||||||
<MissingReturnType errorLevel="info"/>
|
|
||||||
<MissingPropertyType errorLevel="info"/>
|
|
||||||
<InvalidDocblock errorLevel="info"/>
|
|
||||||
|
|
||||||
<PropertyNotSetInConstructor errorLevel="info"/>
|
|
||||||
<MissingConstructor errorLevel="info"/>
|
|
||||||
<MissingClosureParamType errorLevel="info"/>
|
|
||||||
<MissingParamType errorLevel="info"/>
|
|
||||||
|
|
||||||
<RedundantCondition errorLevel="info"/>
|
|
||||||
|
|
||||||
<DocblockTypeContradiction errorLevel="info"/>
|
|
||||||
<RedundantConditionGivenDocblockType errorLevel="info"/>
|
|
||||||
|
|
||||||
<UnresolvableInclude errorLevel="info"/>
|
|
||||||
|
|
||||||
<RawObjectIteration errorLevel="info"/>
|
|
||||||
|
|
||||||
<InvalidStringClass errorLevel="info"/>
|
|
||||||
</issueHandlers>
|
|
||||||
<plugins><pluginClass class="Psalm\SymfonyPsalmPlugin\Plugin"/></plugins></psalm>
|
|
|
@ -118,3 +118,10 @@ DirectoryIndex index.php
|
||||||
# RedirectTemp cannot be used instead
|
# RedirectTemp cannot be used instead
|
||||||
</IfModule>
|
</IfModule>
|
||||||
</IfModule>
|
</IfModule>
|
||||||
|
|
||||||
|
# Set Content-Security-Policy for svg files (and compressed variants), to block embedded javascript in there
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
<FilesMatch "\.(svg|svg\.gz|svg\.br)$">
|
||||||
|
Header set Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none';"
|
||||||
|
</FilesMatch>
|
||||||
|
</IfModule>
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
30
rector.php
30
rector.php
|
@ -2,15 +2,17 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector;
|
||||||
use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector;
|
use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector;
|
||||||
use Rector\Config\RectorConfig;
|
use Rector\Config\RectorConfig;
|
||||||
use Rector\Doctrine\Set\DoctrineSetList;
|
use Rector\Doctrine\Set\DoctrineSetList;
|
||||||
use Rector\PHPUnit\Rector\ClassMethod\AddDoesNotPerformAssertionToNonAssertingTestRector;
|
use Rector\PHPUnit\CodeQuality\Rector\Class_\PreferPHPUnitThisCallRector;
|
||||||
use Rector\PHPUnit\Set\PHPUnitLevelSetList;
|
|
||||||
use Rector\PHPUnit\Set\PHPUnitSetList;
|
use Rector\PHPUnit\Set\PHPUnitSetList;
|
||||||
use Rector\Set\ValueObject\LevelSetList;
|
use Rector\Set\ValueObject\LevelSetList;
|
||||||
use Rector\Set\ValueObject\SetList;
|
use Rector\Set\ValueObject\SetList;
|
||||||
use Rector\Symfony\Set\SymfonyLevelSetList;
|
use Rector\Symfony\CodeQuality\Rector\Class_\EventListenerToEventSubscriberRector;
|
||||||
|
use Rector\Symfony\CodeQuality\Rector\ClassMethod\ActionSuffixRemoverRector;
|
||||||
|
use Rector\Symfony\CodeQuality\Rector\MethodCall\LiteralGetToRequestClassConstantRector;
|
||||||
use Rector\Symfony\Set\SymfonySetList;
|
use Rector\Symfony\Set\SymfonySetList;
|
||||||
use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector;
|
use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector;
|
||||||
|
|
||||||
|
@ -44,20 +46,36 @@ return static function (RectorConfig $rectorConfig): void {
|
||||||
LevelSetList::UP_TO_PHP_81,
|
LevelSetList::UP_TO_PHP_81,
|
||||||
|
|
||||||
//Symfony rules
|
//Symfony rules
|
||||||
SymfonyLevelSetList::UP_TO_SYMFONY_62,
|
|
||||||
SymfonySetList::SYMFONY_CODE_QUALITY,
|
SymfonySetList::SYMFONY_CODE_QUALITY,
|
||||||
|
SymfonySetList::SYMFONY_64,
|
||||||
|
|
||||||
//Doctrine rules
|
//Doctrine rules
|
||||||
DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
|
DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
|
||||||
DoctrineSetList::DOCTRINE_CODE_QUALITY,
|
DoctrineSetList::DOCTRINE_CODE_QUALITY,
|
||||||
|
|
||||||
//PHPUnit rules
|
//PHPUnit rules
|
||||||
PHPUnitLevelSetList::UP_TO_PHPUNIT_90,
|
|
||||||
PHPUnitSetList::PHPUNIT_CODE_QUALITY,
|
PHPUnitSetList::PHPUNIT_CODE_QUALITY,
|
||||||
|
PHPUnitSetList::PHPUNIT_90,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$rectorConfig->skip([
|
$rectorConfig->skip([
|
||||||
AddDoesNotPerformAssertionToNonAssertingTestRector::class,
|
|
||||||
CountArrayToEmptyArrayComparisonRector::class,
|
CountArrayToEmptyArrayComparisonRector::class,
|
||||||
|
//Leave our !== null checks alone
|
||||||
|
FlipTypeControlToUseExclusiveTypeRector::class,
|
||||||
|
//Leave our PartList TableAction alone
|
||||||
|
ActionSuffixRemoverRector::class,
|
||||||
|
//We declare event listeners via attributes, therefore no need to migrate them to subscribers
|
||||||
|
EventListenerToEventSubscriberRector::class,
|
||||||
|
PreferPHPUnitThisCallRector::class,
|
||||||
|
//Do not replace 'GET' with class constant,
|
||||||
|
LiteralGetToRequestClassConstantRector::class,
|
||||||
|
]);
|
||||||
|
|
||||||
|
//Do not apply rules to Symfony own files
|
||||||
|
$rectorConfig->skip([
|
||||||
|
__DIR__ . '/public/index.php',
|
||||||
|
__DIR__ . '/src/Kernel.php',
|
||||||
|
__DIR__ . '/config/preload.php',
|
||||||
|
__DIR__ . '/config/bundles.php',
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue