Fixed some PHPStan level 5 issues

This commit is contained in:
Jan Böhmer 2023-06-13 20:24:54 +02:00
parent 74051c5649
commit 19530a9102
35 changed files with 95 additions and 63 deletions

View file

@ -29,6 +29,7 @@ use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\Base\AbstractPartsContainingDBElement; use App\Entity\Base\AbstractPartsContainingDBElement;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Base\PartsContainingRepositoryInterface; use App\Entity\Base\PartsContainingRepositoryInterface;
use App\Entity\LabelSystem\LabelProcessMode;
use App\Entity\LabelSystem\LabelProfile; use App\Entity\LabelSystem\LabelProfile;
use App\Entity\Parameters\AbstractParameter; use App\Entity\Parameters\AbstractParameter;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
@ -159,7 +160,7 @@ abstract class BaseAdminController extends AbstractController
//Disable editing of options, if user is not allowed to use twig... //Disable editing of options, if user is not allowed to use twig...
if ( if (
$entity instanceof LabelProfile $entity instanceof LabelProfile
&& 'twig' === $entity->getOptions()->getProcessMode() && LabelProcessMode::TWIG === $entity->getOptions()->getProcessMode()
&& !$this->isGranted('@labels.use_twig') && !$this->isGranted('@labels.use_twig')
) { ) {
$form_options['disable_options'] = true; $form_options['disable_options'] = true;

View file

@ -43,6 +43,7 @@ namespace App\Controller;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\LabelSystem\LabelOptions; use App\Entity\LabelSystem\LabelOptions;
use App\Entity\LabelSystem\LabelProcessMode;
use App\Entity\LabelSystem\LabelProfile; use App\Entity\LabelSystem\LabelProfile;
use App\Entity\LabelSystem\LabelSupportedElement; use App\Entity\LabelSystem\LabelSupportedElement;
use App\Exceptions\TwigModeException; use App\Exceptions\TwigModeException;
@ -81,7 +82,7 @@ class LabelController extends AbstractController
$label_options = $profile instanceof LabelProfile ? $profile->getOptions() : new LabelOptions(); $label_options = $profile instanceof LabelProfile ? $profile->getOptions() : new LabelOptions();
//We have to disable the options, if twig mode is selected and user is not allowed to use it. //We have to disable the options, if twig mode is selected and user is not allowed to use it.
$disable_options = 'twig' === $label_options->getProcessMode() && !$this->isGranted('@labels.use_twig'); $disable_options = (LabelProcessMode::TWIG === $label_options->getProcessMode()) && !$this->isGranted('@labels.use_twig');
$form = $this->createForm(LabelDialogType::class, null, [ $form = $this->createForm(LabelDialogType::class, null, [
'disable_options' => $disable_options, 'disable_options' => $disable_options,

View file

@ -176,9 +176,9 @@ class ProjectController extends AbstractController
return $this->redirectToRoute('project_edit', ['id' => $project->getID()]); return $this->redirectToRoute('project_edit', ['id' => $project->getID()]);
} }
if (count ($errors) > 0) { //When we get here, there were validation errors
$this->addFlash('error', t('project.bom_import.flash.invalid_entries')); $this->addFlash('error', t('project.bom_import.flash.invalid_entries'));
}
} catch (\UnexpectedValueException|SyntaxError $e) { } catch (\UnexpectedValueException|SyntaxError $e) {
$this->addFlash('error', t('project.bom_import.flash.invalid_file', ['%message%' => $e->getMessage()])); $this->addFlash('error', t('project.bom_import.flash.invalid_file', ['%message%' => $e->getMessage()]));
} }

View file

@ -77,9 +77,14 @@ class WebauthnKeyRegistrationController extends AbstractController
return $this->redirectToRoute('webauthn_register'); return $this->redirectToRoute('webauthn_register');
} }
$user = $this->getUser();
if (!$user instanceof User) {
throw new RuntimeException('This controller only works only for Part-DB User objects!');
}
$keyEntity = WebauthnKey::fromRegistration($new_key); $keyEntity = WebauthnKey::fromRegistration($new_key);
$keyEntity->setName($keyName); $keyEntity->setName($keyName);
$keyEntity->setUser($this->getUser()); $keyEntity->setUser($user);
$em->persist($keyEntity); $em->persist($keyEntity);
$em->flush(); $em->flush();

