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);
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();
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
),
]);
},
],
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');
},
],