PHP code example of tobento / app-block

1. Go to this page and download the library: Download tobento/app-block library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

tobento / app-block example snippets


use Tobento\App\AppFactory;
use Tobento\App\Block\BlockRepositoryInterface;
use Tobento\App\Block\EditorsInterface;
use Tobento\App\Block\ResourceResolverInterface;

// Create the app
$app = (new AppFactory())->createApp();

// Add directories:
$app->dirs()
    ->dir(realpath(__DIR__.'/../'), 'root')
    ->dir(realpath(__DIR__.'/../app/'), 'app')
    ->dir($app->dir('app').'config', 'config', group: 'config')
    ->dir($app->dir('root').'public', 'public')
    ->dir($app->dir('root').'vendor', 'vendor');

// Adding boots
$app->boot(\Tobento\App\Block\Boot\Block::class);
$app->booting();

// Implemented interfaces:
$blockRepository = $app->get(BlockRepositoryInterface::class);
$editors = $app->get(EditorsInterface::class);
$resourceResolver = $app->get(ResourceResolverInterface::class);

// Run the app
$app->run();

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'hero' => Editable\Hero::class,
            'text' => Editable\Text::class,
        ]);

        $factory->addBlockFactories([
            'hero' => Factory\Hero::class,
            'text' => Factory\Text::class,
        ]);

        return $factory->createEditor(name: 'default');
    },
],

use Tobento\App\Block\BlockFactoryInterface;
use Tobento\App\Block\BlockRepositoryInterface;
use Tobento\App\Block\Editable;
use Tobento\App\Block\Factory;
use Tobento\Service\Language\LanguagesInterface;
        
// Set editable blocks returning a new instance:
$factory = $factory->withEditableBlocks([
    'text' => Editable\Text::class,
]);

// Set block factories returning a new instance:
$factory = $factory->withBlockFactories([
    'text' => Factory\Text::class,
]);

// Set block factory returning a new instance:
$factory = $factory->withBlockFactory($blockFactory); // BlockFactoryInterface

// You may set another block repository returning a new instance:
$factory = $factory->withBlockRepository($blockRepository); // BlockRepositoryInterface

// You may set the available editor languages returning a new instance:
$factory = $factory->withLanguages($languages); // LanguagesInterface

// You may set another view namespace. Just make sure block views within that namespace exist.
$blockFactory = $factory->blockFactory()->withViewNamespace('mail');
$factory = $factory->withBlockFactory($blockFactory);

use Tobento\App\Block\EditorsInterface;
use Tobento\Service\Responser\ResponserInterface;

$app->route('GET', 'example/editor', function(EditorsInterface $editors, ResponserInterface $responser) {
    $editor = $editors->get('default');
    
    // You may fetch existing blocks:
    $blocks = $editor->getBlockRepository()->findAll(where: [
        'id' => ['in' => [1,2]]
    ])->all();
    
    return $responser->render(
        view: 'example/editor',
        data: [
            'editor' => $editor,
            'blocks' => $blocks,
        ],
    );
});

echo $editor->render(
    id: 'unique',
    blocks: $blocks,
    options: [
        // you may set a block status:
        'status' => 'active', // pending is default
        
        // you may set a resource id and group:
        'resource_id' => 'articles:2',
        'resource_group' => 'main',
        
        // you may set a position
        'position' => 'header',
            
        // you may store blocks to a HTML input field
        'storeBlocksToInput' => 'blocks',
    ],
);

<input type="hidden" name="blocks">

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;
use Tobento\App\Block\Mail\MailEditorFactory;

'editors' => [
    'mail' => static function (MailEditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'hero' => Editable\Hero::class,
            'text' => Editable\Text::class,
        ]);

        $factory->addBlockFactories([
            'hero' => Factory\Hero::class,
            'text' => Factory\Text::class,
        ]);

        return $factory->createEditor(name: 'mail');
    },
],

use Tobento\App\Block\Crud\Field\BlockEditor;

BlockEditor::new('blocks')->editor(name: 'default');

use Tobento\App\Block\EditorsInterface;

$editors = $app->get(EditorsInterface::class);
$editor = $editors->get('default');

$html = '';

