10

I need to delete all CMS pages.

Here is the code:

namespace Soon\Core\Setup;

use Magento\Cms\Api\PageRepositoryInterface;
use Magento\Framework\Api\SearchCriteriaInterface;

class Cms
{
    /**
     * @var SearchCriteriaInterface
     */
    private $searchCriteria;
    /**
     * @var PageRepositoryInterface
     */
    private $cmsPageRepository;

    /**
     * Cms constructor.
     * @param SearchCriteriaInterface $searchCriteria
     * @param PageRepositoryInterface $cmsPageRepository
     */
    public function __construct(
        SearchCriteriaInterface $searchCriteria,
        PageRepositoryInterface $cmsPageRepository
    )
    {
        $this->searchCriteria = $searchCriteria;
        $this->cmsPageRepository = $cmsPageRepository;
    }

    /**
     * Delete all existing CMS pages
     */
    public function cleanCmsPages()
    {
        $cmsPageCollection = $this->cmsPageRepository
            ->getList($this->searchCriteria)
            ->getItems();

        foreach ($cmsPageCollection as $cmsPage) {
            $this->cmsPageRepository->delete($cmsPage);
        }
    }
}

So, calling \Soon\Core\Setup\Cms::cleanCmsPages should delete all CMS pages.

But when doing so, I get this error:

Argument 1 passed to Magento\Cms\Model\PageRepository::delete() must implement interface Magento\Cms\Api\Data\PageInterface, array given

So I dumped the $cmsPage used in my foreach ($cmsPageCollection as $cmsPage) and it appears that, indeed, $cmsPage is an array.

I digged into the code:

\Magento\Cms\Api\PageRepositoryInterface::getList is implemented by \Magento\Cms\Model\PageRepository::getList.

Then in \Magento\Cms\Model\PageRepository::getList, we can see this bit of code:

            $pages[] = $this->dataObjectProcessor->buildOutputDataArray(
                $pageData,
                'Magento\Cms\Api\Data\PageInterface'
            );
        }
        $searchResults->setItems($pages);

If I am correct, this code creates an array that populates the $pages array. So this code may explain why $cmsPage is an array!

BUT...

By reading @return statement of \Magento\Cms\Api\PageRepositoryInterface::getList, we can see @return \Magento\Cms\Api\Data\PageSearchResultsInterface.

And, then by reading the @return statement from \Magento\Cms\Api\Data\PageSearchResultsInterface::getItems, we can see \Magento\Cms\Api\Data\PageInterface[]!

So the $cmsPage in my foreach loop should be an implementation of \Magento\Cms\Api\Data\PageInterface which then can be passed properly to \Magento\Cms\Api\PageRepositoryInterface::delete.

Who's wrong?

  1. Me who cannot read / understand @api comments and code properly
  2. Magento who whether does not give the right comment in their @api classes... or does not implements the interface as it should.

This analysis is for the CMS Page API but also applies to the CMS Block API.

2

You can create bug issue on github if you want. But more faster way for you is to use resource model or if you want use this repository method deleteById() where you can pass id of entity.

vendor/magento/module-cms/Model/PageRepository.php

public function deleteById($pageId)
{
    return $this->delete($this->getById($pageId));
}

Repositories is not for bulk operation, this affect performance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.