Applied rector suggestions

This commit is contained in:
Jan Böhmer 2024-06-22 00:31:43 +02:00
parent 4106bcef5f
commit 20f32c7f12
170 changed files with 808 additions and 761 deletions

View file

@ -81,12 +81,12 @@ class EntityFilterHelper
public function getDescription(array $properties): array public function getDescription(array $properties): array
{ {
if (!$properties) { if ($properties === []) {
return []; return [];
} }
$description = []; $description = [];
foreach ($properties as $property => $strategy) { foreach (array_keys($properties) as $property) {
$description[(string)$property] = [ $description[(string)$property] = [
'property' => $property, 'property' => $property,
'type' => Type::BUILTIN_TYPE_STRING, 'type' => Type::BUILTIN_TYPE_STRING,

View file

@ -61,7 +61,7 @@ final class LikeFilter extends AbstractFilter
} }
$description = []; $description = [];
foreach ($this->properties as $property => $strategy) { foreach (array_keys($this->properties) as $property) {
$description[(string)$property] = [ $description[(string)$property] = [
'property' => $property, 'property' => $property,
'type' => Type::BUILTIN_TYPE_STRING, 'type' => Type::BUILTIN_TYPE_STRING,

View file

@ -74,15 +74,10 @@ abstract class BaseAdminController extends AbstractController
protected string $attachment_class = ''; protected string $attachment_class = '';
protected ?string $parameter_class = ''; protected ?string $parameter_class = '';
/**
* @var EventDispatcher|EventDispatcherInterface
*/
protected EventDispatcher|EventDispatcherInterface $eventDispatcher;
public function __construct(protected TranslatorInterface $translator, protected UserPasswordHasherInterface $passwordEncoder, public function __construct(protected TranslatorInterface $translator, protected UserPasswordHasherInterface $passwordEncoder,
protected AttachmentSubmitHandler $attachmentSubmitHandler, protected AttachmentSubmitHandler $attachmentSubmitHandler,
protected EventCommentHelper $commentHelper, protected HistoryHelper $historyHelper, protected TimeTravel $timeTravel, protected EventCommentHelper $commentHelper, protected HistoryHelper $historyHelper, protected TimeTravel $timeTravel,
protected DataTableFactory $dataTableFactory, EventDispatcherInterface $eventDispatcher, protected LabelExampleElementsGenerator $barcodeExampleGenerator, protected DataTableFactory $dataTableFactory, protected EventDispatcher|EventDispatcherInterface $eventDispatcher, protected LabelExampleElementsGenerator $barcodeExampleGenerator,
protected LabelGenerator $labelGenerator, protected EntityManagerInterface $entityManager) protected LabelGenerator $labelGenerator, protected EntityManagerInterface $entityManager)
{ {
if ('' === $this->entity_class || '' === $this->form_class || '' === $this->twig_template || '' === $this->route_base) { if ('' === $this->entity_class || '' === $this->form_class || '' === $this->twig_template || '' === $this->route_base) {
@ -96,7 +91,6 @@ abstract class BaseAdminController extends AbstractController
if ('' === $this->parameter_class || ($this->parameter_class && !is_a($this->parameter_class, AbstractParameter::class, true))) { if ('' === $this->parameter_class || ($this->parameter_class && !is_a($this->parameter_class, AbstractParameter::class, true))) {
throw new InvalidArgumentException('You have to override the $parameter_class value with a valid Parameter class in your subclass!'); throw new InvalidArgumentException('You have to override the $parameter_class value with a valid Parameter class in your subclass!');
} }
$this->eventDispatcher = $eventDispatcher;
} }
protected function revertElementIfNeeded(AbstractDBElement $entity, ?string $timestamp): ?DateTime protected function revertElementIfNeeded(AbstractDBElement $entity, ?string $timestamp): ?DateTime
@ -192,11 +186,9 @@ abstract class BaseAdminController extends AbstractController
} }
//Ensure that the master picture is still part of the attachments //Ensure that the master picture is still part of the attachments
if ($entity instanceof AttachmentContainingDBElement) { if ($entity instanceof AttachmentContainingDBElement && ($entity->getMasterPictureAttachment() !== null && !$entity->getAttachments()->contains($entity->getMasterPictureAttachment()))) {
if ($entity->getMasterPictureAttachment() !== null && !$entity->getAttachments()->contains($entity->getMasterPictureAttachment())) {
$entity->setMasterPictureAttachment(null); $entity->setMasterPictureAttachment(null);
} }
}
$this->commentHelper->setMessage($form['log_comment']->getData()); $this->commentHelper->setMessage($form['log_comment']->getData());
@ -283,11 +275,9 @@ abstract class BaseAdminController extends AbstractController
} }
//Ensure that the master picture is still part of the attachments //Ensure that the master picture is still part of the attachments
if ($new_entity instanceof AttachmentContainingDBElement) { if ($new_entity instanceof AttachmentContainingDBElement && ($new_entity->getMasterPictureAttachment() !== null && !$new_entity->getAttachments()->contains($new_entity->getMasterPictureAttachment()))) {
if ($new_entity->getMasterPictureAttachment() !== null && !$new_entity->getAttachments()->contains($new_entity->getMasterPictureAttachment())) {
$new_entity->setMasterPictureAttachment(null); $new_entity->setMasterPictureAttachment(null);
} }
}
$this->commentHelper->setMessage($form['log_comment']->getData()); $this->commentHelper->setMessage($form['log_comment']->getData());
$em->persist($new_entity); $em->persist($new_entity);

View file

@ -30,6 +30,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
/**
* @see \App\Tests\Controller\KiCadApiControllerTest
*/
#[Route('/kicad-api/v1')] #[Route('/kicad-api/v1')]
class KiCadApiController extends AbstractController class KiCadApiController extends AbstractController
{ {
@ -62,7 +65,7 @@ class KiCadApiController extends AbstractController
#[Route('/parts/category/{category}.json', name: 'kicad_api_category')] #[Route('/parts/category/{category}.json', name: 'kicad_api_category')]
public function categoryParts(?Category $category): Response public function categoryParts(?Category $category): Response
{ {
if ($category) { if ($category !== null) {
$this->denyAccessUnlessGranted('read', $category); $this->denyAccessUnlessGranted('read', $category);
} else { } else {
$this->denyAccessUnlessGranted('@categories.read'); $this->denyAccessUnlessGranted('@categories.read');

View file

@ -51,7 +51,7 @@ class OAuthClientController extends AbstractController
} }
#[Route('/{name}/check', name: 'oauth_client_check')] #[Route('/{name}/check', name: 'oauth_client_check')]
public function check(string $name, Request $request): Response public function check(string $name): Response
{ {
$this->denyAccessUnlessGranted('@system.manage_oauth_tokens'); $this->denyAccessUnlessGranted('@system.manage_oauth_tokens');

View file

@ -219,7 +219,7 @@ class ProjectController extends AbstractController
'project' => $project, 'project' => $project,
'part' => $part 'part' => $part
]); ]);
if ($bom_entry) { if ($bom_entry !== null) {
$preset_data->add($bom_entry); $preset_data->add($bom_entry);
} else { //Otherwise create an empty one } else { //Otherwise create an empty one
$entry = new ProjectBOMEntry(); $entry = new ProjectBOMEntry();

View file

@ -54,6 +54,9 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
/**
* @see \App\Tests\Controller\ScanControllerTest
*/
#[Route(path: '/scan')] #[Route(path: '/scan')]
class ScanController extends AbstractController class ScanController extends AbstractController
{ {

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
*/ */
namespace App\Controller; namespace App\Controller;
use Symfony\Component\Runtime\SymfonyRuntime;
use App\Services\Attachments\AttachmentSubmitHandler; use App\Services\Attachments\AttachmentSubmitHandler;
use App\Services\Attachments\AttachmentURLGenerator; use App\Services\Attachments\AttachmentURLGenerator;
use App\Services\Attachments\BuiltinAttachmentsFinder; use App\Services\Attachments\BuiltinAttachmentsFinder;
@ -84,7 +85,7 @@ class ToolsController extends AbstractController
'php_post_max_size' => ini_get('post_max_size'), 'php_post_max_size' => ini_get('post_max_size'),
'kernel_runtime_environment' => $this->getParameter('kernel.runtime_environment'), 'kernel_runtime_environment' => $this->getParameter('kernel.runtime_environment'),
'kernel_runtime_mode' => $this->getParameter('kernel.runtime_mode'), 'kernel_runtime_mode' => $this->getParameter('kernel.runtime_mode'),
'kernel_runtime' => $_SERVER['APP_RUNTIME'] ?? $_ENV['APP_RUNTIME'] ?? 'Symfony\\Component\\Runtime\\SymfonyRuntime', 'kernel_runtime' => $_SERVER['APP_RUNTIME'] ?? $_ENV['APP_RUNTIME'] ?? SymfonyRuntime::class,
//DB section //DB section
'db_type' => $DBInfoHelper->getDatabaseType() ?? 'Unknown', 'db_type' => $DBInfoHelper->getDatabaseType() ?? 'Unknown',

View file

@ -59,11 +59,8 @@ use Symfony\Component\Validator\Constraints\Length;
#[Route(path: '/user')] #[Route(path: '/user')]
class UserSettingsController extends AbstractController class UserSettingsController extends AbstractController
{ {
protected EventDispatcher|EventDispatcherInterface $eventDispatcher; public function __construct(protected bool $demo_mode, protected EventDispatcher|EventDispatcherInterface $eventDispatcher)
public function __construct(protected bool $demo_mode, EventDispatcherInterface $eventDispatcher)
{ {
$this->eventDispatcher = $eventDispatcher;
} }
#[Route(path: '/2fa_backup_codes', name: 'show_backup_codes')] #[Route(path: '/2fa_backup_codes', name: 'show_backup_codes')]

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\DataTables\Adapters; namespace App\DataTables\Adapters;
use Doctrine\ORM\Query\Expr\From;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator; use Doctrine\ORM\Tools\Pagination\Paginator;
@ -51,12 +52,12 @@ class TwoStepORMAdapter extends ORMAdapter
private bool $use_simple_total = false; private bool $use_simple_total = false;
private \Closure|null $query_modifier; private \Closure|null $query_modifier = null;
public function __construct(ManagerRegistry $registry = null) public function __construct(ManagerRegistry $registry = null)
{ {
parent::__construct($registry); parent::__construct($registry);
$this->detailQueryCallable = static function (QueryBuilder $qb, array $ids) { $this->detailQueryCallable = static function (QueryBuilder $qb, array $ids): never {
throw new \RuntimeException('You need to set the detail_query option to use the TwoStepORMAdapter'); throw new \RuntimeException('You need to set the detail_query option to use the TwoStepORMAdapter');
}; };
} }
@ -66,9 +67,7 @@ class TwoStepORMAdapter extends ORMAdapter
parent::configureOptions($resolver); parent::configureOptions($resolver);
$resolver->setRequired('filter_query'); $resolver->setRequired('filter_query');
$resolver->setDefault('query', function (Options $options) { $resolver->setDefault('query', fn(Options $options) => $options['filter_query']);
return $options['filter_query'];
});
$resolver->setRequired('detail_query'); $resolver->setRequired('detail_query');
$resolver->setAllowedTypes('detail_query', \Closure::class); $resolver->setAllowedTypes('detail_query', \Closure::class);
@ -108,7 +107,7 @@ class TwoStepORMAdapter extends ORMAdapter
} }
} }
/** @var Query\Expr\From $fromClause */ /** @var From $fromClause */
$fromClause = $builder->getDQLPart('from')[0]; $fromClause = $builder->getDQLPart('from')[0];
$identifier = "{$fromClause->getAlias()}.{$this->metadata->getSingleIdentifierFieldName()}"; $identifier = "{$fromClause->getAlias()}.{$this->metadata->getSingleIdentifierFieldName()}";
@ -201,7 +200,7 @@ class TwoStepORMAdapter extends ORMAdapter
/** The paginator count queries can be rather slow, so when query for total count (100ms or longer), /** The paginator count queries can be rather slow, so when query for total count (100ms or longer),
* just return the entity count. * just return the entity count.
*/ */
/** @var Query\Expr\From $from_expr */ /** @var From $from_expr */
$from_expr = $queryBuilder->getDQLPart('from')[0]; $from_expr = $queryBuilder->getDQLPart('from')[0];
return $this->manager->getRepository($from_expr->getFrom())->count([]); return $this->manager->getRepository($from_expr->getFrom())->count([]);

View file

@ -92,7 +92,7 @@ final class AttachmentDataTable implements DataTableTypeInterface
if ($context->isExternal()) { if ($context->isExternal()) {
return sprintf( return sprintf(
'<a href="%s" class="link-external">%s</a>', '<a href="%s" class="link-external">%s</a>',
htmlspecialchars($context->getURL()), htmlspecialchars((string) $context->getURL()),
htmlspecialchars($value) htmlspecialchars($value)
); );
} }

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\DataTables\Column; namespace App\DataTables\Column;
use Omines\DataTablesBundle\Column\AbstractColumn; use Omines\DataTablesBundle\Column\AbstractColumn;

View file

@ -109,7 +109,7 @@ class ColumnSortHelper
} }
//and the remaining non-visible columns //and the remaining non-visible columns
foreach ($this->columns as $col_id => $col_data) { foreach (array_keys($this->columns) as $col_id) {
if (in_array($col_id, $processed_columns, true)) { if (in_array($col_id, $processed_columns, true)) {
// column already processed // column already processed
continue; continue;

View file

@ -162,7 +162,7 @@ class LogDataTable implements DataTableTypeInterface
if (!$user instanceof User) { if (!$user instanceof User) {
if ($context->isCLIEntry()) { if ($context->isCLIEntry()) {
return sprintf('%s [%s]', return sprintf('%s [%s]',
htmlentities($context->getCLIUsername()), htmlentities((string) $context->getCLIUsername()),
$this->translator->trans('log.cli_user') $this->translator->trans('log.cli_user')
); );
} }

View file

@ -156,7 +156,7 @@ final class PartsDataTable implements DataTableTypeInterface
'orderField' => 'NATSORT(_partUnit.name)', 'orderField' => 'NATSORT(_partUnit.name)',
'render' => function($value, Part $context): string { 'render' => function($value, Part $context): string {
$partUnit = $context->getPartUnit(); $partUnit = $context->getPartUnit();
if (!$partUnit) { if ($partUnit === null) {
return ''; return '';
} }
@ -184,7 +184,7 @@ final class PartsDataTable implements DataTableTypeInterface
'label' => $this->translator->trans('part.table.manufacturingStatus'), 'label' => $this->translator->trans('part.table.manufacturingStatus'),
'class' => ManufacturingStatus::class, 'class' => ManufacturingStatus::class,
'render' => function (?ManufacturingStatus $status, Part $context): string { 'render' => function (?ManufacturingStatus $status, Part $context): string {
if (!$status) { if ($status === null) {
return ''; return '';
} }

View file

@ -85,7 +85,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
'orderField' => 'NATSORT(part.name)', 'orderField' => 'NATSORT(part.name)',
'render' => function ($value, ProjectBOMEntry $context) { 'render' => function ($value, ProjectBOMEntry $context) {
if(!$context->getPart() instanceof Part) { if(!$context->getPart() instanceof Part) {
return htmlspecialchars($context->getName()); return htmlspecialchars((string) $context->getName());
} }
if($context->getPart() instanceof Part) { if($context->getPart() instanceof Part) {
$tmp = $this->partDataTableHelper->renderName($context->getPart()); $tmp = $this->partDataTableHelper->renderName($context->getPart());
@ -154,7 +154,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
'label' => 'project.bom.instockAmount', 'label' => 'project.bom.instockAmount',
'visible' => false, 'visible' => false,
'render' => function ($value, ProjectBOMEntry $context) { 'render' => function ($value, ProjectBOMEntry $context) {
if ($context->getPart()) { if ($context->getPart() !== null) {
return $this->partDataTableHelper->renderAmount($context->getPart()); return $this->partDataTableHelper->renderAmount($context->getPart());
} }
@ -165,7 +165,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
'label' => 'part.table.storeLocations', 'label' => 'part.table.storeLocations',
'visible' => false, 'visible' => false,
'render' => function ($value, ProjectBOMEntry $context) { 'render' => function ($value, ProjectBOMEntry $context) {
if ($context->getPart()) { if ($context->getPart() !== null) {
return $this->partDataTableHelper->renderStorageLocations($context->getPart()); return $this->partDataTableHelper->renderStorageLocations($context->getPart());
} }

View file

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace App\Doctrine\Functions; namespace App\Doctrine\Functions;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\AST\Functions\FunctionNode; use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\TokenType; use Doctrine\ORM\Query\TokenType;
@ -36,7 +38,7 @@ class Field2 extends FunctionNode
private $values = []; private $values = [];
public function parse(\Doctrine\ORM\Query\Parser $parser): void public function parse(Parser $parser): void
{ {
$parser->match(TokenType::T_IDENTIFIER); $parser->match(TokenType::T_IDENTIFIER);
$parser->match(TokenType::T_OPEN_PARENTHESIS); $parser->match(TokenType::T_OPEN_PARENTHESIS);
@ -58,15 +60,16 @@ class Field2 extends FunctionNode
$parser->match(TokenType::T_CLOSE_PARENTHESIS); $parser->match(TokenType::T_CLOSE_PARENTHESIS);
} }
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker): string public function getSql(SqlWalker $sqlWalker): string
{ {
$query = 'FIELD2('; $query = 'FIELD2(';
$query .= $this->field->dispatch($sqlWalker); $query .= $this->field->dispatch($sqlWalker);
$query .= ', '; $query .= ', ';
$counter = count($this->values);
for ($i = 0; $i < count($this->values); $i++) { for ($i = 0; $i < $counter; $i++) {
if ($i > 0) { if ($i > 0) {
$query .= ', '; $query .= ', ';
} }
@ -74,8 +77,6 @@ class Field2 extends FunctionNode
$query .= $this->values[$i]->dispatch($sqlWalker); $query .= $this->values[$i]->dispatch($sqlWalker);
} }
$query .= ')'; return $query . ')';
return $query;
} }
} }

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Doctrine\Functions; namespace App\Doctrine\Functions;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver; use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
@ -59,9 +60,9 @@ class Natsort extends FunctionNode
* The result is cached in memory. * The result is cached in memory.
* @param Connection $connection * @param Connection $connection
* @return bool * @return bool
* @throws \Doctrine\DBAL\Exception * @throws Exception
*/ */
private static function mariaDBSupportsNaturalSort(Connection $connection): bool private function mariaDBSupportsNaturalSort(Connection $connection): bool
{ {
if (self::$supportsNaturalSort !== null) { if (self::$supportsNaturalSort !== null) {
return self::$supportsNaturalSort; return self::$supportsNaturalSort;
@ -95,7 +96,7 @@ class Natsort extends FunctionNode
return $this->field->dispatch($sqlWalker) . ' COLLATE numeric'; return $this->field->dispatch($sqlWalker) . ' COLLATE numeric';
} }
if ($platform instanceof MariaDBPlatform && self::mariaDBSupportsNaturalSort($sqlWalker->getConnection())) { if ($platform instanceof MariaDBPlatform && $this->mariaDBSupportsNaturalSort($sqlWalker->getConnection())) {
return 'NATURAL_SORT_KEY(' . $this->field->dispatch($sqlWalker) . ')'; return 'NATURAL_SORT_KEY(' . $this->field->dispatch($sqlWalker) . ')';
} }

View file

@ -98,10 +98,9 @@ class SQLiteRegexExtensionMiddlewareDriver extends AbstractDriverMiddleware
* This function returns the index (position) of the first argument in the subsequent arguments. * This function returns the index (position) of the first argument in the subsequent arguments.
* If the first argument is not found or is NULL, 0 is returned. * If the first argument is not found or is NULL, 0 is returned.
* @param string|int|null $value * @param string|int|null $value
* @param mixed ...$array
* @return int * @return int
*/ */
final public static function field(string|int|null $value, ...$array): int final public static function field(string|int|null $value, mixed ...$array): int
{ {
if ($value === null) { if ($value === null) {
return 0; return 0;

View file

@ -385,7 +385,7 @@ abstract class Attachment extends AbstractNamedDBElement
return null; return null;
} }
return parse_url($this->getURL(), PHP_URL_HOST); return parse_url((string) $this->getURL(), PHP_URL_HOST);
} }
/** /**
@ -477,7 +477,7 @@ abstract class Attachment extends AbstractNamedDBElement
*/ */
public function setElement(AttachmentContainingDBElement $element): self public function setElement(AttachmentContainingDBElement $element): self
{ {
if (!is_a($element, static::ALLOWED_ELEMENT_CLASS)) { if (!$element instanceof AttachmentContainingDBElement) {
throw new InvalidArgumentException(sprintf('The element associated with a %s must be a %s!', static::class, static::ALLOWED_ELEMENT_CLASS)); throw new InvalidArgumentException(sprintf('The element associated with a %s must be a %s!', static::class, static::ALLOWED_ELEMENT_CLASS));
} }

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Attachments; namespace App\Entity\Attachments;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -85,8 +86,11 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])] #[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
class AttachmentType extends AbstractStructuralDBElement class AttachmentType extends AbstractStructuralDBElement
{ {
/**
* @var Collection<int, \App\Entity\Attachments\AttachmentType>
*/
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: AttachmentType::class, cascade: ['persist'])] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: AttachmentType::class, cascade: ['persist'])]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'children')]
@ -110,7 +114,7 @@ class AttachmentType extends AbstractStructuralDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: AttachmentTypeAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: AttachmentTypeAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['attachment_type:read', 'attachment_type:write'])] #[Groups(['attachment_type:read', 'attachment_type:write'])]
protected Collection $attachments; protected Collection $attachments;
@ -123,7 +127,7 @@ class AttachmentType extends AbstractStructuralDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: AttachmentTypeParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: AttachmentTypeParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['attachment_type:read', 'attachment_type:write'])] #[Groups(['attachment_type:read', 'attachment_type:write'])]
protected Collection $parameters; protected Collection $parameters;

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LabelSystem; namespace App\Entity\LabelSystem;
enum BarcodeType: string enum BarcodeType: string

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LabelSystem; namespace App\Entity\LabelSystem;
enum LabelPictureType: string enum LabelPictureType: string

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LabelSystem; namespace App\Entity\LabelSystem;
enum LabelProcessMode: string enum LabelProcessMode: string

View file

@ -41,6 +41,7 @@ declare(strict_types=1);
namespace App\Entity\LabelSystem; namespace App\Entity\LabelSystem;
use Doctrine\Common\Collections\Criteria;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
use App\Repository\LabelProfileRepository; use App\Repository\LabelProfileRepository;
use App\EntityListeners\TreeCacheInvalidationListener; use App\EntityListeners\TreeCacheInvalidationListener;
@ -66,7 +67,7 @@ class LabelProfile extends AttachmentContainingDBElement
* @var Collection<int, LabelAttachment> * @var Collection<int, LabelAttachment>
*/ */
#[ORM\OneToMany(mappedBy: 'element', targetEntity: LabelAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: LabelAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $attachments; protected Collection $attachments;
#[ORM\ManyToOne(targetEntity: LabelAttachment::class)] #[ORM\ManyToOne(targetEntity: LabelAttachment::class)]

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LabelSystem; namespace App\Entity\LabelSystem;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;

View file

@ -55,7 +55,8 @@ abstract class AbstractLogEntry extends AbstractDBElement
#[ORM\Column(type: Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $username = ''; protected string $username = '';
/** @var \DateTime The datetime the event associated with this log entry has occured /**
* @var \DateTimeInterface The datetime the event associated with this log entry has occured
*/ */
#[ORM\Column(name: 'datetime', type: Types::DATETIME_MUTABLE)] #[ORM\Column(name: 'datetime', type: Types::DATETIME_MUTABLE)]
protected \DateTime $timestamp; protected \DateTime $timestamp;

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LogSystem; namespace App\Entity\LogSystem;
use Psr\Log\LogLevel as PSRLogLevel; use Psr\Log\LogLevel as PSRLogLevel;

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LogSystem; namespace App\Entity\LogSystem;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
@ -120,7 +122,7 @@ enum LogTargetType: int
} }
} }
$elementClass = is_object($element) ? get_class($element) : $element; $elementClass = is_object($element) ? $element::class : $element;
//If no matching type was found, throw an exception //If no matching type was found, throw an exception
throw new \InvalidArgumentException("The given class $elementClass is not a valid log target type."); throw new \InvalidArgumentException("The given class $elementClass is not a valid log target type.");
} }

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LogSystem; namespace App\Entity\LogSystem;
use App\Entity\Contracts\LogWithEventUndoInterface; use App\Entity\Contracts\LogWithEventUndoInterface;

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Entity\LogSystem; namespace App\Entity\LogSystem;
enum PartStockChangeType: string enum PartStockChangeType: string

View file

@ -52,8 +52,6 @@ class PartStockChangedLogEntry extends AbstractLogEntry
$this->level = LogLevel::INFO; $this->level = LogLevel::INFO;
$this->setTargetElement($lot); $this->setTargetElement($lot);
$this->typeString = 'part_stock_changed';
$this->extra = array_merge($this->extra, [ $this->extra = array_merge($this->extra, [
't' => $type->toExtraShortType(), 't' => $type->toExtraShortType(),
'o' => $old_stock, 'o' => $old_stock,

View file

@ -38,7 +38,7 @@ use League\OAuth2\Client\Token\AccessTokenInterface;
class OAuthToken extends AbstractNamedDBElement implements AccessTokenInterface class OAuthToken extends AbstractNamedDBElement implements AccessTokenInterface
{ {
/** @var string|null The short-term usable OAuth2 token */ /** @var string|null The short-term usable OAuth2 token */
#[ORM\Column(type: 'text', nullable: true)] #[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $token = null; private ?string $token = null;
/** @var \DateTimeImmutable|null The date when the token expires */ /** @var \DateTimeImmutable|null The date when the token expires */
@ -46,7 +46,7 @@ class OAuthToken extends AbstractNamedDBElement implements AccessTokenInterface
private ?\DateTimeImmutable $expires_at = null; private ?\DateTimeImmutable $expires_at = null;
/** @var string|null The refresh token for the OAuth2 auth */ /** @var string|null The refresh token for the OAuth2 auth */
#[ORM\Column(type: 'text', nullable: true)] #[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $refresh_token = null; private ?string $refresh_token = null;
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -91,7 +92,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class Category extends AbstractPartsContainingDBElement class Category extends AbstractPartsContainingDBElement
{ {
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
@ -165,7 +166,7 @@ class Category extends AbstractPartsContainingDBElement
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full', 'category:read', 'category:write'])] #[Groups(['full', 'category:read', 'category:write'])]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CategoryAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: CategoryAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $attachments; protected Collection $attachments;
#[ORM\ManyToOne(targetEntity: CategoryAttachment::class)] #[ORM\ManyToOne(targetEntity: CategoryAttachment::class)]
@ -178,7 +179,7 @@ class Category extends AbstractPartsContainingDBElement
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full', 'category:read', 'category:write'])] #[Groups(['full', 'category:read', 'category:write'])]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CategoryParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: CategoryParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
#[Groups(['category:read'])] #[Groups(['category:read'])]

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -96,7 +97,7 @@ class Footprint extends AbstractPartsContainingDBElement
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[Groups(['footprint:read', 'footprint:write'])] #[Groups(['footprint:read', 'footprint:write'])]
@ -107,7 +108,7 @@ class Footprint extends AbstractPartsContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: FootprintAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: FootprintAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['footprint:read', 'footprint:write'])] #[Groups(['footprint:read', 'footprint:write'])]
protected Collection $attachments; protected Collection $attachments;
@ -128,7 +129,7 @@ class Footprint extends AbstractPartsContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: FootprintParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: FootprintParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['footprint:read', 'footprint:write'])] #[Groups(['footprint:read', 'footprint:write'])]
protected Collection $parameters; protected Collection $parameters;

View file

@ -31,25 +31,26 @@ use Symfony\Component\Serializer\Annotation\Groups;
/** /**
* This class represents a reference to a info provider inside a part. * This class represents a reference to a info provider inside a part.
* @see \App\Tests\Entity\Parts\InfoProviderReferenceTest
*/ */
#[Embeddable] #[Embeddable]
class InfoProviderReference class InfoProviderReference
{ {
/** @var string|null The key referencing the provider used to get this part, or null if it was not provided by a data provider */ /** @var string|null The key referencing the provider used to get this part, or null if it was not provided by a data provider */
#[Column(type: 'string', nullable: true)] #[Column(type: Types::STRING, nullable: true)]
#[Groups(['provider_reference:read'])] #[Groups(['provider_reference:read'])]
private ?string $provider_key = null; private ?string $provider_key = null;
/** @var string|null The id of this part inside the provider system or null if the part was not provided by a data provider */ /** @var string|null The id of this part inside the provider system or null if the part was not provided by a data provider */
#[Column(type: 'string', nullable: true)] #[Column(type: Types::STRING, nullable: true)]
#[Groups(['provider_reference:read'])] #[Groups(['provider_reference:read'])]
private ?string $provider_id = null; private ?string $provider_id = null;
/** /**
* @var string|null The url of this part inside the provider system or null if this info is not existing * @var string|null The url of this part inside the provider system or null if this info is not existing
*/ */
#[Column(type: 'string', nullable: true)] #[Column(type: Types::STRING, nullable: true)]
#[Groups(['provider_reference:read'])] #[Groups(['provider_reference:read'])]
private ?string $provider_url = null; private ?string $provider_url = null;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -95,7 +96,7 @@ class Manufacturer extends AbstractCompany
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
/** /**
@ -103,7 +104,7 @@ class Manufacturer extends AbstractCompany
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ManufacturerAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: ManufacturerAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['manufacturer:read', 'manufacturer:write'])] #[Groups(['manufacturer:read', 'manufacturer:write'])]
#[ApiProperty(readableLink: false, writableLink: true)] #[ApiProperty(readableLink: false, writableLink: true)]
protected Collection $attachments; protected Collection $attachments;
@ -118,7 +119,7 @@ class Manufacturer extends AbstractCompany
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ManufacturerParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: ManufacturerParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['manufacturer:read', 'manufacturer:write'])] #[Groups(['manufacturer:read', 'manufacturer:write'])]
#[ApiProperty(readableLink: false, writableLink: true)] #[ApiProperty(readableLink: false, writableLink: true)]
protected Collection $parameters; protected Collection $parameters;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -123,7 +124,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
protected bool $use_si_prefix = false; protected bool $use_si_prefix = false;
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class, cascade: ['persist'])] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class, cascade: ['persist'])]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
@ -137,7 +138,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: MeasurementUnitAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: MeasurementUnitAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['measurement_unit:read', 'measurement_unit:write'])] #[Groups(['measurement_unit:read', 'measurement_unit:write'])]
protected Collection $attachments; protected Collection $attachments;
@ -150,7 +151,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: MeasurementUnitParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: MeasurementUnitParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['measurement_unit:read', 'measurement_unit:write'])] #[Groups(['measurement_unit:read', 'measurement_unit:write'])]
protected Collection $parameters; protected Collection $parameters;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
@ -119,7 +120,7 @@ class Part extends AttachmentContainingDBElement
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full', 'part:read', 'part:write'])] #[Groups(['full', 'part:read', 'part:write'])]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: PartParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: PartParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[UniqueObjectCollection(fields: ['name', 'group', 'element'])] #[UniqueObjectCollection(fields: ['name', 'group', 'element'])]
protected Collection $parameters; protected Collection $parameters;
@ -140,7 +141,7 @@ class Part extends AttachmentContainingDBElement
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full', 'part:read', 'part:write'])] #[Groups(['full', 'part:read', 'part:write'])]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: PartAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: PartAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $attachments; protected Collection $attachments;
/** /**

View file

@ -49,6 +49,7 @@ use Symfony\Component\Validator\Constraints\Length;
/** /**
* This entity describes a part association, which is a semantic connection between two parts. * This entity describes a part association, which is a semantic connection between two parts.
* For example, a part association can be used to describe that a part is a replacement for another part. * For example, a part association can be used to describe that a part is a replacement for another part.
* @see \App\Tests\Entity\Parts\PartAssociationTest
*/ */
#[ORM\Entity(repositoryClass: DBElementRepository::class)] #[ORM\Entity(repositoryClass: DBElementRepository::class)]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]

View file

@ -105,7 +105,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
protected string $comment = ''; protected string $comment = '';
/** /**
* @var \DateTime|null Set a time until when the lot must be used. * @var \DateTimeInterface|null Set a time until when the lot must be used.
* Set to null, if the lot can be used indefinitely. * Set to null, if the lot can be used indefinitely.
*/ */
#[Groups(['extended', 'full', 'import', 'part_lot:read', 'part_lot:write'])] #[Groups(['extended', 'full', 'import', 'part_lot:read', 'part_lot:write'])]

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits; namespace App\Entity\Parts\PartTraits;
use Doctrine\Common\Collections\Criteria;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\PartLot; use App\Entity\Parts\PartLot;
@ -42,7 +43,7 @@ trait InstockTrait
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full', 'import', 'part:read', 'part:write'])] #[Groups(['extended', 'full', 'import', 'part:read', 'part:write'])]
#[ORM\OneToMany(mappedBy: 'part', targetEntity: PartLot::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'part', targetEntity: PartLot::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['amount' => 'DESC'])] #[ORM\OrderBy(['amount' => Criteria::DESC])]
protected Collection $partLots; protected Collection $partLots;
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits; namespace App\Entity\Parts\PartTraits;
use Doctrine\Common\Collections\Criteria;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use App\Entity\PriceInformations\Orderdetail; use App\Entity\PriceInformations\Orderdetail;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
@ -41,7 +42,7 @@ trait OrderTrait
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full', 'import', 'part:read', 'part:write'])] #[Groups(['extended', 'full', 'import', 'part:read', 'part:write'])]
#[ORM\OneToMany(mappedBy: 'part', targetEntity: Orderdetail::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'part', targetEntity: Orderdetail::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['supplierpartnr' => 'ASC'])] #[ORM\OrderBy(['supplierpartnr' => Criteria::ASC])]
protected Collection $orderdetails; protected Collection $orderdetails;
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -90,7 +91,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class StorageLocation extends AbstractPartsContainingDBElement class StorageLocation extends AbstractPartsContainingDBElement
{ {
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
@ -114,7 +115,7 @@ class StorageLocation extends AbstractPartsContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: StorageLocationParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: StorageLocationParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['location:read', 'location:write'])] #[Groups(['location:read', 'location:write'])]
protected Collection $parameters; protected Collection $parameters;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -92,7 +93,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class Supplier extends AbstractCompany class Supplier extends AbstractCompany
{ {
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
@ -129,7 +130,7 @@ class Supplier extends AbstractCompany
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: SupplierAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: SupplierAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['supplier:read', 'supplier:write'])] #[Groups(['supplier:read', 'supplier:write'])]
#[ApiProperty(readableLink: false, writableLink: true)] #[ApiProperty(readableLink: false, writableLink: true)]
protected Collection $attachments; protected Collection $attachments;
@ -144,7 +145,7 @@ class Supplier extends AbstractCompany
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: SupplierParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: SupplierParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['supplier:read', 'supplier:write'])] #[Groups(['supplier:read', 'supplier:write'])]
#[ApiProperty(readableLink: false, writableLink: true)] #[ApiProperty(readableLink: false, writableLink: true)]
protected Collection $parameters; protected Collection $parameters;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\PriceInformations; namespace App\Entity\PriceInformations;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -118,7 +119,7 @@ class Currency extends AbstractStructuralDBElement
protected string $iso_code = ""; protected string $iso_code = "";
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class, cascade: ['persist'])] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class, cascade: ['persist'])]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
@ -132,7 +133,7 @@ class Currency extends AbstractStructuralDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CurrencyAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: CurrencyAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['currency:read', 'currency:write'])] #[Groups(['currency:read', 'currency:write'])]
protected Collection $attachments; protected Collection $attachments;
@ -145,7 +146,7 @@ class Currency extends AbstractStructuralDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CurrencyParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: CurrencyParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['currency:read', 'currency:write'])] #[Groups(['currency:read', 'currency:write'])]
protected Collection $parameters; protected Collection $parameters;

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Entity\PriceInformations; namespace App\Entity\PriceInformations;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
@ -96,10 +97,13 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
{ {
use TimestampTrait; use TimestampTrait;
/**
* @var Collection<int, Pricedetail>
*/
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full', 'import', 'orderdetail:read', 'orderdetail:write'])] #[Groups(['extended', 'full', 'import', 'orderdetail:read', 'orderdetail:write'])]
#[ORM\OneToMany(mappedBy: 'orderdetail', targetEntity: Pricedetail::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'orderdetail', targetEntity: Pricedetail::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['min_discount_quantity' => 'ASC'])] #[ORM\OrderBy(['min_discount_quantity' => Criteria::ASC])]
protected Collection $pricedetails; protected Collection $pricedetails;
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\ProjectSystem; namespace App\Entity\ProjectSystem;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiProperty;
@ -88,7 +89,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
class Project extends AbstractStructuralDBElement class Project extends AbstractStructuralDBElement
{ {
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
@ -100,6 +101,9 @@ class Project extends AbstractStructuralDBElement
#[Groups(['project:read', 'project:write'])] #[Groups(['project:read', 'project:write'])]
protected string $comment = ''; protected string $comment = '';
/**
* @var Collection<int, ProjectBOMEntry>
*/
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full'])] #[Groups(['extended', 'full'])]
#[ORM\OneToMany(mappedBy: 'project', targetEntity: ProjectBOMEntry::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'project', targetEntity: ProjectBOMEntry::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
@ -137,7 +141,7 @@ class Project extends AbstractStructuralDBElement
* @var Collection<int, ProjectAttachment> * @var Collection<int, ProjectAttachment>
*/ */
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ProjectAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: ProjectAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['project:read', 'project:write'])] #[Groups(['project:read', 'project:write'])]
protected Collection $attachments; protected Collection $attachments;
@ -149,7 +153,7 @@ class Project extends AbstractStructuralDBElement
/** @var Collection<int, ProjectParameter> /** @var Collection<int, ProjectParameter>
*/ */
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ProjectParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: ProjectParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[Groups(['project:read', 'project:write'])] #[Groups(['project:read', 'project:write'])]
protected Collection $parameters; protected Collection $parameters;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use Doctrine\Common\Collections\Criteria;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
use App\Validator\Constraints\NoLockout; use App\Validator\Constraints\NoLockout;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
@ -49,7 +50,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class Group extends AbstractStructuralDBElement implements HasPermissionsInterface class Group extends AbstractStructuralDBElement implements HasPermissionsInterface
{ {
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children; protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
@ -74,7 +75,7 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: GroupAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: GroupAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $attachments; protected Collection $attachments;
#[ORM\ManyToOne(targetEntity: GroupAttachment::class)] #[ORM\ManyToOne(targetEntity: GroupAttachment::class)]
@ -91,7 +92,7 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: GroupParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: GroupParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
public function __construct() public function __construct()

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
@ -267,7 +268,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
* @var Collection<int, UserAttachment> * @var Collection<int, UserAttachment>
*/ */
#[ORM\OneToMany(mappedBy: 'element', targetEntity: UserAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'element', targetEntity: UserAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['user:read', 'user:write'])] #[Groups(['user:read', 'user:write'])]
protected Collection $attachments; protected Collection $attachments;
@ -317,7 +318,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
protected ?PermissionData $permissions = null; protected ?PermissionData $permissions = null;
/** /**
* @var \DateTime|null the time until the password reset token is valid * @var \DateTimeInterface|null the time until the password reset token is valid
*/ */
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
protected ?\DateTime $pw_reset_expires = null; protected ?\DateTime $pw_reset_expires = null;

View file

@ -142,7 +142,7 @@ class AttachmentFormType extends AbstractType
if (!$file instanceof UploadedFile) { if (!$file instanceof UploadedFile) {
//When no file was uploaded, but a URL was entered, try to determine the attachment name from the URL //When no file was uploaded, but a URL was entered, try to determine the attachment name from the URL
if (empty($attachment->getName()) && !empty($attachment->getURL())) { if ((trim($attachment->getName()) === '') && ($attachment->getURL() !== null && $attachment->getURL() !== '')) {
$name = basename(parse_url($attachment->getURL(), PHP_URL_PATH)); $name = basename(parse_url($attachment->getURL(), PHP_URL_PATH));
$attachment->setName($name); $attachment->setName($name);
} }

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Form; namespace App\Form;
use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\AbstractTypeExtension;

View file

@ -45,9 +45,7 @@ class PermissionsType extends AbstractType
$resolver->setDefaults([ $resolver->setDefaults([
'show_legend' => true, 'show_legend' => true,
'show_presets' => false, 'show_presets' => false,
'show_dependency_notice' => static function (Options $options) { 'show_dependency_notice' => static fn(Options $options) => !$options['disabled'],
return !$options['disabled'];
},
'constraints' => static function (Options $options) { 'constraints' => static function (Options $options) {
if (!$options['disabled']) { if (!$options['disabled']) {
return [new NoLockout()]; return [new NoLockout()];

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Form\ProjectSystem; namespace App\Form\ProjectSystem;
use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\Project;

View file

@ -100,7 +100,7 @@ class StructuralEntityChoiceHelper
public function generateChoiceAttrCurrency(Currency $choice, Options|array $options): array public function generateChoiceAttrCurrency(Currency $choice, Options|array $options): array
{ {
$tmp = $this->generateChoiceAttr($choice, $options); $tmp = $this->generateChoiceAttr($choice, $options);
$symbol = empty($choice->getIsoCode()) ? null : Currencies::getSymbol($choice->getIsoCode()); $symbol = $choice->getIsoCode() === '' ? null : Currencies::getSymbol($choice->getIsoCode());
$tmp['data-short'] = $options['short'] ? $symbol : $choice->getName(); $tmp['data-short'] = $options['short'] ? $symbol : $choice->getName();
//Show entities that are not added to DB yet separately from other entities //Show entities that are not added to DB yet separately from other entities

View file

@ -52,11 +52,7 @@ class StructuralEntityChoiceLoader extends AbstractChoiceLoader
protected function loadChoices(): iterable protected function loadChoices(): iterable
{ {
//If the starting_element is set and not persisted yet, add it to the list //If the starting_element is set and not persisted yet, add it to the list
if ($this->starting_element !== null && $this->starting_element->getID() === null) { $tmp = $this->starting_element !== null && $this->starting_element->getID() === null ? [$this->starting_element] : [];
$tmp = [$this->starting_element];
} else {
$tmp = [];
}
if ($this->additional_element) { if ($this->additional_element) {
$tmp = $this->createNewEntitiesFromValue($this->additional_element); $tmp = $this->createNewEntitiesFromValue($this->additional_element);
@ -163,7 +159,7 @@ class StructuralEntityChoiceLoader extends AbstractChoiceLoader
// the same as the value that is generated for the same entity after it is persisted. // the same as the value that is generated for the same entity after it is persisted.
// Otherwise, errors occurs that the element could not be found. // Otherwise, errors occurs that the element could not be found.
foreach ($values as &$data) { foreach ($values as &$data) {
$data = trim($data); $data = trim((string) $data);
$data = preg_replace('/\s*->\s*/', '->', $data); $data = preg_replace('/\s*->\s*/', '->', $data);
} }
unset ($data); unset ($data);

View file

@ -108,12 +108,8 @@ class StructuralEntityType extends AbstractType
$resolver->setDefault('dto_value', null); $resolver->setDefault('dto_value', null);
$resolver->setAllowedTypes('dto_value', ['null', 'string']); $resolver->setAllowedTypes('dto_value', ['null', 'string']);
//If no help text is explicitly set, we use the dto value as help text and show it as html //If no help text is explicitly set, we use the dto value as help text and show it as html
$resolver->setDefault('help', function (Options $options) { $resolver->setDefault('help', fn(Options $options) => $this->dtoText($options['dto_value']));
return $this->dtoText($options['dto_value']); $resolver->setDefault('help_html', fn(Options $options) => $options['dto_value'] !== null);
});
$resolver->setDefault('help_html', function (Options $options) {
return $options['dto_value'] !== null;
});
$resolver->setDefault('attr', function (Options $options) { $resolver->setDefault('attr', function (Options $options) {
$tmp = [ $tmp = [

View file

@ -47,9 +47,9 @@ class FilenameSanatizer
'-', $filename); '-', $filename);
// avoids ".", ".." or ".hiddenFiles" // avoids ".", ".." or ".hiddenFiles"
$filename = ltrim($filename, '.-'); $filename = ltrim((string) $filename, '.-');
//Limit filename length to 255 bytes //Limit filename length to 255 bytes
$ext = pathinfo($filename, PATHINFO_EXTENSION); $ext = pathinfo($filename, PATHINFO_EXTENSION);
return mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext ? '.' . $ext : ''); return mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext !== '' && $ext !== '0' ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext !== '' && $ext !== '0' ? '.' . $ext : '');
} }
} }

View file

@ -174,11 +174,7 @@ final class ProjectBuildRequest
*/ */
public function getLotWithdrawAmount(PartLot|int $lot): float public function getLotWithdrawAmount(PartLot|int $lot): float
{ {
if ($lot instanceof PartLot) { $lot_id = $lot instanceof PartLot ? $lot->getID() : $lot;
$lot_id = $lot->getID();
} else { // Then it must be an int
$lot_id = $lot;
}
if (! array_key_exists($lot_id, $this->withdraw_amounts)) { if (! array_key_exists($lot_id, $this->withdraw_amounts)) {
throw new \InvalidArgumentException('The given lot is not in the withdraw amounts array!'); throw new \InvalidArgumentException('The given lot is not in the withdraw amounts array!');

View file

@ -26,6 +26,7 @@ namespace App\Helpers;
/** /**
* Helper functions for logic operations with trinary logic. * Helper functions for logic operations with trinary logic.
* True and false are represented as classical boolean values, undefined is represented as null. * True and false are represented as classical boolean values, undefined is represented as null.
* @see \App\Tests\Helpers\TrinaryLogicHelperTest
*/ */
class TrinaryLogicHelper class TrinaryLogicHelper
{ {

View file

@ -64,7 +64,7 @@ trait WithPermPresetsTrait
public function setContainer(ContainerInterface $container = null): void public function setContainer(ContainerInterface $container = null): void
{ {
if ($container) { if ($container !== null) {
$this->container = $container; $this->container = $container;
$this->permission_presets_helper = $container->get(PermissionPresetsHelper::class); $this->permission_presets_helper = $container->get(PermissionPresetsHelper::class);
} }

View file

@ -30,6 +30,7 @@ use Doctrine\ORM\Mapping\ClassMetadata;
/** /**
* @template TEntityClass of AttachmentContainingDBElement * @template TEntityClass of AttachmentContainingDBElement
* @extends NamedDBElementRepository<TEntityClass> * @extends NamedDBElementRepository<TEntityClass>
* @see \App\Tests\Repository\AttachmentContainingDBElementRepositoryTest
*/ */
class AttachmentContainingDBElementRepository extends NamedDBElementRepository class AttachmentContainingDBElementRepository extends NamedDBElementRepository
{ {

View file

@ -49,6 +49,7 @@ use ReflectionClass;
/** /**
* @template TEntityClass of AbstractDBElement * @template TEntityClass of AbstractDBElement
* @extends EntityRepository<TEntityClass> * @extends EntityRepository<TEntityClass>
* @see \App\Tests\Repository\DBElementRepositoryTest
*/ */
class DBElementRepository extends EntityRepository class DBElementRepository extends EntityRepository
{ {
@ -143,9 +144,7 @@ class DBElementRepository extends EntityRepository
*/ */
protected function sortResultArrayByIDArray(array &$result_array, array $ids): void protected function sortResultArrayByIDArray(array &$result_array, array $ids): void
{ {
usort($result_array, static function (AbstractDBElement $a, AbstractDBElement $b) use ($ids) { usort($result_array, static fn(AbstractDBElement $a, AbstractDBElement $b) => array_search($a->getID(), $ids, true) <=> array_search($b->getID(), $ids, true));
return array_search($a->getID(), $ids, true) <=> array_search($b->getID(), $ids, true);
});
} }
protected function setField(AbstractDBElement $element, string $field, int $new_value): void protected function setField(AbstractDBElement $element, string $field, int $new_value): void

View file

@ -29,6 +29,7 @@ use App\Helpers\Trees\TreeViewNode;
/** /**
* @template TEntityClass of AbstractNamedDBElement * @template TEntityClass of AbstractNamedDBElement
* @extends DBElementRepository<TEntityClass> * @extends DBElementRepository<TEntityClass>
* @see \App\Tests\Repository\NamedDBElementRepositoryTest
*/ */
class NamedDBElementRepository extends DBElementRepository class NamedDBElementRepository extends DBElementRepository
{ {

View file

@ -52,7 +52,7 @@ class StructuralDBElementRepository extends AttachmentContainingDBElementReposit
$qb->select('e') $qb->select('e')
->orderBy('NATSORT(e.name)', $nameOrdering); ->orderBy('NATSORT(e.name)', $nameOrdering);
if ($parent) { if ($parent !== null) {
$qb->where('e.parent = :parent') $qb->where('e.parent = :parent')
->setParameter('parent', $parent); ->setParameter('parent', $parent);
} else { } else {
@ -260,7 +260,7 @@ class StructuralDBElementRepository extends AttachmentContainingDBElementReposit
//Try to find if we already have an element cached for this name //Try to find if we already have an element cached for this name
$entity = $this->getNewEntityFromCache($name, null); $entity = $this->getNewEntityFromCache($name, null);
if ($entity) { if ($entity !== null) {
return $entity; return $entity;
} }

View file

@ -36,6 +36,7 @@ use Symfony\Component\Security\Core\User\UserInterface;
* @method User[] findAll() * @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @extends NamedDBElementRepository<User> * @extends NamedDBElementRepository<User>
* @see \App\Tests\Repository\UserRepositoryTest
*/ */
final class UserRepository extends NamedDBElementRepository implements PasswordUpgraderInterface final class UserRepository extends NamedDBElementRepository implements PasswordUpgraderInterface
{ {

View file

@ -44,12 +44,12 @@ class WebauthnKeyLastUseTwoFactorProvider implements TwoFactorProviderInterface
public function __construct( public function __construct(
#[AutowireDecorated] #[AutowireDecorated]
private TwoFactorProviderInterface $decorated, private readonly TwoFactorProviderInterface $decorated,
private EntityManagerInterface $entityManager, private readonly EntityManagerInterface $entityManager,
#[Autowire(service: 'jbtronics_webauthn_tfa.user_public_key_source_repo')] #[Autowire(service: 'jbtronics_webauthn_tfa.user_public_key_source_repo')]
private UserPublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, private readonly UserPublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository,
#[Autowire(service: 'jbtronics_webauthn_tfa.webauthn_provider')] #[Autowire(service: 'jbtronics_webauthn_tfa.webauthn_provider')]
private WebauthnProvider $webauthnProvider, private readonly WebauthnProvider $webauthnProvider,
) )
{ {
} }

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Serializer\APIPlatform; namespace App\Serializer\APIPlatform;
use ApiPlatform\Metadata\Exception\ResourceClassNotFoundException;
use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\IriConverterInterface;
use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Post;
@ -59,7 +60,7 @@ class DetermineTypeFromElementIRIDenormalizer implements DenormalizerInterface,
* @param array $input * @param array $input
* @param Operation $operation * @param Operation $operation
* @return array * @return array
* @throws \ApiPlatform\Metadata\Exception\ResourceClassNotFoundException * @throws ResourceClassNotFoundException
*/ */
private function addTypeDiscriminatorIfNecessary(array $input, Operation $operation): array private function addTypeDiscriminatorIfNecessary(array $input, Operation $operation): array
{ {

View file

@ -161,7 +161,7 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface, Norm
if (isset($data['supplier']) && $data['supplier'] !== "") { if (isset($data['supplier']) && $data['supplier'] !== "") {
$supplier = $this->locationDenormalizer->denormalize($data['supplier'], Supplier::class, $format, $context); $supplier = $this->locationDenormalizer->denormalize($data['supplier'], Supplier::class, $format, $context);
if ($supplier) { if ($supplier !== null) {
$orderdetail = new Orderdetail(); $orderdetail = new Orderdetail();
$orderdetail->setSupplier($supplier); $orderdetail->setSupplier($supplier);

View file

@ -139,12 +139,12 @@ class AttachmentPathResolver
} }
//If we have now have a placeholder left, the string is invalid: //If we have now have a placeholder left, the string is invalid:
if (preg_match('#%\w+%#', $placeholder_path)) { if (preg_match('#%\w+%#', (string) $placeholder_path)) {
return null; return null;
} }
//Path is invalid if path is directory traversal //Path is invalid if path is directory traversal
if (str_contains($placeholder_path, '..')) { if (str_contains((string) $placeholder_path, '..')) {
return null; return null;
} }
@ -183,7 +183,7 @@ class AttachmentPathResolver
} }
//If the new string does not begin with a placeholder, it is invalid //If the new string does not begin with a placeholder, it is invalid
if (!preg_match('#^%\w+%#', $real_path)) { if (!preg_match('#^%\w+%#', (string) $real_path)) {
return null; return null;
} }

View file

@ -300,7 +300,7 @@ class AttachmentSubmitHandler
return $attachment; return $attachment;
} }
$filename = basename($old_path); $filename = basename((string) $old_path);
//If the basename is not one of the new unique on, we have to save the old filename //If the basename is not one of the new unique on, we have to save the old filename
if (!preg_match('#\w+-\w{13}\.#', $filename)) { if (!preg_match('#\w+-\w{13}\.#', $filename)) {
//Save filename to attachment field //Save filename to attachment field
@ -378,7 +378,7 @@ class AttachmentSubmitHandler
//If we don't know filename yet, try to determine it out of url //If we don't know filename yet, try to determine it out of url
if ('' === $filename) { if ('' === $filename) {
$filename = basename(parse_url($url, PHP_URL_PATH)); $filename = basename(parse_url((string) $url, PHP_URL_PATH));
} }
//Set original file //Set original file

View file

@ -46,12 +46,11 @@ class ElementCacheTagGenerator
{ {
//Ensure that the given element is a class name //Ensure that the given element is a class name
if (is_object($element)) { if (is_object($element)) {
$element = get_class($element); $element = $element::class;
} else { //And that the class exists } elseif (!class_exists($element)) {
if (!class_exists($element)) { //And that the class exists
throw new \InvalidArgumentException("The given class '$element' does not exist!"); throw new \InvalidArgumentException("The given class '$element' does not exist!");
} }
}
//Check if the tag is already cached //Check if the tag is already cached
if (isset($this->cache[$element])) { if (isset($this->cache[$element])) {

View file

@ -134,7 +134,7 @@ class KiCadHelper
if ($this->category_depth >= 0) { if ($this->category_depth >= 0) {
//Ensure that the category is set //Ensure that the category is set
if (!$category) { if ($category === null) {
throw new NotFoundHttpException('Category must be set, if category_depth is greater than 1!'); throw new NotFoundHttpException('Category must be set, if category_depth is greater than 1!');
} }
@ -196,25 +196,25 @@ class KiCadHelper
//Add basic fields //Add basic fields
$result["fields"]["description"] = $this->createField($part->getDescription()); $result["fields"]["description"] = $this->createField($part->getDescription());
if ($part->getCategory()) { if ($part->getCategory() !== null) {
$result["fields"]["Category"] = $this->createField($part->getCategory()->getFullPath('/')); $result["fields"]["Category"] = $this->createField($part->getCategory()->getFullPath('/'));
} }
if ($part->getManufacturer()) { if ($part->getManufacturer() !== null) {
$result["fields"]["Manufacturer"] = $this->createField($part->getManufacturer()->getName()); $result["fields"]["Manufacturer"] = $this->createField($part->getManufacturer()->getName());
} }
if ($part->getManufacturerProductNumber() !== "") { if ($part->getManufacturerProductNumber() !== "") {
$result['fields']["MPN"] = $this->createField($part->getManufacturerProductNumber()); $result['fields']["MPN"] = $this->createField($part->getManufacturerProductNumber());
} }
if ($part->getManufacturingStatus()) { if ($part->getManufacturingStatus() !== null) {
$result["fields"]["Manufacturing Status"] = $this->createField( $result["fields"]["Manufacturing Status"] = $this->createField(
//Always use the english translation //Always use the english translation
$this->translator->trans($part->getManufacturingStatus()->toTranslationKey(), locale: 'en') $this->translator->trans($part->getManufacturingStatus()->toTranslationKey(), locale: 'en')
); );
} }
if ($part->getFootprint()) { if ($part->getFootprint() !== null) {
$result["fields"]["Part-DB Footprint"] = $this->createField($part->getFootprint()->getName()); $result["fields"]["Part-DB Footprint"] = $this->createField($part->getFootprint()->getName());
} }
if ($part->getPartUnit()) { if ($part->getPartUnit() !== null) {
$unit = $part->getPartUnit()->getName(); $unit = $part->getPartUnit()->getName();
if ($part->getPartUnit()->getUnit() !== "") { if ($part->getPartUnit()->getUnit() !== "") {
$unit .= ' ('.$part->getPartUnit()->getUnit().')'; $unit .= ' ('.$part->getPartUnit()->getUnit().')';
@ -225,7 +225,7 @@ class KiCadHelper
$result["fields"]["Mass"] = $this->createField($part->getMass() . ' g'); $result["fields"]["Mass"] = $this->createField($part->getMass() . ' g');
} }
$result["fields"]["Part-DB ID"] = $this->createField($part->getId()); $result["fields"]["Part-DB ID"] = $this->createField($part->getId());
if (!empty($part->getIpn())) { if ($part->getIpn() !== null && $part->getIpn() !== '' && $part->getIpn() !== '0') {
$result["fields"]["Part-DB IPN"] = $this->createField($part->getIpn()); $result["fields"]["Part-DB IPN"] = $this->createField($part->getIpn());
} }
@ -308,14 +308,9 @@ class KiCadHelper
)) { )) {
return true; return true;
} }
//And on the footprint //And on the footprint
if ($part->getFootprint() && $part->getFootprint()->getEdaInfo()->getKicadFootprint() !== null) {
return true;
}
//Otherwise the part should be not visible //Otherwise the part should be not visible
return false; return $part->getFootprint() && $part->getFootprint()->getEdaInfo()->getKicadFootprint() !== null;
} }
/** /**

View file

@ -69,7 +69,7 @@ class EntityMerger
{ {
$merger = $this->findMergerForObject($target, $other, $context); $merger = $this->findMergerForObject($target, $other, $context);
if ($merger === null) { if ($merger === null) {
throw new \RuntimeException('No merger found for merging '.get_class($other).' into '.get_class($target)); throw new \RuntimeException('No merger found for merging '.$other::class.' into '.$target::class);
} }
return $merger->merge($target, $other, $context); return $merger->merge($target, $other, $context);
} }

View file

@ -85,9 +85,7 @@ trait EntityMergerHelperTrait
protected function useOtherValueIfNotNull(object $target, object $other, string $field): object protected function useOtherValueIfNotNull(object $target, object $other, string $field): object
{ {
return $this->useCallback( return $this->useCallback(
function ($target_value, $other_value) { fn($target_value, $other_value) => $target_value ?? $other_value,
return $target_value ?? $other_value;
},
$target, $target,
$other, $other,
$field $field
@ -106,9 +104,7 @@ trait EntityMergerHelperTrait
protected function useOtherValueIfNotEmtpy(object $target, object $other, string $field): object protected function useOtherValueIfNotEmtpy(object $target, object $other, string $field): object
{ {
return $this->useCallback( return $this->useCallback(
function ($target_value, $other_value) { fn($target_value, $other_value) => empty($target_value) ? $other_value : $target_value,
return empty($target_value) ? $other_value : $target_value;
},
$target, $target,
$other, $other,
$field $field
@ -126,9 +122,7 @@ trait EntityMergerHelperTrait
protected function useLargerValue(object $target, object $other, string $field): object protected function useLargerValue(object $target, object $other, string $field): object
{ {
return $this->useCallback( return $this->useCallback(
function ($target_value, $other_value) { fn($target_value, $other_value) => max($target_value, $other_value),
return max($target_value, $other_value);
},
$target, $target,
$other, $other,
$field $field
@ -146,9 +140,7 @@ trait EntityMergerHelperTrait
protected function useSmallerValue(object $target, object $other, string $field): object protected function useSmallerValue(object $target, object $other, string $field): object
{ {
return $this->useCallback( return $this->useCallback(
function ($target_value, $other_value) { fn($target_value, $other_value) => min($target_value, $other_value),
return min($target_value, $other_value);
},
$target, $target,
$other, $other,
$field $field
@ -166,9 +158,7 @@ trait EntityMergerHelperTrait
protected function useTrueValue(object $target, object $other, string $field): object protected function useTrueValue(object $target, object $other, string $field): object
{ {
return $this->useCallback( return $this->useCallback(
function (bool $target_value, bool $other_value): bool { fn(bool $target_value, bool $other_value): bool => $target_value || $other_value,
return $target_value || $other_value;
},
$target, $target,
$other, $other,
$field $field
@ -232,11 +222,9 @@ trait EntityMergerHelperTrait
continue 2; continue 2;
} }
} }
} else { } elseif ($target_collection->contains($item)) {
if ($target_collection->contains($item)) {
continue; continue;
} }
}
$clones[] = clone $item; $clones[] = clone $item;
} }
@ -257,11 +245,9 @@ trait EntityMergerHelperTrait
*/ */
protected function mergeAttachments(AttachmentContainingDBElement $target, AttachmentContainingDBElement $other): object protected function mergeAttachments(AttachmentContainingDBElement $target, AttachmentContainingDBElement $other): object
{ {
return $this->mergeCollections($target, $other, 'attachments', function (Attachment $t, Attachment $o): bool { return $this->mergeCollections($target, $other, 'attachments', fn(Attachment $t, Attachment $o): bool => $t->getName() === $o->getName()
return $t->getName() === $o->getName()
&& $t->getAttachmentType() === $o->getAttachmentType() && $t->getAttachmentType() === $o->getAttachmentType()
&& $t->getPath() === $o->getPath(); && $t->getPath() === $o->getPath());
});
} }
/** /**
@ -272,16 +258,14 @@ trait EntityMergerHelperTrait
*/ */
protected function mergeParameters(AbstractStructuralDBElement|Part $target, AbstractStructuralDBElement|Part $other): object protected function mergeParameters(AbstractStructuralDBElement|Part $target, AbstractStructuralDBElement|Part $other): object
{ {
return $this->mergeCollections($target, $other, 'parameters', function (AbstractParameter $t, AbstractParameter $o): bool { return $this->mergeCollections($target, $other, 'parameters', fn(AbstractParameter $t, AbstractParameter $o): bool => $t->getName() === $o->getName()
return $t->getName() === $o->getName()
&& $t->getSymbol() === $o->getSymbol() && $t->getSymbol() === $o->getSymbol()
&& $t->getUnit() === $o->getUnit() && $t->getUnit() === $o->getUnit()
&& $t->getValueMax() === $o->getValueMax() && $t->getValueMax() === $o->getValueMax()
&& $t->getValueMin() === $o->getValueMin() && $t->getValueMin() === $o->getValueMin()
&& $t->getValueTypical() === $o->getValueTypical() && $t->getValueTypical() === $o->getValueTypical()
&& $t->getValueText() === $o->getValueText() && $t->getValueText() === $o->getValueText()
&& $t->getGroup() === $o->getGroup(); && $t->getGroup() === $o->getGroup());
});
} }
/** /**

View file

@ -33,6 +33,7 @@ use App\Entity\PriceInformations\Orderdetail;
* This class merges two parts together. * This class merges two parts together.
* *
* @implements EntityMergerInterface<Part> * @implements EntityMergerInterface<Part>
* @see \App\Tests\Services\EntityMergers\Mergers\PartMergerTest
*/ */
class PartMerger implements EntityMergerInterface class PartMerger implements EntityMergerInterface
{ {
@ -99,7 +100,7 @@ class PartMerger implements EntityMergerInterface
return $target; return $target;
} }
private static function comparePartAssociations(PartAssociation $t, PartAssociation $o): bool { private function comparePartAssociations(PartAssociation $t, PartAssociation $o): bool {
//We compare the translation keys, as it contains info about the type and other type info //We compare the translation keys, as it contains info about the type and other type info
return $t->getOther() === $o->getOther() return $t->getOther() === $o->getOther()
&& $t->getTypeTranslationKey() === $o->getTypeTranslationKey(); && $t->getTypeTranslationKey() === $o->getTypeTranslationKey();
@ -117,7 +118,7 @@ class PartMerger implements EntityMergerInterface
$this->mergeParameters($target, $other); $this->mergeParameters($target, $other);
//Merge the associations //Merge the associations
$this->mergeCollections($target, $other, 'associated_parts_as_owner', self::comparePartAssociations(...)); $this->mergeCollections($target, $other, 'associated_parts_as_owner', $this->comparePartAssociations(...));
//We have to recreate the associations towards the other part, as they are not created by the merger //We have to recreate the associations towards the other part, as they are not created by the merger
foreach ($other->getAssociatedPartsAsOther() as $association) { foreach ($other->getAssociatedPartsAsOther() as $association) {
@ -131,7 +132,7 @@ class PartMerger implements EntityMergerInterface
} }
//Ensure that the association is not already present //Ensure that the association is not already present
foreach ($owner->getAssociatedPartsAsOwner() as $existing_association) { foreach ($owner->getAssociatedPartsAsOwner() as $existing_association) {
if (self::comparePartAssociations($existing_association, $clone)) { if ($this->comparePartAssociations($existing_association, $clone)) {
continue 2; continue 2;
} }
} }

View file

@ -360,11 +360,7 @@ class EntityURLGenerator
*/ */
protected function mapToController(array $map, string|AbstractDBElement $entity): string protected function mapToController(array $map, string|AbstractDBElement $entity): string
{ {
if (is_string($entity)) { //If a class name was already passed, then use it directly $class = is_string($entity) ? $entity : $entity::class;
$class = $entity;
} else { //Otherwise get the class name from the entity
$class = $entity::class;
}
//Check if we have an direct mapping for the given class //Check if we have an direct mapping for the given class
if (!array_key_exists($class, $map)) { if (!array_key_exists($class, $map)) {

View file

@ -116,7 +116,7 @@ class PKOptionalImporter
//All imported users get assigned to the "PartKeepr Users" group //All imported users get assigned to the "PartKeepr Users" group
$group_users = $this->em->find(Group::class, 3); $group_users = $this->em->find(Group::class, 3);
$group = $this->em->getRepository(Group::class)->findOneBy(['name' => 'PartKeepr Users', 'parent' => $group_users]); $group = $this->em->getRepository(Group::class)->findOneBy(['name' => 'PartKeepr Users', 'parent' => $group_users]);
if (!$group) { if ($group === null) {
$group = new Group(); $group = new Group();
$group->setName('PartKeepr Users'); $group->setName('PartKeepr Users');
$group->setParent($group_users); $group->setParent($group_users);

View file

@ -218,7 +218,7 @@ class PKPartImporter
'iso_code' => $currency_iso_code, 'iso_code' => $currency_iso_code,
]); ]);
if (!$currency) { if ($currency === null) {
$currency = new Currency(); $currency = new Currency();
$currency->setIsoCode($currency_iso_code); $currency->setIsoCode($currency_iso_code);
$currency->setName(Currencies::getName($currency_iso_code)); $currency->setName(Currencies::getName($currency_iso_code));
@ -265,7 +265,7 @@ class PKPartImporter
]); ]);
//When no orderdetail exists, create one //When no orderdetail exists, create one
if (!$orderdetail) { if ($orderdetail === null) {
$orderdetail = new Orderdetail(); $orderdetail = new Orderdetail();
$orderdetail->setSupplier($supplier); $orderdetail->setSupplier($supplier);
$orderdetail->setSupplierpartnr($spn); $orderdetail->setSupplierpartnr($spn);

View file

@ -26,6 +26,7 @@ namespace App\Services\InfoProviderSystem\DTOs;
/** /**
* This DTO represents a file that can be downloaded from a URL. * This DTO represents a file that can be downloaded from a URL.
* This could be a datasheet, a 3D model, a picture or similar. * This could be a datasheet, a 3D model, a picture or similar.
* @see \App\Tests\Services\InfoProviderSystem\DTOs\FileDTOTest
*/ */
class FileDTO class FileDTO
{ {

View file

@ -26,6 +26,7 @@ namespace App\Services\InfoProviderSystem\DTOs;
/** /**
* This DTO represents a parameter of a part (similar to the AbstractParameter entity). * This DTO represents a parameter of a part (similar to the AbstractParameter entity).
* This could be a voltage, a current, a temperature or similar. * This could be a voltage, a current, a temperature or similar.
* @see \App\Tests\Services\InfoProviderSystem\DTOs\ParameterDTOTest
*/ */
class ParameterDTO class ParameterDTO
{ {
@ -76,7 +77,7 @@ class ParameterDTO
$parts = preg_split('/\s*(\.{3}|~)\s*/', $value); $parts = preg_split('/\s*(\.{3}|~)\s*/', $value);
if (count($parts) === 2) { if (count($parts) === 2) {
//Try to extract number and unit from value (allow leading +) //Try to extract number and unit from value (allow leading +)
if (empty($unit)) { if ($unit === null || trim($unit) === '') {
[$number, $unit] = self::splitIntoValueAndUnit(ltrim($parts[0], " +")) ?? [$parts[0], null]; [$number, $unit] = self::splitIntoValueAndUnit(ltrim($parts[0], " +")) ?? [$parts[0], null];
} else { } else {
$number = $parts[0]; $number = $parts[0];

View file

@ -25,6 +25,7 @@ namespace App\Services\InfoProviderSystem\DTOs;
/** /**
* This DTO represents a purchase information for a part (supplier name, order number and prices). * This DTO represents a purchase information for a part (supplier name, order number and prices).
* @see \App\Tests\Services\InfoProviderSystem\DTOs\PurchaseInfoDTOTest
*/ */
class PurchaseInfoDTO class PurchaseInfoDTO
{ {

View file

@ -27,6 +27,7 @@ use App\Entity\Parts\ManufacturingStatus;
/** /**
* This DTO represents a search result for a part. * This DTO represents a search result for a part.
* @see \App\Tests\Services\InfoProviderSystem\DTOs\SearchResultDTOTest
*/ */
class SearchResultDTO class SearchResultDTO
{ {

View file

@ -45,6 +45,7 @@ use Doctrine\ORM\EntityManagerInterface;
/** /**
* This class converts DTOs to entities which can be persisted in the DB * This class converts DTOs to entities which can be persisted in the DB
* @see \App\Tests\Services\InfoProviderSystem\DTOtoEntityConverterTest
*/ */
final class DTOtoEntityConverter final class DTOtoEntityConverter
{ {
@ -127,7 +128,7 @@ final class DTOtoEntityConverter
$entity->setAttachmentType($type); $entity->setAttachmentType($type);
//If no name is given, try to extract the name from the URL //If no name is given, try to extract the name from the URL
if (empty($dto->name)) { if ($dto->name === null || $dto->name === '' || $dto->name === '0') {
$entity->setName($this->getAttachmentNameFromURL($dto->url)); $entity->setName($this->getAttachmentNameFromURL($dto->url));
} else { } else {
$entity->setName($dto->name); $entity->setName($dto->name);

View file

@ -27,6 +27,7 @@ use App\Services\InfoProviderSystem\Providers\InfoProviderInterface;
/** /**
* This class keeps track of all registered info providers and allows to find them by their key * This class keeps track of all registered info providers and allows to find them by their key
* @see \App\Tests\Services\InfoProviderSystem\ProviderRegistryTest
*/ */
final class ProviderRegistry final class ProviderRegistry
{ {

View file

@ -93,7 +93,7 @@ class DigikeyProvider implements InfoProviderInterface
public function isActive(): bool public function isActive(): bool
{ {
//The client ID has to be set and a token has to be available (user clicked connect) //The client ID has to be set and a token has to be available (user clicked connect)
return !empty($this->clientId) && $this->authTokenManager->hasToken(self::OAUTH_APP_NAME); return $this->clientId !== '' && $this->authTokenManager->hasToken(self::OAUTH_APP_NAME);
} }
public function searchByKeyword(string $keyword): array public function searchByKeyword(string $keyword): array
@ -210,7 +210,7 @@ class DigikeyProvider implements InfoProviderInterface
$footprint_name = $parameter['Value']; $footprint_name = $parameter['Value'];
} }
if (in_array(trim($parameter['Value']), array('', '-'), true)) { if (in_array(trim((string) $parameter['Value']), ['', '-'], true)) {
continue; continue;
} }

View file

@ -65,7 +65,7 @@ class Element14Provider implements InfoProviderInterface
public function isActive(): bool public function isActive(): bool
{ {
return !empty($this->api_key); return $this->api_key !== '';
} }
/** /**

View file

@ -96,7 +96,7 @@ class LCSCProvider implements InfoProviderInterface
*/ */
private function getRealDatasheetUrl(?string $url): string private function getRealDatasheetUrl(?string $url): string
{ {
if (!empty($url) && preg_match("/^https:\/\/(datasheet\.lcsc\.com|www\.lcsc\.com\/datasheet)\/.*(C\d+)\.pdf$/", $url, $matches) > 0) { if ($url !== null && trim($url) !== '' && preg_match("/^https:\/\/(datasheet\.lcsc\.com|www\.lcsc\.com\/datasheet)\/.*(C\d+)\.pdf$/", $url, $matches) > 0) {
$response = $this->lcscClient->request('GET', $url, [ $response = $this->lcscClient->request('GET', $url, [
'headers' => [ 'headers' => [
'Referer' => 'https://www.lcsc.com/product-detail/_' . $matches[2] . '.html' 'Referer' => 'https://www.lcsc.com/product-detail/_' . $matches[2] . '.html'
@ -139,7 +139,7 @@ class LCSCProvider implements InfoProviderInterface
// LCSC does not display LCSC codes in the search, instead taking you directly to the // LCSC does not display LCSC codes in the search, instead taking you directly to the
// detailed product listing. It does so utilizing a product tip field. // detailed product listing. It does so utilizing a product tip field.
// If product tip exists and there are no products in the product list try a detail query // If product tip exists and there are no products in the product list try a detail query
if (count($products) === 0 && !($tipProductCode === null)) { if (count($products) === 0 && $tipProductCode !== null) {
$result[] = $this->queryDetail($tipProductCode); $result[] = $this->queryDetail($tipProductCode);
} }
@ -174,11 +174,11 @@ class LCSCProvider implements InfoProviderInterface
{ {
// Get product images in advance // Get product images in advance
$product_images = $this->getProductImages($product['productImages'] ?? null); $product_images = $this->getProductImages($product['productImages'] ?? null);
$product['productImageUrl'] = $product['productImageUrl'] ?? null; $product['productImageUrl'] ??= null;
// If the product does not have a product image but otherwise has attached images, use the first one. // If the product does not have a product image but otherwise has attached images, use the first one.
if (count($product_images) > 0) { if (count($product_images) > 0) {
$product['productImageUrl'] = $product['productImageUrl'] ?? $product_images[0]->url; $product['productImageUrl'] ??= $product_images[0]->url;
} }
// LCSC puts HTML in footprints and descriptions sometimes randomly // LCSC puts HTML in footprints and descriptions sometimes randomly
@ -321,7 +321,7 @@ class LCSCProvider implements InfoProviderInterface
foreach ($attributes as $attribute) { foreach ($attributes as $attribute) {
//Skip this attribute if it's empty //Skip this attribute if it's empty
if (in_array(trim($attribute['paramValueEn']), array('', '-'), true)) { if (in_array(trim((string) $attribute['paramValueEn']), ['', '-'], true)) {
continue; continue;
} }

View file

@ -74,7 +74,7 @@ class MouserProvider implements InfoProviderInterface
public function isActive(): bool public function isActive(): bool
{ {
return !empty($this->api_key); return $this->api_key !== '';
} }
public function searchByKeyword(string $keyword): array public function searchByKeyword(string $keyword): array
@ -247,7 +247,7 @@ class MouserProvider implements InfoProviderInterface
private function parseDataSheets(?string $sheetUrl, ?string $sheetName): ?array private function parseDataSheets(?string $sheetUrl, ?string $sheetName): ?array
{ {
if (empty($sheetUrl)) { if ($sheetUrl === null || $sheetUrl === '' || $sheetUrl === '0') {
return null; return null;
} }
$result = []; $result = [];

View file

@ -183,7 +183,7 @@ class OctopartProvider implements InfoProviderInterface
{ {
//The client ID has to be set and a token has to be available (user clicked connect) //The client ID has to be set and a token has to be available (user clicked connect)
//return /*!empty($this->clientId) && */ $this->authTokenManager->hasToken(self::OAUTH_APP_NAME); //return /*!empty($this->clientId) && */ $this->authTokenManager->hasToken(self::OAUTH_APP_NAME);
return !empty($this->clientId) && !empty($this->secret); return $this->clientId !== '' && $this->secret !== '';
} }
private function mapLifeCycleStatus(?string $value): ?ManufacturingStatus private function mapLifeCycleStatus(?string $value): ?ManufacturingStatus
@ -243,11 +243,14 @@ class OctopartProvider implements InfoProviderInterface
//If we encounter the mass spec, we save it for later //If we encounter the mass spec, we save it for later
if ($spec['attribute']['shortname'] === "weight") { if ($spec['attribute']['shortname'] === "weight") {
$mass = (float) $spec['siValue']; $mass = (float) $spec['siValue'];
} else if ($spec['attribute']['shortname'] === "case_package") { //Package } elseif ($spec['attribute']['shortname'] === "case_package") {
//Package
$package = $spec['value']; $package = $spec['value'];
} else if ($spec['attribute']['shortname'] === "numberofpins") { //Pin Count } elseif ($spec['attribute']['shortname'] === "numberofpins") {
//Pin Count
$pinCount = $spec['value']; $pinCount = $spec['value'];
} else if ($spec['attribute']['shortname'] === "lifecyclestatus") { //LifeCycleStatus } elseif ($spec['attribute']['shortname'] === "lifecyclestatus") {
//LifeCycleStatus
$mStatus = $this->mapLifeCycleStatus($spec['value']); $mStatus = $this->mapLifeCycleStatus($spec['value']);
} }
@ -295,7 +298,7 @@ class OctopartProvider implements InfoProviderInterface
$category = null; $category = null;
if (!empty($part['category']['name'])) { if (!empty($part['category']['name'])) {
$category = implode(' -> ', array_map(static fn($c) => $c['name'], $part['category']['ancestors'] ?? [])); $category = implode(' -> ', array_map(static fn($c) => $c['name'], $part['category']['ancestors'] ?? []));
if (!empty($category)) { if ($category !== '' && $category !== '0') {
$category .= ' -> '; $category .= ' -> ';
} }
$category .= $part['category']['name']; $category .= $part['category']['name'];

View file

@ -47,7 +47,7 @@ class TMEClient
public function isUsable(): bool public function isUsable(): bool
{ {
return !($this->token === '' || $this->secret === ''); return $this->token !== '' && $this->secret !== '';
} }

View file

@ -80,7 +80,7 @@ class TMEProvider implements InfoProviderInterface
$result[] = new SearchResultDTO( $result[] = new SearchResultDTO(
provider_key: $this->getProviderKey(), provider_key: $this->getProviderKey(),
provider_id: $product['Symbol'], provider_id: $product['Symbol'],
name: !empty($product['OriginalSymbol']) ? $product['OriginalSymbol'] : $product['Symbol'], name: empty($product['OriginalSymbol']) ? $product['Symbol'] : $product['OriginalSymbol'],
description: $product['Description'], description: $product['Description'],
category: $product['Category'], category: $product['Category'],
manufacturer: $product['Producer'], manufacturer: $product['Producer'],
@ -116,7 +116,7 @@ class TMEProvider implements InfoProviderInterface
return new PartDetailDTO( return new PartDetailDTO(
provider_key: $this->getProviderKey(), provider_key: $this->getProviderKey(),
provider_id: $product['Symbol'], provider_id: $product['Symbol'],
name: !empty($product['OriginalSymbol']) ? $product['OriginalSymbol'] : $product['Symbol'], name: empty($product['OriginalSymbol']) ? $product['Symbol'] : $product['OriginalSymbol'],
description: $product['Description'], description: $product['Description'],
category: $product['Category'], category: $product['Category'],
manufacturer: $product['Producer'], manufacturer: $product['Producer'],

View file

@ -28,6 +28,7 @@ use Com\Tecnick\Barcode\Barcode;
/** /**
* This function is used to generate barcodes of various types using arbitrary (text) content. * This function is used to generate barcodes of various types using arbitrary (text) content.
* @see \App\Tests\Services\LabelSystem\Barcodes\BarcodeHelperTest
*/ */
class BarcodeHelper class BarcodeHelper
{ {
@ -66,7 +67,7 @@ class BarcodeHelper
{ {
$svg = $this->barcodeAsSVG($content, $type); $svg = $this->barcodeAsSVG($content, $type);
$base64 = $this->dataUri($svg, 'image/svg+xml'); $base64 = $this->dataUri($svg, 'image/svg+xml');
$alt_text = $alt_text ?? $content; $alt_text ??= $content;
return '<img src="'.$base64.'" width="'.$width.'" style="min-height: 25px;" alt="'.$alt_text.'"/>'; return '<img src="'.$base64.'" width="'.$width.'" style="min-height: 25px;" alt="'.$alt_text.'"/>';
} }

View file

@ -48,7 +48,7 @@ use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException; use InvalidArgumentException;
/** /**
* @see \App\Tests\Services\LabelSystem\Barcodes\BarcodeNormalizerTest * @see \App\Tests\Services\LabelSystem\Barcodes\BarcodeScanHelperTest
*/ */
final class BarcodeScanHelper final class BarcodeScanHelper
{ {

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Services\LabelSystem; namespace App\Services\LabelSystem;
use Dompdf\Dompdf; use Dompdf\Dompdf;
@ -36,12 +38,10 @@ class DompdfFactory implements DompdfFactoryInterface
private function createDirectoryIfNotExisting(string $path): void private function createDirectoryIfNotExisting(string $path): void
{ {
if (!is_dir($path)) { if (!is_dir($path) && (!mkdir($concurrentDirectory = $path, 0777, true) && !is_dir($concurrentDirectory))) {
if (!mkdir($concurrentDirectory = $path, 0777, true) && !is_dir($concurrentDirectory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory)); throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
} }
} }
}
public function create(): Dompdf public function create(): Dompdf
{ {

View file

@ -49,7 +49,7 @@ use App\Services\LabelSystem\Barcodes\BarcodeHelper;
use InvalidArgumentException; use InvalidArgumentException;
/** /**
* @see \App\Tests\Services\LabelSystem\BarcodeGeneratorTest * @see \App\Tests\Services\LabelSystem\LabelBarcodeGeneratorTest
*/ */
final class LabelBarcodeGenerator final class LabelBarcodeGenerator
{ {

View file

@ -119,7 +119,7 @@ final class PartProvider implements PlaceholderProviderInterface
} }
if ('[[DESCRIPTION_T]]' === $placeholder) { if ('[[DESCRIPTION_T]]' === $placeholder) {
return strip_tags($parsedown->line($part->getDescription())); return strip_tags((string) $parsedown->line($part->getDescription()));
} }
if ('[[COMMENT]]' === $placeholder) { if ('[[COMMENT]]' === $placeholder) {
@ -127,7 +127,7 @@ final class PartProvider implements PlaceholderProviderInterface
} }
if ('[[COMMENT_T]]' === $placeholder) { if ('[[COMMENT_T]]' === $placeholder) {
return strip_tags($parsedown->line($part->getComment())); return strip_tags((string) $parsedown->line($part->getComment()));
} }
return null; return null;

View file

@ -52,7 +52,7 @@ final class StructuralDBElementProvider implements PlaceholderProviderInterface
return $label_target->getComment(); return $label_target->getComment();
} }
if ('[[COMMENT_T]]' === $placeholder) { if ('[[COMMENT_T]]' === $placeholder) {
return strip_tags($label_target->getComment()); return strip_tags((string) $label_target->getComment());
} }
if ('[[FULL_PATH]]' === $placeholder) { if ('[[FULL_PATH]]' === $placeholder) {
return $label_target->getFullPath(); return $label_target->getFullPath();

View file

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
* *
@ -17,7 +20,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Services\LogSystem; namespace App\Services\LogSystem;
use InvalidArgumentException; use InvalidArgumentException;

View file

@ -135,7 +135,7 @@ class LogEntryExtraFormatter
} }
if ($context instanceof LogWithCommentInterface && $context->hasComment()) { if ($context instanceof LogWithCommentInterface && $context->hasComment()) {
$array[] = htmlspecialchars($context->getComment()); $array[] = htmlspecialchars((string) $context->getComment());
} }
if ($context instanceof ElementCreatedLogEntry && $context->hasCreationInstockValue()) { if ($context instanceof ElementCreatedLogEntry && $context->hasCreationInstockValue()) {
@ -193,7 +193,7 @@ class LogEntryExtraFormatter
htmlspecialchars($this->elementTypeNameGenerator->getLocalizedTypeLabel(PartLot::class)) htmlspecialchars($this->elementTypeNameGenerator->getLocalizedTypeLabel(PartLot::class))
.' ' . $context->getMoveToTargetID(); .' ' . $context->getMoveToTargetID();
} }
if ($context->getActionTimestamp()) { if ($context->getActionTimestamp() !== null) {
$formatter = new \IntlDateFormatter($this->translator->getLocale(), \IntlDateFormatter::SHORT, \IntlDateFormatter::SHORT); $formatter = new \IntlDateFormatter($this->translator->getLocale(), \IntlDateFormatter::SHORT, \IntlDateFormatter::SHORT);
$array['log.part_stock_changed.timestamp'] = $formatter->format($context->getActionTimestamp()); $array['log.part_stock_changed.timestamp'] = $formatter->format($context->getActionTimestamp());
} }

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