Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
113 lines
2.8 KiB
PHP
113 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Domain\Theme;
|
|
|
|
use App\Domain\Plugin\Hook;
|
|
|
|
/**
|
|
* Named injection points for themes / plugins / site snippets.
|
|
*
|
|
* Themes call ThemeSlot::render('head') (or @themeslot('head')).
|
|
* Plugins listen on Hook event "theme.{slot}".
|
|
* Admin SnippetSettings also appends into these slots at boot.
|
|
*/
|
|
final class ThemeSlot
|
|
{
|
|
public const HEAD = 'head';
|
|
|
|
public const BODY_START = 'body_start';
|
|
|
|
public const BODY_END = 'body_end';
|
|
|
|
public const HEADER_AFTER = 'header_after';
|
|
|
|
public const NAV_AFTER = 'nav_after';
|
|
|
|
public const CONTENT_BEFORE = 'content_before';
|
|
|
|
public const CONTENT_AFTER = 'content_after';
|
|
|
|
public const ARTICLE_TOP = 'article_top';
|
|
|
|
public const ARTICLE_BOTTOM = 'article_bottom';
|
|
|
|
public const SIDEBAR_BEFORE = 'sidebar_before';
|
|
|
|
public const SIDEBAR = 'sidebar';
|
|
|
|
public const SIDEBAR_AFTER = 'sidebar_after';
|
|
|
|
public const FOOTER_BEFORE = 'footer_before';
|
|
|
|
public const FOOTER_AFTER = 'footer_after';
|
|
|
|
/** @return list<string> */
|
|
public static function all(): array
|
|
{
|
|
return [
|
|
self::HEAD,
|
|
self::BODY_START,
|
|
self::BODY_END,
|
|
self::HEADER_AFTER,
|
|
self::NAV_AFTER,
|
|
self::CONTENT_BEFORE,
|
|
self::CONTENT_AFTER,
|
|
self::ARTICLE_TOP,
|
|
self::ARTICLE_BOTTOM,
|
|
self::SIDEBAR_BEFORE,
|
|
self::SIDEBAR,
|
|
self::SIDEBAR_AFTER,
|
|
self::FOOTER_BEFORE,
|
|
self::FOOTER_AFTER,
|
|
];
|
|
}
|
|
|
|
public static function event(string $slot): string
|
|
{
|
|
return 'theme.'.$slot;
|
|
}
|
|
|
|
public static function render(string $slot): string
|
|
{
|
|
return Hook::gather(self::event($slot), '');
|
|
}
|
|
|
|
/**
|
|
* Soft contract for theme authors & admin UI.
|
|
* Sizes are recommendations only — the active theme's CSS wins.
|
|
*
|
|
* @return array<string, array{label: string, place: string, size: string, multi: bool}>
|
|
*/
|
|
public static function catalog(): array
|
|
{
|
|
$catalog = [];
|
|
|
|
foreach (self::all() as $slot) {
|
|
$catalog[$slot] = [
|
|
'label' => __('admin.slots.'.$slot.'.label'),
|
|
'place' => __('admin.slots.'.$slot.'.place'),
|
|
'size' => __('admin.slots.'.$slot.'.size'),
|
|
'multi' => true,
|
|
];
|
|
}
|
|
|
|
return $catalog;
|
|
}
|
|
|
|
public static function hint(string $slot): string
|
|
{
|
|
$meta = self::catalog()[$slot] ?? null;
|
|
if ($meta === null) {
|
|
return __('admin.slots.custom', ['slot' => $slot]);
|
|
}
|
|
|
|
return __('admin.slots.hint', [
|
|
'place' => $meta['place'],
|
|
'size' => $meta['size'],
|
|
'slot' => $slot,
|
|
]);
|
|
}
|
|
}
|