Question

I want to create command for delete operation for simple product by sku. I'm getting following error.how to set admin area?

[Magento\Framework\Exception\LocalizedException]
Delete operation is forbidden for current area

<?php
namespace Sivakumar\Sample\Console;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;

class DeleteSimpleProduct extends Command
{
    protected $_product;
    public function __construct(\Magento\Catalog\Model\Product $_product)
    {
        $this->_product =$_product;
        parent::__construct();
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('delete_simple_product')
            ->setDescription('Delete Simple Product')
            ->setDefinition($this->getOptionsList());

        parent::configure();
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $errors = $this->validate($input);
        if ($errors) {
            throw new \InvalidArgumentException(implode("\n", $errors));
        }

    $product_id = $this->_product->getIdBySku($input->getOption('sku'));
    $product=$this->_product->load($product_id);
        $product->delete();
        $output->writeln('<info>product deleted ' . $input->getOption('sku') . '</info>');
    }

    public function getOptionsList()
    {
        return [
            new InputOption('sku', null, InputOption::VALUE_REQUIRED, 'SKU'),
        ];
    }

    public function validate(InputInterface $input)
    {
        $errors = [];
        $required =['sku',]; 

        foreach ($required as $key) {
            if (!$input->getOption($key)) {
                $errors[] = 'Missing option ' . $key;
            }
        }
        return $errors;
    }
}

di.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Console\CommandList">
    <arguments>
        <argument name="commands" xsi:type="array">
            <item name="delete_simple_product" xsi:type="object">Sivakumar\Sample\Console\DeleteSimpleProduct</item>
        </argument>
    </arguments>
</type>
</config>
Was it helpful?

Solution

Agree with Max that you should use the ProductRepositoryInterface::deleteById($sku), but you'll also need to make an additional change to get permissions to delete.

Note that the Admin area handles this by creating the following config in app/code/Magento/Backend/etc/adminhtml/di.xml

    <preference for="Magento\Framework\Model\ActionValidator\RemoveAction" type="Magento\Framework\Model\ActionValidator\RemoveAction\Allowed" />

The Magento\Framework\Model\ActionValidator\RemoveAction\Allowed class prevents a permission check by simply returning true in the isAllowed method.

Without the above change to di.xml the Magento\Framework\Model\ActionValidator\RemoveAction class will be used, which will cause your delete request to fail unless $this->registry->registry('isSecureArea') is set to true.

It looks like you are trying to create some console commands and I'm not very familiar with them yet, so your best bet for now may be to set the registry to allow the delete operation and refactor later if a cleaner solution is found.

$this->registry->register('isSecureArea', true)

OTHER TIPS

I recently had this problem while writing a console command to delete empty categories.

As said in another answer you need to register 'isSecureArea' to true.

To do this in a console command you need to have the Magento\Framework\Registry class passed into your constructor.

In my case I did in this way:

public function __construct(CategoryManagementInterface $categoryManagementInterface, CategoryRepositoryInterface $categoryRepositoryInterface, Registry $registry)
{
    $this->_categoryRepository = $categoryRepositoryInterface;
    $this->_categoryManagement = $categoryManagementInterface;
    $registry->register('isSecureArea', true);


    parent::__construct();
}

and then in the execute method I used the repository to perform the actual deletion:

$this->_categoryRepository->deleteByIdentifier($category->getId());

if you using script please create the registry object as shown below.

  $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
  $objectManager->get('Magento\Framework\Registry')->register('isSecureArea', true);

Please click here for detailed explanation. http://www.pearlbells.co.uk/mass-delete-magento-2-categories-programmatically/

if it is a one time script, you can use OM

Expanding on Chris O'Toole's answer. I too need to delete categories from a command, actually from multiple commands. Initially just having

$oRegistry->register('isSecureArea', true);

in one command worked fine, but when I put that in multiple commands (in the constructor) I got this error during compilation

Registry key "isSecureArea" already exists

First checking for the existence of the registry key solved it

if($oRegistry->registry('isSecureArea') === null) {
    $oRegistry->register('isSecureArea', true);
}

I'm not sure if it's bad form to put that in the constructor, but assume that's why the error was encountered. Alternatively, you should be able to get away with running the first snippet from your commands' execute methods. Again, I'm not sure what's considered best practice...

For operations with product you must use Repository.

Magento\Catalog\Model\ProductRepository

Instead of setting isSecureArea you can also allow to remove a single type of object by overriding type RemoveAction arguments in your di.xml like this:

<type name="Magento\Framework\Model\ActionValidator\RemoveAction">
    <arguments>
        <argument name="protectedModels" xsi:type="array">
            <item name="salesOrder" xsi:type="null" /> <!--allow orders to be removed from front area-->
        </argument>
    </arguments>
</type>
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top