mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Merge branch 'master' into log_detail_page
This commit is contained in:
commit
4c6ceab8e8
291 changed files with 1994 additions and 1621 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.3.0-dev
|
||||
1.3.2
|
||||
|
|
|
@ -30,9 +30,73 @@ export default class SpecialCharactersEmoji extends Plugin {
|
|||
const editor = this.editor;
|
||||
const specialCharsPlugin = editor.plugins.get('SpecialCharacters');
|
||||
|
||||
//Add greek characters to special characters
|
||||
specialCharsPlugin.addItems('Greek', this.getGreek());
|
||||
|
||||
//Add Emojis to special characters
|
||||
specialCharsPlugin.addItems('Emoji', this.getEmojis());
|
||||
}
|
||||
|
||||
getGreek() {
|
||||
return [
|
||||
{ title: 'Alpha', character: 'Α' },
|
||||
{ title: 'Beta', character: 'Β' },
|
||||
{ title: 'Gamma', character: 'Γ' },
|
||||
{ title: 'Delta', character: 'Δ' },
|
||||
{ title: 'Epsilon', character: 'Ε' },
|
||||
{ title: 'Zeta', character: 'Ζ' },
|
||||
{ title: 'Eta', character: 'Η' },
|
||||
{ title: 'Theta', character: 'Θ' },
|
||||
{ title: 'Iota', character: 'Ι' },
|
||||
{ title: 'Kappa', character: 'Κ' },
|
||||
{ title: 'Lambda', character: 'Λ' },
|
||||
{ title: 'Mu', character: 'Μ' },
|
||||
{ title: 'Nu', character: 'Ν' },
|
||||
{ title: 'Xi', character: 'Ξ' },
|
||||
{ title: 'Omicron', character: 'Ο' },
|
||||
{ title: 'Pi', character: 'Π' },
|
||||
{ title: 'Rho', character: 'Ρ' },
|
||||
{ title: 'Sigma', character: 'Σ' },
|
||||
{ title: 'Tau', character: 'Τ' },
|
||||
{ title: 'Upsilon', character: 'Υ' },
|
||||
{ title: 'Phi', character: 'Φ' },
|
||||
{ title: 'Chi', character: 'Χ' },
|
||||
{ title: 'Psi', character: 'Ψ' },
|
||||
{ title: 'Omega', character: 'Ω' },
|
||||
{ title: 'alpha', character: 'α' },
|
||||
{ title: 'beta', character: 'β' },
|
||||
{ title: 'gamma', character: 'γ' },
|
||||
{ title: 'delta', character: 'δ' },
|
||||
{ title: 'epsilon', character: 'ε' },
|
||||
{ title: 'zeta', character: 'ζ' },
|
||||
{ title: 'eta', character: 'η' },
|
||||
{ title: 'theta', character: 'θ' },
|
||||
{ title: 'alternate theta', character: 'ϑ' },
|
||||
{ title: 'iota', character: 'ι' },
|
||||
{ title: 'kappa', character: 'κ' },
|
||||
{ title: 'lambda', character: 'λ' },
|
||||
{ title: 'mu', character: 'μ' },
|
||||
{ title: 'nu', character: 'ν' },
|
||||
{ title: 'xi', character: 'ξ' },
|
||||
{ title: 'omicron', character: 'ο' },
|
||||
{ title: 'pi', character: 'π' },
|
||||
{ title: 'rho', character: 'ρ' },
|
||||
{ title: 'sigma', character: 'σ' },
|
||||
{ title: 'tau', character: 'τ' },
|
||||
{ title: 'upsilon', character: 'υ' },
|
||||
{ title: 'phi', character: 'φ' },
|
||||
{ title: 'chi', character: 'χ' },
|
||||
{ title: 'psi', character: 'ψ' },
|
||||
{ title: 'omega', character: 'ω' },
|
||||
{ title: 'digamma', character: 'Ϝ' },
|
||||
{ title: 'stigma', character: 'Ϛ' },
|
||||
{ title: 'heta', character: 'Ͱ' },
|
||||
{ title: 'sampi', character: 'Ϡ' },
|
||||
{ title: 'koppa', character: 'Ϟ' },
|
||||
{ title: 'san', character: 'Ϻ' },
|
||||
];
|
||||
}
|
||||
|
||||
getEmojis() {
|
||||
//Map our emoji data to the format the plugin expects
|
||||
return emoji.map(emoji => {
|
||||
|
|
|
@ -29,42 +29,16 @@ export default class extends Controller
|
|||
this._confirmed = false;
|
||||
}
|
||||
|
||||
click(event) {
|
||||
//If a user has not already confirmed the deletion, just let turbo do its work
|
||||
if(this._confirmed) {
|
||||
this._confirmed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const message = this.element.dataset.deleteMessage;
|
||||
const title = this.element.dataset.deleteTitle;
|
||||
|
||||
const that = this;
|
||||
|
||||
const confirm = bootbox.confirm({
|
||||
message: message, title: title, callback: function (result) {
|
||||
//If the dialog was confirmed, then submit the form.
|
||||
if (result) {
|
||||
that._confirmed = true;
|
||||
event.target.click();
|
||||
} else {
|
||||
that._confirmed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
submit(event) {
|
||||
//If a user has not already confirmed the deletion, just let turbo do its work
|
||||
if(this._confirmed) {
|
||||
if (this._confirmed) {
|
||||
this._confirmed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//Prevent turbo from doing its work
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const message = this.element.dataset.deleteMessage;
|
||||
const title = this.element.dataset.deleteTitle;
|
||||
|
@ -72,19 +46,20 @@ export default class extends Controller
|
|||
const form = this.element;
|
||||
const that = this;
|
||||
|
||||
//Create a clone of the event with the same submitter, so we can redispatch it if needed
|
||||
//We need to do this that way, as we need the submitter info, just calling form.submit() would not work
|
||||
this._our_event = new SubmitEvent('submit', {
|
||||
submitter: event.submitter,
|
||||
bubbles: true, //This line is important, otherwise Turbo will not receive the event
|
||||
});
|
||||
|
||||
const confirm = bootbox.confirm({
|
||||
message: message, title: title, callback: function (result) {
|
||||
//If the dialog was confirmed, then submit the form.
|
||||
if (result) {
|
||||
//Set a flag to prevent the dialog from popping up again and allowing turbo to submit the form
|
||||
that._confirmed = true;
|
||||
form.dispatchEvent(that._our_event);
|
||||
|
||||
//Create a submit button in the form and click it to submit the form
|
||||
//Before a submit event was dispatched, but this caused weird issues on Firefox causing the delete request being posted twice (and the second time was returning 404). See https://github.com/Part-DB/Part-DB-server/issues/273
|
||||
const submit_btn = document.createElement('button');
|
||||
submit_btn.type = 'submit';
|
||||
submit_btn.style.display = 'none';
|
||||
form.appendChild(submit_btn);
|
||||
submit_btn.click();
|
||||
} else {
|
||||
that._confirmed = false;
|
||||
}
|
||||
|
|
|
@ -72,63 +72,223 @@ class RegisterEventHelper {
|
|||
this.registerLoadHandler(() => {
|
||||
//@ts-ignore
|
||||
$("input[type=text], input[type=search]").unbind("keydown").keydown(function (event) {
|
||||
let greek = event.altKey;
|
||||
let use_special_char = event.altKey;
|
||||
|
||||
let greek_char = "";
|
||||
if (greek){
|
||||
if (use_special_char){
|
||||
//Use the key property to determine the greek letter (as it is independent of the keyboard layout)
|
||||
switch(event.key) {
|
||||
case "w": //Omega
|
||||
greek_char = '\u2126';
|
||||
break;
|
||||
case "u":
|
||||
case "m": //Micro
|
||||
greek_char = "\u00B5";
|
||||
break;
|
||||
case "p": //Phi
|
||||
greek_char = "\u03C6";
|
||||
break;
|
||||
case "a": //Alpha
|
||||
//Greek letters
|
||||
case "a": //Alpha (lowercase)
|
||||
greek_char = "\u03B1";
|
||||
break;
|
||||
case "b": //Beta
|
||||
case "A": //Alpha (uppercase)
|
||||
greek_char = "\u0391";
|
||||
break;
|
||||
case "b": //Beta (lowercase)
|
||||
greek_char = "\u03B2";
|
||||
break;
|
||||
case "c": //Gamma
|
||||
case "B": //Beta (uppercase)
|
||||
greek_char = "\u0392";
|
||||
break;
|
||||
case "g": //Gamma (lowercase)
|
||||
greek_char = "\u03B3";
|
||||
break;
|
||||
case "d": //Delta
|
||||
case "G": //Gamma (uppercase)
|
||||
greek_char = "\u0393";
|
||||
break;
|
||||
case "d": //Delta (lowercase)
|
||||
greek_char = "\u03B4";
|
||||
break;
|
||||
case "l": //Pound
|
||||
greek_char = "\u00A3";
|
||||
case "D": //Delta (uppercase)
|
||||
greek_char = "\u0394";
|
||||
break;
|
||||
case "y": //Yen
|
||||
greek_char = "\u00A5";
|
||||
case "e": //Epsilon (lowercase)
|
||||
greek_char = "\u03B5";
|
||||
break;
|
||||
case "o": //Yen
|
||||
greek_char = "\u00A4";
|
||||
case "E": //Epsilon (uppercase)
|
||||
greek_char = "\u0395";
|
||||
break;
|
||||
case "1": //Sum symbol
|
||||
greek_char = "\u2211";
|
||||
case "z": //Zeta (lowercase)
|
||||
greek_char = "\u03B6";
|
||||
break;
|
||||
case "2": //Integral
|
||||
greek_char = "\u222B";
|
||||
case "Z": //Zeta (uppercase)
|
||||
greek_char = "\u0396";
|
||||
break;
|
||||
case "3": //Less-than or equal
|
||||
greek_char = "\u2264";
|
||||
case "h": //Eta (lowercase)
|
||||
greek_char = "\u03B7";
|
||||
break;
|
||||
case "4": //Greater than or equal
|
||||
greek_char = "\u2265";
|
||||
case "H": //Eta (uppercase)
|
||||
greek_char = "\u0397";
|
||||
break;
|
||||
case "5": //PI
|
||||
greek_char = "\u03c0";
|
||||
case "q": //Theta (lowercase)
|
||||
greek_char = "\u03B8";
|
||||
break;
|
||||
case "q": //Copyright
|
||||
greek_char = "\u00A9";
|
||||
case "Q": //Theta (uppercase)
|
||||
greek_char = "\u0398";
|
||||
break;
|
||||
case "e": //Euro
|
||||
greek_char = "\u20AC";
|
||||
case "i": //Iota (lowercase)
|
||||
greek_char = "\u03B9";
|
||||
break;
|
||||
case "I": //Iota (uppercase)
|
||||
greek_char = "\u0399";
|
||||
break;
|
||||
case "k": //Kappa (lowercase)
|
||||
greek_char = "\u03BA";
|
||||
break;
|
||||
case "K": //Kappa (uppercase)
|
||||
greek_char = "\u039A";
|
||||
break;
|
||||
case "l": //Lambda (lowercase)
|
||||
greek_char = "\u03BB";
|
||||
break;
|
||||
case "L": //Lambda (uppercase)
|
||||
greek_char = "\u039B";
|
||||
break;
|
||||
case "m": //Mu (lowercase)
|
||||
greek_char = "\u03BC";
|
||||
break;
|
||||
case "M": //Mu (uppercase)
|
||||
greek_char = "\u039C";
|
||||
break;
|
||||
case "n": //Nu (lowercase)
|
||||
greek_char = "\u03BD";
|
||||
break;
|
||||
case "N": //Nu (uppercase)
|
||||
greek_char = "\u039D";
|
||||
break;
|
||||
case "x": //Xi (lowercase)
|
||||
greek_char = "\u03BE";
|
||||
break;
|
||||
case "X": //Xi (uppercase)
|
||||
greek_char = "\u039E";
|
||||
break;
|
||||
case "o": //Omicron (lowercase)
|
||||
greek_char = "\u03BF";
|
||||
break;
|
||||
case "O": //Omicron (uppercase)
|
||||
greek_char = "\u039F";
|
||||
break;
|
||||
case "p": //Pi (lowercase)
|
||||
greek_char = "\u03C0";
|
||||
break;
|
||||
case "P": //Pi (uppercase)
|
||||
greek_char = "\u03A0";
|
||||
break;
|
||||
case "r": //Rho (lowercase)
|
||||
greek_char = "\u03C1";
|
||||
break;
|
||||
case "R": //Rho (uppercase)
|
||||
greek_char = "\u03A1";
|
||||
break;
|
||||
case "s": //Sigma (lowercase)
|
||||
greek_char = "\u03C3";
|
||||
break;
|
||||
case "S": //Sigma (uppercase)
|
||||
greek_char = "\u03A3";
|
||||
break;
|
||||
case "t": //Tau (lowercase)
|
||||
greek_char = "\u03C4";
|
||||
break;
|
||||
case "T": //Tau (uppercase)
|
||||
greek_char = "\u03A4";
|
||||
break;
|
||||
case "u": //Upsilon (lowercase)
|
||||
greek_char = "\u03C5";
|
||||
break;
|
||||
case "U": //Upsilon (uppercase)
|
||||
greek_char = "\u03A5";
|
||||
break;
|
||||
case "f": //Phi (lowercase)
|
||||
greek_char = "\u03C6";
|
||||
break;
|
||||
case "F": //Phi (uppercase)
|
||||
greek_char = "\u03A6";
|
||||
break;
|
||||
case "c": //Chi (lowercase)
|
||||
greek_char = "\u03C7";
|
||||
break;
|
||||
case "C": //Chi (uppercase)
|
||||
greek_char = "\u03A7";
|
||||
break;
|
||||
case "y": //Psi (lowercase)
|
||||
greek_char = "\u03C8";
|
||||
break;
|
||||
case "Y": //Psi (uppercase)
|
||||
greek_char = "\u03A8";
|
||||
break;
|
||||
case "w": //Omega (lowercase)
|
||||
greek_char = "\u03C9";
|
||||
break;
|
||||
case "W": //Omega (uppercase)
|
||||
greek_char = "\u03A9";
|
||||
break;
|
||||
}
|
||||
|
||||
//Use keycodes for special characters as the shift char on the number keys are layout dependent
|
||||
switch (event.keyCode) {
|
||||
case 49: //1 key
|
||||
//Product symbol on shift, sum on no shift
|
||||
greek_char = event.shiftKey ? "\u220F" : "\u2211";
|
||||
break;
|
||||
case 50: //2 key
|
||||
//Integral on no shift, partial derivative on shift
|
||||
greek_char = event.shiftKey ? "\u2202" : "\u222B";
|
||||
break;
|
||||
case 51: //3 key
|
||||
//Less than or equal on no shift, greater than or equal on shift
|
||||
greek_char = event.shiftKey ? "\u2265" : "\u2264";
|
||||
break;
|
||||
case 52: //4 key
|
||||
//Empty set on shift, infinity on no shift
|
||||
greek_char = event.shiftKey ? "\u2205" : "\u221E";
|
||||
break;
|
||||
case 53: //5 key
|
||||
//Not equal on shift, approx equal on no shift
|
||||
greek_char = event.shiftKey ? "\u2260" : "\u2248";
|
||||
break;
|
||||
case 54: //6 key
|
||||
//Element of on no shift, not element of on shift
|
||||
greek_char = event.shiftKey ? "\u2209" : "\u2208";
|
||||
break;
|
||||
case 55: //7 key
|
||||
//And on shift, or on no shift
|
||||
greek_char = event.shiftKey ? "\u2227" : "\u2228";
|
||||
break;
|
||||
case 56: //8 key
|
||||
//Proportional to on shift, angle on no shift
|
||||
greek_char = event.shiftKey ? "\u221D" : "\u2220";
|
||||
break;
|
||||
case 57: //9 key
|
||||
//Cube root on shift, square root on no shift
|
||||
greek_char = event.shiftKey ? "\u221B" : "\u221A";
|
||||
break;
|
||||
case 48: //0 key
|
||||
//Minus-Plus on shift, plus-minus on no shift
|
||||
greek_char = event.shiftKey ? "\u2213" : "\u00B1";
|
||||
break;
|
||||
|
||||
//Special characters
|
||||
case 219: //hyphen (or ß on german layout)
|
||||
//Copyright on no shift, TM on shift
|
||||
greek_char = event.shiftKey ? "\u2122" : "\u00A9";
|
||||
break;
|
||||
case 191: //forward slash (or # on german layout)
|
||||
//Generic currency on no shift, paragraph on shift
|
||||
greek_char = event.shiftKey ? "\u00B6" : "\u00A4";
|
||||
break;
|
||||
|
||||
//Currency symbols
|
||||
case 192: //: or (ö on german layout)
|
||||
//Euro on no shift, pound on shift
|
||||
greek_char = event.shiftKey ? "\u00A3" : "\u20AC";
|
||||
break;
|
||||
case 221: //; or (ä on german layout)
|
||||
//Yen on no shift, dollar on shift
|
||||
greek_char = event.shiftKey ? "\u0024" : "\u00A5";
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(greek_char=="") return;
|
||||
|
|
627
composer.lock
generated
627
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,9 @@ liip_imagine:
|
|||
# valid drivers options include "gd" or "gmagick" or "imagick"
|
||||
driver: "gd"
|
||||
|
||||
twig:
|
||||
mode: lazy
|
||||
|
||||
default_filter_set_settings:
|
||||
format: webp
|
||||
|
||||
|
|
|
@ -244,6 +244,13 @@ services:
|
|||
tags:
|
||||
- {name: serializer.normalizer, priority: -9000}
|
||||
|
||||
# Disable igbinary serialization for cache even when igbinary is available, as it causes issues with the doctrine
|
||||
# proxy objects (see https://github.com/igbinary/igbinary/issues/377 and https://github.com/igbinary/igbinary/issues/273)
|
||||
cache.default_marshaller:
|
||||
class: Symfony\Component\Cache\Marshaller\DefaultMarshaller
|
||||
arguments:
|
||||
$useIgbinarySerialize: false
|
||||
|
||||
|
||||
####################################################################################################################
|
||||
# Miscellaneous
|
||||
|
|
|
@ -22,6 +22,11 @@ php bin/console doctrine:migrations:migrate
|
|||
|
||||
If this does not help, please [open an issue on GitHub](https://github.com/Part-DB/Part-DB-symfony).
|
||||
|
||||
## Search for user and reset password:
|
||||
You can list all users with the following command: `php bin/console partdb:users:list`
|
||||
To reset the password of a user you can use the following command: `php bin/console partdb:users:set-password [username]`
|
||||
|
||||
|
||||
## Error logs
|
||||
Detailed error logs can be found in the `var/log` directory.
|
||||
When Part-DB is installed directly, the errors are written to the `var/log/prod.log` file.
|
||||
|
|
119
docs/usage/keybindings.md
Normal file
119
docs/usage/keybindings.md
Normal file
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
title: Keybindings
|
||||
layout: default
|
||||
parent: Usage
|
||||
---
|
||||
|
||||
# Keybindings
|
||||
|
||||
This page lists all the keybindings of Part-DB. Currently, there are only the special character keybindings.
|
||||
|
||||
## Special characters
|
||||
Using the keybindings below (Alt + key) you can insert special characters into the text fields of Part-DB. This works on all text and search fields in Part-DB.
|
||||
|
||||
### Greek letters
|
||||
|
||||
| Key | Character |
|
||||
|---------------------|---------------------|
|
||||
| **Alt + a** | α (Alpha) |
|
||||
| **Alt + Shift + A** | Α (Alpha uppercase) |
|
||||
| **Alt + b** | β (Beta) |
|
||||
| **Alt + Shift + B** | Β (Beta uppercase) |
|
||||
| **Alt + g** | γ (Gamma) |
|
||||
| **Alt + Shift + G** | Γ (Gamma uppercase) |
|
||||
| **Alt + d** | δ (Delta) |
|
||||
| **Alt + Shift + D** | Δ (Delta uppercase) |
|
||||
| **Alt + e** | ε (Epsilon) |
|
||||
| **Alt + Shift + E** | Ε (Epsilon uppercase) |
|
||||
| **Alt + z** | ζ (Zeta) |
|
||||
| **Alt + Shift + Z** | Ζ (Zeta uppercase) |
|
||||
| **Alt + h** | η (Eta) |
|
||||
| **Alt + Shift + H** | Η (Eta uppercase) |
|
||||
| **Alt + q** | θ (Theta) |
|
||||
| **Alt + Shift + Q** | Θ (Theta uppercase) |
|
||||
| **Alt + i** | ι (Iota) |
|
||||
| **Alt + Shift + I** | Ι (Iota uppercase) |
|
||||
| **Alt + k** | κ (Kappa) |
|
||||
| **Alt + Shift + K** | Κ (Kappa uppercase) |
|
||||
| **Alt + l** | λ (Lambda) |
|
||||
| **Alt + Shift + L** | Λ (Lambda uppercase) |
|
||||
| **Alt + m** | μ (Mu) |
|
||||
| **Alt + Shift + M** | Μ (Mu uppercase) |
|
||||
| **Alt + n** | ν (Nu) |
|
||||
| **Alt + Shift + N** | Ν (Nu uppercase) |
|
||||
| **Alt + x** | ξ (Xi) |
|
||||
| **Alt + Shift + x** | Ξ (Xi uppercase) |
|
||||
| **Alt + o** | ο (Omicron) |
|
||||
| **Alt + Shift + O** | Ο (Omicron uppercase) |
|
||||
| **Alt + p** | π (Pi) |
|
||||
| **Alt + Shift + P** | Π (Pi uppercase) |
|
||||
| **Alt + r** | ρ (Rho) |
|
||||
| **Alt + Shift + R** | Ρ (Rho uppercase) |
|
||||
| **Alt + s** | σ (Sigma) |
|
||||
| **Alt + Shift + S** | Σ (Sigma uppercase) |
|
||||
| **Alt + t** | τ (Tau) |
|
||||
| **Alt + Shift + T** | Τ (Tau uppercase) |
|
||||
| **Alt + u** | υ (Upsilon) |
|
||||
| **Alt + Shift + U** | Υ (Upsilon uppercase) |
|
||||
| **Alt + f** | φ (Phi) |
|
||||
| **Alt + Shift + F** | Φ (Phi uppercase) |
|
||||
| **Alt + y** | ψ (Psi) |
|
||||
| **Alt + Shift + Y** | Ψ (Psi uppercase) |
|
||||
| **Alt + c** | χ (Chi) |
|
||||
| **Alt + Shift + C** | Χ (Chi uppercase) |
|
||||
| **Alt + w** | ω (Omega) |
|
||||
| **Alt + Shift + W** | Ω (Omega uppercase) |
|
||||
|
||||
### Mathematical symbols
|
||||
|
||||
| Key | Character |
|
||||
|----------------------|-------------------------------------------|
|
||||
| **Alt + 1** | ∑ (Sum symbol) |
|
||||
| **Alt + Shift + 1** | ∏ (Product symbol) |
|
||||
| **Alt + 2** | ∫ (Integral symbol) |
|
||||
| **Alt + Shift + 2** | ∂ (Partial derivation) |
|
||||
| **Alt + 3** | ≤ (Less or equal symbol) |
|
||||
| **Alt + Shift + 3** | ≥ (Greater or equal symbol) |
|
||||
| **Alt + 4** | ∞ (Infinity symbol) |
|
||||
| **Alt + Shift + 4** | ∅ (Empty set symbol) |
|
||||
| **Alt + 5** | ≈ (Approximatley) |
|
||||
| **Alt + Shift + 5** | ≠ (Not equal symbol) |
|
||||
| **Alt + 6** | ∈ (Element of) |
|
||||
| **Alt + Shift + 6** | ∉ (Not element of) |
|
||||
| **Alt + 7** | ∨ (Logical or) |
|
||||
| **Alt + Shift + 7** | ∧ (Logical and) |
|
||||
| **Alt + 8** | ∠ (Angle symbol) |
|
||||
| **Alt + Shift + 8** | ∝ (Proportional to) |
|
||||
| **Alt + 9** | √ (Square root) |
|
||||
| **Alt + Shift + 9** | ∛ (Cube root) |
|
||||
| **Alt + 0** | ± (Plus minus) |
|
||||
| **Alt + Shift + 0** | ∓ (Minus plus) |
|
||||
|
||||
### Currency symbols
|
||||
|
||||
Please not the following keybindings are bound to a specific keycode. The key character is not the same on all keyboards.
|
||||
It is given here for a US keyboard layout.
|
||||
|
||||
For a German keyboard layout, replace ; with ö, and ' with ä.
|
||||
|
||||
| Key | Character |
|
||||
|---------------------------------|---------------------------|
|
||||
| **Alt + ;** (code 192) | € (Euro currency symbol) |
|
||||
| **Alt + Shift + ;** (code 192) | £ (Pound currency symbol) |
|
||||
| **Alt + '** (code 222) | ¥ (Yen currency symbol) |
|
||||
| **Alt + Shift + '** (code 222) | $ (Dollar currency symbol) |
|
||||
|
||||
|
||||
### Others
|
||||
|
||||
Please not the following keybindings are bound to a specific keycode. The key character is not the same on all keyboards.
|
||||
It is given here for a US keyboard layout.
|
||||
|
||||
For a German keyboard layout, replace `[` with `0`, and `]` with `´`.
|
||||
|
||||
| Key | Character |
|
||||
|--------------------------------|--------------------|
|
||||
| **Alt + [** (code 219) | © (Copyright char) |
|
||||
| **Alt + Shift + [** (code 219) | (Registered char) |
|
||||
| **Alt + ]** (code 221) | ™ (Trademark char) |
|
||||
| **Alt + Shift + ]** (code 221) | (Degree char) |
|
|
@ -216,10 +216,10 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
|||
$this->addSql('CREATE INDEX IDX_C68C4459398D64AA ON pricedetails (id_currency)');
|
||||
$this->addSql('CREATE INDEX IDX_C68C44594A01DDC7 ON pricedetails (orderdetails_id)');
|
||||
$this->addSql('DROP INDEX pricedetails_orderdetails_id_k ON pricedetails');
|
||||
$this->addSql('DROP INDEX name ON groups');
|
||||
$this->addSql('ALTER TABLE groups ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE perms_labels perms_labels INT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('ALTER TABLE groups ADD CONSTRAINT FK_F06D3970727ACA70 FOREIGN KEY (parent_id) REFERENCES `groups` (id)');
|
||||
$this->addSql('CREATE INDEX IDX_F06D3970727ACA70 ON groups (parent_id)');
|
||||
$this->addSql('DROP INDEX name ON `groups`');
|
||||
$this->addSql('ALTER TABLE `groups` ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE perms_labels perms_labels INT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('ALTER TABLE `groups` ADD CONSTRAINT FK_F06D3970727ACA70 FOREIGN KEY (parent_id) REFERENCES `groups` (id)');
|
||||
$this->addSql('CREATE INDEX IDX_F06D3970727ACA70 ON `groups` (parent_id)');
|
||||
|
||||
//Fill empty timestamps with current date
|
||||
$tables = ['attachments', 'attachment_types', 'categories', 'devices', 'footprints', 'manufacturers',
|
||||
|
@ -232,6 +232,10 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
|||
|
||||
//Set the dbVersion to a high value, to prevent the old Part-DB versions to upgrade DB!
|
||||
$this->addSql("UPDATE `internal` SET `keyValue` = '99' WHERE `internal`.`keyName` = 'dbVersion'");
|
||||
|
||||
//Migrate theme config to new format
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".min.css", "") WHERE users.config_theme LIKE "%.min.css"');
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".css", "") WHERE users.config_theme LIKE "%.css"');
|
||||
}
|
||||
|
||||
public function mySQLDown(Schema $schema): void
|
||||
|
@ -357,10 +361,6 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
|||
$this->addSql('ALTER TABLE `users` CHANGE name name VARCHAR(32) NOT NULL COLLATE utf8_general_ci, CHANGE need_pw_change need_pw_change TINYINT(1) DEFAULT \'0\' NOT NULL, CHANGE first_name first_name TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE last_name last_name TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE department department TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE email email TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_language config_language TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_timezone config_timezone TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_theme config_theme TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_currency config_currency TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, CHANGE perms_labels perms_labels SMALLINT NOT NULL');
|
||||
$this->addSql('DROP INDEX uniq_1483a5e95e237e06 ON `users`');
|
||||
$this->addSql('CREATE UNIQUE INDEX name ON `users` (name)');
|
||||
|
||||
//Migrate theme config to new format
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".min.css", "") WHERE users.config_theme LIKE "%.min.css"');
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".css", "") WHERE users.config_theme LIKE "%.css"');
|
||||
}
|
||||
|
||||
public function sqLiteUp(Schema $schema): void
|
||||
|
|
51
migrations/Version20230417211732.php
Normal file
51
migrations/Version20230417211732.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?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 Version20230417211732 extends AbstractMultiPlatformMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Fix class names in attachments table for databases migrated from legacy Part-DB';
|
||||
}
|
||||
|
||||
public function mySQLUp(Schema $schema): void
|
||||
{
|
||||
//Delete all attachments where the corresponding part or device was deleted in legacy Part-DB (and therefore does not exist in the new Part-DB
|
||||
$this->addSql('DELETE FROM attachments WHERE class_name = "PartDB\\\\Part" AND NOT EXISTS (SELECT id FROM parts WHERE id = attachments.element_id)');
|
||||
$this->addSql('DELETE FROM attachments WHERE class_name = "PartDB\\\\Device" AND NOT EXISTS (SELECT id FROM projects WHERE id = attachments.element_id)');
|
||||
|
||||
// Replace all attachments where class_name is the legacy "PartDB\Part" with the new version "Part"
|
||||
//We have to use 4 backslashes here, as PHP reduces them to 2 backslashes, which MySQL interprets as an escaped backslash.
|
||||
$this->addSql('UPDATE attachments SET class_name = "Part" WHERE class_name = "PartDB\\\\Part"');
|
||||
//Do the same with PartDB\Device and Device
|
||||
$this->addSql('UPDATE attachments SET class_name = "Device" WHERE class_name = "PartDB\\\\Device"');
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function mySQLDown(Schema $schema): void
|
||||
{
|
||||
// We can not revert this migration, because we don't know the old class name.
|
||||
}
|
||||
|
||||
public function sqLiteUp(Schema $schema): void
|
||||
{
|
||||
//As legacy database can only be migrated to MySQL, we don't need to implement this method.
|
||||
$this->skipIf(true, 'Not needed for SQLite');
|
||||
}
|
||||
|
||||
public function sqLiteDown(Schema $schema): void
|
||||
{
|
||||
//As we done nothing, we don't need to implement this method.
|
||||
}
|
||||
}
|
|
@ -10,7 +10,6 @@ use PhpZip\ZipFile;
|
|||
use Spatie\DbDumper\Databases\MySql;
|
||||
use Spatie\DbDumper\DbDumper;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\Input;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
|
|
@ -45,12 +45,12 @@ use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
|||
use function count;
|
||||
|
||||
/**
|
||||
* This command converts the BBCode used by old Part-DB versions (<1.0), to the current used markdown format.
|
||||
* This command converts the BBCode used by old Part-DB versions (<1.0), to the current used Markdown format.
|
||||
*/
|
||||
class ConvertBBCodeCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var string The LIKE criteria used to detect on SQL server if a entry contains BBCode
|
||||
* @var string The LIKE criteria used to detect on SQL server if an entry contains BBCode
|
||||
*/
|
||||
protected const BBCODE_CRITERIA = '%[%]%[/%]%';
|
||||
/**
|
||||
|
|
|
@ -69,7 +69,7 @@ class ImportPartKeeprCommand extends Command
|
|||
$this->addOption('--import-users', null, InputOption::VALUE_NONE, 'Import users (passwords will not be imported).');
|
||||
}
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
|
|
|
@ -27,9 +27,7 @@ use App\Services\LogSystem\EventCommentHelper;
|
|||
use App\Services\UserSystem\PermissionSchemaUpdater;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
|
@ -91,12 +89,12 @@ final class UpgradePermissionsSchemaCommand extends Command
|
|||
|
||||
//List all users and groups that need an update
|
||||
$io->section('Groups that need an update:');
|
||||
$io->listing(array_map(function (Group $group) {
|
||||
$io->listing(array_map(static function (Group $group) {
|
||||
return $group->getName() . ' (ID: '. $group->getID() .', Current version: ' . $group->getPermissions()->getSchemaVersion() . ')';
|
||||
}, $groups_to_upgrade));
|
||||
|
||||
$io->section('Users that need an update:');
|
||||
$io->listing(array_map(function (User $user) {
|
||||
$io->listing(array_map(static function (User $user) {
|
||||
return $user->getUsername() . ' (ID: '. $user->getID() .', Current version: ' . $user->getPermissions()->getSchemaVersion() . ')';
|
||||
}, $users_to_upgrade));
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ class UserEnableCommand extends Command
|
|||
$io->note('The following users will be enabled:');
|
||||
}
|
||||
$io->table(['Username', 'Enabled/Disabled'],
|
||||
array_map(function(User $user) {
|
||||
array_map(static function(User $user) {
|
||||
return [$user->getFullName(true), $user->isDisabled() ? 'Disabled' : 'Enabled'];
|
||||
}, $users));
|
||||
|
||||
|
|
|
@ -269,7 +269,6 @@ abstract class BaseAdminController extends AbstractController
|
|||
|
||||
protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AbstractNamedDBElement $entity = null)
|
||||
{
|
||||
$master_picture_backup = null;
|
||||
if (null === $entity) {
|
||||
/** @var AbstractStructuralDBElement|User $new_entity */
|
||||
$new_entity = new $this->entity_class();
|
||||
|
@ -390,7 +389,7 @@ abstract class BaseAdminController extends AbstractController
|
|||
foreach ($errors as $error) {
|
||||
if ($error['entity'] instanceof AbstractStructuralDBElement) {
|
||||
$this->addFlash('error', $error['entity']->getFullPath().':'.$error['violations']);
|
||||
} else { //When we dont have a structural element, we can only show the name
|
||||
} else { //When we don't have a structural element, we can only show the name
|
||||
$this->addFlash('error', $error['entity']->getName().':'.$error['violations']);
|
||||
}
|
||||
}
|
||||
|
@ -413,11 +412,11 @@ abstract class BaseAdminController extends AbstractController
|
|||
}
|
||||
|
||||
/**
|
||||
* Performs checks if the element can be deleted safely. Otherwise an flash message is added.
|
||||
* Performs checks if the element can be deleted safely. Otherwise, a flash message is added.
|
||||
*
|
||||
* @param AbstractNamedDBElement $entity the element that should be checked
|
||||
*
|
||||
* @return bool True if the the element can be deleted, false if not
|
||||
* @return bool True if the element can be deleted, false if not
|
||||
*/
|
||||
protected function deleteCheck(AbstractNamedDBElement $entity): bool
|
||||
{
|
||||
|
|
|
@ -25,7 +25,6 @@ namespace App\Controller\AdminPages;
|
|||
use App\Entity\Attachments\ProjectAttachment;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Entity\Parameters\ProjectParameter;
|
||||
use App\Form\AdminPages\BaseEntityAdminForm;
|
||||
use App\Form\AdminPages\ProjectAdminForm;
|
||||
use App\Services\ImportExportSystem\EntityExporter;
|
||||
use App\Services\ImportExportSystem\EntityImporter;
|
||||
|
|
|
@ -24,12 +24,8 @@ namespace App\Controller;
|
|||
|
||||
use App\DataTables\AttachmentDataTable;
|
||||
use App\DataTables\Filters\AttachmentFilter;
|
||||
use App\DataTables\Filters\PartFilter;
|
||||
use App\DataTables\PartsDataTable;
|
||||
use App\Entity\Attachments\Attachment;
|
||||
use App\Entity\Attachments\PartAttachment;
|
||||
use App\Form\Filters\AttachmentFilterType;
|
||||
use App\Form\Filters\PartFilterType;
|
||||
use App\Services\Attachments\AttachmentManager;
|
||||
use App\Services\Trees\NodesListBuilder;
|
||||
use Omines\DataTablesBundle\DataTableFactory;
|
||||
|
@ -106,10 +102,8 @@ class AttachmentFileController extends AbstractController
|
|||
|
||||
/**
|
||||
* @Route("/attachment/list", name="attachment_list")
|
||||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function attachmentsTable(Request $request, DataTableFactory $dataTableFactory, NodesListBuilder $nodesListBuilder)
|
||||
public function attachmentsTable(Request $request, DataTableFactory $dataTableFactory, NodesListBuilder $nodesListBuilder): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@attachments.list_attachments');
|
||||
|
||||
|
|
|
@ -74,9 +74,9 @@ class GroupController extends BaseAdminController
|
|||
|
||||
//We need to stop the execution here, or our permissions changes will be overwritten by the form values
|
||||
return $this->redirectToRoute('group_edit', ['id' => $entity->getID()]);
|
||||
} else {
|
||||
$this->addFlash('danger', 'csfr_invalid');
|
||||
}
|
||||
|
||||
$this->addFlash('danger', 'csfr_invalid');
|
||||
}
|
||||
|
||||
return $this->_edit($entity, $request, $em, $timestamp);
|
||||
|
|
|
@ -68,9 +68,9 @@ class LogController extends AbstractController
|
|||
/**
|
||||
* @Route("/", name="log_view")
|
||||
*
|
||||
* @return JsonResponse|Response
|
||||
* @return Response
|
||||
*/
|
||||
public function showLogs(Request $request, DataTableFactory $dataTable)
|
||||
public function showLogs(Request $request, DataTableFactory $dataTable): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@system.show_logs');
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ use Symfony\Component\Form\FormInterface;
|
|||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
@ -351,8 +350,10 @@ class PartController extends AbstractController
|
|||
if($partLot->getPart() !== $part) {
|
||||
throw new \RuntimeException("The origin partlot does not belong to the part!");
|
||||
}
|
||||
//Try to determine the target lot (used for move actions)
|
||||
$targetLot = $em->find(PartLot::class, $request->request->get('target_id'));
|
||||
|
||||
//Try to determine the target lot (used for move actions), if the parameter is existing
|
||||
$targetId = $request->request->get('target_id', null);
|
||||
$targetLot = $targetId ? $em->find(PartLot::class, $targetId) : null;
|
||||
if ($targetLot && $targetLot->getPart() !== $part) {
|
||||
throw new \RuntimeException("The target partlot does not belong to the part!");
|
||||
}
|
||||
|
@ -396,7 +397,7 @@ class PartController extends AbstractController
|
|||
}
|
||||
|
||||
err:
|
||||
//If an redirect was passed, then redirect there
|
||||
//If a redirect was passed, then redirect there
|
||||
if($request->request->get('_redirect')) {
|
||||
return $this->redirect($request->request->get('_redirect'));
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@ use App\Services\ImportExportSystem\EntityExporter;
|
|||
use App\Services\ImportExportSystem\EntityImporter;
|
||||
use App\Services\LogSystem\EventCommentHelper;
|
||||
use App\Services\Parts\PartsTableActionHandler;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
|
|
@ -158,7 +158,7 @@ class PartListsController extends AbstractController
|
|||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function showCategory(Category $category, Request $request)
|
||||
public function showCategory(Category $category, Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@categories.read');
|
||||
|
||||
|
@ -180,7 +180,7 @@ class PartListsController extends AbstractController
|
|||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function showFootprint(Footprint $footprint, Request $request)
|
||||
public function showFootprint(Footprint $footprint, Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@footprints.read');
|
||||
|
||||
|
@ -202,7 +202,7 @@ class PartListsController extends AbstractController
|
|||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function showManufacturer(Manufacturer $manufacturer, Request $request)
|
||||
public function showManufacturer(Manufacturer $manufacturer, Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@manufacturers.read');
|
||||
|
||||
|
@ -224,7 +224,7 @@ class PartListsController extends AbstractController
|
|||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function showStorelocation(Storelocation $storelocation, Request $request)
|
||||
public function showStorelocation(Storelocation $storelocation, Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@storelocations.read');
|
||||
|
||||
|
@ -246,7 +246,7 @@ class PartListsController extends AbstractController
|
|||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function showSupplier(Supplier $supplier, Request $request)
|
||||
public function showSupplier(Supplier $supplier, Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@suppliers.read');
|
||||
|
||||
|
@ -268,7 +268,7 @@ class PartListsController extends AbstractController
|
|||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function showTag(string $tag, Request $request, DataTableFactory $dataTable)
|
||||
public function showTag(string $tag, Request $request): Response
|
||||
{
|
||||
$tag = trim($tag);
|
||||
|
||||
|
@ -291,6 +291,7 @@ class PartListsController extends AbstractController
|
|||
$filter->setName($request->query->getBoolean('name', true));
|
||||
$filter->setCategory($request->query->getBoolean('category', true));
|
||||
$filter->setDescription($request->query->getBoolean('description', true));
|
||||
$filter->setMpn($request->query->getBoolean('mpn', true));
|
||||
$filter->setTags($request->query->getBoolean('tags', true));
|
||||
$filter->setStorelocation($request->query->getBoolean('storelocation', true));
|
||||
$filter->setComment($request->query->getBoolean('comment', true));
|
||||
|
@ -300,6 +301,7 @@ class PartListsController extends AbstractController
|
|||
$filter->setManufacturer($request->query->getBoolean('manufacturer', false));
|
||||
$filter->setFootprint($request->query->getBoolean('footprint', false));
|
||||
|
||||
|
||||
$filter->setRegex($request->query->getBoolean('regex', false));
|
||||
|
||||
return $filter;
|
||||
|
@ -310,7 +312,7 @@ class PartListsController extends AbstractController
|
|||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function showSearch(Request $request, DataTableFactory $dataTable)
|
||||
public function showSearch(Request $request, DataTableFactory $dataTable): Response
|
||||
{
|
||||
$searchFilter = $this->searchRequestToFilter($request);
|
||||
|
||||
|
@ -331,9 +333,9 @@ class PartListsController extends AbstractController
|
|||
/**
|
||||
* @Route("/parts", name="parts_show_all")
|
||||
*
|
||||
* @return JsonResponse|Response
|
||||
* @return Response
|
||||
*/
|
||||
public function showAll(Request $request, DataTableFactory $dataTable)
|
||||
public function showAll(Request $request): Response
|
||||
{
|
||||
return $this->showListWithFilter($request,'parts/lists/all_list.html.twig');
|
||||
}
|
||||
|
|
|
@ -32,10 +32,8 @@ use App\Services\ImportExportSystem\BOMImporter;
|
|||
use App\Services\ProjectSystem\ProjectBuildHelper;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use League\Csv\Exception;
|
||||
use League\Csv\SyntaxError;
|
||||
use Omines\DataTablesBundle\DataTableFactory;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
@ -64,7 +62,7 @@ class ProjectController extends AbstractController
|
|||
/**
|
||||
* @Route("/{id}/info", name="project_info", requirements={"id"="\d+"})
|
||||
*/
|
||||
public function info(Project $project, Request $request, ProjectBuildHelper $buildHelper)
|
||||
public function info(Project $project, Request $request, ProjectBuildHelper $buildHelper): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('read', $project);
|
||||
|
||||
|
@ -114,9 +112,9 @@ class ProjectController extends AbstractController
|
|||
$request->get('_redirect',
|
||||
$this->generateUrl('project_info', ['id' => $project->getID()]
|
||||
)));
|
||||
} else {
|
||||
$this->addFlash('error', 'project.build.flash.invalid_input');
|
||||
}
|
||||
|
||||
$this->addFlash('error', 'project.build.flash.invalid_input');
|
||||
}
|
||||
|
||||
return $this->renderForm('projects/build/build.html.twig', [
|
||||
|
|
|
@ -28,20 +28,17 @@ use function in_array;
|
|||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class RedirectController extends AbstractController
|
||||
{
|
||||
protected string $default_locale;
|
||||
protected TranslatorInterface $translator;
|
||||
protected SessionInterface $session;
|
||||
protected bool $enforce_index_php;
|
||||
|
||||
public function __construct(string $default_locale, TranslatorInterface $translator, SessionInterface $session, bool $enforce_index_php)
|
||||
public function __construct(string $default_locale, TranslatorInterface $translator, bool $enforce_index_php)
|
||||
{
|
||||
$this->default_locale = $default_locale;
|
||||
$this->session = $session;
|
||||
$this->translator = $translator;
|
||||
$this->enforce_index_php = $enforce_index_php;
|
||||
}
|
||||
|
@ -52,7 +49,7 @@ class RedirectController extends AbstractController
|
|||
*/
|
||||
public function addLocalePart(Request $request): RedirectResponse
|
||||
{
|
||||
//By default we use the global default locale
|
||||
//By default, we use the global default locale
|
||||
$locale = $this->default_locale;
|
||||
|
||||
//Check if a user has set a preferred language setting:
|
||||
|
@ -61,7 +58,6 @@ class RedirectController extends AbstractController
|
|||
$locale = $user->getLanguage();
|
||||
}
|
||||
|
||||
//$new_url = str_replace($request->getPathInfo(), '/' . $locale . $request->getPathInfo(), $request->getUri());
|
||||
$new_url = $request->getUriForPath('/'.$locale.$request->getPathInfo());
|
||||
|
||||
//If either mod_rewrite is not enabled or the index.php version is enforced, add index.php to the string
|
||||
|
@ -71,6 +67,9 @@ class RedirectController extends AbstractController
|
|||
$new_url = $request->getSchemeAndHttpHost().$request->getBaseUrl().'/index.php/'.$locale.$request->getPathInfo();
|
||||
}
|
||||
|
||||
//Add the query string
|
||||
$new_url .= $request->getQueryString() ? '?'.$request->getQueryString() : '';
|
||||
|
||||
return $this->redirect($new_url);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace App\Controller;
|
|||
|
||||
use App\Entity\Base\AbstractNamedDBElement;
|
||||
use App\Entity\Base\AbstractStructuralDBElement;
|
||||
use App\Entity\Contracts\NamedElementInterface;
|
||||
use App\Entity\LabelSystem\LabelProfile;
|
||||
use App\Entity\Parts\Category;
|
||||
use App\Entity\Parts\Footprint;
|
||||
|
@ -106,7 +105,7 @@ class SelectAPIController extends AbstractController
|
|||
3 => $this->translator->trans('export.level.full'),
|
||||
];
|
||||
|
||||
return $this->json(array_map(function ($key, $value) {
|
||||
return $this->json(array_map(static function ($key, $value) {
|
||||
return [
|
||||
'text' => $value,
|
||||
'value' => $key,
|
||||
|
@ -198,7 +197,7 @@ class SelectAPIController extends AbstractController
|
|||
]);
|
||||
//Remove the data-* prefix for each key
|
||||
$data = array_combine(
|
||||
array_map(function ($key) {
|
||||
array_map(static function ($key) {
|
||||
if (strpos($key, 'data-') === 0) {
|
||||
return substr($key, 5);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ class TypeaheadController extends AbstractController
|
|||
}
|
||||
|
||||
/**
|
||||
* This functions map the parameter type to the class, so we can access its repository
|
||||
* This function map the parameter type to the class, so we can access its repository
|
||||
* @param string $type
|
||||
* @return class-string
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,6 @@ namespace App\Controller;
|
|||
use App\DataTables\LogDataTable;
|
||||
use App\Entity\Attachments\UserAttachment;
|
||||
use App\Entity\Base\AbstractNamedDBElement;
|
||||
use App\Entity\Parameters\AbstractParameter;
|
||||
use App\Entity\UserSystem\User;
|
||||
use App\Events\SecurityEvent;
|
||||
use App\Events\SecurityEvents;
|
||||
|
@ -62,11 +61,11 @@ class UserController extends AdminPages\BaseAdminController
|
|||
|
||||
protected function additionalActionEdit(FormInterface $form, AbstractNamedDBElement $entity): bool
|
||||
{
|
||||
//Check if we editing a user and if we need to change the password of it
|
||||
//Check if we're editing a user and if we need to change the password of it
|
||||
if ($entity instanceof User && !empty($form['new_password']->getData())) {
|
||||
$password = $this->passwordEncoder->hashPassword($entity, $form['new_password']->getData());
|
||||
$entity->setPassword($password);
|
||||
//By default the user must change the password afterwards
|
||||
//By default, the user must change the password afterward
|
||||
$entity->setNeedPwChange(true);
|
||||
|
||||
$event = new SecurityEvent($entity);
|
||||
|
@ -129,9 +128,9 @@ class UserController extends AdminPages\BaseAdminController
|
|||
|
||||
//We need to stop the execution here, or our permissions changes will be overwritten by the form values
|
||||
return $this->redirectToRoute('user_edit', ['id' => $entity->getID()]);
|
||||
} else {
|
||||
$this->addFlash('danger', 'csfr_invalid');
|
||||
}
|
||||
|
||||
$this->addFlash('danger', 'csfr_invalid');
|
||||
}
|
||||
|
||||
return $this->_edit($entity, $request, $em, $timestamp);
|
||||
|
@ -142,7 +141,7 @@ class UserController extends AdminPages\BaseAdminController
|
|||
if ($entity instanceof User && !empty($form['new_password']->getData())) {
|
||||
$password = $this->passwordEncoder->hashPassword($entity, $form['new_password']->getData());
|
||||
$entity->setPassword($password);
|
||||
//By default the user must change the password afterwards
|
||||
//By default, the user must change the password afterward
|
||||
$entity->setNeedPwChange(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ class UserSettingsController extends AbstractController
|
|||
*/
|
||||
public function userSettings(Request $request, EntityManagerInterface $em, UserPasswordHasherInterface $passwordEncoder, GoogleAuthenticator $googleAuthenticator, BackupCodeManager $backupCodeManager, FormFactoryInterface $formFactory, UserAvatarHelper $avatarHelper)
|
||||
{
|
||||
/** @var User */
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
|
||||
$page_need_reload = false;
|
||||
|
@ -261,7 +261,7 @@ class UserSettingsController extends AbstractController
|
|||
$page_need_reload = true;
|
||||
}
|
||||
|
||||
/** @var Form $form We need an form implementation for the next calls */
|
||||
/** @var Form $form We need a form implementation for the next calls */
|
||||
if ($form->getClickedButton() && 'remove_avatar' === $form->getClickedButton()->getName()) {
|
||||
//Remove the avatar attachment from the user if requested
|
||||
if ($user->getMasterPictureAttachment() !== null) {
|
||||
|
@ -327,7 +327,7 @@ class UserSettingsController extends AbstractController
|
|||
|
||||
$pw_form->handleRequest($request);
|
||||
|
||||
//Check if password if everything was correct, then save it to User and DB
|
||||
//Check if everything was correct, then save it to User and DB
|
||||
if (!$this->demo_mode && $pw_form->isSubmitted() && $pw_form->isValid()) {
|
||||
$password = $passwordEncoder->hashPassword($user, $pw_form['new_password']->getData());
|
||||
$user->setPassword($password);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
namespace App\DataTables\Adapters;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||
use Omines\DataTablesBundle\Adapter\Doctrine\FetchJoinORMAdapter;
|
||||
|
@ -38,7 +37,7 @@ use Omines\DataTablesBundle\Adapter\Doctrine\FetchJoinORMAdapter;
|
|||
*/
|
||||
class CustomFetchJoinORMAdapter extends FetchJoinORMAdapter
|
||||
{
|
||||
public function getCount(QueryBuilder $queryBuilder, $identifier)
|
||||
public function getCount(QueryBuilder $queryBuilder, $identifier): ?int
|
||||
{
|
||||
$qb_without_group_by = clone $queryBuilder;
|
||||
|
||||
|
|
|
@ -22,9 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\DataTables\Column;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Base\AbstractNamedDBElement;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Services\EntityURLGenerator;
|
||||
use Omines\DataTablesBundle\Column\AbstractColumn;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
|
|
|
@ -31,7 +31,7 @@ use Omines\DataTablesBundle\Column\AbstractColumn;
|
|||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* Similar to the built in DateTimeColumn, but the datetime is formatted using a IntlDateFormatter,
|
||||
* Similar to the built-in DateTimeColumn, but the datetime is formatted using a IntlDateFormatter,
|
||||
* to get prettier locale based formatting.
|
||||
*/
|
||||
class LocaleDateTimeColumn extends AbstractColumn
|
||||
|
@ -45,7 +45,9 @@ class LocaleDateTimeColumn extends AbstractColumn
|
|||
{
|
||||
if (null === $value) {
|
||||
return $this->options['nullValue'];
|
||||
} elseif (!$value instanceof DateTimeInterface) {
|
||||
}
|
||||
|
||||
if (!$value instanceof DateTimeInterface) {
|
||||
$value = new DateTime((string) $value);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class PrettyBoolColumn extends AbstractColumn
|
|||
return (bool) $value;
|
||||
}
|
||||
|
||||
public function render($value, $context)
|
||||
public function render($value, $context): string
|
||||
{
|
||||
if ($value === true) {
|
||||
return '<span class="badge bg-success"><i class="fa-solid fa-circle-check fa-fw"></i> '
|
||||
|
|
|
@ -27,7 +27,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||
class RowClassColumn extends AbstractColumn
|
||||
{
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
public function configureOptions(OptionsResolver $resolver): self
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
|
||||
|
@ -48,6 +48,9 @@ class RowClassColumn extends AbstractColumn
|
|||
parent::initialize('$$rowClass', $index, $options, $dataTable); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function normalize($value)
|
||||
{
|
||||
return $value;
|
||||
|
|
|
@ -33,7 +33,7 @@ class SIUnitNumberColumn extends AbstractColumn
|
|||
$this->formatter = $formatter;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
public function configureOptions(OptionsResolver $resolver): self
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
|
||||
|
@ -43,7 +43,7 @@ class SIUnitNumberColumn extends AbstractColumn
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function normalize($value)
|
||||
public function normalize($value): string
|
||||
{
|
||||
//Ignore null values
|
||||
if ($value === null) {
|
||||
|
|
|
@ -28,7 +28,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||
*/
|
||||
class SelectColumn extends AbstractColumn
|
||||
{
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
public function configureOptions(OptionsResolver $resolver): self
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
|
||||
|
@ -43,12 +43,15 @@ class SelectColumn extends AbstractColumn
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function normalize($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function render($value, $context)
|
||||
public function render($value, $context): string
|
||||
{
|
||||
//Return empty string, as it this column is filled by datatables on client side
|
||||
return '';
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
namespace App\DataTables\Filters\Constraints;
|
||||
|
||||
use App\DataTables\Filters\FilterInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
abstract class AbstractConstraint implements FilterInterface
|
||||
{
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
namespace App\DataTables\Filters\Constraints;
|
||||
|
||||
use App\DataTables\Filters\FilterInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
class BooleanConstraint extends AbstractConstraint
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
namespace App\DataTables\Filters\Constraints;
|
||||
|
||||
use Doctrine\DBAL\ParameterType;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
trait FilterTrait
|
||||
|
@ -51,7 +50,7 @@ trait FilterTrait
|
|||
protected function generateParameterIdentifier(string $property): string
|
||||
{
|
||||
//Replace all special characters with underscores
|
||||
$property = preg_replace('/[^a-zA-Z0-9_]/', '_', $property);
|
||||
$property = preg_replace('/\W/', '_', $property);
|
||||
//Add a random number to the end of the property name for uniqueness
|
||||
return $property . '_' . uniqid("", false);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ class InstanceOfConstraint extends AbstractConstraint
|
|||
|
||||
if ($this->operator === 'ANY' || $this->operator === 'NONE') {
|
||||
foreach($this->value as $value) {
|
||||
//We cannnot use an paramater here, as this is the only way to pass the FCQN to the query (via binded params, we would need to use ClassMetaData). See: https://github.com/doctrine/orm/issues/4462
|
||||
//We can not use a parameter here, as this is the only way to pass the FCQN to the query (via binded params, we would need to use ClassMetaData). See: https://github.com/doctrine/orm/issues/4462
|
||||
$expressions[] = ($queryBuilder->expr()->isInstanceOf($this->property, $value));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
namespace App\DataTables\Filters\Constraints;
|
||||
|
||||
use Doctrine\DBAL\ParameterType;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use RuntimeException;
|
||||
|
||||
|
@ -42,7 +41,7 @@ class NumberConstraint extends AbstractConstraint
|
|||
protected $value2;
|
||||
|
||||
/**
|
||||
* @var string The operator to use
|
||||
* @var string|null The operator to use
|
||||
*/
|
||||
protected ?string $operator;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ use App\DataTables\Filters\Constraints\AbstractConstraint;
|
|||
use App\DataTables\Filters\Constraints\TextConstraint;
|
||||
use App\Entity\Parameters\PartParameter;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Svg\Tag\Text;
|
||||
|
||||
class ParameterConstraint extends AbstractConstraint
|
||||
{
|
||||
|
|
|
@ -101,7 +101,7 @@ class TextConstraint extends AbstractConstraint
|
|||
return;
|
||||
}
|
||||
|
||||
//The CONTAINS, LIKE, STARTS and ENDS operators use the LIKE operator but we have to build the value string differently
|
||||
//The CONTAINS, LIKE, STARTS and ENDS operators use the LIKE operator, but we have to build the value string differently
|
||||
$like_value = null;
|
||||
if ($this->operator === 'LIKE') {
|
||||
$like_value = $this->value;
|
||||
|
|
|
@ -38,11 +38,9 @@ use App\Entity\Parts\MeasurementUnit;
|
|||
use App\Entity\Parts\Storelocation;
|
||||
use App\Entity\Parts\Supplier;
|
||||
use App\Entity\UserSystem\User;
|
||||
use App\Form\Filters\Constraints\UserEntityConstraintType;
|
||||
use App\Services\Trees\NodesListBuilder;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Svg\Tag\Text;
|
||||
|
||||
class PartFilter implements FilterInterface
|
||||
{
|
||||
|
@ -148,9 +146,9 @@ class PartFilter implements FilterInterface
|
|||
|
||||
|
||||
/**
|
||||
* @return BooleanConstraint|false
|
||||
* @return BooleanConstraint
|
||||
*/
|
||||
public function getFavorite()
|
||||
public function getFavorite(): BooleanConstraint
|
||||
{
|
||||
return $this->favorite;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ class PartSearchFilter implements FilterInterface
|
|||
$fields_to_search[] = 'orderdetails.supplierpartnr';
|
||||
}
|
||||
if($this->mpn) {
|
||||
$fields_to_search[] = 'part.manufacturer_product_url';
|
||||
$fields_to_search[] = 'part.manufacturer_product_number';
|
||||
}
|
||||
if($this->supplier) {
|
||||
$fields_to_search[] = 'suppliers.name';
|
||||
|
|
|
@ -28,7 +28,6 @@ use App\DataTables\Column\LogEntryExtraColumn;
|
|||
use App\DataTables\Column\LogEntryTargetColumn;
|
||||
use App\DataTables\Column\RevertLogColumn;
|
||||
use App\DataTables\Column\RowClassColumn;
|
||||
use App\DataTables\Filters\AttachmentFilter;
|
||||
use App\DataTables\Filters\LogFilter;
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Contracts\TimeTravelInterface;
|
||||
|
@ -60,8 +59,6 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
class LogDataTable implements DataTableTypeInterface
|
||||
{
|
||||
protected ElementTypeNameGenerator $elementTypeNameGenerator;
|
||||
|
|
|
@ -36,22 +36,14 @@ use App\DataTables\Column\TagsColumn;
|
|||
use App\DataTables\Filters\PartFilter;
|
||||
use App\DataTables\Filters\PartSearchFilter;
|
||||
use App\DataTables\Helpers\PartDataTableHelper;
|
||||
use App\Entity\Parts\Category;
|
||||
use App\Entity\Parts\Footprint;
|
||||
use App\Entity\Parts\Manufacturer;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Entity\Parts\PartLot;
|
||||
use App\Entity\Parts\Storelocation;
|
||||
use App\Entity\Parts\Supplier;
|
||||
use App\Services\Formatters\AmountFormatter;
|
||||
use App\Services\Attachments\AttachmentURLGenerator;
|
||||
use App\Services\Attachments\PartPreviewGenerator;
|
||||
use App\Services\EntityURLGenerator;
|
||||
use App\Services\Trees\NodesListBuilder;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Omines\DataTablesBundle\Adapter\Doctrine\FetchJoinORMAdapter;
|
||||
use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider;
|
||||
use Omines\DataTablesBundle\Column\BoolColumn;
|
||||
use Omines\DataTablesBundle\Column\MapColumn;
|
||||
use Omines\DataTablesBundle\Column\TextColumn;
|
||||
use Omines\DataTablesBundle\DataTable;
|
||||
|
@ -63,27 +55,19 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
|||
final class PartsDataTable implements DataTableTypeInterface
|
||||
{
|
||||
private TranslatorInterface $translator;
|
||||
private NodesListBuilder $treeBuilder;
|
||||
private AmountFormatter $amountFormatter;
|
||||
private AttachmentURLGenerator $attachmentURLGenerator;
|
||||
private Security $security;
|
||||
|
||||
private PartDataTableHelper $partDataTableHelper;
|
||||
|
||||
/**
|
||||
* @var EntityURLGenerator
|
||||
*/
|
||||
private $urlGenerator;
|
||||
private EntityURLGenerator $urlGenerator;
|
||||
|
||||
public function __construct(EntityURLGenerator $urlGenerator, TranslatorInterface $translator,
|
||||
NodesListBuilder $treeBuilder, AmountFormatter $amountFormatter,PartDataTableHelper $partDataTableHelper,
|
||||
AttachmentURLGenerator $attachmentURLGenerator, Security $security)
|
||||
AmountFormatter $amountFormatter,PartDataTableHelper $partDataTableHelper, Security $security)
|
||||
{
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->translator = $translator;
|
||||
$this->treeBuilder = $treeBuilder;
|
||||
$this->amountFormatter = $amountFormatter;
|
||||
$this->attachmentURLGenerator = $attachmentURLGenerator;
|
||||
$this->security = $security;
|
||||
$this->partDataTableHelper = $partDataTableHelper;
|
||||
}
|
||||
|
@ -168,6 +152,7 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
if ($this->security->isGranted('@storelocations.read')) {
|
||||
$dataTable->add('storelocation', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.storeLocations'),
|
||||
'orderField' => 'storelocations.name',
|
||||
'render' => function ($value, Part $context) {
|
||||
$tmp = [];
|
||||
foreach ($context->getPartLots() as $lot) {
|
||||
|
@ -193,7 +178,22 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
$amount = $context->getAmountSum();
|
||||
$expiredAmount = $context->getExpiredAmountSum();
|
||||
|
||||
$ret = htmlspecialchars($this->amountFormatter->format($amount, $context->getPartUnit()));
|
||||
$ret = '';
|
||||
|
||||
if ($context->isAmountUnknown()) {
|
||||
//When all amounts are unknown, we show a question mark
|
||||
if ($amount === 0.0) {
|
||||
$ret .= sprintf('<b class="text-primary" title="%s">?</b>',
|
||||
$this->translator->trans('part_lots.instock_unknown'));
|
||||
} else { //Otherwise mark it with greater equal and the (known) amount
|
||||
$ret .= sprintf('<b class="text-primary" title="%s">≥</b>',
|
||||
$this->translator->trans('part_lots.instock_unknown')
|
||||
);
|
||||
$ret .= htmlspecialchars($this->amountFormatter->format($amount, $context->getPartUnit()));
|
||||
}
|
||||
} else {
|
||||
$ret .= htmlspecialchars($this->amountFormatter->format($amount, $context->getPartUnit()));
|
||||
}
|
||||
|
||||
//If we have expired lots, we show them in parentheses behind
|
||||
if ($expiredAmount > 0) {
|
||||
|
|
|
@ -27,7 +27,6 @@ use Doctrine\Common\DataFixtures\Purger\PurgerInterface;
|
|||
use Doctrine\Common\DataFixtures\Sorter\TopologicalSorter;
|
||||
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Platforms\MySQLPlatform;
|
||||
use Doctrine\DBAL\Schema\Identifier;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
|
@ -35,7 +34,6 @@ use Doctrine\ORM\Mapping\ClassMetadata;
|
|||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
|
||||
use function array_reverse;
|
||||
use function array_search;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function is_callable;
|
||||
|
@ -53,21 +51,21 @@ class ResetAutoIncrementORMPurger implements PurgerInterface, ORMPurgerInterface
|
|||
public const PURGE_MODE_TRUNCATE = 2;
|
||||
|
||||
/** @var EntityManagerInterface|null */
|
||||
private $em;
|
||||
private ?EntityManagerInterface $em;
|
||||
|
||||
/**
|
||||
* If the purge should be done through DELETE or TRUNCATE statements
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $purgeMode = self::PURGE_MODE_DELETE;
|
||||
private int $purgeMode = self::PURGE_MODE_DELETE;
|
||||
|
||||
/**
|
||||
* Table/view names to be excluded from purge
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $excluded;
|
||||
private array $excluded;
|
||||
|
||||
/**
|
||||
* Construct new purger instance.
|
||||
|
|
|
@ -49,7 +49,7 @@ class SQLiteRegexExtension implements EventSubscriberInterface
|
|||
}
|
||||
}
|
||||
|
||||
public function getSubscribedEvents()
|
||||
public function getSubscribedEvents(): array
|
||||
{
|
||||
return[
|
||||
Events::postConnect
|
||||
|
|
|
@ -24,7 +24,7 @@ use Doctrine\DBAL\Driver;
|
|||
use Doctrine\DBAL\Driver\Middleware;
|
||||
|
||||
/**
|
||||
* This class wraps the Doctrine DBAL driver and wraps it into an Midleware driver so we can change the SQL mode
|
||||
* This class wraps the Doctrine DBAL driver and wraps it into a Midleware driver, so we can change the SQL mode
|
||||
*/
|
||||
class SetSQLModeMiddlewareWrapper implements Middleware
|
||||
{
|
||||
|
|
|
@ -29,17 +29,17 @@ use Doctrine\DBAL\Types\Type;
|
|||
class TinyIntType extends Type
|
||||
{
|
||||
|
||||
public function getSQLDeclaration(array $column, AbstractPlatform $platform)
|
||||
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
|
||||
{
|
||||
return 'TINYINT';
|
||||
}
|
||||
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'tinyint';
|
||||
}
|
||||
|
||||
public function requiresSQLCommentHint(AbstractPlatform $platform)
|
||||
public function requiresSQLCommentHint(AbstractPlatform $platform): bool
|
||||
{
|
||||
//We use the comment, so that doctrine migrations can properly detect, that nothing has changed and no migration is needed.
|
||||
return true;
|
||||
|
|
|
@ -59,7 +59,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
/**
|
||||
* A list of file extensions, that browsers can show directly as image.
|
||||
* Based on: https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types
|
||||
* It will be used to determine if a attachment is a picture and therefore will be shown to user as preview.
|
||||
* It will be used to determine if an attachment is a picture and therefore will be shown to user as preview.
|
||||
*/
|
||||
public const PICTURE_EXTS = ['apng', 'bmp', 'gif', 'ico', 'cur', 'jpg', 'jpeg', 'jfif', 'pjpeg', 'pjp', 'png',
|
||||
'svg', 'webp', ];
|
||||
|
@ -70,7 +70,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
public const MODEL_EXTS = ['x3d'];
|
||||
|
||||
/**
|
||||
* When the path begins with one of this placeholders.
|
||||
* When the path begins with one of the placeholders.
|
||||
*/
|
||||
public const INTERNAL_PLACEHOLDER = ['%BASE%', '%MEDIA%', '%SECURE%'];
|
||||
|
||||
|
@ -105,7 +105,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
protected string $name = '';
|
||||
|
||||
/**
|
||||
* ORM mapping is done in sub classes (like PartAttachment).
|
||||
* ORM mapping is done in subclasses (like PartAttachment).
|
||||
*/
|
||||
protected ?AttachmentContainingDBElement $element = null;
|
||||
|
||||
|
@ -116,7 +116,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
protected bool $show_in_table = false;
|
||||
|
||||
/**
|
||||
* @var AttachmentType
|
||||
* @var AttachmentType|null
|
||||
* @ORM\ManyToOne(targetEntity="AttachmentType", inversedBy="attachments_with_type")
|
||||
* @ORM\JoinColumn(name="type_id", referencedColumnName="id", nullable=false)
|
||||
* @Selectable()
|
||||
|
@ -153,7 +153,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
*/
|
||||
public function isPicture(): bool
|
||||
{
|
||||
//We can not check if a external link is a picture, so just assume this is false
|
||||
//We can not check if an external link is a picture, so just assume this is false
|
||||
if ($this->isExternal()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
* Checks if the attachment file is using a builtin file. (see BUILTIN_PLACEHOLDERS const for possible placeholders)
|
||||
* If a file is built in, the path is shown to user in url field (no sensitive infos are provided).
|
||||
*
|
||||
* @return bool true if the attachment is using an builtin file
|
||||
* @return bool true if the attachment is using a builtin file
|
||||
*/
|
||||
public function isBuiltIn(): bool
|
||||
{
|
||||
|
@ -259,7 +259,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
}
|
||||
|
||||
/**
|
||||
* The URL to the external file, or the path to the built in file.
|
||||
* The URL to the external file, or the path to the built-in file.
|
||||
* Returns null, if the file is not external (and not builtin).
|
||||
*/
|
||||
public function getURL(): ?string
|
||||
|
@ -455,9 +455,9 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
* @param string $string The string which should be checked
|
||||
* @param bool $path_required If true, the string must contain a path to be valid. (e.g. foo.bar would be invalid, foo.bar/test.php would be valid).
|
||||
* @param bool $only_http Set this to true, if only HTTPS or HTTP schemata should be allowed.
|
||||
* *Caution: When this is set to false, a attacker could use the file:// schema, to get internal server files, like /etc/passwd.*
|
||||
* *Caution: When this is set to false, an attacker could use the file:// schema, to get internal server files, like /etc/passwd.*
|
||||
*
|
||||
* @return bool True if the string is a valid URL. False, if the string is not an URL or invalid.
|
||||
* @return bool True if the string is a valid URL. False, if the string is not a URL or invalid.
|
||||
*/
|
||||
public static function isValidURL(string $string, bool $path_required = true, bool $only_http = true): bool
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ abstract class AttachmentContainingDBElement extends AbstractNamedDBElement impl
|
|||
* Mapping is done in sub classes like part
|
||||
* @Groups({"full"})
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -45,13 +45,13 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
* @ORM\OneToMany(targetEntity="AttachmentType", mappedBy="parent", cascade={"persist"})
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
protected Collection $children;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="AttachmentType", inversedBy="children")
|
||||
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
|
||||
*/
|
||||
protected $parent;
|
||||
protected ?AbstractStructuralDBElement $parent;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -65,14 +65,14 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
/** @var Collection<int, AttachmentTypeParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\AttachmentTypeParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Attachment>
|
||||
|
@ -99,7 +99,7 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets an filter, which file types are allowed for attachment files.
|
||||
* Gets a filter, which file types are allowed for attachment files.
|
||||
* Must be in the format of <input type=file> accept attribute
|
||||
* (See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers).
|
||||
*/
|
||||
|
|
|
@ -35,7 +35,7 @@ class AttachmentTypeAttachment extends Attachment
|
|||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = AttachmentType::class;
|
||||
/**
|
||||
* @var AttachmentType the element this attachment is associated with
|
||||
* @var AttachmentContainingDBElement|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Attachments\AttachmentType", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a category element.
|
||||
* An attachment attached to a category element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
|
@ -36,7 +36,7 @@ class CategoryAttachment extends Attachment
|
|||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Category::class;
|
||||
/**
|
||||
* @var Category the element this attachment is associated with
|
||||
* @var AttachmentContainingDBElement|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Category", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -36,7 +36,7 @@ class CurrencyAttachment extends Attachment
|
|||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Currency::class;
|
||||
/**
|
||||
* @var Currency the element this attachment is associated with
|
||||
* @var Currency|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\PriceInformations\Currency", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a footprint element.
|
||||
* An attachment attached to a footprint element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
|
@ -36,7 +36,7 @@ class FootprintAttachment extends Attachment
|
|||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Footprint::class;
|
||||
/**
|
||||
* @var Footprint the element this attachment is associated with
|
||||
* @var Footprint|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Footprint", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a Group element.
|
||||
* An attachment attached to a Group element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
|
@ -35,8 +35,9 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
|||
class GroupAttachment extends Attachment
|
||||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Group::class;
|
||||
|
||||
/**
|
||||
* @var Group the element this attachment is associated with
|
||||
* @var Group|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\UserSystem\Group", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a manufacturer element.
|
||||
* An attachment attached to a manufacturer element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
|
@ -35,8 +35,9 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
|||
class ManufacturerAttachment extends Attachment
|
||||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Manufacturer::class;
|
||||
|
||||
/**
|
||||
* @var Manufacturer the element this attachment is associated with
|
||||
* @var Manufacturer|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Manufacturer", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -28,7 +28,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a measurement unit element.
|
||||
* An attachment attached to a measurement unit element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
|
@ -37,7 +37,7 @@ class MeasurementUnitAttachment extends Attachment
|
|||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = MeasurementUnit::class;
|
||||
/**
|
||||
* @var Manufacturer the element this attachment is associated with
|
||||
* @var Manufacturer|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\MeasurementUnit", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -36,7 +36,7 @@ class ProjectAttachment extends Attachment
|
|||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Project::class;
|
||||
/**
|
||||
* @var Project the element this attachment is associated with
|
||||
* @var Project|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\ProjectSystem\Project", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a measurement unit element.
|
||||
* An attachment attached to a measurement unit element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
|
@ -35,8 +35,9 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
|||
class StorelocationAttachment extends Attachment
|
||||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Storelocation::class;
|
||||
|
||||
/**
|
||||
* @var Storelocation the element this attachment is associated with
|
||||
* @var Storelocation|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Storelocation", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -35,8 +35,9 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
|||
class SupplierAttachment extends Attachment
|
||||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = Supplier::class;
|
||||
|
||||
/**
|
||||
* @var Supplier the element this attachment is associated with
|
||||
* @var Supplier|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Supplier", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a user element.
|
||||
* An attachment attached to a user element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
|
@ -35,8 +35,9 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
|||
class UserAttachment extends Attachment
|
||||
{
|
||||
public const ALLOWED_ELEMENT_CLASS = User::class;
|
||||
|
||||
/**
|
||||
* @var User the element this attachment is associated with
|
||||
* @var User|null the element this attachment is associated with
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\UserSystem\User", inversedBy="attachments")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Base;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
|
@ -33,5 +34,5 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||
abstract class AbstractPartsContainingDBElement extends AbstractStructuralDBElement
|
||||
{
|
||||
/** @Groups({"full"}) */
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
}
|
||||
|
|
|
@ -81,22 +81,22 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
protected int $level = 0;
|
||||
|
||||
/**
|
||||
* We can not define the mapping here or we will get an exception. Unfortunately we have to do the mapping in the
|
||||
* We can not define the mapping here, or we will get an exception. Unfortunately we have to do the mapping in the
|
||||
* subclasses.
|
||||
*
|
||||
* @var AbstractStructuralDBElement[]|Collection
|
||||
* @Groups({"include_children"})
|
||||
*/
|
||||
protected $children;
|
||||
protected Collection $children;
|
||||
|
||||
/**
|
||||
* @var AbstractStructuralDBElement
|
||||
* @NoneOfItsChildren()
|
||||
* @Groups({"include_parents", "import"})
|
||||
*/
|
||||
protected $parent = null;
|
||||
protected ?AbstractStructuralDBElement $parent = null;
|
||||
|
||||
/** @var string[] all names of all parent elements as a array of strings,
|
||||
/** @var string[] all names of all parent elements as an array of strings,
|
||||
* the last array element is the name of the element itself
|
||||
*/
|
||||
private array $full_path_strings = [];
|
||||
|
@ -106,6 +106,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
parent::__construct();
|
||||
$this->children = new ArrayCollection();
|
||||
$this->parameters = new ArrayCollection();
|
||||
$this->parent = null;
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
|
@ -155,10 +156,8 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
if ($this->getParent() === $another_element) {
|
||||
return true;
|
||||
}
|
||||
} else { //If the IDs are defined, we can compare the IDs
|
||||
if ($this->getParent()->getID() === $another_element->getID()) {
|
||||
return true;
|
||||
}
|
||||
} elseif ($this->getParent()->getID() === $another_element->getID()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Otherwise, check recursively
|
||||
|
@ -168,7 +167,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
/**
|
||||
* Checks if this element is an root element (has no parent).
|
||||
*
|
||||
* @return bool true if the this element is an root element
|
||||
* @return bool true if this element is a root element
|
||||
*/
|
||||
public function isRoot(): bool
|
||||
{
|
||||
|
|
|
@ -27,12 +27,12 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* A entity with this class has a master attachment, which is used as a preview image for this object.
|
||||
* An entity with this class has a master attachment, which is used as a preview image for this object.
|
||||
*/
|
||||
trait MasterAttachmentTrait
|
||||
{
|
||||
/**
|
||||
* @var Attachment
|
||||
* @var Attachment|null
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Attachments\Attachment")
|
||||
* @ORM\JoinColumn(name="id_preview_attachment", referencedColumnName="id", onDelete="SET NULL", nullable=true)
|
||||
* @Assert\Expression("value == null or value.isPicture()", message="part.master_attachment.must_be_picture")
|
||||
|
|
|
@ -27,9 +27,9 @@ use DateTime;
|
|||
interface TimeTravelInterface
|
||||
{
|
||||
/**
|
||||
* Checks if this entry has informations which data has changed.
|
||||
* Checks if this entry has information which data has changed.
|
||||
*
|
||||
* @return bool true if this entry has informations about the changed data
|
||||
* @return bool true if this entry has information about the changed data
|
||||
*/
|
||||
public function hasOldDataInformations(): bool;
|
||||
|
||||
|
@ -39,7 +39,7 @@ interface TimeTravelInterface
|
|||
public function getOldData(): array;
|
||||
|
||||
/**
|
||||
* Returns the the timestamp associated with this change.
|
||||
* Returns the timestamp associated with this change.
|
||||
*/
|
||||
public function getTimestamp(): DateTime;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class LabelProfile extends AttachmentContainingDBElement
|
|||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\LabelAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
/**
|
||||
* @var LabelOptions
|
||||
|
|
|
@ -48,7 +48,7 @@ use InvalidArgumentException;
|
|||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* This entity describes a entry in the event log.
|
||||
* This entity describes an entry in the event log.
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="App\Repository\LogEntryRepository")
|
||||
* @ORM\Table("log", indexes={
|
||||
|
@ -142,7 +142,7 @@ abstract class AbstractLogEntry extends AbstractDBElement
|
|||
self::TARGET_TYPE_LABEL_PROFILE => LabelProfile::class,
|
||||
];
|
||||
|
||||
/** @var User The user which has caused this log entry
|
||||
/** @var User|null The user which has caused this log entry
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\UserSystem\User", fetch="EAGER")
|
||||
* @ORM\JoinColumn(name="id_user", nullable=true, onDelete="SET NULL")
|
||||
*/
|
||||
|
@ -183,7 +183,7 @@ abstract class AbstractLogEntry extends AbstractDBElement
|
|||
/** @var array The extra data in raw (short form) saved in the DB
|
||||
* @ORM\Column(name="extra", type="json")
|
||||
*/
|
||||
protected $extra = [];
|
||||
protected array $extra = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -340,7 +340,7 @@ abstract class AbstractLogEntry extends AbstractDBElement
|
|||
|
||||
/**
|
||||
* Returns the class name of the target element associated with this log entry.
|
||||
* Returns null, if this log entry is not associated with an log entry.
|
||||
* Returns null, if this log entry is not associated with a log entry.
|
||||
*
|
||||
* @return string|null the class name of the target class
|
||||
*/
|
||||
|
@ -355,7 +355,7 @@ abstract class AbstractLogEntry extends AbstractDBElement
|
|||
|
||||
/**
|
||||
* Returns the ID of the target element associated with this log entry.
|
||||
* Returns null, if this log entry is not associated with an log entry.
|
||||
* Returns null, if this log entry is not associated with a log entry.
|
||||
*
|
||||
* @return int|null the ID of the associated element
|
||||
*/
|
||||
|
@ -451,7 +451,7 @@ abstract class AbstractLogEntry extends AbstractDBElement
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts an target type id to an full qualified class name.
|
||||
* Converts a target type id to a full qualified class name.
|
||||
*
|
||||
* @param int $type_id The target type ID
|
||||
*/
|
||||
|
|
|
@ -81,13 +81,12 @@ use App\Entity\Parts\Supplier;
|
|||
use App\Entity\PriceInformations\Currency;
|
||||
use App\Entity\UserSystem\Group;
|
||||
use App\Entity\UserSystem\User;
|
||||
use App\Repository\Parts\ManufacturerRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* This log entry is created when an element is deleted, that is used in a collection of an other entity.
|
||||
* This log entry is created when an element is deleted, that is used in a collection of another entity.
|
||||
* This is needed to signal time travel, that it has to undelete the deleted entity.
|
||||
*/
|
||||
class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventUndoInterface
|
||||
|
|
|
@ -43,7 +43,7 @@ class DatabaseUpdatedLogEntry extends AbstractLogEntry
|
|||
*/
|
||||
public function isSuccessful(): bool
|
||||
{
|
||||
//We dont save unsuccessful updates now, so just assume it to save space.
|
||||
//We don't save unsuccessful updates now, so just assume it to save space.
|
||||
return $this->extra['s'] ?? true;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ class LegacyInstockChangedLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the price that has to be payed for the change (in the base currency).
|
||||
* Returns the price that has to be paid for the change (in the base currency).
|
||||
*
|
||||
* @param bool $absolute Set this to true, if you want only get the absolute value of the price (without minus)
|
||||
*/
|
||||
|
@ -92,9 +92,9 @@ class LegacyInstockChangedLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if the Change was an withdrawal of parts.
|
||||
* Checks if the Change was a withdrawal of parts.
|
||||
*
|
||||
* @return bool true if the change was an withdrawal, false if not
|
||||
* @return bool true if the change was a withdrawal, false if not
|
||||
*/
|
||||
public function isWithdrawal(): bool
|
||||
{
|
||||
|
|
|
@ -117,7 +117,7 @@ class SecurityEventLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the (anonymized) IP address used to login the user.
|
||||
* Return the (anonymized) IP address used to log in the user.
|
||||
*/
|
||||
public function getIPAddress(): string
|
||||
{
|
||||
|
@ -125,9 +125,9 @@ class SecurityEventLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the IP address used to login the user.
|
||||
* Sets the IP address used to log in the user.
|
||||
*
|
||||
* @param string $ip the IP address used to login the user
|
||||
* @param string $ip the IP address used to log in the user
|
||||
* @param bool $anonymize Anonymize the IP address (remove last block) to be GPDR compliant
|
||||
*
|
||||
* @return $this
|
||||
|
|
|
@ -42,7 +42,7 @@ class UserLoginLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the (anonymized) IP address used to login the user.
|
||||
* Return the (anonymized) IP address used to log in the user.
|
||||
*/
|
||||
public function getIPAddress(): string
|
||||
{
|
||||
|
@ -50,9 +50,9 @@ class UserLoginLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the IP address used to login the user.
|
||||
* Sets the IP address used to log in the user.
|
||||
*
|
||||
* @param string $ip the IP address used to login the user
|
||||
* @param string $ip the IP address used to log in the user
|
||||
* @param bool $anonymize Anonymize the IP address (remove last block) to be GPDR compliant
|
||||
*
|
||||
* @return $this
|
||||
|
|
|
@ -40,7 +40,7 @@ class UserLogoutLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the (anonymized) IP address used to login the user.
|
||||
* Return the (anonymized) IP address used to log in the user.
|
||||
*/
|
||||
public function getIPAddress(): string
|
||||
{
|
||||
|
@ -48,9 +48,9 @@ class UserLogoutLogEntry extends AbstractLogEntry
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the IP address used to login the user.
|
||||
* Sets the IP address used to log in the user.
|
||||
*
|
||||
* @param string $ip the IP address used to login the user
|
||||
* @param string $ip the IP address used to log in the user
|
||||
* @param bool $anonymize Anonymize the IP address (remove last block) to be GPDR compliant
|
||||
*
|
||||
* @return $this
|
||||
|
|
|
@ -139,11 +139,11 @@ abstract class AbstractParameter extends AbstractNamedDBElement
|
|||
protected string $group = '';
|
||||
|
||||
/**
|
||||
* Mapping is done in sub classes.
|
||||
* Mapping is done in subclasses.
|
||||
*
|
||||
* @var AbstractDBElement|null the element to which this parameter belongs to
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -42,6 +42,7 @@ declare(strict_types=1);
|
|||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Attachments\AttachmentType;
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
|
@ -57,5 +58,5 @@ class AttachmentTypeParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Attachments\AttachmentType", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Parts\Category;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -57,5 +58,5 @@ class CategoryParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Category", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,12 +41,13 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\PriceInformations\Currency;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a category element.
|
||||
* An attachment attached to a category element.
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ParameterRepository")
|
||||
* @UniqueEntity(fields={"name", "group", "element"})
|
||||
|
@ -60,5 +61,5 @@ class CurrencyParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\PriceInformations\Currency", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Parts\Footprint;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class FootprintParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Footprint", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\UserSystem\Group;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class GroupParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\UserSystem\Group", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Parts\Manufacturer;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class ManufacturerParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Manufacturer", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Parts\MeasurementUnit;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class MeasurementUnitParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\MeasurementUnit", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ trait ParametersTrait
|
|||
* @var Collection<int, AbstractParameter>
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
|
||||
/**
|
||||
* Return all associated specifications.
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Parts\Part;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class PartParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Part", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class ProjectParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\ProjectSystem\Project", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Parts\Storelocation;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class StorelocationParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Storelocation", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Parts\Supplier;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
@ -58,5 +59,5 @@ class SupplierParameter extends AbstractParameter
|
|||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Supplier", inversedBy="parameters")
|
||||
* @ORM\JoinColumn(name="element_id", referencedColumnName="id", nullable=false, onDelete="CASCADE").
|
||||
*/
|
||||
protected $element;
|
||||
protected ?AbstractDBElement $element = null;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace App\Entity\Parts;
|
|||
|
||||
use App\Entity\Attachments\CategoryAttachment;
|
||||
use App\Entity\Base\AbstractPartsContainingDBElement;
|
||||
use App\Entity\Base\AbstractStructuralDBElement;
|
||||
use App\Entity\Parameters\CategoryParameter;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
@ -46,13 +47,13 @@ class Category extends AbstractPartsContainingDBElement
|
|||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @var Collection
|
||||
*/
|
||||
protected $children;
|
||||
protected Collection $children;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
|
||||
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
|
||||
*/
|
||||
protected $parent;
|
||||
protected ?AbstractStructuralDBElement $parent = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -109,6 +110,7 @@ class Category extends AbstractPartsContainingDBElement
|
|||
* @Groups({"full", "import"})
|
||||
*/
|
||||
protected string $default_comment = '';
|
||||
|
||||
/**
|
||||
* @var Collection<int, CategoryAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\CategoryAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
|
@ -116,7 +118,7 @@ class Category extends AbstractPartsContainingDBElement
|
|||
* @Assert\Valid()
|
||||
* @Groups({"full"})
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
/** @var Collection<int, CategoryParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\CategoryParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
|
@ -124,7 +126,7 @@ class Category extends AbstractPartsContainingDBElement
|
|||
* @Assert\Valid()
|
||||
* @Groups({"full"})
|
||||
*/
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
|
||||
public function getPartnameHint(): string
|
||||
{
|
||||
|
|
|
@ -44,14 +44,14 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
* @ORM\ManyToOne(targetEntity="Footprint", inversedBy="children")
|
||||
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
|
||||
*/
|
||||
protected $parent;
|
||||
protected ?\App\Entity\Base\AbstractStructuralDBElement $parent;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Footprint", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @var Collection
|
||||
*/
|
||||
protected $children;
|
||||
protected Collection $children;
|
||||
|
||||
/**
|
||||
* @var Collection<int, FootprintAttachment>
|
||||
|
@ -59,7 +59,7 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
/**
|
||||
* @var FootprintAttachment|null
|
||||
|
@ -73,7 +73,7 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
|
||||
/****************************************
|
||||
* Getters
|
||||
|
|
|
@ -44,14 +44,14 @@ class Manufacturer extends AbstractCompany
|
|||
* @ORM\ManyToOne(targetEntity="Manufacturer", inversedBy="children")
|
||||
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
|
||||
*/
|
||||
protected $parent;
|
||||
protected ?\App\Entity\Base\AbstractStructuralDBElement $parent;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Manufacturer", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @var Collection
|
||||
*/
|
||||
protected $children;
|
||||
protected Collection $children;
|
||||
|
||||
/**
|
||||
* @var Collection<int, ManufacturerAttachment>
|
||||
|
@ -59,12 +59,12 @@ class Manufacturer extends AbstractCompany
|
|||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
/** @var Collection<int, ManufacturerParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\ManufacturerParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
}
|
||||
|
|
|
@ -75,13 +75,13 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @var Collection
|
||||
*/
|
||||
protected $children;
|
||||
protected Collection $children;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MeasurementUnit", inversedBy="children")
|
||||
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
|
||||
*/
|
||||
protected $parent;
|
||||
protected ?\App\Entity\Base\AbstractStructuralDBElement $parent;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MeasurementUnitAttachment>
|
||||
|
@ -89,14 +89,14 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
/** @var Collection<int, MeasurementUnitParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\MeasurementUnitParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
|
|
|
@ -26,7 +26,6 @@ use App\Entity\Attachments\Attachment;
|
|||
use App\Entity\Attachments\AttachmentContainingDBElement;
|
||||
use App\Entity\Attachments\PartAttachment;
|
||||
use App\Entity\Parts\PartTraits\ProjectTrait;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Entity\Parameters\ParametersTrait;
|
||||
use App\Entity\Parameters\PartParameter;
|
||||
use App\Entity\Parts\PartTraits\AdvancedPropertyTrait;
|
||||
|
@ -34,7 +33,6 @@ use App\Entity\Parts\PartTraits\BasicPropertyTrait;
|
|||
use App\Entity\Parts\PartTraits\InstockTrait;
|
||||
use App\Entity\Parts\PartTraits\ManufacturerTrait;
|
||||
use App\Entity\Parts\PartTraits\OrderTrait;
|
||||
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
||||
use DateTime;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
@ -48,7 +46,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||
* Part class.
|
||||
*
|
||||
* The class properties are split over various traits in directory PartTraits.
|
||||
* Otherwise this class would be too big, to be maintained.
|
||||
* Otherwise, this class would be too big, to be maintained.
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="App\Repository\PartRepository")
|
||||
* @ORM\Table("`parts`", indexes={
|
||||
|
@ -75,7 +73,7 @@ class Part extends AttachmentContainingDBElement
|
|||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Groups({"full"})
|
||||
*/
|
||||
protected $parameters;
|
||||
protected Collection $parameters;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime", name="datetime_added", options={"default":"CURRENT_TIMESTAMP"})
|
||||
|
@ -100,16 +98,16 @@ class Part extends AttachmentContainingDBElement
|
|||
* @Assert\Valid()
|
||||
* @Groups({"full"})
|
||||
*/
|
||||
protected $attachments;
|
||||
protected Collection $attachments;
|
||||
|
||||
/**
|
||||
* @var DateTime the date when this element was modified the last time
|
||||
* @var DateTime|null the date when this element was modified the last time
|
||||
* @ORM\Column(type="datetime", name="last_modified", options={"default":"CURRENT_TIMESTAMP"})
|
||||
*/
|
||||
protected ?DateTime $lastModified = null;
|
||||
|
||||
/**
|
||||
* @var Attachment
|
||||
* @var Attachment|null
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Attachments\Attachment")
|
||||
* @ORM\JoinColumn(name="id_preview_attachment", referencedColumnName="id", onDelete="SET NULL", nullable=true)
|
||||
* @Assert\Expression("value == null or value.isPicture()", message="part.master_attachment.must_be_picture")
|
||||
|
|
|
@ -130,7 +130,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
|
|||
|
||||
/**
|
||||
* Check if the current part lot is expired.
|
||||
* This is the case, if the expiration date is greater the the current date.
|
||||
* This is the case, if the expiration date is greater the current date.
|
||||
*
|
||||
* @return bool|null True, if the part lot is expired. Returns null, if no expiration date was set.
|
||||
*
|
||||
|
@ -195,7 +195,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the expiration date for the part lot. Set to null, if the part lot does not expires.
|
||||
* Sets the expiration date for the part lot. Set to null, if the part lot does not expire.
|
||||
*
|
||||
* @param DateTime|null $expiration_date
|
||||
*
|
||||
|
|
|
@ -55,7 +55,7 @@ trait AdvancedPropertyTrait
|
|||
protected ?float $mass = null;
|
||||
|
||||
/**
|
||||
* @var string The internal part number of the part
|
||||
* @var string|null The internal part number of the part
|
||||
* @ORM\Column(type="string", length=100, nullable=true, unique=true)
|
||||
* @Assert\Length(max="100")
|
||||
* @Groups({"extended", "full", "import"})
|
||||
|
|
|
@ -46,7 +46,7 @@ trait BasicPropertyTrait
|
|||
protected string $comment = '';
|
||||
|
||||
/**
|
||||
* @var bool Kept for compatibility (it is not used now, and I dont think it was used in old versions)
|
||||
* @var bool Kept for compatibility (it is not used now, and I don't think it was used in old versions)
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
protected bool $visible = true;
|
||||
|
@ -59,7 +59,7 @@ trait BasicPropertyTrait
|
|||
protected bool $favorite = false;
|
||||
|
||||
/**
|
||||
* @var Category The category this part belongs too (e.g. Resistors). Use tags, for more complex grouping.
|
||||
* @var Category|null The category this part belongs too (e.g. Resistors). Use tags, for more complex grouping.
|
||||
* Every part must have a category.
|
||||
* @ORM\ManyToOne(targetEntity="Category")
|
||||
* @ORM\JoinColumn(name="id_category", referencedColumnName="id", nullable=false)
|
||||
|
@ -136,7 +136,7 @@ trait BasicPropertyTrait
|
|||
/**
|
||||
* Gets the Footprint of this part (e.g. DIP8).
|
||||
*
|
||||
* @return Footprint|null The footprint of this part. Null if this part should no have a footprint.
|
||||
* @return Footprint|null The footprint of this part. Null if this part should not have a footprint.
|
||||
*/
|
||||
public function getFootprint(): ?Footprint
|
||||
{
|
||||
|
|
|
@ -122,7 +122,7 @@ trait InstockTrait
|
|||
|
||||
/**
|
||||
* Get the count of parts which must be in stock at least.
|
||||
* If a integer-based part unit is selected, the value will be rounded to integers.
|
||||
* If an integer-based part unit is selected, the value will be rounded to integers.
|
||||
*
|
||||
* @return float count of parts which must be in stock at least
|
||||
*/
|
||||
|
@ -160,9 +160,25 @@ trait InstockTrait
|
|||
return $this->getAmountSum() < $this->getMinAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if at least one of the part lots has an unknown amount.
|
||||
* It is possible that other part lots have a known amount, then getAmountSum() will return sum of all known amounts.
|
||||
* @return bool True if at least one part lot has an unknown amount.
|
||||
*/
|
||||
public function isAmountUnknown(): bool
|
||||
{
|
||||
foreach ($this->getPartLots() as $lot) {
|
||||
if ($lot->isInstockUnknown()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the summed amount of this part (over all part lots)
|
||||
* Part Lots that have unknown value or are expired, are not used for this value.
|
||||
* Part Lots that have unknown value or are expired, are not used for this value (counted as 0).
|
||||
*
|
||||
* @return float The amount of parts given in partUnit
|
||||
*/
|
||||
|
@ -171,7 +187,7 @@ trait InstockTrait
|
|||
//TODO: Find a method to do this natively in SQL, the current method could be a bit slow
|
||||
$sum = 0;
|
||||
foreach ($this->getPartLots() as $lot) {
|
||||
//Dont use the instock value, if it is unkown
|
||||
//Don't use the in stock value, if it is unknown
|
||||
if ($lot->isInstockUnknown() || $lot->isExpired() ?? false) {
|
||||
continue;
|
||||
}
|
||||
|
|
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