Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Bridge/Sylius/config/app/twig_hooks/media/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
return static function (ContainerConfigurator $container): void {
$container->extension('sylius_twig_hooks', [
'hooks' => [
'joli_media_sylius_admin.media.index' => [
'modal' => [
'template' => '@JoliMediaSylius/admin/media/index/modal/move_directory_modal.html.twig',
'priority' => 100,
],
],

'joli_media_sylius_admin.media.index.content' => [
'header' => [
'template' => '@JoliMediaSylius/admin/media/index/content/header.html.twig',
Expand Down
38 changes: 38 additions & 0 deletions src/Bridge/Sylius/src/Admin/Controller/MediaAdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,44 @@ public function renameDirectory(Request $request): Response
}
}

#[Route(path: '/move-directory', name: 'move_directory', methods: [Request::METHOD_POST])]
public function moveDirectory(Request $request): Response
{
$from = Resolver::normalizePath($request->request->getString('from'));
$to = Resolver::normalizePath($request->request->getString('to'));

$csrfToken = $request->request->getString('_csrf_token');

if (!$this->csrfTokenManager->isTokenValid(new CsrfToken('media_move_directory', $csrfToken))) {
$this->addFlash('error', 'Invalid CSRF token');

return $this->redirect($request->headers->get('referer') ?? $this->generateUrl('joli_media_sylius_admin_explore'));
}

if (!$from) {
$this->addFlash('error', 'Missing parameters');

return $this->redirect($request->headers->get('referer') ?? $this->generateUrl('joli_media_sylius_admin_explore'));
}

try {
$target = $to ? \sprintf('%s/%s', $to, basename($from)) : basename($from);
$this->getOriginalStorage()->moveFolder($from, $target);

$this->addFlash('success', $this->translator->trans(
'directory.move_success',
['%from%' => $from, '%to%' => $target],
'JoliMediaSyliusBundle'
));

return $this->redirectAfterRename($request, $from, $target);
} catch (\Throwable $e) {
$this->addFlash('error', $e->getMessage());

return $this->redirect($request->headers->get('referer') ?? $this->generateUrl('joli_media_sylius_admin_explore'));
}
}

#[Route(path: '/rename', name: 'rename', methods: [Request::METHOD_POST])]
public function rename(Request $request): Response
{
Expand Down
4 changes: 4 additions & 0 deletions src/Bridge/Sylius/src/Admin/Grid/MediaGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public function __invoke(GridBuilderInterface $gridBuilder): void
->setLabel($this->trans('action.rename_directory'))
->setIcon('tabler:pencil')
->setTemplate('@JoliMediaSylius/admin/media/grid/action/rename_directory.html.twig'),
Action::create('move_directory', 'custom')
->setLabel($this->trans('action.move_directory'))
->setIcon('fa7-solid:folder-tree')
->setTemplate('@JoliMediaSylius/admin/media/grid/action/move_directory.html.twig'),
Action::create('create_directory', 'custom')
->setLabel($this->trans('directory.create'))
->setIcon('tabler:folder-plus')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
{% import ['@SyliusBootstrapAdminUi/shared/helper/button.html.twig', '@SyliusAdmin/shared/helper/button.html.twig'] as button %}

{% set message = action.label %}
{% if message is empty %}
{% set message = 'sylius.ui.create' %}
{% endif %}

<a href="#" class="btn" data-component="directory-create">
{{ ux_icon(action.icon|default('tabler:plus'), {'class': 'icon dropdown-item-icon'}) }}
{{ message|trans }}
</a>
{{ button.default({
url: '#',
icon: action.icon|default('tabler:plus'),
icon_class: 'icon dropdown-item-icon',
icon_only: true,
text: message|trans,
attr: {
'data-bs-toggle': 'tooltip',
'data-bs-title': message|trans,
'data-component': 'directory-create'
}
}) }}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
id: key,
modal_id: 'delete-directory-modal-' ~ random(),
path: path('joli_media_sylius_admin_delete_directory', {'key': key}),
icon_only: false,
icon_only: true,
label: action.label,
}) }}
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% import ['@SyliusBootstrapAdminUi/shared/helper/button.html.twig', '@SyliusAdmin/shared/helper/button.html.twig'] as button %}

