Skip to content

Commit

Permalink
[shopsys] product files support (#3288)
Browse files Browse the repository at this point in the history
  • Loading branch information
KennyDaren authored Aug 12, 2024
2 parents 43bfd57 + 0b969a9 commit 2af0e63
Show file tree
Hide file tree
Showing 35 changed files with 542 additions and 92 deletions.
3 changes: 3 additions & 0 deletions app/config/packages/overblog_dataloader.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ overblog_dataloader:
categoryChildrenBatchLoader:
alias: "category_children_batch_loader"
batch_load_fn: "@App\\FrontendApi\\Model\\Category\\CategoryChildrenBatchLoader:loadByCategories"
filesBatchLoader:
alias: "files_batch_loader"
batch_load_fn: "@Shopsys\\FrontendApiBundle\\Component\\Files\\FilesBatchLoader:loadByBatchData"
firstImageBatchLoader:
alias: "first_image_batch_loader"
batch_load_fn: "@Shopsys\\FrontendApiBundle\\Component\\Image\\FirstImageBatchLoader:loadByBatchData"
Expand Down
1 change: 1 addition & 0 deletions app/config/packages/paths.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ parameters:
shopsys.content_dir_name: 'content'
shopsys.data_fixtures.resources_dir: '%kernel.project_dir%/src/DataFixtures/resources'
shopsys.data_fixtures_images.resources_dir: '%shopsys.data_fixtures.resources_dir%/images/'
shopsys.data_fixtures_uploaded_files.resources_dir: '%shopsys.data_fixtures.resources_dir%/uploaded_files/'
shopsys.default_db_schema_filepath: '%shopsys.framework.resources_dir%/database/schema.sql'
shopsys.domain_config_filepath: '%kernel.project_dir%/config/domains.yaml'
shopsys.domain_images_dir: '/web%shopsys.domain_images_url_prefix%'
Expand Down
11 changes: 10 additions & 1 deletion app/config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ security:
- ROLE_HEUREKA_FULL
- ROLE_LANGUAGE_CONSTANTS_FULL
- ROLE_TRANSFER_VIEW
- ROLE_FILES_FULL
ROLE_ALL_VIEW:
- ROLE_ORDER_VIEW
- ROLE_CUSTOMER_VIEW
Expand Down Expand Up @@ -105,6 +106,7 @@ security:
- ROLE_HEUREKA_VIEW
- ROLE_LANGUAGE_CONSTANTS_VIEW
- ROLE_TRANSFER_VIEW
- ROLE_FILES_VIEW
ROLE_ORDER_FULL: [ROLE_ORDER_VIEW]
ROLE_CUSTOMER_FULL: [ROLE_CUSTOMER_VIEW]
ROLE_NEWSLETTER_FULL: [ROLE_NEWSLETTER_VIEW]
Expand Down Expand Up @@ -151,6 +153,7 @@ security:
ROLE_STOCK_FULL: [ROLE_STOCK_VIEW]
ROLE_HEUREKA_FULL: [ROLE_HEUREKA_VIEW]
ROLE_LANGUAGE_CONSTANTS_FULL: [ROLE_LANGUAGE_CONSTANTS_VIEW]
ROLE_FILES_FULL: [ROLE_FILES_VIEW]
# FE API ROLES
ROLE_API_ALL: [ROLE_API_CUSTOMER_SELF_MANAGE]

Expand Down Expand Up @@ -429,8 +432,14 @@ security:
- { path: ^/%admin_url%/constant/list/, roles: ROLE_LANGUAGE_CONSTANTS_VIEW }
# transfers
- { path: ^/%admin_url%/transfer/issue/list/, roles: ROLE_TRANSFER_VIEW }
# special paths for file manager in wysiwyg, product picker, grid, domain selector, login as user.
# uploaded files
- { path: ^/%admin_url%/uploaded-file/new, roles: ROLE_FILES_FULL }
- { path: ^/%admin_url%/uploaded-file/edit, roles: ROLE_FILES_FULL, methods: [POST] }
- { path: ^/%admin_url%/uploaded-file/delete, roles: ROLE_FILES_FULL }
- { path: ^/%admin_url%/uploaded-file/, roles: ROLE_FILES_VIEW }
# special paths for file manager in wysiwyg, file picker, product picker, grid, domain selector, login as user.
- { path: ^/%admin_url%/product-picker/, roles: ROLE_ADMIN }
- { path: ^/%admin_url%/file-picker/, roles: ROLE_ADMIN }
- { path: ^/%admin_url%/_grid/save-form/, roles: ROLE_ALL }
- { path: ^/%admin_url%/_grid/save-ordering/, roles: ROLE_ALL }
- { path: ^/%admin_url%/_grid/get-form/, roles: ROLE_ALL }
Expand Down
3 changes: 3 additions & 0 deletions app/config/packages/twig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ twig:
- '@ShopsysFramework/Admin/Form/Product/Price/pricesWithCalculatedSellingPricesType.html.twig'
- '@ShopsysFramework/Admin/Form/Product/Price/productPricesWithVatSelectType.html.twig'
- '@ShopsysFramework/Admin/Form/abstractFileuploadFields.html.twig'
- '@ShopsysFramework/Admin/Form/abstractMultiplePicker.html.twig'
- '@ShopsysFramework/Admin/Form/blogCategoriesType.html.twig'
- '@ShopsysFramework/Admin/Form/blogCategoryCheckboxType.html.twig'
- '@ShopsysFramework/Admin/Form/colorpickerFields.html.twig'
Expand All @@ -21,6 +22,8 @@ twig:
- '@ShopsysFramework/Admin/Form/imageuploadFields.html.twig'
- '@ShopsysFramework/Admin/Form/localizedFullWidth.html.twig'
- '@ShopsysFramework/Admin/Form/mailWhitelistFormTheme.html.twig'
- '@ShopsysFramework/Admin/Form/multiLocaleBasicFileuploadFields.html.twig'
- '@ShopsysFramework/Admin/Form/multiLocaleFileuploadFields.html.twig'
- '@ShopsysFramework/Admin/Form/orderItems.html.twig'
- '@ShopsysFramework/Admin/Form/orderlistFields.html.twig'
- '@ShopsysFramework/Admin/Form/parameterValueConversionList.html.twig'
Expand Down
11 changes: 8 additions & 3 deletions app/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,14 @@ services:

App\DataFixtures\Demo\ImageDataFixture:
arguments:
- '%shopsys.data_fixtures_images.resources_dir%'
- '%shopsys.image_dir%'
- '%shopsys.domain_images_dir%'
$dataFixturesImagesDirectory: '%shopsys.data_fixtures_images.resources_dir%'
$targetImagesDirectory: '%shopsys.image_dir%'
$targetDomainImagesDirectory: '%shopsys.domain_images_dir%'
tags: ['doctrine.fixture.orm']

App\DataFixtures\Demo\UploadedFileDataFixture:
arguments:
$dataFixturesFilesDirectory: '%shopsys.data_fixtures_uploaded_files.resources_dir%'
tags: ['doctrine.fixture.orm']

App\DataFixtures\Performance\CategoryDataFixture:
Expand Down
1 change: 1 addition & 0 deletions app/config/services_frontend_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ services:
Overblog\DataLoader\DataLoaderInterface $productsSellableByIdsBatchLoader: '@products_sellable_by_ids_batch_loader'
Overblog\DataLoader\DataLoaderInterface $productsByEntitiesBatchLoader: '@products_by_entities_batch_loader'
Overblog\DataLoader\DataLoaderInterface $imagesBatchLoader: '@images_batch_loader'
Overblog\DataLoader\DataLoaderInterface $filesBatchLoader: '@files_batch_loader'
Overblog\DataLoader\DataLoaderInterface $firstImageBatchLoader: '@first_image_batch_loader'
Overblog\DataLoader\DataLoaderInterface $readyCategorySeoMixesBatchLoader: '@ready_category_seo_mixes_batch_loader'
Overblog\DataLoader\DataLoaderInterface $categoryChildrenBatchLoader: '@category_children_batch_loader'
Expand Down
7 changes: 7 additions & 0 deletions app/config/uploaded_files.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@
types:
- name: default
multiple: false


- name: product
class: Shopsys\FrameworkBundle\Model\Product\Product
types:
- name: default
multiple: true
12 changes: 12 additions & 0 deletions app/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,14 @@ input EditCustomerUserPersonalDataInput {
telephone: String!
}

"Represents a downloadable file"
type File {
"Clickable text for a hyperlink"
anchorText: String!
"Url to download the file"
url: String!
}

"Represents a flag"
type Flag implements Hreflang & Slug & Breadcrumb & ProductListable {
"Hierarchy of the current element in relation to the structure"
Expand Down Expand Up @@ -866,6 +874,7 @@ type MainVariant implements Product & Hreflang & Breadcrumb & Slug {
description: String
"EAN"
ean: String
files: [File!]!
"List of flags"
flags: [Flag!]!
"The full name of the product, which consists of a prefix, name, and a suffix"
Expand Down Expand Up @@ -1491,6 +1500,7 @@ interface Product {
description: String
"EAN"
ean: String
files: [File!]!
"List of flags"
flags: [Flag!]!
"The full name of the product, which consists of a prefix, name, and a suffix"
Expand Down Expand Up @@ -1919,6 +1929,7 @@ type RegularProduct implements Product & Hreflang & Breadcrumb & Slug {
description: String
"EAN"
ean: String
files: [File!]!
"List of flags"
flags: [Flag!]!
"The full name of the product, which consists of a prefix, name, and a suffix"
Expand Down Expand Up @@ -2215,6 +2226,7 @@ type Variant implements Product & Hreflang & Breadcrumb & Slug {
description: String
"EAN"
ean: String
files: [File!]!
"List of flags"
flags: [Flag!]!
"The full name of the product, which consists of a prefix, name, and a suffix"
Expand Down
23 changes: 6 additions & 17 deletions app/src/Component/FileUpload/FileUpload.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace App\Component\FileUpload;

use App\Component\Image\ImageRepository;
use App\Component\UploadedFile\UploadedFileRepository;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\MountManager;
use Shopsys\FrameworkBundle\Component\Doctrine\Exception\UnexpectedTypeException;
Expand Down Expand Up @@ -33,7 +32,6 @@ class FileUpload extends BaseFileUpload implements ResetInterface
* @param \League\Flysystem\FilesystemOperator $filesystem
* @param \Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface $parameterBag
* @param \App\Component\Image\ImageRepository $imageRepository
* @param \App\Component\UploadedFile\UploadedFileRepository $uploadedFileRepository
*/
public function __construct(
$temporaryDir,
Expand All @@ -44,7 +42,6 @@ public function __construct(
FilesystemOperator $filesystem,
ParameterBagInterface $parameterBag,
private readonly ImageRepository $imageRepository,
private readonly UploadedFileRepository $uploadedFileRepository,
) {
parent::__construct(
$temporaryDir,
Expand All @@ -64,7 +61,7 @@ public function preFlushEntity(EntityFileUploadInterface $entity)
{
parent::preFlushEntity($entity);

if ($entity->getPosition() === null) {
if ($entity instanceof Image && $entity->getPosition() === null) {
$entity->setPosition($this->getPositionForNewEntity($entity));
}
}
Expand All @@ -86,19 +83,11 @@ private function getPositionForNewEntity(EntityFileUploadInterface $entity): int
return $this->positionByEntityAndType[$entityName][$entityId][$uploadEntityType][$type];
}

if ($uploadEntityType === 'image') {
$position = $this->imageRepository->getImagesCountByEntityIndexedById(
$entityName,
$entityId,
$type,
);
} else {
$position = $this->uploadedFileRepository->getUploadedFilesCountByEntityIndexedById(
$entityName,
$entityId,
$type,
);
}
$position = $this->imageRepository->getImagesCountByEntityIndexedById(
$entityName,
$entityId,
$type,
);

$this->positionByEntityAndType[$entityName][$entityId][$uploadEntityType][$type] = $position;

Expand Down
14 changes: 11 additions & 3 deletions app/src/Component/UploadedFile/UploadedFileFacade.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

/**
* @property \App\Component\UploadedFile\UploadedFileRepository $uploadedFileRepository
* @method __construct(\Doctrine\ORM\EntityManagerInterface $em, \Shopsys\FrameworkBundle\Component\UploadedFile\Config\UploadedFileConfig $uploadedFileConfig, \App\Component\UploadedFile\UploadedFileRepository $uploadedFileRepository, \League\Flysystem\FilesystemOperator $filesystem, \Shopsys\FrameworkBundle\Component\UploadedFile\UploadedFileLocator $uploadedFileLocator, \Shopsys\FrameworkBundle\Component\UploadedFile\UploadedFileFactoryInterface $uploadedFileFactory)
* @method __construct(\Doctrine\ORM\EntityManagerInterface $em, \Shopsys\FrameworkBundle\Component\UploadedFile\Config\UploadedFileConfig $uploadedFileConfig, \App\Component\UploadedFile\UploadedFileRepository $uploadedFileRepository, \League\Flysystem\FilesystemOperator $filesystem, \Shopsys\FrameworkBundle\Component\UploadedFile\UploadedFileLocator $uploadedFileLocator, \Shopsys\FrameworkBundle\Component\UploadedFile\UploadedFileFactoryInterface $uploadedFileFactory, \Shopsys\FrameworkBundle\Component\UploadedFile\UploadedFileRelationFactory $uploadedFileRelationFactory, \Shopsys\FrameworkBundle\Component\UploadedFile\UploadedFileRelationRepository $uploadedFileRelationRepository)
*/
class UploadedFileFacade extends BaseUploadedFileFacade
{
Expand All @@ -27,9 +27,17 @@ public function manageSingleFile(
$uploadedFiles = $uploadedFileData->uploadedFiles;
$uploadedFilenames = $uploadedFileData->uploadedFilenames;
$uploadedFileEntityConfig = $this->uploadedFileConfig->getUploadedFileEntityConfig($entity);
$orderedFiles = $uploadedFileData->orderedFiles;

$this->deleteAllUploadedFilesByEntity($entity);
$this->deleteRelationsByEntityAndUploadedFiles($entity, $orderedFiles, $type);

$this->uploadFile($entity, $uploadedFileEntityConfig->getEntityName(), $type, array_pop($uploadedFiles), array_pop($uploadedFilenames));
$this->uploadFile(
$entity,
$uploadedFileEntityConfig->getEntityName(),
$type,
array_pop($uploadedFiles),
array_pop($uploadedFilenames),
array_pop($uploadedFileData->names),
);
}
}
92 changes: 92 additions & 0 deletions app/src/DataFixtures/Demo/AbstractFileFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

namespace App\DataFixtures\Demo;

use Doctrine\ORM\EntityManagerInterface;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\MountManager;
use Shopsys\FrameworkBundle\Component\DataFixture\AbstractReferenceFixture;
use Shopsys\FrameworkBundle\Component\String\TransformString;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;

abstract class AbstractFileFixture extends AbstractReferenceFixture
{
/**
* @param \League\Flysystem\FilesystemOperator $filesystem
* @param \Symfony\Component\Filesystem\Filesystem $localFilesystem
* @param \League\Flysystem\MountManager $mountManager
* @param \Doctrine\ORM\EntityManagerInterface $em
*/
public function __construct(
protected readonly FilesystemOperator $filesystem,
protected readonly Filesystem $localFilesystem,
protected readonly MountManager $mountManager,
protected readonly EntityManagerInterface $em,
) {
}

/**
* @param string[] $sequences
* @throws \Doctrine\DBAL\Exception
*/
protected function syncDatabaseSequences(array $sequences): void
{
foreach ($sequences as $sequence) {
$parts = explode('.', $sequence);
list($table, $column) = $parts;

$this->em->getConnection()->executeStatement(
sprintf(
'SELECT SETVAL(pg_get_serial_sequence(\'%s\', \'%s\'), COALESCE((SELECT MAX(%s) FROM %s) + 1, 1), false)',
$table,
$column,
$column,
$table,
),
);
}
}

/**
* @param string[] $tables
* @throws \Doctrine\DBAL\Exception
*/
protected function truncateDatabaseTables(array $tables): void
{
if (count($tables) <= 0) {
return;
}

$this->em->getConnection()->executeStatement(
sprintf('TRUNCATE TABLE %s', implode(', ', $tables)),
);
}

/**
* @param string $origin
* @param string $target
*/
protected function moveFilesFromLocalFilesystemToFilesystem(string $origin, string $target): void
{
$finder = new Finder();
$finder->files()->in($origin);

foreach ($finder as $file) {
$filepath = TransformString::removeDriveLetterFromPath($file->getPathname());

if (!$this->localFilesystem->exists($filepath)) {
continue;
}

$newFilepath = $target . $file->getRelativePathname();

if ($this->filesystem->has($newFilepath)) {
$this->filesystem->delete($newFilepath);
}
$this->mountManager->copy('local://' . $filepath, 'main://' . $newFilepath);
}
}
}
Loading

0 comments on commit 2af0e63

Please sign in to comment.