Skip to content

Commit

Permalink
Merge branch 'release/2.22.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
adamwaclawczyk committed May 8, 2023
2 parents 4d4a5dd + bb58b89 commit 809cb3f
Show file tree
Hide file tree
Showing 20 changed files with 349 additions and 28 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [2.22.0] - 2023-05-08
### Fixed
- Get product title method ([#270](https://github.com/SnowdogApps/magento2-menu/pull/270))
- Category Child node without parent category chosen makes menu disappear (DEV-99318)

### Changed
- Change Custom URL without URL content to not clickable (DEV-99301)

### Added
- Error skipping mechanism for some exceptions ([#271](https://github.com/SnowdogApps/magento2-menu/pull/271))
- Required prop for category child field (DEV-99318)
- Display a message indicating success or error after saving the menu. #274

## [2.21.0] - 2023-04-03
### Fixed
- Reset button doesn't reset menu node structure ([#256](https://github.com/SnowdogApps/magento2-menu/pull/256))
Expand Down
3 changes: 2 additions & 1 deletion Controller/Adminhtml/Menu/ImportPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Snowdog\Menu\Model\ImportExport\File\Upload as FileUpload;
use Snowdog\Menu\Model\ImportExport\Processor\Import as ImportProcessor;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Validator\ValidationAggregateError;
use Throwable;

class ImportPost extends Action implements HttpPostActionInterface
{
Expand Down Expand Up @@ -67,7 +68,7 @@ public function execute()
$exception->flush();
} catch (ValidatorException $exception) {
$this->messageManager->addErrorMessage($exception->getMessage());
} catch (Exception $exception) {
} catch (Exception|Throwable $exception) {
$this->logger->critical($exception);
$this->messageManager->addErrorMessage(__('An error occurred while importing menu.'));
}
Expand Down
37 changes: 33 additions & 4 deletions Controller/Adminhtml/Menu/Save.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@

namespace Snowdog\Menu\Controller\Adminhtml\Menu;

use Exception;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Phrase;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;
use Snowdog\Menu\Api\MenuRepositoryInterface;
use Snowdog\Menu\Api\Data\MenuInterface;
use Snowdog\Menu\Controller\Adminhtml\MenuAction;
Expand Down Expand Up @@ -40,19 +45,26 @@ class Save extends MenuAction implements HttpPostActionInterface
*/
private $storeManager;

/**
* @var LoggerInterface
*/
private $logger;

public function __construct(
Context $context,
MenuRepositoryInterface $menuRepository,
MenuFactory $menuFactory,
CloneRequestProcessor $cloneRequestProcessor,
MenuHydrator $hydrator,
MenuSaveRequestProcessor $menuSaveRequestProcessor,
StoreManagerInterface $storeManager
StoreManagerInterface $storeManager,
LoggerInterface $logger
) {
$this->cloneRequestProcessor = $cloneRequestProcessor;
$this->hydrator = $hydrator;
$this->menuSaveRequestProcessor = $menuSaveRequestProcessor;
$this->storeManager = $storeManager;
$this->logger = $logger;

parent::__construct($context, $menuRepository, $menuFactory);
}
Expand All @@ -68,10 +80,8 @@ public function execute()
$nodes = $nodes ? json_decode($nodes, true) : [];

$this->hydrator->mapRequest($menu, $request);
$this->menuRepository->save($menu);
$menu->saveStores($this->getStores());

$this->menuSaveRequestProcessor->saveData($menu, $nodes);
$this->processSave($menu, $nodes);

return $this->processRedirect($menu);
}
Expand Down Expand Up @@ -106,4 +116,23 @@ private function getStores(): array

return $stores;
}

private function processSave(MenuInterface $menu, $nodes): void
{
try {
$this->menuRepository->save($menu);
$menu->saveStores($this->getStores());

$this->menuSaveRequestProcessor->saveData($menu, $nodes);

if (empty($this->messageManager->getMessages()->getErrors())) {
$this->messageManager->addSuccessMessage(new Phrase('Menu has been saved successfully.'));
}
} catch (AlreadyExistsException|CouldNotSaveException $e) {
$this->messageManager->addErrorMessage(new Phrase('Could not save Menu: %1', [$e->getMessage()]));
} catch (Exception $e) {
$this->logger->critical($e);
$this->messageManager->addErrorMessage(new Phrase('An error occurred while saving menu.'));
}
}
}
45 changes: 41 additions & 4 deletions Model/ImportExport/Processor/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

namespace Snowdog\Menu\Model\ImportExport\Processor;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Snowdog\Menu\Api\Data\MenuInterface;
use Snowdog\Menu\Model\ImportExport\Processor\ExtendedFields;
use Snowdog\Menu\Model\ImportExport\Processor\Import\InvalidNodes as InvalidNodesProcessor;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Menu as MenuProcessor;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Node as NodeProcessor;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Validator\ValidationAggregateError;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Validator\ValidationException;

class Import
{
Expand All @@ -27,19 +29,36 @@ class Import
*/
private $validationAggregateError;

/**
* @var InvalidNodesProcessor
*/
private $invalidNodesProcessor;
/**
* @var ScopeConfigInterface
*/
private $scopeConfig;

public function __construct(
MenuProcessor $menuProcessor,
NodeProcessor $nodeProcessor,
ValidationAggregateError $validationAggregateError
ValidationAggregateError $validationAggregateError,
InvalidNodesProcessor $invalidNodesProcessor,
ScopeConfigInterface $scopeConfig
) {
$this->menuProcessor = $menuProcessor;
$this->nodeProcessor = $nodeProcessor;
$this->validationAggregateError = $validationAggregateError;
$this->invalidNodesProcessor = $invalidNodesProcessor;
$this->scopeConfig = $scopeConfig;
}

/**
* @throws ValidationAggregateError
*/
public function importData(array $data): string
{
$this->validateData($data);

$menu = $this->createMenu($data);

if (isset($data[ExtendedFields::NODES])) {
Expand All @@ -63,16 +82,34 @@ private function createMenu(array $data): MenuInterface
/**
* @throws ValidationAggregateError
*/
private function validateData(array $data): void
private function validateData(array &$data): void
{
$this->menuProcessor->validateImportData($data);

if (isset($data[ExtendedFields::NODES])) {
$this->nodeProcessor->validateImportData($data[ExtendedFields::NODES]);
}

if ($this->validationAggregateError->getErrors()) {
if (empty($this->scopeConfig->getValue('snowmenu/import/strip_invalid_nodes'))
&& $this->validationAggregateError->getErrors()
) {
throw $this->validationAggregateError;
}

$this->checkExceptionTypes($this->validationAggregateError);
$this->invalidNodesProcessor->process($data, $this->validationAggregateError);
}

/**
* Rethrows $e if there's at least one error not matching ValidationException
* @throws ValidationAggregateError
*/
private function checkExceptionTypes(ValidationAggregateError $e)
{
foreach ($e->getErrors() as $error) {
if (!($error instanceof ValidationException)) {
throw $e;
}
}
}
}
84 changes: 84 additions & 0 deletions Model/ImportExport/Processor/Import/InvalidNodes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php declare(strict_types=1);

namespace Snowdog\Menu\Model\ImportExport\Processor\Import;

use Magento\Framework\Message\Manager;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Node\Validator\TreeTrace;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Validator\ValidationAggregateError;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Validator\ValidationException;

class InvalidNodes
{
/**
* @var TreeTrace
*/
private $treeTrace;

/**
* @var Manager
*/
private $manager;

public function __construct(TreeTrace $treeTrace, Manager $manager)
{
$this->treeTrace = $treeTrace;
$this->manager = $manager;
}

public function process(array &$data, ValidationAggregateError $error): array
{
return $this->stripInvalidNodes($data, $error);
}

/**
* @param array $data
* @param ValidationAggregateError $validationAggregateError
* @return array
*/
private function stripInvalidNodes(array &$data, ValidationAggregateError $validationAggregateError): array
{
foreach ($validationAggregateError->getErrors() as $error) {
if ($error instanceof ValidationException) {
if (empty($error->getInvalidNodePath())) {
continue;
}

$this->unsetItemByPath($error->getInvalidNodePath(), $data);
$this->manager->addNoticeMessage(__(
"Invalid node %1 not imported. %2",
implode(' > ', $error->getInvalidNodePath()),
$error->getMessage()
));
}
}
return $data;
}

/**
* Unsets specific $data element by $path
*/
private function unsetItemByPath(array $path, array &$data): void
{
$path = $this->updatePathValues($path);

$dataElement =& $data;
$lastItemKey = array_pop($path);

foreach ($path as $key) {
$dataElement =& $dataElement["nodes"][$key];
}

$dataElement["nodes"][$lastItemKey] = null;
}

private function updatePathValues(array $path): array
{
if ($this->treeTrace->isEnabledNodeIdAddend()) {
foreach ($path as &$idx) {
$idx--;
}
}

return $path;
}
}
4 changes: 4 additions & 0 deletions Model/ImportExport/Processor/Import/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ public function createNodes(
?int $parentId = null
): void {
foreach ($nodes as $nodeData) {
if ($nodeData === null) {
continue;
}

$node = $this->nodeFactory->create();
$data = $this->dataProcessor->getData($nodeData, $menuId, $level, $position++, $parentId);

Expand Down
17 changes: 12 additions & 5 deletions Model/ImportExport/Processor/Import/Node/Validator/NodeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Snowdog\Menu\Model\ImportExport\Processor\Import\Node\Type\Cms;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Node\Validator\TreeTrace;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Validator\ValidationAggregateError;
use Snowdog\Menu\Model\ImportExport\Processor\Import\Validator\ValidationException;
use Snowdog\Menu\Model\ImportExport\Processor\NodeTypes;
use Snowdog\Menu\Model\NodeTypeProvider;

Expand Down Expand Up @@ -122,12 +123,18 @@ private function validateNodeTypeContent(array $node, $nodeId, array $treeTrace)
}

if (!$isValid) {
$treeTraceBreadcrumbs = $this->treeTrace->getBreadcrumbs($treeTrace, $nodeId);
$this->validationAggregateError->addError(
__(
'Node "%1" %2 identifier "%3" is invalid.',
$this->treeTrace->getBreadcrumbs($treeTrace, $nodeId),
$node[NodeInterface::TYPE],
$node[NodeInterface::CONTENT]
new ValidationException(
__(
'Node "%1" %2 identifier "%3" is invalid.',
$treeTraceBreadcrumbs,
$node[NodeInterface::TYPE],
$node[NodeInterface::CONTENT]
),
null,
0,
explode(' > ', $treeTraceBreadcrumbs)
)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@ public function disableNodeIdAddend(): void
{
$this->nodeIdAddend = 0;
}

public function isEnabledNodeIdAddend(): bool
{
return (bool) $this->nodeIdAddend;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Exception;
use Magento\Framework\Message\ManagerInterface as MessageManagerInterface;
use Magento\Framework\Phrase;

class ValidationAggregateError extends Exception
{
Expand All @@ -25,7 +26,7 @@ public function __construct(MessageManagerInterface $messageManager)
}

/**
* @param string|\Magento\Framework\Phrase $error
* @param string|Phrase|Exception $error
*/
public function addError($error): void
{
Expand All @@ -39,10 +40,26 @@ public function getErrors(): array

public function flush(): void
{
foreach ($this->errors as $error) {
$this->messageManager->addErrorMessage($error);
foreach ($this->getErrorMessages() as $errorMessage) {
$this->messageManager->addErrorMessage($errorMessage);
}

$this->errors = [];
}

public function getErrorMessages(): array
{
$errorMessages = [];
foreach ($this->errors as $error) {
if (is_string($error) || $error instanceof Phrase) {
$errorMessages[] = $error;
}

if ($error instanceof Exception) {
$errorMessages[] = $error->getMessage();
}
}

return $errorMessages;
}
}
Loading

0 comments on commit 809cb3f

Please sign in to comment.