View file

@ -96,6 +96,7 @@ class EntityConstraint extends AbstractConstraint
/** /**
* Checks whether the constraints apply to a structural type or not * Checks whether the constraints apply to a structural type or not
* @phpstan-assert-if-true AbstractStructuralDBElement $this->value
*/ */
public function isStructural(): bool public function isStructural(): bool
{ {

View file

@ -95,6 +95,8 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
} }
return $tmp; return $tmp;
} }
//@phpstan-ignore-next-line
throw new \Exception('This should never happen!'); throw new \Exception('This should never happen!');
}, },
]) ])

View file

@ -110,7 +110,7 @@ abstract class Attachment extends AbstractNamedDBElement
protected bool $show_in_table = false; protected bool $show_in_table = false;
#[Assert\NotNull(message: 'validator.attachment.must_not_be_null')] #[Assert\NotNull(message: 'validator.attachment.must_not_be_null')]
#[ORM\ManyToOne(targetEntity: 'AttachmentType', inversedBy: 'attachments_with_type')] #[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'attachments_with_type')]
#[ORM\JoinColumn(name: 'type_id', nullable: false)] #[ORM\JoinColumn(name: 'type_id', nullable: false)]
#[Selectable()] #[Selectable()]
protected ?AttachmentType $attachment_type = null; protected ?AttachmentType $attachment_type = null;

View file

