| name | atomic-framework-event-hook-lang-mail |
| description | Use when working on Atomic events (dot-notation typed event bus), hooks (WordPress-style add_action/add_filter), shortcodes, i18n localization, mail sending (Mailer, Notifier), or text-extensibility features. |
| argument-hint | Events, hooks, filters, shortcodes, localization, lang_url, mail_to, notifier |
| user-invocable | true |
Atomic Framework Event, Hook, Lang, and Mail
When to Use
- Emitting or listening to application events.
- Registering WordPress-style actions or filters.
- Working with shortcodes.
- Adding translation strings or locale-aware URL generation.
- Sending SMTP emails or push notifications.
Engine Files
engine/Atomic/Event/*, engine/Atomic/Hook/*, engine/Atomic/Lang/*, engine/Atomic/Mail/*
Reference Docs
docs/event.md, docs/hook.md, docs/i18n.md, docs/mailer.md, docs/notifier.md, docs/template.md
Events (typed dot-notation bus)
Engine\Atomic\Event\Event - backed by F3 hive.
use Engine\Atomic\Event\Event;
$events = Event::instance();
$events->on('user.login', function ($user, array &$context, array $event) {
return $user;
});
$events->on('post.publish', function ($post, array &$context, array $event) {
return $post;
}, 5, ['source' => 'admin']);
$user = $events->emit('user.login', $user);
$result = $events->broadcast('notification.sent', $payload);
$events->on('form.validate', function ($data) {
return empty($data['email']) ? false : $data;
});
Hierarchical Events
$events->on('user', fn ($p) => $p);
$events->on('user.register', fn ($p) => $p);
$events->emit('user.register.success', $payload);
Object-Local Events
$watcher = $events->watch($object);
$watcher->on('save', fn ($data) => $data);
$watcher->emit('save', ['id' => 1]);
$events->unwatch($object);
Introspection
$events->has('user.login');
$events->get_registered_events();
$events->off('user.login');
App Event Wiring
Application-level events are initialized in app/Event/Application.php:
class Application
{
public function init(): void
{
$events = Event::instance();
$events->on('user.registered', [new UserWelcome(), 'handle']);
}
}
Hooks (WordPress-style actions & filters)
Engine\Atomic\Hook\Hook - thin wrapper over the Event bus.
enum HookTag: string { case INIT = 'init'; case USER_REGISTERED = 'user_registered'; }
add_action('init', function () {
});
add_action(HookTag::USER_REGISTERED, function ($userId, $data) {
}, 10, 2);
do_action('init');
do_action(HookTag::USER_REGISTERED, 123, ['username' => 'john']);
has_action('init');
remove_action('init');
remove_action('init', $specificCallback);
add_filter('the_content', function ($content) {
return '<div class="wrap">' . $content . '</div>';
});
add_filter('price_label', function ($label, $currency) {
return $label . ' ' . $currency;
}, 10, 2);
$content = apply_filters('the_content', '<p>Original</p>');
echo apply_filters('price_label', 'Price:', 'USD');
remove_filter('the_content');
remove_filter('the_content', $myCallback);
Note: pass null as callback to remove_action() / remove_filter() to clear ALL listeners on the tag. Pass a specific callable to remove only that one callback.
App Hook Wiring
class Application
{
public function init(): void
{
add_filter('the_title', fn ($t) => strtoupper($t));
}
}
Shortcodes
Engine\Atomic\Hook\Shortcode provides a WordPress-style shortcode API. See the full API at the bottom of this skill (## Shortcodes).
Localization (i18n)
Engine\Atomic\Lang\I18n - locale loading and translation.
$app->route('GET /@lang/about', 'App\\Http\\Controllers\\Page->about');
function about(\Base $f3, array $params): void
{
$lang = $params['lang'] ?? get_locale();
}
Helpers
get_locale();
get_languages();
lang_url('/', 'uk');
lang_url('/login');
hreflang_links('/about');
Translation Functions
$label = __('btn.submit');
$label = __('welcome', ['name' => 'John']);
_e('btn.submit');
$label = _x('bank', 'financial context');
$msg = _n('1 item', '%d items', $count, [$count]);
content_locale('uk');
content_locale();
$label = __c('btn.save');
_ec('btn.save');
$label = _xc('bank', 'financial');
$msg = _nc('1 item', '%d items', $count, [$count]);
set_locale('uk');
Locale Files
Locales live in engine/Atomic/Lang/locales/en.php, ru.php, etc. as PHP arrays.
App translations go in the app-level locale directory configured by LOCALES.
Mail
Engine\Atomic\Mail\Mailer - fluent SMTP wrapper.
mail_to('user@example.com', 'John Doe')
->set_html('<h1>Welcome!</h1>')
->send('Welcome');
mail_to('user@example.com')
->set_text('Hello!')
->send('Hello');
mail_send('user@example.com', 'Subject', '<h1>Hi</h1>');
mail_send('user@example.com', 'Subject', 'Plain text', false);
mail_to('primary@example.com')
->add_cc('manager@example.com')
->add_bcc('archive@example.com')
->send('Report');
mail_to('client@example.com')
->attach('/path/to/report.pdf', 'Report.pdf')
->send('Documents');
mail_to('user@example.com')
->set_from('noreply@example.com', 'System')
->send('Notification');
mail_to('user@example.com')
->set_reply('support@example.com', 'Support')
->set_html('<p>Hello</p>')
->send('Hello');
mail_to('user@example.com')
->add_header('X-Campaign', 'welcome-2024')
->set_html('<p>Hi</p>')
->send('Hi');
$ok = mail_to('user@example.com')->set_html('<p>Test</p>')->send('Test', mock: true);
Welcome Email Pattern
mail_to($user->email, $user->name)
->set_html("
<h1>Welcome, {$user->name}!</h1>
<p><a href='" . lang_url('/activate/' . $user->token) . "'>Activate</a></p>
")
->send('Welcome to ' . get_option('site_name'));
Notifier
Engine\Atomic\Mail\Notifier -- flash messages and notification queue.
notify('Saved successfully!', 'success');
notify_success('Order created');
notify_info('Please check your email');
notify_warning('Stock is low');
notify_error('Payment failed');
$all = get_notifications();
$errs = get_notifications('error');
$ok = has_notifications('warning');
clear_notifications();
clear_notifications('error');
set_flash('form_data', $_POST, 1);
$data = get_flash('form_data');
$data = peek_flash('form_data');
$ok = has_flash('form_data');
Mail Deliverability Checks
Engine\Atomic\Mail\MailerUtils -- DNS validation helpers.
$spf = mail_check_spf('example.com');
$dkim = mail_check_dkim('example.com', 'default');
$dmarc = mail_check_dmarc('example.com');
$full = mail_analyze('example.com', 'default');
Shortcodes
add_shortcode('alert', function (array $atts, ?string $content): string {
$type = $atts['type'] ?? 'info';
return "<div class=\"alert alert-$type\">" . ($content ?? '') . "</div>";
});
$html = do_shortcode('[alert type="warning"]Low stock![/alert]');
add_shortcode('icon', function (array $atts, ?string $content): string {
return '<i class="icon-' . ($atts['name'] ?? '') . '"></i>';
});
$html = do_shortcode('[icon name="star"]');
remove_shortcode('alert');
The do_shortcode() helper wraps Shortcode::instance()->do_shortcode($text).
Guardrails
- Keep event and hook handlers small and single-purpose.
- Never call
do_action inside a listener for the same action (infinite loop).
- Call
Mailer::reset() (or $mailer->reset()) between sends in a loop to clear recipients and body.
- Keep locale files as plain arrays without side effects.