Skip to content

Commit

Permalink
Merge pull request #5 from heimrichhannot/feature/delete-product
Browse files Browse the repository at this point in the history
Feature: delete product
  • Loading branch information
ericges authored Dec 13, 2023
2 parents e71c6ca + 2fe64ff commit 9af2ebf
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 70 deletions.
143 changes: 87 additions & 56 deletions src/DataContainer/ProductArchiveContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,37 @@

use Contao\BackendUser;
use Contao\Controller;
use Contao\CoreBundle\Exception\AccessDeniedException;
use Contao\CoreBundle\Security\ContaoCorePermissions;
use Contao\Database;
use Contao\DataContainer;
use Contao\Image;
use Contao\Input;
use Contao\RequestToken;
use Contao\StringUtil;
use Contao\System;
use HeimrichHannot\UtilsBundle\File\FileUtil;
use HeimrichHannot\UtilsBundle\Model\ModelUtil;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Security;

class ProductArchiveContainer
{
/**
* @var FileUtil
*/
protected $fileUtil;
protected FileUtil $fileUtil;

/**
* @var ModelUtil
*/
protected $modelUtil;
protected ModelUtil $modelUtil;

protected Security $security;

public function __construct(
FileUtil $fileUtil,
ModelUtil $modelUtil
ModelUtil $modelUtil,
Security $security
) {
$this->fileUtil = $fileUtil;
$this->modelUtil = $modelUtil;
$this->security = $security;
}

/**
Expand Down Expand Up @@ -61,8 +70,8 @@ public function getImageSizes()

public function checkPermission()
{
$user = \Contao\BackendUser::getInstance();
$database = \Contao\Database::getInstance();
$user = BackendUser::getInstance();
$database = Database::getInstance();

if ($user->isAdmin) {
return;
Expand All @@ -82,45 +91,41 @@ public function checkPermission()
$GLOBALS['TL_DCA']['tl_ml_product_archive']['config']['closed'] = true;
}

/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $objSession */
$objSession = \Contao\System::getContainer()->get('session');
/** @var SessionInterface $objSession */
$objSession = System::getContainer()->get('session');

// Check current action
switch (\Contao\Input::get('act')) {
switch (Input::get('act')) {
case 'create':
case 'select':
// Allow
break;

case 'edit':
// Dynamically add the record to the user profile
if (!\in_array(\Contao\Input::get('id'), $root, true)) {
/** @var \Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface $sessionBag */
if (!\in_array(Input::get('id'), $root, true)) {
/** @var AttributeBagInterface $sessionBag */
$sessionBag = $objSession->getBag('contao_backend');

$arrNew = $sessionBag->get('new_records');

if (\is_array($arrNew['tl_ml_product_archive']) && \in_array(\Contao\Input::get('id'),
if (\is_array($arrNew['tl_ml_product_archive']) && \in_array(Input::get('id'),
$arrNew['tl_ml_product_archive'], true)) {
// Add the permissions on group level
if ('custom' != $user->inherit) {
$objGroup = $database->execute(
'SELECT id, contao_media_library_bundles, contao_media_library_bundlep FROM tl_user_group WHERE id IN('.implode(
',',
array_map(
'intval',
$user->groups
)
).')'
);
if ('custom' != $user->inherit)
{
$sql = "SELECT id, contao_media_library_bundles, contao_media_library_bundlep FROM tl_user_group WHERE id IN(%s);";
$sql = sprintf($sql, implode(',', array_map('intval', $user->groups)));

$objGroup = $database->execute($sql);

while ($objGroup->next()) {
$arrModulep = \StringUtil::deserialize($objGroup->contao_media_library_bundlep);
$arrModulep = StringUtil::deserialize($objGroup->contao_media_library_bundlep);

if (\is_array($arrModulep) && \in_array('create', $arrModulep, true)) {
$arrModules = \StringUtil::deserialize($objGroup->contao_media_library_bundles,
$arrModules = StringUtil::deserialize($objGroup->contao_media_library_bundles,
true);
$arrModules[] = \Contao\Input::get('id');
$arrModules[] = Input::get('id');

$database->prepare('UPDATE tl_user_group SET contao_media_library_bundles=? WHERE id=?')->execute(
serialize($arrModules),
Expand All @@ -136,21 +141,19 @@ public function checkPermission()
->limit(1)
->execute($user->id);

$arrModulep = \StringUtil::deserialize($user->contao_media_library_bundlep);
$arrModulep = StringUtil::deserialize($user->contao_media_library_bundlep);

if (\is_array($arrModulep) && \in_array('create', $arrModulep, true)) {
$arrModules = \StringUtil::deserialize($user->contao_media_library_bundles, true);
$arrModules[] = \Contao\Input::get('id');
$arrModules = StringUtil::deserialize($user->contao_media_library_bundles, true);
$arrModules[] = Input::get('id');

$database->prepare('UPDATE tl_user SET contao_media_library_bundles=? WHERE id=?')->execute(
serialize($arrModules),
$user->id
);
$database->prepare('UPDATE tl_user SET contao_media_library_bundles=? WHERE id=?')
->execute(serialize($arrModules), $user->id);
}
}

// Add the new element to the user object
$root[] = \Contao\Input::get('id');
$root[] = Input::get('id');
$user->contao_media_library_bundles = $root;
}
}
Expand All @@ -159,14 +162,14 @@ public function checkPermission()
case 'copy':
case 'delete':
case 'show':
if (!\in_array(\Contao\Input::get('id'), $root, true)
|| ('delete' == \Contao\Input::get('act')
if (!\in_array(Input::get('id'), $root, true)
|| ('delete' == Input::get('act')
&& !$user->hasAccess(
'delete',
'contao_media_library_bundlep'
))
) {
throw new \Contao\CoreBundle\Exception\AccessDeniedException('Not enough permissions to '.\Contao\Input::get('act').' ml_product_archive ID '.\Contao\Input::get('id').'.');
throw new AccessDeniedException('Not enough permissions to '. Input::get('act').' ml_product_archive ID '. Input::get('id').'.');
}

break;
Expand All @@ -176,7 +179,7 @@ public function checkPermission()
case 'overrideAll':
$session = $objSession->all();

if ('deleteAll' == \Contao\Input::get('act') && !$user->hasAccess('delete',
if ('deleteAll' == Input::get('act') && !$user->hasAccess('delete',
'contao_media_library_bundlep')) {
$session['CURRENT']['IDS'] = [];
} else {
Expand All @@ -187,43 +190,71 @@ public function checkPermission()
break;

default:
if (\strlen(\Contao\Input::get('act'))) {
throw new \Contao\CoreBundle\Exception\AccessDeniedException('Not enough permissions to '.\Contao\Input::get('act').' ml_product_archives.');
if (\strlen(Input::get('act'))) {
throw new AccessDeniedException('Not enough permissions to '. Input::get('act').' ml_product_archives.');
}

break;
}
}

public function checkIncludeDelete(DataContainer $dc)
{
$record = Database::getInstance()
->prepare('SELECT * FROM tl_ml_product_archive WHERE id=?')
->limit(1)
->execute($dc->id)
;

if (!$record->numRows) {
return;
}

if ($record->includeDelete ?? false) {
$GLOBALS['TL_DCA']['tl_ml_product_archive']['fields']['redirectAfterDelete']['eval']['mandatory'] = true;
} else {
unset($GLOBALS['TL_DCA']['tl_ml_product_archive']['fields']['redirectAfterDelete']);
}
}

public function editHeader($row, $href, $label, $title, $icon, $attributes)
{
return \Contao\BackendUser::getInstance()->canEditFieldsOf('tl_ml_product_archive') ? '<a href="'.Controller::addToUrl(
$href.'&amp;id='.$row['id']
).'&rt='.\RequestToken::get().'" title="'.\StringUtil::specialchars($title).'"'.$attributes.'>'.\Image::getHtml(
$icon,
$label
).'</a> ' : \Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)).' ';
if ($this->security->isGranted(ContaoCorePermissions::USER_CAN_EDIT_FIELDS_OF_TABLE, 'tl_ml_product_archive'))
{
$anchor = sprintf(
'<a href="%s&rt=%s" title="%s" %s>%s</a> ',
Controller::addToUrl("$href&amp;id={$row['id']}"),
RequestToken::get(),
StringUtil::specialchars($title),
$attributes,
Image::getHtml($icon, $label)
);

return $anchor;
}

return Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)) . ' ';
}

public function copyArchive($row, $href, $label, $title, $icon, $attributes)
{
return \Contao\BackendUser::getInstance()->hasAccess('create',
return BackendUser::getInstance()->hasAccess('create',
'contao_media_library_bundlep') ? '<a href="'.Controller::addToUrl(
$href.'&amp;id='.$row['id']
).'&rt='.\RequestToken::get().'" title="'.\StringUtil::specialchars($title).'"'.$attributes.'>'.\Image::getHtml(
).'&rt='.RequestToken::get().'" title="'. StringUtil::specialchars($title).'"'.$attributes.'>'.Image::getHtml(
$icon,
$label
).'</a> ' : \Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)).' ';
).'</a> ' : Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)).' ';
}

public function deleteArchive($row, $href, $label, $title, $icon, $attributes)
{
return \Contao\BackendUser::getInstance()->hasAccess('delete',
return BackendUser::getInstance()->hasAccess('delete',
'contao_media_library_bundlep') ? '<a href="'.Controller::addToUrl(
$href.'&amp;id='.$row['id']
).'&rt='.\RequestToken::get().'" title="'.\StringUtil::specialchars($title).'"'.$attributes.'>'.\Image::getHtml(
).'&rt='.RequestToken::get().'" title="'.StringUtil::specialchars($title).'"'.$attributes.'>'.Image::getHtml(
$icon,
$label
).'</a> ' : \Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)).' ';
).'</a> ' : Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)).' ';
}
}
92 changes: 92 additions & 0 deletions src/EventListener/DeleteProductListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace HeimrichHannot\MediaLibraryBundle\EventListener;

use Contao\CoreBundle\Exception\InternalServerErrorHttpException;
use Contao\CoreBundle\Exception\RedirectResponseException;
use Contao\Input;
use Contao\Model;
use Contao\PageModel;
use HeimrichHannot\MediaLibraryBundle\Model\ProductArchiveModel;
use HeimrichHannot\ReaderBundle\Event\ReaderBeforeRenderEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Contracts\Translation\TranslatorInterface;

class DeleteProductListener
{
private RequestStack $requestStack;

private TranslatorInterface $translator;

private SessionInterface $session;

public function __construct(
RequestStack $requestStack,
TranslatorInterface $translator,
SessionInterface $session
)
{
$this->requestStack = $requestStack;
$this->translator = $translator;
$this->session = $session;
}

#[AsEventListener('huh.reader.event.reader_before_render')]
public function deleteProduct(ReaderBeforeRenderEvent $event): void
{
$item = $event->getItem();

if ($item->getDataContainer() !== 'tl_ml_product') {
return;
}

$request = $this->requestStack->getCurrentRequest();

if (!$request->isMethod(Request::METHOD_DELETE)
&& Input::post('_method') !== 'DELETE')
{
return;
}

/** @var class-string<Model> $modelClass */
$modelClass = Model::getClassFromTable('tl_ml_product');
$product = $modelClass::findByPk($item->getRawValue('id'));
if ($product === null) {
throw new BadRequestHttpException('Invalid product id');
}

/** @var ProductArchiveModel|null $productArchive */
$productArchive = $product->getRelated('pid');

if ($productArchive === null) {
throw new InternalServerErrorHttpException('Product archive not found');
}

if (!$productArchive->includeDelete) {
throw new MethodNotAllowedHttpException([Request::METHOD_DELETE], 'Delete not allowed');
}

if (!$product->delete()) {
throw new InternalServerErrorHttpException('Could not delete product');
}

$pageId = $productArchive->redirectAfterDelete;
$page = PageModel::findByPk($pageId);

if ($page === null) {
throw new InternalServerErrorHttpException('No redirect page found');
}

$this->session
->getFlashBag()
->add('success', $this->translator->trans('huh.mediaLibrary.product.delete.success', ['title' => $product->title]))
;

throw new RedirectResponseException($page->getAbsoluteUrl());
}
}
10 changes: 9 additions & 1 deletion src/FormType/MediaLibraryType.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,15 @@ public function onPrepareFormData(PrepareFormDataEvent $event): void
$event->getForm()->storeValues = '1';
$event->getForm()->targetTable = ProductModel::getTable();
}

parent::onPrepareFormData($event);
}