@ -43,11 +43,11 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Index(name: 'attachment_types_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'attachment_types_idx_parent_name', columns: ['parent_id', 'name'])]
class AttachmentType extends AbstractStructuralDBElement class AttachmentType extends AbstractStructuralDBElement
{ {
#[ORM\OneToMany(targetEntity: 'AttachmentType', mappedBy: 'parent', cascade: ['persist'])] #[ORM\OneToMany(targetEntity: AttachmentType::class, mappedBy: 'parent', cascade: ['persist'])]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'AttachmentType', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
@ -76,7 +76,7 @@ class AttachmentType extends AbstractStructuralDBElement
/** /**
* @var Collection<Attachment> * @var Collection<Attachment>
*/ */
#[ORM\OneToMany(targetEntity: 'Attachment', mappedBy: 'attachment_type')] #[ORM\OneToMany(targetEntity: Attachment::class, mappedBy: 'attachment_type')]
protected Collection $attachments_with_type; protected Collection $attachments_with_type;
public function __construct() public function __construct()

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Base; namespace App\Entity\Base;
use App\Repository\NamedDBElementRepository;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\NamedElementInterface;
use App\Entity\Contracts\TimeStampableInterface; use App\Entity\Contracts\TimeStampableInterface;
@ -32,7 +33,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/** /**
* All subclasses of this class have an attribute "name". * All subclasses of this class have an attribute "name".
*/ */
#[ORM\MappedSuperclass(repositoryClass: 'App\Repository\NamedDBElement')] #[ORM\MappedSuperclass(repositoryClass: NamedDBElementRepository::class)]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]
abstract class AbstractNamedDBElement extends AbstractDBElement implements NamedElementInterface, TimeStampableInterface, \Stringable abstract class AbstractNamedDBElement extends AbstractDBElement implements NamedElementInterface, TimeStampableInterface, \Stringable
{ {

View file

@ -45,11 +45,11 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Index(name: 'category_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'category_idx_parent_name', columns: ['parent_id', 'name'])]
class Category extends AbstractPartsContainingDBElement class Category extends AbstractPartsContainingDBElement
{ {
#[ORM\OneToMany(targetEntity: 'Category', mappedBy: 'parent')] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'Category', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;

View file

@ -43,11 +43,11 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Index(name: 'footprint_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'footprint_idx_parent_name', columns: ['parent_id', 'name'])]
class Footprint extends AbstractPartsContainingDBElement class Footprint extends AbstractPartsContainingDBElement
{ {
#[ORM\ManyToOne(targetEntity: 'Footprint', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
#[ORM\OneToMany(targetEntity: 'Footprint', mappedBy: 'parent')] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;

View file

@ -43,11 +43,11 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Index(name: 'manufacturer_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'manufacturer_idx_parent_name', columns: ['parent_id', 'name'])]
class Manufacturer extends AbstractCompany class Manufacturer extends AbstractCompany
{ {
#[ORM\ManyToOne(targetEntity: 'Manufacturer', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
#[ORM\OneToMany(targetEntity: 'Manufacturer', mappedBy: 'parent')] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;

View file

@ -74,11 +74,11 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
#[ORM\Column(type: Types::BOOLEAN, name: 'use_si_prefix')] #[ORM\Column(type: Types::BOOLEAN, name: 'use_si_prefix')]
protected bool $use_si_prefix = false; protected bool $use_si_prefix = false;
#[ORM\OneToMany(targetEntity: 'MeasurementUnit', mappedBy: 'parent', cascade: ['persist'])] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent', cascade: ['persist'])]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'MeasurementUnit', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;

View file

@ -79,7 +79,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
* @var Storelocation|null The storelocation of this lot * @var Storelocation|null The storelocation of this lot
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: 'Storelocation')] #[ORM\ManyToOne(targetEntity: Storelocation::class)]
#[ORM\JoinColumn(name: 'id_store_location')] #[ORM\JoinColumn(name: 'id_store_location')]
#[Selectable()] #[Selectable()]
protected ?Storelocation $storage_location = null; protected ?Storelocation $storage_location = null;
@ -110,7 +110,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
* @var Part The part that is stored in this lot * @var Part The part that is stored in this lot
*/ */
#[Assert\NotNull] #[Assert\NotNull]
#[ORM\ManyToOne(targetEntity: 'Part', inversedBy: 'partLots')] #[ORM\ManyToOne(targetEntity: Part::class, inversedBy: 'partLots')]
#[ORM\JoinColumn(name: 'id_part', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'id_part', nullable: false, onDelete: 'CASCADE')]
protected Part $part; protected Part $part;

View file

@ -66,7 +66,7 @@ trait BasicPropertyTrait
#[Assert\NotNull(message: 'validator.select_valid_category')] #[Assert\NotNull(message: 'validator.select_valid_category')]
#[Selectable()] #[Selectable()]
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: 'Category')] #[ORM\ManyToOne(targetEntity: Category::class)]
#[ORM\JoinColumn(name: 'id_category', nullable: false)] #[ORM\JoinColumn(name: 'id_category', nullable: false)]
protected ?Category $category = null; protected ?Category $category = null;
@ -74,7 +74,7 @@ trait BasicPropertyTrait
* @var Footprint|null The footprint of this part (e.g. DIP8) * @var Footprint|null The footprint of this part (e.g. DIP8)
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: 'Footprint')] #[ORM\ManyToOne(targetEntity: Footprint::class)]
#[ORM\JoinColumn(name: 'id_footprint')] #[ORM\JoinColumn(name: 'id_footprint')]
#[Selectable()] #[Selectable()]
protected ?Footprint $footprint = null; protected ?Footprint $footprint = null;

View file

@ -40,7 +40,7 @@ trait InstockTrait
*/ */
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\OneToMany(targetEntity: 'PartLot', mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: PartLot::class, mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['amount' => 'DESC'])] #[ORM\OrderBy(['amount' => 'DESC'])]
protected Collection $partLots; protected Collection $partLots;
@ -57,7 +57,7 @@ trait InstockTrait
* @var ?MeasurementUnit the unit in which the part's amount is measured * @var ?MeasurementUnit the unit in which the part's amount is measured
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: 'MeasurementUnit')] #[ORM\ManyToOne(targetEntity: MeasurementUnit::class)]
#[ORM\JoinColumn(name: 'id_part_unit')] #[ORM\JoinColumn(name: 'id_part_unit')]
protected ?MeasurementUnit $partUnit = null; protected ?MeasurementUnit $partUnit = null;

View file

@ -39,7 +39,7 @@ trait ManufacturerTrait
* @var Manufacturer|null The manufacturer of this part * @var Manufacturer|null The manufacturer of this part
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: 'Manufacturer')] #[ORM\ManyToOne(targetEntity: Manufacturer::class)]
#[ORM\JoinColumn(name: 'id_manufacturer')] #[ORM\JoinColumn(name: 'id_manufacturer')]
#[Selectable()] #[Selectable()]
protected ?Manufacturer $manufacturer = null; protected ?Manufacturer $manufacturer = null;

View file

@ -98,7 +98,7 @@ trait OrderTrait
* *
* @param bool $hide_obsolete If true, obsolete orderdetails will NOT be returned * @param bool $hide_obsolete If true, obsolete orderdetails will NOT be returned
* *
* @return Collection|Orderdetail[] * all orderdetails as a one-dimensional array of Orderdetails objects * @return Collection<int, Orderdetail> * all orderdetails as a one-dimensional array of Orderdetails objects
* (empty array if there are no ones) * (empty array if there are no ones)
* * the array is sorted by the suppliers names / minimum order quantity * * the array is sorted by the suppliers names / minimum order quantity
*/ */

View file

@ -45,18 +45,18 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Index(name: 'location_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'location_idx_parent_name', columns: ['parent_id', 'name'])]
class Storelocation extends AbstractPartsContainingDBElement class Storelocation extends AbstractPartsContainingDBElement
{ {
#[ORM\OneToMany(targetEntity: 'Storelocation', mappedBy: 'parent')] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'Storelocation', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
/** /**
* @var MeasurementUnit|null The measurement unit, which parts can be stored in here * @var MeasurementUnit|null The measurement unit, which parts can be stored in here
*/ */
#[ORM\ManyToOne(targetEntity: 'MeasurementUnit')] #[ORM\ManyToOne(targetEntity: MeasurementUnit::class)]
#[ORM\JoinColumn(name: 'storage_type_id')] #[ORM\JoinColumn(name: 'storage_type_id')]
protected ?MeasurementUnit $storage_type = null; protected ?MeasurementUnit $storage_type = null;

View file

@ -49,11 +49,11 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Index(name: 'supplier_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'supplier_idx_parent_name', columns: ['parent_id', 'name'])]
class Supplier extends AbstractCompany class Supplier extends AbstractCompany
{ {
#[ORM\OneToMany(targetEntity: 'Supplier', mappedBy: 'parent')] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'Supplier', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;

View file

@ -66,11 +66,11 @@ class Currency extends AbstractStructuralDBElement
#[ORM\Column(type: Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $iso_code = ""; protected string $iso_code = "";
#[ORM\OneToMany(targetEntity: 'Currency', mappedBy: 'parent', cascade: ['persist'])] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent', cascade: ['persist'])]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'Currency', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;

View file

@ -52,7 +52,7 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\OneToMany(targetEntity: 'Pricedetail', mappedBy: 'orderdetail', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: Pricedetail::class, mappedBy: 'orderdetail', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['min_discount_quantity' => 'ASC'])] #[ORM\OrderBy(['min_discount_quantity' => 'ASC'])]
protected Collection $pricedetails; protected Collection $pricedetails;

View file

@ -64,7 +64,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
* If this is null, the global base unit is assumed * If this is null, the global base unit is assumed
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: 'Currency', inversedBy: 'pricedetails')] #[ORM\ManyToOne(targetEntity: Currency::class, inversedBy: 'pricedetails')]
#[ORM\JoinColumn(name: 'id_currency')] #[ORM\JoinColumn(name: 'id_currency')]
#[Selectable()] #[Selectable()]
protected ?Currency $currency = null; protected ?Currency $currency = null;
@ -95,7 +95,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
* @var Orderdetail|null * @var Orderdetail|null
*/ */
#[Assert\NotNull] #[Assert\NotNull]
#[ORM\ManyToOne(targetEntity: 'Orderdetail', inversedBy: 'pricedetails')] #[ORM\ManyToOne(targetEntity: Orderdetail::class, inversedBy: 'pricedetails')]
#[ORM\JoinColumn(name: 'orderdetails_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'orderdetails_id', nullable: false, onDelete: 'CASCADE')]
protected ?Orderdetail $orderdetail = null; protected ?Orderdetail $orderdetail = null;

View file

@ -45,17 +45,17 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Table(name: 'projects')] #[ORM\Table(name: 'projects')]
class Project extends AbstractStructuralDBElement class Project extends AbstractStructuralDBElement
{ {
#[ORM\OneToMany(targetEntity: 'Project', mappedBy: 'parent')] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'Project', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full'])] #[Groups(['extended', 'full'])]
#[ORM\OneToMany(targetEntity: 'ProjectBOMEntry', mappedBy: 'project', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: ProjectBOMEntry::class, mappedBy: 'project', cascade: ['persist', 'remove'], orphanRemoval: true)]
protected Collection $bom_entries; protected Collection $bom_entries;
#[ORM\Column(type: Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]

View file

@ -76,7 +76,7 @@ class ProjectBOMEntry extends AbstractDBElement
/** /**
* @var Project|null * @var Project|null
*/ */
#[ORM\ManyToOne(targetEntity: 'Project', inversedBy: 'bom_entries')] #[ORM\ManyToOne(targetEntity: Project::class, inversedBy: 'bom_entries')]
#[ORM\JoinColumn(name: 'id_device')] #[ORM\JoinColumn(name: 'id_device')]
protected ?Project $project = null; protected ?Project $project = null;

View file

@ -47,18 +47,18 @@ use Symfony\Component\Validator\Constraints as Assert;
#[NoLockout()] #[NoLockout()]
class Group extends AbstractStructuralDBElement implements HasPermissionsInterface class Group extends AbstractStructuralDBElement implements HasPermissionsInterface
{ {
#[ORM\OneToMany(targetEntity: 'Group', mappedBy: 'parent')] #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: 'Group', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
/** /**
* @var Collection<int, User> * @var Collection<int, User>
*/ */
#[ORM\OneToMany(targetEntity: 'User', mappedBy: 'group')] #[ORM\OneToMany(targetEntity: User::class, mappedBy: 'group')]
protected Collection $users; protected Collection $users;
/** /**
@ -77,7 +77,7 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
protected Collection $attachments; protected Collection $attachments;
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Embedded(class: 'PermissionData', columnPrefix: 'permissions_')] #[ORM\Embedded(class: PermissionData::class, columnPrefix: 'permissions_')]
#[ValidPermission()] #[ValidPermission()]
protected ?PermissionData $permissions = null; protected ?PermissionData $permissions = null;

View file

@ -133,7 +133,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
* DO NOT PUT A fetch eager here! Otherwise, you can not unset the group of a user! This seems to be some kind of bug in doctrine. Maybe this is fixed in future versions. * DO NOT PUT A fetch eager here! Otherwise, you can not unset the group of a user! This seems to be some kind of bug in doctrine. Maybe this is fixed in future versions.
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: 'Group', inversedBy: 'users')] #[ORM\ManyToOne(targetEntity: Group::class, inversedBy: 'users')]
#[ORM\JoinColumn(name: 'group_id')] #[ORM\JoinColumn(name: 'group_id')]
#[Selectable] #[Selectable]
protected ?Group $group = null; protected ?Group $group = null;

View file

@ -58,6 +58,11 @@ class UpgradePermissionsSchemaSubscriber implements EventSubscriberInterface
$session = $event->getRequest()->getSession(); $session = $event->getRequest()->getSession();
$flashBag = $session->getFlashBag(); $flashBag = $session->getFlashBag();
//Check if the user is an instance of User, otherwise we can't upgrade the schema
if (!$user instanceof User) {
return;
}
if ($this->permissionSchemaUpdater->isSchemaUpdateNeeded($user)) { if ($this->permissionSchemaUpdater->isSchemaUpdateNeeded($user)) {
$this->eventCommentHelper->setMessage('Automatic permission schema update'); $this->eventCommentHelper->setMessage('Automatic permission schema update');
$this->permissionSchemaUpdater->userUpgradeSchemaRecursively($user); $this->permissionSchemaUpdater->userUpgradeSchemaRecursively($user);

View file

@ -53,12 +53,12 @@ class LogEntryRepository extends DBElementRepository
* *
* @param AbstractDBElement $element The element for which the history should be generated * @param AbstractDBElement $element The element for which the history should be generated
* @param string $order By default, the newest entries are shown first. Change this to ASC to show the oldest entries first. * @param string $order By default, the newest entries are shown first. Change this to ASC to show the oldest entries first.
* @param null $limit * @param int|null $limit
* @param null $offset * @param int|null $offset
* *
* @return AbstractLogEntry[] * @return AbstractLogEntry[]
*/ */
public function getElementHistory(AbstractDBElement $element, string $order = 'DESC', $limit = null, $offset = null): array public function getElementHistory(AbstractDBElement $element, string $order = 'DESC', ?int $limit = null, ?int $offset = null): array
{ {
return $this->findBy(['element' => $element], ['timestamp' => $order], $limit, $offset); return $this->findBy(['element' => $element], ['timestamp' => $order], $limit, $offset);
} }
@ -100,11 +100,11 @@ class LogEntryRepository extends DBElementRepository
* Gets all log entries that are related to time travelling. * Gets all log entries that are related to time travelling.
* *
* @param AbstractDBElement $element The element for which the time travel data should be retrieved * @param AbstractDBElement $element The element for which the time travel data should be retrieved
* @param DateTime $until Back to which timestamp should the data be got (including the timestamp) * @param \DateTimeInterface $until Back to which timestamp should the data be got (including the timestamp)
* *
* @return AbstractLogEntry[] * @return AbstractLogEntry[]
*/ */
public function getTimetravelDataForElement(AbstractDBElement $element, DateTime $until): array public function getTimetravelDataForElement(AbstractDBElement $element, \DateTimeInterface $until): array
{ {
$qb = $this->createQueryBuilder('log'); $qb = $this->createQueryBuilder('log');
$qb->select('log') $qb->select('log')
@ -132,7 +132,7 @@ class LogEntryRepository extends DBElementRepository
* *
* @return bool True if the element existed at the given timestamp * @return bool True if the element existed at the given timestamp
*/ */
public function getElementExistedAtTimestamp(AbstractDBElement $element, DateTime $timestamp): bool public function getElementExistedAtTimestamp(AbstractDBElement $element, \DateTimeInterface $timestamp): bool
{ {
$qb = $this->createQueryBuilder('log'); $qb = $this->createQueryBuilder('log');
$qb->select('count(log)') $qb->select('count(log)')
@ -157,8 +157,8 @@ class LogEntryRepository extends DBElementRepository
/** /**
* Gets the last log entries ordered by timestamp. * Gets the last log entries ordered by timestamp.
* *
* @param null $limit * @param int|null $limit
* @param null $offset * @param int|null $offset
*/ */
public function getLogsOrderedByTimestamp(string $order = 'DESC', $limit = null, $offset = null): array public function getLogsOrderedByTimestamp(string $order = 'DESC', $limit = null, $offset = null): array
{ {

View file

@ -26,6 +26,7 @@ use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentType;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\NamedElementInterface;
use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\Project;
use App\Entity\LabelSystem\LabelProfile; use App\Entity\LabelSystem\LabelProfile;
@ -180,7 +181,7 @@ class ElementTypeNameGenerator
$on = $entity->getProject(); $on = $entity->getProject();
} }
if (isset($on) && is_object($on)) { if (isset($on) && $on instanceof NamedElementInterface) {
try { try {
$tmp .= sprintf( $tmp .= sprintf(
' (<a href="%s">%s</a>)', ' (<a href="%s">%s</a>)',

View file

@ -132,6 +132,14 @@ final class LabelExampleElementsGenerator
return $user; return $user;
} }
/**
* @template T of AbstractStructuralDBElement
* @param string $class
* @phpstan-param class-string<T> $class
* @return AbstractStructuralDBElement
* @phpstan-return T
* @throws \ReflectionException
*/
private function getStructuralData(string $class): AbstractStructuralDBElement private function getStructuralData(string $class): AbstractStructuralDBElement
{ {
if (!is_a($class, AbstractStructuralDBElement::class, true)) { if (!is_a($class, AbstractStructuralDBElement::class, true)) {

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
*/ */
namespace App\Services\LabelSystem\PlaceholderProviders; namespace App\Services\LabelSystem\PlaceholderProviders;
use App\Entity\LabelSystem\BarcodeType;
use App\Entity\LabelSystem\LabelOptions; use App\Entity\LabelSystem\LabelOptions;
use App\Services\LabelSystem\BarcodeGenerator; use App\Services\LabelSystem\BarcodeGenerator;
use App\Services\LabelSystem\Barcodes\BarcodeContentGenerator; use App\Services\LabelSystem\Barcodes\BarcodeContentGenerator;
@ -52,19 +53,19 @@ final class BarcodeProvider implements PlaceholderProviderInterface
if ('[[BARCODE_QR]]' === $placeholder) { if ('[[BARCODE_QR]]' === $placeholder) {
$label_options = new LabelOptions(); $label_options = new LabelOptions();
$label_options->setBarcodeType('qr'); $label_options->setBarcodeType(BarcodeType::QR);
return $this->barcodeGenerator->generateHTMLBarcode($label_options, $label_target); return $this->barcodeGenerator->generateHTMLBarcode($label_options, $label_target);
} }
if ('[[BARCODE_C39]]' === $placeholder) { if ('[[BARCODE_C39]]' === $placeholder) {
$label_options = new LabelOptions(); $label_options = new LabelOptions();
$label_options->setBarcodeType('code39'); $label_options->setBarcodeType(BarcodeType::CODE39);
return $this->barcodeGenerator->generateHTMLBarcode($label_options, $label_target); return $this->barcodeGenerator->generateHTMLBarcode($label_options, $label_target);
} }
if ('[[BARCODE_C128]]' === $placeholder) { if ('[[BARCODE_C128]]' === $placeholder) {
$label_options = new LabelOptions(); $label_options = new LabelOptions();
$label_options->setBarcodeType('code128'); $label_options->setBarcodeType(BarcodeType::CODE128);
return $this->barcodeGenerator->generateHTMLBarcode($label_options, $label_target); return $this->barcodeGenerator->generateHTMLBarcode($label_options, $label_target);
} }

View file

@ -79,7 +79,7 @@ class TimeTravel
* *
* @throws Exception * @throws Exception
*/ */
public function revertEntityToTimestamp(AbstractDBElement $element, DateTime $timestamp, array $reverted_elements = []): void public function revertEntityToTimestamp(AbstractDBElement $element, \DateTimeInterface $timestamp, array $reverted_elements = []): void
{ {
if (!$element instanceof TimeStampableInterface) { if (!$element instanceof TimeStampableInterface) {
throw new InvalidArgumentException('$element must have a Timestamp!'); throw new InvalidArgumentException('$element must have a Timestamp!');
@ -228,7 +228,7 @@ class TimeTravel
$this->setField($element, 'lastModified', $logEntry->getTimestamp()); $this->setField($element, 'lastModified', $logEntry->getTimestamp());
} }
protected function getField(AbstractDBElement $element, string $field) protected function getField(AbstractDBElement $element, string $field): mixed
{ {
$reflection = new ReflectionClass($element::class); $reflection = new ReflectionClass($element::class);
$property = $reflection->getProperty($field); $property = $reflection->getProperty($field);
@ -237,7 +237,7 @@ class TimeTravel
return $property->getValue($element); return $property->getValue($element);
} }
protected function setField(AbstractDBElement $element, string $field, \DateTime|int|null $new_value): void protected function setField(AbstractDBElement $element, string $field, mixed $new_value): void
{ {
$reflection = new ReflectionClass($element::class); $reflection = new ReflectionClass($element::class);
$property = $reflection->getProperty($field); $property = $reflection->getProperty($field);

View file

@ -112,7 +112,7 @@ class PermissionManager
/** @var Group $parent */ /** @var Group $parent */
$parent = $user->getGroup(); $parent = $user->getGroup();
while ($parent instanceof AbstractStructuralDBElement) { //The top group, has parent == null while ($parent instanceof Group) { //The top group, has parent == null
//Check if our current element gives an info about disallow/allow //Check if our current element gives an info about disallow/allow
$allowed = $this->dontInherit($parent, $permission, $operation); $allowed = $this->dontInherit($parent, $permission, $operation);
if (null !== $allowed) { if (null !== $allowed) {

View file

@ -172,12 +172,18 @@ class PermissionPresetsHelper
return $perm_holder; return $perm_holder;
} }
/**
* @phpstan-api
*/
private function AllForbid(HasPermissionsInterface $perm_holder): HasPermissionsInterface private function AllForbid(HasPermissionsInterface $perm_holder): HasPermissionsInterface
{ {
$this->permissionResolver->setAllPermissions($perm_holder, PermissionData::DISALLOW); $this->permissionResolver->setAllPermissions($perm_holder, PermissionData::DISALLOW);
return $perm_holder; return $perm_holder;
} }
/**
* @phpstan-api
*/
private function AllAllow(HasPermissionsInterface $perm_holder): HasPermissionsInterface private function AllAllow(HasPermissionsInterface $perm_holder): HasPermissionsInterface
{ {
$this->permissionResolver->setAllPermissions($perm_holder, PermissionData::ALLOW); $this->permissionResolver->setAllPermissions($perm_holder, PermissionData::ALLOW);