- Create AnsibleDeployStage using framework's Process module for secure command execution - Integrate AnsibleDeployStage into DeploymentPipelineCommands for production deployments - Add force_deploy flag support in Ansible playbook to override stale locks - Use PHP deployment module as orchestrator (php console.php deploy:production) - Fix ErrorAggregationInitializer to use Environment class instead of $_ENV superglobal Architecture: - BuildStage → AnsibleDeployStage → HealthCheckStage for production - Process module provides timeout, error handling, and output capture - Ansible playbook supports rollback via rollback-git-based.yml - Zero-downtime deployments with health checks
310 lines
10 KiB
PHP
310 lines
10 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../vendor/autoload.php';
|
|
|
|
use App\Framework\Notification\Templates\NotificationTemplate;
|
|
use App\Framework\Notification\Templates\TemplateRenderer;
|
|
use App\Framework\Notification\Templates\ChannelTemplate;
|
|
use App\Framework\Notification\Templates\InMemoryTemplateRegistry;
|
|
use App\Framework\Notification\ValueObjects\NotificationChannel;
|
|
use App\Framework\Notification\ValueObjects\NotificationPriority;
|
|
use App\Framework\Notification\ValueObjects\SystemNotificationType;
|
|
|
|
/**
|
|
* Notification Template System Example
|
|
*
|
|
* Demonstrates:
|
|
* - Template creation with placeholders
|
|
* - Variable substitution
|
|
* - Per-channel customization
|
|
* - Template registry
|
|
* - Required and default variables
|
|
*/
|
|
|
|
echo "=== Notification Template System Examples ===\n\n";
|
|
|
|
// Setup
|
|
$registry = new InMemoryTemplateRegistry();
|
|
$renderer = new TemplateRenderer();
|
|
|
|
// Example 1: Basic Template with Simple Placeholders
|
|
echo "1. Basic Template - Order Shipped\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$orderShippedTemplate = NotificationTemplate::create(
|
|
name: 'order.shipped',
|
|
titleTemplate: 'Order {{order_id}} Shipped',
|
|
bodyTemplate: 'Your order {{order_id}} has been shipped and will arrive by {{delivery_date}}. Track your package: {{tracking_url}}'
|
|
)->withPriority(NotificationPriority::HIGH)
|
|
->withRequiredVariables('order_id', 'delivery_date', 'tracking_url');
|
|
|
|
$registry->register($orderShippedTemplate);
|
|
|
|
// Render notification
|
|
$notification = $renderer->render(
|
|
template: $orderShippedTemplate,
|
|
recipientId: 'user_123',
|
|
variables: [
|
|
'order_id' => '#12345',
|
|
'delivery_date' => 'December 25, 2024',
|
|
'tracking_url' => 'https://example.com/track/ABC123',
|
|
],
|
|
channels: [NotificationChannel::EMAIL, NotificationChannel::TELEGRAM],
|
|
type: new SystemNotificationType('order.shipped')
|
|
);
|
|
|
|
echo "Title: {$notification->title}\n";
|
|
echo "Body: {$notification->body}\n";
|
|
echo "Priority: {$notification->priority->value}\n";
|
|
echo "Template Data: " . json_encode($notification->data, JSON_PRETTY_PRINT) . "\n";
|
|
echo "\n";
|
|
|
|
// Example 2: Template with Nested Variables
|
|
echo "2. Nested Variables - User Welcome\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$welcomeTemplate = NotificationTemplate::create(
|
|
name: 'user.welcome',
|
|
titleTemplate: 'Welcome to {{app.name}}, {{user.name}}!',
|
|
bodyTemplate: 'Hi {{user.name}}, welcome to {{app.name}}! Your account has been created successfully. Get started here: {{app.url}}'
|
|
)->withRequiredVariables('user.name')
|
|
->withDefaultVariables([
|
|
'app' => [
|
|
'name' => 'My Application',
|
|
'url' => 'https://example.com/start',
|
|
],
|
|
]);
|
|
|
|
$registry->register($welcomeTemplate);
|
|
|
|
$notification = $renderer->render(
|
|
template: $welcomeTemplate,
|
|
recipientId: 'user_456',
|
|
variables: [
|
|
'user' => [
|
|
'name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
],
|
|
],
|
|
channels: [NotificationChannel::EMAIL],
|
|
type: new SystemNotificationType('user.welcome')
|
|
);
|
|
|
|
echo "Title: {$notification->title}\n";
|
|
echo "Body: {$notification->body}\n";
|
|
echo "\n";
|
|
|
|
// Example 3: Per-Channel Customization
|
|
echo "3. Per-Channel Templates - Different Formats\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$securityAlertTemplate = NotificationTemplate::create(
|
|
name: 'security.alert',
|
|
titleTemplate: 'Security Alert',
|
|
bodyTemplate: 'Unusual login activity detected from {{ip_address}} at {{time}}.'
|
|
)->withPriority(NotificationPriority::URGENT);
|
|
|
|
// Telegram: Use Markdown formatting
|
|
$telegramTemplate = ChannelTemplate::create(
|
|
titleTemplate: '🔒 *Security Alert*',
|
|
bodyTemplate: '⚠️ Unusual login activity detected:\n\n📍 IP: `{{ip_address}}`\n⏰ Time: {{time}}\n\nIf this wasn\'t you, secure your account immediately!'
|
|
)->withMetadata(['parse_mode' => 'Markdown']);
|
|
|
|
// Email: Use HTML formatting
|
|
$emailTemplate = ChannelTemplate::create(
|
|
titleTemplate: '🔒 Security Alert',
|
|
bodyTemplate: '<h2>Unusual Login Activity</h2><p>We detected a login from <strong>{{ip_address}}</strong> at {{time}}.</p><p>If this wasn\'t you, please secure your account immediately.</p>'
|
|
)->withMetadata(['content_type' => 'text/html']);
|
|
|
|
// SMS: Keep it short and plain
|
|
$smsTemplate = ChannelTemplate::create(
|
|
bodyTemplate: 'SECURITY ALERT: Login from {{ip_address}} at {{time}}. If not you, secure account now.'
|
|
);
|
|
|
|
$securityAlertTemplate = $securityAlertTemplate
|
|
->withChannelTemplate(NotificationChannel::TELEGRAM, $telegramTemplate)
|
|
->withChannelTemplate(NotificationChannel::EMAIL, $emailTemplate)
|
|
->withChannelTemplate(NotificationChannel::SMS, $smsTemplate);
|
|
|
|
$registry->register($securityAlertTemplate);
|
|
|
|
// Render for each channel
|
|
$variables = [
|
|
'ip_address' => '203.0.113.42',
|
|
'time' => '2024-12-19 15:30:00 UTC',
|
|
];
|
|
|
|
echo "TELEGRAM VERSION:\n";
|
|
$telegramContent = $renderer->renderForChannel(
|
|
$securityAlertTemplate,
|
|
NotificationChannel::TELEGRAM,
|
|
$variables
|
|
);
|
|
echo "Title: {$telegramContent->title}\n";
|
|
echo "Body:\n{$telegramContent->body}\n";
|
|
echo "Metadata: " . json_encode($telegramContent->metadata) . "\n\n";
|
|
|
|
echo "EMAIL VERSION:\n";
|
|
$emailContent = $renderer->renderForChannel(
|
|
$securityAlertTemplate,
|
|
NotificationChannel::EMAIL,
|
|
$variables
|
|
);
|
|
echo "Title: {$emailContent->title}\n";
|
|
echo "Body:\n{$emailContent->body}\n";
|
|
echo "Metadata: " . json_encode($emailContent->metadata) . "\n\n";
|
|
|
|
echo "SMS VERSION:\n";
|
|
$smsContent = $renderer->renderForChannel(
|
|
$securityAlertTemplate,
|
|
NotificationChannel::SMS,
|
|
$variables
|
|
);
|
|
echo "Body: {$smsContent->body}\n";
|
|
echo "\n";
|
|
|
|
// Example 4: Template with Default Variables
|
|
echo "4. Default Variables - Newsletter Template\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$newsletterTemplate = NotificationTemplate::create(
|
|
name: 'newsletter.weekly',
|
|
titleTemplate: '{{newsletter.title}} - Week {{week_number}}',
|
|
bodyTemplate: 'Hi {{user.name}}, here\'s your weekly {{newsletter.title}}! This week\'s highlights: {{highlights}}. Read more: {{newsletter.url}}'
|
|
)->withDefaultVariables([
|
|
'newsletter' => [
|
|
'title' => 'Weekly Update',
|
|
'url' => 'https://example.com/newsletter',
|
|
],
|
|
'highlights' => 'New features, bug fixes, and improvements',
|
|
])->withRequiredVariables('user.name', 'week_number');
|
|
|
|
$registry->register($newsletterTemplate);
|
|
|
|
$notification = $renderer->render(
|
|
template: $newsletterTemplate,
|
|
recipientId: 'user_789',
|
|
variables: [
|
|
'user' => ['name' => 'Jane Smith'],
|
|
'week_number' => '51',
|
|
// Using default values for newsletter and highlights
|
|
],
|
|
channels: [NotificationChannel::EMAIL],
|
|
type: new SystemNotificationType('newsletter.weekly')
|
|
);
|
|
|
|
echo "Title: {$notification->title}\n";
|
|
echo "Body: {$notification->body}\n";
|
|
echo "\n";
|
|
|
|
// Example 5: Template Registry Usage
|
|
echo "5. Template Registry - Lookup and Reuse\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
echo "Registered templates:\n";
|
|
foreach ($registry->all() as $name => $template) {
|
|
echo " - {$name} (Priority: {$template->defaultPriority->value})\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Reuse template from registry
|
|
$template = $registry->get('order.shipped');
|
|
if ($template !== null) {
|
|
echo "Retrieved template: {$template->name}\n";
|
|
echo "Required variables: " . implode(', ', $template->requiredVariables) . "\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Example 6: Error Handling - Missing Required Variable
|
|
echo "6. Error Handling - Validation\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
try {
|
|
$renderer->render(
|
|
template: $orderShippedTemplate,
|
|
recipientId: 'user_999',
|
|
variables: [
|
|
'order_id' => '#67890',
|
|
// Missing 'delivery_date' and 'tracking_url'
|
|
],
|
|
channels: [NotificationChannel::EMAIL],
|
|
type: new SystemNotificationType('order.shipped')
|
|
);
|
|
} catch (\InvalidArgumentException $e) {
|
|
echo "❌ Validation Error: {$e->getMessage()}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Example 7: Complex Object in Variables
|
|
echo "7. Complex Objects - Value Object Support\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$paymentTemplate = NotificationTemplate::create(
|
|
name: 'payment.received',
|
|
titleTemplate: 'Payment Received',
|
|
bodyTemplate: 'We received your payment of {{amount}} on {{date}}. Transaction ID: {{transaction.id}}'
|
|
);
|
|
|
|
// Create notification with object variables
|
|
$notification = $renderer->render(
|
|
template: $paymentTemplate,
|
|
recipientId: 'user_101',
|
|
variables: [
|
|
'amount' => '$99.00',
|
|
'date' => '2024-12-19',
|
|
'transaction' => [
|
|
'id' => 'TXN_123456',
|
|
'status' => 'completed',
|
|
],
|
|
],
|
|
channels: [NotificationChannel::EMAIL, NotificationChannel::TELEGRAM],
|
|
type: new SystemNotificationType('payment.received')
|
|
);
|
|
|
|
echo "Title: {$notification->title}\n";
|
|
echo "Body: {$notification->body}\n";
|
|
echo "\n";
|
|
|
|
// Example 8: Integration with NotificationDispatcher
|
|
echo "8. Template + Dispatcher Integration\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
echo "Step 1: Create template\n";
|
|
$template = NotificationTemplate::create(
|
|
name: 'account.deleted',
|
|
titleTemplate: 'Account Deletion Confirmation',
|
|
bodyTemplate: 'Your account {{username}} has been permanently deleted on {{deletion_date}}.'
|
|
)->withPriority(NotificationPriority::URGENT);
|
|
|
|
echo "Step 2: Render notification from template\n";
|
|
$notification = $renderer->render(
|
|
template: $template,
|
|
recipientId: 'user_202',
|
|
variables: [
|
|
'username' => 'johndoe',
|
|
'deletion_date' => '2024-12-19',
|
|
],
|
|
channels: [NotificationChannel::EMAIL, NotificationChannel::SMS],
|
|
type: new SystemNotificationType('account.deleted')
|
|
);
|
|
|
|
echo "Step 3: Dispatch via NotificationDispatcher\n";
|
|
echo " (In real app: \$dispatcher->sendNow(\$notification, DispatchStrategy::ALL_OR_NONE))\n";
|
|
echo " Notification ready for dispatch:\n";
|
|
echo " - Title: {$notification->title}\n";
|
|
echo " - Channels: " . count($notification->channels) . "\n";
|
|
echo " - Priority: {$notification->priority->value}\n";
|
|
echo "\n";
|
|
|
|
// Summary
|
|
echo "=== Template System Summary ===\n";
|
|
echo "✅ Created " . count($registry->all()) . " templates\n";
|
|
echo "✅ Demonstrated placeholder substitution ({{variable}})\n";
|
|
echo "✅ Demonstrated nested variables ({{user.name}})\n";
|
|
echo "✅ Demonstrated per-channel customization\n";
|
|
echo "✅ Demonstrated default variables\n";
|
|
echo "✅ Demonstrated validation and error handling\n";
|
|
echo "✅ Template system ready for production use\n";
|