Use imports instead of FQNs

This commit is contained in:
Jan Böhmer 2023-06-11 14:55:06 +02:00
parent f63b6d7207
commit 5629215ce4
179 changed files with 792 additions and 597 deletions

View file

@ -14,6 +14,11 @@ return static function (RectorConfig $rectorConfig): void {
$rectorConfig->symfonyContainerXml(__DIR__ . '/var/cache/dev/App_KernelDevDebugContainer.xml'); $rectorConfig->symfonyContainerXml(__DIR__ . '/var/cache/dev/App_KernelDevDebugContainer.xml');
$rectorConfig->symfonyContainerPhp(__DIR__ . '/tests/symfony-container.php'); $rectorConfig->symfonyContainerPhp(__DIR__ . '/tests/symfony-container.php');
//Import class names instead of using fully qualified class names
$rectorConfig->importNames();
//But keep the fully qualified class names for classes in the global namespace
$rectorConfig->importShortClasses(false);
$rectorConfig->paths([ $rectorConfig->paths([
__DIR__ . '/config', __DIR__ . '/config',
__DIR__ . '/public', __DIR__ . '/public',

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Command\Attachments; namespace App\Command\Attachments;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Services\Attachments\AttachmentManager; use App\Services\Attachments\AttachmentManager;
use App\Services\Attachments\AttachmentPathResolver; use App\Services\Attachments\AttachmentPathResolver;
use App\Services\Attachments\AttachmentReverseSearch; use App\Services\Attachments\AttachmentReverseSearch;
@ -40,7 +41,7 @@ use function count;
use const DIRECTORY_SEPARATOR; use const DIRECTORY_SEPARATOR;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:attachments:clean-unused|app:clean-attachments', 'Lists (and deletes if wanted) attachments files that are not used anymore (abandoned files).')] #[AsCommand('partdb:attachments:clean-unused|app:clean-attachments', 'Lists (and deletes if wanted) attachments files that are not used anymore (abandoned files).')]
class CleanAttachmentsCommand extends Command class CleanAttachmentsCommand extends Command
{ {
protected MimeTypes $mimeTypeGuesser; protected MimeTypes $mimeTypeGuesser;
@ -99,7 +100,7 @@ class CleanAttachmentsCommand extends Command
if (!$continue) { if (!$continue) {
//We are finished here, when no files should be deleted //We are finished here, when no files should be deleted
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
//Delete the files //Delete the files
@ -112,7 +113,7 @@ class CleanAttachmentsCommand extends Command
$io->success('No abandoned files found.'); $io->success('No abandoned files found.');
} }
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
/** /**

View file

@ -2,6 +2,8 @@
namespace App\Command; namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use PhpZip\Constants\ZipCompressionMethod; use PhpZip\Constants\ZipCompressionMethod;
@ -16,7 +18,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:backup', 'Backup the files and the database of Part-DB')] #[AsCommand('partdb:backup', 'Backup the files and the database of Part-DB')]
class BackupCommand extends Command class BackupCommand extends Command
{ {
public function __construct(private readonly string $project_dir, private readonly EntityManagerInterface $entityManager) public function __construct(private readonly string $project_dir, private readonly EntityManagerInterface $entityManager)
@ -153,7 +155,7 @@ class BackupCommand extends Command
$io->error('Could not dump database: '.$e->getMessage()); $io->error('Could not dump database: '.$e->getMessage());
$io->error('This can maybe be fixed by installing the mysqldump binary and adding it to the PATH variable!'); $io->error('This can maybe be fixed by installing the mysqldump binary and adding it to the PATH variable!');
} }
} elseif ($connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) { } elseif ($connection->getDatabasePlatform() instanceof SqlitePlatform) {
$io->note('SQLite database detected. Copy DB file to ZIP...'); $io->note('SQLite database detected. Copy DB file to ZIP...');
$params = $connection->getParams(); $params = $connection->getParams();
$zip->addFile($params['path'], 'var/app.db'); $zip->addFile($params['path'], 'var/app.db');

View file

@ -20,6 +20,7 @@
namespace App\Command; namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@ -27,7 +28,7 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:check-requirements', 'Checks if the requirements Part-DB needs or recommends are fulfilled.')] #[AsCommand('partdb:check-requirements', 'Checks if the requirements Part-DB needs or recommends are fulfilled.')]
class CheckRequirementsCommand extends Command class CheckRequirementsCommand extends Command
{ {
public function __construct(protected ContainerBagInterface $params) public function __construct(protected ContainerBagInterface $params)

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Command\Currencies; namespace App\Command\Currencies;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\PriceInformations\Currency; use App\Entity\PriceInformations\Currency;
use App\Services\Tools\ExchangeRateUpdater; use App\Services\Tools\ExchangeRateUpdater;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -35,7 +36,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
use function count; use function count;
use function strlen; use function strlen;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:currencies:update-exchange-rates|partdb:update-exchange-rates|app:update-exchange-rates', 'Updates the currency exchange rates.')] #[AsCommand('partdb:currencies:update-exchange-rates|partdb:update-exchange-rates|app:update-exchange-rates', 'Updates the currency exchange rates.')]
class UpdateExchangeRatesCommand extends Command class UpdateExchangeRatesCommand extends Command
{ {
public function __construct(protected string $base_current, protected EntityManagerInterface $em, protected ExchangeRateUpdater $exchangeRateUpdater) public function __construct(protected string $base_current, protected EntityManagerInterface $em, protected ExchangeRateUpdater $exchangeRateUpdater)
@ -56,7 +57,7 @@ class UpdateExchangeRatesCommand extends Command
if (3 !== strlen($this->base_current)) { if (3 !== strlen($this->base_current)) {
$io->error('Chosen Base current is not valid. Check your settings!'); $io->error('Chosen Base current is not valid. Check your settings!');
return \Symfony\Component\Console\Command\Command::FAILURE; return Command::FAILURE;
} }
$io->note('Update currency exchange rates with base currency: '.$this->base_current); $io->note('Update currency exchange rates with base currency: '.$this->base_current);
@ -89,6 +90,6 @@ class UpdateExchangeRatesCommand extends Command
$io->success(sprintf('%d (of %d) currency exchange rates were updated.', $success_counter, count($candidates))); $io->success(sprintf('%d (of %d) currency exchange rates were updated.', $success_counter, count($candidates)));
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
} }

View file

@ -22,6 +22,8 @@ declare(strict_types=1);
namespace App\Command\Logs; namespace App\Command\Logs;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\UserSystem\User;
use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\LogSystem\AbstractLogEntry; use App\Entity\LogSystem\AbstractLogEntry;
use App\Repository\LogEntryRepository; use App\Repository\LogEntryRepository;
@ -36,7 +38,7 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:logs:show|app:show-logs', 'List the last event log entries.')] #[AsCommand('partdb:logs:show|app:show-logs', 'List the last event log entries.')]
class ShowEventLogCommand extends Command class ShowEventLogCommand extends Command
{ {
protected LogEntryRepository $repo; protected LogEntryRepository $repo;
@ -65,7 +67,7 @@ class ShowEventLogCommand extends Command
if ($page > $max_page && $max_page > 0) { if ($page > $max_page && $max_page > 0) {
$io->error("There is no page ${page}! The maximum page is ${max_page}."); $io->error("There is no page ${page}! The maximum page is ${max_page}.");
return \Symfony\Component\Console\Command\Command::FAILURE; return Command::FAILURE;
} }
$io->note("There are a total of ${total_count} log entries in the DB."); $io->note("There are a total of ${total_count} log entries in the DB.");
@ -75,14 +77,14 @@ class ShowEventLogCommand extends Command
$this->showPage($output, $desc, $limit, $page, $max_page, $showExtra); $this->showPage($output, $desc, $limit, $page, $max_page, $showExtra);
if ($onePage) { if ($onePage) {
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
$continue = $io->confirm('Do you want to show the next page?'); $continue = $io->confirm('Do you want to show the next page?');
++$page; ++$page;
} }
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
protected function configure(): void protected function configure(): void
@ -136,7 +138,7 @@ class ShowEventLogCommand extends Command
$target_class = $this->elementTypeNameGenerator->getLocalizedTypeLabel($entry->getTargetClass()); $target_class = $this->elementTypeNameGenerator->getLocalizedTypeLabel($entry->getTargetClass());
} }
if ($entry->getUser() instanceof \App\Entity\UserSystem\User) { if ($entry->getUser() instanceof User) {
$user = $entry->getUser()->getFullName(true); $user = $entry->getUser()->getFullName(true);
} elseif ($entry->isCLIEntry()) { } elseif ($entry->isCLIEntry()) {
$user = $entry->getCLIUsername() . ' [CLI]'; $user = $entry->getCLIUsername() . ' [CLI]';

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Command\Migrations; namespace App\Command\Migrations;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentType;
use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\Project;
@ -47,7 +48,7 @@ use function count;
/** /**
* This command converts the BBCode used by old Part-DB versions (<1.0), to the current used Markdown format. * This command converts the BBCode used by old Part-DB versions (<1.0), to the current used Markdown format.
*/ */
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:migrations:convert-bbcode|app:convert-bbcode', 'Converts BBCode used in old Part-DB versions to newly used Markdown')] #[AsCommand('partdb:migrations:convert-bbcode|app:convert-bbcode', 'Converts BBCode used in old Part-DB versions to newly used Markdown')]
class ConvertBBCodeCommand extends Command class ConvertBBCodeCommand extends Command
{ {
/** /**
@ -159,6 +160,6 @@ class ConvertBBCodeCommand extends Command
$io->success('Changes saved to DB successfully!'); $io->success('Changes saved to DB successfully!');
} }
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
} }

View file

@ -20,6 +20,7 @@
namespace App\Command\Migrations; namespace App\Command\Migrations;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Services\ImportExportSystem\PartKeeprImporter\PKDatastructureImporter; use App\Services\ImportExportSystem\PartKeeprImporter\PKDatastructureImporter;
use App\Services\ImportExportSystem\PartKeeprImporter\MySQLDumpXMLConverter; use App\Services\ImportExportSystem\PartKeeprImporter\MySQLDumpXMLConverter;
use App\Services\ImportExportSystem\PartKeeprImporter\PKImportHelper; use App\Services\ImportExportSystem\PartKeeprImporter\PKImportHelper;
@ -33,7 +34,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:migrations:import-partkeepr', 'Import a PartKeepr database XML dump into Part-DB')] #[AsCommand('partdb:migrations:import-partkeepr', 'Import a PartKeepr database XML dump into Part-DB')]
class ImportPartKeeprCommand extends Command class ImportPartKeeprCommand extends Command
{ {
@ -85,7 +86,7 @@ class ImportPartKeeprCommand extends Command
if (!$this->importHelper->checkVersion($data)) { if (!$this->importHelper->checkVersion($data)) {
$db_version = $this->importHelper->getDatabaseSchemaVersion($data); $db_version = $this->importHelper->getDatabaseSchemaVersion($data);
$io->error('The version of the imported database is not supported! (Version: '.$db_version.')'); $io->error('The version of the imported database is not supported! (Version: '.$db_version.')');
return \Symfony\Component\Console\Command\Command::FAILURE; return Command::FAILURE;
} }
//Import the mandatory data //Import the mandatory data
@ -103,7 +104,7 @@ class ImportPartKeeprCommand extends Command
$io->success('Imported '.$count.' users.'); $io->success('Imported '.$count.' users.');
} }
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
private function doImport(SymfonyStyle $io, array $data): void private function doImport(SymfonyStyle $io, array $data): void

View file

@ -20,6 +20,7 @@
namespace App\Command\User; namespace App\Command\User;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use App\Security\SamlUserFactory; use App\Security\SamlUserFactory;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -30,7 +31,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:user:convert-to-saml-user|partdb:users:convert-to-saml-user', 'Converts a local user to a SAML user (and vice versa)')] #[AsCommand('partdb:user:convert-to-saml-user|partdb:users:convert-to-saml-user', 'Converts a local user to a SAML user (and vice versa)')]
class ConvertToSAMLUserCommand extends Command class ConvertToSAMLUserCommand extends Command
{ {
public function __construct(protected EntityManagerInterface $entityManager, protected bool $saml_enabled) public function __construct(protected EntityManagerInterface $entityManager, protected bool $saml_enabled)
@ -62,7 +63,7 @@ class ConvertToSAMLUserCommand extends Command
if (!$user) { if (!$user) {
$io->error('User not found!'); $io->error('User not found!');
return \Symfony\Component\Console\Command\Command::FAILURE; return Command::FAILURE;
} }
$io->info('User found: '.$user->getFullName(true) . ': '.$user->getEmail().' [ID: ' . $user->getID() . ']'); $io->info('User found: '.$user->getFullName(true) . ': '.$user->getEmail().' [ID: ' . $user->getID() . ']');

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Command\User; namespace App\Command\User;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use App\Events\SecurityEvent; use App\Events\SecurityEvent;
use App\Events\SecurityEvents; use App\Events\SecurityEvents;
@ -34,7 +35,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:users:set-password|app:set-password|users:set-password|partdb:user:set-password', 'Sets the password of a user')] #[AsCommand('partdb:users:set-password|app:set-password|users:set-password|partdb:user:set-password', 'Sets the password of a user')]
class SetPasswordCommand extends Command class SetPasswordCommand extends Command
{ {
public function __construct(protected EntityManagerInterface $entityManager, protected UserPasswordHasherInterface $encoder, protected EventDispatcherInterface $eventDispatcher) public function __construct(protected EntityManagerInterface $entityManager, protected UserPasswordHasherInterface $encoder, protected EventDispatcherInterface $eventDispatcher)
@ -56,17 +57,17 @@ class SetPasswordCommand extends Command
$user = $this->entityManager->getRepository(User::class)->findByEmailOrName($user_name); $user = $this->entityManager->getRepository(User::class)->findByEmailOrName($user_name);
if (!$user instanceof \App\Entity\UserSystem\User) { if (!$user instanceof User) {
$io->error(sprintf('No user with the given username %s found in the database!', $user_name)); $io->error(sprintf('No user with the given username %s found in the database!', $user_name));
return \Symfony\Component\Console\Command\Command::FAILURE; return Command::FAILURE;
} }
$io->note('User found!'); $io->note('User found!');
if ($user->isSamlUser()) { if ($user->isSamlUser()) {
$io->error('This user is a SAML user, so you can not change the password!'); $io->error('This user is a SAML user, so you can not change the password!');
return \Symfony\Component\Console\Command\Command::FAILURE; return Command::FAILURE;
} }
$proceed = $io->confirm( $proceed = $io->confirm(
@ -74,7 +75,7 @@ class SetPasswordCommand extends Command
$user->getFullName(true), $user->getID())); $user->getFullName(true), $user->getID()));
if (!$proceed) { if (!$proceed) {
return \Symfony\Component\Console\Command\Command::FAILURE; return Command::FAILURE;
} }
$success = false; $success = false;
@ -105,6 +106,6 @@ class SetPasswordCommand extends Command
$security_event = new SecurityEvent($user); $security_event = new SecurityEvent($user);
$this->eventDispatcher->dispatch($security_event, SecurityEvents::PASSWORD_CHANGED); $this->eventDispatcher->dispatch($security_event, SecurityEvents::PASSWORD_CHANGED);
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
} }

View file

@ -20,6 +20,7 @@
namespace App\Command\User; namespace App\Command\User;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\UserSystem\Group; use App\Entity\UserSystem\Group;
use App\Entity\UserSystem\PermissionData; use App\Entity\UserSystem\PermissionData;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
@ -31,7 +32,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:users:upgrade-permissions-schema', '(Manually) upgrades the permissions schema of all users to the latest version.')] #[AsCommand('partdb:users:upgrade-permissions-schema', '(Manually) upgrades the permissions schema of all users to the latest version.')]
final class UpgradePermissionsSchemaCommand extends Command final class UpgradePermissionsSchemaCommand extends Command
{ {
public function __construct(private readonly PermissionSchemaUpdater $permissionSchemaUpdater, private readonly EntityManagerInterface $em, private readonly EventCommentHelper $eventCommentHelper) public function __construct(private readonly PermissionSchemaUpdater $permissionSchemaUpdater, private readonly EntityManagerInterface $em, private readonly EventCommentHelper $eventCommentHelper)
@ -74,7 +75,7 @@ final class UpgradePermissionsSchemaCommand extends Command
if ($groups_to_upgrade === [] && $users_to_upgrade === []) { if ($groups_to_upgrade === [] && $users_to_upgrade === []) {
$io->success('All users and group permissions schemas are up-to-date. No update needed.'); $io->success('All users and group permissions schemas are up-to-date. No update needed.');
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
//List all users and groups that need an update //List all users and groups that need an update
@ -86,7 +87,7 @@ final class UpgradePermissionsSchemaCommand extends Command
if(!$io->confirm('Continue with the update?', false)) { if(!$io->confirm('Continue with the update?', false)) {
$io->warning('Update aborted.'); $io->warning('Update aborted.');
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
//Update all users and groups //Update all users and groups

View file

@ -20,6 +20,7 @@
namespace App\Command\User; namespace App\Command\User;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
@ -29,7 +30,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:users:enable|partdb:user:enable', 'Enables/Disable the login of one or more users')] #[AsCommand('partdb:users:enable|partdb:user:enable', 'Enables/Disable the login of one or more users')]
class UserEnableCommand extends Command class UserEnableCommand extends Command
{ {
public function __construct(protected EntityManagerInterface $entityManager, string $name = null) public function __construct(protected EntityManagerInterface $entityManager, string $name = null)
@ -66,7 +67,7 @@ class UserEnableCommand extends Command
} else { //Otherwise, fetch the users from DB } else { //Otherwise, fetch the users from DB
foreach ($usernames as $username) { foreach ($usernames as $username) {
$user = $repo->findByEmailOrName($username); $user = $repo->findByEmailOrName($username);
if (!$user instanceof \App\Entity\UserSystem\User) { if (!$user instanceof User) {
$io->error('No user found with username: '.$username); $io->error('No user found with username: '.$username);
return self::FAILURE; return self::FAILURE;
} }

View file

@ -20,6 +20,8 @@
namespace App\Command\User; namespace App\Command\User;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\UserSystem\Group;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
@ -28,7 +30,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:users:list|users:list', 'Lists all users')] #[AsCommand('partdb:users:list|users:list', 'Lists all users')]
class UserListCommand extends Command class UserListCommand extends Command
{ {
public function __construct(protected EntityManagerInterface $entityManager) public function __construct(protected EntityManagerInterface $entityManager)
@ -79,7 +81,7 @@ class UserListCommand extends Command
$user->getUsername(), $user->getUsername(),
$user->getFullName(), $user->getFullName(),
$user->getEmail(), $user->getEmail(),
$user->getGroup() instanceof \App\Entity\UserSystem\Group ? $user->getGroup()->getName() . ' (ID: ' . $user->getGroup()->getID() . ')' : 'No group', $user->getGroup() instanceof Group ? $user->getGroup()->getName() . ' (ID: ' . $user->getGroup()->getID() . ')' : 'No group',
$user->isDisabled() ? 'Yes' : 'No', $user->isDisabled() ? 'Yes' : 'No',
$user->isSAMLUser() ? 'SAML' : 'Local', $user->isSAMLUser() ? 'SAML' : 'Local',
]); ]);

View file

@ -20,6 +20,7 @@
namespace App\Command\User; namespace App\Command\User;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use App\Repository\UserRepository; use App\Repository\UserRepository;
use App\Services\UserSystem\PermissionManager; use App\Services\UserSystem\PermissionManager;
@ -34,7 +35,7 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:users:permissions|partdb:user:permissions', 'View and edit the permissions of a given user')] #[AsCommand('partdb:users:permissions|partdb:user:permissions', 'View and edit the permissions of a given user')]
class UsersPermissionsCommand extends Command class UsersPermissionsCommand extends Command
{ {
protected UserRepository $userRepository; protected UserRepository $userRepository;
@ -65,7 +66,7 @@ class UsersPermissionsCommand extends Command
//Find user //Find user
$io->note('Finding user with username: ' . $username); $io->note('Finding user with username: ' . $username);
$user = $this->userRepository->findByEmailOrName($username); $user = $this->userRepository->findByEmailOrName($username);
if (!$user instanceof \App\Entity\UserSystem\User) { if (!$user instanceof User) {
$io->error('No user found with username: ' . $username); $io->error('No user found with username: ' . $username);
return Command::FAILURE; return Command::FAILURE;
} }

View file

@ -20,6 +20,7 @@
namespace App\Command; namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use App\Services\Misc\GitVersionInfo; use App\Services\Misc\GitVersionInfo;
use Shivas\VersioningBundle\Service\VersionManagerInterface; use Shivas\VersioningBundle\Service\VersionManagerInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
@ -27,7 +28,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:version|app:version', 'Shows the currently installed version of Part-DB.')] #[AsCommand('partdb:version|app:version', 'Shows the currently installed version of Part-DB.')]
class VersionCommand extends Command class VersionCommand extends Command
{ {
public function __construct(protected VersionManagerInterface $versionManager, protected GitVersionInfo $gitVersionInfo) public function __construct(protected VersionManagerInterface $versionManager, protected GitVersionInfo $gitVersionInfo)
@ -57,6 +58,6 @@ class VersionCommand extends Command
$io->info('OS: '. php_uname()); $io->info('OS: '. php_uname());
$io->info('PHP extension: '. implode(', ', get_loaded_extensions())); $io->info('PHP extension: '. implode(', ', get_loaded_extensions()));
return \Symfony\Component\Console\Command\Command::SUCCESS; return Command::SUCCESS;
} }
} }

View file

@ -245,7 +245,7 @@ abstract class BaseAdminController extends AbstractController
protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AbstractNamedDBElement $entity = null) protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AbstractNamedDBElement $entity = null)
{ {
$new_entity = $entity instanceof \App\Entity\Base\AbstractNamedDBElement ? clone $entity : new $this->entity_class(); $new_entity = $entity instanceof AbstractNamedDBElement ? clone $entity : new $this->entity_class();
$this->denyAccessUnlessGranted('read', $new_entity); $this->denyAccessUnlessGranted('read', $new_entity);

View file

@ -73,11 +73,11 @@ class LabelController extends AbstractController
$this->denyAccessUnlessGranted('@labels.create_labels'); $this->denyAccessUnlessGranted('@labels.create_labels');
//If we inherit a LabelProfile, the user need to have access to it... //If we inherit a LabelProfile, the user need to have access to it...
if ($profile instanceof \App\Entity\LabelSystem\LabelProfile) { if ($profile instanceof LabelProfile) {
$this->denyAccessUnlessGranted('read', $profile); $this->denyAccessUnlessGranted('read', $profile);
} }
$label_options = $profile instanceof \App\Entity\LabelSystem\LabelProfile ? $profile->getOptions() : new LabelOptions(); $label_options = $profile instanceof LabelProfile ? $profile->getOptions() : new LabelOptions();
//We have to disable the options, if twig mode is selected and user is not allowed to use it. //We have to disable the options, if twig mode is selected and user is not allowed to use it.
$disable_options = 'twig' === $label_options->getLinesMode() && !$this->isGranted('@labels.use_twig'); $disable_options = 'twig' === $label_options->getLinesMode() && !$this->isGranted('@labels.use_twig');
@ -91,7 +91,7 @@ class LabelController extends AbstractController
$target_id = $request->query->get('target_id', null); $target_id = $request->query->get('target_id', null);
$generate = $request->query->getBoolean('generate', false); $generate = $request->query->getBoolean('generate', false);
if (!$profile instanceof \App\Entity\LabelSystem\LabelProfile && is_string($target_type)) { if (!$profile instanceof LabelProfile && is_string($target_type)) {
$label_options->setSupportedElement($target_type); $label_options->setSupportedElement($target_type);
} }
if (is_string($target_id)) { if (is_string($target_id)) {
@ -108,7 +108,7 @@ class LabelController extends AbstractController
$filename = 'invalid.pdf'; $filename = 'invalid.pdf';
//Generate PDF either when the form is submitted and valid, or the form was not submit yet, and generate is set //Generate PDF either when the form is submitted and valid, or the form was not submit yet, and generate is set
if (($form->isSubmitted() && $form->isValid()) || ($generate && !$form->isSubmitted() && $profile instanceof \App\Entity\LabelSystem\LabelProfile)) { if (($form->isSubmitted() && $form->isValid()) || ($generate && !$form->isSubmitted() && $profile instanceof LabelProfile)) {
$target_id = (string) $form->get('target_id')->getData(); $target_id = (string) $form->get('target_id')->getData();
$targets = $this->findObjects($form_options->getSupportedElement(), $target_id); $targets = $this->findObjects($form_options->getSupportedElement(), $target_id);
if ($targets !== []) { if ($targets !== []) {

View file

@ -141,7 +141,7 @@ class LogController extends AbstractController
} }
$log_element = $this->entityManager->find(AbstractLogEntry::class, $id); $log_element = $this->entityManager->find(AbstractLogEntry::class, $id);
if (!$log_element instanceof \App\Entity\LogSystem\AbstractLogEntry) { if (!$log_element instanceof AbstractLogEntry) {
throw new InvalidArgumentException('No log entry with the given ID is existing!'); throw new InvalidArgumentException('No log entry with the given ID is existing!');
} }

View file

@ -210,13 +210,13 @@ class PartController extends AbstractController
?Part $part = null, ?Project $project = null): Response ?Part $part = null, ?Project $project = null): Response
{ {
if ($part instanceof \App\Entity\Parts\Part) { if ($part instanceof Part) {
//Clone part //Clone part
$new_part = clone $part; $new_part = clone $part;
} elseif ($project instanceof \App\Entity\ProjectSystem\Project) { } elseif ($project instanceof Project) {
//Initialize a new part for a build part from the given project //Initialize a new part for a build part from the given project
//Ensure that the project has not already a build part //Ensure that the project has not already a build part
if ($project->getBuildPart() instanceof \App\Entity\Parts\Part) { if ($project->getBuildPart() instanceof Part) {
$this->addFlash('error', 'part.new_build_part.error.build_part_already_exists'); $this->addFlash('error', 'part.new_build_part.error.build_part_already_exists');
return $this->redirectToRoute('part_edit', ['id' => $project->getBuildPart()->getID()]); return $this->redirectToRoute('part_edit', ['id' => $project->getBuildPart()->getID()]);
} }
@ -229,7 +229,7 @@ class PartController extends AbstractController
$cid = $request->get('category', null); $cid = $request->get('category', null);
$category = $cid ? $em->find(Category::class, $cid) : null; $category = $cid ? $em->find(Category::class, $cid) : null;
if ($category instanceof \App\Entity\Parts\Category && !$new_part->getCategory() instanceof \App\Entity\Parts\Category) { if ($category instanceof Category && !$new_part->getCategory() instanceof Category) {
$new_part->setCategory($category); $new_part->setCategory($category);
$new_part->setDescription($category->getDefaultDescription()); $new_part->setDescription($category->getDefaultDescription());
$new_part->setComment($category->getDefaultComment()); $new_part->setComment($category->getDefaultComment());
@ -237,19 +237,19 @@ class PartController extends AbstractController
$fid = $request->get('footprint', null); $fid = $request->get('footprint', null);
$footprint = $fid ? $em->find(Footprint::class, $fid) : null; $footprint = $fid ? $em->find(Footprint::class, $fid) : null;
if ($footprint instanceof \App\Entity\Parts\Footprint && !$new_part->getFootprint() instanceof \App\Entity\Parts\Footprint) { if ($footprint instanceof Footprint && !$new_part->getFootprint() instanceof Footprint) {
$new_part->setFootprint($footprint); $new_part->setFootprint($footprint);
} }
$mid = $request->get('manufacturer', null); $mid = $request->get('manufacturer', null);
$manufacturer = $mid ? $em->find(Manufacturer::class, $mid) : null; $manufacturer = $mid ? $em->find(Manufacturer::class, $mid) : null;
if ($manufacturer instanceof \App\Entity\Parts\Manufacturer && !$new_part->getManufacturer() instanceof \App\Entity\Parts\Manufacturer) { if ($manufacturer instanceof Manufacturer && !$new_part->getManufacturer() instanceof Manufacturer) {
$new_part->setManufacturer($manufacturer); $new_part->setManufacturer($manufacturer);
} }
$store_id = $request->get('storelocation', null); $store_id = $request->get('storelocation', null);
$storelocation = $store_id ? $em->find(Storelocation::class, $store_id) : null; $storelocation = $store_id ? $em->find(Storelocation::class, $store_id) : null;
if ($storelocation instanceof \App\Entity\Parts\Storelocation && $new_part->getPartLots()->isEmpty()) { if ($storelocation instanceof Storelocation && $new_part->getPartLots()->isEmpty()) {
$partLot = new PartLot(); $partLot = new PartLot();
$partLot->setStorageLocation($storelocation); $partLot->setStorageLocation($storelocation);
$partLot->setInstockUnknown(true); $partLot->setInstockUnknown(true);
@ -258,7 +258,7 @@ class PartController extends AbstractController
$supplier_id = $request->get('supplier', null); $supplier_id = $request->get('supplier', null);
$supplier = $supplier_id ? $em->find(Supplier::class, $supplier_id) : null; $supplier = $supplier_id ? $em->find(Supplier::class, $supplier_id) : null;
if ($supplier instanceof \App\Entity\Parts\Supplier && $new_part->getOrderdetails()->isEmpty()) { if ($supplier instanceof Supplier && $new_part->getOrderdetails()->isEmpty()) {
$orderdetail = new Orderdetail(); $orderdetail = new Orderdetail();
$orderdetail->setSupplier($supplier); $orderdetail->setSupplier($supplier);
$new_part->addOrderdetail($orderdetail); $new_part->addOrderdetail($orderdetail);
@ -329,7 +329,7 @@ class PartController extends AbstractController
if ($this->isCsrfTokenValid('part_withraw' . $part->getID(), $request->request->get('_csfr'))) { if ($this->isCsrfTokenValid('part_withraw' . $part->getID(), $request->request->get('_csfr'))) {
//Retrieve partlot from the request //Retrieve partlot from the request
$partLot = $em->find(PartLot::class, $request->request->get('lot_id')); $partLot = $em->find(PartLot::class, $request->request->get('lot_id'));
if(!$partLot instanceof \App\Entity\Parts\PartLot) { if(!$partLot instanceof PartLot) {
throw new \RuntimeException('Part lot not found!'); throw new \RuntimeException('Part lot not found!');
} }
//Ensure that the partlot belongs to the part //Ensure that the partlot belongs to the part

View file

@ -193,7 +193,7 @@ class ProjectController extends AbstractController
#[Route(path: '/{id}/add_parts', name: 'project_add_parts', requirements: ['id' => '\d+'])] #[Route(path: '/{id}/add_parts', name: 'project_add_parts', requirements: ['id' => '\d+'])]
public function addPart(Request $request, EntityManagerInterface $entityManager, ?Project $project): Response public function addPart(Request $request, EntityManagerInterface $entityManager, ?Project $project): Response
{ {
if($project instanceof \App\Entity\ProjectSystem\Project) { if($project instanceof Project) {
$this->denyAccessUnlessGranted('edit', $project); $this->denyAccessUnlessGranted('edit', $project);
} else { } else {
$this->denyAccessUnlessGranted('@projects.edit'); $this->denyAccessUnlessGranted('@projects.edit');
@ -203,7 +203,7 @@ class ProjectController extends AbstractController
$builder->add('project', StructuralEntityType::class, [ $builder->add('project', StructuralEntityType::class, [
'class' => Project::class, 'class' => Project::class,
'required' => true, 'required' => true,
'disabled' => $project instanceof \App\Entity\ProjectSystem\Project, //If a project is given, disable the field 'disabled' => $project instanceof Project, //If a project is given, disable the field
'data' => $project, 'data' => $project,
'constraints' => [ 'constraints' => [
new NotNull() new NotNull()

View file

@ -71,7 +71,7 @@ class SecurityController extends AbstractController
* @return RedirectResponse|Response * @return RedirectResponse|Response
*/ */
#[Route(path: '/pw_reset/request', name: 'pw_reset_request')] #[Route(path: '/pw_reset/request', name: 'pw_reset_request')]
public function requestPwReset(PasswordResetManager $passwordReset, Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response public function requestPwReset(PasswordResetManager $passwordReset, Request $request): RedirectResponse|Response
{ {
if (!$this->allow_email_pw_reset) { if (!$this->allow_email_pw_reset) {
throw new AccessDeniedHttpException('The password reset via email is disabled!'); throw new AccessDeniedHttpException('The password reset via email is disabled!');
@ -114,7 +114,7 @@ class SecurityController extends AbstractController
* @return RedirectResponse|Response * @return RedirectResponse|Response
*/ */
#[Route(path: '/pw_reset/new_pw/{user}/{token}', name: 'pw_reset_new_pw')] #[Route(path: '/pw_reset/new_pw/{user}/{token}', name: 'pw_reset_new_pw')]
public function pwResetNewPw(PasswordResetManager $passwordReset, Request $request, EntityManagerInterface $em, EventDispatcherInterface $eventDispatcher, ?string $user = null, ?string $token = null): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response public function pwResetNewPw(PasswordResetManager $passwordReset, Request $request, EntityManagerInterface $em, EventDispatcherInterface $eventDispatcher, ?string $user = null, ?string $token = null): RedirectResponse|Response
{ {
if (!$this->allow_email_pw_reset) { if (!$this->allow_email_pw_reset) {
throw new AccessDeniedHttpException('The password reset via email is disabled!'); throw new AccessDeniedHttpException('The password reset via email is disabled!');

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\Project;
use App\Entity\Parts\Category; use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint; use App\Entity\Parts\Footprint;
@ -59,7 +60,7 @@ class TreeController extends AbstractController
if ($this->isGranted('@parts.read') && $this->isGranted('@categories.read')) { if ($this->isGranted('@parts.read') && $this->isGranted('@categories.read')) {
$tree = $this->treeGenerator->getTreeView(Category::class, $category, 'list_parts_root'); $tree = $this->treeGenerator->getTreeView(Category::class, $category, 'list_parts_root');
} else { } else {
return new JsonResponse("Access denied", \Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN); return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN);
} }
return new JsonResponse($tree); return new JsonResponse($tree);
@ -72,7 +73,7 @@ class TreeController extends AbstractController
if ($this->isGranted('@parts.read') && $this->isGranted('@footprints.read')) { if ($this->isGranted('@parts.read') && $this->isGranted('@footprints.read')) {
$tree = $this->treeGenerator->getTreeView(Footprint::class, $footprint, 'list_parts_root'); $tree = $this->treeGenerator->getTreeView(Footprint::class, $footprint, 'list_parts_root');
} else { } else {
return new JsonResponse("Access denied", \Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN); return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN);
} }
return new JsonResponse($tree); return new JsonResponse($tree);
} }
@ -84,7 +85,7 @@ class TreeController extends AbstractController
if ($this->isGranted('@parts.read') && $this->isGranted('@storelocations.read')) { if ($this->isGranted('@parts.read') && $this->isGranted('@storelocations.read')) {
$tree = $this->treeGenerator->getTreeView(Storelocation::class, $location, 'list_parts_root'); $tree = $this->treeGenerator->getTreeView(Storelocation::class, $location, 'list_parts_root');
} else { } else {
return new JsonResponse("Access denied", \Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN); return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN);
} }
return new JsonResponse($tree); return new JsonResponse($tree);
@ -97,7 +98,7 @@ class TreeController extends AbstractController
if ($this->isGranted('@parts.read') && $this->isGranted('@manufacturers.read')) { if ($this->isGranted('@parts.read') && $this->isGranted('@manufacturers.read')) {
$tree = $this->treeGenerator->getTreeView(Manufacturer::class, $manufacturer, 'list_parts_root'); $tree = $this->treeGenerator->getTreeView(Manufacturer::class, $manufacturer, 'list_parts_root');
} else { } else {
return new JsonResponse("Access denied", \Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN); return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN);
} }
return new JsonResponse($tree); return new JsonResponse($tree);
@ -110,7 +111,7 @@ class TreeController extends AbstractController
if ($this->isGranted('@parts.read') && $this->isGranted('@suppliers.read')) { if ($this->isGranted('@parts.read') && $this->isGranted('@suppliers.read')) {
$tree = $this->treeGenerator->getTreeView(Supplier::class, $supplier, 'list_parts_root'); $tree = $this->treeGenerator->getTreeView(Supplier::class, $supplier, 'list_parts_root');
} else { } else {
return new JsonResponse("Access denied", \Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN); return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN);
} }
return new JsonResponse($tree); return new JsonResponse($tree);
@ -123,7 +124,7 @@ class TreeController extends AbstractController
if ($this->isGranted('@projects.read')) { if ($this->isGranted('@projects.read')) {
$tree = $this->treeGenerator->getTreeView(Project::class, $device, 'devices'); $tree = $this->treeGenerator->getTreeView(Project::class, $device, 'devices');
} else { } else {
return new JsonResponse("Access denied", \Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN); return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN);
} }
return new JsonResponse($tree); return new JsonResponse($tree);

View file

@ -22,6 +22,10 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use App\Entity\Attachments\Attachment;
use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
use App\Entity\Parameters\AttachmentTypeParameter; use App\Entity\Parameters\AttachmentTypeParameter;
use App\Entity\Parameters\CategoryParameter; use App\Entity\Parameters\CategoryParameter;
use App\Entity\Parameters\ProjectParameter; use App\Entity\Parameters\ProjectParameter;
@ -83,7 +87,7 @@ class TypeaheadController extends AbstractController
$serializer = new Serializer($normalizers, $encoders); $serializer = new Serializer($normalizers, $encoders);
$data = $serializer->serialize($result, 'json'); $data = $serializer->serialize($result, 'json');
return new JsonResponse($data, \Symfony\Component\HttpFoundation\Response::HTTP_OK, [], true); return new JsonResponse($data, Response::HTTP_OK, [], true);
} }
/** /**
@ -122,7 +126,7 @@ class TypeaheadController extends AbstractController
foreach ($parts as $part) { foreach ($parts as $part) {
//Determine the picture to show: //Determine the picture to show:
$preview_attachment = $previewGenerator->getTablePreviewAttachment($part); $preview_attachment = $previewGenerator->getTablePreviewAttachment($part);
if($preview_attachment instanceof \App\Entity\Attachments\Attachment) { if($preview_attachment instanceof Attachment) {
$preview_url = $attachmentURLGenerator->getThumbnailURL($preview_attachment, 'thumbnail_sm'); $preview_url = $attachmentURLGenerator->getThumbnailURL($preview_attachment, 'thumbnail_sm');
} else { } else {
$preview_url = ''; $preview_url = '';
@ -132,8 +136,8 @@ class TypeaheadController extends AbstractController
$data[] = [ $data[] = [
'id' => $part->getID(), 'id' => $part->getID(),
'name' => $part->getName(), 'name' => $part->getName(),
'category' => $part->getCategory() instanceof \App\Entity\Parts\Category ? $part->getCategory()->getName() : 'Unknown', 'category' => $part->getCategory() instanceof Category ? $part->getCategory()->getName() : 'Unknown',
'footprint' => $part->getFootprint() instanceof \App\Entity\Parts\Footprint ? $part->getFootprint()->getName() : '', 'footprint' => $part->getFootprint() instanceof Footprint ? $part->getFootprint()->getName() : '',
'description' => mb_strimwidth($part->getDescription(), 0, 127, '...'), 'description' => mb_strimwidth($part->getDescription(), 0, 127, '...'),
'image' => $preview_url, 'image' => $preview_url,
]; ];
@ -176,6 +180,6 @@ class TypeaheadController extends AbstractController
$serializer = new Serializer($normalizers, $encoders); $serializer = new Serializer($normalizers, $encoders);
$data = $serializer->serialize($array, 'json'); $data = $serializer->serialize($array, 'json');
return new JsonResponse($data, \Symfony\Component\HttpFoundation\Response::HTTP_OK, [], true); return new JsonResponse($data, Response::HTTP_OK, [], true);
} }
} }

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use App\Controller\AdminPages\BaseAdminController;
use App\DataTables\LogDataTable; use App\DataTables\LogDataTable;
use App\Entity\Attachments\UserAttachment; use App\Entity\Attachments\UserAttachment;
use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractNamedDBElement;
@ -47,7 +48,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
#[Route(path: '/user')] #[Route(path: '/user')]
class UserController extends AdminPages\BaseAdminController class UserController extends BaseAdminController
{ {
protected string $entity_class = User::class; protected string $entity_class = User::class;
protected string $twig_template = 'admin/user_admin.html.twig'; protected string $twig_template = 'admin/user_admin.html.twig';
@ -180,7 +181,7 @@ class UserController extends AdminPages\BaseAdminController
public function userInfo(?User $user, Packages $packages, Request $request, DataTableFactory $dataTableFactory): Response public function userInfo(?User $user, Packages $packages, Request $request, DataTableFactory $dataTableFactory): Response
{ {
//If no user id was passed, then we show info about the current user //If no user id was passed, then we show info about the current user
if (!$user instanceof \App\Entity\UserSystem\User) { if (!$user instanceof User) {
$tmp = $this->getUser(); $tmp = $this->getUser();
if (!$tmp instanceof User) { if (!$tmp instanceof User) {
throw new InvalidArgumentException('Userinfo only works for database users!'); throw new InvalidArgumentException('Userinfo only works for database users!');

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use App\Entity\Attachments\Attachment;
use App\Entity\UserSystem\U2FKey; use App\Entity\UserSystem\U2FKey;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use App\Entity\UserSystem\WebauthnKey; use App\Entity\UserSystem\WebauthnKey;
@ -118,7 +119,7 @@ class UserSettingsController extends AbstractController
$key_repo = $entityManager->getRepository(U2FKey::class); $key_repo = $entityManager->getRepository(U2FKey::class);
/** @var U2FKey|null $u2f */ /** @var U2FKey|null $u2f */
$u2f = $key_repo->find($key_id); $u2f = $key_repo->find($key_id);
if (!$u2f instanceof \App\Entity\UserSystem\U2FKey) { if (!$u2f instanceof U2FKey) {
$this->addFlash('danger', 'tfa_u2f.u2f_delete.not_existing'); $this->addFlash('danger', 'tfa_u2f.u2f_delete.not_existing');
return $this->redirectToRoute('user_settings'); return $this->redirectToRoute('user_settings');
@ -140,7 +141,7 @@ class UserSettingsController extends AbstractController
$key_repo = $entityManager->getRepository(WebauthnKey::class); $key_repo = $entityManager->getRepository(WebauthnKey::class);
/** @var WebauthnKey|null $key */ /** @var WebauthnKey|null $key */
$key = $key_repo->find($key_id); $key = $key_repo->find($key_id);
if (!$key instanceof \App\Entity\UserSystem\WebauthnKey) { if (!$key instanceof WebauthnKey) {
$this->addFlash('error', 'tfa_u2f.u2f_delete.not_existing'); $this->addFlash('error', 'tfa_u2f.u2f_delete.not_existing');
return $this->redirectToRoute('user_settings'); return $this->redirectToRoute('user_settings');
@ -166,7 +167,7 @@ class UserSettingsController extends AbstractController
} }
#[Route(path: '/invalidate_trustedDevices', name: 'tfa_trustedDevices_invalidate', methods: ['DELETE'])] #[Route(path: '/invalidate_trustedDevices', name: 'tfa_trustedDevices_invalidate', methods: ['DELETE'])]
public function resetTrustedDevices(Request $request, EntityManagerInterface $entityManager): \RuntimeException|\Symfony\Component\HttpFoundation\RedirectResponse public function resetTrustedDevices(Request $request, EntityManagerInterface $entityManager): \RuntimeException|RedirectResponse
{ {
if ($this->demo_mode) { if ($this->demo_mode) {
throw new RuntimeException('You can not do 2FA things in demo mode'); throw new RuntimeException('You can not do 2FA things in demo mode');
@ -203,7 +204,7 @@ class UserSettingsController extends AbstractController
* @return RedirectResponse|Response * @return RedirectResponse|Response
*/ */
#[Route(path: '/settings', name: 'user_settings')] #[Route(path: '/settings', name: 'user_settings')]
public function userSettings(Request $request, EntityManagerInterface $em, UserPasswordHasherInterface $passwordEncoder, GoogleAuthenticator $googleAuthenticator, BackupCodeManager $backupCodeManager, FormFactoryInterface $formFactory, UserAvatarHelper $avatarHelper): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response public function userSettings(Request $request, EntityManagerInterface $em, UserPasswordHasherInterface $passwordEncoder, GoogleAuthenticator $googleAuthenticator, BackupCodeManager $backupCodeManager, FormFactoryInterface $formFactory, UserAvatarHelper $avatarHelper): RedirectResponse|Response
{ {
/** @var User $user */ /** @var User $user */
$user = $this->getUser(); $user = $this->getUser();
@ -243,7 +244,7 @@ class UserSettingsController extends AbstractController
/** @var Form $form We need a form implementation for the next calls */ /** @var Form $form We need a form implementation for the next calls */
//Remove the avatar attachment from the user if requested //Remove the avatar attachment from the user if requested
if ($form->getClickedButton() && 'remove_avatar' === $form->getClickedButton()->getName() && $user->getMasterPictureAttachment() instanceof \App\Entity\Attachments\Attachment) { if ($form->getClickedButton() && 'remove_avatar' === $form->getClickedButton()->getName() && $user->getMasterPictureAttachment() instanceof Attachment) {
$em->remove($user->getMasterPictureAttachment()); $em->remove($user->getMasterPictureAttachment());
$user->setMasterPictureAttachment(null); $user->setMasterPictureAttachment(null);
$page_need_reload = true; $page_need_reload = true;

View file

@ -64,7 +64,7 @@ class EntityColumn extends AbstractColumn
/** @var AbstractNamedDBElement|null $entity */ /** @var AbstractNamedDBElement|null $entity */
if ($entity instanceof \App\Entity\Base\AbstractNamedDBElement) { if ($entity instanceof AbstractNamedDBElement) {
if (null !== $entity->getID()) { if (null !== $entity->getID()) {
return sprintf( return sprintf(
'<a href="%s">%s</a>', '<a href="%s">%s</a>',

View file

@ -41,17 +41,17 @@ declare(strict_types=1);
namespace App\DataTables\Column; namespace App\DataTables\Column;
use Symfony\Bundle\SecurityBundle\Security;
use App\Entity\LogSystem\CollectionElementDeleted; use App\Entity\LogSystem\CollectionElementDeleted;
use App\Entity\LogSystem\ElementCreatedLogEntry; use App\Entity\LogSystem\ElementCreatedLogEntry;
use App\Entity\LogSystem\ElementDeletedLogEntry; use App\Entity\LogSystem\ElementDeletedLogEntry;
use App\Entity\LogSystem\ElementEditedLogEntry; use App\Entity\LogSystem\ElementEditedLogEntry;
use Omines\DataTablesBundle\Column\AbstractColumn; use Omines\DataTablesBundle\Column\AbstractColumn;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
class RevertLogColumn extends AbstractColumn class RevertLogColumn extends AbstractColumn
{ {
public function __construct(protected TranslatorInterface $translator, protected \Symfony\Bundle\SecurityBundle\Security $security) public function __construct(protected TranslatorInterface $translator, protected Security $security)
{ {
} }

View file

@ -41,9 +41,9 @@ class EntityConstraint extends AbstractConstraint
* @param null $value * @param null $value
* @param string $operator * @param string $operator
*/ */
public function __construct(protected ?\App\Services\Trees\NodesListBuilder $nodesListBuilder, protected string $class, string $property, string $identifier = null, protected $value = null, protected ?string $operator = '') public function __construct(protected ?NodesListBuilder $nodesListBuilder, protected string $class, string $property, string $identifier = null, protected $value = null, protected ?string $operator = '')
{ {
if (!$nodesListBuilder instanceof \App\Services\Trees\NodesListBuilder && $this->isStructural()) { if (!$nodesListBuilder instanceof NodesListBuilder && $this->isStructural()) {
throw new \InvalidArgumentException('NodesListBuilder must be provided for structural entities'); throw new \InvalidArgumentException('NodesListBuilder must be provided for structural entities');
} }
@ -128,7 +128,7 @@ class EntityConstraint extends AbstractConstraint
} }
//We need to handle null values differently, as they can not be compared with == or != //We need to handle null values differently, as they can not be compared with == or !=
if (!$this->value instanceof \App\Entity\Base\AbstractDBElement) { if (!$this->value instanceof AbstractDBElement) {
if($this->operator === '=' || $this->operator === 'INCLUDING_CHILDREN') { if($this->operator === '=' || $this->operator === 'INCLUDING_CHILDREN') {
$queryBuilder->andWhere(sprintf("%s IS NULL", $this->property)); $queryBuilder->andWhere(sprintf("%s IS NULL", $this->property));
return; return;

View file

@ -20,6 +20,7 @@
namespace App\DataTables\Filters\Constraints\Part; namespace App\DataTables\Filters\Constraints\Part;
use Doctrine\ORM\Query\Expr\Orx;
use App\DataTables\Filters\Constraints\AbstractConstraint; use App\DataTables\Filters\Constraints\AbstractConstraint;
use Doctrine\ORM\Query\Expr; use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
@ -88,7 +89,7 @@ class TagsConstraint extends AbstractConstraint
/** /**
* Builds an expression to query for a single tag * Builds an expression to query for a single tag
*/ */
protected function getExpressionForTag(QueryBuilder $queryBuilder, string $tag): Expr\Orx protected function getExpressionForTag(QueryBuilder $queryBuilder, string $tag): Orx
{ {
$tag_identifier_prefix = uniqid($this->identifier . '_', false); $tag_identifier_prefix = uniqid($this->identifier . '_', false);

View file

@ -66,7 +66,7 @@ class LogFilter implements FilterInterface
/** /**
* @return IntConstraint|NumberConstraint * @return IntConstraint|NumberConstraint
*/ */
public function getDbId(): \App\DataTables\Filters\Constraints\IntConstraint|\App\DataTables\Filters\Constraints\NumberConstraint public function getDbId(): IntConstraint|NumberConstraint
{ {
return $this->dbId; return $this->dbId;
} }

View file

@ -20,6 +20,8 @@
namespace App\DataTables\Helpers; namespace App\DataTables\Helpers;
use App\Entity\ProjectSystem\Project;
use App\Entity\Attachments\Attachment;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;
use App\Services\Attachments\AttachmentURLGenerator; use App\Services\Attachments\AttachmentURLGenerator;
use App\Services\Attachments\PartPreviewGenerator; use App\Services\Attachments\PartPreviewGenerator;
@ -46,7 +48,7 @@ class PartDataTableHelper
if ($context->isNeedsReview()) { if ($context->isNeedsReview()) {
$icon = sprintf('<i class="fa-solid fa-ambulance fa-fw me-1" title="%s"></i>', $this->translator->trans('part.needs_review.badge')); $icon = sprintf('<i class="fa-solid fa-ambulance fa-fw me-1" title="%s"></i>', $this->translator->trans('part.needs_review.badge'));
} }
if ($context->getBuiltProject() instanceof \App\Entity\ProjectSystem\Project) { if ($context->getBuiltProject() instanceof Project) {
$icon = sprintf('<i class="fa-solid fa-box-archive fa-fw me-1" title="%s"></i>', $icon = sprintf('<i class="fa-solid fa-box-archive fa-fw me-1" title="%s"></i>',
$this->translator->trans('part.info.projectBuildPart.hint') . ': ' . $context->getBuiltProject()->getName()); $this->translator->trans('part.info.projectBuildPart.hint') . ': ' . $context->getBuiltProject()->getName());
} }
@ -63,7 +65,7 @@ class PartDataTableHelper
public function renderPicture(Part $context): string public function renderPicture(Part $context): string
{ {
$preview_attachment = $this->previewGenerator->getTablePreviewAttachment($context); $preview_attachment = $this->previewGenerator->getTablePreviewAttachment($context);
if (!$preview_attachment instanceof \App\Entity\Attachments\Attachment) { if (!$preview_attachment instanceof Attachment) {
return ''; return '';
} }

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\DataTables; namespace App\DataTables;
use Symfony\Bundle\SecurityBundle\Security;
use App\DataTables\Column\IconLinkColumn; use App\DataTables\Column\IconLinkColumn;
use App\DataTables\Column\LocaleDateTimeColumn; use App\DataTables\Column\LocaleDateTimeColumn;
use App\DataTables\Column\LogEntryExtraColumn; use App\DataTables\Column\LogEntryExtraColumn;
@ -56,7 +57,6 @@ use Psr\Log\LogLevel;
use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
class LogDataTable implements DataTableTypeInterface class LogDataTable implements DataTableTypeInterface
@ -65,7 +65,7 @@ class LogDataTable implements DataTableTypeInterface
public function __construct(protected ElementTypeNameGenerator $elementTypeNameGenerator, protected TranslatorInterface $translator, public function __construct(protected ElementTypeNameGenerator $elementTypeNameGenerator, protected TranslatorInterface $translator,
protected UrlGeneratorInterface $urlGenerator, protected EntityURLGenerator $entityURLGenerator, EntityManagerInterface $entityManager, protected UrlGeneratorInterface $urlGenerator, protected EntityURLGenerator $entityURLGenerator, EntityManagerInterface $entityManager,
protected \Symfony\Bundle\SecurityBundle\Security $security, protected UserAvatarHelper $userAvatarHelper, protected LogLevelHelper $logLevelHelper) protected Security $security, protected UserAvatarHelper $userAvatarHelper, protected LogLevelHelper $logLevelHelper)
{ {
$this->logRepo = $entityManager->getRepository(AbstractLogEntry::class); $this->logRepo = $entityManager->getRepository(AbstractLogEntry::class);
} }
@ -158,7 +158,7 @@ class LogDataTable implements DataTableTypeInterface
$user = $context->getUser(); $user = $context->getUser();
//If user was deleted, show the info from the username field //If user was deleted, show the info from the username field
if (!$user instanceof \App\Entity\UserSystem\User) { if (!$user instanceof User) {
if ($context->isCLIEntry()) { if ($context->isCLIEntry()) {
return sprintf('%s [%s]', return sprintf('%s [%s]',
htmlentities($context->getCLIUsername()), htmlentities($context->getCLIUsername()),
@ -219,7 +219,7 @@ class LogDataTable implements DataTableTypeInterface
) { ) {
try { try {
$target = $this->logRepo->getTargetElement($context); $target = $this->logRepo->getTargetElement($context);
if ($target instanceof \App\Entity\Base\AbstractDBElement) { if ($target instanceof AbstractDBElement) {
return $this->entityURLGenerator->timeTravelURL($target, $context->getTimestamp()); return $this->entityURLGenerator->timeTravelURL($target, $context->getTimestamp());
} }
} catch (EntityNotSupportedException) { } catch (EntityNotSupportedException) {

View file

@ -22,6 +22,8 @@ declare(strict_types=1);
namespace App\DataTables; namespace App\DataTables;
use Symfony\Bundle\SecurityBundle\Security;
use App\Entity\Parts\Storelocation;
use App\DataTables\Adapters\CustomFetchJoinORMAdapter; use App\DataTables\Adapters\CustomFetchJoinORMAdapter;
use App\DataTables\Column\EntityColumn; use App\DataTables\Column\EntityColumn;
use App\DataTables\Column\IconLinkColumn; use App\DataTables\Column\IconLinkColumn;
@ -49,12 +51,11 @@ use Omines\DataTablesBundle\Column\TextColumn;
use Omines\DataTablesBundle\DataTable; use Omines\DataTablesBundle\DataTable;
use Omines\DataTablesBundle\DataTableTypeInterface; use Omines\DataTablesBundle\DataTableTypeInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
final class PartsDataTable implements DataTableTypeInterface final class PartsDataTable implements DataTableTypeInterface
{ {
public function __construct(private readonly EntityURLGenerator $urlGenerator, private readonly TranslatorInterface $translator, private readonly AmountFormatter $amountFormatter, private readonly PartDataTableHelper $partDataTableHelper, private readonly \Symfony\Bundle\SecurityBundle\Security $security) public function __construct(private readonly EntityURLGenerator $urlGenerator, private readonly TranslatorInterface $translator, private readonly AmountFormatter $amountFormatter, private readonly PartDataTableHelper $partDataTableHelper, private readonly Security $security)
{ {
} }
@ -139,7 +140,7 @@ final class PartsDataTable implements DataTableTypeInterface
$tmp = []; $tmp = [];
foreach ($context->getPartLots() as $lot) { foreach ($context->getPartLots() as $lot) {
//Ignore lots without storelocation //Ignore lots without storelocation
if (!$lot->getStorageLocation() instanceof \App\Entity\Parts\Storelocation) { if (!$lot->getStorageLocation() instanceof Storelocation) {
continue; continue;
} }
$tmp[] = sprintf( $tmp[] = sprintf(

View file

@ -53,7 +53,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
'label' => '', 'label' => '',
'className' => 'no-colvis', 'className' => 'no-colvis',
'render' => function ($value, ProjectBOMEntry $context) { 'render' => function ($value, ProjectBOMEntry $context) {
if(!$context->getPart() instanceof \App\Entity\Parts\Part) { if(!$context->getPart() instanceof Part) {
return ''; return '';
} }
return $this->partDataTableHelper->renderPicture($context->getPart()); return $this->partDataTableHelper->renderPicture($context->getPart());
@ -71,7 +71,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
'orderField' => 'bom_entry.quantity', 'orderField' => 'bom_entry.quantity',
'render' => function ($value, ProjectBOMEntry $context): float|string { 'render' => function ($value, ProjectBOMEntry $context): float|string {
//If we have a non-part entry, only show the rounded quantity //If we have a non-part entry, only show the rounded quantity
if (!$context->getPart() instanceof \App\Entity\Parts\Part) { if (!$context->getPart() instanceof Part) {
return round($context->getQuantity()); return round($context->getQuantity());
} }
//Otherwise use the unit of the part to format the quantity //Otherwise use the unit of the part to format the quantity
@ -83,10 +83,10 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
'label' => $this->translator->trans('part.table.name'), 'label' => $this->translator->trans('part.table.name'),
'orderField' => 'part.name', 'orderField' => 'part.name',
'render' => function ($value, ProjectBOMEntry $context) { 'render' => function ($value, ProjectBOMEntry $context) {
if(!$context->getPart() instanceof \App\Entity\Parts\Part) { if(!$context->getPart() instanceof Part) {
return htmlspecialchars($context->getName()); return htmlspecialchars($context->getName());
} }
if($context->getPart() instanceof \App\Entity\Parts\Part) { if($context->getPart() instanceof Part) {
$tmp = $this->partDataTableHelper->renderName($context->getPart()); $tmp = $this->partDataTableHelper->renderName($context->getPart());
if(!empty($context->getName())) { if(!empty($context->getName())) {
$tmp .= '<br><b>'.htmlspecialchars($context->getName()).'</b>'; $tmp .= '<br><b>'.htmlspecialchars($context->getName()).'</b>';
@ -100,7 +100,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
->add('description', MarkdownColumn::class, [ ->add('description', MarkdownColumn::class, [
'label' => $this->translator->trans('part.table.description'), 'label' => $this->translator->trans('part.table.description'),
'data' => function (ProjectBOMEntry $context) { 'data' => function (ProjectBOMEntry $context) {
if($context->getPart() instanceof \App\Entity\Parts\Part) { if($context->getPart() instanceof Part) {
return $context->getPart()->getDescription(); return $context->getPart()->getDescription();
} }
//For non-part BOM entries show the comment field //For non-part BOM entries show the comment field

View file

@ -64,7 +64,7 @@ class ResetAutoIncrementORMPurger implements PurgerInterface, ORMPurgerInterface
* @param string[] $excluded array of table/view names to be excluded from purge * @param string[] $excluded array of table/view names to be excluded from purge
*/ */
public function __construct( public function __construct(
private ?\Doctrine\ORM\EntityManagerInterface $em = null, private ?EntityManagerInterface $em = null,
/** /**
* Table/view names to be excluded from purge * Table/view names to be excluded from purge
*/ */

View file

@ -20,6 +20,7 @@
namespace App\Doctrine\SetSQLMode; namespace App\Doctrine\SetSQLMode;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware; use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
@ -29,7 +30,7 @@ use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
*/ */
class SetSQLModeMiddlewareDriver extends AbstractDriverMiddleware class SetSQLModeMiddlewareDriver extends AbstractDriverMiddleware
{ {
public function connect(array $params): \Doctrine\DBAL\Driver\Connection public function connect(array $params): Connection
{ {
//Only set this on MySQL connections, as other databases don't support this parameter //Only set this on MySQL connections, as other databases don't support this parameter
if($this->getDatabasePlatform() instanceof AbstractMySQLPlatform) { if($this->getDatabasePlatform() instanceof AbstractMySQLPlatform) {

View file

@ -53,7 +53,7 @@ class BigDecimalType extends Type
*/ */
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
{ {
if (!$value instanceof \Brick\Math\BigDecimal) { if (!$value instanceof BigDecimal) {
return null; return null;
} }

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\Attachments; namespace App\Entity\Attachments;
use App\Repository\AttachmentRepository;
use App\EntityListeners\AttachmentDeleteListener;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractNamedDBElement;
use App\Validator\Constraints\Selectable; use App\Validator\Constraints\Selectable;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@ -34,11 +37,11 @@ use LogicException;
/** /**
* Class Attachment. * Class Attachment.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\AttachmentRepository::class)] #[ORM\Entity(repositoryClass: AttachmentRepository::class)]
#[ORM\InheritanceType('SINGLE_TABLE')] #[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorColumn(name: 'class_name', type: 'string')] #[ORM\DiscriminatorColumn(name: 'class_name', type: 'string')]
#[ORM\DiscriminatorMap(['PartDB\Part' => 'PartAttachment', 'Part' => 'PartAttachment', 'PartDB\Device' => 'ProjectAttachment', 'Device' => 'ProjectAttachment', 'AttachmentType' => 'AttachmentTypeAttachment', 'Category' => 'CategoryAttachment', 'Footprint' => 'FootprintAttachment', 'Manufacturer' => 'ManufacturerAttachment', 'Currency' => 'CurrencyAttachment', 'Group' => 'GroupAttachment', 'MeasurementUnit' => 'MeasurementUnitAttachment', 'Storelocation' => 'StorelocationAttachment', 'Supplier' => 'SupplierAttachment', 'User' => 'UserAttachment', 'LabelProfile' => 'LabelAttachment'])] #[ORM\DiscriminatorMap(['PartDB\Part' => 'PartAttachment', 'Part' => 'PartAttachment', 'PartDB\Device' => 'ProjectAttachment', 'Device' => 'ProjectAttachment', 'AttachmentType' => 'AttachmentTypeAttachment', 'Category' => 'CategoryAttachment', 'Footprint' => 'FootprintAttachment', 'Manufacturer' => 'ManufacturerAttachment', 'Currency' => 'CurrencyAttachment', 'Group' => 'GroupAttachment', 'MeasurementUnit' => 'MeasurementUnitAttachment', 'Storelocation' => 'StorelocationAttachment', 'Supplier' => 'SupplierAttachment', 'User' => 'UserAttachment', 'LabelProfile' => 'LabelAttachment'])]
#[ORM\EntityListeners([\App\EntityListeners\AttachmentDeleteListener::class])] #[ORM\EntityListeners([AttachmentDeleteListener::class])]
#[ORM\Table(name: '`attachments`')] #[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_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: 'attachments_idx_class_name_id', columns: ['class_name', 'id'])]
@ -78,13 +81,13 @@ abstract class Attachment extends AbstractNamedDBElement
/** /**
* @var string|null the original filename the file had, when the user uploaded it * @var string|null the original filename the file had, when the user uploaded it
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] #[ORM\Column(type: Types::STRING, nullable: true)]
protected ?string $original_filename = null; protected ?string $original_filename = null;
/** /**
* @var string The path to the file relative to a placeholder path like %MEDIA% * @var string The path to the file relative to a placeholder path like %MEDIA%
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'path')] #[ORM\Column(type: Types::STRING, name: 'path')]
protected string $path = ''; protected string $path = '';
/** /**
@ -92,7 +95,7 @@ abstract class Attachment extends AbstractNamedDBElement
*/ */
#[Assert\NotBlank(message: 'validator.attachment.name_not_blank')] #[Assert\NotBlank(message: 'validator.attachment.name_not_blank')]
#[Groups(['simple', 'extended', 'full'])] #[Groups(['simple', 'extended', 'full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $name = ''; protected string $name = '';
/** /**
@ -103,7 +106,7 @@ abstract class Attachment extends AbstractNamedDBElement
/** /**
* @var bool * @var bool
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $show_in_table = false; protected bool $show_in_table = false;
/** /**

View file

@ -22,6 +22,8 @@ declare(strict_types=1);
namespace App\Entity\Attachments; namespace App\Entity\Attachments;
use App\Repository\StructuralDBElementRepository;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Parameters\AttachmentTypeParameter; use App\Entity\Parameters\AttachmentTypeParameter;
use App\Validator\Constraints\ValidFileFilter; use App\Validator\Constraints\ValidFileFilter;
@ -33,7 +35,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/** /**
* Class AttachmentType. * Class AttachmentType.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\StructuralDBElementRepository::class)] #[ORM\Entity(repositoryClass: StructuralDBElementRepository::class)]
#[ORM\Table(name: '`attachment_types`')] #[ORM\Table(name: '`attachment_types`')]
#[ORM\Index(name: 'attachment_types_idx_name', columns: ['name'])] #[ORM\Index(name: 'attachment_types_idx_name', columns: ['name'])]
#[ORM\Index(name: 'attachment_types_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'attachment_types_idx_parent_name', columns: ['parent_id', 'name'])]
@ -51,33 +53,36 @@ class AttachmentType extends AbstractStructuralDBElement
* @var string * @var string
* @ValidFileFilter * @ValidFileFilter
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $filetype_filter = ''; protected string $filetype_filter = '';
/** /**
* @var Collection<int, AttachmentTypeAttachment> * @var Collection<int, AttachmentTypeAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\AttachmentTypeAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: AttachmentTypeAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** @var Collection<int, AttachmentTypeParameter> /** @var Collection<int, AttachmentTypeParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\AttachmentTypeParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: AttachmentTypeParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
/** /**
* @var \Doctrine\Common\Collections\Collection<\App\Entity\Attachments\Attachment> * @var Collection<Attachment>
*/
/**
* @var Collection<Attachment>
*/ */
#[ORM\OneToMany(targetEntity: 'Attachment', mappedBy: 'attachment_type')] #[ORM\OneToMany(targetEntity: 'Attachment', mappedBy: 'attachment_type')]
protected \Doctrine\Common\Collections\Collection $attachments_with_type; protected Collection $attachments_with_type;
public function __construct() public function __construct()
{ {
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
parent::__construct(); parent::__construct();
$this->attachments = new ArrayCollection(); $this->attachments = new ArrayCollection();
$this->attachments_with_type = new ArrayCollection(); $this->attachments_with_type = new ArrayCollection();

View file

@ -36,7 +36,7 @@ class AttachmentTypeAttachment extends Attachment
/** /**
* @var AttachmentContainingDBElement|null the element this attachment is associated with * @var AttachmentContainingDBElement|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Attachments\AttachmentType::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -37,7 +37,7 @@ class CategoryAttachment extends Attachment
/** /**
* @var AttachmentContainingDBElement|null the element this attachment is associated with * @var AttachmentContainingDBElement|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Category::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Category::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -37,7 +37,7 @@ class CurrencyAttachment extends Attachment
/** /**
* @var Currency|null the element this attachment is associated with * @var Currency|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\PriceInformations\Currency::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Currency::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -37,7 +37,7 @@ class FootprintAttachment extends Attachment
/** /**
* @var Footprint|null the element this attachment is associated with * @var Footprint|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Footprint::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Footprint::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -38,7 +38,7 @@ class GroupAttachment extends Attachment
/** /**
* @var Group|null the element this attachment is associated with * @var Group|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\Group::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Group::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -57,7 +57,7 @@ class LabelAttachment extends Attachment
/** /**
* @var LabelProfile the element this attachment is associated with * @var LabelProfile the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\LabelSystem\LabelProfile::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: LabelProfile::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -38,7 +38,7 @@ class ManufacturerAttachment extends Attachment
/** /**
* @var Manufacturer|null the element this attachment is associated with * @var Manufacturer|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Manufacturer::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Manufacturer::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -38,7 +38,7 @@ class MeasurementUnitAttachment extends Attachment
/** /**
* @var Manufacturer|null the element this attachment is associated with * @var Manufacturer|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\MeasurementUnit::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: MeasurementUnit::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -37,7 +37,7 @@ class PartAttachment extends Attachment
/** /**
* @var Part the element this attachment is associated with * @var Part the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Part::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Part::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -37,7 +37,7 @@ class ProjectAttachment extends Attachment
/** /**
* @var Project|null the element this attachment is associated with * @var Project|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\ProjectSystem\Project::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Project::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -38,7 +38,7 @@ class StorelocationAttachment extends Attachment
/** /**
* @var Storelocation|null the element this attachment is associated with * @var Storelocation|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Storelocation::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Storelocation::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -38,7 +38,7 @@ class SupplierAttachment extends Attachment
/** /**
* @var Supplier|null the element this attachment is associated with * @var Supplier|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Supplier::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: Supplier::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -38,7 +38,7 @@ class UserAttachment extends Attachment
/** /**
* @var User|null the element this attachment is associated with * @var User|null the element this attachment is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\User::class, inversedBy: 'attachments')] #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AttachmentContainingDBElement $element = null; protected ?AttachmentContainingDBElement $element = null;
} }

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Base; namespace App\Entity\Base;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
use function is_string; use function is_string;
@ -37,21 +38,21 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement
* @var string The address of the company * @var string The address of the company
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $address = ''; protected string $address = '';
/** /**
* @var string The phone number of the company * @var string The phone number of the company
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $phone_number = ''; protected string $phone_number = '';
/** /**
* @var string The fax number of the company * @var string The fax number of the company
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $fax_number = ''; protected string $fax_number = '';
/** /**
@ -59,7 +60,7 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement
*/ */
#[Assert\Email] #[Assert\Email]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $email_address = ''; protected string $email_address = '';
/** /**
@ -67,13 +68,13 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement
*/ */
#[Assert\Url] #[Assert\Url]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $website = ''; protected string $website = '';
/** /**
* @var string * @var string
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $auto_product_url = ''; protected string $auto_product_url = '';
/******************************************************************************** /********************************************************************************

View file

@ -22,6 +22,37 @@ declare(strict_types=1);
namespace App\Entity\Base; namespace App\Entity\Base;
use App\Entity\Attachments\AttachmentType;
use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentTypeAttachment;
use App\Entity\Attachments\CategoryAttachment;
use App\Entity\Attachments\CurrencyAttachment;
use App\Entity\Attachments\FootprintAttachment;
use App\Entity\Attachments\GroupAttachment;
use App\Entity\Attachments\LabelAttachment;
use App\Entity\Attachments\ManufacturerAttachment;
use App\Entity\Attachments\MeasurementUnitAttachment;
use App\Entity\Attachments\PartAttachment;
use App\Entity\Attachments\ProjectAttachment;
use App\Entity\Attachments\StorelocationAttachment;
use App\Entity\Attachments\SupplierAttachment;
use App\Entity\Attachments\UserAttachment;
use App\Entity\Parts\Category;
use App\Entity\ProjectSystem\Project;
use App\Entity\ProjectSystem\ProjectBOMEntry;
use App\Entity\Parts\Footprint;
use App\Entity\UserSystem\Group;
use App\Entity\Parts\Manufacturer;
use App\Entity\PriceInformations\Orderdetail;
use App\Entity\Parts\Part;
use App\Entity\Parts\Storelocation;
use App\Entity\Parts\PartLot;
use App\Entity\PriceInformations\Currency;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Supplier;
use App\Entity\UserSystem\User;
use App\Repository\DBElementRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use JsonSerializable; use JsonSerializable;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
@ -35,15 +66,15 @@ use Symfony\Component\Serializer\Annotation\Groups;
* Every database table which are managed with this class (or a subclass of it) * Every database table which are managed with this class (or a subclass of it)
* must have the table row "id"!! The ID is the unique key to identify the elements. * must have the table row "id"!! The ID is the unique key to identify the elements.
*/ */
#[DiscriminatorMap(typeProperty: 'type', mapping: ['attachment_type' => \App\Entity\Attachments\AttachmentType::class, 'attachment' => \App\Entity\Attachments\Attachment::class, 'attachment_type_attachment' => \App\Entity\Attachments\AttachmentTypeAttachment::class, 'category_attachment' => \App\Entity\Attachments\CategoryAttachment::class, 'currency_attachment' => \App\Entity\Attachments\CurrencyAttachment::class, 'footprint_attachment' => \App\Entity\Attachments\FootprintAttachment::class, 'group_attachment' => \App\Entity\Attachments\GroupAttachment::class, 'label_attachment' => \App\Entity\Attachments\LabelAttachment::class, 'manufacturer_attachment' => \App\Entity\Attachments\ManufacturerAttachment::class, 'measurement_unit_attachment' => \App\Entity\Attachments\MeasurementUnitAttachment::class, 'part_attachment' => \App\Entity\Attachments\PartAttachment::class, 'project_attachment' => \App\Entity\Attachments\ProjectAttachment::class, 'storelocation_attachment' => \App\Entity\Attachments\StorelocationAttachment::class, 'supplier_attachment' => \App\Entity\Attachments\SupplierAttachment::class, 'user_attachment' => \App\Entity\Attachments\UserAttachment::class, 'category' => \App\Entity\Parts\Category::class, 'project' => \App\Entity\ProjectSystem\Project::class, 'project_bom_entry' => \App\Entity\ProjectSystem\ProjectBOMEntry::class, 'footprint' => \App\Entity\Parts\Footprint::class, 'group' => \App\Entity\UserSystem\Group::class, 'manufacturer' => \App\Entity\Parts\Manufacturer::class, 'orderdetail' => \App\Entity\PriceInformations\Orderdetail::class, 'part' => \App\Entity\Parts\Part::class, 'pricedetail' => 'App\Entity\PriceInformation\Pricedetail', 'storelocation' => \App\Entity\Parts\Storelocation::class, 'part_lot' => \App\Entity\Parts\PartLot::class, 'currency' => \App\Entity\PriceInformations\Currency::class, 'measurement_unit' => \App\Entity\Parts\MeasurementUnit::class, 'parameter' => 'App\Entity\Parts\AbstractParameter', 'supplier' => \App\Entity\Parts\Supplier::class, 'user' => \App\Entity\UserSystem\User::class])] #[DiscriminatorMap(typeProperty: 'type', mapping: ['attachment_type' => AttachmentType::class, 'attachment' => Attachment::class, 'attachment_type_attachment' => AttachmentTypeAttachment::class, 'category_attachment' => CategoryAttachment::class, 'currency_attachment' => CurrencyAttachment::class, 'footprint_attachment' => FootprintAttachment::class, 'group_attachment' => GroupAttachment::class, 'label_attachment' => LabelAttachment::class, 'manufacturer_attachment' => ManufacturerAttachment::class, 'measurement_unit_attachment' => MeasurementUnitAttachment::class, 'part_attachment' => PartAttachment::class, 'project_attachment' => ProjectAttachment::class, 'storelocation_attachment' => StorelocationAttachment::class, 'supplier_attachment' => SupplierAttachment::class, 'user_attachment' => UserAttachment::class, 'category' => Category::class, 'project' => Project::class, 'project_bom_entry' => ProjectBOMEntry::class, 'footprint' => Footprint::class, 'group' => Group::class, 'manufacturer' => Manufacturer::class, 'orderdetail' => Orderdetail::class, 'part' => Part::class, 'pricedetail' => 'App\Entity\PriceInformation\Pricedetail', 'storelocation' => Storelocation::class, 'part_lot' => PartLot::class, 'currency' => Currency::class, 'measurement_unit' => MeasurementUnit::class, 'parameter' => 'App\Entity\Parts\AbstractParameter', 'supplier' => Supplier::class, 'user' => User::class])]
#[ORM\MappedSuperclass(repositoryClass: \App\Repository\DBElementRepository::class)] #[ORM\MappedSuperclass(repositoryClass: DBElementRepository::class)]
abstract class AbstractDBElement implements JsonSerializable abstract class AbstractDBElement implements JsonSerializable
{ {
/** @var int|null The Identification number for this part. This value is unique for the element in this table. /** @var int|null The Identification number for this part. This value is unique for the element in this table.
* Null if the element is not saved to DB yet. * Null if the element is not saved to DB yet.
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue] #[ORM\GeneratedValue]
protected ?int $id = null; protected ?int $id = null;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Base; namespace App\Entity\Base;
use Doctrine\DBAL\Types\Types;
use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\NamedElementInterface;
use App\Entity\Contracts\TimeStampableInterface; use App\Entity\Contracts\TimeStampableInterface;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@ -42,7 +43,7 @@ abstract class AbstractNamedDBElement extends AbstractDBElement implements Named
*/ */
#[Assert\NotBlank] #[Assert\NotBlank]
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $name = ''; protected string $name = '';
/****************************************************************************** /******************************************************************************

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Base; namespace App\Entity\Base;
use App\Repository\AbstractPartsContainingRepository;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
@ -29,7 +30,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
/** /**
* Class PartsContainingDBElement. * Class PartsContainingDBElement.
*/ */
#[ORM\MappedSuperclass(repositoryClass: \App\Repository\AbstractPartsContainingRepository::class)] #[ORM\MappedSuperclass(repositoryClass: AbstractPartsContainingRepository::class)]
abstract class AbstractPartsContainingDBElement extends AbstractStructuralDBElement abstract class AbstractPartsContainingDBElement extends AbstractStructuralDBElement
{ {
#[Groups(['full'])] #[Groups(['full'])]

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\Base; namespace App\Entity\Base;
use App\Repository\StructuralDBElementRepository;
use App\EntityListeners\TreeCacheInvalidationListener;
use Doctrine\DBAL\Types\Types;
use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Parameters\ParametersTrait; use App\Entity\Parameters\ParametersTrait;
use App\Validator\Constraints\NoneOfItsChildren; use App\Validator\Constraints\NoneOfItsChildren;
@ -46,24 +49,24 @@ use Symfony\Component\Serializer\Annotation\Groups;
* *
*/ */
#[UniqueEntity(fields: ['name', 'parent'], ignoreNull: false, message: 'structural.entity.unique_name')] #[UniqueEntity(fields: ['name', 'parent'], ignoreNull: false, message: 'structural.entity.unique_name')]
#[ORM\MappedSuperclass(repositoryClass: \App\Repository\StructuralDBElementRepository::class)] #[ORM\MappedSuperclass(repositoryClass: StructuralDBElementRepository::class)]
#[ORM\EntityListeners([\App\EntityListeners\TreeCacheInvalidationListener::class])] #[ORM\EntityListeners([TreeCacheInvalidationListener::class])]
abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
{ {
use ParametersTrait; use ParametersTrait;
public const ID_ROOT_ELEMENT = 0; final public const ID_ROOT_ELEMENT = 0;
/** /**
* This is a not standard character, so build a const, so a dev can easily use it. * This is a not standard character, so build a const, so a dev can easily use it.
*/ */
public const PATH_DELIMITER_ARROW = ' → '; final public const PATH_DELIMITER_ARROW = ' → ';
/** /**
* @var string The comment info for this element * @var string The comment info for this element
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $comment = ''; protected string $comment = '';
/** /**
@ -71,7 +74,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
* Useful if this element should be used only for grouping, sorting. * Useful if this element should be used only for grouping, sorting.
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $not_selectable = false; protected bool $not_selectable = false;
/** /**

View file

@ -35,7 +35,7 @@ trait MasterAttachmentTrait
* @var Attachment|null * @var Attachment|null
*/ */
#[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')] #[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')]
#[ORM\ManyToOne(targetEntity: \App\Entity\Attachments\Attachment::class)] #[ORM\ManyToOne(targetEntity: Attachment::class)]
#[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')]
protected ?Attachment $master_picture_attachment = null; protected ?Attachment $master_picture_attachment = null;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Base; namespace App\Entity\Base;
use Doctrine\DBAL\Types\Types;
use DateTime; use DateTime;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
@ -35,14 +36,14 @@ trait TimestampTrait
* @var \DateTimeInterface|null the date when this element was modified the last time * @var \DateTimeInterface|null the date when this element was modified the last time
*/ */
#[Groups(['extended', 'full'])] #[Groups(['extended', 'full'])]
#[ORM\Column(name: 'last_modified', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, options: ['default' => 'CURRENT_TIMESTAMP'])] #[ORM\Column(name: 'last_modified', type: Types::DATETIME_MUTABLE, options: ['default' => 'CURRENT_TIMESTAMP'])]
protected ?\DateTimeInterface $lastModified = null; protected ?\DateTimeInterface $lastModified = null;
/** /**
* @var \DateTimeInterface|null the date when this element was created * @var \DateTimeInterface|null the date when this element was created
*/ */
#[Groups(['extended', 'full'])] #[Groups(['extended', 'full'])]
#[ORM\Column(name: 'datetime_added', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, options: ['default' => 'CURRENT_TIMESTAMP'])] #[ORM\Column(name: 'datetime_added', type: Types::DATETIME_MUTABLE, options: ['default' => 'CURRENT_TIMESTAMP'])]
protected ?\DateTimeInterface $addedDate = null; protected ?\DateTimeInterface $addedDate = null;
/** /**

View file

@ -41,6 +41,7 @@ declare(strict_types=1);
namespace App\Entity\LabelSystem; namespace App\Entity\LabelSystem;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
@ -57,53 +58,53 @@ class LabelOptions
* @var float The page size of the label in mm * @var float The page size of the label in mm
*/ */
#[Assert\Positive] #[Assert\Positive]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] #[ORM\Column(type: Types::FLOAT)]
protected float $width = 50.0; protected float $width = 50.0;
/** /**
* @var float The page size of the label in mm * @var float The page size of the label in mm
*/ */
#[Assert\Positive] #[Assert\Positive]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] #[ORM\Column(type: Types::FLOAT)]
protected float $height = 30.0; protected float $height = 30.0;
/** /**
* @var string The type of the barcode that should be used in the label (e.g. 'qr') * @var string The type of the barcode that should be used in the label (e.g. 'qr')
*/ */
#[Assert\Choice(choices: LabelOptions::BARCODE_TYPES)] #[Assert\Choice(choices: LabelOptions::BARCODE_TYPES)]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $barcode_type = 'none'; protected string $barcode_type = 'none';
/** /**
* @var string What image should be shown along the * @var string What image should be shown along the
*/ */
#[Assert\Choice(choices: LabelOptions::PICTURE_TYPES)] #[Assert\Choice(choices: LabelOptions::PICTURE_TYPES)]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $picture_type = 'none'; protected string $picture_type = 'none';
/** /**
* @var string * @var string
*/ */
#[Assert\Choice(choices: LabelOptions::SUPPORTED_ELEMENTS)] #[Assert\Choice(choices: LabelOptions::SUPPORTED_ELEMENTS)]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $supported_element = 'part'; protected string $supported_element = 'part';
/** /**
* @var string any additional CSS for the label * @var string any additional CSS for the label
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $additional_css = ''; protected string $additional_css = '';
/** @var string The mode that will be used to interpret the lines /** @var string The mode that will be used to interpret the lines
*/ */
#[Assert\Choice(choices: LabelOptions::LINES_MODES)] #[Assert\Choice(choices: LabelOptions::LINES_MODES)]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $lines_mode = 'html'; protected string $lines_mode = 'html';
/** /**
* @var string * @var string
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $lines = ''; protected string $lines = '';
public function getWidth(): float public function getWidth(): float

View file

@ -41,6 +41,10 @@ declare(strict_types=1);
namespace App\Entity\LabelSystem; namespace App\Entity\LabelSystem;
use App\Repository\LabelProfileRepository;
use App\EntityListeners\TreeCacheInvalidationListener;
use Doctrine\DBAL\Types\Types;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Attachments\LabelAttachment; use App\Entity\Attachments\LabelAttachment;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
@ -49,15 +53,15 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
#[UniqueEntity(['name', 'options.supported_element'])] #[UniqueEntity(['name', 'options.supported_element'])]
#[ORM\Entity(repositoryClass: \App\Repository\LabelProfileRepository::class)] #[ORM\Entity(repositoryClass: LabelProfileRepository::class)]
#[ORM\EntityListeners([\App\EntityListeners\TreeCacheInvalidationListener::class])] #[ORM\EntityListeners([TreeCacheInvalidationListener::class])]
#[ORM\Table(name: 'label_profiles')] #[ORM\Table(name: 'label_profiles')]
class LabelProfile extends AttachmentContainingDBElement class LabelProfile extends AttachmentContainingDBElement
{ {
/** /**
* @var Collection<int, LabelAttachment> * @var Collection<int, LabelAttachment>
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\LabelAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: LabelAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
@ -71,18 +75,18 @@ class LabelProfile extends AttachmentContainingDBElement
/** /**
* @var string The comment info for this element * @var string The comment info for this element
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $comment = ''; protected string $comment = '';
/** /**
* @var bool determines, if this label profile should be shown in the dropdown quick menu * @var bool determines, if this label profile should be shown in the dropdown quick menu
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $show_in_dropdown = true; protected bool $show_in_dropdown = true;
public function __construct() public function __construct()
{ {
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
parent::__construct(); parent::__construct();
$this->options = new LabelOptions(); $this->options = new LabelOptions();
} }

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\LogSystem; namespace App\Entity\LogSystem;
use Doctrine\DBAL\Types\Types;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentType;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
@ -129,19 +130,19 @@ abstract class AbstractLogEntry extends AbstractDBElement
/** @var User|null The user which has caused this log entry /** @var User|null The user which has caused this log entry
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\User::class, fetch: 'EAGER')] #[ORM\ManyToOne(targetEntity: User::class, fetch: 'EAGER')]
#[ORM\JoinColumn(name: 'id_user', onDelete: 'SET NULL')] #[ORM\JoinColumn(name: 'id_user', onDelete: 'SET NULL')]
protected ?User $user = null; protected ?User $user = null;
/** /**
* @var string The username of the user which has caused this log entry (shown if the user is deleted) * @var string The username of the user which has caused this log entry (shown if the user is deleted)
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $username = ''; protected string $username = '';
/** @var \DateTimeInterface|null The datetime the event associated with this log entry has occured /** @var \DateTimeInterface|null The datetime the event associated with this log entry has occured
*/ */
#[ORM\Column(name: 'datetime', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE)] #[ORM\Column(name: 'datetime', type: Types::DATETIME_MUTABLE)]
protected ?\DateTimeInterface $timestamp = null; protected ?\DateTimeInterface $timestamp = null;
/** @var int The priority level of the associated level. 0 is highest, 7 lowest /** @var int The priority level of the associated level. 0 is highest, 7 lowest
@ -151,12 +152,12 @@ abstract class AbstractLogEntry extends AbstractDBElement
/** @var int The ID of the element targeted by this event /** @var int The ID of the element targeted by this event
*/ */
#[ORM\Column(name: 'target_id', type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(name: 'target_id', type: Types::INTEGER)]
protected int $target_id = 0; protected int $target_id = 0;
/** @var int The Type of the targeted element /** @var int The Type of the targeted element
*/ */
#[ORM\Column(name: 'target_type', type: \Doctrine\DBAL\Types\Types::SMALLINT)] #[ORM\Column(name: 'target_type', type: Types::SMALLINT)]
protected int $target_type = 0; protected int $target_type = 0;
/** @var string The type of this log entry, aka the description what has happened. /** @var string The type of this log entry, aka the description what has happened.
@ -167,7 +168,7 @@ abstract class AbstractLogEntry extends AbstractDBElement
/** @var array The extra data in raw (short form) saved in the DB /** @var array The extra data in raw (short form) saved in the DB
*/ */
#[ORM\Column(name: 'extra', type: \Doctrine\DBAL\Types\Types::JSON)] #[ORM\Column(name: 'extra', type: Types::JSON)]
protected array $extra = []; protected array $extra = [];
public function __construct() public function __construct()
@ -370,7 +371,7 @@ abstract class AbstractLogEntry extends AbstractDBElement
*/ */
public function setTargetElement(?AbstractDBElement $element): self public function setTargetElement(?AbstractDBElement $element): self
{ {
if (!$element instanceof \App\Entity\Base\AbstractDBElement) { if (!$element instanceof AbstractDBElement) {
$this->target_id = 0; $this->target_id = 0;
$this->target_type = self::TARGET_TYPE_NONE; $this->target_type = self::TARGET_TYPE_NONE;

View file

@ -68,7 +68,7 @@ class PartStockChangedLogEntry extends AbstractLogEntry
$this->extra['c'] = mb_strimwidth($comment, 0, self::COMMENT_MAX_LENGTH, '...'); $this->extra['c'] = mb_strimwidth($comment, 0, self::COMMENT_MAX_LENGTH, '...');
} }
if ($move_to_target instanceof \App\Entity\Parts\PartLot) { if ($move_to_target instanceof PartLot) {
if ($type !== self::TYPE_MOVE) { if ($type !== self::TYPE_MOVE) {
throw new \InvalidArgumentException('The move_to_target parameter can only be set if the type is "move"!'); throw new \InvalidArgumentException('The move_to_target parameter can only be set if the type is "move"!');
} }

View file

@ -41,6 +41,8 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractNamedDBElement;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@ -51,7 +53,7 @@ use Symfony\Component\Validator\Constraints as Assert;
use function sprintf; use function sprintf;
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
#[ORM\InheritanceType('SINGLE_TABLE')] #[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorColumn(name: 'type', type: 'smallint')] #[ORM\DiscriminatorColumn(name: 'type', type: 'smallint')]
#[ORM\DiscriminatorMap([0 => 'CategoryParameter', 1 => 'CurrencyParameter', 2 => 'ProjectParameter', 3 => 'FootprintParameter', 4 => 'GroupParameter', 5 => 'ManufacturerParameter', 6 => 'MeasurementUnitParameter', 7 => 'PartParameter', 8 => 'StorelocationParameter', 9 => 'SupplierParameter', 10 => 'AttachmentTypeParameter'])] #[ORM\DiscriminatorMap([0 => 'CategoryParameter', 1 => 'CurrencyParameter', 2 => 'ProjectParameter', 3 => 'FootprintParameter', 4 => 'GroupParameter', 5 => 'ManufacturerParameter', 6 => 'MeasurementUnitParameter', 7 => 'PartParameter', 8 => 'StorelocationParameter', 9 => 'SupplierParameter', 10 => 'AttachmentTypeParameter'])]
@ -71,7 +73,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement
*/ */
#[Assert\Length(max: 20)] #[Assert\Length(max: 20)]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $symbol = ''; protected string $symbol = '';
/** /**
@ -81,7 +83,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement
#[Assert\LessThanOrEqual(propertyPath: 'value_typical', message: 'parameters.validator.min_lesser_typical')] #[Assert\LessThanOrEqual(propertyPath: 'value_typical', message: 'parameters.validator.min_lesser_typical')]
#[Assert\LessThan(propertyPath: 'value_max', message: 'parameters.validator.min_lesser_max')] #[Assert\LessThan(propertyPath: 'value_max', message: 'parameters.validator.min_lesser_max')]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, nullable: true)] #[ORM\Column(type: Types::FLOAT, nullable: true)]
protected ?float $value_min = null; protected ?float $value_min = null;
/** /**
@ -89,7 +91,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement
*/ */
#[Assert\Type([null, 'float'])] #[Assert\Type([null, 'float'])]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, nullable: true)] #[ORM\Column(type: Types::FLOAT, nullable: true)]
protected ?float $value_typical = null; protected ?float $value_typical = null;
/** /**
@ -98,21 +100,21 @@ abstract class AbstractParameter extends AbstractNamedDBElement
#[Assert\Type(['float', null])] #[Assert\Type(['float', null])]
#[Assert\GreaterThanOrEqual(propertyPath: 'value_typical', message: 'parameters.validator.max_greater_typical')] #[Assert\GreaterThanOrEqual(propertyPath: 'value_typical', message: 'parameters.validator.max_greater_typical')]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, nullable: true)] #[ORM\Column(type: Types::FLOAT, nullable: true)]
protected ?float $value_max = null; protected ?float $value_max = null;
/** /**
* @var string The unit in which the value values are given (e.g. V) * @var string The unit in which the value values are given (e.g. V)
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $unit = ''; protected string $unit = '';
/** /**
* @var string a text value for the given property * @var string a text value for the given property
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $value_text = ''; protected string $value_text = '';
/** /**
@ -120,7 +122,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'param_group')] #[ORM\Column(type: Types::STRING, name: 'param_group')]
protected string $group = ''; protected string $group = '';
/** /**

View file

@ -41,20 +41,21 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentType;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class AttachmentTypeParameter extends AbstractParameter class AttachmentTypeParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = AttachmentType::class; final public const ALLOWED_ELEMENT_CLASS = AttachmentType::class;
/** /**
* @var AttachmentType the element this para is associated with * @var AttachmentType the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Attachments\AttachmentType::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,20 +41,21 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\Category; use App\Entity\Parts\Category;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class CategoryParameter extends AbstractParameter class CategoryParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Category::class; final public const ALLOWED_ELEMENT_CLASS = Category::class;
/** /**
* @var Category the element this para is associated with * @var Category the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Category::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Category::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,6 +41,7 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\PriceInformations\Currency; use App\Entity\PriceInformations\Currency;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@ -50,7 +51,7 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
* An attachment attached to a category element. * An attachment attached to a category element.
*/ */
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class CurrencyParameter extends AbstractParameter class CurrencyParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Currency::class; final public const ALLOWED_ELEMENT_CLASS = Currency::class;
@ -58,7 +59,7 @@ class CurrencyParameter extends AbstractParameter
/** /**
* @var Currency the element this para is associated with * @var Currency the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\PriceInformations\Currency::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Currency::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\Footprint; use App\Entity\Parts\Footprint;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class FootprintParameter extends AbstractParameter class FootprintParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Footprint::class; final public const ALLOWED_ELEMENT_CLASS = Footprint::class;
@ -55,7 +56,7 @@ class FootprintParameter extends AbstractParameter
/** /**
* @var Footprint the element this para is associated with * @var Footprint the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Footprint::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Footprint::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\UserSystem\Group; use App\Entity\UserSystem\Group;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class GroupParameter extends AbstractParameter class GroupParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Group::class; final public const ALLOWED_ELEMENT_CLASS = Group::class;
@ -55,7 +56,7 @@ class GroupParameter extends AbstractParameter
/** /**
* @var Group the element this para is associated with * @var Group the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\Group::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Group::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\Manufacturer; use App\Entity\Parts\Manufacturer;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class ManufacturerParameter extends AbstractParameter class ManufacturerParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Manufacturer::class; final public const ALLOWED_ELEMENT_CLASS = Manufacturer::class;
@ -55,7 +56,7 @@ class ManufacturerParameter extends AbstractParameter
/** /**
* @var Manufacturer the element this para is associated with * @var Manufacturer the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Manufacturer::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Manufacturer::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\MeasurementUnit;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class MeasurementUnitParameter extends AbstractParameter class MeasurementUnitParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = MeasurementUnit::class; final public const ALLOWED_ELEMENT_CLASS = MeasurementUnit::class;
@ -55,7 +56,7 @@ class MeasurementUnitParameter extends AbstractParameter
/** /**
* @var MeasurementUnit the element this para is associated with * @var MeasurementUnit the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\MeasurementUnit::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: MeasurementUnit::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class PartParameter extends AbstractParameter class PartParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Part::class; final public const ALLOWED_ELEMENT_CLASS = Part::class;
@ -55,7 +56,7 @@ class PartParameter extends AbstractParameter
/** /**
* @var Part the element this para is associated with * @var Part the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Part::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Part::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\Project;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class ProjectParameter extends AbstractParameter class ProjectParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Project::class; final public const ALLOWED_ELEMENT_CLASS = Project::class;
@ -55,7 +56,7 @@ class ProjectParameter extends AbstractParameter
/** /**
* @var Project the element this para is associated with * @var Project the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\ProjectSystem\Project::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Project::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\Storelocation; use App\Entity\Parts\Storelocation;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class StorelocationParameter extends AbstractParameter class StorelocationParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Storelocation::class; final public const ALLOWED_ELEMENT_CLASS = Storelocation::class;
@ -55,7 +56,7 @@ class StorelocationParameter extends AbstractParameter
/** /**
* @var Storelocation the element this para is associated with * @var Storelocation the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Storelocation::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Storelocation::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -41,13 +41,14 @@ declare(strict_types=1);
namespace App\Entity\Parameters; namespace App\Entity\Parameters;
use App\Repository\ParameterRepository;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\Supplier; use App\Entity\Parts\Supplier;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['name', 'group', 'element'])] #[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: \App\Repository\ParameterRepository::class)] #[ORM\Entity(repositoryClass: ParameterRepository::class)]
class SupplierParameter extends AbstractParameter class SupplierParameter extends AbstractParameter
{ {
final public const ALLOWED_ELEMENT_CLASS = Supplier::class; final public const ALLOWED_ELEMENT_CLASS = Supplier::class;
@ -55,7 +56,7 @@ class SupplierParameter extends AbstractParameter
/** /**
* @var Supplier the element this para is associated with * @var Supplier the element this para is associated with
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Supplier::class, inversedBy: 'parameters')] #[ORM\ManyToOne(targetEntity: Supplier::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
protected ?AbstractDBElement $element = null; protected ?AbstractDBElement $element = null;
} }

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use App\Repository\Parts\CategoryRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Attachments\CategoryAttachment; use App\Entity\Attachments\CategoryAttachment;
use App\Entity\Base\AbstractPartsContainingDBElement; use App\Entity\Base\AbstractPartsContainingDBElement;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
@ -34,7 +37,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/** /**
* Class AttachmentType. * Class AttachmentType.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\Parts\CategoryRepository::class)] #[ORM\Entity(repositoryClass: CategoryRepository::class)]
#[ORM\Table(name: '`categories`')] #[ORM\Table(name: '`categories`')]
#[ORM\Index(name: 'category_idx_name', columns: ['name'])] #[ORM\Index(name: 'category_idx_name', columns: ['name'])]
#[ORM\Index(name: 'category_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'category_idx_parent_name', columns: ['parent_id', 'name'])]
@ -55,56 +58,56 @@ class Category extends AbstractPartsContainingDBElement
* @var string * @var string
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $partname_hint = ''; protected string $partname_hint = '';
/** /**
* @var string * @var string
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $partname_regex = ''; protected string $partname_regex = '';
/** /**
* @var bool * @var bool
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $disable_footprints = false; protected bool $disable_footprints = false;
/** /**
* @var bool * @var bool
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $disable_manufacturers = false; protected bool $disable_manufacturers = false;
/** /**
* @var bool * @var bool
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $disable_autodatasheets = false; protected bool $disable_autodatasheets = false;
/** /**
* @var bool * @var bool
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $disable_properties = false; protected bool $disable_properties = false;
/** /**
* @var string * @var string
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $default_description = ''; protected string $default_description = '';
/** /**
* @var string * @var string
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $default_comment = ''; protected string $default_comment = '';
/** /**
@ -112,7 +115,7 @@ class Category extends AbstractPartsContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\CategoryAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: CategoryAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
@ -120,7 +123,7 @@ class Category extends AbstractPartsContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\CategoryParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: CategoryParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
@ -222,8 +225,8 @@ class Category extends AbstractPartsContainingDBElement
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
} }
} }

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use App\Repository\Parts\FootprintRepository;
use App\Entity\Base\AbstractStructuralDBElement;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Attachments\FootprintAttachment; use App\Entity\Attachments\FootprintAttachment;
use App\Entity\Base\AbstractPartsContainingDBElement; use App\Entity\Base\AbstractPartsContainingDBElement;
use App\Entity\Parameters\FootprintParameter; use App\Entity\Parameters\FootprintParameter;
@ -32,7 +35,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/** /**
* Class Footprint. * Class Footprint.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\Parts\FootprintRepository::class)] #[ORM\Entity(repositoryClass: FootprintRepository::class)]
#[ORM\Table('`footprints`')] #[ORM\Table('`footprints`')]
#[ORM\Index(name: 'footprint_idx_name', columns: ['name'])] #[ORM\Index(name: 'footprint_idx_name', columns: ['name'])]
#[ORM\Index(name: 'footprint_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'footprint_idx_parent_name', columns: ['parent_id', 'name'])]
@ -40,7 +43,7 @@ class Footprint extends AbstractPartsContainingDBElement
{ {
#[ORM\ManyToOne(targetEntity: 'Footprint', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: 'Footprint', inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?\App\Entity\Base\AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
/** /**
* @var Collection * @var Collection
@ -53,21 +56,21 @@ class Footprint extends AbstractPartsContainingDBElement
* @var Collection<int, FootprintAttachment> * @var Collection<int, FootprintAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\FootprintAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: FootprintAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** /**
* @var FootprintAttachment|null * @var FootprintAttachment|null
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Attachments\FootprintAttachment::class)] #[ORM\ManyToOne(targetEntity: FootprintAttachment::class)]
#[ORM\JoinColumn(name: 'id_footprint_3d')] #[ORM\JoinColumn(name: 'id_footprint_3d')]
protected ?FootprintAttachment $footprint_3d = null; protected ?FootprintAttachment $footprint_3d = null;
/** @var Collection<int, FootprintParameter> /** @var Collection<int, FootprintParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\FootprintParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: FootprintParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
@ -102,8 +105,8 @@ class Footprint extends AbstractPartsContainingDBElement
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
} }
} }

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use App\Repository\Parts\ManufacturerRepository;
use App\Entity\Base\AbstractStructuralDBElement;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Attachments\ManufacturerAttachment; use App\Entity\Attachments\ManufacturerAttachment;
use App\Entity\Base\AbstractCompany; use App\Entity\Base\AbstractCompany;
use App\Entity\Parameters\ManufacturerParameter; use App\Entity\Parameters\ManufacturerParameter;
@ -32,7 +35,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/** /**
* Class Manufacturer. * Class Manufacturer.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\Parts\ManufacturerRepository::class)] #[ORM\Entity(repositoryClass: ManufacturerRepository::class)]
#[ORM\Table('`manufacturers`')] #[ORM\Table('`manufacturers`')]
#[ORM\Index(name: 'manufacturer_name', columns: ['name'])] #[ORM\Index(name: 'manufacturer_name', columns: ['name'])]
#[ORM\Index(name: 'manufacturer_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'manufacturer_idx_parent_name', columns: ['parent_id', 'name'])]
@ -40,7 +43,7 @@ class Manufacturer extends AbstractCompany
{ {
#[ORM\ManyToOne(targetEntity: 'Manufacturer', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: 'Manufacturer', inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?\App\Entity\Base\AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
/** /**
* @var Collection * @var Collection
@ -53,21 +56,21 @@ class Manufacturer extends AbstractCompany
* @var Collection<int, ManufacturerAttachment> * @var Collection<int, ManufacturerAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\ManufacturerAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: ManufacturerAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** @var Collection<int, ManufacturerParameter> /** @var Collection<int, ManufacturerParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\ManufacturerParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: ManufacturerParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
} }
} }

View file

@ -22,6 +22,10 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use App\Repository\Parts\MeasurementUnitRepository;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractStructuralDBElement;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Attachments\MeasurementUnitAttachment; use App\Entity\Attachments\MeasurementUnitAttachment;
use App\Entity\Base\AbstractPartsContainingDBElement; use App\Entity\Base\AbstractPartsContainingDBElement;
use App\Entity\Parameters\MeasurementUnitParameter; use App\Entity\Parameters\MeasurementUnitParameter;
@ -36,7 +40,7 @@ use Symfony\Component\Validator\Constraints as Assert;
* This could be something like N, grams, meters, etc... * This could be something like N, grams, meters, etc...
*/ */
#[UniqueEntity('unit')] #[UniqueEntity('unit')]
#[ORM\Entity(repositoryClass: \App\Repository\Parts\MeasurementUnitRepository::class)] #[ORM\Entity(repositoryClass: MeasurementUnitRepository::class)]
#[ORM\Table(name: '`measurement_units`')] #[ORM\Table(name: '`measurement_units`')]
#[ORM\Index(name: 'unit_idx_name', columns: ['name'])] #[ORM\Index(name: 'unit_idx_name', columns: ['name'])]
#[ORM\Index(name: 'unit_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'unit_idx_parent_name', columns: ['parent_id', 'name'])]
@ -48,7 +52,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
*/ */
#[Assert\Length(max: 10)] #[Assert\Length(max: 10)]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'unit', nullable: true)] #[ORM\Column(type: Types::STRING, name: 'unit', nullable: true)]
protected ?string $unit = null; protected ?string $unit = null;
/** /**
@ -56,7 +60,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
* Set to false, to measure continuous sizes likes masses or lengths. * Set to false, to measure continuous sizes likes masses or lengths.
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, name: 'is_integer')] #[ORM\Column(type: Types::BOOLEAN, name: 'is_integer')]
protected bool $is_integer = false; protected bool $is_integer = false;
/** /**
@ -65,7 +69,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
*/ */
#[Assert\Expression('this.isUseSIPrefix() == false or this.getUnit() != null', message: 'validator.measurement_unit.use_si_prefix_needs_unit')] #[Assert\Expression('this.isUseSIPrefix() == false or this.getUnit() != null', message: 'validator.measurement_unit.use_si_prefix_needs_unit')]
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, name: 'use_si_prefix')] #[ORM\Column(type: Types::BOOLEAN, name: 'use_si_prefix')]
protected bool $use_si_prefix = false; protected bool $use_si_prefix = false;
/** /**
@ -77,20 +81,20 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
#[ORM\ManyToOne(targetEntity: 'MeasurementUnit', inversedBy: 'children')] #[ORM\ManyToOne(targetEntity: 'MeasurementUnit', inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')] #[ORM\JoinColumn(name: 'parent_id')]
protected ?\App\Entity\Base\AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
/** /**
* @var Collection<int, MeasurementUnitAttachment> * @var Collection<int, MeasurementUnitAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\MeasurementUnitAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: MeasurementUnitAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** @var Collection<int, MeasurementUnitParameter> /** @var Collection<int, MeasurementUnitParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\MeasurementUnitParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: MeasurementUnitParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
@ -135,8 +139,8 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
} }
} }

View file

@ -22,6 +22,8 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use App\Repository\PartRepository;
use Doctrine\DBAL\Types\Types;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Attachments\PartAttachment; use App\Entity\Attachments\PartAttachment;
@ -49,7 +51,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
* Otherwise, this class would be too big, to be maintained. * Otherwise, this class would be too big, to be maintained.
*/ */
#[UniqueEntity(fields: ['ipn'], message: 'part.ipn.must_be_unique')] #[UniqueEntity(fields: ['ipn'], message: 'part.ipn.must_be_unique')]
#[ORM\Entity(repositoryClass: \App\Repository\PartRepository::class)] #[ORM\Entity(repositoryClass: PartRepository::class)]
#[ORM\Table('`parts`')] #[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_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_name', columns: ['name'])]
@ -69,7 +71,7 @@ class Part extends AttachmentContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\PartParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: PartParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
@ -81,7 +83,7 @@ class Part extends AttachmentContainingDBElement
/** /**
* @var string The name of this part * @var string The name of this part
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $name = ''; protected string $name = '';
/** /**
@ -89,7 +91,7 @@ class Part extends AttachmentContainingDBElement
*/ */
#[Assert\Valid] #[Assert\Valid]
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\PartAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: PartAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
@ -97,13 +99,13 @@ class Part extends AttachmentContainingDBElement
* @var Attachment|null * @var Attachment|null
*/ */
#[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')] #[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')]
#[ORM\ManyToOne(targetEntity: \App\Entity\Attachments\Attachment::class)] #[ORM\ManyToOne(targetEntity: Attachment::class)]
#[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')]
protected ?Attachment $master_picture_attachment = null; protected ?Attachment $master_picture_attachment = null;
public function __construct() public function __construct()
{ {
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
parent::__construct(); parent::__construct();
$this->partLots = new ArrayCollection(); $this->partLots = new ArrayCollection();
$this->orderdetails = new ArrayCollection(); $this->orderdetails = new ArrayCollection();
@ -142,7 +144,7 @@ class Part extends AttachmentContainingDBElement
public function validate(ExecutionContextInterface $context, $payload) public function validate(ExecutionContextInterface $context, $payload)
{ {
//Ensure that the part name fullfills the regex of the category //Ensure that the part name fullfills the regex of the category
if ($this->category instanceof \App\Entity\Parts\Category) { if ($this->category instanceof Category) {
$regex = $this->category->getPartnameRegex(); $regex = $this->category->getPartnameRegex();
if (!empty($regex) && !preg_match($regex, $this->name)) { if (!empty($regex) && !preg_match($regex, $this->name)) {
$context->buildViolation('part.name.must_match_category_regex') $context->buildViolation('part.name.must_match_category_regex')

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\TimestampTrait; use App\Entity\Base\TimestampTrait;
use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\NamedElementInterface;
@ -55,14 +56,14 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
* @var string A short description about this lot, shown in table * @var string A short description about this lot, shown in table
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $description = ''; protected string $description = '';
/** /**
* @var string a comment stored with this lot * @var string a comment stored with this lot
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $comment = ''; protected string $comment = '';
/** /**
@ -70,7 +71,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
* Set to null, if the lot can be used indefinitely. * Set to null, if the lot can be used indefinitely.
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, name: 'expiration_date', nullable: true)] #[ORM\Column(type: Types::DATETIME_MUTABLE, name: 'expiration_date', nullable: true)]
protected ?\DateTimeInterface $expiration_date = null; protected ?\DateTimeInterface $expiration_date = null;
/** /**
@ -86,7 +87,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
* @var bool If this is set to true, the instock amount is marked as not known * @var bool If this is set to true, the instock amount is marked as not known
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $instock_unknown = false; protected bool $instock_unknown = false;
/** /**
@ -94,14 +95,14 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
*/ */
#[Assert\PositiveOrZero] #[Assert\PositiveOrZero]
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] #[ORM\Column(type: Types::FLOAT)]
protected float $amount = 0.0; protected float $amount = 0.0;
/** /**
* @var bool determines if this lot was manually marked for refilling * @var bool determines if this lot was manually marked for refilling
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $needs_refill = false; protected bool $needs_refill = false;
/** /**
@ -115,7 +116,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
/** /**
* @var User|null The owner of this part lot * @var User|null The owner of this part lot
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\User::class)] #[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(name: 'id_owner', onDelete: 'SET NULL')] #[ORM\JoinColumn(name: 'id_owner', onDelete: 'SET NULL')]
protected ?User $owner = null; protected ?User $owner = null;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits; namespace App\Entity\Parts\PartTraits;
use Doctrine\DBAL\Types\Types;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
@ -36,14 +37,14 @@ trait AdvancedPropertyTrait
* @var bool Determines if this part entry needs review (for example, because it is work in progress) * @var bool Determines if this part entry needs review (for example, because it is work in progress)
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $needs_review = false; protected bool $needs_review = false;
/** /**
* @var string a comma separated list of tags, associated with the part * @var string a comma separated list of tags, associated with the part
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $tags = ''; protected string $tags = '';
/** /**
@ -51,7 +52,7 @@ trait AdvancedPropertyTrait
*/ */
#[Assert\PositiveOrZero] #[Assert\PositiveOrZero]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, nullable: true)] #[ORM\Column(type: Types::FLOAT, nullable: true)]
protected ?float $mass = null; protected ?float $mass = null;
/** /**
@ -59,7 +60,7 @@ trait AdvancedPropertyTrait
*/ */
#[Assert\Length(max: 100)] #[Assert\Length(max: 100)]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 100, nullable: true, unique: true)] #[ORM\Column(type: Types::STRING, length: 100, nullable: true, unique: true)]
protected ?string $ipn = null; protected ?string $ipn = null;
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits; namespace App\Entity\Parts\PartTraits;
use Doctrine\DBAL\Types\Types;
use App\Entity\Parts\Category; use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint; use App\Entity\Parts\Footprint;
use App\Validator\Constraints\Selectable; use App\Validator\Constraints\Selectable;
@ -35,27 +36,27 @@ trait BasicPropertyTrait
* @var string A text describing what this part does * @var string A text describing what this part does
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $description = ''; protected string $description = '';
/** /**
* @var string A comment/note related to this part * @var string A comment/note related to this part
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $comment = ''; protected string $comment = '';
/** /**
* @var bool Kept for compatibility (it is not used now, and I don't think it was used in old versions) * @var bool Kept for compatibility (it is not used now, and I don't think it was used in old versions)
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $visible = true; protected bool $visible = true;
/** /**
* @var bool true, if the part is marked as favorite * @var bool true, if the part is marked as favorite
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $favorite = false; protected bool $favorite = false;
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits; namespace App\Entity\Parts\PartTraits;
use Doctrine\DBAL\Types\Types;
use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\PartLot; use App\Entity\Parts\PartLot;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
@ -41,7 +42,7 @@ trait InstockTrait
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\OneToMany(targetEntity: 'PartLot', mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: 'PartLot', mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['amount' => 'DESC'])] #[ORM\OrderBy(['amount' => 'DESC'])]
protected \Doctrine\Common\Collections\Collection $partLots; protected Collection $partLots;
/** /**
* @var float The minimum amount of the part that has to be instock, otherwise more is ordered. * @var float The minimum amount of the part that has to be instock, otherwise more is ordered.
@ -49,7 +50,7 @@ trait InstockTrait
*/ */
#[Assert\PositiveOrZero] #[Assert\PositiveOrZero]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] #[ORM\Column(type: Types::FLOAT)]
protected float $minamount = 0; protected float $minamount = 0;
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits; namespace App\Entity\Parts\PartTraits;
use Doctrine\DBAL\Types\Types;
use App\Entity\Parts\Manufacturer; use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;
use App\Validator\Constraints\Selectable; use App\Validator\Constraints\Selectable;
@ -48,14 +49,14 @@ trait ManufacturerTrait
*/ */
#[Assert\Url] #[Assert\Url]
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $manufacturer_product_url = ''; protected string $manufacturer_product_url = '';
/** /**
* @var string The product number used by the manufacturer. If this is set to "", the name field is used. * @var string The product number used by the manufacturer. If this is set to "", the name field is used.
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $manufacturer_product_number = ''; protected string $manufacturer_product_number = '';
/** /**
@ -63,7 +64,7 @@ trait ManufacturerTrait
*/ */
#[Assert\Choice(['announced', 'active', 'nrfnd', 'eol', 'discontinued', ''])] #[Assert\Choice(['announced', 'active', 'nrfnd', 'eol', 'discontinued', ''])]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] #[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
protected ?string $manufacturing_status = ''; protected ?string $manufacturing_status = '';
/** /**

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits; namespace App\Entity\Parts\PartTraits;
use Doctrine\DBAL\Types\Types;
use App\Entity\PriceInformations\Orderdetail; use App\Entity\PriceInformations\Orderdetail;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
@ -39,26 +40,26 @@ trait OrderTrait
*/ */
#[Assert\Valid] #[Assert\Valid]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\OneToMany(targetEntity: \App\Entity\PriceInformations\Orderdetail::class, mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: Orderdetail::class, mappedBy: 'part', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['supplierpartnr' => 'ASC'])] #[ORM\OrderBy(['supplierpartnr' => 'ASC'])]
protected \Doctrine\Common\Collections\Collection $orderdetails; protected Collection $orderdetails;
/** /**
* @var int * @var int
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]
protected int $order_quantity = 0; protected int $order_quantity = 0;
/** /**
* @var bool * @var bool
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $manual_order = false; protected bool $manual_order = false;
/** /**
* @var Orderdetail|null * @var Orderdetail|null
*/ */
#[ORM\OneToOne(targetEntity: \App\Entity\PriceInformations\Orderdetail::class)] #[ORM\OneToOne(targetEntity: Orderdetail::class)]
#[ORM\JoinColumn(name: 'order_orderdetails_id')] #[ORM\JoinColumn(name: 'order_orderdetails_id')]
protected ?Orderdetail $order_orderdetail = null; protected ?Orderdetail $order_orderdetail = null;

View file

@ -11,15 +11,18 @@ use Doctrine\ORM\Mapping as ORM;
trait ProjectTrait trait ProjectTrait
{ {
/** /**
* @var \Doctrine\Common\Collections\Collection<\App\Entity\ProjectSystem\ProjectBOMEntry> $project_bom_entries * @var Collection<ProjectBOMEntry> $project_bom_entries
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\ProjectSystem\ProjectBOMEntry::class, mappedBy: 'part', cascade: ['remove'], orphanRemoval: true)] /**
protected \Doctrine\Common\Collections\Collection $project_bom_entries; * @var Collection<ProjectBOMEntry> $project_bom_entries
*/
#[ORM\OneToMany(targetEntity: ProjectBOMEntry::class, mappedBy: 'part', 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. * @var Project|null If a project is set here, then this part is special and represents the builds of a project.
*/ */
#[ORM\OneToOne(targetEntity: \App\Entity\ProjectSystem\Project::class, inversedBy: 'build_part')] #[ORM\OneToOne(targetEntity: Project::class, inversedBy: 'build_part')]
#[ORM\JoinColumn] #[ORM\JoinColumn]
protected ?Project $built_project = null; protected ?Project $built_project = null;

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use App\Repository\Parts\StorelocationRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Attachments\StorelocationAttachment; use App\Entity\Attachments\StorelocationAttachment;
use App\Entity\Base\AbstractPartsContainingDBElement; use App\Entity\Base\AbstractPartsContainingDBElement;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
@ -35,7 +38,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/** /**
* Class Store location. * Class Store location.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\Parts\StorelocationRepository::class)] #[ORM\Entity(repositoryClass: StorelocationRepository::class)]
#[ORM\Table('`storelocations`')] #[ORM\Table('`storelocations`')]
#[ORM\Index(name: 'location_idx_name', columns: ['name'])] #[ORM\Index(name: 'location_idx_name', columns: ['name'])]
#[ORM\Index(name: 'location_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'location_idx_parent_name', columns: ['parent_id', 'name'])]
@ -62,7 +65,7 @@ class Storelocation extends AbstractPartsContainingDBElement
/** @var Collection<int, StorelocationParameter> /** @var Collection<int, StorelocationParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\StorelocationParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: StorelocationParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
@ -70,42 +73,42 @@ class Storelocation extends AbstractPartsContainingDBElement
* @var bool * @var bool
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $is_full = false; protected bool $is_full = false;
/** /**
* @var bool * @var bool
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $only_single_part = false; protected bool $only_single_part = false;
/** /**
* @var bool * @var bool
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $limit_to_existing_parts = false; protected bool $limit_to_existing_parts = false;
/** /**
* @var User|null The owner of this storage location * @var User|null The owner of this storage location
*/ */
#[Assert\Expression('this.getOwner() == null or this.getOwner().isAnonymousUser() === false', message: 'validator.part_lot.owner_must_not_be_anonymous')] #[Assert\Expression('this.getOwner() == null or this.getOwner().isAnonymousUser() === false', message: 'validator.part_lot.owner_must_not_be_anonymous')]
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\User::class)] #[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(name: 'id_owner', onDelete: 'SET NULL')] #[ORM\JoinColumn(name: 'id_owner', onDelete: 'SET NULL')]
protected ?User $owner = null; protected ?User $owner = null;
/** /**
* @var bool If this is set to true, only parts lots, which are owned by the same user as the store location are allowed to be stored here. * @var bool If this is set to true, only parts lots, which are owned by the same user as the store location are allowed to be stored here.
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] #[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
protected bool $part_owner_must_match = false; protected bool $part_owner_must_match = false;
/** /**
* @var Collection<int, StorelocationAttachment> * @var Collection<int, StorelocationAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\StorelocationAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: StorelocationAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
protected Collection $attachments; protected Collection $attachments;
/******************************************************************************** /********************************************************************************
@ -229,8 +232,8 @@ class Storelocation extends AbstractPartsContainingDBElement
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
} }
} }

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\Parts; namespace App\Entity\Parts;
use App\Repository\Parts\SupplierRepository;
use App\Entity\PriceInformations\Orderdetail;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Attachments\SupplierAttachment; use App\Entity\Attachments\SupplierAttachment;
use App\Entity\Base\AbstractCompany; use App\Entity\Base\AbstractCompany;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
@ -38,7 +41,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/** /**
* Class Supplier. * Class Supplier.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\Parts\SupplierRepository::class)] #[ORM\Entity(repositoryClass: SupplierRepository::class)]
#[ORM\Table('`suppliers`')] #[ORM\Table('`suppliers`')]
#[ORM\Index(name: 'supplier_idx_name', columns: ['name'])] #[ORM\Index(name: 'supplier_idx_name', columns: ['name'])]
#[ORM\Index(name: 'supplier_idx_parent_name', columns: ['parent_id', 'name'])] #[ORM\Index(name: 'supplier_idx_parent_name', columns: ['parent_id', 'name'])]
@ -56,9 +59,12 @@ class Supplier extends AbstractCompany
protected ?AbstractStructuralDBElement $parent = null; protected ?AbstractStructuralDBElement $parent = null;
/** /**
* @var \Doctrine\Common\Collections\Collection<int, \App\Entity\PriceInformations\Orderdetail>|\App\Entity\PriceInformations\Orderdetail[] * @var Collection<int, Orderdetail>|Orderdetail[]
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\PriceInformations\Orderdetail::class, mappedBy: 'supplier')] /**
* @var Collection<int, Orderdetail>|Orderdetail[]
*/
#[ORM\OneToMany(targetEntity: Orderdetail::class, mappedBy: 'supplier')]
protected Collection $orderdetails; protected Collection $orderdetails;
/** /**
@ -66,7 +72,7 @@ class Supplier extends AbstractCompany
* Set to null, to use global base currency. * Set to null, to use global base currency.
* @Selectable() * @Selectable()
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\PriceInformations\Currency::class)] #[ORM\ManyToOne(targetEntity: Currency::class)]
#[ORM\JoinColumn(name: 'default_currency_id')] #[ORM\JoinColumn(name: 'default_currency_id')]
protected ?Currency $default_currency = null; protected ?Currency $default_currency = null;
@ -82,14 +88,14 @@ class Supplier extends AbstractCompany
* @var Collection<int, SupplierAttachment> * @var Collection<int, SupplierAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\SupplierAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: SupplierAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** @var Collection<int, SupplierParameter> /** @var Collection<int, SupplierParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\SupplierParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: SupplierParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
@ -128,7 +134,7 @@ class Supplier extends AbstractCompany
*/ */
public function setShippingCosts(?BigDecimal $shipping_costs): self public function setShippingCosts(?BigDecimal $shipping_costs): self
{ {
if (!$shipping_costs instanceof \Brick\Math\BigDecimal) { if (!$shipping_costs instanceof BigDecimal) {
$this->shipping_costs = null; $this->shipping_costs = null;
} }
@ -142,9 +148,9 @@ class Supplier extends AbstractCompany
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->orderdetails = new \Doctrine\Common\Collections\ArrayCollection(); $this->orderdetails = new ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
} }
} }

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\PriceInformations; namespace App\Entity\PriceInformations;
use Doctrine\DBAL\Types\Types;
use App\Entity\Attachments\CurrencyAttachment; use App\Entity\Attachments\CurrencyAttachment;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Parameters\CurrencyParameter; use App\Entity\Parameters\CurrencyParameter;
@ -60,7 +61,7 @@ class Currency extends AbstractStructuralDBElement
*/ */
#[Assert\Currency] #[Assert\Currency]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $iso_code = ""; protected string $iso_code = "";
#[ORM\OneToMany(targetEntity: 'Currency', mappedBy: 'parent', cascade: ['persist'])] #[ORM\OneToMany(targetEntity: 'Currency', mappedBy: 'parent', cascade: ['persist'])]
@ -75,27 +76,27 @@ class Currency extends AbstractStructuralDBElement
* @var Collection<int, CurrencyAttachment> * @var Collection<int, CurrencyAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\CurrencyAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: CurrencyAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** @var Collection<int, CurrencyParameter> /** @var Collection<int, CurrencyParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\CurrencyParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: CurrencyParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
/** @var Collection<int, Pricedetail> /** @var Collection<int, Pricedetail>
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\PriceInformations\Pricedetail::class, mappedBy: 'currency')] #[ORM\OneToMany(targetEntity: Pricedetail::class, mappedBy: 'currency')]
protected Collection $pricedetails; protected Collection $pricedetails;
public function __construct() public function __construct()
{ {
$this->children = new \Doctrine\Common\Collections\ArrayCollection(); $this->children = new ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
$this->pricedetails = new ArrayCollection(); $this->pricedetails = new ArrayCollection();
parent::__construct(); parent::__construct();
} }
@ -129,7 +130,7 @@ class Currency extends AbstractStructuralDBElement
{ {
$tmp = $this->getExchangeRate(); $tmp = $this->getExchangeRate();
if (!$tmp instanceof \Brick\Math\BigDecimal || $tmp->isZero()) { if (!$tmp instanceof BigDecimal || $tmp->isZero()) {
return null; return null;
} }
@ -153,7 +154,7 @@ class Currency extends AbstractStructuralDBElement
*/ */
public function setExchangeRate(?BigDecimal $exchange_rate): self public function setExchangeRate(?BigDecimal $exchange_rate): self
{ {
if (!$exchange_rate instanceof \Brick\Math\BigDecimal) { if (!$exchange_rate instanceof BigDecimal) {
$this->exchange_rate = null; $this->exchange_rate = null;
} }
$tmp = $exchange_rate->toScale(self::PRICE_SCALE, RoundingMode::HALF_UP); $tmp = $exchange_rate->toScale(self::PRICE_SCALE, RoundingMode::HALF_UP);

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Entity\PriceInformations; namespace App\Entity\PriceInformations;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\TimestampTrait; use App\Entity\Base\TimestampTrait;
use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\NamedElementInterface;
@ -59,14 +60,14 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
* @var string * @var string
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $supplierpartnr = ''; protected string $supplierpartnr = '';
/** /**
* @var bool * @var bool
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $obsolete = false; protected bool $obsolete = false;
/** /**
@ -74,14 +75,14 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
*/ */
#[Assert\Url] #[Assert\Url]
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $supplier_product_url = ''; protected string $supplier_product_url = '';
/** /**
* @var Part|null * @var Part|null
*/ */
#[Assert\NotNull] #[Assert\NotNull]
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Part::class, inversedBy: 'orderdetails')] #[ORM\ManyToOne(targetEntity: Part::class, inversedBy: 'orderdetails')]
#[ORM\JoinColumn(name: 'part_id', nullable: false, onDelete: 'CASCADE')] #[ORM\JoinColumn(name: 'part_id', nullable: false, onDelete: 'CASCADE')]
protected ?Part $part = null; protected ?Part $part = null;
@ -90,7 +91,7 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
*/ */
#[Assert\NotNull(message: 'validator.orderdetail.supplier_must_not_be_null')] #[Assert\NotNull(message: 'validator.orderdetail.supplier_must_not_be_null')]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Supplier::class, inversedBy: 'orderdetails')] #[ORM\ManyToOne(targetEntity: Supplier::class, inversedBy: 'orderdetails')]
#[ORM\JoinColumn(name: 'id_supplier')] #[ORM\JoinColumn(name: 'id_supplier')]
protected ?Supplier $supplier = null; protected ?Supplier $supplier = null;
@ -194,7 +195,7 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
return $this->supplier_product_url; return $this->supplier_product_url;
} }
if (!$this->getSupplier() instanceof \App\Entity\Parts\Supplier) { if (!$this->getSupplier() instanceof Supplier) {
return ''; return '';
} }

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\PriceInformations; namespace App\Entity\PriceInformations;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\TimestampTrait; use App\Entity\Base\TimestampTrait;
use App\Entity\Contracts\TimeStampableInterface; use App\Entity\Contracts\TimeStampableInterface;
@ -73,7 +74,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
*/ */
#[Assert\Positive] #[Assert\Positive]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] #[ORM\Column(type: Types::FLOAT)]
protected float $price_related_quantity = 1.0; protected float $price_related_quantity = 1.0;
/** /**
@ -81,13 +82,13 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
*/ */
#[Assert\Positive] #[Assert\Positive]
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] #[ORM\Column(type: Types::FLOAT)]
protected float $min_discount_quantity = 1.0; protected float $min_discount_quantity = 1.0;
/** /**
* @var bool * @var bool
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $manual_input = true; protected bool $manual_input = true;
/** /**
@ -166,7 +167,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
* *
* @return BigDecimal the price as a bcmath string * @return BigDecimal the price as a bcmath string
*/ */
public function getPricePerUnit(float|string|\Brick\Math\BigDecimal $multiplier = 1.0): BigDecimal public function getPricePerUnit(float|string|BigDecimal $multiplier = 1.0): BigDecimal
{ {
$tmp = BigDecimal::of($multiplier); $tmp = BigDecimal::of($multiplier);
$tmp = $tmp->multipliedBy($this->price); $tmp = $tmp->multipliedBy($this->price);

View file

@ -22,6 +22,8 @@ declare(strict_types=1);
namespace App\Entity\ProjectSystem; namespace App\Entity\ProjectSystem;
use App\Repository\Parts\DeviceRepository;
use Doctrine\DBAL\Types\Types;
use App\Entity\Attachments\ProjectAttachment; use App\Entity\Attachments\ProjectAttachment;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Parameters\ProjectParameter; use App\Entity\Parameters\ProjectParameter;
@ -37,7 +39,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
/** /**
* Class AttachmentType. * Class AttachmentType.
*/ */
#[ORM\Entity(repositoryClass: \App\Repository\Parts\DeviceRepository::class)] #[ORM\Entity(repositoryClass: DeviceRepository::class)]
#[ORM\Table(name: 'projects')] #[ORM\Table(name: 'projects')]
class Project extends AbstractStructuralDBElement class Project extends AbstractStructuralDBElement
{ {
@ -57,7 +59,7 @@ class Project extends AbstractStructuralDBElement
#[ORM\OneToMany(targetEntity: 'ProjectBOMEntry', mappedBy: 'project', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: 'ProjectBOMEntry', mappedBy: 'project', cascade: ['persist', 'remove'], orphanRemoval: true)]
protected Collection $bom_entries; protected Collection $bom_entries;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]
protected int $order_quantity = 0; protected int $order_quantity = 0;
/** /**
@ -65,33 +67,33 @@ class Project extends AbstractStructuralDBElement
*/ */
#[Assert\Choice(['draft', 'planning', 'in_production', 'finished', 'archived'])] #[Assert\Choice(['draft', 'planning', 'in_production', 'finished', 'archived'])]
#[Groups(['extended', 'full'])] #[Groups(['extended', 'full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 64, nullable: true)] #[ORM\Column(type: Types::STRING, length: 64, nullable: true)]
protected ?string $status = null; protected ?string $status = null;
/** /**
* @var Part|null The (optional) part that represents the builds of this project in the stock * @var Part|null The (optional) part that represents the builds of this project in the stock
*/ */
#[ORM\OneToOne(targetEntity: \App\Entity\Parts\Part::class, mappedBy: 'built_project', cascade: ['persist'], orphanRemoval: true)] #[ORM\OneToOne(targetEntity: Part::class, mappedBy: 'built_project', cascade: ['persist'], orphanRemoval: true)]
protected ?Part $build_part = null; protected ?Part $build_part = null;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $order_only_missing_parts = false; protected bool $order_only_missing_parts = false;
#[Groups(['simple', 'extended', 'full'])] #[Groups(['simple', 'extended', 'full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $description = ''; protected string $description = '';
/** /**
* @var Collection<int, ProjectAttachment> * @var Collection<int, ProjectAttachment>
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\ProjectAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: ProjectAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** @var Collection<int, ProjectParameter> /** @var Collection<int, ProjectParameter>
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\ProjectParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: ProjectParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
@ -103,8 +105,8 @@ class Project extends AbstractStructuralDBElement
public function __construct() public function __construct()
{ {
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
parent::__construct(); parent::__construct();
$this->bom_entries = new ArrayCollection(); $this->bom_entries = new ArrayCollection();
$this->children = new ArrayCollection(); $this->children = new ArrayCollection();
@ -241,7 +243,7 @@ class Project extends AbstractStructuralDBElement
*/ */
public function hasBuildPart(): bool public function hasBuildPart(): bool
{ {
return $this->build_part instanceof \App\Entity\Parts\Part; return $this->build_part instanceof Part;
} }
/** /**
@ -258,7 +260,7 @@ class Project extends AbstractStructuralDBElement
public function setBuildPart(?Part $build_part): void public function setBuildPart(?Part $build_part): void
{ {
$this->build_part = $build_part; $this->build_part = $build_part;
if ($build_part instanceof \App\Entity\Parts\Part) { if ($build_part instanceof Part) {
$build_part->setBuiltProject($this); $build_part->setBuiltProject($this);
} }
} }
@ -269,7 +271,7 @@ class Project extends AbstractStructuralDBElement
//If this project has subprojects, and these have builds part, they must be included in the BOM //If this project has subprojects, and these have builds part, they must be included in the BOM
foreach ($this->getChildren() as $child) { foreach ($this->getChildren() as $child) {
/** @var $child Project */ /** @var $child Project */
if (!$child->getBuildPart() instanceof \App\Entity\Parts\Part) { if (!$child->getBuildPart() instanceof Part) {
continue; continue;
} }
//We have to search all bom entries for the build part //We have to search all bom entries for the build part

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\ProjectSystem; namespace App\Entity\ProjectSystem;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\TimestampTrait; use App\Entity\Base\TimestampTrait;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;
@ -50,26 +51,26 @@ class ProjectBOMEntry extends AbstractDBElement
* @var float * @var float
*/ */
#[Assert\Positive] #[Assert\Positive]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'quantity')] #[ORM\Column(type: Types::FLOAT, name: 'quantity')]
protected float $quantity; protected float $quantity;
/** /**
* @var string A comma separated list of the names, where this parts should be placed * @var string A comma separated list of the names, where this parts should be placed
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, name: 'mountnames')] #[ORM\Column(type: Types::TEXT, name: 'mountnames')]
protected string $mountnames = ''; protected string $mountnames = '';
/** /**
* @var string|null An optional name describing this BOM entry (useful for non-part entries) * @var string|null An optional name describing this BOM entry (useful for non-part entries)
*/ */
#[Assert\Expression('this.getPart() !== null or this.getName() !== null', message: 'validator.project.bom_entry.name_or_part_needed')] #[Assert\Expression('this.getPart() !== null or this.getName() !== null', message: 'validator.project.bom_entry.name_or_part_needed')]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] #[ORM\Column(type: Types::STRING, nullable: true)]
protected ?string $name = null; protected ?string $name = null;
/** /**
* @var string An optional comment for this BOM entry * @var string An optional comment for this BOM entry
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $comment; protected string $comment;
/** /**
@ -82,7 +83,7 @@ class ProjectBOMEntry extends AbstractDBElement
/** /**
* @var Part|null The part associated with this * @var Part|null The part associated with this
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\Parts\Part::class, inversedBy: 'project_bom_entries')] #[ORM\ManyToOne(targetEntity: Part::class, inversedBy: 'project_bom_entries')]
#[ORM\JoinColumn(name: 'id_part')] #[ORM\JoinColumn(name: 'id_part')]
protected ?Part $part = null; protected ?Part $part = null;
@ -97,7 +98,7 @@ class ProjectBOMEntry extends AbstractDBElement
* @var ?Currency The currency for the price of this non-part BOM entry * @var ?Currency The currency for the price of this non-part BOM entry
* @Selectable() * @Selectable()
*/ */
#[ORM\ManyToOne(targetEntity: \App\Entity\PriceInformations\Currency::class)] #[ORM\ManyToOne(targetEntity: Currency::class)]
#[ORM\JoinColumn] #[ORM\JoinColumn]
protected ?Currency $price_currency = null; protected ?Currency $price_currency = null;
@ -213,18 +214,18 @@ class ProjectBOMEntry extends AbstractDBElement
*/ */
public function isPartBomEntry(): bool public function isPartBomEntry(): bool
{ {
return $this->part instanceof \App\Entity\Parts\Part; return $this->part instanceof Part;
} }
#[Assert\Callback] #[Assert\Callback]
public function validate(ExecutionContextInterface $context, $payload): void public function validate(ExecutionContextInterface $context, $payload): void
{ {
//Round quantity to whole numbers, if the part is not a decimal part //Round quantity to whole numbers, if the part is not a decimal part
if ($this->part instanceof \App\Entity\Parts\Part && (!$this->part->getPartUnit() || $this->part->getPartUnit()->isInteger())) { if ($this->part instanceof Part && (!$this->part->getPartUnit() || $this->part->getPartUnit()->isInteger())) {
$this->quantity = round($this->quantity); $this->quantity = round($this->quantity);
} }
//Non-Part BOM entries are rounded //Non-Part BOM entries are rounded
if (!$this->part instanceof \App\Entity\Parts\Part) { if (!$this->part instanceof Part) {
$this->quantity = round($this->quantity); $this->quantity = round($this->quantity);
} }
@ -248,14 +249,14 @@ class ProjectBOMEntry extends AbstractDBElement
} }
//Prices are only allowed on non-part BOM entries //Prices are only allowed on non-part BOM entries
if ($this->part instanceof \App\Entity\Parts\Part && $this->price instanceof \Brick\Math\BigDecimal) { if ($this->part instanceof Part && $this->price instanceof BigDecimal) {
$context->buildViolation('project.bom_entry.price_not_allowed_on_parts') $context->buildViolation('project.bom_entry.price_not_allowed_on_parts')
->atPath('price') ->atPath('price')
->addViolation(); ->addViolation();
} }
//Check that the part is not the build representation part of this device or one of its parents //Check that the part is not the build representation part of this device or one of its parents
if ($this->part && $this->part->getBuiltProject() instanceof \App\Entity\ProjectSystem\Project) { if ($this->part && $this->part->getBuiltProject() instanceof Project) {
//Get the associated project //Get the associated project
$associated_project = $this->part->getBuiltProject(); $associated_project = $this->part->getBuiltProject();
//Check that it is not the same as the current project neither one of its parents //Check that it is not the same as the current project neither one of its parents

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use Doctrine\DBAL\Types\Types;
use App\Entity\Attachments\GroupAttachment; use App\Entity\Attachments\GroupAttachment;
use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Parameters\GroupParameter; use App\Entity\Parameters\GroupParameter;
@ -63,13 +64,13 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
* @var bool If true all users associated with this group must have enabled some kind of two-factor authentication * @var bool If true all users associated with this group must have enabled some kind of two-factor authentication
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, name: 'enforce_2fa')] #[ORM\Column(type: Types::BOOLEAN, name: 'enforce_2fa')]
protected bool $enforce2FA = false; protected bool $enforce2FA = false;
/** /**
* @var Collection<int, GroupAttachment> * @var Collection<int, GroupAttachment>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\GroupAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: GroupAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
@ -84,14 +85,14 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
/** @var Collection<int, GroupParameter> /** @var Collection<int, GroupParameter>
*/ */
#[Assert\Valid] #[Assert\Valid]
#[ORM\OneToMany(targetEntity: \App\Entity\Parameters\GroupParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: GroupParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])]
protected Collection $parameters; protected Collection $parameters;
public function __construct() public function __construct()
{ {
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
$this->parameters = new \Doctrine\Common\Collections\ArrayCollection(); $this->parameters = new ArrayCollection();
parent::__construct(); parent::__construct();
$this->permissions = new PermissionData(); $this->permissions = new PermissionData();
$this->users = new ArrayCollection(); $this->users = new ArrayCollection();
@ -122,7 +123,7 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
public function getPermissions(): PermissionData public function getPermissions(): PermissionData
{ {
if (!$this->permissions instanceof \App\Entity\UserSystem\PermissionData) { if (!$this->permissions instanceof PermissionData) {
$this->permissions = new PermissionData(); $this->permissions = new PermissionData();
} }

View file

@ -20,6 +20,7 @@
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
/** /**
@ -52,7 +53,7 @@ final class PermissionData implements \JsonSerializable
* operation => value, * operation => value,
* ] * ]
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, name: 'data')] #[ORM\Column(type: Types::JSON, name: 'data')]
protected array $data = []) protected array $data = [])
{ {
//If the passed data did not contain a schema version, we set it to the current version //If the passed data did not contain a schema version, we set it to the current version

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\TimestampTrait; use App\Entity\Base\TimestampTrait;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Jbtronics\TFAWebauthn\Model\LegacyU2FKeyInterface; use Jbtronics\TFAWebauthn\Model\LegacyU2FKeyInterface;
@ -41,39 +42,39 @@ class U2FKey implements LegacyU2FKeyInterface
* *
* @var string * @var string
**/ **/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 128)] #[ORM\Column(type: Types::STRING, length: 128)]
public string $keyHandle; public string $keyHandle;
/** /**
* @var string * @var string
**/ **/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
public string $publicKey; public string $publicKey;
/** /**
* @var string * @var string
**/ **/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
public string $certificate; public string $certificate;
/** /**
* @var int * @var int
**/ **/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
public int $counter; public int $counter;
#[ORM\Id] #[ORM\Id]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]
#[ORM\GeneratedValue] #[ORM\GeneratedValue]
protected int $id; protected int $id;
/** /**
* @var string * @var string
**/ **/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $name; protected string $name;
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\User::class, inversedBy: 'u2fKeys')] #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'u2fKeys')]
protected ?User $user = null; protected ?User $user = null;
public function getKeyHandle(): string public function getKeyHandle(): string

View file

@ -22,6 +22,9 @@ declare(strict_types=1);
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use App\Repository\UserRepository;
use App\EntityListeners\TreeCacheInvalidationListener;
use Doctrine\DBAL\Types\Types;
use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Attachments\UserAttachment; use App\Entity\Attachments\UserAttachment;
use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractNamedDBElement;
@ -56,8 +59,8 @@ use Jbtronics\TFAWebauthn\Model\TwoFactorInterface as WebauthnTwoFactorInterface
* Also, this entity is able to save some information about the user, like the names, email-address and other info. * Also, this entity is able to save some information about the user, like the names, email-address and other info.
*/ */
#[UniqueEntity('name', message: 'validator.user.username_already_used')] #[UniqueEntity('name', message: 'validator.user.username_already_used')]
#[ORM\Entity(repositoryClass: \App\Repository\UserRepository::class)] #[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\EntityListeners([\App\EntityListeners\TreeCacheInvalidationListener::class])] #[ORM\EntityListeners([TreeCacheInvalidationListener::class])]
#[ORM\Table('`users`')] #[ORM\Table('`users`')]
#[ORM\Index(name: 'user_idx_username', columns: ['name'])] #[ORM\Index(name: 'user_idx_username', columns: ['name'])]
class User extends AttachmentContainingDBElement implements UserInterface, HasPermissionsInterface, TwoFactorInterface, class User extends AttachmentContainingDBElement implements UserInterface, HasPermissionsInterface, TwoFactorInterface,
@ -74,7 +77,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
* @var bool Determines if the user is disabled (user can not log in) * @var bool Determines if the user is disabled (user can not log in)
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $disabled = false; protected bool $disabled = false;
/** /**
@ -82,42 +85,42 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
* @ValidTheme() * @ValidTheme()
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'config_theme', nullable: true)] #[ORM\Column(type: Types::STRING, name: 'config_theme', nullable: true)]
protected ?string $theme = null; protected ?string $theme = null;
/** /**
* @var string|null the hash of a token the user must provide when he wants to reset his password * @var string|null the hash of a token the user must provide when he wants to reset his password
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] #[ORM\Column(type: Types::STRING, nullable: true)]
protected ?string $pw_reset_token = null; protected ?string $pw_reset_token = null;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, name: 'config_instock_comment_a')] #[ORM\Column(type: Types::TEXT, name: 'config_instock_comment_a')]
protected string $instock_comment_a = ''; protected string $instock_comment_a = '';
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, name: 'config_instock_comment_w')] #[ORM\Column(type: Types::TEXT, name: 'config_instock_comment_w')]
protected string $instock_comment_w = ''; protected string $instock_comment_w = '';
/** /**
* @var string A self-description of the user * @var string A self-description of the user
*/ */
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] #[ORM\Column(type: Types::TEXT)]
protected string $aboutMe = ''; protected string $aboutMe = '';
/** @var int The version of the trusted device cookie. Used to invalidate all trusted device cookies at once. /** @var int The version of the trusted device cookie. Used to invalidate all trusted device cookies at once.
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]
protected int $trustedDeviceCookieVersion = 0; protected int $trustedDeviceCookieVersion = 0;
/** /**
* @var string[]|null A list of backup codes that can be used, if the user has no access to its Google Authenticator device * @var string[]|null A list of backup codes that can be used, if the user has no access to its Google Authenticator device
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] #[ORM\Column(type: Types::JSON)]
protected ?array $backupCodes = []; protected ?array $backupCodes = [];
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue] #[ORM\GeneratedValue]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]
protected ?int $id = null; protected ?int $id = null;
/** /**
@ -133,7 +136,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
/** /**
* @var string|null The secret used for Google authenticator * @var string|null The secret used for Google authenticator
*/ */
#[ORM\Column(name: 'google_authenticator_secret', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] #[ORM\Column(name: 'google_authenticator_secret', type: Types::STRING, nullable: true)]
protected ?string $googleAuthenticatorSecret = null; protected ?string $googleAuthenticatorSecret = null;
/** /**
@ -141,7 +144,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
*/ */
#[Assert\Timezone] #[Assert\Timezone]
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'config_timezone', nullable: true)] #[ORM\Column(type: Types::STRING, name: 'config_timezone', nullable: true)]
protected ?string $timezone = ''; protected ?string $timezone = '';
/** /**
@ -149,7 +152,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
*/ */
#[Assert\Language] #[Assert\Language]
#[Groups(['full', 'import'])] #[Groups(['full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'config_language', nullable: true)] #[ORM\Column(type: Types::STRING, name: 'config_language', nullable: true)]
protected ?string $language = ''; protected ?string $language = '';
/** /**
@ -157,82 +160,82 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
*/ */
#[Assert\Email] #[Assert\Email]
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] #[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
protected ?string $email = ''; protected ?string $email = '';
/** /**
* @var bool True if the user wants to show his email address on his (public) profile * @var bool True if the user wants to show his email address on his (public) profile
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] #[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
protected bool $show_email_on_profile = false; protected bool $show_email_on_profile = false;
/** /**
* @var string|null The department the user is working * @var string|null The department the user is working
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] #[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
protected ?string $department = ''; protected ?string $department = '';
/** /**
* @var string|null The last name of the User * @var string|null The last name of the User
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] #[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
protected ?string $last_name = ''; protected ?string $last_name = '';
/** /**
* @var string|null The first name of the User * @var string|null The first name of the User
*/ */
#[Groups(['simple', 'extended', 'full', 'import'])] #[Groups(['simple', 'extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] #[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
protected ?string $first_name = ''; protected ?string $first_name = '';
/** /**
* @var bool True if the user needs to change password after log in * @var bool True if the user needs to change password after log in
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $need_pw_change = true; protected bool $need_pw_change = true;
/** /**
* @var string|null The hashed password * @var string|null The hashed password
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] #[ORM\Column(type: Types::STRING, nullable: true)]
protected ?string $password = null; protected ?string $password = null;
#[Assert\NotBlank] #[Assert\NotBlank]
#[Assert\Regex('/^[\w\.\+\-\$]+$/', message: 'user.invalid_username')] #[Assert\Regex('/^[\w\.\+\-\$]+$/', message: 'user.invalid_username')]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 180, unique: true)] #[ORM\Column(type: Types::STRING, length: 180, unique: true)]
protected string $name = ''; protected string $name = '';
/** /**
* @var array|null * @var array|null
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] #[ORM\Column(type: Types::JSON)]
protected ?array $settings = []; protected ?array $settings = [];
/** /**
* @var Collection<int, UserAttachment> * @var Collection<int, UserAttachment>
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\Attachments\UserAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: UserAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])] #[ORM\OrderBy(['name' => 'ASC'])]
protected Collection $attachments; protected Collection $attachments;
/** @var \DateTimeInterface|null The time when the backup codes were generated /** @var \DateTimeInterface|null The time when the backup codes were generated
*/ */
#[Groups(['full'])] #[Groups(['full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
protected ?\DateTimeInterface $backupCodesGenerationDate = null; protected ?\DateTimeInterface $backupCodesGenerationDate = null;
/** @var Collection<int, LegacyU2FKeyInterface> /** @var Collection<int, LegacyU2FKeyInterface>
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\UserSystem\U2FKey::class, mappedBy: 'user', cascade: ['REMOVE'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: U2FKey::class, mappedBy: 'user', cascade: ['REMOVE'], orphanRemoval: true)]
protected Collection $u2fKeys; protected Collection $u2fKeys;
/** /**
* @var Collection<int, WebauthnKey> * @var Collection<int, WebauthnKey>
*/ */
#[ORM\OneToMany(targetEntity: \App\Entity\UserSystem\WebauthnKey::class, mappedBy: 'user', cascade: ['REMOVE'], orphanRemoval: true)] #[ORM\OneToMany(targetEntity: WebauthnKey::class, mappedBy: 'user', cascade: ['REMOVE'], orphanRemoval: true)]
protected Collection $webauthn_keys; protected Collection $webauthn_keys;
/** /**
@ -243,7 +246,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
* @Selectable() * @Selectable()
*/ */
#[Groups(['extended', 'full', 'import'])] #[Groups(['extended', 'full', 'import'])]
#[ORM\ManyToOne(targetEntity: \App\Entity\PriceInformations\Currency::class)] #[ORM\ManyToOne(targetEntity: Currency::class)]
#[ORM\JoinColumn(name: 'currency_id')] #[ORM\JoinColumn(name: 'currency_id')]
protected ?Currency $currency = null; protected ?Currency $currency = null;
@ -258,19 +261,19 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
/** /**
* @var \DateTimeInterface|null the time until the password reset token is valid * @var \DateTimeInterface|null the time until the password reset token is valid
*/ */
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
protected ?\DateTimeInterface $pw_reset_expires = null; protected ?\DateTimeInterface $pw_reset_expires = null;
/** /**
* @var bool True if the user was created by a SAML provider (and therefore cannot change its password) * @var bool True if the user was created by a SAML provider (and therefore cannot change its password)
*/ */
#[Groups(['extended', 'full'])] #[Groups(['extended', 'full'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] #[ORM\Column(type: Types::BOOLEAN)]
protected bool $saml_user = false; protected bool $saml_user = false;
public function __construct() public function __construct()
{ {
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); $this->attachments = new ArrayCollection();
parent::__construct(); parent::__construct();
$this->permissions = new PermissionData(); $this->permissions = new PermissionData();
$this->u2fKeys = new ArrayCollection(); $this->u2fKeys = new ArrayCollection();
@ -419,7 +422,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
public function getPermissions(): PermissionData public function getPermissions(): PermissionData
{ {
if (!$this->permissions instanceof \App\Entity\UserSystem\PermissionData) { if (!$this->permissions instanceof PermissionData) {
$this->permissions = new PermissionData(); $this->permissions = new PermissionData();
} }

View file

@ -20,6 +20,7 @@
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use Doctrine\DBAL\Types\Types;
use App\Entity\Base\TimestampTrait; use App\Entity\Base\TimestampTrait;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Webauthn\PublicKeyCredentialSource as BasePublicKeyCredentialSource; use Webauthn\PublicKeyCredentialSource as BasePublicKeyCredentialSource;
@ -32,14 +33,14 @@ class WebauthnKey extends BasePublicKeyCredentialSource
use TimestampTrait; use TimestampTrait;
#[ORM\Id] #[ORM\Id]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] #[ORM\Column(type: Types::INTEGER)]
#[ORM\GeneratedValue] #[ORM\GeneratedValue]
protected int $id; protected int $id;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] #[ORM\Column(type: Types::STRING)]
protected string $name; protected string $name;
#[ORM\ManyToOne(targetEntity: \App\Entity\UserSystem\User::class, inversedBy: 'webauthn_keys')] #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'webauthn_keys')]
protected ?User $user = null; protected ?User $user = null;
public function getName(): string public function getName(): string

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\EntityListeners; namespace App\EntityListeners;
use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
use App\Services\Attachments\AttachmentManager; use App\Services\Attachments\AttachmentManager;
use App\Services\Attachments\AttachmentPathResolver; use App\Services\Attachments\AttachmentPathResolver;
@ -80,7 +81,7 @@ class AttachmentDeleteListener
//Ensure that the attachment that will be deleted, is not used as preview picture anymore... //Ensure that the attachment that will be deleted, is not used as preview picture anymore...
$attachment_holder = $attachment->getElement(); $attachment_holder = $attachment->getElement();
if (!$attachment_holder instanceof \App\Entity\Attachments\AttachmentContainingDBElement) { if (!$attachment_holder instanceof AttachmentContainingDBElement) {
return; return;
} }

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