foreach($storedBlocks as $block) {
    $block['editable'] = false; // set blocks as uneditable.
    $block['locale'] = 'de'; // you may change its locale.
    $entity = $editor->getBlockRepository()->createEntity($block);
    $html .= $editor->getBlockFactory()->createBlockFromEntity($entity)->render();
}

echo $html;

use Tobento\App\AppFactory;
use Tobento\App\Block\Middleware\BlockViewsEditor;
use Tobento\Service\Responser\ResponserInterface;

// Create the app
$app = (new AppFactory())->createApp();

// Add directories:
$app->dirs()
    ->dir(realpath(__DIR__.'/../'), 'root')
    ->dir(realpath(__DIR__.'/../app/'), 'app')
    ->dir($app->dir('app').'config', 'config', group: 'config')
    ->dir($app->dir('root').'public', 'public')
    ->dir($app->dir('root').'vendor', 'vendor');

// Adding boots
$app->boot(\Tobento\App\Block\Boot\Block::class);
$app->booting();

// Routes:
$app->route('GET', 'about', function(ResponserInterface $responser) {
    return $responser->render(
        view: 'about',
        data: [],
    );
})->middleware([
    BlockViewsEditor::class,
    'editorName' => 'default',
    'editable' => true,
    
    // you may set a resource id and/or group
    // modifying the resource resolved from the resource resolver:
    'resourceId' => 'about',
    'resourceGroup' => 'main',
]);

// Run the app
$app->run();

'interfaces' => [
    \Tobento\App\Block\ResourceResolverInterface::class => \Tobento\App\Block\ResourceResolver\Slugs::class,
],

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>About</title>
        <?= $view->render('inc/head') 

use Tobento\App\Block\Crud\Field\BlockResourceEditor;
use Tobento\App\Crud\Entity\EntityInterface;

BlockResourceEditor::new()
    ->editor('default')
    
    // Set the supported block positions:
    ->blockPositions('resource.header', 'resource')
    
    // You may customize the resource id:
    ->resourceId(fn (EntityInterface $entity): string => sprintf('articles:%s', $entity->id()))
    // By default, the CRUD resource name and the entity id is used e.g. 'articles:45'
    // matching the slugs resource resolver pattern.
    
    // You may set a resource group:
    ->resourceGroup(name: 'main')
    
    // You may disable blocks being editable as they are editable by the middleware:
    ->editable(false) // default true
    
    // You may enable to store blocks on its field
    // (not recommended if using the middleware to edit blocks as data are not in sync):
    ->storable(true); // default false

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'downloads' => Editable\Downloads::class,
            
            // Or:
            'downloads' => new Editable\Downloads(
                // you may customize the picture definitions:
                pictureDefinitions: ['block-downloads'], // default
                
                // you may configure the allowed file extensions:
                allowedFileExtensions: ['jpg', 'png', 'webp', 'pdf'], // default
                
                // you may set the max number of files allowed:
                maxNumberOfFiles: 50, // default
            ),
        ]);

        $factory->addBlockFactories([
            'downloads' => Factory\Downloads::class,
            
            // you may generate images immediately:
            'downloads' => [Factory\Downloads::class, 'generateImagesInBackground' => false],
        ]);

        return $factory->createEditor(name: 'default');
    },
],

