mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Fixed some inspection issues
This commit is contained in:
parent
33475dca66
commit
42e604245c
85 changed files with 272 additions and 291 deletions
|
@ -30,8 +30,9 @@ use Symfony\Component\PropertyInfo\Type;
|
|||
|
||||
class EntityFilterHelper
|
||||
{
|
||||
public function __construct(private NodesListBuilder $nodesListBuilder,
|
||||
private EntityManagerInterface $entityManager)
|
||||
public function __construct(
|
||||
private readonly NodesListBuilder $nodesListBuilder,
|
||||
private readonly EntityManagerInterface $entityManager)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -86,7 +87,7 @@ class EntityFilterHelper
|
|||
|
||||
$description = [];
|
||||
foreach ($properties as $property => $strategy) {
|
||||
$description["$property"] = [
|
||||
$description[(string)$property] = [
|
||||
'property' => $property,
|
||||
'type' => Type::BUILTIN_TYPE_STRING,
|
||||
'required' => false,
|
||||
|
|
|
@ -62,7 +62,7 @@ final class LikeFilter extends AbstractFilter
|
|||
|
||||
$description = [];
|
||||
foreach ($this->properties as $property => $strategy) {
|
||||
$description["$property"] = [
|
||||
$description[(string)$property] = [
|
||||
'property' => $property,
|
||||
'type' => Type::BUILTIN_TYPE_STRING,
|
||||
'required' => false,
|
||||
|
|
|
@ -62,8 +62,6 @@ final class HandleAttachmentsUploadsProcessor implements ProcessorInterface
|
|||
$this->attachmentSubmitHandler->handleUpload($data, $upload);
|
||||
}
|
||||
|
||||
$result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
|
||||
|
||||
return $result;
|
||||
return $this->persistProcessor->process($data, $operation, $uriVariables, $context);
|
||||
}
|
||||
}
|
|
@ -55,7 +55,7 @@ class AttachmentTypeController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'attachment_type_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'attachment_type_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(AttachmentType $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -259,10 +259,6 @@ abstract class BaseAdminController extends AbstractController
|
|||
$attachments = $form['attachments'];
|
||||
foreach ($attachments as $attachment) {
|
||||
/** @var FormInterface $attachment */
|
||||
$options = [
|
||||
'secure_attachment' => $attachment['secureFile']->getData(),
|
||||
'download_url' => $attachment['downloadURL']->getData(),
|
||||
];
|
||||
|
||||
try {
|
||||
$this->attachmentSubmitHandler->handleUpload(
|
||||
|
|
|
@ -54,7 +54,7 @@ class CategoryController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'category_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'category_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(Category $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -124,7 +124,7 @@ class CurrencyController extends BaseAdminController
|
|||
return true;
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'currency_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'currency_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(Currency $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ class FootprintController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'footprint_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'footprint_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(Footprint $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ class LabelProfileController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'label_profile_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'label_profile_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(LabelProfile $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@ class ManufacturerController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'manufacturer_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'manufacturer_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(Manufacturer $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ class MeasurementUnitController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'measurement_unit_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'measurement_unit_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(MeasurementUnit $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -51,7 +51,7 @@ class ProjectAdminController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'project_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'project_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}/edit', requirements: ['id' => '\d+'])]
|
||||
public function edit(Project $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@ class StorageLocationController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'store_location_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'store_location_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(StorageLocation $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@ class SupplierController extends BaseAdminController
|
|||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'supplier_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'supplier_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', requirements: ['id' => '\d+'])]
|
||||
public function edit(Supplier $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -49,7 +49,7 @@ class GroupController extends BaseAdminController
|
|||
protected string $attachment_class = GroupAttachment::class;
|
||||
protected ?string $parameter_class = GroupParameter::class;
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'group_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'group_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}/', requirements: ['id' => '\d+'])]
|
||||
public function edit(Group $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper, PermissionSchemaUpdater $permissionSchemaUpdater, ?string $timestamp = null): Response
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ class RedirectController extends AbstractController
|
|||
|
||||
//If either mod_rewrite is not enabled or the index.php version is enforced, add index.php to the string
|
||||
if (($this->enforce_index_php || !$this->checkIfModRewriteAvailable())
|
||||
&& !str_contains((string) $new_url, 'index.php')) {
|
||||
&& !str_contains($new_url, 'index.php')) {
|
||||
//Like Request::getUriForPath only with index.php
|
||||
$new_url = $request->getSchemeAndHttpHost().$request->getBaseUrl().'/index.php/'.$locale.$request->getPathInfo();
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ class ToolsController extends AbstractController
|
|||
$this->denyAccessUnlessGranted('@tools.builtin_footprints_viewer');
|
||||
|
||||
$grouped_footprints = $builtinAttachmentsFinder->getListOfFootprintsGroupedByFolder();
|
||||
$grouped_footprints = array_map(fn($group) => array_map(fn($placeholder_filepath) => [
|
||||
$grouped_footprints = array_map(static fn($group) => array_map(static fn($placeholder_filepath) => [
|
||||
'filename' => basename((string) $placeholder_filepath),
|
||||
'assets_path' => $urlGenerator->placeholderPathToAssetPath($placeholder_filepath),
|
||||
], $group), $grouped_footprints);
|
||||
|
|
|
@ -78,7 +78,7 @@ class UserController extends BaseAdminController
|
|||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Route(path: '/{id}/edit/{timestamp}', requirements: ['id' => '\d+'], name: 'user_edit')]
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'user_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}/', requirements: ['id' => '\d+'])]
|
||||
public function edit(User $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper,
|
||||
PermissionSchemaUpdater $permissionSchemaUpdater, ValidatorInterface $validator, ?string $timestamp = null): Response
|
||||
|
@ -166,7 +166,7 @@ class UserController extends BaseAdminController
|
|||
return $this->_new($request, $em, $importer, $entity);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}', name: 'user_delete', methods: ['DELETE'], requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}', name: 'user_delete', requirements: ['id' => '\d+'], methods: ['DELETE'])]
|
||||
public function delete(Request $request, User $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse
|
||||
{
|
||||
//Disallow deleting the anonymous user
|
||||
|
|
|
@ -221,7 +221,7 @@ final class AttachmentDataTable implements DataTableTypeInterface
|
|||
//We do the most stuff here in the filter class
|
||||
if (isset($options['filter'])) {
|
||||
if(!$options['filter'] instanceof AttachmentFilter) {
|
||||
throw new \Exception('filter must be an instance of AttachmentFilter!');
|
||||
throw new \RuntimeException('filter must be an instance of AttachmentFilter!');
|
||||
}
|
||||
|
||||
$filter = $options['filter'];
|
||||
|
|
|
@ -35,9 +35,9 @@ class MarkdownColumn extends AbstractColumn
|
|||
* The normalize function is responsible for converting parsed and processed data to a datatables-appropriate type.
|
||||
*
|
||||
* @param mixed $value The single value of the column
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function normalize($value): mixed
|
||||
public function normalize($value): string
|
||||
{
|
||||
return $this->markdown->markForRendering($value, true);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ use App\Entity\Parts\PartLot;
|
|||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Services\EntityURLGenerator;
|
||||
use App\Services\Formatters\AmountFormatter;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider;
|
||||
|
@ -235,7 +236,7 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
'filter_query' => $this->getFilterQuery(...),
|
||||
'detail_query' => $this->getDetailQuery(...),
|
||||
'entity' => Part::class,
|
||||
'hydrate' => Query::HYDRATE_OBJECT,
|
||||
'hydrate' => AbstractQuery::HYDRATE_OBJECT,
|
||||
//Use the simple total query, as we just want to get the total number of parts without any conditions
|
||||
//For this the normal query would be pretty slow
|
||||
'simple_total_query' => true,
|
||||
|
@ -270,7 +271,7 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
|
||||
private function getDetailQuery(QueryBuilder $builder, array $filter_results): void
|
||||
{
|
||||
$ids = array_map(fn($row) => $row['id'], $filter_results);
|
||||
$ids = array_map(static fn($row) => $row['id'], $filter_results);
|
||||
|
||||
/*
|
||||
* In this query we take the IDs which were filtered, paginated and sorted in the filter query, and fetch the
|
||||
|
|
|
@ -97,7 +97,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
}
|
||||
|
||||
//@phpstan-ignore-next-line
|
||||
throw new \Exception('This should never happen!');
|
||||
throw new \RuntimeException('This should never happen!');
|
||||
},
|
||||
])
|
||||
->add('ipn', TextColumn::class, [
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace App\Doctrine\Functions;
|
|||
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\TokenType;
|
||||
|
||||
/**
|
||||
* Basically the same as the original Field function, but uses FIELD2 for the SQL query.
|
||||
|
@ -38,8 +39,8 @@ class Field2 extends FunctionNode
|
|||
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser): void
|
||||
{
|
||||
$parser->match(Lexer::T_IDENTIFIER);
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
$parser->match(TokenType::T_IDENTIFIER);
|
||||
$parser->match(TokenType::T_OPEN_PARENTHESIS);
|
||||
|
||||
// Do the field.
|
||||
$this->field = $parser->ArithmeticPrimary();
|
||||
|
@ -50,12 +51,12 @@ class Field2 extends FunctionNode
|
|||
$lexer = $parser->getLexer();
|
||||
|
||||
while (count($this->values) < 1 ||
|
||||
$lexer->lookahead['type'] != Lexer::T_CLOSE_PARENTHESIS) {
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
$lexer->lookahead['type'] != TokenType::T_CLOSE_PARENTHESIS) {
|
||||
$parser->match(TokenType::T_COMMA);
|
||||
$this->values[] = $parser->ArithmeticPrimary();
|
||||
}
|
||||
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
$parser->match(TokenType::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker): string
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Attachments;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
|
@ -61,10 +62,10 @@ use LogicException;
|
|||
#[ORM\DiscriminatorMap(self::ORM_DISCRIMINATOR_MAP)]
|
||||
#[ORM\EntityListeners([AttachmentDeleteListener::class])]
|
||||
#[ORM\Table(name: '`attachments`')]
|
||||
#[ORM\Index(name: 'attachments_idx_id_element_id_class_name', columns: ['id', 'element_id', 'class_name'])]
|
||||
#[ORM\Index(name: 'attachments_idx_class_name_id', columns: ['class_name', 'id'])]
|
||||
#[ORM\Index(name: 'attachment_name_idx', columns: ['name'])]
|
||||
#[ORM\Index(name: 'attachment_element_idx', columns: ['class_name', 'element_id'])]
|
||||
#[ORM\Index(columns: ['id', 'element_id', 'class_name'], name: 'attachments_idx_id_element_id_class_name')]
|
||||
#[ORM\Index(columns: ['class_name', 'id'], name: 'attachments_idx_class_name_id')]
|
||||
#[ORM\Index(columns: ['name'], name: 'attachment_name_idx')]
|
||||
#[ORM\Index(columns: ['class_name', 'element_id'], name: 'attachment_element_idx')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -84,7 +85,7 @@ use LogicException;
|
|||
description: 'The URL to a thumbnail version of this file. This only exists for internal picture attachments.')]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name"])]
|
||||
#[ApiFilter(EntityFilter::class, properties: ["attachment_type"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
//This discriminator map is required for API platform to know which class to use for deserialization, when creating a new attachment.
|
||||
#[DiscriminatorMap(typeProperty: '_type', mapping: self::API_DISCRIMINATOR_MAP)]
|
||||
|
@ -151,7 +152,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
/**
|
||||
* @var string The path to the file relative to a placeholder path like %MEDIA%
|
||||
*/
|
||||
#[ORM\Column(type: Types::STRING, name: 'path')]
|
||||
#[ORM\Column(name: 'path', type: Types::STRING)]
|
||||
protected string $path = '';
|
||||
|
||||
/**
|
||||
|
@ -176,7 +177,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
#[Assert\NotNull(message: 'validator.attachment.must_not_be_null')]
|
||||
#[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'attachments_with_type')]
|
||||
#[ORM\JoinColumn(name: 'type_id', nullable: false)]
|
||||
#[Selectable()]
|
||||
#[Selectable]
|
||||
#[Groups(['attachment:read', 'attachment:write'])]
|
||||
protected ?AttachmentType $attachment_type = null;
|
||||
|
||||
|
@ -246,12 +247,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
$extension = pathinfo(parse_url($this->path, PHP_URL_PATH) ?? '', PATHINFO_EXTENSION);
|
||||
|
||||
//If no extension is found or it is known picture extension, we assume that this is a picture extension
|
||||
if ($extension === '' || in_array(strtolower($extension), static::PICTURE_EXTS, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Otherwise we assume that the file is not a picture
|
||||
return false;
|
||||
return $extension === '' || in_array(strtolower($extension), static::PICTURE_EXTS, true);
|
||||
}
|
||||
|
||||
$extension = pathinfo($this->getPath(), PATHINFO_EXTENSION);
|
||||
|
@ -521,6 +517,11 @@ abstract class Attachment extends AbstractNamedDBElement
|
|||
#[SerializedName('url')]
|
||||
public function setURL(?string $url): self
|
||||
{
|
||||
//Do nothing if the URL is empty
|
||||
if ($url === null || $url === '') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$url = trim($url);
|
||||
//Escape spaces in URL
|
||||
$url = str_replace(' ', '%20', $url);
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Attachments;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
|
@ -55,8 +56,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
*/
|
||||
#[ORM\Entity(repositoryClass: StructuralDBElementRepository::class)]
|
||||
#[ORM\Table(name: '`attachment_types`')]
|
||||
#[ORM\Index(name: 'attachment_types_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'attachment_types_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'attachment_types_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'attachment_types_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -81,11 +82,11 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class AttachmentType extends AbstractStructuralDBElement
|
||||
{
|
||||
#[ORM\OneToMany(targetEntity: AttachmentType::class, mappedBy: 'parent', cascade: ['persist'])]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: AttachmentType::class, cascade: ['persist'])]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -109,7 +110,7 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
* @var Collection<int, AttachmentTypeAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: AttachmentTypeAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: AttachmentTypeAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
#[Groups(['attachment_type:read', 'attachment_type:write'])]
|
||||
protected Collection $attachments;
|
||||
|
@ -122,7 +123,7 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
/** @var Collection<int, AttachmentTypeParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: AttachmentTypeParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: AttachmentTypeParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['attachment_type:read', 'attachment_type:write'])]
|
||||
protected Collection $parameters;
|
||||
|
@ -130,7 +131,7 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
/**
|
||||
* @var Collection<Attachment>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Attachment::class, mappedBy: 'attachment_type')]
|
||||
#[ORM\OneToMany(mappedBy: 'attachment_type', targetEntity: Attachment::class)]
|
||||
protected Collection $attachments_with_type;
|
||||
|
||||
#[Groups(['attachment_type:read'])]
|
||||
|
|
|
@ -62,7 +62,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||
* @extends AttachmentContainingDBElement<AT>
|
||||
* @uses ParametersTrait<PT>
|
||||
*/
|
||||
#[UniqueEntity(fields: ['name', 'parent'], ignoreNull: false, message: 'structural.entity.unique_name')]
|
||||
#[UniqueEntity(fields: ['name', 'parent'], message: 'structural.entity.unique_name', ignoreNull: false)]
|
||||
#[ORM\MappedSuperclass(repositoryClass: StructuralDBElementRepository::class)]
|
||||
#[ORM\EntityListeners([TreeCacheInvalidationListener::class])]
|
||||
abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
||||
|
@ -118,7 +118,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
* @var Collection<int, AbstractParameter>
|
||||
* @phpstan-var Collection<int, PT>
|
||||
*/
|
||||
#[Assert\Valid()]
|
||||
#[Assert\Valid]
|
||||
protected Collection $parameters;
|
||||
|
||||
/** @var string[] all names of all parent elements as an array of strings,
|
||||
|
@ -176,7 +176,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
throw new InvalidArgumentException('isChildOf() only works for objects of the same type!');
|
||||
}
|
||||
|
||||
if (!$this->getParent() instanceof \App\Entity\Base\AbstractStructuralDBElement) { // this is the root node
|
||||
if (!$this->getParent() instanceof self) { // this is the root node
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -244,9 +244,9 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
/*
|
||||
* Only check for nodes that have a parent. In the other cases zero is correct.
|
||||
*/
|
||||
if (0 === $this->level && $this->parent instanceof \App\Entity\Base\AbstractStructuralDBElement) {
|
||||
if (0 === $this->level && $this->parent instanceof self) {
|
||||
$element = $this->parent;
|
||||
while ($element instanceof \App\Entity\Base\AbstractStructuralDBElement) {
|
||||
while ($element instanceof self) {
|
||||
/** @var AbstractStructuralDBElement $element */
|
||||
$element = $element->parent;
|
||||
++$this->level;
|
||||
|
@ -274,7 +274,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
|
||||
$overflow = 20; //We only allow 20 levels depth
|
||||
|
||||
while ($element->parent instanceof \App\Entity\Base\AbstractStructuralDBElement && $overflow >= 0) {
|
||||
while ($element->parent instanceof self && $overflow >= 0) {
|
||||
$element = $element->parent;
|
||||
$this->full_path_strings[] = $element->getName();
|
||||
//Decrement to prevent mem overflow.
|
||||
|
@ -360,7 +360,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
$this->parent = $new_parent;
|
||||
|
||||
//Add this element as child to the new parent
|
||||
if ($new_parent instanceof \App\Entity\Base\AbstractStructuralDBElement) {
|
||||
if ($new_parent instanceof self) {
|
||||
$new_parent->getChildren()->add($this);
|
||||
}
|
||||
|
||||
|
@ -445,7 +445,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
public function setAlternativeNames(?string $new_value): self
|
||||
{
|
||||
//Add a trailing comma, if not already there (makes it easier to find in the database)
|
||||
if (is_string($new_value) && substr($new_value, -1) !== ',') {
|
||||
if (is_string($new_value) && !str_ends_with($new_value, ',')) {
|
||||
$new_value .= ',';
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ class LabelOptions
|
|||
|
||||
/** @var LabelProcessMode The mode that will be used to interpret the lines
|
||||
*/
|
||||
#[ORM\Column(type: Types::STRING, enumType: LabelProcessMode::class, name: 'lines_mode')]
|
||||
#[ORM\Column(name: 'lines_mode', type: Types::STRING, enumType: LabelProcessMode::class)]
|
||||
protected LabelProcessMode $process_mode = LabelProcessMode::PLACEHOLDER;
|
||||
|
||||
/**
|
||||
|
|
|
@ -66,7 +66,7 @@ class LabelProfile extends AttachmentContainingDBElement
|
|||
/**
|
||||
* @var Collection<int, LabelAttachment>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: LabelAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: LabelAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $attachments;
|
||||
|
||||
|
|
|
@ -147,65 +147,38 @@ class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventU
|
|||
private function resolveAbstractClassToInstantiableClass(string $abstract_class): string
|
||||
{
|
||||
if (is_a($abstract_class, AbstractParameter::class, true)) {
|
||||
switch ($this->getTargetClass()) {
|
||||
case AttachmentType::class:
|
||||
return AttachmentTypeParameter::class;
|
||||
case Category::class:
|
||||
return CategoryParameter::class;
|
||||
case Currency::class:
|
||||
return CurrencyParameter::class;
|
||||
case Project::class:
|
||||
return ProjectParameter::class;
|
||||
case Footprint::class:
|
||||
return FootprintParameter::class;
|
||||
case Group::class:
|
||||
return GroupParameter::class;
|
||||
case Manufacturer::class:
|
||||
return ManufacturerParameter::class;
|
||||
case MeasurementUnit::class:
|
||||
return MeasurementUnitParameter::class;
|
||||
case Part::class:
|
||||
return PartParameter::class;
|
||||
case StorageLocation::class:
|
||||
return StorageLocationParameter::class;
|
||||
case Supplier::class:
|
||||
return SupplierParameter::class;
|
||||
|
||||
default:
|
||||
throw new \RuntimeException('Unknown target class for parameter: '.$this->getTargetClass());
|
||||
}
|
||||
return match ($this->getTargetClass()) {
|
||||
AttachmentType::class => AttachmentTypeParameter::class,
|
||||
Category::class => CategoryParameter::class,
|
||||
Currency::class => CurrencyParameter::class,
|
||||
Project::class => ProjectParameter::class,
|
||||
Footprint::class => FootprintParameter::class,
|
||||
Group::class => GroupParameter::class,
|
||||
Manufacturer::class => ManufacturerParameter::class,
|
||||
MeasurementUnit::class => MeasurementUnitParameter::class,
|
||||
Part::class => PartParameter::class,
|
||||
StorageLocation::class => StorageLocationParameter::class,
|
||||
Supplier::class => SupplierParameter::class,
|
||||
default => throw new \RuntimeException('Unknown target class for parameter: '.$this->getTargetClass()),
|
||||
};
|
||||
}
|
||||
|
||||
if (is_a($abstract_class, Attachment::class, true)) {
|
||||
switch ($this->getTargetClass()) {
|
||||
case AttachmentType::class:
|
||||
return AttachmentTypeAttachment::class;
|
||||
case Category::class:
|
||||
return CategoryAttachment::class;
|
||||
case Currency::class:
|
||||
return CurrencyAttachment::class;
|
||||
case Project::class:
|
||||
return ProjectAttachment::class;
|
||||
case Footprint::class:
|
||||
return FootprintAttachment::class;
|
||||
case Group::class:
|
||||
return GroupAttachment::class;
|
||||
case Manufacturer::class:
|
||||
return ManufacturerAttachment::class;
|
||||
case MeasurementUnit::class:
|
||||
return MeasurementUnitAttachment::class;
|
||||
case Part::class:
|
||||
return PartAttachment::class;
|
||||
case StorageLocation::class:
|
||||
return StorageLocationAttachment::class;
|
||||
case Supplier::class:
|
||||
return SupplierAttachment::class;
|
||||
case User::class:
|
||||
return UserAttachment::class;
|
||||
|
||||
default:
|
||||
throw new \RuntimeException('Unknown target class for parameter: '.$this->getTargetClass());
|
||||
}
|
||||
return match ($this->getTargetClass()) {
|
||||
AttachmentType::class => AttachmentTypeAttachment::class,
|
||||
Category::class => CategoryAttachment::class,
|
||||
Currency::class => CurrencyAttachment::class,
|
||||
Project::class => ProjectAttachment::class,
|
||||
Footprint::class => FootprintAttachment::class,
|
||||
Group::class => GroupAttachment::class,
|
||||
Manufacturer::class => ManufacturerAttachment::class,
|
||||
MeasurementUnit::class => MeasurementUnitAttachment::class,
|
||||
Part::class => PartAttachment::class,
|
||||
StorageLocation::class => StorageLocationAttachment::class,
|
||||
Supplier::class => SupplierAttachment::class,
|
||||
User::class => UserAttachment::class,
|
||||
default => throw new \RuntimeException('Unknown target class for parameter: '.$this->getTargetClass()),
|
||||
};
|
||||
}
|
||||
|
||||
throw new \RuntimeException('The class '.$abstract_class.' is abstract and no explicit resolving to an concrete type is defined!');
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
namespace App\Entity\LogSystem;
|
||||
|
||||
use \Psr\Log\LogLevel as PSRLogLevel;
|
||||
use Psr\Log\LogLevel as PSRLogLevel;
|
||||
|
||||
enum LogLevel: int
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@ use League\OAuth2\Client\Token\AccessTokenInterface;
|
|||
/**
|
||||
* This entity represents a OAuth token pair (access and refresh token), for an application
|
||||
*/
|
||||
#[ORM\Entity()]
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: 'oauth_tokens')]
|
||||
#[ORM\UniqueConstraint(name: 'oauth_tokens_unique_name', columns: ['name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'oauth_tokens_name_idx')]
|
||||
|
|
|
@ -41,6 +41,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parameters;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\RangeFilter;
|
||||
|
@ -76,9 +77,9 @@ use function sprintf;
|
|||
6 => MeasurementUnitParameter::class, 7 => PartParameter::class, 8 => StorageLocationParameter::class,
|
||||
9 => SupplierParameter::class, 10 => AttachmentTypeParameter::class])]
|
||||
#[ORM\Table('parameters')]
|
||||
#[ORM\Index(name: 'parameter_name_idx', columns: ['name'])]
|
||||
#[ORM\Index(name: 'parameter_group_idx', columns: ['param_group'])]
|
||||
#[ORM\Index(name: 'parameter_type_element_idx', columns: ['type', 'element_id'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'parameter_name_idx')]
|
||||
#[ORM\Index(columns: ['param_group'], name: 'parameter_group_idx')]
|
||||
#[ORM\Index(columns: ['type', 'element_id'], name: 'parameter_type_element_idx')]
|
||||
#[ApiResource(
|
||||
shortName: 'Parameter',
|
||||
operations: [
|
||||
|
@ -91,7 +92,7 @@ use function sprintf;
|
|||
denormalizationContext: ['groups' => ['parameter:write', 'parameter:write:standalone', 'api:basic:write'], 'openapi_definition_name' => 'Write'],
|
||||
)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "symbol", "unit", "group", "value_text"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(RangeFilter::class, properties: ["value_min", "value_typical", "value_max"])]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
//This discriminator map is required for API platform to know which class to use for deserialization, when creating a new parameter.
|
||||
|
@ -166,7 +167,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement
|
|||
* @var string the group this parameter belongs to
|
||||
*/
|
||||
#[Groups(['full', 'parameter:read', 'parameter:write'])]
|
||||
#[ORM\Column(type: Types::STRING, name: 'param_group')]
|
||||
#[ORM\Column(name: 'param_group', type: Types::STRING)]
|
||||
protected string $group = '';
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
|
||||
|
@ -60,8 +61,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
*/
|
||||
#[ORM\Entity(repositoryClass: CategoryRepository::class)]
|
||||
#[ORM\Table(name: '`categories`')]
|
||||
#[ORM\Index(name: 'category_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'category_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'category_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'category_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -88,11 +89,11 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class Category extends AbstractPartsContainingDBElement
|
||||
{
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -166,7 +167,7 @@ class Category extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
#[Assert\Valid]
|
||||
#[Groups(['full', 'category:read', 'category:write'])]
|
||||
#[ORM\OneToMany(targetEntity: CategoryAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CategoryAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $attachments;
|
||||
|
||||
|
@ -179,7 +180,7 @@ class Category extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
#[Assert\Valid]
|
||||
#[Groups(['full', 'category:read', 'category:write'])]
|
||||
#[ORM\OneToMany(targetEntity: CategoryParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CategoryParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
protected Collection $parameters;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
|
||||
|
@ -61,8 +62,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
*/
|
||||
#[ORM\Entity(repositoryClass: FootprintRepository::class)]
|
||||
#[ORM\Table('`footprints`')]
|
||||
#[ORM\Index(name: 'footprint_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'footprint_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'footprint_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'footprint_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -89,7 +90,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class Footprint extends AbstractPartsContainingDBElement
|
||||
{
|
||||
|
@ -99,7 +100,7 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
#[ApiProperty(readableLink: false, writableLink: false)]
|
||||
protected ?AbstractStructuralDBElement $parent = null;
|
||||
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -110,7 +111,7 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
* @var Collection<int, FootprintAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: FootprintAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: FootprintAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
#[Groups(['footprint:read', 'footprint:write'])]
|
||||
protected Collection $attachments;
|
||||
|
@ -131,7 +132,7 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
/** @var Collection<int, FootprintParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: FootprintParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: FootprintParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['footprint:read', 'footprint:write'])]
|
||||
protected Collection $parameters;
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
|
@ -56,8 +57,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
*/
|
||||
#[ORM\Entity(repositoryClass: ManufacturerRepository::class)]
|
||||
#[ORM\Table('`manufacturers`')]
|
||||
#[ORM\Index(name: 'manufacturer_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'manufacturer_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'manufacturer_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'manufacturer_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -84,7 +85,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class Manufacturer extends AbstractCompany
|
||||
{
|
||||
|
@ -94,7 +95,7 @@ class Manufacturer extends AbstractCompany
|
|||
#[ApiProperty(readableLink: false, writableLink: false)]
|
||||
protected ?AbstractStructuralDBElement $parent = null;
|
||||
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -102,7 +103,7 @@ class Manufacturer extends AbstractCompany
|
|||
* @var Collection<int, ManufacturerAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: ManufacturerAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ManufacturerAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
#[Groups(['manufacturer:read', 'manufacturer:write'])]
|
||||
#[ApiProperty(readableLink: false, writableLink: true)]
|
||||
|
@ -117,7 +118,7 @@ class Manufacturer extends AbstractCompany
|
|||
/** @var Collection<int, ManufacturerParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: ManufacturerParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ManufacturerParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['manufacturer:read', 'manufacturer:write'])]
|
||||
#[ApiProperty(readableLink: false, writableLink: true)]
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
|
@ -60,8 +61,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
#[UniqueEntity('unit')]
|
||||
#[ORM\Entity(repositoryClass: MeasurementUnitRepository::class)]
|
||||
#[ORM\Table(name: '`measurement_units`')]
|
||||
#[ORM\Index(name: 'unit_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'unit_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'unit_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'unit_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -88,7 +89,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment", "unit"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class MeasurementUnit extends AbstractPartsContainingDBElement
|
||||
{
|
||||
|
@ -98,7 +99,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
#[Assert\Length(max: 10)]
|
||||
#[Groups(['extended', 'full', 'import', 'measurement_unit:read', 'measurement_unit:write'])]
|
||||
#[ORM\Column(type: Types::STRING, name: 'unit', nullable: true)]
|
||||
#[ORM\Column(name: 'unit', type: Types::STRING, nullable: true)]
|
||||
protected ?string $unit = null;
|
||||
|
||||
#[Groups(['measurement_unit:read', 'measurement_unit:write'])]
|
||||
|
@ -109,7 +110,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
* Set to false, to measure continuous sizes likes masses or lengths.
|
||||
*/
|
||||
#[Groups(['extended', 'full', 'import', 'measurement_unit:read', 'measurement_unit:write'])]
|
||||
#[ORM\Column(type: Types::BOOLEAN, name: 'is_integer')]
|
||||
#[ORM\Column(name: 'is_integer', type: Types::BOOLEAN)]
|
||||
protected bool $is_integer = false;
|
||||
|
||||
/**
|
||||
|
@ -118,10 +119,10 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
#[Assert\Expression('this.isUseSIPrefix() == false or this.getUnit() != null', message: 'validator.measurement_unit.use_si_prefix_needs_unit')]
|
||||
#[Groups(['full', 'import', 'measurement_unit:read', 'measurement_unit:write'])]
|
||||
#[ORM\Column(type: Types::BOOLEAN, name: 'use_si_prefix')]
|
||||
#[ORM\Column(name: 'use_si_prefix', type: Types::BOOLEAN)]
|
||||
protected bool $use_si_prefix = false;
|
||||
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent', cascade: ['persist'])]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class, cascade: ['persist'])]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -135,7 +136,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
* @var Collection<int, MeasurementUnitAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: MeasurementUnitAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: MeasurementUnitAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
#[Groups(['measurement_unit:read', 'measurement_unit:write'])]
|
||||
protected Collection $attachments;
|
||||
|
@ -148,7 +149,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
/** @var Collection<int, MeasurementUnitParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: MeasurementUnitParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: MeasurementUnitParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['measurement_unit:read', 'measurement_unit:write'])]
|
||||
protected Collection $parameters;
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
|
@ -74,9 +75,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||
#[ORM\Entity(repositoryClass: PartRepository::class)]
|
||||
#[ORM\EntityListeners([TreeCacheInvalidationListener::class])]
|
||||
#[ORM\Table('`parts`')]
|
||||
#[ORM\Index(name: 'parts_idx_datet_name_last_id_needs', columns: ['datetime_added', 'name', 'last_modified', 'id', 'needs_review'])]
|
||||
#[ORM\Index(name: 'parts_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'parts_idx_ipn', columns: ['ipn'])]
|
||||
#[ORM\Index(columns: ['datetime_added', 'name', 'last_modified', 'id', 'needs_review'], name: 'parts_idx_datet_name_last_id_needs')]
|
||||
#[ORM\Index(columns: ['name'], name: 'parts_idx_name')]
|
||||
#[ORM\Index(columns: ['ipn'], name: 'parts_idx_ipn')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(normalizationContext: ['groups' => ['part:read', 'provider_reference:read', 'api:basic:read', 'part_lot:read',
|
||||
|
@ -97,7 +98,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment", "description", "ipn", "tags", "manufacturer_product_number"])]
|
||||
#[ApiFilter(BooleanFilter::class, properties: ["favorite" , "needs_review"])]
|
||||
#[ApiFilter(RangeFilter::class, properties: ["mass", "minamount"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class Part extends AttachmentContainingDBElement
|
||||
{
|
||||
|
@ -116,7 +117,7 @@ class Part extends AttachmentContainingDBElement
|
|||
*/
|
||||
#[Assert\Valid]
|
||||
#[Groups(['full', 'part:read', 'part:write'])]
|
||||
#[ORM\OneToMany(targetEntity: PartParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: PartParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
protected Collection $parameters;
|
||||
|
||||
|
@ -136,7 +137,7 @@ class Part extends AttachmentContainingDBElement
|
|||
*/
|
||||
#[Assert\Valid]
|
||||
#[Groups(['full', 'part:read', 'part:write'])]
|
||||
#[ORM\OneToMany(targetEntity: PartAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: PartAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $attachments;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
|
@ -67,7 +68,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["other_type", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['comment', 'addedDate', 'lastModified'])]
|
||||
class PartAssociation extends AbstractDBElement implements TimeStampableInterface
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
|
@ -80,7 +81,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["description", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(BooleanFilter::class, properties: ['instock_unknown', 'needs_refill'])]
|
||||
#[ApiFilter(RangeFilter::class, properties: ['amount'])]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['description', 'comment', 'addedDate', 'lastModified'])]
|
||||
|
@ -107,7 +108,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
|
|||
* Set to null, if the lot can be used indefinitely.
|
||||
*/
|
||||
#[Groups(['extended', 'full', 'import', 'part_lot:read', 'part_lot:write'])]
|
||||
#[ORM\Column(type: Types::DATETIME_MUTABLE, name: 'expiration_date', nullable: true)]
|
||||
#[ORM\Column(name: 'expiration_date', type: Types::DATETIME_MUTABLE, nullable: true)]
|
||||
protected ?\DateTimeInterface $expiration_date = null;
|
||||
|
||||
/**
|
||||
|
@ -116,7 +117,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
|
|||
#[Groups(['simple', 'extended', 'full', 'import', 'part_lot:read', 'part_lot:write'])]
|
||||
#[ORM\ManyToOne(targetEntity: StorageLocation::class, fetch: 'EAGER')]
|
||||
#[ORM\JoinColumn(name: 'id_store_location')]
|
||||
#[Selectable()]
|
||||
#[Selectable]
|
||||
protected ?StorageLocation $storage_location = null;
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,7 +64,7 @@ trait BasicPropertyTrait
|
|||
* Every part must have a category.
|
||||
*/
|
||||
#[Assert\NotNull(message: 'validator.select_valid_category')]
|
||||
#[Selectable()]
|
||||
#[Selectable]
|
||||
#[Groups(['simple', 'extended', 'full', 'import', "part:read", "part:write"])]
|
||||
#[ORM\ManyToOne(targetEntity: Category::class)]
|
||||
#[ORM\JoinColumn(name: 'id_category', nullable: false)]
|
||||
|
@ -76,7 +76,7 @@ trait BasicPropertyTrait
|
|||
#[Groups(['simple', 'extended', 'full', 'import', 'part:read', 'part:write'])]
|
||||
#[ORM\ManyToOne(targetEntity: Footprint::class)]
|
||||
#[ORM\JoinColumn(name: 'id_footprint')]
|
||||
#[Selectable()]
|
||||
#[Selectable]
|
||||
protected ?Footprint $footprint = null;
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,7 +41,7 @@ trait InstockTrait
|
|||
*/
|
||||
#[Assert\Valid]
|
||||
#[Groups(['extended', 'full', 'import', 'part:read', 'part:write'])]
|
||||
#[ORM\OneToMany(targetEntity: PartLot::class, mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'part', targetEntity: PartLot::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['amount' => 'DESC'])]
|
||||
protected Collection $partLots;
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ trait ManufacturerTrait
|
|||
#[Groups(['simple', 'extended', 'full', 'import', 'part:read', 'part:write'])]
|
||||
#[ORM\ManyToOne(targetEntity: Manufacturer::class)]
|
||||
#[ORM\JoinColumn(name: 'id_manufacturer')]
|
||||
#[Selectable()]
|
||||
#[Selectable]
|
||||
protected ?Manufacturer $manufacturer = null;
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,7 +40,7 @@ trait OrderTrait
|
|||
*/
|
||||
#[Assert\Valid]
|
||||
#[Groups(['extended', 'full', 'import', 'part:read', 'part:write'])]
|
||||
#[ORM\OneToMany(targetEntity: Orderdetail::class, mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'part', targetEntity: Orderdetail::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['supplierpartnr' => 'ASC'])]
|
||||
protected Collection $orderdetails;
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ trait ProjectTrait
|
|||
/**
|
||||
* @var Collection<ProjectBOMEntry> $project_bom_entries
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: ProjectBOMEntry::class, mappedBy: 'part', cascade: ['remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'part', targetEntity: ProjectBOMEntry::class, cascade: ['remove'], orphanRemoval: true)]
|
||||
protected Collection $project_bom_entries;
|
||||
|
||||
/**
|
||||
* @var Project|null If a project is set here, then this part is special and represents the builds of a project.
|
||||
*/
|
||||
#[ORM\OneToOne(targetEntity: Project::class, inversedBy: 'build_part')]
|
||||
#[ORM\OneToOne(inversedBy: 'build_part', targetEntity: Project::class)]
|
||||
#[ORM\JoinColumn]
|
||||
protected ?Project $built_project = null;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
|
@ -56,8 +57,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
*/
|
||||
#[ORM\Entity(repositoryClass: StorelocationRepository::class)]
|
||||
#[ORM\Table('`storelocations`')]
|
||||
#[ORM\Index(name: 'location_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'location_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'location_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'location_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -84,11 +85,11 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class StorageLocation extends AbstractPartsContainingDBElement
|
||||
{
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -112,7 +113,7 @@ class StorageLocation extends AbstractPartsContainingDBElement
|
|||
/** @var Collection<int, StorageLocationParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: StorageLocationParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: StorageLocationParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['location:read', 'location:write'])]
|
||||
protected Collection $parameters;
|
||||
|
@ -158,7 +159,7 @@ class StorageLocation extends AbstractPartsContainingDBElement
|
|||
* @var Collection<int, StorageLocationAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: StorageLocationAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: StorageLocationAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[Groups(['location:read', 'location:write'])]
|
||||
protected Collection $attachments;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Parts;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
|
@ -61,8 +62,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
*/
|
||||
#[ORM\Entity(repositoryClass: SupplierRepository::class)]
|
||||
#[ORM\Table('`suppliers`')]
|
||||
#[ORM\Index(name: 'supplier_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'supplier_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'supplier_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'supplier_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -81,17 +82,17 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
security: 'is_granted("@manufacturers.read")'
|
||||
)],
|
||||
uriVariables: [
|
||||
'id' => new Link(fromClass: Supplier::class, fromProperty: 'children')
|
||||
'id' => new Link(fromProperty: 'children', fromClass: Supplier::class)
|
||||
],
|
||||
normalizationContext: ['groups' => ['supplier:read', 'company:read', 'api:basic:read'], 'openapi_definition_name' => 'Read']
|
||||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class Supplier extends AbstractCompany
|
||||
{
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -104,7 +105,7 @@ class Supplier extends AbstractCompany
|
|||
/**
|
||||
* @var Collection<int, Orderdetail>|Orderdetail[]
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Orderdetail::class, mappedBy: 'supplier')]
|
||||
#[ORM\OneToMany(mappedBy: 'supplier', targetEntity: Orderdetail::class)]
|
||||
protected Collection $orderdetails;
|
||||
|
||||
/**
|
||||
|
@ -113,22 +114,22 @@ class Supplier extends AbstractCompany
|
|||
*/
|
||||
#[ORM\ManyToOne(targetEntity: Currency::class)]
|
||||
#[ORM\JoinColumn(name: 'default_currency_id')]
|
||||
#[Selectable()]
|
||||
#[Selectable]
|
||||
protected ?Currency $default_currency = null;
|
||||
|
||||
/**
|
||||
* @var BigDecimal|null The shipping costs that have to be paid, when ordering via this supplier
|
||||
*/
|
||||
#[Groups(['extended', 'full', 'import'])]
|
||||
#[ORM\Column(name: 'shipping_costs', nullable: true, type: 'big_decimal', precision: 11, scale: 5)]
|
||||
#[BigDecimalPositiveOrZero()]
|
||||
#[ORM\Column(name: 'shipping_costs', type: 'big_decimal', precision: 11, scale: 5, nullable: true)]
|
||||
#[BigDecimalPositiveOrZero]
|
||||
protected ?BigDecimal $shipping_costs = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, SupplierAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: SupplierAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: SupplierAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
#[Groups(['supplier:read', 'supplier:write'])]
|
||||
#[ApiProperty(readableLink: false, writableLink: true)]
|
||||
|
@ -143,7 +144,7 @@ class Supplier extends AbstractCompany
|
|||
/** @var Collection<int, SupplierParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: SupplierParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: SupplierParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['supplier:read', 'supplier:write'])]
|
||||
#[ApiProperty(readableLink: false, writableLink: true)]
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\PriceInformations;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
|
@ -60,8 +61,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
#[UniqueEntity('iso_code')]
|
||||
#[ORM\Entity(repositoryClass: CurrencyRepository::class)]
|
||||
#[ORM\Table(name: 'currencies')]
|
||||
#[ORM\Index(name: 'currency_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'currency_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'currency_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'currency_idx_parent_name')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -88,7 +89,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "comment", "iso_code"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class Currency extends AbstractStructuralDBElement
|
||||
{
|
||||
|
@ -99,7 +100,7 @@ class Currency extends AbstractStructuralDBElement
|
|||
* (how many base units the current currency is worth)
|
||||
*/
|
||||
#[ORM\Column(type: 'big_decimal', precision: 11, scale: 5, nullable: true)]
|
||||
#[BigDecimalPositive()]
|
||||
#[BigDecimalPositive]
|
||||
#[Groups(['currency:read', 'currency:write'])]
|
||||
#[ApiProperty(readableLink: false, writableLink: false)]
|
||||
protected ?BigDecimal $exchange_rate = null;
|
||||
|
@ -116,7 +117,7 @@ class Currency extends AbstractStructuralDBElement
|
|||
#[ORM\Column(type: Types::STRING)]
|
||||
protected string $iso_code = "";
|
||||
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent', cascade: ['persist'])]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class, cascade: ['persist'])]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -130,7 +131,7 @@ class Currency extends AbstractStructuralDBElement
|
|||
* @var Collection<int, CurrencyAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: CurrencyAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CurrencyAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
#[Groups(['currency:read', 'currency:write'])]
|
||||
protected Collection $attachments;
|
||||
|
@ -143,14 +144,14 @@ class Currency extends AbstractStructuralDBElement
|
|||
/** @var Collection<int, CurrencyParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: CurrencyParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: CurrencyParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['currency:read', 'currency:write'])]
|
||||
protected Collection $parameters;
|
||||
|
||||
/** @var Collection<int, Pricedetail>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Pricedetail::class, mappedBy: 'currency')]
|
||||
#[ORM\OneToMany(mappedBy: 'currency', targetEntity: Pricedetail::class)]
|
||||
protected Collection $pricedetails;
|
||||
|
||||
#[Groups(['currency:read'])]
|
||||
|
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\PriceInformations;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
|
@ -59,7 +60,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
#[ORM\Entity]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ORM\Table('`orderdetails`')]
|
||||
#[ORM\Index(name: 'orderdetails_supplier_part_nr', columns: ['supplierpartnr'])]
|
||||
#[ORM\Index(columns: ['supplierpartnr'], name: 'orderdetails_supplier_part_nr')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -88,7 +89,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["supplierpartnr", "supplier_product_url"])]
|
||||
#[ApiFilter(BooleanFilter::class, properties: ["obsolete"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['supplierpartnr', 'id', 'addedDate', 'lastModified'])]
|
||||
class Orderdetail extends AbstractDBElement implements TimeStampableInterface, NamedElementInterface
|
||||
{
|
||||
|
@ -96,7 +97,7 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
|
|||
|
||||
#[Assert\Valid]
|
||||
#[Groups(['extended', 'full', 'import', 'orderdetail:read', 'orderdetail:write'])]
|
||||
#[ORM\OneToMany(targetEntity: Pricedetail::class, mappedBy: 'orderdetail', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'orderdetail', targetEntity: Pricedetail::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['min_discount_quantity' => 'ASC'])]
|
||||
protected Collection $pricedetails;
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
#[ORM\Entity]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ORM\Table('`pricedetails`')]
|
||||
#[ORM\Index(name: 'pricedetails_idx_min_discount', columns: ['min_discount_quantity'])]
|
||||
#[ORM\Index(name: 'pricedetails_idx_min_discount_price_qty', columns: ['min_discount_quantity', 'price_related_quantity'])]
|
||||
#[ORM\Index(columns: ['min_discount_quantity'], name: 'pricedetails_idx_min_discount')]
|
||||
#[ORM\Index(columns: ['min_discount_quantity', 'price_related_quantity'], name: 'pricedetails_idx_min_discount_price_qty')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)'),
|
||||
|
@ -80,7 +80,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
|
|||
*/
|
||||
#[Groups(['extended', 'full', 'pricedetail:read', 'pricedetail:write'])]
|
||||
#[ORM\Column(type: 'big_decimal', precision: 11, scale: 5)]
|
||||
#[BigDecimalPositive()]
|
||||
#[BigDecimalPositive]
|
||||
protected BigDecimal $price;
|
||||
|
||||
/**
|
||||
|
@ -90,7 +90,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
|
|||
#[Groups(['extended', 'full', 'import', 'pricedetail:read', 'pricedetail:write'])]
|
||||
#[ORM\ManyToOne(targetEntity: Currency::class, inversedBy: 'pricedetails')]
|
||||
#[ORM\JoinColumn(name: 'id_currency')]
|
||||
#[Selectable()]
|
||||
#[Selectable]
|
||||
protected ?Currency $currency = null;
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,7 +90,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
class Project extends AbstractStructuralDBElement
|
||||
{
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -105,9 +105,9 @@ class Project extends AbstractStructuralDBElement
|
|||
|
||||
#[Assert\Valid]
|
||||
#[Groups(['extended', 'full'])]
|
||||
#[ORM\OneToMany(targetEntity: ProjectBOMEntry::class, mappedBy: 'project', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[UniqueObjectCollection(fields: ['part'], message: 'project.bom_entry.part_already_in_bom')]
|
||||
#[UniqueObjectCollection(fields: ['name'], message: 'project.bom_entry.name_already_in_bom')]
|
||||
#[ORM\OneToMany(mappedBy: 'project', targetEntity: ProjectBOMEntry::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[UniqueObjectCollection(message: 'project.bom_entry.part_already_in_bom', fields: ['part'])]
|
||||
#[UniqueObjectCollection(message: 'project.bom_entry.name_already_in_bom', fields: ['name'])]
|
||||
protected Collection $bom_entries;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER)]
|
||||
|
@ -125,7 +125,7 @@ class Project extends AbstractStructuralDBElement
|
|||
/**
|
||||
* @var Part|null The (optional) part that represents the builds of this project in the stock
|
||||
*/
|
||||
#[ORM\OneToOne(targetEntity: Part::class, mappedBy: 'built_project', cascade: ['persist'], orphanRemoval: true)]
|
||||
#[ORM\OneToOne(mappedBy: 'built_project', targetEntity: Part::class, cascade: ['persist'], orphanRemoval: true)]
|
||||
#[Groups(['project:read', 'project:write'])]
|
||||
protected ?Part $build_part = null;
|
||||
|
||||
|
@ -139,7 +139,7 @@ class Project extends AbstractStructuralDBElement
|
|||
/**
|
||||
* @var Collection<int, ProjectAttachment>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: ProjectAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ProjectAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
#[Groups(['project:read', 'project:write'])]
|
||||
protected Collection $attachments;
|
||||
|
@ -151,7 +151,7 @@ class Project extends AbstractStructuralDBElement
|
|||
|
||||
/** @var Collection<int, ProjectParameter>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: ProjectParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: ProjectParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
#[Groups(['project:read', 'project:write'])]
|
||||
protected Collection $parameters;
|
||||
|
|
|
@ -59,11 +59,11 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||
#[ORM\Table('project_bom_entries')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(security: 'is_granted("read", object)', uriTemplate: '/project_bom_entries/{id}.{_format}',),
|
||||
new GetCollection(security: 'is_granted("@projects.read")', uriTemplate: '/project_bom_entries.{_format}',),
|
||||
new Post(securityPostDenormalize: 'is_granted("create", object)', uriTemplate: '/project_bom_entries.{_format}',),
|
||||
new Patch(security: 'is_granted("edit", object)', uriTemplate: '/project_bom_entries/{id}.{_format}',),
|
||||
new Delete(security: 'is_granted("delete", object)', uriTemplate: '/project_bom_entries/{id}.{_format}',),
|
||||
new Get(uriTemplate: '/project_bom_entries/{id}.{_format}', security: 'is_granted("read", object)',),
|
||||
new GetCollection(uriTemplate: '/project_bom_entries.{_format}', security: 'is_granted("@projects.read")',),
|
||||
new Post(uriTemplate: '/project_bom_entries.{_format}', securityPostDenormalize: 'is_granted("create", object)',),
|
||||
new Patch(uriTemplate: '/project_bom_entries/{id}.{_format}', security: 'is_granted("edit", object)',),
|
||||
new Delete(uriTemplate: '/project_bom_entries/{id}.{_format}', security: 'is_granted("delete", object)',),
|
||||
],
|
||||
normalizationContext: ['groups' => ['bom_entry:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'],
|
||||
denormalizationContext: ['groups' => ['bom_entry:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'],
|
||||
|
@ -90,14 +90,14 @@ class ProjectBOMEntry extends AbstractDBElement implements UniqueValidatableInte
|
|||
use TimestampTrait;
|
||||
|
||||
#[Assert\Positive]
|
||||
#[ORM\Column(type: Types::FLOAT, name: 'quantity')]
|
||||
#[ORM\Column(name: 'quantity', type: Types::FLOAT)]
|
||||
#[Groups(['bom_entry:read', 'bom_entry:write'])]
|
||||
protected float $quantity = 1.0;
|
||||
|
||||
/**
|
||||
* @var string A comma separated list of the names, where this parts should be placed
|
||||
*/
|
||||
#[ORM\Column(type: Types::TEXT, name: 'mountnames')]
|
||||
#[ORM\Column(name: 'mountnames', type: Types::TEXT)]
|
||||
#[Groups(['bom_entry:read', 'bom_entry:write'])]
|
||||
protected string $mountnames = '';
|
||||
|
||||
|
|
|
@ -45,12 +45,12 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
*/
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table('`groups`')]
|
||||
#[ORM\Index(name: 'group_idx_name', columns: ['name'])]
|
||||
#[ORM\Index(name: 'group_idx_parent_name', columns: ['parent_id', 'name'])]
|
||||
#[NoLockout()]
|
||||
#[ORM\Index(columns: ['name'], name: 'group_idx_name')]
|
||||
#[ORM\Index(columns: ['parent_id', 'name'], name: 'group_idx_parent_name')]
|
||||
#[NoLockout]
|
||||
class Group extends AbstractStructuralDBElement implements HasPermissionsInterface
|
||||
{
|
||||
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $children;
|
||||
|
||||
|
@ -61,21 +61,21 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
|
|||
/**
|
||||
* @var Collection<int, User>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: User::class, mappedBy: 'group')]
|
||||
#[ORM\OneToMany(mappedBy: 'group', targetEntity: User::class)]
|
||||
protected Collection $users;
|
||||
|
||||
/**
|
||||
* @var bool If true all users associated with this group must have enabled some kind of two-factor authentication
|
||||
*/
|
||||
#[Groups(['extended', 'full', 'import'])]
|
||||
#[ORM\Column(type: Types::BOOLEAN, name: 'enforce_2fa')]
|
||||
#[ORM\Column(name: 'enforce_2fa', type: Types::BOOLEAN)]
|
||||
protected bool $enforce2FA = false;
|
||||
|
||||
/**
|
||||
* @var Collection<int, GroupAttachment>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: GroupAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: GroupAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['name' => 'ASC'])]
|
||||
protected Collection $attachments;
|
||||
|
||||
|
@ -85,14 +85,14 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
|
|||
|
||||
#[Groups(['full'])]
|
||||
#[ORM\Embedded(class: PermissionData::class, columnPrefix: 'permissions_')]
|
||||
#[ValidPermission()]
|
||||
#[ValidPermission]
|
||||
protected ?PermissionData $permissions = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, GroupParameter>
|
||||
*/
|
||||
#[Assert\Valid]
|
||||
#[ORM\OneToMany(targetEntity: GroupParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(mappedBy: 'element', targetEntity: GroupParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
|
||||
protected Collection $parameters;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ final class PermissionData implements \JsonSerializable
|
|||
* operation => value,
|
||||
* ]
|
||||
*/
|
||||
#[ORM\Column(type: Types::JSON, name: 'data')]
|
||||
#[ORM\Column(name: 'data', type: Types::JSON)]
|
||||
protected array $data = []
|
||||
)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\UserSystem;
|
||||
|
||||
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
|
||||
|
@ -80,7 +81,7 @@ use Jbtronics\TFAWebauthn\Model\TwoFactorInterface as WebauthnTwoFactorInterface
|
|||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||
#[ORM\EntityListeners([TreeCacheInvalidationListener::class])]
|
||||
#[ORM\Table('`users`')]
|
||||
#[ORM\Index(name: 'user_idx_username', columns: ['name'])]
|
||||
#[ORM\Index(columns: ['name'], name: 'user_idx_username')]
|
||||
#[ORM\AttributeOverrides([
|
||||
new ORM\AttributeOverride(name: 'name', column: new ORM\Column(type: Types::STRING, length: 180, unique: true))
|
||||
])]
|
||||
|
@ -100,9 +101,9 @@ use Jbtronics\TFAWebauthn\Model\TwoFactorInterface as WebauthnTwoFactorInterface
|
|||
)]
|
||||
#[ApiFilter(PropertyFilter::class)]
|
||||
#[ApiFilter(LikeFilter::class, properties: ["name", "aboutMe"])]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)]
|
||||
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
|
||||
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
|
||||
#[NoLockout()]
|
||||
#[NoLockout]
|
||||
class User extends AttachmentContainingDBElement implements UserInterface, HasPermissionsInterface, TwoFactorInterface,
|
||||
BackupCodeInterface, TrustedDeviceInterface, WebauthnTwoFactorInterface, PreferredProviderInterface, PasswordAuthenticatedUserInterface, SamlUserInterface
|
||||
{
|
||||
|
@ -133,8 +134,8 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
* @var string|null The theme
|
||||
*/
|
||||
#[Groups(['full', 'import', 'user:read'])]
|
||||
#[ORM\Column(type: Types::STRING, name: 'config_theme', nullable: true)]
|
||||
#[ValidTheme()]
|
||||
#[ORM\Column(name: 'config_theme', type: Types::STRING, nullable: true)]
|
||||
#[ValidTheme]
|
||||
protected ?string $theme = null;
|
||||
|
||||
/**
|
||||
|
@ -143,10 +144,10 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
#[ORM\Column(type: Types::STRING, nullable: true)]
|
||||
protected ?string $pw_reset_token = null;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, name: 'config_instock_comment_a')]
|
||||
#[ORM\Column(name: 'config_instock_comment_a', type: Types::TEXT)]
|
||||
protected string $instock_comment_a = '';
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, name: 'config_instock_comment_w')]
|
||||
#[ORM\Column(name: 'config_instock_comment_w', type: Types::TEXT)]
|
||||
protected string $instock_comment_w = '';
|
||||
|
||||
/**
|
||||
|
@ -189,7 +190,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
*/
|
||||
#[Assert\Timezone]
|
||||
#[Groups(['full', 'import', 'user:read'])]
|
||||
#[ORM\Column(type: Types::STRING, name: 'config_timezone', nullable: true)]
|
||||
#[ORM\Column(name: 'config_timezone', type: Types::STRING, nullable: true)]
|
||||
protected ?string $timezone = '';
|
||||
|
||||
/**
|
||||
|
@ -197,7 +198,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
*/
|
||||
#[Assert\Language]
|
||||
#[Groups(['full', 'import', 'user:read'])]
|
||||
#[ORM\Column(type: Types::STRING, name: 'config_language', nullable: true)]
|
||||
#[ORM\Column(name: 'config_language', type: Types::STRING, nullable: true)]
|
||||
protected ?string $language = '';
|
||||
|
||||
/**
|
||||
|
@ -310,7 +311,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
|
||||
#[Groups(['simple', 'extended', 'full', 'import'])]
|
||||
#[ORM\Embedded(class: 'PermissionData', columnPrefix: 'permissions_')]
|
||||
#[ValidPermission()]
|
||||
#[ValidPermission]
|
||||
protected ?PermissionData $permissions = null;
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ use App\Services\LogSystem\EventCommentHelper;
|
|||
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
|
||||
#[AsEventListener()]
|
||||
#[AsEventListener]
|
||||
class AddEditCommentRequestListener
|
||||
{
|
||||
public function __construct(private readonly EventCommentHelper $helper)
|
||||
|
|
|
@ -47,8 +47,8 @@ class ProviderSelectType extends AbstractType
|
|||
{
|
||||
$resolver->setDefaults([
|
||||
'choices' => $this->providerRegistry->getActiveProviders(),
|
||||
'choice_label' => ChoiceList::label($this, fn (?InfoProviderInterface $choice) => $choice?->getProviderInfo()['name']),
|
||||
'choice_value' => ChoiceList::value($this, fn(?InfoProviderInterface $choice) => $choice?->getProviderKey()),
|
||||
'choice_label' => ChoiceList::label($this, static fn (?InfoProviderInterface $choice) => $choice?->getProviderInfo()['name']),
|
||||
'choice_value' => ChoiceList::value($this, static fn(?InfoProviderInterface $choice) => $choice?->getProviderKey()),
|
||||
|
||||
'multiple' => true,
|
||||
]);
|
||||
|
|
|
@ -49,13 +49,15 @@ class ProjectAddPartsType extends AbstractType
|
|||
$builder->add('bom_entries', ProjectBOMEntryCollectionType::class, [
|
||||
'entry_options' => [
|
||||
'constraints' => [
|
||||
new UniqueEntity(fields: ['part', 'project'], entityClass: ProjectBOMEntry::class, message: 'project.bom_entry.part_already_in_bom'),
|
||||
new UniqueEntity(fields: ['name', 'project'], entityClass: ProjectBOMEntry::class, message: 'project.bom_entry.name_already_in_bom', ignoreNull: true),
|
||||
new UniqueEntity(fields: ['part', 'project'], message: 'project.bom_entry.part_already_in_bom',
|
||||
entityClass: ProjectBOMEntry::class),
|
||||
new UniqueEntity(fields: ['name', 'project'], message: 'project.bom_entry.name_already_in_bom',
|
||||
entityClass: ProjectBOMEntry::class, ignoreNull: true),
|
||||
]
|
||||
],
|
||||
'constraints' => [
|
||||
new UniqueObjectCollection(fields: ['part'], message: 'project.bom_entry.part_already_in_bom'),
|
||||
new UniqueObjectCollection(fields: ['name'], message: 'project.bom_entry.name_already_in_bom'),
|
||||
new UniqueObjectCollection(message: 'project.bom_entry.part_already_in_bom', fields: ['part']),
|
||||
new UniqueObjectCollection(message: 'project.bom_entry.name_already_in_bom', fields: ['name']),
|
||||
]
|
||||
]);
|
||||
$builder->add('submit', SubmitType::class, ['label' => 'save']);
|
||||
|
|
|
@ -34,7 +34,7 @@ class UserSelectType extends AbstractType
|
|||
{
|
||||
$resolver->setDefaults([
|
||||
'class' => User::class,
|
||||
'choice_label' => fn(Options $options) => fn(User $choice, $key, $value) => $choice->getFullName(true),
|
||||
'choice_label' => fn(Options $options) => static fn(User $choice, $key, $value) => $choice->getFullName(true),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ class FilenameSanatizer
|
|||
$filename = ltrim($filename, '.-');
|
||||
//Limit filename length to 255 bytes
|
||||
$ext = pathinfo($filename, PATHINFO_EXTENSION);
|
||||
$filename = mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext ? '.' . $ext : '');
|
||||
return $filename;
|
||||
return mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext ? '.' . $ext : '');
|
||||
}
|
||||
}
|
|
@ -35,6 +35,9 @@ abstract class AbstractMultiPlatformMigration extends AbstractMigration
|
|||
final public const ADMIN_PW_LENGTH = 10;
|
||||
protected string $admin_pw = '';
|
||||
|
||||
/** @noinspection SenselessProxyMethodInspection
|
||||
* This method is required to redefine the logger type hint to protected
|
||||
*/
|
||||
public function __construct(Connection $connection, protected LoggerInterface $logger)
|
||||
{
|
||||
parent::__construct($connection, $logger);
|
||||
|
|
|
@ -43,7 +43,7 @@ use function Symfony\Component\Translation\t;
|
|||
class AuthenticationEntryPoint implements AuthenticationEntryPointInterface
|
||||
{
|
||||
public function __construct(
|
||||
private UrlGeneratorInterface $urlGenerator,
|
||||
private readonly UrlGeneratorInterface $urlGenerator,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
|||
*/
|
||||
class DetermineTypeFromElementIRIDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
|
||||
{
|
||||
const SUPPORTED_CLASSES = [
|
||||
private const SUPPORTED_CLASSES = [
|
||||
Attachment::class,
|
||||
AbstractParameter::class
|
||||
];
|
||||
|
|
|
@ -54,7 +54,7 @@ class StructuralElementNormalizer implements NormalizerInterface
|
|||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function normalize($object, string $format = null, array $context = [])
|
||||
public function normalize($object, string $format = null, array $context = []): array
|
||||
{
|
||||
if (!$object instanceof AbstractStructuralDBElement) {
|
||||
throw new \InvalidArgumentException('This normalizer only supports AbstractStructural objects!');
|
||||
|
|
|
@ -448,7 +448,7 @@ class AttachmentSubmitHandler
|
|||
'g' => 1000 * 1000 * 1000,
|
||||
'gi' => 1 << 30,
|
||||
];
|
||||
if (ctype_digit((string) $maxSize)) {
|
||||
if (ctype_digit($maxSize)) {
|
||||
return (int) $maxSize;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,9 @@ class FileTypeFilterTools
|
|||
//Convert jpg to .jpg
|
||||
$element = '.'.$element;
|
||||
}
|
||||
|
||||
//Prevent weird side effects
|
||||
unset($element);
|
||||
}
|
||||
|
||||
$elements = array_unique($elements);
|
||||
|
|
|
@ -133,7 +133,7 @@ class ElementTypeNameGenerator
|
|||
{
|
||||
$type = $this->getLocalizedTypeLabel($entity);
|
||||
if ($use_html) {
|
||||
return '<i>'.$type.':</i> '.htmlspecialchars((string) $entity->getName());
|
||||
return '<i>'.$type.':</i> '.htmlspecialchars($entity->getName());
|
||||
}
|
||||
|
||||
return $type.': '.$entity->getName();
|
||||
|
|
|
@ -42,7 +42,7 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
use function \count;
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* This service is used to import the datastructures (categories, manufacturers, etc.) from a PartKeepr export.
|
||||
|
|
|
@ -222,7 +222,7 @@ trait PKImportHelperTrait
|
|||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function setCreationDate(TimeStampableInterface $entity, ?string $datetime_str)
|
||||
protected function setCreationDate(TimeStampableInterface $entity, ?string $datetime_str): void
|
||||
{
|
||||
if ($datetime_str !== null && $datetime_str !== '' && $datetime_str !== '0000-00-00 00:00:00') {
|
||||
$date = new \DateTime($datetime_str);
|
||||
|
@ -252,7 +252,7 @@ trait PKImportHelperTrait
|
|||
$prefixes = $data['siprefix'];
|
||||
foreach ($prefixes as $prefix) {
|
||||
if ((int) $prefix['id'] === $prefix_id) {
|
||||
return pow((int) $prefix['base'], (int) $prefix['exponent']);
|
||||
return (int)$prefix['base'] ** (int)$prefix['exponent'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class FileDTO
|
|||
//Find all occurrences of non URL safe characters and replace them with their URL encoded version.
|
||||
//We only want to replace characters which can not have a valid meaning in a URL (what would break the URL).
|
||||
//Digikey provided some wrong URLs with a ^ in them, which is not a valid URL character. (https://github.com/Part-DB/Part-DB-server/issues/521)
|
||||
$this->url = preg_replace_callback('/[^a-zA-Z0-9_\-.$+!*();\/?:@=&#%]/', fn($matches) => rawurlencode($matches[0]), $url);
|
||||
$this->url = preg_replace_callback('/[^a-zA-Z0-9_\-.$+!*();\/?:@=&#%]/', static fn($matches) => rawurlencode($matches[0]), $url);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ class Element14Provider implements InfoProviderInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @param mixed[]|null $datasheets
|
||||
* @param array|null $datasheets
|
||||
* @return FileDTO[]|null Array of FileDTOs
|
||||
*/
|
||||
private function parseDataSheets(?array $datasheets): ?array
|
||||
|
|
|
@ -40,7 +40,7 @@ class LCSCProvider implements InfoProviderInterface
|
|||
|
||||
public const DISTRIBUTOR_NAME = 'LCSC';
|
||||
|
||||
public function __construct(private readonly HttpClientInterface $lcscClient, private string $currency, private bool $enabled = true)
|
||||
public function __construct(private readonly HttpClientInterface $lcscClient, private readonly string $currency, private readonly bool $enabled = true)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -152,10 +152,7 @@ class LCSCProvider implements InfoProviderInterface
|
|||
}
|
||||
|
||||
//Build category by concatenating the catalogName and parentCatalogName
|
||||
$category = null;
|
||||
if (isset($product['parentCatalogName'])) {
|
||||
$category = $product['parentCatalogName'];
|
||||
}
|
||||
$category = $product['parentCatalogName'] ?? null;
|
||||
if (isset($product['catalogName'])) {
|
||||
$category = ($category ?? '') . ' -> ' . $product['catalogName'];
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ class OctopartProvider implements InfoProviderInterface
|
|||
|
||||
$item = $this->partInfoCache->getItem($key);
|
||||
$item->set($part);
|
||||
$item->expiresAfter(3600 * 24 * 1); //Cache for 1 day
|
||||
$item->expiresAfter(3600 * 24); //Cache for 1 day
|
||||
$this->partInfoCache->save($item);
|
||||
}
|
||||
|
||||
|
@ -295,7 +295,7 @@ class OctopartProvider implements InfoProviderInterface
|
|||
//Built the category full path
|
||||
$category = null;
|
||||
if (!empty($part['category']['name'])) {
|
||||
$category = implode(' -> ', array_map(fn($c) => $c['name'], $part['category']['ancestors'] ?? []));
|
||||
$category = implode(' -> ', array_map(static fn($c) => $c['name'], $part['category']['ancestors'] ?? []));
|
||||
if (!empty($category)) {
|
||||
$category .= ' -> ';
|
||||
}
|
||||
|
|
|
@ -49,11 +49,7 @@ class TMEClient
|
|||
|
||||
public function isUsable(): bool
|
||||
{
|
||||
if ($this->token === '' || $this->secret === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !($this->token === '' || $this->secret === '');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
|
|||
#[AsDecorator(decorates: DompdfFactoryInterface::class)]
|
||||
class DompdfFactory implements DompdfFactoryInterface
|
||||
{
|
||||
public function __construct(private string $fontDirectory, private string $tmpDirectory)
|
||||
public function __construct(private readonly string $fontDirectory, private readonly string $tmpDirectory)
|
||||
{
|
||||
//Create folder if it does not exist
|
||||
$this->createDirectoryIfNotExisting($this->fontDirectory);
|
||||
|
|
|
@ -119,7 +119,7 @@ final class PartProvider implements PlaceholderProviderInterface
|
|||
}
|
||||
|
||||
if ('[[DESCRIPTION_T]]' === $placeholder) {
|
||||
return strip_tags((string) $parsedown->line($part->getDescription()));
|
||||
return strip_tags($parsedown->line($part->getDescription()));
|
||||
}
|
||||
|
||||
if ('[[COMMENT]]' === $placeholder) {
|
||||
|
@ -127,7 +127,7 @@ final class PartProvider implements PlaceholderProviderInterface
|
|||
}
|
||||
|
||||
if ('[[COMMENT_T]]' === $placeholder) {
|
||||
return strip_tags((string) $parsedown->line($part->getComment()));
|
||||
return strip_tags($parsedown->line($part->getComment()));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -41,7 +41,7 @@ class LogDataFormatter
|
|||
public function formatData(mixed $data, AbstractLogEntry $logEntry, string $fieldName): string
|
||||
{
|
||||
if (is_string($data)) {
|
||||
$tmp = '<span class="text-muted user-select-none">"</span>' . mb_strimwidth(htmlspecialchars($data), 0, self::STRING_MAX_LENGTH, ) . '<span class="text-muted user-select-none">"</span>';
|
||||
$tmp = '<span class="text-muted user-select-none">"</span>' . mb_strimwidth(htmlspecialchars($data), 0, self::STRING_MAX_LENGTH) . '<span class="text-muted user-select-none">"</span>';
|
||||
|
||||
//Show special characters and line breaks
|
||||
$tmp = preg_replace('/\n/', '<span class="text-muted user-select-none">\\n</span><br>', $tmp);
|
||||
|
@ -87,7 +87,7 @@ class LogDataFormatter
|
|||
|
||||
private function formatJSON(array $data): string
|
||||
{
|
||||
$json = htmlspecialchars(json_encode($data, JSON_PRETTY_PRINT), ENT_QUOTES | ENT_SUBSTITUTE);
|
||||
$json = htmlspecialchars(json_encode($data, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT), ENT_QUOTES | ENT_SUBSTITUTE);
|
||||
|
||||
return sprintf(
|
||||
'<div data-controller="elements--json-formatter" data-json="%s"></div>',
|
||||
|
|
|
@ -105,7 +105,7 @@ class DBInfoHelper
|
|||
*/
|
||||
public function getDatabaseName(): ?string
|
||||
{
|
||||
return $this->connection->getDatabase() ?? null;
|
||||
return $this->connection->getDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -98,7 +98,7 @@ final class OAuthTokenManager
|
|||
$token = $this->getToken($app_name);
|
||||
|
||||
if (!$token) {
|
||||
throw new \Exception('No token was saved yet for '.$app_name);
|
||||
throw new \RuntimeException('No token was saved yet for '.$app_name);
|
||||
}
|
||||
|
||||
$client = $this->clientRegistry->getClient($app_name);
|
||||
|
|
|
@ -17,7 +17,7 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
final class PartLotWithdrawAddHelper
|
||||
{
|
||||
public function __construct(private readonly EventLogger $eventLogger,
|
||||
private readonly EventCommentHelper $eventCommentHelper, private EntityManagerInterface $entityManager)
|
||||
private readonly EventCommentHelper $eventCommentHelper, private readonly EntityManagerInterface $entityManager)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ class NodesListBuilder
|
|||
/** @var StructuralDBElementRepository $repo */
|
||||
$repo = $this->em->getRepository($class_name);
|
||||
|
||||
return array_map(fn(AbstractDBElement $element) => $element->getID(), $repo->getFlatList($parent));
|
||||
return array_map(static fn(AbstractDBElement $element) => $element->getID(), $repo->getFlatList($parent));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class TreeViewGenerator
|
|||
protected ElementCacheTagGenerator $tagGenerator,
|
||||
protected UserCacheKeyGenerator $keyGenerator,
|
||||
protected TranslatorInterface $translator,
|
||||
private UrlGeneratorInterface $router,
|
||||
private readonly UrlGeneratorInterface $router,
|
||||
protected bool $rootNodeExpandedByDefault,
|
||||
protected bool $rootNodeEnabled,
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ class DecoratedGoogleAuthenticator implements GoogleAuthenticatorInterface
|
|||
|
||||
public function __construct(
|
||||
#[AutowireDecorated]
|
||||
private GoogleAuthenticatorInterface $inner,
|
||||
private RequestStack $requestStack)
|
||||
private readonly GoogleAuthenticatorInterface $inner,
|
||||
private readonly RequestStack $requestStack)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class PartDBInfoProvider implements ProviderInterface
|
|||
public function __construct(private readonly VersionManagerInterface $versionManager,
|
||||
private readonly GitVersionInfo $gitVersionInfo,
|
||||
private readonly string $partdb_title,
|
||||
private string $base_currency,
|
||||
private readonly string $base_currency,
|
||||
private readonly BannerHelper $bannerHelper,
|
||||
private readonly string $default_uri,
|
||||
private readonly string $global_timezone,
|
||||
|
|
|
@ -86,11 +86,7 @@ class UniqueObjectCollectionValidator extends ConstraintValidator
|
|||
|
||||
private function getNormalizer(UniqueObjectCollection $unique): callable
|
||||
{
|
||||
if (null === $unique->normalizer) {
|
||||
return static fn ($value) => $value;
|
||||
}
|
||||
|
||||
return $unique->normalizer;
|
||||
return $unique->normalizer ?? static fn($value) => $value;
|
||||
}
|
||||
|
||||
private function reduceElementKeys(array $fields, array $element, UniqueObjectCollection $constraint): array
|
||||
|
|
|
@ -38,7 +38,7 @@ use function strlen;
|
|||
|
||||
class ValidGoogleAuthCodeValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(private GoogleAuthenticatorInterface $googleAuthenticator, private Security $security)
|
||||
public function __construct(private readonly GoogleAuthenticatorInterface $googleAuthenticator, private readonly Security $security)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue