* @link https://getkirby.com * @copyright Bastian Allgeier * @license https://getkirby.com/license */ class Block extends Item { use HasMethods; public const ITEMS_CLASS = Blocks::class; /** * Registry with all block models */ public static array $models = []; protected Content $content; protected bool $isHidden; protected string $type; /** * Proxy for content fields */ public function __call(string $method, array $args = []): mixed { // block methods if ($this->hasMethod($method)) { return $this->callMethod($method, $args); } return $this->content()->get($method); } /** * Creates a new block object * * @throws \Kirby\Exception\InvalidArgumentException */ public function __construct(array $params) { parent::__construct($params); // @deprecated import old builder format // @todo block.converter remove eventually // @codeCoverageIgnoreStart $params = BlockConverter::builderBlock($params); $params = BlockConverter::editorBlock($params); // @codeCoverageIgnoreEnd if (isset($params['type']) === false) { throw new InvalidArgumentException('The block type is missing'); } // make sure the content is always defined as array to keep // at least a bit of backward compatibility with older fields if (is_array($params['content'] ?? null) === false) { $params['content'] = []; } $this->isHidden = $params['isHidden'] ?? false; $this->type = $params['type']; // create the content object $this->content = new Content($params['content'], $this->parent); } /** * Converts the object to a string */ public function __toString(): string { return $this->toHtml(); } /** * Returns the content object */ public function content(): Content { return $this->content; } /** * Controller for the block snippet */ public function controller(): array { return [ 'block' => $this, 'content' => $this->content(), // deprecated block data 'data' => $this, 'id' => $this->id(), 'prev' => $this->prev(), 'next' => $this->next() ]; } /** * Converts the block to HTML and then * uses the Str::excerpt method to create * a non-formatted, shortened excerpt from it */ public function excerpt(mixed ...$args): string { return Str::excerpt($this->toHtml(), ...$args); } /** * Constructs a block object with registering blocks models * @internal * * @throws \Kirby\Exception\InvalidArgumentException */ public static function factory(array $params): static { $type = $params['type'] ?? null; if ( empty($type) === false && $class = (static::$models[$type] ?? null) ) { $object = new $class($params); if ($object instanceof self) { return $object; } } // default model for blocks if ($class = (static::$models['default'] ?? null)) { $object = new $class($params); if ($object instanceof self) { return $object; } } return new static($params); } /** * Checks if the block is empty */ public function isEmpty(): bool { return empty($this->content()->toArray()); } /** * Checks if the block is hidden * from being rendered in the frontend */ public function isHidden(): bool { return $this->isHidden; } /** * Checks if the block is not empty */ public function isNotEmpty(): bool { return $this->isEmpty() === false; } /** * Returns the sibling collection that filtered by block status */ protected function siblingsCollection(): Blocks { return $this->siblings->filter('isHidden', $this->isHidden()); } /** * Returns the block type */ public function type(): string { return $this->type; } /** * The result is being sent to the editor * via the API in the panel */ public function toArray(): array { return [ 'content' => $this->content()->toArray(), 'id' => $this->id(), 'isHidden' => $this->isHidden(), 'type' => $this->type(), ]; } /** * Converts the block to html first * and then places that inside a field * object. This can be used further * with all available field methods */ public function toField(): Field { return new Field($this->parent(), $this->id(), $this->toHtml()); } /** * Converts the block to HTML */ public function toHtml(): string { try { $kirby = $this->parent()->kirby(); return (string)$kirby->snippet( 'blocks/' . $this->type(), $this->controller(), true ); } catch (Throwable $e) { if ($kirby->option('debug') === true) { return '
Block error: "' . $e->getMessage() . '" in block type: "' . $this->type() . '"
'; } return ''; } } }