'features' => [
    new Feature\File(
        supportedStorages: ['images', 'uploads', 'downloads'],
    ),
    new Feature\FileDownload(
        supportedStorages: ['downloads'],
    ),
    new Feature\FileDisplay(
        supportedStorages: ['downloads'],
    ),
],

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'hero' => Editable\Hero::class,
            
            // you may customize the picture definitions:
            'hero' => new Editable\Hero(
                pictureDefinitions: ['block-hero'], // default
            ),
        ]);

        $factory->addBlockFactories([
            'hero' => Factory\Hero::class,
            
            // you may generate images immediately:
            'hero' => [Factory\Hero::class, 'generateImagesInBackground' => false],
        ]);

        return $factory->createEditor(name: 'default');
    },
],

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'image' => Editable\Image::class,
            
            // you may customize the picture definitions:
            'image' => new Editable\Image(
                pictureDefinitions: ['block-image'], // default
            ),
        ]);

        $factory->addBlockFactories([
            'image' => Factory\Image::class,
            
            // you may generate images immediately:
            'image' => [Factory\Image::class, 'generateImagesInBackground' => false],
        ]);

        return $factory->createEditor(name: 'default');
    },
],

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'image-gallery' => Editable\ImageGallery::class,
            
            // Or:
            'image-gallery' => new Editable\ImageGallery(
                // you may customize the picture definitions:
                pictureDefinitions: [
                    'block-image-gallery', // default
                    'block-image-gallery-large', // you may add which is used for large images.
                ],
                
                // you may set the max number of images allowed:
                maxNumberOfImages: 50, // default
            ),
        ]);

        $factory->addBlockFactories([
            'image-gallery' => Factory\ImageGallery::class,
            
            // you may generate images immediately:
            'image-gallery' => [Factory\ImageGallery::class, 'generateImagesInBackground' => false],
        ]);

        return $factory->createEditor(name: 'default');
    },
],

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'persons' => Editable\Persons::class,
            
            // you may customize the picture definitions:
            'persons' => new Editable\Persons(
                pictureDefinitions: ['block-persons'], // default
            ),
        ]);

        $factory->addBlockFactories([
            'persons' => Factory\Persons::class,
            
            // you may generate images immediately:
            'persons' => [Factory\Persons::class, 'generateImagesInBackground' => false],
        ]);

        return $factory->createEditor(name: 'default');
    },
],

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'text' => Editable\Text::class,
        ]);

        $factory->addBlockFactories([
            'text' => Factory\Text::class,
        ]);

        return $factory->createEditor(name: 'default');
    },
],

use Tobento\App\Block\Editable\Option as EditableOption;
use Tobento\App\Block\Editable\Option\Options as EditableOptions;
use Tobento\App\Block\Editable\Option\OptionsInterface as EditableOptionsInterface;

'interfaces' => [
    \Tobento\App\Block\Block\Option\OptionsFactoryInterface::class => \Tobento\App\Block\Block\Option\OptionsFactory::class,

    EditableOptionsInterface::class => static function(): EditableOptionsInterface {
        return new EditableOptions([
            'padding' => new EditableOption\Padding(),
            'margin' => new EditableOption\Margin(),
            'color' => new EditableOption\Color(),
        ]);
    },
],

use Tobento\App\Block\Editable;
use Tobento\App\Block\Editable\Option as EditableOption;
use Tobento\App\Block\Editable\Option\Options as EditableOptions;
use Tobento\App\Block\Editable\Option\OptionsInterface as EditableOptionsInterface;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory, EditableOptionsInterface $editableOptions): EditorInterface {
        $factory->addEditableBlocks([
            'hero' => new Editable\Hero(
                options: $editableOptions->withOption(
                    name: 'layout',
                    option: new EditableOption\Layout(['foo' => 'Foo'])
                ),
            ),
        ]);

        $factory->addBlockFactories([
            'hero' => Factory\Hero::class,
        ]);

        return $factory->createEditor(name: 'default');
    },
],

// Adds an option returning a new instance:
$editableOptions = $editableOptions->withOption(
    name: 'layout',
    option: new EditableOption\Layout(['foo' => 'Foo'])
);

// Returns a new instance ONLY with the specified options:
$editableOptions = $editableOptions->only('padding', 'margin');

// Returns a new instance EXCEPT with the specified options:
$editableOptions = $editableOptions->except('padding', 'margin');

// Returns a new instance with the options orderd by the specified names:
$editableOptions = $editableOptions->reorder('padding', 'margin');

use Tobento\App\Block\Editable\Option as EditableOption;
use Tobento\App\Block\Editable\Option\Options as EditableOptions;
use Tobento\App\Block\Editable\Option\OptionsInterface as EditableOptionsInterface;

'interfaces' => [
    EditableOptionsInterface::class => static function(): EditableOptionsInterface {
        return new EditableOptions([
            'classes' => new EditableOption\Classes(
                // You may set custom classes, otherwise default are used:
                classes: ['classname' => 'A title'],
                
                // You may disable searching classes if you have only a few class:
                searchableClasses: false, // true is default
                
                // You may change the group name:
                groupName: 'Classes', // default
            ),
        ]);
    },
],

use Tobento\App\Block\Editable\Option as EditableOption;
use Tobento\App\Block\Editable\Option\Options as EditableOptions;
use Tobento\App\Block\Editable\Option\OptionsInterface as EditableOptionsInterface;

