mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-07-03 06:54:34 +02:00
Merge remote-tracking branch 'origin/l10n_master' into l10n_master
This commit is contained in:
commit
8343fffc1c
140 changed files with 3217 additions and 4762 deletions
|
@ -110,9 +110,12 @@ $(document).on("ajaxUI:start ajaxUI:reload", function() {
|
|||
});
|
||||
|
||||
//Register bootstrap select picker
|
||||
$(document).on("ajaxUI:reload", function () {
|
||||
$(document).on("ajaxUI:reload ajaxUI:start", function () {
|
||||
//@ts-ignore
|
||||
$(".selectpicker").selectpicker();
|
||||
$(".selectpicker").selectpicker({
|
||||
dropdownAlignRight: 'auto',
|
||||
container: '#content',
|
||||
});
|
||||
});
|
||||
|
||||
//Use bootstrap tooltips for the most tooltips
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
"phpstan/phpstan": "^0.12.8",
|
||||
"phpstan/phpstan-doctrine": "^0.12.9",
|
||||
"phpstan/phpstan-symfony": "^0.12.4",
|
||||
"psalm/plugin-symfony": "^1.1",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"symfony/debug-pack": "*",
|
||||
"symfony/maker-bundle": "^1.13",
|
||||
|
|
635
composer.lock
generated
635
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -2,26 +2,14 @@ doctrine:
|
|||
orm:
|
||||
auto_generate_proxy_classes: false
|
||||
metadata_cache_driver:
|
||||
type: service
|
||||
id: doctrine.system_cache_provider
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
query_cache_driver:
|
||||
type: service
|
||||
id: doctrine.system_cache_provider
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
result_cache_driver:
|
||||
type: service
|
||||
id: doctrine.result_cache_provider
|
||||
|
||||
services:
|
||||
doctrine.result_cache_provider:
|
||||
class: Symfony\Component\Cache\DoctrineProvider
|
||||
public: false
|
||||
arguments:
|
||||
- '@doctrine.result_cache_pool'
|
||||
doctrine.system_cache_provider:
|
||||
class: Symfony\Component\Cache\DoctrineProvider
|
||||
public: false
|
||||
arguments:
|
||||
- '@doctrine.system_cache_pool'
|
||||
type: pool
|
||||
pool: doctrine.result_cache_pool
|
||||
|
||||
framework:
|
||||
cache:
|
||||
|
@ -29,4 +17,4 @@ framework:
|
|||
doctrine.result_cache_pool:
|
||||
adapter: cache.app
|
||||
doctrine.system_cache_pool:
|
||||
adapter: cache.system
|
||||
adapter: cache.system
|
|
@ -17,4 +17,4 @@ framework:
|
|||
doctrine.result_cache_pool:
|
||||
adapter: cache.app
|
||||
doctrine.system_cache_pool:
|
||||
adapter: cache.system
|
||||
adapter: cache.system
|
|
@ -4,4 +4,4 @@ webpack_encore:
|
|||
cache: true
|
||||
|
||||
# Preload in production
|
||||
preload: false
|
||||
preload: true
|
|
@ -8,7 +8,7 @@ webpack_encore:
|
|||
# crossorigin: 'anonymous'
|
||||
|
||||
# preload all rendered script and link tags automatically via the http2 Link header
|
||||
#preload: false
|
||||
preload: false
|
||||
|
||||
# Throw an exception if the entrypoints.json file is missing or an entry is missing from the data
|
||||
# strict_mode: false
|
||||
|
|
|
@ -187,6 +187,10 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
|||
label: "perm.revert_elements"
|
||||
bit: 10
|
||||
alsoSet: ["read", "edit", "create", "delete", "show_history"]
|
||||
show_private:
|
||||
label: "perm.attachment_show_private"
|
||||
bit: 12
|
||||
alsoSet: ["read"]
|
||||
|
||||
parts_order:
|
||||
<<: *PART_ATTRIBUTE
|
||||
|
|
|
@ -33,6 +33,8 @@ services:
|
|||
bind:
|
||||
bool $demo_mode: '%demo_mode%'
|
||||
bool $gpdr_compliance : '%gpdr_compliance%'
|
||||
bool $kernel_debug: '%kernel.debug%'
|
||||
string $kernel_cache_dir: '%kernel.cache_dir%'
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
|
|
59
psalm.xml
59
psalm.xml
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="5"
|
||||
totallyTyped="false"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
|
@ -7,49 +8,49 @@
|
|||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<directory name="src"/>
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
<directory name="vendor"/>
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<LessSpecificReturnType errorLevel="info" />
|
||||
<LessSpecificReturnType errorLevel="info"/>
|
||||
|
||||
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
|
||||
|
||||
<DeprecatedMethod errorLevel="info" />
|
||||
<DeprecatedProperty errorLevel="info" />
|
||||
<DeprecatedClass errorLevel="info" />
|
||||
<DeprecatedConstant errorLevel="info" />
|
||||
<DeprecatedFunction errorLevel="info" />
|
||||
<DeprecatedInterface errorLevel="info" />
|
||||
<DeprecatedTrait errorLevel="info" />
|
||||
<DeprecatedMethod errorLevel="info"/>
|
||||
<DeprecatedProperty errorLevel="info"/>
|
||||
<DeprecatedClass errorLevel="info"/>
|
||||
<DeprecatedConstant errorLevel="info"/>
|
||||
<DeprecatedFunction errorLevel="info"/>
|
||||
<DeprecatedInterface errorLevel="info"/>
|
||||
<DeprecatedTrait errorLevel="info"/>
|
||||
|
||||
<InternalMethod errorLevel="info" />
|
||||
<InternalProperty errorLevel="info" />
|
||||
<InternalClass errorLevel="info" />
|
||||
<InternalMethod errorLevel="info"/>
|
||||
<InternalProperty errorLevel="info"/>
|
||||
<InternalClass errorLevel="info"/>
|
||||
|
||||
<MissingClosureReturnType errorLevel="info" />
|
||||
<MissingReturnType errorLevel="info" />
|
||||
<MissingPropertyType errorLevel="info" />
|
||||
<InvalidDocblock errorLevel="info" />
|
||||
<MisplacedRequiredParam errorLevel="info" />
|
||||
<MissingClosureReturnType errorLevel="info"/>
|
||||
<MissingReturnType errorLevel="info"/>
|
||||
<MissingPropertyType errorLevel="info"/>
|
||||
<InvalidDocblock errorLevel="info"/>
|
||||
<MisplacedRequiredParam errorLevel="info"/>
|
||||
|
||||
<PropertyNotSetInConstructor errorLevel="info" />
|
||||
<MissingConstructor errorLevel="info" />
|
||||
<MissingClosureParamType errorLevel="info" />
|
||||
<MissingParamType errorLevel="info" />
|
||||
<PropertyNotSetInConstructor errorLevel="info"/>
|
||||
<MissingConstructor errorLevel="info"/>
|
||||
<MissingClosureParamType errorLevel="info"/>
|
||||
<MissingParamType errorLevel="info"/>
|
||||
|
||||
<RedundantCondition errorLevel="info" />
|
||||
<RedundantCondition errorLevel="info"/>
|
||||
|
||||
<DocblockTypeContradiction errorLevel="info" />
|
||||
<RedundantConditionGivenDocblockType errorLevel="info" />
|
||||
<DocblockTypeContradiction errorLevel="info"/>
|
||||
<RedundantConditionGivenDocblockType errorLevel="info"/>
|
||||
|
||||
<UnresolvableInclude errorLevel="info" />
|
||||
<UnresolvableInclude errorLevel="info"/>
|
||||
|
||||
<RawObjectIteration errorLevel="info" />
|
||||
<RawObjectIteration errorLevel="info"/>
|
||||
|
||||
<InvalidStringClass errorLevel="info" />
|
||||
<InvalidStringClass errorLevel="info"/>
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
<plugins><pluginClass class="Psalm\SymfonyPsalmPlugin\Plugin"/></plugins></psalm>
|
||||
|
|
|
@ -197,7 +197,7 @@ abstract class BaseAdminController extends AbstractController
|
|||
//We can not use dynamic form events here, because the parent entity list is build from database!
|
||||
$form = $this->createForm($this->form_class, $entity, [
|
||||
'attachment_class' => $this->attachment_class,
|
||||
'parameter_class' => $this->parameter_class
|
||||
'parameter_class' => $this->parameter_class,
|
||||
]);
|
||||
} elseif ($form->isSubmitted() && ! $form->isValid()) {
|
||||
$this->addFlash('error', 'entity.edit_flash.invalid');
|
||||
|
|
|
@ -72,7 +72,7 @@ class FootprintController extends BaseAdminController
|
|||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function delete(Request $request, Footprint $entity, StructuralElementRecursionHelper $recursionHelper)
|
||||
public function delete(Request $request, Footprint $entity, StructuralElementRecursionHelper $recursionHelper): \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
{
|
||||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class FootprintController extends BaseAdminController
|
|||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function edit(Footprint $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null)
|
||||
public function edit(Footprint $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
return $this->_edit($entity, $request, $em, $timestamp);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ class AttachmentFileController extends AbstractController
|
|||
{
|
||||
$this->denyAccessUnlessGranted('read', $attachment);
|
||||
|
||||
if ($attachment->isSecure()) {
|
||||
$this->denyAccessUnlessGranted('show_private', $attachment);
|
||||
}
|
||||
|
||||
if ($attachment->isExternal()) {
|
||||
throw new RuntimeException('You can not download external attachments!');
|
||||
}
|
||||
|
@ -97,6 +101,10 @@ class AttachmentFileController extends AbstractController
|
|||
{
|
||||
$this->denyAccessUnlessGranted('read', $attachment);
|
||||
|
||||
if ($attachment->isSecure()) {
|
||||
$this->denyAccessUnlessGranted('show_private', $attachment);
|
||||
}
|
||||
|
||||
if ($attachment->isExternal()) {
|
||||
throw new RuntimeException('You can not download external attachments!');
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ use App\Services\LogSystem\EventUndoHelper;
|
|||
use App\Services\LogSystem\TimeTravel;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Omines\DataTablesBundle\DataTableFactory;
|
||||
use phpDocumentor\Reflection\Element;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -100,7 +99,7 @@ class LogController extends AbstractController
|
|||
/**
|
||||
* @Route("/undo", name="log_undo", methods={"POST"})
|
||||
*/
|
||||
public function undoRevertLog(Request $request, EventUndoHelper $eventUndoHelper)
|
||||
public function undoRevertLog(Request $request, EventUndoHelper $eventUndoHelper): \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
{
|
||||
$mode = EventUndoHelper::MODE_UNDO;
|
||||
$id = $request->request->get('undo');
|
||||
|
|
|
@ -44,7 +44,12 @@ namespace App\Controller;
|
|||
|
||||
use App\DataTables\LogDataTable;
|
||||
use App\Entity\Parts\Category;
|
||||
use App\Entity\Parts\Footprint;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Entity\Parts\PartLot;
|
||||
use App\Entity\Parts\Storelocation;
|
||||
use App\Entity\Parts\Supplier;
|
||||
use App\Entity\PriceInformations\Orderdetail;
|
||||
use App\Exceptions\AttachmentDownloadException;
|
||||
use App\Form\Part\PartBaseType;
|
||||
use App\Services\Attachments\AttachmentManager;
|
||||
|
@ -57,6 +62,7 @@ use App\Services\Parameters\ParameterExtractor;
|
|||
use App\Services\PricedetailHelper;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Omines\DataTablesBundle\DataTableFactory;
|
||||
use Proxies\__CG__\App\Entity\Parts\Manufacturer;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
@ -135,7 +141,7 @@ class PartController extends AbstractController
|
|||
'pictures' => $this->partPreviewGenerator->getPreviewAttachments($part),
|
||||
'timeTravel' => $timeTravel_timestamp,
|
||||
'description_params' => $parameterExtractor->extractParameters($part->getDescription()),
|
||||
'comment_params' => $parameterExtractor->extractParameters($part->getComment())
|
||||
'comment_params' => $parameterExtractor->extractParameters($part->getComment()),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -235,13 +241,42 @@ class PartController extends AbstractController
|
|||
|
||||
$this->denyAccessUnlessGranted('create', $new_part);
|
||||
|
||||
$cid = $request->get('cid', 1);
|
||||
|
||||
$category = $em->find(Category::class, $cid);
|
||||
$cid = $request->get('category', null);
|
||||
$category = $cid ? $em->find(Category::class, $cid) : null;
|
||||
if (null !== $category && null === $new_part->getCategory()) {
|
||||
$new_part->setCategory($category);
|
||||
}
|
||||
|
||||
$fid = $request->get('footprint', null);
|
||||
$footprint = $fid ? $em->find(Footprint::class, $cid) : null;
|
||||
if (null !== $footprint && null === $new_part->getFootprint()) {
|
||||
$new_part->setFootprint($footprint);
|
||||
}
|
||||
|
||||
$mid = $request->get('manufacturer', null);
|
||||
$manufacturer = $mid ? $em->find(Manufacturer::class, $mid) : null;
|
||||
if (null !== $manufacturer && null === $new_part->getManufacturer()) {
|
||||
$new_part->setManufacturer($manufacturer);
|
||||
}
|
||||
|
||||
$store_id = $request->get('storelocation', null);
|
||||
$storelocation = $store_id ? $em->find(Storelocation::class, $store_id): null;
|
||||
if (null !== $storelocation && $new_part->getPartLots()->isEmpty()) {
|
||||
$partLot = new PartLot();
|
||||
$partLot->setStorageLocation($storelocation);
|
||||
$partLot->setInstockUnknown(true);
|
||||
$new_part->addPartLot($partLot);
|
||||
}
|
||||
|
||||
$supplier_id = $request->get('supplier', null);
|
||||
$supplier = $supplier_id ? $em->find(Supplier::class, $supplier_id): null;
|
||||
if (null !== $supplier && $new_part->getOrderdetails()->isEmpty()) {
|
||||
$orderdetail = new Orderdetail();
|
||||
$orderdetail->setSupplier($supplier);
|
||||
$new_part->addOrderdetail($orderdetail);
|
||||
}
|
||||
|
||||
|
||||
$form = $this->createForm(PartBaseType::class, $new_part);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
|
|
@ -62,9 +62,11 @@ class TypeaheadController extends AbstractController
|
|||
/**
|
||||
* @Route("/builtInResources/search/{query}", name="typeahead_builtInRessources", requirements={"query"= ".+"})
|
||||
*
|
||||
* @param string $query
|
||||
* @param BuiltinAttachmentsFinder $finder
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function builtInResources(Request $request, string $query, BuiltinAttachmentsFinder $finder)
|
||||
public function builtInResources(string $query, BuiltinAttachmentsFinder $finder)
|
||||
{
|
||||
$array = $finder->find($query);
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ declare(strict_types=1);
|
|||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Attachments\UserAttachment;
|
||||
use App\Entity\Parameters\PartParameter;
|
||||
use App\Entity\UserSystem\User;
|
||||
use App\Form\Permissions\PermissionsType;
|
||||
use App\Form\UserAdminForm;
|
||||
|
@ -69,7 +68,7 @@ class UserController extends AdminPages\BaseAdminController
|
|||
protected $route_base = 'user';
|
||||
protected $attachment_class = UserAttachment::class;
|
||||
//Just define a value here to prevent error. It is not used.
|
||||
protected $parameter_class = "not used";
|
||||
protected $parameter_class = 'not used';
|
||||
|
||||
/**
|
||||
* @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="user_edit")
|
||||
|
|
|
@ -43,7 +43,7 @@ declare(strict_types=1);
|
|||
namespace App\DataFixtures;
|
||||
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class AppFixtures extends Fixture
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ use App\Entity\Parts\MeasurementUnit;
|
|||
use App\Entity\Parts\Storelocation;
|
||||
use App\Entity\Parts\Supplier;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace App\DataFixtures;
|
|||
|
||||
use App\Entity\UserSystem\Group;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class GroupFixtures extends Fixture
|
||||
{
|
||||
|
|
|
@ -89,16 +89,16 @@ class PartFixtures extends Fixture
|
|||
|
||||
$orderdetail = new Orderdetail();
|
||||
$orderdetail->setSupplier($manager->find(Supplier::class, 1));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice("10.0"));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice("15.0"));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice('10.0'));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice('15.0'));
|
||||
$part->addOrderdetail($orderdetail);
|
||||
|
||||
$orderdetail = new Orderdetail();
|
||||
$orderdetail->setSupplierpartnr('BC 547');
|
||||
$orderdetail->setObsolete(true);
|
||||
$orderdetail->setSupplier($manager->find(Supplier::class, 1));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice("10.0"));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice("15.1"));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(1.0)->setPrice('10.0'));
|
||||
$orderdetail->addPricedetail((new Pricedetail())->setPriceRelatedQuantity(10.0)->setPrice('15.1'));
|
||||
$part->addOrderdetail($orderdetail);
|
||||
|
||||
$attachment = new PartAttachment();
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace App\DataFixtures;
|
|||
|
||||
use App\Entity\UserSystem\User;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ class FetchJoinORMAdapter extends ORMAdapter
|
|||
}
|
||||
}
|
||||
|
||||
public function getCount(QueryBuilder $queryBuilder, $identifier)
|
||||
public function getCount(QueryBuilder $queryBuilder, string $identifier)
|
||||
{
|
||||
$paginator = new Paginator($queryBuilder);
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ class ORMAdapter extends AbstractAdapter
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getCount(QueryBuilder $queryBuilder, $identifier)
|
||||
protected function getCount(QueryBuilder $queryBuilder, string $identifier)
|
||||
{
|
||||
$qb = clone $queryBuilder;
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ namespace App\DataTables\Column;
|
|||
|
||||
use App\Entity\Attachments\Attachment;
|
||||
use App\Entity\Base\AbstractDBElement;
|
||||
use App\Entity\Base\AbstractNamedDBElement;
|
||||
use App\Entity\Contracts\NamedElementInterface;
|
||||
use App\Entity\LogSystem\AbstractLogEntry;
|
||||
use App\Entity\Parameters\AbstractParameter;
|
||||
|
@ -99,7 +98,7 @@ class LogEntryTargetColumn extends AbstractColumn
|
|||
$tmp = '';
|
||||
|
||||
//The element is existing
|
||||
if ($target instanceof NamedElementInterface && !empty($target->getName())) {
|
||||
if ($target instanceof NamedElementInterface && ! empty($target->getName())) {
|
||||
try {
|
||||
$tmp = sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
|
@ -126,15 +125,15 @@ class LogEntryTargetColumn extends AbstractColumn
|
|||
|
||||
//Add a hint to the associated element if possible
|
||||
if (null !== $target && $this->options['show_associated']) {
|
||||
if ($target instanceof Attachment && $target->getElement() !== null) {
|
||||
if ($target instanceof Attachment && null !== $target->getElement()) {
|
||||
$on = $target->getElement();
|
||||
} elseif ($target instanceof AbstractParameter && $target->getElement() !== null) {
|
||||
} elseif ($target instanceof AbstractParameter && null !== $target->getElement()) {
|
||||
$on = $target->getElement();
|
||||
} elseif ($target instanceof PartLot && $target->getPart() !== null) {
|
||||
} elseif ($target instanceof PartLot && null !== $target->getPart()) {
|
||||
$on = $target->getPart();
|
||||
} elseif ($target instanceof Orderdetail && $target->getPart() !== null) {
|
||||
} elseif ($target instanceof Orderdetail && null !== $target->getPart()) {
|
||||
$on = $target->getPart();
|
||||
} elseif ($target instanceof Pricedetail && $target->getOrderdetail() !== null && $target->getOrderdetail()->getPart() !== null) {
|
||||
} elseif ($target instanceof Pricedetail && null !== $target->getOrderdetail() && null !== $target->getOrderdetail()->getPart()) {
|
||||
$on = $target->getOrderdetail()->getPart();
|
||||
}
|
||||
|
||||
|
@ -146,7 +145,7 @@ class LogEntryTargetColumn extends AbstractColumn
|
|||
$this->elementTypeNameGenerator->getTypeNameCombination($on, true)
|
||||
);
|
||||
} catch (EntityNotSupportedException $exception) {
|
||||
$tmp .= ' (' . $this->elementTypeNameGenerator->getTypeNameCombination($target, true) .')';
|
||||
$tmp .= ' ('.$this->elementTypeNameGenerator->getTypeNameCombination($target, true).')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@ class RevertLogColumn extends AbstractColumn
|
|||
|
||||
public function render($value, $context)
|
||||
{
|
||||
$revertable = true;
|
||||
if (
|
||||
$context instanceof CollectionElementDeleted
|
||||
|| ($context instanceof ElementDeletedLogEntry && $context->hasOldDataInformations())
|
||||
|
|
|
@ -212,7 +212,7 @@ class LogDataTable implements DataTableTypeInterface
|
|||
|
||||
$dataTable->add('target', LogEntryTargetColumn::class, [
|
||||
'label' => $this->translator->trans('log.target'),
|
||||
'show_associated' => $options['mode'] !== 'element_history',
|
||||
'show_associated' => 'element_history' !== $options['mode'],
|
||||
]);
|
||||
|
||||
$dataTable->add('extra', LogEntryExtraColumn::class, [
|
||||
|
|
|
@ -329,8 +329,6 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
|
||||
private function buildCriteria(QueryBuilder $builder, array $options): void
|
||||
{
|
||||
$em = $builder->getEntityManager();
|
||||
|
||||
if (isset($options['category'])) {
|
||||
$category = $options['category'];
|
||||
$list = $this->treeBuilder->typeToNodesList(Category::class, $category);
|
||||
|
|
|
@ -40,6 +40,7 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="AttachmentType", mappedBy="parent", cascade={"persist"})
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -56,13 +57,14 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
*/
|
||||
protected $filetype_filter = '';
|
||||
/**
|
||||
* @var Collection|AttachmentTypeAttachment[]
|
||||
* @var Collection<int, AttachmentTypeAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\AttachmentTypeAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
/** @var AttachmentTypeParameter[]
|
||||
/** @var Collection<int, AttachmentTypeParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\AttachmentTypeParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
@ -70,7 +72,7 @@ class AttachmentType extends AbstractStructuralDBElement
|
|||
protected $parameters;
|
||||
|
||||
/**
|
||||
* @var Collection|Attachment[]
|
||||
* @var Collection<int, Attachment>
|
||||
* @ORM\OneToMany(targetEntity="Attachment", mappedBy="attachment_type")
|
||||
*/
|
||||
protected $attachments_with_type;
|
||||
|
|
|
@ -43,11 +43,13 @@ declare(strict_types=1);
|
|||
namespace App\Entity\Attachments;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to an attachmentType element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class AttachmentTypeAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\Parts\Category;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a category element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class CategoryAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\PriceInformations\Currency;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a currency element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class CurrencyAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\Devices\Device;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a device element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class DeviceAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\Parts\Footprint;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a footprint element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class FootprintAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\UserSystem\Group;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a Group element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class GroupAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\Parts\Manufacturer;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a manufacturer element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class ManufacturerAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -45,11 +45,13 @@ namespace App\Entity\Attachments;
|
|||
use App\Entity\Parts\Manufacturer;
|
||||
use App\Entity\Parts\MeasurementUnit;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a measurement unit element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class MeasurementUnitAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\Parts\Part;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a part element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class PartAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\Parts\Storelocation;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a measurement unit element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class StorelocationAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\Parts\Supplier;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a supplier element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class SupplierAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -44,11 +44,13 @@ namespace App\Entity\Attachments;
|
|||
|
||||
use App\Entity\UserSystem\User;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* A attachment attached to a user element.
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @UniqueEntity({"name", "attachment_type", "element"})
|
||||
*/
|
||||
class UserAttachment extends Attachment
|
||||
{
|
||||
|
|
|
@ -254,6 +254,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
* Get all sub elements of this element.
|
||||
*
|
||||
* @return Collection<static>|iterable all subelements as an array of objects (sorted by their full path)
|
||||
* @psalm-return Collection<int, static>
|
||||
*/
|
||||
public function getSubelements(): iterable
|
||||
{
|
||||
|
@ -262,6 +263,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
|
|||
|
||||
/**
|
||||
* @return Collection<static>|iterable
|
||||
* @psalm-return Collection<int, static>
|
||||
*/
|
||||
public function getChildren(): iterable
|
||||
{
|
||||
|
|
|
@ -67,6 +67,7 @@ class Device extends AbstractPartsContainingDBElement
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Device", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -93,12 +94,13 @@ class Device extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
protected $order_only_missing_parts = false;
|
||||
/**
|
||||
* @var Collection|DeviceAttachment[]
|
||||
* @var Collection<int, DeviceAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\DeviceAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
/** @var DeviceParameter[]
|
||||
/** @var Collection<int, DeviceParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\DeviceParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
*/
|
||||
|
|
|
@ -84,11 +84,7 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf
|
|||
return array_keys($this->getOldData());
|
||||
}
|
||||
|
||||
if (isset($this->extra['f'])) {
|
||||
return $this->extra['f'];
|
||||
}
|
||||
|
||||
return [];
|
||||
return $this->extra['f'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,7 +28,6 @@ use App\Entity\Base\AbstractNamedDBElement;
|
|||
use Doctrine\ORM\Mapping as ORM;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
|
@ -121,16 +120,6 @@ abstract class AbstractParameter extends AbstractNamedDBElement
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the specification (e.g. "Collector-Base Voltage").
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element this parameter belongs to.
|
||||
*
|
||||
|
@ -213,7 +202,8 @@ abstract class AbstractParameter extends AbstractNamedDBElement
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the group this parameter is associated to (e.g. Technical Parameters)
|
||||
* Returns the name of the group this parameter is associated to (e.g. Technical Parameters).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGroup(): string
|
||||
|
@ -223,12 +213,13 @@ abstract class AbstractParameter extends AbstractNamedDBElement
|
|||
|
||||
/**
|
||||
* Sets the name of the group this parameter is associated to.
|
||||
* @param string $group
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroup(string $group): self
|
||||
{
|
||||
$this->group = $group;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,17 +31,19 @@ trait ParametersTrait
|
|||
/**
|
||||
* Mapping done in subclasses.
|
||||
*
|
||||
* @var AbstractParameter[]|Collection
|
||||
* @var Collection<int, AbstractParameter>
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $parameters;
|
||||
|
||||
/**
|
||||
* Return all associated specifications.
|
||||
* Return all associated specifications.
|
||||
*
|
||||
* @return AbstractParameter[]|Collection
|
||||
* @return Collection
|
||||
*
|
||||
* @psalm-return Collection<int, PartParameter>
|
||||
*/
|
||||
public function getParameters(): Collection
|
||||
public function getParameters(): \Doctrine\Common\Collections\Collection
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
|
@ -73,6 +75,7 @@ trait ParametersTrait
|
|||
foreach ($this->parameters as $parameter) {
|
||||
$tmp[$parameter->getGroup()][] = $parameter;
|
||||
}
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ class Category extends AbstractPartsContainingDBElement
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -101,13 +102,14 @@ class Category extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
protected $default_comment = '';
|
||||
/**
|
||||
* @var Collection|CategoryAttachment[]
|
||||
* @var Collection<int, CategoryAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\CategoryAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
/** @var CategoryParameter[]
|
||||
/** @var Collection<int, CategoryParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\CategoryParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
|
|
@ -73,6 +73,7 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Footprint", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -81,8 +82,9 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
protected $parts;
|
||||
/**
|
||||
* @var Collection|FootprintAttachment[]
|
||||
* @var Collection<int, FootprintAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\FootprintAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
@ -94,9 +96,9 @@ class Footprint extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
protected $footprint_3d;
|
||||
|
||||
/** @var FootprintParameter[]
|
||||
/** @var Collection<int, FootprintParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\FootprintParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})@ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $parameters;
|
||||
|
|
|
@ -73,6 +73,7 @@ class Manufacturer extends AbstractCompany
|
|||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Manufacturer", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -81,13 +82,14 @@ class Manufacturer extends AbstractCompany
|
|||
*/
|
||||
protected $parts;
|
||||
/**
|
||||
* @var Collection|ManufacturerAttachment[]
|
||||
* @var Collection<int, ManufacturerAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\ManufacturerAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
/** @var ManufacturerParameter[]
|
||||
/** @var Collection<int, ManufacturerParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\ManufacturerParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
|
|
@ -84,6 +84,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MeasurementUnit", mappedBy="parent", cascade={"persist"})
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -98,13 +99,14 @@ class MeasurementUnit extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
protected $parts;
|
||||
/**
|
||||
* @var Collection|MeasurementUnitAttachment[]
|
||||
* @var Collection<int, MeasurementUnitAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\MeasurementUnitAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
/** @var MeasurementUnitParameter[]
|
||||
/** @var Collection<int, MeasurementUnitParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\MeasurementUnitParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace App\Entity\Parts;
|
|||
|
||||
use App\Entity\Attachments\Attachment;
|
||||
use App\Entity\Attachments\AttachmentContainingDBElement;
|
||||
use App\Entity\Attachments\PartAttachment;
|
||||
use App\Entity\Devices\Device;
|
||||
use App\Entity\Parameters\ParametersTrait;
|
||||
use App\Entity\Parameters\PartParameter;
|
||||
|
@ -63,6 +64,7 @@ use App\Entity\Parts\PartTraits\OrderTrait;
|
|||
use App\Security\Annotations\ColumnSecurity;
|
||||
use DateTime;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
|
@ -90,11 +92,10 @@ class Part extends AttachmentContainingDBElement
|
|||
*/
|
||||
protected $devices = [];
|
||||
|
||||
/** @var PartParameter[]
|
||||
/** @var Collection<int, PartParameter>
|
||||
* @Assert\Valid()
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\PartParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
*/
|
||||
protected $parameters;
|
||||
|
||||
|
@ -117,8 +118,10 @@ class Part extends AttachmentContainingDBElement
|
|||
protected $name = '';
|
||||
|
||||
/**
|
||||
* @var Collection<int, PartAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\PartAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ColumnSecurity(type="collection", prefix="attachments")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
|
|
@ -303,8 +303,20 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
|
|||
return (float) $this->amount;
|
||||
}
|
||||
|
||||
public function setAmount(float $new_amount): self
|
||||
/**
|
||||
* Sets the amount of parts in the part lot.
|
||||
* If null is passed, amount will be set to unknown.
|
||||
* @param float|null $new_amount
|
||||
* @return $this
|
||||
*/
|
||||
public function setAmount(?float $new_amount): self
|
||||
{
|
||||
//Treat null like unknown amount
|
||||
if ($new_amount === null) {
|
||||
$this->instock_unknown = true;
|
||||
$new_amount = 0.0;
|
||||
}
|
||||
|
||||
$this->amount = $new_amount;
|
||||
|
||||
return $this;
|
||||
|
@ -328,9 +340,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->description;
|
||||
|
|
|
@ -57,6 +57,7 @@ trait InstockTrait
|
|||
* @ORM\OneToMany(targetEntity="PartLot", mappedBy="part", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @Assert\Valid()
|
||||
* @ColumnSecurity(type="collection", prefix="lots")
|
||||
* @ORM\OrderBy({"amount" = "DESC"})
|
||||
*/
|
||||
protected $partLots;
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace App\Entity\Parts\PartTraits;
|
|||
|
||||
use App\Entity\PriceInformations\Orderdetail;
|
||||
use App\Security\Annotations\ColumnSecurity;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use function count;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
|
@ -57,6 +58,7 @@ trait OrderTrait
|
|||
* @ORM\OneToMany(targetEntity="App\Entity\PriceInformations\Orderdetail", mappedBy="part", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @Assert\Valid()
|
||||
* @ColumnSecurity(prefix="orderdetails", type="collection")
|
||||
* @ORM\OrderBy({"supplierpartnr" = "ASC"})
|
||||
*/
|
||||
protected $orderdetails;
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ class Storelocation extends AbstractPartsContainingDBElement
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Storelocation", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -92,7 +93,7 @@ class Storelocation extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
protected $parts;
|
||||
|
||||
/** @var StorelocationParameter[]
|
||||
/** @var Collection<int, StorelocationParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\StorelocationParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
@ -117,7 +118,7 @@ class Storelocation extends AbstractPartsContainingDBElement
|
|||
*/
|
||||
protected $limit_to_existing_parts = false;
|
||||
/**
|
||||
* @var Collection|StorelocationAttachment[]
|
||||
* @var Collection<int, StorelocationAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\StorelocationAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
|
|
|
@ -69,6 +69,7 @@ class Supplier extends AbstractCompany
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Supplier", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -107,14 +108,16 @@ class Supplier extends AbstractCompany
|
|||
* )
|
||||
*/
|
||||
protected $parts;
|
||||
|
||||
/**
|
||||
* @var Collection|SupplierAttachment[]
|
||||
* @var Collection<int, SupplierAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\SupplierAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
/** @var SupplierParameter[]
|
||||
/** @var Collection<int, SupplierParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\SupplierParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
|
|
@ -78,6 +78,7 @@ class Currency extends AbstractStructuralDBElement
|
|||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Currency", mappedBy="parent", cascade={"persist"})
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -88,13 +89,14 @@ class Currency extends AbstractStructuralDBElement
|
|||
protected $parent;
|
||||
|
||||
/**
|
||||
* @var Collection|CurrencyAttachment[]
|
||||
* @var Collection<int, CurrencyAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\CurrencyAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
/** @var CurrencyParameter[]
|
||||
/** @var Collection<int, CurrencyParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\CurrencyParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
|
|
@ -59,6 +59,7 @@ use App\Entity\Parts\Supplier;
|
|||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
|
@ -67,6 +68,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
* @ORM\Table("`orderdetails`")
|
||||
* @ORM\Entity()
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
* @UniqueEntity({"supplierpartnr", "supplier", "part"})
|
||||
*/
|
||||
class Orderdetail extends AbstractDBElement implements TimeStampableInterface, NamedElementInterface
|
||||
{
|
||||
|
@ -361,9 +363,6 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->getSupplierPartNr();
|
||||
|
|
|
@ -64,7 +64,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
* @ORM\Entity()
|
||||
* @ORM\Table("`pricedetails`")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
* @UniqueEntity(fields={"orderdetail", "min_discount_quantity"})
|
||||
* @UniqueEntity(fields={"min_discount_quantity", "orderdetail"})
|
||||
*/
|
||||
class Pricedetail extends AbstractDBElement implements TimeStampableInterface
|
||||
{
|
||||
|
@ -136,11 +136,11 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
|
|||
*********************************************************************************/
|
||||
|
||||
/**
|
||||
* Get the orderdetail to which this pricedetail belongs to this pricedetails.
|
||||
* Get the orderdetail to which this pricedetail belongs to this pricedetails.
|
||||
*
|
||||
* @return Orderdetail the orderdetail this price belongs to
|
||||
* @return Orderdetail|null the orderdetail this price belongs to
|
||||
*/
|
||||
public function getOrderdetail(): Orderdetail
|
||||
public function getOrderdetail(): ?Orderdetail
|
||||
{
|
||||
return $this->orderdetail;
|
||||
}
|
||||
|
@ -157,17 +157,20 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the price for a single unit in the currency associated with this price detail.
|
||||
* Get the price for a single unit in the currency associated with this price detail.
|
||||
*
|
||||
* @param float|string $multiplier The returned price (float or string) will be multiplied
|
||||
* with this multiplier.
|
||||
*
|
||||
* You will get the price for $multiplier parts. If you want the price which is stored
|
||||
* in the database, you have to pass the "price_related_quantity" count as $multiplier.
|
||||
*
|
||||
* @param float|string $multiplier The returned price (float or string) will be multiplied
|
||||
* with this multiplier.
|
||||
*
|
||||
* You will get the price for $multiplier parts. If you want the price which is stored
|
||||
* in the database, you have to pass the "price_related_quantity" count as $multiplier.
|
||||
*
|
||||
* @return string the price as a bcmath string
|
||||
* @return null|string the price as a bcmath string
|
||||
*/
|
||||
public function getPricePerUnit($multiplier = 1.0): string
|
||||
public function getPricePerUnit($multiplier = 1.0): ?string
|
||||
{
|
||||
$multiplier = (string) $multiplier;
|
||||
$tmp = bcmul($this->price, $multiplier, static::PRICE_PRECISION);
|
||||
|
|
|
@ -61,6 +61,7 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Group", mappedBy="parent")
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $children;
|
||||
|
||||
|
@ -81,8 +82,9 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
|
|||
*/
|
||||
protected $enforce2FA = false;
|
||||
/**
|
||||
* @var Collection|GroupAttachment[]
|
||||
* @var Collection<int, GroupAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\ManufacturerAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
protected $attachments;
|
||||
|
@ -93,7 +95,7 @@ class Group extends AbstractStructuralDBElement implements HasPermissionsInterfa
|
|||
*/
|
||||
protected $permissions;
|
||||
|
||||
/** @var GroupParameter[]
|
||||
/** @var Collection<int, GroupParameter>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Parameters\GroupParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"})
|
||||
* @Assert\Valid()
|
||||
|
|
|
@ -53,7 +53,6 @@ namespace App\Entity\UserSystem;
|
|||
use App\Entity\Attachments\AttachmentContainingDBElement;
|
||||
use App\Entity\Attachments\UserAttachment;
|
||||
use App\Entity\Base\AbstractNamedDBElement;
|
||||
use App\Entity\Base\MasterAttachmentTrait;
|
||||
use App\Entity\PriceInformations\Currency;
|
||||
use App\Security\Interfaces\HasPermissionsInterface;
|
||||
use App\Validator\Constraints\Selectable;
|
||||
|
@ -114,7 +113,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
* @var string|null The hash of a token the user must provide when he wants to reset his password.
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
*/
|
||||
protected $pw_reset_token = null;
|
||||
protected $pw_reset_token;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", name="config_instock_comment_a")
|
||||
|
@ -228,8 +227,9 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
protected $settings = [];
|
||||
|
||||
/**
|
||||
* @var Collection|UserAttachment[]
|
||||
* @var Collection<int, UserAttachment>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Attachments\UserAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"name" = "ASC"})
|
||||
*/
|
||||
protected $attachments;
|
||||
|
||||
|
@ -238,7 +238,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
*/
|
||||
protected $backupCodesGenerationDate;
|
||||
|
||||
/** @var Collection<TwoFactorKeyInterface>
|
||||
/** @var Collection<int, TwoFactorKeyInterface>
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\UserSystem\U2FKey", mappedBy="user", cascade={"REMOVE"}, orphanRemoval=true)
|
||||
*/
|
||||
protected $u2fKeys;
|
||||
|
@ -252,7 +252,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
* @ORM\JoinColumn(name="currency_id", referencedColumnName="id")
|
||||
* @Selectable()
|
||||
*/
|
||||
protected $currency = null;
|
||||
protected $currency;
|
||||
|
||||
/** @var PermissionsEmbed
|
||||
* @ORM\Embedded(class="PermissionsEmbed", columnPrefix="perms_")
|
||||
|
@ -264,7 +264,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
* @var DateTime The time until the password reset token is valid.
|
||||
* @ORM\Column(type="datetime", nullable=true)
|
||||
*/
|
||||
protected $pw_reset_expires = null;
|
||||
protected $pw_reset_expires;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -863,9 +863,11 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all U2F Keys that are associated with this user.
|
||||
* Get all U2F Keys that are associated with this user.
|
||||
*
|
||||
* @return Collection<TwoFactorKeyInterface>
|
||||
* @return Collection
|
||||
*
|
||||
* @psalm-return Collection<int, TwoFactorKeyInterface>
|
||||
*/
|
||||
public function getU2FKeys(): Collection
|
||||
{
|
||||
|
|
|
@ -77,12 +77,21 @@ class AttachmentDeleteListener
|
|||
public function preUpdateHandler(Attachment $attachment, PreUpdateEventArgs $event): void
|
||||
{
|
||||
if ($event->hasChangedField('path')) {
|
||||
$old_path = $event->getOldValue('path');
|
||||
|
||||
//Dont delete file if the attachment uses a builtin ressource:
|
||||
if (Attachment::checkIfBuiltin($event->getOldValue('path'))) {
|
||||
if (Attachment::checkIfBuiltin($old_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = new SplFileInfo($this->pathResolver->placeholderToRealPath($event->getOldValue('path')));
|
||||
$real_path = $this->pathResolver->placeholderToRealPath($old_path);
|
||||
|
||||
//If the attachment does not point to a valid file, ignore it!
|
||||
if ($real_path === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = new SplFileInfo($real_path);
|
||||
$this->attachmentReverseSearch->deleteIfNotUsed($file);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class EventLoggerSubscriber implements EventSubscriber
|
|||
Orderdetail::class => ['part'],
|
||||
Pricedetail::class => ['orderdetail'],
|
||||
Attachment::class => ['element'],
|
||||
AbstractParameter::class => ['element']
|
||||
AbstractParameter::class => ['element'],
|
||||
];
|
||||
|
||||
protected const MAX_STRING_LENGTH = 2000;
|
||||
|
@ -163,7 +163,7 @@ class EventLoggerSubscriber implements EventSubscriber
|
|||
*/
|
||||
public function hasFieldRestrictions(AbstractDBElement $element): bool
|
||||
{
|
||||
foreach (static::FIELD_BLACKLIST as $class => $blacklist) {
|
||||
foreach (array_keys(static::FIELD_BLACKLIST) as $class) {
|
||||
if (is_a($element, $class)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ class EventLoggerSubscriber implements EventSubscriber
|
|||
}, ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
|
||||
protected function saveChangeSet(AbstractDBElement $entity, AbstractLogEntry $logEntry, EntityManagerInterface $em, $element_deleted = false): void
|
||||
protected function saveChangeSet(AbstractDBElement $entity, AbstractLogEntry $logEntry, EntityManagerInterface $em, bool $element_deleted = false): void
|
||||
{
|
||||
$uow = $em->getUnitOfWork();
|
||||
|
||||
|
|
|
@ -53,8 +53,6 @@ use Symfony\Component\Security\Core\Security;
|
|||
final class LogoutOnDisabledUserListener implements EventSubscriberInterface
|
||||
{
|
||||
private $security;
|
||||
private $translator;
|
||||
private $flashBag;
|
||||
private $urlGenerator;
|
||||
|
||||
public function __construct(Security $security, UrlGeneratorInterface $urlGenerator)
|
||||
|
|
|
@ -45,14 +45,15 @@ namespace App\EventSubscriber;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
|
||||
final class SymfonyDebugToolbarSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private $kernel;
|
||||
private $kernel_debug;
|
||||
|
||||
public function __construct(ContainerInterface $kernel)
|
||||
public function __construct(bool $kernel_debug)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
$this->kernel_debug = $kernel_debug;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,9 +79,9 @@ final class SymfonyDebugToolbarSubscriber implements EventSubscriberInterface
|
|||
return ['kernel.response' => 'onKernelResponse'];
|
||||
}
|
||||
|
||||
public function onKernelResponse(FilterResponseEvent $event): void
|
||||
public function onKernelResponse(ResponseEvent $event): void
|
||||
{
|
||||
if (! $this->kernel->getParameter('kernel.debug')) {
|
||||
if (! $this->kernel_debug) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ namespace App\Form\AdminPages;
|
|||
use App\Entity\Attachments\Attachment;
|
||||
use App\Entity\Base\AbstractNamedDBElement;
|
||||
use App\Entity\Base\AbstractStructuralDBElement;
|
||||
use App\Entity\Parameters\PartParameter;
|
||||
use App\Form\AttachmentFormType;
|
||||
use App\Form\ParameterType;
|
||||
use App\Form\Type\MasterPictureAttachmentType;
|
||||
|
@ -133,6 +132,7 @@ class BaseEntityAdminForm extends AbstractType
|
|||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'label' => false,
|
||||
'reindex_enable' => true,
|
||||
'disabled' => ! $this->security->isGranted($is_new ? 'create' : 'edit', $entity),
|
||||
'entry_options' => [
|
||||
'data_class' => $options['attachment_class'],
|
||||
|
@ -159,6 +159,7 @@ class BaseEntityAdminForm extends AbstractType
|
|||
'allow_add' => $this->security->isGranted($is_new ? 'create' : 'edit', $entity),
|
||||
'allow_delete' => $this->security->isGranted($is_new ? 'create' : 'edit', $entity),
|
||||
'disabled' => ! $this->security->isGranted($is_new ? 'create' : 'edit', $entity),
|
||||
'reindex_enable' => true,
|
||||
'label' => false,
|
||||
'by_reference' => false,
|
||||
'prototype_data' => new $options['parameter_class'](),
|
||||
|
|
|
@ -57,6 +57,7 @@ use Symfony\Component\Form\FormEvent;
|
|||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Validator\Constraints\File;
|
||||
use Symfony\Component\Validator\Constraints\Url;
|
||||
|
||||
|
@ -65,13 +66,15 @@ class AttachmentFormType extends AbstractType
|
|||
protected $attachment_helper;
|
||||
protected $urlGenerator;
|
||||
protected $allow_attachments_download;
|
||||
protected $security;
|
||||
|
||||
public function __construct(AttachmentManager $attachmentHelper,
|
||||
UrlGeneratorInterface $urlGenerator, bool $allow_attachments_downloads)
|
||||
UrlGeneratorInterface $urlGenerator, Security $security, bool $allow_attachments_downloads)
|
||||
{
|
||||
$this->attachment_helper = $attachmentHelper;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->allow_attachments_download = $allow_attachments_downloads;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
@ -103,6 +106,7 @@ class AttachmentFormType extends AbstractType
|
|||
'required' => false,
|
||||
'label' => 'attachment.edit.secure_file',
|
||||
'mapped' => false,
|
||||
'disabled' => !$this->security->isGranted('@parts_attachments.show_private'),
|
||||
'attr' => [
|
||||
'class' => 'form-control-sm',
|
||||
],
|
||||
|
|
120
src/Form/CollectionTypeExtension.php
Normal file
120
src/Form/CollectionTypeExtension.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormConfigBuilder;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
/**
|
||||
* Perform a reindexing on CollectionType elements, by assigning the database id as index.
|
||||
* This prevents issues when the collection that is edited uses a OrderBy annotation and therefore the direction of the
|
||||
* elements can change during requests.
|
||||
* Must me enabled by setting reindex_enable to true in Type options.
|
||||
* @package App\Form
|
||||
*/
|
||||
class CollectionTypeExtension extends AbstractTypeExtension
|
||||
{
|
||||
protected $propertyAccess;
|
||||
|
||||
public function __construct(PropertyAccessorInterface $propertyAccess)
|
||||
{
|
||||
$this->propertyAccess = $propertyAccess;
|
||||
}
|
||||
|
||||
public static function getExtendedTypes(): iterable
|
||||
{
|
||||
return [CollectionType::class];
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
/*$resolver->setDefault('error_mapping', function (Options $options) {
|
||||
$options->
|
||||
});*/
|
||||
|
||||
$resolver->setDefaults([
|
||||
'reindex_enable' => false,
|
||||
'reindex_prefix' => 'db_',
|
||||
'reindex_path' => 'id',
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('reindex_enable', 'bool');
|
||||
$resolver->setAllowedTypes('reindex_prefix', 'string');
|
||||
$resolver->setAllowedTypes('reindex_path', 'string');
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options) {
|
||||
$data = $event->getData();
|
||||
$config = $event->getForm()->getConfig();
|
||||
//If enabled do a reindexing of the collection
|
||||
if ($options['reindex_enable'] && $data instanceof Collection) {
|
||||
$reindexed_data = new ArrayCollection();
|
||||
|
||||
$error_mapping = [];
|
||||
|
||||
foreach ($data->toArray() as $key => $item) {
|
||||
$index = $options['reindex_prefix'] . $this->propertyAccess->getValue($item, $options['reindex_path']);
|
||||
$error_mapping['[' . $key . ']'] = $index;
|
||||
$reindexed_data->set($index, $item);
|
||||
}
|
||||
$event->setData($reindexed_data);
|
||||
|
||||
//Add error mapping, so that validator error are mapped correctly to the new index fields
|
||||
if ($config instanceof FormBuilder && empty($config->getOption('error_mapping'))) {
|
||||
$this->setOption($config, 'error_mapping', $error_mapping);
|
||||
}
|
||||
}
|
||||
}, 100); //We need to have a higher priority then the PRE_SET_DATA listener on CollectionType
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the option of the form.
|
||||
* This a bit hacky cause we access private properties....
|
||||
* @param $builder
|
||||
* @param string $option
|
||||
* @param $value
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function setOption(FormBuilder $builder, string $option, $value): void
|
||||
{
|
||||
//We have to use FormConfigBuilder::class here, because options is private and not available in sub classes
|
||||
$reflection = new \ReflectionClass(FormConfigBuilder::class);
|
||||
$property = $reflection->getProperty('options');
|
||||
$property->setAccessible(true);
|
||||
$tmp = $property->getValue($builder);
|
||||
$tmp[$option] = $value;
|
||||
$property->setValue($builder, $tmp);
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
}
|
|
@ -113,14 +113,14 @@ class ParameterType extends AbstractType
|
|||
'attr' => [
|
||||
'placeholder' => 'parameter.group.placeholder',
|
||||
'class' => 'form-control-sm',
|
||||
]
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => AbstractParameter::class,
|
||||
]);
|
||||
'data_class' => AbstractParameter::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,9 +69,6 @@ class OrderdetailType extends AbstractType
|
|||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
/** @var Orderdetail $orderdetail */
|
||||
$orderdetail = $builder->getData();
|
||||
|
||||
$builder->add('supplierpartnr', TextType::class, [
|
||||
'label' => 'orderdetails.edit.supplierpartnr',
|
||||
'attr' => [
|
||||
|
@ -117,6 +114,7 @@ class OrderdetailType extends AbstractType
|
|||
'allow_add' => $this->security->isGranted('@parts_prices.create'),
|
||||
'allow_delete' => $this->security->isGranted('@parts_prices.delete'),
|
||||
'label' => false,
|
||||
'reindex_enable' => true,
|
||||
'prototype_data' => $dummy_pricedetail,
|
||||
'by_reference' => false,
|
||||
'entry_options' => [
|
||||
|
|
|
@ -52,7 +52,6 @@ use App\Entity\Parts\MeasurementUnit;
|
|||
use App\Entity\Parts\Part;
|
||||
use App\Entity\PriceInformations\Orderdetail;
|
||||
use App\Form\AttachmentFormType;
|
||||
use App\Form\ParameterGroupType;
|
||||
use App\Form\ParameterType;
|
||||
use App\Form\Type\MasterPictureAttachmentType;
|
||||
use App\Form\Type\SIUnitType;
|
||||
|
@ -225,6 +224,7 @@ class PartBaseType extends AbstractType
|
|||
'entry_type' => PartLotType::class,
|
||||
'allow_add' => $this->security->isGranted('lots.create', $part),
|
||||
'allow_delete' => $this->security->isGranted('lots.delete', $part),
|
||||
'reindex_enable' => true,
|
||||
'label' => false,
|
||||
'entry_options' => [
|
||||
'measurement_unit' => $part->getPartUnit(),
|
||||
|
@ -238,6 +238,7 @@ class PartBaseType extends AbstractType
|
|||
'entry_type' => AttachmentFormType::class,
|
||||
'allow_add' => $this->security->isGranted('attachments.create', $part),
|
||||
'allow_delete' => $this->security->isGranted('attachments.delete', $part),
|
||||
'reindex_enable' => true,
|
||||
'label' => false,
|
||||
'entry_options' => [
|
||||
'data_class' => PartAttachment::class,
|
||||
|
@ -258,6 +259,7 @@ class PartBaseType extends AbstractType
|
|||
'entry_type' => OrderdetailType::class,
|
||||
'allow_add' => $this->security->isGranted('orderdetails.create', $part),
|
||||
'allow_delete' => $this->security->isGranted('orderdetails.delete', $part),
|
||||
'reindex_enable' => true,
|
||||
'label' => false,
|
||||
'by_reference' => false,
|
||||
'prototype_data' => new Orderdetail(),
|
||||
|
@ -272,6 +274,7 @@ class PartBaseType extends AbstractType
|
|||
'allow_add' => $this->security->isGranted('parameters.create', $part),
|
||||
'allow_delete' => $this->security->isGranted('parameters.delete', $part),
|
||||
'label' => false,
|
||||
'reindex_enable' => true,
|
||||
'by_reference' => false,
|
||||
'prototype_data' => new PartParameter(),
|
||||
'entry_options' => [
|
||||
|
|
|
@ -49,7 +49,7 @@ use App\Form\Type\SIUnitType;
|
|||
use App\Form\Type\StructuralEntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
@ -88,6 +88,7 @@ class PartLotType extends AbstractType
|
|||
|
||||
$builder->add('amount', SIUnitType::class, [
|
||||
'measurement_unit' => $options['measurement_unit'],
|
||||
'required' => false,
|
||||
'label' => 'part_lot.edit.amount',
|
||||
'attr' => [
|
||||
'class' => 'form-control-sm',
|
||||
|
@ -116,9 +117,11 @@ class PartLotType extends AbstractType
|
|||
'required' => false,
|
||||
]);
|
||||
|
||||
$builder->add('expirationDate', DateTimeType::class, [
|
||||
$builder->add('expirationDate', DateType::class, [
|
||||
'label' => 'part_lot.edit.expiration_date',
|
||||
'attr' => [],
|
||||
'widget' => 'single_text',
|
||||
'model_timezone' => 'UTC',
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ class PermissionsType extends AbstractType
|
|||
{
|
||||
$groups = $this->perm_structure['groups'];
|
||||
|
||||
foreach ($groups as $key => $group) {
|
||||
foreach (array_keys($groups) as $key) {
|
||||
$builder->add($key, PermissionGroupType::class, [
|
||||
'group_name' => $key,
|
||||
'mapped' => false,
|
||||
|
|
|
@ -102,7 +102,7 @@ class CurrencyEntityType extends StructuralEntityType
|
|||
$level -= $parent->getLevel() - 1;
|
||||
}
|
||||
|
||||
$tmp = str_repeat(' ', $choice->getLevel()); //Use 3 spaces for intendation
|
||||
$tmp = str_repeat(' ', $level); //Use 3 spaces for intendation
|
||||
if (empty($choice->getIsoCode())) {
|
||||
$tmp .= htmlspecialchars($choice->getName());
|
||||
} else {
|
||||
|
|
|
@ -153,37 +153,37 @@ class StructuralEntityType extends AbstractType
|
|||
}
|
||||
|
||||
/**
|
||||
* Transforms a value from the original representation to a transformed representation.
|
||||
* Transforms a value from the original representation to a transformed representation.
|
||||
*
|
||||
* This method is called when the form field is initialized with its default data, on
|
||||
* two occasions for two types of transformers:
|
||||
* This method is called when the form field is initialized with its default data, on
|
||||
* two occasions for two types of transformers:
|
||||
*
|
||||
* 1. Model transformers which normalize the model data.
|
||||
* This is mainly useful when the same form type (the same configuration)
|
||||
* has to handle different kind of underlying data, e.g The DateType can
|
||||
* deal with strings or \DateTime objects as input.
|
||||
* 1. Model transformers which normalize the model data.
|
||||
* This is mainly useful when the same form type (the same configuration)
|
||||
* has to handle different kind of underlying data, e.g The DateType can
|
||||
* deal with strings or \DateTime objects as input.
|
||||
*
|
||||
* 2. View transformers which adapt the normalized data to the view format.
|
||||
* a/ When the form is simple, the value returned by convention is used
|
||||
* directly in the view and thus can only be a string or an array. In
|
||||
* this case the data class should be null.
|
||||
* 2. View transformers which adapt the normalized data to the view format.
|
||||
* a/ When the form is simple, the value returned by convention is used
|
||||
* directly in the view and thus can only be a string or an array. In
|
||||
* this case the data class should be null.
|
||||
*
|
||||
* b/ When the form is compound the returned value should be an array or
|
||||
* an object to be mapped to the children. Each property of the compound
|
||||
* data will be used as model data by each child and will be transformed
|
||||
* too. In this case data class should be the class of the object, or null
|
||||
* when it is an array.
|
||||
* b/ When the form is compound the returned value should be an array or
|
||||
* an object to be mapped to the children. Each property of the compound
|
||||
* data will be used as model data by each child and will be transformed
|
||||
* too. In this case data class should be the class of the object, or null
|
||||
* when it is an array.
|
||||
*
|
||||
* All transformers are called in a configured order from model data to view value.
|
||||
* At the end of this chain the view data will be validated against the data class
|
||||
* setting.
|
||||
* All transformers are called in a configured order from model data to view value.
|
||||
* At the end of this chain the view data will be validated against the data class
|
||||
* setting.
|
||||
*
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
* be NULL, but depending on your implementation other empty values are
|
||||
* possible as well (such as empty strings). The reasoning behind this is
|
||||
* that data transformers must be chainable. If the transform() method
|
||||
* of the first data transformer outputs NULL, the second must be able to
|
||||
* process that value.
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
* be NULL, but depending on your implementation other empty values are
|
||||
* possible as well (such as empty strings). The reasoning behind this is
|
||||
* that data transformers must be chainable. If the transform() method
|
||||
* of the first data transformer outputs NULL, the second must be able to
|
||||
* process that value.
|
||||
*
|
||||
* @param mixed $value The value in the original representation
|
||||
*
|
||||
|
@ -191,31 +191,31 @@ class StructuralEntityType extends AbstractType
|
|||
*
|
||||
* @throws TransformationFailedException when the transformation fails
|
||||
*/
|
||||
public function transform($value, $options)
|
||||
public function transform($value, array $options)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a value from the transformed representation to its original
|
||||
* representation.
|
||||
* Transforms a value from the transformed representation to its original
|
||||
* representation.
|
||||
*
|
||||
* This method is called when {@link Form::submit()} is called to transform the requests tainted data
|
||||
* into an acceptable format.
|
||||
* This method is called when {@link Form::submit()} is called to transform the requests tainted data
|
||||
* into an acceptable format.
|
||||
*
|
||||
* The same transformers are called in the reverse order so the responsibility is to
|
||||
* return one of the types that would be expected as input of transform().
|
||||
* The same transformers are called in the reverse order so the responsibility is to
|
||||
* return one of the types that would be expected as input of transform().
|
||||
*
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
* be an empty string, but depending on your implementation other empty
|
||||
* values are possible as well (such as NULL). The reasoning behind
|
||||
* this is that value transformers must be chainable. If the
|
||||
* reverseTransform() method of the first value transformer outputs an
|
||||
* empty string, the second value transformer must be able to process that
|
||||
* value.
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
* be an empty string, but depending on your implementation other empty
|
||||
* values are possible as well (such as NULL). The reasoning behind
|
||||
* this is that value transformers must be chainable. If the
|
||||
* reverseTransform() method of the first value transformer outputs an
|
||||
* empty string, the second value transformer must be able to process that
|
||||
* value.
|
||||
*
|
||||
* By convention, reverseTransform() should return NULL if an empty string
|
||||
* is passed.
|
||||
* By convention, reverseTransform() should return NULL if an empty string
|
||||
* is passed.
|
||||
*
|
||||
* @param mixed $value The value in the transformed representation
|
||||
*
|
||||
|
@ -223,7 +223,7 @@ class StructuralEntityType extends AbstractType
|
|||
*
|
||||
* @throws TransformationFailedException when the transformation fails
|
||||
*/
|
||||
public function reverseTransform($value, $options)
|
||||
public function reverseTransform($value, array $options)
|
||||
{
|
||||
/* This step is important in combination with the caching!
|
||||
The elements deserialized from cache, are not known to Doctrinte ORM any more, so doctrine thinks,
|
||||
|
@ -272,7 +272,7 @@ class StructuralEntityType extends AbstractType
|
|||
$level -= $parent->getLevel() - 1;
|
||||
}
|
||||
|
||||
$tmp = str_repeat(' ', $choice->getLevel()); //Use 3 spaces for intendation
|
||||
$tmp = str_repeat(' ', $level); //Use 3 spaces for intendation
|
||||
$tmp .= htmlspecialchars($choice->getName());
|
||||
|
||||
return $tmp;
|
||||
|
|
|
@ -244,6 +244,7 @@ class UserAdminForm extends AbstractType
|
|||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'label' => false,
|
||||
'reindex_enable' => true,
|
||||
'entry_options' => [
|
||||
'data_class' => $options['attachment_class'],
|
||||
],
|
||||
|
|
|
@ -46,11 +46,6 @@ use JsonSerializable;
|
|||
|
||||
final class TreeViewNodeState implements JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private $checked = null;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
|
|
|
@ -41,7 +41,7 @@ final class Version1 extends AbstractMigration
|
|||
try {
|
||||
//Check if we can use this migration method:
|
||||
$version = (int) $this->connection->fetchColumn("SELECT keyValue AS version FROM `internal` WHERE `keyName` = 'dbVersion'");
|
||||
$this->skipIf(true, 'Old Part-DB Database detected! Continue with upgrade...');
|
||||
$this->skipIf($version > 0, 'Old Part-DB Database detected! Continue with upgrade...');
|
||||
} catch (DBALException $dBALException) {
|
||||
//when the table was not found, we can proceed, because we have an empty DB!
|
||||
}
|
||||
|
|
|
@ -27,11 +27,11 @@ final class Version20200311204104 extends AbstractMigration
|
|||
$this->addSql('ALTER TABLE `users` ADD perms_parts_parameters SMALLINT NOT NULL');
|
||||
$this->addSql('ALTER TABLE log CHANGE level level TINYINT');
|
||||
|
||||
$sql = 'UPDATE `groups`' .
|
||||
$sql = 'UPDATE `groups`'.
|
||||
'SET perms_parts_parameters = 341 WHERE (id = 1 AND name = "admins") OR (id = 3 AND name = "users");';
|
||||
$this->addSql($sql);
|
||||
|
||||
$sql = 'UPDATE `groups`' .
|
||||
$sql = 'UPDATE `groups`'.
|
||||
'SET perms_parts_parameters = 681 WHERE (id = 2 AND name = "readonly");';
|
||||
$this->addSql($sql);
|
||||
|
||||
|
|
|
@ -44,12 +44,13 @@ class DBElementRepository extends EntityRepository
|
|||
->setParameter(1, $element->getID())
|
||||
->getQuery();
|
||||
|
||||
$p = $q->execute();
|
||||
//Do the renaming
|
||||
$q->execute();
|
||||
|
||||
$this->setField($element, 'id', $new_id);
|
||||
}
|
||||
|
||||
protected function setField(AbstractDBElement $element, string $field, $new_value): void
|
||||
protected function setField(AbstractDBElement $element, string $field, int $new_value): void
|
||||
{
|
||||
$reflection = new \ReflectionClass(get_class($element));
|
||||
$property = $reflection->getProperty($field);
|
||||
|
|
|
@ -142,7 +142,6 @@ class ElementPermissionListener
|
|||
return;
|
||||
}
|
||||
|
||||
$em = $eventArgs->getEntityManager();
|
||||
$unitOfWork = $eventArgs->getEntityManager()->getUnitOfWork();
|
||||
|
||||
$reflectionClass = new ReflectionClass($element);
|
||||
|
|
|
@ -43,6 +43,7 @@ declare(strict_types=1);
|
|||
namespace App\Security\Voter;
|
||||
|
||||
use App\Entity\UserSystem\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Services\PermissionResolver;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
@ -76,6 +77,7 @@ abstract class ExtendedVoter extends Voter
|
|||
|
||||
// if the user is anonymous, we use the anonymous user.
|
||||
if (! $user instanceof User) {
|
||||
/** @var UserRepository $repo */
|
||||
$repo = $this->entityManager->getRepository(User::class);
|
||||
$user = $repo->getAnonymousUser();
|
||||
if (null === $user) {
|
||||
|
|
|
@ -60,10 +60,11 @@ class AmountFormatter
|
|||
}
|
||||
|
||||
/**
|
||||
* Formats the given value using the measurement unit and options.
|
||||
* Formats the given value using the measurement unit and options.
|
||||
*
|
||||
* @param MeasurementUnit|null $unit The measurement unit, whose unit symbol should be used for formatting.
|
||||
* If set to null, it is assumed that the part amount is measured in pieces.
|
||||
* @param float|string|int $value
|
||||
* @param MeasurementUnit|null $unit The measurement unit, whose unit symbol should be used for formatting.
|
||||
* If set to null, it is assumed that the part amount is measured in pieces.
|
||||
*
|
||||
* @return string The formatted string
|
||||
*
|
||||
|
|
|
@ -130,7 +130,7 @@ class AttachmentURLGenerator
|
|||
throw new InvalidArgumentException('Thumbnail creation only works for picture attachments!');
|
||||
}
|
||||
|
||||
if ($attachment->isExternal()) {
|
||||
if ($attachment->isExternal() && !empty($attachment->getURL())) {
|
||||
return $attachment->getURL();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,10 @@ declare(strict_types=1);
|
|||
namespace App\Services\Attachments;
|
||||
|
||||
use App\Entity\Attachments\Attachment;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* This service is used to find builtin attachment ressources.
|
||||
|
|
|
@ -174,7 +174,7 @@ class FileTypeFilterTools
|
|||
$extensions = array_merge($extensions, static::IMAGE_EXTS);
|
||||
} elseif ('audio/*' === $element) {
|
||||
$extensions = array_merge($extensions, static::AUDIO_EXTS);
|
||||
} elseif ('image/*' === $element) {
|
||||
} elseif ('video/*' === $element) {
|
||||
$extensions = array_merge($extensions, static::VIDEO_EXTS);
|
||||
} elseif (preg_match('#^[-\w.]+\/[-\w.*]+#', $element)) {
|
||||
$extensions = array_merge($extensions, $this->mimeTypes->getExtensions($element));
|
||||
|
|
|
@ -55,13 +55,15 @@ class PartPreviewGenerator
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of attachments that can be used for previewing the part ordered by priority.
|
||||
* The priority is: Part MasterAttachment -> Footprint MasterAttachment -> Category MasterAttachment
|
||||
* -> Storelocation Attachment -> MeasurementUnit Attachment -> ManufacturerAttachment.
|
||||
* Returns a list of attachments that can be used for previewing the part ordered by priority.
|
||||
* The priority is: Part MasterAttachment -> Footprint MasterAttachment -> Category MasterAttachment
|
||||
* -> Storelocation Attachment -> MeasurementUnit Attachment -> ManufacturerAttachment.
|
||||
*
|
||||
* @param Part $part the part for which the attachments should be determined
|
||||
*
|
||||
* @return Attachment[]
|
||||
* @return (Attachment|null)[]
|
||||
*
|
||||
* @psalm-return list<Attachment|null>
|
||||
*/
|
||||
public function getPreviewAttachments(Part $part): array
|
||||
{
|
||||
|
|
|
@ -102,7 +102,7 @@ class ElementTypeNameGenerator
|
|||
* Useful when the type should be shown to user.
|
||||
* Throws an exception if the class is not supported.
|
||||
*
|
||||
* @param AbstractDBElement|string $entity The element or class for which the label should be generated
|
||||
* @param object|string $entity The element or class for which the label should be generated
|
||||
*
|
||||
* @return string the localized label for the entity type
|
||||
*
|
||||
|
|
|
@ -77,9 +77,10 @@ class EntityExporter
|
|||
}
|
||||
|
||||
/**
|
||||
* Exports an Entity or an array of entities to multiple file formats.
|
||||
* Exports an Entity or an array of entities to multiple file formats.
|
||||
*
|
||||
* @param Request $request the request that should be used for option resolving
|
||||
* @param AbstractNamedDBElement|object[] $entity
|
||||
*
|
||||
* @return Response the generated response containing the exported data
|
||||
*
|
||||
|
|
|
@ -94,12 +94,12 @@ class EntityURLGenerator
|
|||
* @param mixed $entity The element for which the page should be generated
|
||||
* @param string $type The page type. Currently supported: 'info', 'edit', 'create', 'clone', 'list'/'list_parts'
|
||||
*
|
||||
* @return string the link to the desired page
|
||||
* @return null|string the link to the desired page
|
||||
*
|
||||
* @throws EntityNotSupportedException thrown if the entity is not supported for the given type
|
||||
* @throws InvalidArgumentException thrown if the givent type is not existing
|
||||
*/
|
||||
public function getURL($entity, string $type)
|
||||
public function getURL($entity, string $type): ?string
|
||||
{
|
||||
switch ($type) {
|
||||
case 'info':
|
||||
|
@ -187,7 +187,7 @@ class EntityURLGenerator
|
|||
throw new EntityNotSupportedException('The given entity is not supported yet!');
|
||||
}
|
||||
|
||||
public function viewURL($entity): string
|
||||
public function viewURL(Attachment $entity): ?string
|
||||
{
|
||||
if ($entity instanceof Attachment) {
|
||||
if ($entity->isExternal()) { //For external attachments, return the link to external path
|
||||
|
@ -201,7 +201,7 @@ class EntityURLGenerator
|
|||
throw new EntityNotSupportedException('The given entity is not supported yet!');
|
||||
}
|
||||
|
||||
public function downloadURL($entity): string
|
||||
public function downloadURL($entity): ?string
|
||||
{
|
||||
if ($entity instanceof Attachment) {
|
||||
if ($entity->isExternal()) { //For external attachments, return the link to external path
|
||||
|
@ -383,7 +383,7 @@ class EntityURLGenerator
|
|||
//Check if we have an direct mapping for the given class
|
||||
if (! array_key_exists($class, $map)) {
|
||||
//Check if we need to check inheritance by looping through our map
|
||||
foreach ($map as $key => $value) {
|
||||
foreach (array_keys($map) as $key) {
|
||||
if (is_a($entity, $key)) {
|
||||
return $map[$key];
|
||||
}
|
||||
|
|
|
@ -60,10 +60,14 @@ class GitVersionInfo
|
|||
*/
|
||||
public function getGitBranchName()
|
||||
{
|
||||
if (file_exists($this->project_dir.'/.git/HEAD')) {
|
||||
if (is_file($this->project_dir.'/.git/HEAD')) {
|
||||
$git = file($this->project_dir.'/.git/HEAD');
|
||||
$head = explode('/', $git[0], 3);
|
||||
|
||||
if (! isset($head[2])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return trim($head[2]);
|
||||
}
|
||||
|
||||
|
@ -82,8 +86,13 @@ class GitVersionInfo
|
|||
public function getGitCommitHash(int $length = 7)
|
||||
{
|
||||
$filename = $this->project_dir.'/.git/refs/remotes/origin/'.$this->getGitBranchName();
|
||||
if (file_exists($filename)) {
|
||||
if (is_file($filename)) {
|
||||
$head = file($filename);
|
||||
|
||||
if (! isset($head[0])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$hash = $head[0];
|
||||
|
||||
return substr($hash, 0, $length);
|
||||
|
|
|
@ -31,7 +31,7 @@ class EventCommentHelper
|
|||
|
||||
public function __construct()
|
||||
{
|
||||
$message = null;
|
||||
$this->message = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,7 +37,7 @@ class EventUndoHelper
|
|||
|
||||
public function __construct()
|
||||
{
|
||||
$undone_event = null;
|
||||
$this->undone_event = null;
|
||||
$this->mode = self::MODE_UNDO;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,12 @@ class HistoryHelper
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all elements that are associated with the argument.
|
||||
* The returned array contains the given element.
|
||||
* Returns an array containing all elements that are associated with the argument.
|
||||
* The returned array contains the given element.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @psalm-return array<\App\Entity\Parameters\AbstractParameter|array-key, mixed>
|
||||
*/
|
||||
public function getAssociatedElements(AbstractDBElement $element): array
|
||||
{
|
||||
|
|
|
@ -209,6 +209,9 @@ class TimeTravel
|
|||
return $property->getValue($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime|int|null $new_value
|
||||
*/
|
||||
protected function setField(AbstractDBElement $element, string $field, $new_value): void
|
||||
{
|
||||
$reflection = new \ReflectionClass(get_class($element));
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
|
@ -20,31 +23,29 @@
|
|||
|
||||
namespace App\Services\Parameters;
|
||||
|
||||
|
||||
use App\Entity\Parameters\AbstractParameter;
|
||||
use App\Entity\Parameters\PartParameter;
|
||||
|
||||
class ParameterExtractor
|
||||
{
|
||||
protected const ALLOWED_PARAM_SEPARATORS = [", ", "\n"];
|
||||
protected const ALLOWED_PARAM_SEPARATORS = [', ', "\n"];
|
||||
|
||||
protected const CHAR_LIMIT = 1000;
|
||||
|
||||
/**
|
||||
* Tries to extract parameters from the given string.
|
||||
* Useful for extraction from part description and comment.
|
||||
* @param string $input
|
||||
* @param string $class
|
||||
*
|
||||
* @return AbstractParameter[]
|
||||
*/
|
||||
public function extractParameters(string $input, string $class = PartParameter::class): array
|
||||
{
|
||||
if (!is_a($class, AbstractParameter::class, true)) {
|
||||
if (! is_a($class, AbstractParameter::class, true)) {
|
||||
throw new \InvalidArgumentException('$class must be a child class of AbstractParameter!');
|
||||
}
|
||||
|
||||
//Restrict search length
|
||||
$input = mb_strimwidth($input,0,self::CHAR_LIMIT);
|
||||
$input = mb_strimwidth($input, 0, self::CHAR_LIMIT);
|
||||
|
||||
$parameters = [];
|
||||
|
||||
|
@ -52,7 +53,7 @@ class ParameterExtractor
|
|||
$split = $this->splitString($input);
|
||||
foreach ($split as $param_string) {
|
||||
$tmp = $this->stringToParam($param_string, $class);
|
||||
if ($tmp !== null) {
|
||||
if (null !== $tmp) {
|
||||
$parameters[] = $tmp;
|
||||
}
|
||||
}
|
||||
|
@ -67,9 +68,8 @@ class ParameterExtractor
|
|||
|
||||
$matches = [];
|
||||
\preg_match($regex, $input, $matches);
|
||||
dump($matches);
|
||||
if (!empty($matches)) {
|
||||
[$raw, $name, $value] = $matches;
|
||||
if (! empty($matches)) {
|
||||
[, $name, $value] = $matches;
|
||||
$value = trim($value);
|
||||
|
||||
//Dont allow empty names or values (these are a sign of an invalid extracted string)
|
||||
|
@ -91,7 +91,8 @@ class ParameterExtractor
|
|||
protected function splitString(string $input): array
|
||||
{
|
||||
//Allow comma as limiter (include space, to prevent splitting in german style numbers)
|
||||
$input = str_replace(static::ALLOWED_PARAM_SEPARATORS, ";", $input);
|
||||
return explode(";", $input);
|
||||
$input = str_replace(static::ALLOWED_PARAM_SEPARATORS, ';', $input);
|
||||
|
||||
return explode(';', $input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,12 +62,12 @@ class PermissionResolver
|
|||
/**
|
||||
* PermissionResolver constructor.
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
public function __construct(bool $kernel_debug, string $kernel_cache_dir)
|
||||
{
|
||||
$cache_dir = $container->getParameter('kernel.cache_dir');
|
||||
$cache_dir = $kernel_cache_dir;
|
||||
//Here the cached structure will be saved.
|
||||
$this->cache_file = $cache_dir.'/permissions.php.cache';
|
||||
$this->is_debug = $container->getParameter('kernel.debug');
|
||||
$this->is_debug = $kernel_debug;
|
||||
|
||||
$this->permission_structure = $this->generatePermissionStructure();
|
||||
|
||||
|
@ -127,7 +127,7 @@ class PermissionResolver
|
|||
return $allowed;
|
||||
}
|
||||
|
||||
/** @var HasPermissionsInterface $parent */
|
||||
/** @var Group $parent */
|
||||
$parent = $user->getGroup();
|
||||
while (null !== $parent) { //The top group, has parent == null
|
||||
//Check if our current element gives a info about disallow/allow
|
||||
|
|
|
@ -30,12 +30,10 @@ use Twig\TwigFunction;
|
|||
|
||||
class LastUserExtension extends AbstractExtension
|
||||
{
|
||||
private $em;
|
||||
private $repo;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->repo = $em->getRepository(AbstractLogEntry::class);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@
|
|||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
{% if attach.picture %}
|
||||
{% if attach.secure and not is_granted('show_private', attach) %}
|
||||
{# Leave blank #}
|
||||
{% elseif attach.picture %}
|
||||
<a href="{{ attach | entityURL('file_view') }}" target="_blank" rel="noopener" data-no-ajax>
|
||||
<img class="img-fluid img-thumbnail thumbnail-sm" src="{{ attachment_thumbnail(attach, 'thumbnail_md') }}" alt="{% trans %}attachment.preview.alt{% endtrans %}" />
|
||||
</a>
|
||||
|
@ -60,7 +62,7 @@
|
|||
|
||||
{% if attach.secure %}
|
||||
<h6>
|
||||
<span class="badge badge-primary">
|
||||
<span class="badge badge-success">
|
||||
<i class="fas fa-fw fa-shield-alt"></i> {% trans %}attachment.secure{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
|
@ -90,7 +92,7 @@
|
|||
//Determine the table, so we can determine, how many entries there are already.
|
||||
$holder = $("#attachments_table");
|
||||
|
||||
var index = $holder.find(":input").length;
|
||||
var index = $holder.children("tbody").children("tr").length;
|
||||
var newForm = $holder.data("prototype");
|
||||
|
||||
//Increase the index
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
//Determine the table, so we can determine, how many entries there are already.
|
||||
$holder = $(btn).siblings("table");
|
||||
|
||||
var index = $holder.find(":input").length;
|
||||
var index = $holder.children("tbody").children("tr").length;
|
||||
var newForm = $holder.data("prototype");
|
||||
|
||||
//Increase the index
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue