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 a CMS Block via data patch is easy to use, it will create automatically blocks 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;
    }
}