Skip to content

Commit

Permalink
Merge pull request #456 from BitBagCommerce/feature/save-with-origina…
Browse files Browse the repository at this point in the history
…l-name

Add ability to save file while upload with original name instead of hash
  • Loading branch information
marekrzytki authored Jan 16, 2023
2 parents fcf7fd1 + 5917c42 commit 533fbdc
Show file tree
Hide file tree
Showing 17 changed files with 83 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
php: ["8.0", "7.4"]
symfony: ["^4.4", "^5.2"]
sylius: ["~1.9.0", "~1.10.0", "~1.11.0"]
node: [">=12.13.0"]
node: ["14.19"]
mysql: ["8.0"]

exclude:
Expand Down
20 changes: 10 additions & 10 deletions spec/Entity/MediaSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,26 @@
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Resource\Model\ResourceInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;

final class MediaSpec extends ObjectBehavior
{
function it_is_initializable(): void
public function it_is_initializable(): void
{
$this->shouldHaveType(Media::class);
}

function it_is_a_resource(): void
public function it_is_a_resource(): void
{
$this->shouldHaveType(ResourceInterface::class);
}

function it_implements_media_interface(): void
public function it_implements_media_interface(): void
{
$this->shouldHaveType(MediaInterface::class);
}

function it_allows_access_via_properties(): void
public function it_allows_access_via_properties(): void
{
$this->setCode('file');
$this->getCode()->shouldReturn('file');
Expand All @@ -47,7 +47,7 @@ function it_allows_access_via_properties(): void
$this->setPath('/media/video');
$this->getPath()->shouldReturn('/media/video');

$file = new File(__DIR__ . '/MediaSpec.php');
$file = new UploadedFile(__DIR__ . '/MediaSpec.php', 'originalName');

$this->setFile($file);
$this->getFile()->shouldReturn($file);
Expand All @@ -56,7 +56,7 @@ function it_allows_access_via_properties(): void
$this->getMimeType()->shouldReturn('video/mp4');
}

function it_toggles(): void
public function it_toggles(): void
{
$this->enable();
$this->isEnabled()->shouldReturn(true);
Expand All @@ -65,7 +65,7 @@ function it_toggles(): void
$this->isEnabled()->shouldReturn(false);
}

function it_associates_products(ProductInterface $firstProduct, ProductInterface $secondProduct): void
public function it_associates_products(ProductInterface $firstProduct, ProductInterface $secondProduct): void
{
$this->addProduct($firstProduct);
$this->hasProduct($firstProduct)->shouldReturn(true);
Expand All @@ -77,7 +77,7 @@ function it_associates_products(ProductInterface $firstProduct, ProductInterface
$this->hasProduct($firstProduct)->shouldReturn(false);
}

function it_associates_sections(SectionInterface $firstSection, SectionInterface $secondSection): void
public function it_associates_sections(SectionInterface $firstSection, SectionInterface $secondSection): void
{
$this->addSection($firstSection);
$this->hasSection($firstSection)->shouldReturn(true);
Expand All @@ -89,7 +89,7 @@ function it_associates_sections(SectionInterface $firstSection, SectionInterface
$this->hasSection($firstSection)->shouldReturn(false);
}

function it_associates_channels(ChannelInterface $firstChannel, ChannelInterface $secondChannel): void
public function it_associates_channels(ChannelInterface $firstChannel, ChannelInterface $secondChannel): void
{
$this->addChannel($firstChannel);
$this->hasChannel($firstChannel)->shouldReturn(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@
use PhpSpec\ObjectBehavior;
use Twig\Environment;

final class FileProviderSpec extends ObjectBehavior
final class GenericProviderSpec extends ObjectBehavior
{
function let(
public function let(
MediaUploaderInterface $uploader,
Environment $twigEngine
) {
$this->beConstructedWith($uploader, $twigEngine, '@Template', '/media/');
}

function it_is_initializable(): void
public function it_is_initializable(): void
{
$this->shouldHaveType(GenericProvider::class);
}

function it_implements_provider_interface(): void
public function it_implements_provider_interface(): void
{
$this->shouldHaveType(ProviderInterface::class);
}
Expand All @@ -40,7 +40,7 @@ public function it_renders(MediaInterface $media, Environment $twigEngine): void
{
$twigEngine->render('@Template', ['media' => $media, 'config' => []])->willReturn('content');

$this->render($media, ['config' => []])->shouldReturn('content');
$this->render($media, '@Template', ['config' => []])->shouldReturn('content');
}

public function it_uploads(MediaInterface $media, MediaUploaderInterface $uploader): void
Expand Down
8 changes: 5 additions & 3 deletions src/Downloader/ImageDownloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace BitBag\SyliusCmsPlugin\Downloader;

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Webmozart\Assert\Assert;

final class ImageDownloader implements ImageDownloaderInterface
Expand All @@ -24,18 +24,20 @@ public function __construct(Filesystem $filesystem)
$this->filesystem = $filesystem;
}

public function download(string $url): File
public function download(string $url): UploadedFile
{
$path = rtrim(sys_get_temp_dir(), \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR . md5(random_bytes(10));
$pathInfo = pathinfo($url);
$extension = $pathInfo['extension'] ?? null;
$originalName = $pathInfo['basename'] ?? '';

if (null !== $extension) {
$path .= '.' . $extension;
}
$contents = file_get_contents($url);
Assert::string($contents, sprintf('Content of file in path %s is null', $path));
$this->filesystem->dumpFile($path, $contents);

return new File($path);
return new UploadedFile($path, $originalName);
}
}
4 changes: 2 additions & 2 deletions src/Downloader/ImageDownloaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

namespace BitBag\SyliusCmsPlugin\Downloader;

use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;

interface ImageDownloaderInterface
{
public function download(string $url): File;
public function download(string $url): UploadedFile;
}
21 changes: 17 additions & 4 deletions src/Entity/Media.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Sylius\Component\Resource\Model\ToggleableTrait;
use Sylius\Component\Resource\Model\TranslatableTrait;
use Sylius\Component\Resource\Model\TranslationInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Webmozart\Assert\Assert;

class Media implements MediaInterface
Expand Down Expand Up @@ -43,7 +43,7 @@ class Media implements MediaInterface
/** @var string|null */
protected $path;

/** @var File|null */
/** @var UploadedFile|null */
protected $file;

/** @var string|null */
Expand All @@ -58,6 +58,9 @@ class Media implements MediaInterface
/** @var int|null */
protected $height;

/** @var bool */
protected $saveWithOriginalName = false;

public function __construct()
{
$this->initializeTranslationsCollection();
Expand Down Expand Up @@ -101,12 +104,12 @@ public function setPath(?string $path): void
$this->path = $path;
}

public function getFile(): ?File
public function getFile(): ?UploadedFile
{
return $this->file;
}

public function setFile(?File $file): void
public function setFile(?UploadedFile $file): void
{
$this->file = $file;
}
Expand Down Expand Up @@ -211,6 +214,16 @@ public function setHeight(?int $height): void
$this->height = $height;
}

public function getSaveWithOriginalName(): bool
{
return $this->saveWithOriginalName;
}

public function setSaveWithOriginalName(bool $saveWithOriginalName): void
{
$this->saveWithOriginalName = $saveWithOriginalName;
}

/**
* @return MediaTranslationInterface|TranslationInterface
*/
Expand Down
10 changes: 7 additions & 3 deletions src/Entity/MediaInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Sylius\Component\Resource\Model\ResourceInterface;
use Sylius\Component\Resource\Model\ToggleableInterface;
use Sylius\Component\Resource\Model\TranslatableInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;

interface MediaInterface extends
ResourceInterface,
Expand All @@ -41,9 +41,9 @@ public function getPath(): ?string;

public function setPath(?string $path): void;

public function getFile(): ?File;
public function getFile(): ?UploadedFile;

public function setFile(?File $file): void;
public function setFile(?UploadedFile $file): void;

public function hasFile(): bool;

Expand Down Expand Up @@ -80,4 +80,8 @@ public function setWidth(?int $width): void;
public function getHeight(): ?int;

public function setHeight(?int $height): void;

public function getSaveWithOriginalName(): bool;

public function setSaveWithOriginalName(bool $saveWithOriginalName): void;
}
4 changes: 2 additions & 2 deletions src/Fixture/Factory/MediaFixtureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use BitBag\SyliusCmsPlugin\Repository\MediaRepositoryInterface;
use BitBag\SyliusCmsPlugin\Resolver\MediaProviderResolverInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;

final class MediaFixtureFactory implements FixtureFactoryInterface
{
Expand Down Expand Up @@ -88,7 +88,7 @@ private function createMedia(string $code, array $mediaData): void
$media->setType($mediaData['type']);
$media->setCode($code);
$media->setEnabled($mediaData['enabled']);
$media->setFile(new File($mediaData['path']));
$media->setFile(new UploadedFile($mediaData['path'], $mediaData['original_name']));

$this->mediaProviderResolver->resolveProvider($media)->upload($media);

Expand Down
1 change: 1 addition & 0 deletions src/Fixture/MediaFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ protected function configureOptionsNode(ArrayNodeDefinition $optionsNode): void
->integerNode('number')->defaultNull()->end()
->scalarNode('type')->isRequired()->cannotBeEmpty()->end()
->scalarNode('path')->isRequired()->cannotBeEmpty()->end()
->scalarNode('original_name')->isRequired()->cannotBeEmpty()->end()
->booleanNode('enabled')->defaultTrue()->end()
->arrayNode('productCodes')->scalarPrototype()->end()->end()
->arrayNode('sections')->scalarPrototype()->end()->end()
Expand Down
3 changes: 3 additions & 0 deletions src/Form/Type/MediaType.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
->add('enabled', CheckboxType::class, [
'label' => 'bitbag_sylius_cms_plugin.ui.enabled',
])
->add('saveWithOriginalName', CheckboxType::class, [
'label' => 'bitbag_sylius_cms_plugin.ui.save_with_original_name',
])
->add('products', ProductAutocompleteChoiceType::class, [
'label' => 'bitbag_sylius_cms_plugin.ui.products',
'multiple' => true,
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/api_resources/Media.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<property name="enabled" identifier="false" writable="false"/>
<property name="width" identifier="false" writable="false"/>
<property name="height" identifier="false" writable="false"/>
<property name="saveWithOriginalName" identifier="false" writable="false"/>
<property name="sections" identifier="false" writable="false"/>
<property name="products" identifier="false" writable="false"/>
<property name="channels" identifier="false" writable="false"/>
Expand Down
3 changes: 3 additions & 0 deletions src/Resources/config/serialization/Media.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
<attribute name="height">
<group>shop:cms:read</group>
</attribute>
<attribute name="saveWithOriginalName">
<group>shop:cms:read</group>
</attribute>
<attribute name="sections">
<group>shop:cms:read</group>
</attribute>
Expand Down
1 change: 1 addition & 0 deletions src/Resources/translations/messages.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ bitbag_sylius_cms_plugin:
empty_name: Empty name
publish_at: Publish at
page_will_be_publish_at: This page will be publish at
save_with_original_name: Save with original name
1 change: 1 addition & 0 deletions src/Resources/translations/messages.pl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ bitbag_sylius_cms_plugin:
empty_name: Brak nazwy
publish_at: Opublikuj
page_will_be_publish_at: Strona zostanie opublikowana
save_with_original_name: Zapisz z oryginalną nazwą
9 changes: 5 additions & 4 deletions src/Resources/views/Media/Crud/_form.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
{{ form_row(form.type) }}
{{ form_row(form.file) }}
{{ form_row(form.enabled) }}
{{ form_row(form.saveWithOriginalName) }}
{{ form_row(form.products) }}
{{ form_row(form.sections) }}
{{ form_row(form.channels) }}

<a
href="#"
class="ui labeled button icon primary bitbag-cms-resource-preview"
data-bb-cms-preview-btn
<a
href="#"
class="ui labeled button icon primary bitbag-cms-resource-preview"
data-bb-cms-preview-btn
data-url="{{ path('bitbag_sylius_cms_plugin_admin_media_preview', {'id': form.vars.data.id}) }}"
>
<i class="eye icon"></i>
Expand Down
16 changes: 12 additions & 4 deletions src/Uploader/MediaUploader.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ public function upload(MediaInterface $media, string $pathPrefix): void
$this->remove($media->getPath());
}

$originalName = null;
if ($media->getSaveWithOriginalName()) {
$originalName = $file->getClientOriginalName();
}

do {
$hash = bin2hex(random_bytes(16));
$path = $this->expandPath($hash . '.' . $file->guessExtension(), $pathPrefix);
$path = $this->expandPath($hash . '.' . $file->guessExtension(), $pathPrefix, $originalName);
} while ($this->filesystem->has($path));

$media->setPath('/' . $path);
Expand Down Expand Up @@ -71,14 +76,17 @@ public function remove(string $path): bool
return false;
}

private function expandPath(string $path, string $pathPrefix): string
{
private function expandPath(
string $path,
string $pathPrefix,
?string $originalName = null
): string {
return sprintf(
'%s/%s/%s/%s',
$pathPrefix,
substr($path, 0, 2),
substr($path, 2, 2),
substr($path, 4)
$originalName ?? substr($path, 4)
);
}

Expand Down
Loading

0 comments on commit 533fbdc

Please sign in to comment.