'interfaces' => [
    EditableOptionsInterface::class => static function(): EditableOptionsInterface {
        return new EditableOptions([
            'color' => new EditableOption\Color(
                supportedColors: ['text', 'background'] // default
            ),
        ]);
    },
],

use Tobento\App\Block\Editable;
use Tobento\App\Block\Editable\Option as EditableOption;
use Tobento\App\Block\Editable\Option\Options as EditableOptions;
use Tobento\App\Block\Editable\Option\OptionsInterface as EditableOptionsInterface;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'default' => static function (EditorFactory $factory, EditableOptionsInterface $editableOptions): EditorInterface {
        $factory->addEditableBlocks([
            'hero' => new Editable\Hero(
                options: $editableOptions->withOption(
                    name: 'layout',
                    option: new EditableOption\Layout(['fit' => 'Fit Image'])
                ),
            ),
        ]);

        $factory->addBlockFactories([
            'hero' => Factory\Hero::class,
        ]);

        return $factory->createEditor(name: 'default');
    },
],

use Tobento\App\Block\Editable\Option as EditableOption;
use Tobento\App\Block\Editable\Option\Options as EditableOptions;
use Tobento\App\Block\Editable\Option\OptionsInterface as EditableOptionsInterface;

'interfaces' => [
    EditableOptionsInterface::class => static function(): EditableOptionsInterface {
        return new EditableOptions([
            'margin' => new EditableOption\Margin(
                supportedMargin: ['top', 'bottom', 'left', 'right'], // default
            ),
            
            'padding' => new EditableOption\Padding(
                supportedPadding: ['top', 'bottom', 'left', 'right'], // default
            ),
        ]);
    },
],

'listeners' => [
    \Tobento\App\Crud\Event\FileSourceDeleted::class => [
        \Tobento\App\Crud\Listener\DeletesGeneratedPictures::class,
    ],
],

use Tobento\Service\Schedule\Task;
use Butschster\CronExpression\Generator;

$schedule->task(
    (new Task\CommandTask(
        command: 'php ap blocks:purge',
    ))
    // schedule task:
    ->cron(Generator::create()->daily())
);

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'custom' => static function (EditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'hero' => Editable\Hero::class,
            'text' => Editable\Text::class,
        ]);

        $factory->addBlockFactories([
            'hero' => Factory\Hero::class,
            'text' => Factory\Text::class,
        ]);
        
        // add custom namespace
        $blockFactory = $factory->blockFactory()->withViewNamespace('custom');
        $factory = $factory->withBlockFactory($blockFactory);

        return $factory->createEditor(name: 'custom');
    },
],

use Tobento\App\Block\BlockFactoryInterface;
use Tobento\App\Block\Editor\BlockFactory;
use Tobento\App\Block\Editor\EditorFactory;

class CustomEditorFactory extends EditorFactory
{
    /**
     * Returns the created block factory.
     *
     * @return BlockFactoryInterface
     */
    protected function createBlockFactory(): BlockFactoryInterface
    {
        return new BlockFactory(container: $this->container, viewNamespace: 'custom');
    }
}

use Tobento\App\Block\Editable;
use Tobento\App\Block\EditorInterface;
use Tobento\App\Block\Factory;
use Tobento\App\Block\Editor\EditorFactory;

'editors' => [
    'custom' => static function (CustomEditorFactory $factory): EditorInterface {
        $factory->addEditableBlocks([
            'hero' => Editable\Hero::class,
            'text' => Editable\Text::class,
        ]);

        $factory->addBlockFactories([
            'hero' => Factory\Hero::class,
            'text' => Factory\Text::class,
        ]);

        return $factory->createEditor(name: 'custom');
    },
],

use Tobento\App\Block\Editor\EditorFactory;

$app->on(
    EditorFactory::class,
    static function(EditorFactory $factory): void {
        $factory->addEditableBlocks([
            'products' => ProductListEditable::class,
        ]);

        $factory->addBlockFactories([
            'products' => ProductListFactory::class,
        ]);
    }
);
app/config/block.php
blocks.header
config/media.php
app/config/block.php
app/config/event.php

php ap blocks:purge

views/block/custom/
    hero.php
    hero-editor.php
    ...

views/block/custom/
    hero.php
    hero-editor.php
    ...