diff --git a/src/Command/CheckRequirementsCommand.php b/src/Command/CheckRequirementsCommand.php index cc557bd1..068147e2 100644 --- a/src/Command/CheckRequirementsCommand.php +++ b/src/Command/CheckRequirementsCommand.php @@ -63,7 +63,7 @@ class CheckRequirementsCommand extends Command } - protected function checkPHP(SymfonyStyle $io, $only_issues = false): void + protected function checkPHP(SymfonyStyle $io, bool $only_issues = false): void { //Check PHP versions if ($io->isVerbose()) { @@ -98,7 +98,7 @@ class CheckRequirementsCommand extends Command } } - protected function checkPartDBConfig(SymfonyStyle $io, $only_issues = false): void + protected function checkPartDBConfig(SymfonyStyle $io, bool $only_issues = false): void { //Check if APP_ENV is set to prod if ($io->isVerbose()) { @@ -112,7 +112,7 @@ class CheckRequirementsCommand extends Command } - protected function checkPHPExtensions(SymfonyStyle $io, $only_issues = false): void + protected function checkPHPExtensions(SymfonyStyle $io, bool $only_issues = false): void { //Get all installed PHP extensions $extensions = get_loaded_extensions(); diff --git a/src/Controller/AdminPages/BaseAdminController.php b/src/Controller/AdminPages/BaseAdminController.php index a00dc1a6..9f43d07d 100644 --- a/src/Controller/AdminPages/BaseAdminController.php +++ b/src/Controller/AdminPages/BaseAdminController.php @@ -244,7 +244,7 @@ abstract class BaseAdminController extends AbstractController return true; } - protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AbstractNamedDBElement $entity = null) + protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AbstractNamedDBElement $entity = null): Response { $new_entity = $entity instanceof AbstractNamedDBElement ? clone $entity : new $this->entity_class(); diff --git a/src/Controller/HomepageController.php b/src/Controller/HomepageController.php index 45b80113..212363ff 100644 --- a/src/Controller/HomepageController.php +++ b/src/Controller/HomepageController.php @@ -44,11 +44,18 @@ class HomepageController extends AbstractController public function getBanner(): string { $banner = $this->getParameter('partdb.banner'); + if (!is_string($banner)) { + throw new \RuntimeException('The parameter "partdb.banner" must be a string.'); + } if (empty($banner)) { $banner_path = $this->kernel->getProjectDir() .DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'banner.md'; - return file_get_contents($banner_path); + $tmp = file_get_contents($banner_path); + if (false === $tmp) { + throw new \RuntimeException('The banner file could not be read.'); + } + $banner = $tmp; } return $banner; diff --git a/src/Controller/UserSettingsController.php b/src/Controller/UserSettingsController.php index 3805ad09..76df8994 100644 --- a/src/Controller/UserSettingsController.php +++ b/src/Controller/UserSettingsController.php @@ -66,7 +66,7 @@ class UserSettingsController extends AbstractController } #[Route(path: '/2fa_backup_codes', name: 'show_backup_codes')] - public function showBackupCodes() + public function showBackupCodes(): Response { $user = $this->getUser(); @@ -74,7 +74,7 @@ class UserSettingsController extends AbstractController $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); if (!$user instanceof User) { - return new RuntimeException('This controller only works only for Part-DB User objects!'); + throw new RuntimeException('This controller only works only for Part-DB User objects!'); } if ($user->isSamlUser()) { diff --git a/src/Controller/WebauthnKeyRegistrationController.php b/src/Controller/WebauthnKeyRegistrationController.php index 5f2e3e9b..9329a3b9 100644 --- a/src/Controller/WebauthnKeyRegistrationController.php +++ b/src/Controller/WebauthnKeyRegistrationController.php @@ -29,6 +29,7 @@ use Jbtronics\TFAWebauthn\Services\TFAWebauthnRegistrationHelper; use RuntimeException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use function Symfony\Component\Translation\t; @@ -40,7 +41,7 @@ class WebauthnKeyRegistrationController extends AbstractController } #[Route(path: '/webauthn/register', name: 'webauthn_register')] - public function register(Request $request, TFAWebauthnRegistrationHelper $registrationHelper, EntityManagerInterface $em) + public function register(Request $request, TFAWebauthnRegistrationHelper $registrationHelper, EntityManagerInterface $em): Response { //When user change its settings, he should be logged in fully. $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); diff --git a/src/DataTables/ErrorDataTable.php b/src/DataTables/ErrorDataTable.php index 3aaf11d1..ea3c1e76 100644 --- a/src/DataTables/ErrorDataTable.php +++ b/src/DataTables/ErrorDataTable.php @@ -48,7 +48,7 @@ class ErrorDataTable implements DataTableTypeInterface }); } - public function configure(DataTable $dataTable, array $options) + public function configure(DataTable $dataTable, array $options): void { $optionsResolver = new OptionsResolver(); $this->configureOptions($optionsResolver); @@ -74,7 +74,10 @@ class ErrorDataTable implements DataTableTypeInterface $dataTable->createAdapter(ArrayAdapter::class, $data); } - public static function errorTable(DataTableFactory $dataTableFactory, Request $request, $errors): Response + /** + * @param string[]|string $errors + */ + public static function errorTable(DataTableFactory $dataTableFactory, Request $request, array|string $errors): Response { $error_table = $dataTableFactory->createFromType(self::class, ['errors' => $errors]); $error_table->handleRequest($request); diff --git a/src/DataTables/Filters/Constraints/NumberConstraint.php b/src/DataTables/Filters/Constraints/NumberConstraint.php index cad1c6a8..9e53b8f3 100644 --- a/src/DataTables/Filters/Constraints/NumberConstraint.php +++ b/src/DataTables/Filters/Constraints/NumberConstraint.php @@ -49,7 +49,7 @@ class NumberConstraint extends AbstractConstraint $this->value2 = $value2; } - public function getOperator(): string + public function getOperator(): string|null { return $this->operator; } diff --git a/src/DataTables/ProjectBomEntriesDataTable.php b/src/DataTables/ProjectBomEntriesDataTable.php index dec3ea1e..4586d2f7 100644 --- a/src/DataTables/ProjectBomEntriesDataTable.php +++ b/src/DataTables/ProjectBomEntriesDataTable.php @@ -47,7 +47,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface } - public function configure(DataTable $dataTable, array $options) + public function configure(DataTable $dataTable, array $options): void { $dataTable //->add('select', SelectColumn::class) diff --git a/src/Doctrine/Types/UTCDateTimeType.php b/src/Doctrine/Types/UTCDateTimeType.php index 462d4ae4..c7140252 100644 --- a/src/Doctrine/Types/UTCDateTimeType.php +++ b/src/Doctrine/Types/UTCDateTimeType.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace App\Doctrine\Types; use DateTime; +use DateTimeInterface; use DateTimeZone; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\ConversionException; @@ -58,7 +59,16 @@ class UTCDateTimeType extends DateTimeType return parent::convertToDatabaseValue($value, $platform); } - public function convertToPHPValue($value, AbstractPlatform $platform): ?DateTime + /** + * {@inheritDoc} + * + * @param T $value + * + * @return (T is null ? null : DateTimeInterface) + * + * @template T + */ + public function convertToPHPValue($value, AbstractPlatform $platform): ?\DateTimeInterface { if (!self::$utc_timezone instanceof \DateTimeZone) { self::$utc_timezone = new DateTimeZone('UTC'); diff --git a/src/Entity/Attachments/AttachmentContainingDBElement.php b/src/Entity/Attachments/AttachmentContainingDBElement.php index e72276d8..b3b71a85 100644 --- a/src/Entity/Attachments/AttachmentContainingDBElement.php +++ b/src/Entity/Attachments/AttachmentContainingDBElement.php @@ -78,9 +78,9 @@ abstract class AttachmentContainingDBElement extends AbstractNamedDBElement impl *********************************************************************************/ /** - * Gets all attachments associated with this element. + * Gets all attachments associated with this element. * - * @return Collection + * @phpstan-return Collection */ public function getAttachments(): Collection { diff --git a/src/Entity/Attachments/AttachmentType.php b/src/Entity/Attachments/AttachmentType.php index 6314fe7c..c99ac392 100644 --- a/src/Entity/Attachments/AttachmentType.php +++ b/src/Entity/Attachments/AttachmentType.php @@ -91,8 +91,9 @@ class AttachmentType extends AbstractStructuralDBElement /** * Get all attachments ("Attachment" objects) with this type. * - * @return Collection|Attachment[] all attachments with this type, as a one-dimensional array of Attachments + * @return Collection all attachments with this type, as a one-dimensional array of Attachments * (sorted by their names) + * @phpstan-return Collection */ public function getAttachmentsForType(): Collection { diff --git a/src/Entity/LogSystem/AbstractLogEntry.php b/src/Entity/LogSystem/AbstractLogEntry.php index f6176e4f..9329a33d 100644 --- a/src/Entity/LogSystem/AbstractLogEntry.php +++ b/src/Entity/LogSystem/AbstractLogEntry.php @@ -247,9 +247,9 @@ abstract class AbstractLogEntry extends AbstractDBElement } /** - * Returns the timestamp when the event that caused this log entry happened. + * Returns the timestamp when the event that caused this log entry happened. */ - public function getTimestamp(): \DateTimeInterface + public function getTimestamp(): \DateTimeInterface|null { return $this->timestamp; } diff --git a/src/Entity/Parts/Part.php b/src/Entity/Parts/Part.php index 63f4dce4..9279ec11 100644 --- a/src/Entity/Parts/Part.php +++ b/src/Entity/Parts/Part.php @@ -144,7 +144,7 @@ class Part extends AttachmentContainingDBElement } #[Assert\Callback] - public function validate(ExecutionContextInterface $context, $payload) + public function validate(ExecutionContextInterface $context, $payload): void { //Ensure that the part name fullfills the regex of the category if ($this->category instanceof Category) { diff --git a/src/Entity/Parts/PartLot.php b/src/Entity/Parts/PartLot.php index f52f8984..c54511f6 100644 --- a/src/Entity/Parts/PartLot.php +++ b/src/Entity/Parts/PartLot.php @@ -322,7 +322,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named } #[Assert\Callback] - public function validate(ExecutionContextInterface $context, $payload) + public function validate(ExecutionContextInterface $context, $payload): void { //Ensure that the owner is not the anonymous user if ($this->getOwner() && $this->getOwner()->isAnonymousUser()) { diff --git a/src/Entity/Parts/PartTraits/InstockTrait.php b/src/Entity/Parts/PartTraits/InstockTrait.php index 18295720..068173a7 100644 --- a/src/Entity/Parts/PartTraits/InstockTrait.php +++ b/src/Entity/Parts/PartTraits/InstockTrait.php @@ -63,8 +63,7 @@ trait InstockTrait /** * Get all part lots where this part is stored. - * - * @return PartLot[]|Collection + * @phpstan-return Collection */ public function getPartLots(): Collection { diff --git a/src/Entity/Parts/PartTraits/OrderTrait.php b/src/Entity/Parts/PartTraits/OrderTrait.php index 2e0ec0b2..a442298c 100644 --- a/src/Entity/Parts/PartTraits/OrderTrait.php +++ b/src/Entity/Parts/PartTraits/OrderTrait.php @@ -36,7 +36,7 @@ use Doctrine\ORM\Mapping as ORM; trait OrderTrait { /** - * @var Orderdetail[]|Collection the details about how and where you can order this part + * @var Collection the details about how and where you can order this part */ #[Assert\Valid] #[Groups(['extended', 'full', 'import'])] @@ -66,7 +66,7 @@ trait OrderTrait /** * Get the selected order orderdetails of this part. * - * @return Orderdetail the selected order orderdetails + * @return Orderdetail|null the selected order orderdetails */ public function getOrderOrderdetails(): ?Orderdetail { diff --git a/src/Entity/Parts/PartTraits/ProjectTrait.php b/src/Entity/Parts/PartTraits/ProjectTrait.php index 6fd076bf..51208b6a 100644 --- a/src/Entity/Parts/PartTraits/ProjectTrait.php +++ b/src/Entity/Parts/PartTraits/ProjectTrait.php @@ -29,8 +29,9 @@ trait ProjectTrait protected ?Project $built_project = null; /** - * Returns all ProjectBOMEntries that use this part. - * @return Collection|ProjectBOMEntry[] + * Returns all ProjectBOMEntries that use this part. + * + * @phpstan-return Collection */ public function getProjectBomEntries(): Collection { diff --git a/src/Entity/PriceInformations/Orderdetail.php b/src/Entity/PriceInformations/Orderdetail.php index 40d512a5..ec5e9ce5 100644 --- a/src/Entity/PriceInformations/Orderdetail.php +++ b/src/Entity/PriceInformations/Orderdetail.php @@ -205,8 +205,7 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N /** * Get all pricedetails. * - * @return Pricedetail[]|Collection all pricedetails as a one-dimensional array of Pricedetails objects, - * sorted by minimum discount quantity + * @return Collection */ public function getPricedetails(): Collection { diff --git a/src/Entity/ProjectSystem/Project.php b/src/Entity/ProjectSystem/Project.php index 0b07ef22..352d42c4 100644 --- a/src/Entity/ProjectSystem/Project.php +++ b/src/Entity/ProjectSystem/Project.php @@ -183,9 +183,6 @@ class Project extends AbstractStructuralDBElement return $this; } - /** - * @return Collection|ProjectBOMEntry[] - */ public function getBomEntries(): Collection { return $this->bom_entries; @@ -265,7 +262,7 @@ class Project extends AbstractStructuralDBElement } #[Assert\Callback] - public function validate(ExecutionContextInterface $context, $payload) + public function validate(ExecutionContextInterface $context, $payload): void { //If this project has subprojects, and these have builds part, they must be included in the BOM foreach ($this->getChildren() as $child) { diff --git a/src/Entity/UserSystem/U2FKey.php b/src/Entity/UserSystem/U2FKey.php index b74cd8db..f6a2a2e4 100644 --- a/src/Entity/UserSystem/U2FKey.php +++ b/src/Entity/UserSystem/U2FKey.php @@ -139,9 +139,9 @@ class U2FKey implements LegacyU2FKeyInterface } /** - * Gets the user, this U2F key belongs to. + * Gets the user, this U2F key belongs to. */ - public function getUser(): User + public function getUser(): User|null { return $this->user; } diff --git a/src/Entity/UserSystem/User.php b/src/Entity/UserSystem/User.php index aecff6a6..0ec54be3 100644 --- a/src/Entity/UserSystem/User.php +++ b/src/Entity/UserSystem/User.php @@ -468,9 +468,9 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe } /** - * Gets the datetime when the password reset token expires. + * Gets the datetime when the password reset token expires. */ - public function getPwResetExpires(): \DateTimeInterface + public function getPwResetExpires(): \DateTimeInterface|null { return $this->pw_reset_expires; } diff --git a/src/Form/CollectionTypeExtension.php b/src/Form/CollectionTypeExtension.php index 38266315..4fa93852 100644 --- a/src/Form/CollectionTypeExtension.php +++ b/src/Form/CollectionTypeExtension.php @@ -162,9 +162,11 @@ class CollectionTypeExtension extends AbstractTypeExtension /** * Set the option of the form. * This a bit hacky because we access private properties.... - * + * @param FormConfigInterface $builder The form on which the option should be set + * @param string $option The option which should be changed + * @param mixed $value The new value */ - public function setOption(FormConfigInterface $builder, string $option, $value): void + public function setOption(FormConfigInterface $builder, string $option, mixed $value): void { if (!$builder instanceof FormConfigBuilder) { throw new \RuntimeException('This method only works with FormConfigBuilder instances.'); @@ -173,10 +175,8 @@ class CollectionTypeExtension extends AbstractTypeExtension //We have to use FormConfigBuilder::class here, because options is private and not available in subclasses $reflection = new ReflectionClass(FormConfigBuilder::class); $property = $reflection->getProperty('options'); - $property->setAccessible(true); $tmp = $property->getValue($builder); $tmp[$option] = $value; $property->setValue($builder, $tmp); - $property->setAccessible(false); } } diff --git a/src/Form/Permissions/PermissionsMapper.php b/src/Form/Permissions/PermissionsMapper.php index 07c47bdd..2163b26f 100644 --- a/src/Form/Permissions/PermissionsMapper.php +++ b/src/Form/Permissions/PermissionsMapper.php @@ -39,13 +39,13 @@ final class PermissionsMapper implements DataMapperInterface } /** - * Maps the view data of a compound form to its children. + * Maps the view data of a compound form to its children. * - * The method is responsible for calling {@link FormInterface::setData()} - * on the children of compound forms, defining their underlying model data. + * The method is responsible for calling {@link FormInterface::setData()} + * on the children of compound forms, defining their underlying model data. * * @param mixed $viewData View data of the compound form being initialized - * @param FormInterface[]|Traversable $forms A list of {@link FormInterface} instances + * @param Traversable $forms A list of {@link FormInterface} instances */ public function mapDataToForms($viewData, \Traversable $forms): void { @@ -68,29 +68,29 @@ final class PermissionsMapper implements DataMapperInterface } /** - * Maps the model data of a list of children forms into the view data of their parent. + * Maps the model data of a list of children forms into the view data of their parent. * - * This is the internal cascade call of FormInterface::submit for compound forms, since they - * cannot be bound to any input nor the request as scalar, but their children may: + * This is the internal cascade call of FormInterface::submit for compound forms, since they + * cannot be bound to any input nor the request as scalar, but their children may: * - * $compoundForm->submit($arrayOfChildrenViewData) - * // inside: - * $childForm->submit($childViewData); - * // for each entry, do the same and/or reverse transform - * $this->dataMapper->mapFormsToData($compoundForm, $compoundInitialViewData) - * // then reverse transform + * $compoundForm->submit($arrayOfChildrenViewData) + * // inside: + * $childForm->submit($childViewData); + * // for each entry, do the same and/or reverse transform + * $this->dataMapper->mapFormsToData($compoundForm, $compoundInitialViewData) + * // then reverse transform * - * When a simple form is submitted the following is happening: + * When a simple form is submitted the following is happening: * - * $simpleForm->submit($submittedViewData) - * // inside: - * $this->viewData = $submittedViewData - * // then reverse transform + * $simpleForm->submit($submittedViewData) + * // inside: + * $this->viewData = $submittedViewData + * // then reverse transform * - * The model data can be an array or an object, so this second argument is always passed - * by reference. + * The model data can be an array or an object, so this second argument is always passed + * by reference. * - * @param FormInterface[]|Traversable $forms A list of {@link FormInterface} instances + * @param Traversable $forms A list of {@link FormInterface} instances * @param mixed $viewData The compound form's view data that get mapped * its children model data */ diff --git a/src/Form/Type/SIUnitType.php b/src/Form/Type/SIUnitType.php index c018d5e1..2f0138f0 100644 --- a/src/Form/Type/SIUnitType.php +++ b/src/Form/Type/SIUnitType.php @@ -143,13 +143,13 @@ final class SIUnitType extends AbstractType implements DataMapperInterface } /** - * Maps the view data of a compound form to its children. + * Maps the view data of a compound form to its children. * - * The method is responsible for calling {@link FormInterface::setData()} - * on the children of compound forms, defining their underlying model data. + * The method is responsible for calling {@link FormInterface::setData()} + * on the children of compound forms, defining their underlying model data. * * @param mixed $viewData View data of the compound form being initialized - * @param FormInterface[]|Traversable $forms A list of {@link FormInterface} instances + * @param Traversable $forms A list of {@link FormInterface} instances * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported */ @@ -176,29 +176,29 @@ final class SIUnitType extends AbstractType implements DataMapperInterface } /** - * Maps the model data of a list of children forms into the view data of their parent. + * Maps the model data of a list of children forms into the view data of their parent. * - * This is the internal cascade call of FormInterface::submit for compound forms, since they - * cannot be bound to any input nor the request as scalar, but their children may: + * This is the internal cascade call of FormInterface::submit for compound forms, since they + * cannot be bound to any input nor the request as scalar, but their children may: * - * $compoundForm->submit($arrayOfChildrenViewData) - * // inside: - * $childForm->submit($childViewData); - * // for each entry, do the same and/or reverse transform - * $this->dataMapper->mapFormsToData($compoundForm, $compoundInitialViewData) - * // then reverse transform + * $compoundForm->submit($arrayOfChildrenViewData) + * // inside: + * $childForm->submit($childViewData); + * // for each entry, do the same and/or reverse transform + * $this->dataMapper->mapFormsToData($compoundForm, $compoundInitialViewData) + * // then reverse transform * - * When a simple form is submitted the following is happening: + * When a simple form is submitted the following is happening: * - * $simpleForm->submit($submittedViewData) - * // inside: - * $this->viewData = $submittedViewData - * // then reverse transform + * $simpleForm->submit($submittedViewData) + * // inside: + * $this->viewData = $submittedViewData + * // then reverse transform * - * The model data can be an array or an object, so this second argument is always passed - * by reference. + * The model data can be an array or an object, so this second argument is always passed + * by reference. * - * @param FormInterface[]|Traversable $forms A list of {@link FormInterface} instances + * @param Traversable $forms A list of {@link FormInterface} instances * @param mixed $viewData The compound form's view data that get mapped * its children model data * diff --git a/src/Serializer/BigNumberNormalizer.php b/src/Serializer/BigNumberNormalizer.php index b97b9b64..8bb686ee 100644 --- a/src/Serializer/BigNumberNormalizer.php +++ b/src/Serializer/BigNumberNormalizer.php @@ -45,7 +45,10 @@ class BigNumberNormalizer implements NormalizerInterface return (string) $object; } - public function getSupportedTypes(?string $format) + /** + * @return bool[] + */ + public function getSupportedTypes(?string $format): array { return [ BigNumber::class => true, diff --git a/src/Serializer/PartNormalizer.php b/src/Serializer/PartNormalizer.php index 00bd2256..b453a58e 100644 --- a/src/Serializer/PartNormalizer.php +++ b/src/Serializer/PartNormalizer.php @@ -68,7 +68,12 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface return $data instanceof Part; } - public function normalize($object, string $format = null, array $context = []): array + /** + * @return (float|mixed)[]|\ArrayObject|null|scalar + * + * @psalm-return \ArrayObject|array{total_instock: float|mixed,...}|null|scalar + */ + public function normalize($object, string $format = null, array $context = []) { if (!$object instanceof Part) { throw new \InvalidArgumentException('This normalizer only supports Part objects!'); @@ -178,7 +183,10 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface return $object; } - public function getSupportedTypes(?string $format) + /** + * @return bool[] + */ + public function getSupportedTypes(?string $format): array { //Must be false, because we rely on is_array($data) in supportsDenormalization() return [ diff --git a/src/Serializer/StructuralElementFromNameDenormalizer.php b/src/Serializer/StructuralElementFromNameDenormalizer.php index e0d29606..63fba0a6 100644 --- a/src/Serializer/StructuralElementFromNameDenormalizer.php +++ b/src/Serializer/StructuralElementFromNameDenormalizer.php @@ -42,7 +42,12 @@ class StructuralElementFromNameDenormalizer implements DenormalizerInterface return is_string($data) && is_subclass_of($type, AbstractStructuralDBElement::class); } - public function denormalize($data, string $type, string $format = null, array $context = []): ?AbstractStructuralDBElement + /** + * @template T + * @phpstan-param class-string $type + * @phpstan-return T|null + */ + public function denormalize($data, string $type, string $format = null, array $context = []): AbstractStructuralDBElement|null { //Retrieve the repository for the given type /** @var StructuralDBElementRepository $repo */ @@ -69,7 +74,10 @@ class StructuralElementFromNameDenormalizer implements DenormalizerInterface return end($elements); } - public function getSupportedTypes(?string $format) + /** + * @return bool[] + */ + public function getSupportedTypes(?string $format): array { //Cachable value Must be false, because we do an is_string check on data in supportsDenormalization return [ diff --git a/src/Serializer/StructuralElementNormalizer.php b/src/Serializer/StructuralElementNormalizer.php index 0c7f2ca5..fc64aec0 100644 --- a/src/Serializer/StructuralElementNormalizer.php +++ b/src/Serializer/StructuralElementNormalizer.php @@ -46,7 +46,10 @@ class StructuralElementNormalizer implements NormalizerInterface return $data instanceof AbstractStructuralDBElement; } - public function normalize($object, string $format = null, array $context = []): array + /** + * @return array + */ + public function normalize($object, string $format = null, array $context = []) { if (!$object instanceof AbstractStructuralDBElement) { throw new \InvalidArgumentException('This normalizer only supports AbstractStructural objects!'); @@ -64,7 +67,10 @@ class StructuralElementNormalizer implements NormalizerInterface return $data; } - public function getSupportedTypes(?string $format) + /** + * @return bool[] + */ + public function getSupportedTypes(?string $format): array { return [ AbstractStructuralDBElement::class => true, diff --git a/src/Services/Attachments/AttachmentPathResolver.php b/src/Services/Attachments/AttachmentPathResolver.php index 0628a6a9..4e1a7149 100644 --- a/src/Services/Attachments/AttachmentPathResolver.php +++ b/src/Services/Attachments/AttachmentPathResolver.php @@ -33,8 +33,8 @@ use Symfony\Component\Filesystem\Filesystem; */ class AttachmentPathResolver { - protected ?string $media_path; - protected ?string $footprints_path; + protected string $media_path; + protected string $footprints_path; protected ?string $models_path; protected ?string $secure_path; @@ -54,11 +54,11 @@ class AttachmentPathResolver */ public function __construct(protected string $project_dir, string $media_path, string $secure_path, ?string $footprints_path, ?string $models_path) { - //Determine the path for our ressources - $this->media_path = $this->parameterToAbsolutePath($media_path); - $this->footprints_path = $this->parameterToAbsolutePath($footprints_path); + //Determine the path for our resources + $this->media_path = $this->parameterToAbsolutePath($media_path) ?? throw new \InvalidArgumentException('The media path must be set and valid!'); + $this->secure_path = $this->parameterToAbsolutePath($secure_path) ?? throw new \InvalidArgumentException('The secure path must be set and valid!'); + $this->footprints_path = $this->parameterToAbsolutePath($footprints_path) ; $this->models_path = $this->parameterToAbsolutePath($models_path); - $this->secure_path = $this->parameterToAbsolutePath($secure_path); $this->pathes = [$this->media_path, $this->media_path, $this->footprints_path, $this->models_path, $this->secure_path]; //Remove all disabled placeholders @@ -192,7 +192,7 @@ class AttachmentPathResolver } /** - * The path where uploaded attachments is stored. + * The path where uploaded attachments is stored. * * @return string the absolute path to the media folder */ @@ -202,8 +202,8 @@ class AttachmentPathResolver } /** - * The path where secured attachments are stored. Must not be located in public/ folder, so it can only be accessed - * via the attachment controller. + * The path where secured attachments are stored. Must not be located in public/ folder, so it can only be accessed + * via the attachment controller. * * @return string the absolute path to the secure path */ @@ -215,7 +215,7 @@ class AttachmentPathResolver /** * The string where the builtin footprints are stored. * - * @return string|null The absolute path to the footprints folder. Null if built footprints were disabled. + * @return string|null The absolute path to the footprints' folder. Null if built footprints were disabled. */ public function getFootprintsPath(): ?string { @@ -225,7 +225,7 @@ class AttachmentPathResolver /** * The string where the builtin 3D models are stored. * - * @return string|null The absolute path to the models folder. Null if builtin models were disabled. + * @return string|null The absolute path to the models' folder. Null if builtin models were disabled. */ public function getModelsPath(): ?string { diff --git a/src/Services/EntityURLGenerator.php b/src/Services/EntityURLGenerator.php index 2f4e0c0b..30f56e5d 100644 --- a/src/Services/EntityURLGenerator.php +++ b/src/Services/EntityURLGenerator.php @@ -159,7 +159,7 @@ class EntityURLGenerator public function viewURL(Attachment $entity): string { if ($entity->isExternal()) { //For external attachments, return the link to external path - return $entity->getURL(); + return $entity->getURL() ?? throw new \RuntimeException('External attachment has no URL!'); } //return $this->urlGenerator->generate('attachment_view', ['id' => $entity->getID()]); return $this->attachmentURLGenerator->getViewURL($entity) ?? ''; @@ -169,7 +169,7 @@ class EntityURLGenerator { if ($entity instanceof Attachment) { if ($entity->isExternal()) { //For external attachments, return the link to external path - return $entity->getURL(); + return $entity->getURL() ?? throw new \RuntimeException('External attachment has no URL!'); } return $this->attachmentURLGenerator->getDownloadURL($entity); diff --git a/src/Services/LabelSystem/LabelGenerator.php b/src/Services/LabelSystem/LabelGenerator.php index 41a5235e..333461f3 100644 --- a/src/Services/LabelSystem/LabelGenerator.php +++ b/src/Services/LabelSystem/LabelGenerator.php @@ -60,7 +60,9 @@ final class LabelGenerator } /** - * @param object|object[] $elements An element or an array of elements for which labels should be generated + * @param object|object[] $elements An element or an array of elements for which labels should be generated + * + * @return null|string */ public function generateLabel(LabelOptions $options, object|array $elements): string { @@ -83,7 +85,7 @@ final class LabelGenerator $dompdf->loadHtml($this->labelHTMLGenerator->getLabelHTML($options, $elements)); $dompdf->render(); - return $dompdf->output(); + return $dompdf->output() ?? throw new \RuntimeException('Could not generate label!'); } /** diff --git a/src/Services/LabelSystem/LabelTextReplacer.php b/src/Services/LabelSystem/LabelTextReplacer.php index e352729c..034e243f 100644 --- a/src/Services/LabelSystem/LabelTextReplacer.php +++ b/src/Services/LabelSystem/LabelTextReplacer.php @@ -77,19 +77,20 @@ final class LabelTextReplacer } /** - * Replaces all placeholders in the input lines. + * Replaces all placeholders in the input lines. * * @param string $lines The input lines that should be replaced - * @param object $target the object that should be used as source for the informations + * @param object $target the object that should be used as source for the information * - * @return string the Lines with replaced informations + * @return string the Lines with replaced information */ public function replace(string $lines, object $target): string { $patterns = [ - '/(\[\[[A-Z_0-9]+\]\])/' => fn($match) => $this->handlePlaceholder($match[0], $target), + '/(\[\[[A-Z_0-9]+\]\])/' => fn($match): string => $this->handlePlaceholder($match[0], $target), ]; - return preg_replace_callback_array($patterns, $lines); + return preg_replace_callback_array($patterns, $lines) ?? throw new \RuntimeException('Could not replace placeholders!'); + } } diff --git a/src/Services/LogSystem/HistoryHelper.php b/src/Services/LogSystem/HistoryHelper.php index e1638f41..f4752b6f 100644 --- a/src/Services/LogSystem/HistoryHelper.php +++ b/src/Services/LogSystem/HistoryHelper.php @@ -55,10 +55,10 @@ class HistoryHelper } /** - * Returns an array containing all elements that are associated with the argument. - * The returned array contains the given element. + * Returns an array containing all elements that are associated with the argument. + * The returned array contains the given element. * - * @psalm-return array + * @return AbstractDBElement[] */ public function getAssociatedElements(AbstractDBElement $element): array { diff --git a/src/Services/LogSystem/LogDiffFormatter.php b/src/Services/LogSystem/LogDiffFormatter.php index 5828185c..8b165d5a 100644 --- a/src/Services/LogSystem/LogDiffFormatter.php +++ b/src/Services/LogSystem/LogDiffFormatter.php @@ -57,7 +57,11 @@ class LogDiffFormatter ]); } - private function diffNumeric($old_data, $new_data): string + /** + * @param numeric $old_data + * @param numeric $new_data + */ + private function diffNumeric(int|float|string $old_data, int|float|string $new_data): string { if ((!is_numeric($old_data)) || (!is_numeric($new_data))) { throw new \InvalidArgumentException('The given data is not numeric.'); diff --git a/src/Services/LogSystem/TimeTravel.php b/src/Services/LogSystem/TimeTravel.php index 82e98afb..cb612907 100644 --- a/src/Services/LogSystem/TimeTravel.php +++ b/src/Services/LogSystem/TimeTravel.php @@ -232,16 +232,17 @@ class TimeTravel { $reflection = new ReflectionClass($element::class); $property = $reflection->getProperty($field); - $property->setAccessible(true); return $property->getValue($element); } + /** + * @param int|null|object $new_value + */ protected function setField(AbstractDBElement $element, string $field, mixed $new_value): void { $reflection = new ReflectionClass($element::class); $property = $reflection->getProperty($field); - $property->setAccessible(true); $property->setValue($element, $new_value); } diff --git a/src/Services/Parts/PartsTableActionHandler.php b/src/Services/Parts/PartsTableActionHandler.php index c97357e0..08c0715d 100644 --- a/src/Services/Parts/PartsTableActionHandler.php +++ b/src/Services/Parts/PartsTableActionHandler.php @@ -178,7 +178,7 @@ implode(',', array_map(static fn (PartLot $lot) => $lot->getID(), $part->getPart * * @throws AccessDeniedException */ - private function denyAccessUnlessGranted($attributes, $subject = null, string $message = 'Access Denied.'): void + private function denyAccessUnlessGranted(mixed $attributes, mixed $subject = null, string $message = 'Access Denied.'): void { if (!$this->security->isGranted($attributes, $subject)) { $exception = new AccessDeniedException($message); diff --git a/src/Services/Trees/NodesListBuilder.php b/src/Services/Trees/NodesListBuilder.php index 49c0aa6b..c3e06455 100644 --- a/src/Services/Trees/NodesListBuilder.php +++ b/src/Services/Trees/NodesListBuilder.php @@ -66,12 +66,16 @@ class NodesListBuilder } /** - * Returns a flattened list of all (recursive) children elements of the given AbstractStructuralDBElement. - * The value is cached for performance reasons. + * Returns a flattened list of all (recursive) children elements of the given AbstractStructuralDBElement. + * The value is cached for performance reasons. * * @template T of AbstractStructuralDBElement - * @param T $element - * @return T[] + * + * @param T $element + * + * @return AbstractStructuralDBElement[] + * + * @phpstan-return list */ public function getChildrenFlatList(AbstractStructuralDBElement $element): array { diff --git a/src/Services/UserSystem/UserAvatarHelper.php b/src/Services/UserSystem/UserAvatarHelper.php index 5e14b34b..dd06ce1b 100644 --- a/src/Services/UserSystem/UserAvatarHelper.php +++ b/src/Services/UserSystem/UserAvatarHelper.php @@ -42,13 +42,16 @@ class UserAvatarHelper /** - * Returns the URL to the profile picture of the given user (in big size) + * Returns the URL to the profile picture of the given user (in big size) + * + * @return string */ public function getAvatarURL(User $user): string { //Check if the user has a master attachment defined (meaning he has explicitly defined a profile picture) if ($user->getMasterPictureAttachment() instanceof Attachment) { - return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_md'); + return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_md') + ?? throw new RuntimeException('Could not generate thumbnail URL'); } //If not check if gravatar is enabled (then use gravatar URL) @@ -64,7 +67,8 @@ class UserAvatarHelper { //Check if the user has a master attachment defined (meaning he has explicitly defined a profile picture) if ($user->getMasterPictureAttachment() instanceof Attachment) { - return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_xs'); + return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_xs') + ?? throw new RuntimeException('Could not generate thumbnail URL');; } //If not check if gravatar is enabled (then use gravatar URL) @@ -85,7 +89,8 @@ class UserAvatarHelper { //Check if the user has a master attachment defined (meaning he has explicitly defined a profile picture) if ($user->getMasterPictureAttachment() instanceof Attachment) { - return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_sm'); + return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_sm') + ?? throw new RuntimeException('Could not generate thumbnail URL'); } //If not check if gravatar is enabled (then use gravatar URL) diff --git a/src/Twig/TwigCoreExtension.php b/src/Twig/TwigCoreExtension.php index d9a35882..fb7da6d7 100644 --- a/src/Twig/TwigCoreExtension.php +++ b/src/Twig/TwigCoreExtension.php @@ -58,6 +58,10 @@ final class TwigCoreExtension extends AbstractExtension ]; } + /** + * @param string $enum_class + * @phpstan-param class-string $enum_class + */ public function getEnumCases(string $enum_class): array { if (!enum_exists($enum_class)) { @@ -75,12 +79,8 @@ final class TwigCoreExtension extends AbstractExtension ]; } - public function toArray($object) + public function toArray(object|array $object): array { - if(! is_object($object) && ! is_array($object)) { - throw new \InvalidArgumentException('The given variable is not an object or array!'); - } - //If it is already an array, we can just return it if(is_array($object)) { return $object;