Initial baseline: LaraBlog core with plugin commerce surface.
Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user