public function onStoreFormData(StoreFormDataEvent $event): void
{
if ($event->getForm()->ml_archive && ($archiveModel = ProductArchiveModel::findByPk($event->getForm()->ml_archive))) {
if ($event->getForm()->ml_archive
&& ($archiveModel = ProductArchiveModel::findByPk($event->getForm()->ml_archive)))
{
$data = $event->getData();
$data = array_intersect_key($data, array_flip(Database::getInstance()->getFieldNames(ProductModel::getTable())));
$data['pid'] = $event->getForm()->ml_archive;
Expand Down Expand Up @@ -140,10 +144,14 @@ public function onStoreFormData(StoreFormDataEvent $event): void

$event->setData($data);
}

parent::onStoreFormData($event);
}

public function onProcessFormData(ProcessFormDataEvent $event): void
{
parent::onProcessFormData($event);

if (!class_exists(HeimrichHannotFileCreditsBundle::class)) {
return;
}
Expand Down
2 changes: 2 additions & 0 deletions src/Model/ProductArchiveModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
* @property string $type
* @property string $additionalFields
* @property bool $keepProductTitleForDownloadItems
* @property bool $includeDelete
* @property bool $redirectAfterDelete
* @property bool $protected
*/
class ProductArchiveModel extends Model
Expand Down
Loading

0 comments on commit 9af2ebf

Please sign in to comment.