{% set key = app.request.attributes.get('key', '') %}

{% if key != '' %}
{% set message = action.label %}
{% if message is empty %}
{% set message = 'sylius.ui.update' %}
{% endif %}

<span data-media-key="{{ key }}">
{{ button.default({
url: path('joli_media_sylius_admin_choose'),
icon: action.icon|default('fa7-solid:folder-tree'),
icon_class: 'icon dropdown-item-icon',
icon_only: true,
text: message|trans,
attr: {
'data-bs-toggle': 'tooltip',
'data-bs-title': message|trans,
'data-folder': key|joli_media_admin_dirname,
'data-component': 'media-move'
}
}) }}
</span>
{% endif %}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% import ['@SyliusBootstrapAdminUi/shared/helper/button.html.twig', '@SyliusAdmin/shared/helper/button.html.twig'] as button %}

{% set key = app.request.attributes.get('key', '') %}

{% if key != '' %}
Expand All @@ -6,8 +8,18 @@
{% set message = 'sylius.ui.update' %}
{% endif %}

<a href="#" class="btn directory-rename-header-btn" data-component="directory-rename">
{{ ux_icon(action.icon|default('tabler:pencil'), {'class': 'icon dropdown-item-icon'}) }}
{{ message|trans }}
</a>
{{ button.default({
url: '#',
icon: action.icon|default('tabler:pencil'),
icon_class: 'icon dropdown-item-icon',
icon_only: true,
text: message|trans,
class: 'directory-rename-header-btn',
attr: {
'data-bs-toggle': 'tooltip',
'data-bs-title': message|trans,
'data-component': 'directory-rename'
}
}) }}
{% endif %}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% import '@JoliMediaSylius/admin/shared/helper/move_directory_modal.html.twig' as modal %}

{% set directory = hookable_metadata.context.key %}

{{ modal.render(directory) }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{% macro render(directoryPath) %}
{% trans_default_domain 'JoliMediaSyliusBundle' %}

<div id="modal-folder-choice" class="modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="mb-3 d-flex justify-content-between align-items-center">
<div class="folder-modal-breadcrumb">
{% if directoryPath %}
{% set parts = directoryPath|split('/') %}
<a href="{{ path('joli_media_sylius_admin_choose') }}" data-folder-path="">
{{ 'media_library'|trans }}
</a>
{% for part in parts %}
{% if part %}
<span class="breadcrumb-separator">/</span>
{% set path_so_far = parts|slice(0, loop.index)|join('/') %}
{% if loop.last %}
<span class="breadcrumb-current">{{ part }}</span>
{% else %}
<a href="{{ path('joli_media_sylius_admin_choose', { key: path_so_far }) }}" data-folder-path="{{ path_so_far }}">{{ part }}</a>
{% endif %}
{% endif %}
{% endfor %}
{% else %}
<a href="{{ path('joli_media_sylius_admin_choose') }}" data-folder-path="">
{{ 'media_library'|trans }}
</a>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-current">{{ 'root'|trans }}</span>
{% endif %}
</div>
<button type="button" class="btn btn-primary" data-component="folder-create">
{{ ux_icon('tabler:folder-plus') }}
{{ 'directory.create'|trans }}
</button>
</div>
<form method="post" action="{{ path('joli_media_sylius_admin_create_directory') }}" class="folder-create-form d-none mb-3">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('media_create_directory') }}">
<input type="hidden" name="parentPath" value="{{ directoryPath|default('') }}">
<div class="input-group">
<input type="text" name="name" class="form-control folder-create-input" placeholder="{{ 'directory.create'|trans }}">
<button type="submit" class="btn btn-primary">{{ 'action.create'|trans }}</button>
<button type="button" class="btn btn-secondary folder-create-cancel">{{ 'action.cancel'|trans }}</button>
</div>
</form>
<div class="folder-list-container"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
{{ 'action.cancel'|trans }}
</button>
<a
href="#"
class="btn btn-primary folder-move-btn"
data-folder-path=""
>
{{ 'action.move_to_this_directory'|trans }}
</a>
</div>
</div>
</div>
</div>

