. */ declare(strict_types=1); namespace App\DataTables; use App\DataTables\Column\LocaleDateTimeColumn; use App\DataTables\Column\PrettyBoolColumn; use App\DataTables\Column\RowClassColumn; use App\DataTables\Filters\AttachmentFilter; use App\Entity\Attachments\Attachment; use App\Services\Attachments\AttachmentManager; use App\Services\Attachments\AttachmentURLGenerator; use App\Services\ElementTypeNameGenerator; use App\Services\EntityURLGenerator; use Doctrine\ORM\QueryBuilder; use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider; use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapter; use Omines\DataTablesBundle\Column\NumberColumn; use Omines\DataTablesBundle\Column\TextColumn; use Omines\DataTablesBundle\DataTable; use Omines\DataTablesBundle\DataTableTypeInterface; use Symfony\Contracts\Translation\TranslatorInterface; final class AttachmentDataTable implements DataTableTypeInterface { public function __construct(private readonly TranslatorInterface $translator, private readonly EntityURLGenerator $entityURLGenerator, private readonly AttachmentManager $attachmentHelper, private readonly AttachmentURLGenerator $attachmentURLGenerator, private readonly ElementTypeNameGenerator $elementTypeNameGenerator) { } public function configure(DataTable $dataTable, array $options): void { $dataTable->add('dont_matter', RowClassColumn::class, [ 'render' => function ($value, Attachment $context): string { //Mark attachments yellow which have an internal file linked that doesn't exist if($context->hasInternal() && !$this->attachmentHelper->isInternalFileExisting($context)){ return 'table-warning'; } return ''; //Default coloring otherwise }, ]); $dataTable->add('picture', TextColumn::class, [ 'label' => '', 'className' => 'no-colvis', 'render' => function ($value, Attachment $context): string { if ($context->isPicture() && $this->attachmentHelper->isInternalFileExisting($context)) { $title = htmlspecialchars($context->getName()); if ($context->getFilename()) { $title .= ' ('.htmlspecialchars($context->getFilename()).')'; } return sprintf( '%s', 'Part image', $this->attachmentURLGenerator->getThumbnailURL($context), $this->attachmentURLGenerator->getThumbnailURL($context, 'thumbnail_md'), 'img-fluid hoverpic', $title ); } return ''; }, ]); $dataTable->add('id', NumberColumn::class, [ 'label' => $this->translator->trans('part.table.id'), 'visible' => false, ]); $dataTable->add('name', TextColumn::class, [ 'label' => 'attachment.edit.name', 'orderField' => 'NATSORT(attachment.name)', ]); $dataTable->add('attachment_type', TextColumn::class, [ 'label' => 'attachment.table.type', 'field' => 'attachment_type.name', 'orderField' => 'NATSORT(attachment_type.name)', 'render' => fn($value, Attachment $context): string => sprintf( '%s', $this->entityURLGenerator->editURL($context->getAttachmentType()), htmlspecialchars((string) $value) ), ]); $dataTable->add('element', TextColumn::class, [ 'label' => 'attachment.table.element', //'propertyPath' => 'element.name', 'render' => fn($value, Attachment $context): string => sprintf( '%s', $this->entityURLGenerator->infoURL($context->getElement()), $this->elementTypeNameGenerator->getTypeNameCombination($context->getElement(), true) ), ]); $dataTable->add('internal_link', TextColumn::class, [ 'label' => 'attachment.table.internal_file', 'propertyPath' => 'filename', 'render' => function ($value, Attachment $context) { if ($this->attachmentHelper->isInternalFileExisting($context)) { return sprintf( '%s', $this->entityURLGenerator->viewURL($context), htmlspecialchars($value) ); } return $value; } ]); $dataTable->add('external_link', TextColumn::class, [ 'label' => 'attachment.table.external_link', 'propertyPath' => 'host', 'render' => function ($value, Attachment $context) { if ($context->hasExternal()) { return sprintf( '%s', htmlspecialchars((string) $context->getExternalPath()), htmlspecialchars($value) ); } return $value; } ]); $dataTable->add('filesize', TextColumn::class, [ 'label' => $this->translator->trans('attachment.table.filesize'), 'render' => function ($value, Attachment $context) { if (!$context->hasInternal()) { return sprintf( ' %s ', $this->translator->trans('attachment.external_only') ); } if ($this->attachmentHelper->isInternalFileExisting($context)) { return sprintf( ' %s ', $this->attachmentHelper->getHumanFileSize($context) ); } return sprintf( ' %s ', $this->translator->trans('attachment.file_not_found') ); }, ]); $dataTable ->add('addedDate', LocaleDateTimeColumn::class, [ 'label' => 'part.table.addedDate', 'visible' => false, ]) ->add('lastModified', LocaleDateTimeColumn::class, [ 'label' => 'part.table.lastModified', 'visible' => false, ]); $dataTable->add('show_in_table', PrettyBoolColumn::class, [ 'label' => 'attachment.edit.show_in_table', 'visible' => false, ]); $dataTable->add('isPicture', PrettyBoolColumn::class, [ 'label' => 'attachment.edit.isPicture', 'visible' => false, 'propertyPath' => 'picture', ]); $dataTable->add('is3DModel', PrettyBoolColumn::class, [ 'label' => 'attachment.edit.is3DModel', 'visible' => false, 'propertyPath' => '3dmodel', ]); $dataTable->add('isBuiltin', PrettyBoolColumn::class, [ 'label' => 'attachment.edit.isBuiltin', 'visible' => false, 'propertyPath' => 'builtin', ]); $dataTable->createAdapter(ORMAdapter::class, [ 'entity' => Attachment::class, 'query' => function (QueryBuilder $builder): void { $this->getQuery($builder); }, 'criteria' => [ function (QueryBuilder $builder) use ($options): void { $this->buildCriteria($builder, $options); }, new SearchCriteriaProvider(), ], ]); } private function getQuery(QueryBuilder $builder): void { $builder->select('attachment') ->addSelect('attachment_type') //->addSelect('element') ->from(Attachment::class, 'attachment') ->leftJoin('attachment.attachment_type', 'attachment_type'); //->leftJoin('attachment.element', 'element'); } private function buildCriteria(QueryBuilder $builder, array $options): void { //We do the most stuff here in the filter class if (isset($options['filter'])) { if(!$options['filter'] instanceof AttachmentFilter) { throw new \RuntimeException('filter must be an instance of AttachmentFilter!'); } $filter = $options['filter']; $filter->apply($builder); } } }