Magento 2

Magento 2 + CMS block create via Data Patch

It’s easy to create a Cms block via admin, but when code is moved to another server or in some cases of data loss, might be a chance to lose that block, and is not recoverable. creating CMS block via data patch is easy to use, it will create automatically pages when the source moves to another server, and no worry about data loss.

<?php

declare(strict_types=1);

namespace Mage2\Demo\Setup\Patch\Data;

use Exception;
use Magento\Cms\Api\BlockRepositoryInterface;
use Magento\Cms\Model\BlockFactory;
use Magento\Framework\App\Area;
use Magento\Framework\App\State;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Store\Model\Store;
use Psr\Log\LoggerInterface;

/**
 * class CustomCmsBlock create a Custom Cms Block
 */
class CustomCmsBlock implements DataPatchInterface
{
    private const BLOCK_IDENTIFIER = "custom-cms-block";

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

    /**
     * @var BlockFactory
     */
    private $blockFactory;

    /**
     * @var State
     */
    private $state;

    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

    /**
     * @var BlockRepositoryInterface
     */
    private $blockRepository;

    /**
     * @param BlockFactory $blockFactory
     * @param LoggerInterface $logger
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param State $state
     * @param BlockRepositoryInterface $blockRepository
     */
    public function __construct(
        BlockFactory             $blockFactory,
        LoggerInterface          $logger,
        ModuleDataSetupInterface $moduleDataSetup,
        State                    $state,
        BlockRepositoryInterface $blockRepository
    ) {
        $this->logger = $logger;
        $this->blockFactory = $blockFactory;
        $this->state = $state;
        $this->moduleDataSetup = $moduleDataSetup;
        $this->blockRepository = $blockRepository;
    }

    /**
     * Get array of patches that have to be executed prior to this.
     *
     * @return string[]
     */
    public static function getDependencies()
    {
        return [];
    }

    /**
     * Get aliases (previous names) for the patch.
     *
     * @return string[]
     */
    public function getAliases()
    {
        return [];
    }

    /**
     * This patch is create Custom Cms Block
     *
     * @return $this|CustomCmsBlock
     */
    public function apply()
    {
        $this->moduleDataSetup->startSetup();

        try {
            $this->state->emulateAreaCode(
                Area::AREA_ADMINHTML,
                [$this, 'setupCustomCmsBlock']
            );
        } catch (Exception $e) {
            $this->logger->error(
                'Error when Saving settings for patch CustomCmsBlock: ' . $e->getMessage()
            );
        }

        $this->moduleDataSetup->endSetup();
        return $this;
    }

    /**
     * This patch is to create Custom Cms Block
     */
    public function setupCustomCmsBlock()
    {
        $cmsBlock = $this->createBlock()->setData($this->getBlock());
        $this->blockRepository->save($cmsBlock);
    }

    /**
     * Create block instance.
     *
     * @return Block
     */
    private function createBlock()
    {
        return $this->blockFactory->create();
    }

    /**
     * Get Block Config
     *
     * @return array
     */
    private function getBlock(): array
    {
        return [
            'title' => 'Test CMS Block',
            'identifier' => self::BLOCK_IDENTIFIER,
            'content' => $this->getCmsBlockHtml(),
            'stores' => [Store::DEFAULT_STORE_ID],
            'is_active' => true
        ];
    }

    /**
     * Get Custom CMS block html
     *
     * @return string
     */
    private function getCmsBlockHtml(): string
    {
        // Set HTML content here
        $html = <<<HTML
You can set here Html Content
HTML;

        return $html;
    }
}