<form method="post" action="{{ path('joli_media_sylius_admin_move_directory') }}" id="move-form" class="d-none">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('media_move_directory') }}">
<input type="hidden" name="from" value="{{ directoryPath }}">
<input type="hidden" name="to" id="move_to" value="">
</form>
{% endmacro %}
2 changes: 2 additions & 0 deletions src/Bridge/Sylius/translations/JoliMediaSyliusBundle.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ action:
rename_directory: 'Rename directory'
cancel: 'Cancel'
entity_actions: 'Actions'
move_directory: 'Move directory'
move_file: 'Move this file'
move_to_this_directory: 'Move to this directory'
search: 'Search'
Expand All @@ -26,6 +27,7 @@ directory:
name: 'Directory name'
name_required: 'Directory name is required'
rename_success: 'The directory "%from%" was successfully renamed to "%to%"'
move_success: 'The directory "%from%" was successfully moved to "%to%".'
media:
add: 'Add media'
dimensions: 'Dimensions'
Expand Down
2 changes: 2 additions & 0 deletions src/Bridge/Sylius/translations/JoliMediaSyliusBundle.fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ action:
rename_directory: 'Renommer le dossier'
cancel: 'Annuler'
entity_actions: 'Actions'
move_directory: 'Déplacer ce dossier'
move_file: 'Déplacer ce fichier'
move_to_this_directory: 'Déplacer dans ce répertoire'
search: 'Rechercher'
Expand All @@ -25,6 +26,7 @@ directory:
create_failure: 'Échec de la création du répertoire "%directory%" : %error%'
name_required: 'Le nom du répertoire est requis'
rename_success: 'Le répertoire %from% a été renommé avec succès en %to%.'
move_success: 'Le répertoire "%from%" a été déplacé avec succès vers "%to%".'
media:
add: 'Ajouter un média'
dimensions: 'Dimensions'
Expand Down
1 change: 1 addition & 0 deletions src/Bridge/src/Twig/JoliMediaAdminExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function __construct(
public function getFilters(): array
{
return [
new TwigFilter('joli_media_admin_dirname', 'dirname'),
new TwigFilter('joli_media_admin_basename', 'basename'),
new TwigFilter('joli_media_admin_readable_filesize', $this->getReadableFileSize(...)),
];
Expand Down
30 changes: 30 additions & 0 deletions tests/Bridge/Sylius/Admin/Controller/MediaAdminControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,29 @@ public function testCreateDirectoryFailsWhenEmptyName(): void
$this->assertSelectorTextContains('[data-test-sylius-flash-message]', 'Directory name is required');
}

public function testMoveDirectoryFromSubdirectoryToRoot(): void
{
$crawler = $this->client->request(Request::METHOD_GET, '/sylius-admin/media/explore/sub/folder');
$this->assertResponseIsSuccessful();

$form = $this->getMoveDirectoryForm($crawler);

$phpValues = $form->getPhpValues();
$phpValues['to'] = '';

$this->client->request($form->getMethod(), $form->getUri(), $phpValues);

$this->assertResponseRedirects('/sylius-admin/media/explore/folder');

// I should be redirected to the new directory path
$this->client->followRedirect();
$this->assertResponseIsSuccessful();

// Test flash message
$this->assertSelectorExists('[data-test-sylius-flash-message]');
$this->assertSelectorTextContains('[data-test-sylius-flash-message]', 'The directory "sub/folder" was successfully moved to "folder".');
}

protected static function getKernelClass(): string
{
return Kernel::class;
Expand Down Expand Up @@ -561,6 +584,13 @@ private function getCreateDirectoryForm(Crawler $crawler): Form
return $crawler->filter('form[data-component="directory-create-form"]')->form();
}

private function getMoveDirectoryForm(Crawler $crawler): Form
{
$this->assertSelectorExists('form[id="move-form"]');

return $crawler->filter('form[id="move-form"]')->form();
}

private function createTemporaryFile(): string
{
return tempnam(sys_get_temp_dir(), 'upload-test');
Expand Down
Loading