diff --git a/app/Commands/Incident/ReportIncidentCommand.php b/app/Commands/Incident/ReportIncidentCommand.php index 25bae98a..a4bcda9e 100644 --- a/app/Commands/Incident/ReportIncidentCommand.php +++ b/app/Commands/Incident/ReportIncidentCommand.php @@ -69,6 +69,20 @@ final class ReportIncidentCommand */ public $incident_date; + /** + * A given incident template. + * + * @var string|null + */ + public $template; + + /** + * Variables for the incident template. + * + * @var string[]|null + */ + public $template_vars; + /** * The validation rules. * @@ -83,6 +97,7 @@ final class ReportIncidentCommand 'component_status' => 'int|min:1|max:4|required_with:component_id', 'notify' => 'bool', 'incident_date' => 'string', + 'template' => 'string', ]; /** @@ -96,10 +111,12 @@ final class ReportIncidentCommand * @param int $component_status * @param bool $notify * @param string|null $incident_date + * @param string|null $template + * @param array|null $template_vars * * @return void */ - public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $incident_date) + public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $incident_date, $template, $template_vars) { $this->name = $name; $this->status = $status; @@ -109,5 +126,7 @@ final class ReportIncidentCommand $this->component_status = $component_status; $this->notify = $notify; $this->incident_date = $incident_date; + $this->template = $template; + $this->template_vars = $template_vars; } } diff --git a/app/Commands/Incident/UpdateIncidentCommand.php b/app/Commands/Incident/UpdateIncidentCommand.php index 41c7ddd4..7517b7ec 100644 --- a/app/Commands/Incident/UpdateIncidentCommand.php +++ b/app/Commands/Incident/UpdateIncidentCommand.php @@ -78,6 +78,20 @@ final class UpdateIncidentCommand */ public $incident_date; + /** + * A given incident template. + * + * @var string|null + */ + public $template; + + /** + * Variables for the incident template. + * + * @var string[]|null + */ + public $template_vars; + /** * The validation rules. * @@ -91,6 +105,7 @@ final class UpdateIncidentCommand 'component_id' => 'int', 'component_status' => 'int|min:1|max:4|required_with:component_id', 'notify' => 'bool', + 'template' => 'string', ]; /** @@ -105,10 +120,12 @@ final class UpdateIncidentCommand * @param int $component_status * @param bool $notify * @param string|null $incident_date + * @param string|null $template + * @param array|null $template_vars * * @return void */ - public function __construct(Incident $incident, $name, $status, $message, $visible, $component_id, $component_status, $notify, $incident_date = null) + public function __construct(Incident $incident, $name, $status, $message, $visible, $component_id, $component_status, $notify, $incident_date, $template, $template_vars) { $this->incident = $incident; $this->name = $name; @@ -119,5 +136,7 @@ final class UpdateIncidentCommand $this->component_status = $component_status; $this->notify = $notify; $this->incident_date = $incident_date; + $this->template = $template; + $this->template_vars = $template_vars; } } diff --git a/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php b/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php index 0e85d0e0..b9a0d379 100644 --- a/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php +++ b/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php @@ -16,6 +16,9 @@ use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Events\Incident\IncidentWasReportedEvent; use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\Incident; +use CachetHQ\Cachet\Models\IncidentTemplate; +use Twig_Loader_String; +use TwigBridge\Facade\Twig; class ReportIncidentCommandHandler { @@ -47,6 +50,10 @@ class ReportIncidentCommandHandler */ public function handle(ReportIncidentCommand $command) { + if ($command->template) { + $command->message = $this->parseIncidentTemplate($command->template, $command->template_vars); + } + $data = [ 'name' => $command->name, 'status' => $command->status, @@ -81,4 +88,20 @@ class ReportIncidentCommandHandler return $incident; } + + /** + * Compiles an incident template into an incident message. + * + * @param string $templateSlug + * @param array $vars + * + * @return string + */ + protected function parseIncidentTemplate($templateSlug, $vars) + { + Twig::setLoader(new Twig_Loader_String()); + $template = IncidentTemplate::forSlug($templateSlug)->first(); + + return Twig::render($template->template, $vars); + } } diff --git a/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php b/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php index c9303bce..7a6bed4f 100644 --- a/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php +++ b/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php @@ -16,6 +16,9 @@ use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Events\Incident\IncidentWasUpdatedEvent; use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\Incident; +use CachetHQ\Cachet\Models\IncidentTemplate; +use Twig_Loader_String; +use TwigBridge\Facade\Twig; class UpdateIncidentCommandHandler { @@ -47,6 +50,10 @@ class UpdateIncidentCommandHandler */ public function handle(UpdateIncidentCommand $command) { + if ($command->template) { + $command->message = $this->parseIncidentTemplate($command->template, $command->template_vars); + } + $incident = $command->incident; $incident->update($this->filterIncidentData($command)); @@ -91,4 +98,20 @@ class UpdateIncidentCommandHandler 'notify' => $command->notify, ]); } + + /** + * Compiles an incident template into an incident message. + * + * @param string $templateSlug + * @param array $vars + * + * @return string + */ + protected function parseIncidentTemplate($templateSlug, $vars) + { + Twig::setLoader(new Twig_Loader_String()); + $template = IncidentTemplate::forSlug($templateSlug)->first(); + + return Twig::render($template->template, $vars); + } } diff --git a/app/Http/Controllers/Api/IncidentController.php b/app/Http/Controllers/Api/IncidentController.php index b5bf8e77..c0d482a2 100644 --- a/app/Http/Controllers/Api/IncidentController.php +++ b/app/Http/Controllers/Api/IncidentController.php @@ -73,7 +73,9 @@ class IncidentController extends AbstractApiController Binput::get('component_id'), Binput::get('component_status'), Binput::get('notify', true), - Binput::get('created_at') + Binput::get('created_at'), + Binput::get('template'), + Binput::get('vars') )); } catch (Exception $e) { throw new BadRequestHttpException(); @@ -101,7 +103,9 @@ class IncidentController extends AbstractApiController Binput::get('component_id'), Binput::get('component_status'), Binput::get('notify', true), - Binput::get('created_at') + Binput::get('created_at'), + Binput::get('template'), + Binput::get('vars') )); } catch (Exception $e) { throw new BadRequestHttpException(); diff --git a/app/Models/IncidentTemplate.php b/app/Models/IncidentTemplate.php index ecb40abf..a810198f 100644 --- a/app/Models/IncidentTemplate.php +++ b/app/Models/IncidentTemplate.php @@ -58,4 +58,17 @@ class IncidentTemplate extends Model $template->slug = Str::slug($template->name); }); } + + /** + * Finds a template by the slug. + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $slug + * + * @return \Illuminate\Database\Query\Builder + */ + public function scopeForSlug($query, $slug) + { + return $query->where('slug', $slug); + } } diff --git a/composer.json b/composer.json index c9988d94..81745e82 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,8 @@ "jenssegers/date": "^3.0", "mccool/laravel-auto-presenter": "^4.2", "pragmarx/google2fa": "^0.7", - "roumen/feed": "^2.9" + "roumen/feed": "^2.9", + "rcrowe/twigbridge": "^0.9.0" }, "require-dev": { "fzaninotto/faker": "^1.5", diff --git a/composer.lock b/composer.lock index a4d3c401..d9bad787 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f139419cc0b4579b34749d181cf9c15b", - "content-hash": "cb98697488db5c325f3fb86c98dddef8", + "hash": "ff4fd4c7d8c30ce6da667c81caa67372", + "content-hash": "dd7e113fcc687c33e7d47bdc27b87f75", "packages": [ { "name": "alt-three/emoji", @@ -2593,6 +2593,70 @@ ], "time": "2015-11-12 16:18:56" }, + { + "name": "rcrowe/twigbridge", + "version": "v0.9.0", + "source": { + "type": "git", + "url": "https://github.com/rcrowe/TwigBridge.git", + "reference": "f875fa9457ebadf8f24b683b226848b660407f8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/f875fa9457ebadf8f24b683b226848b660407f8f", + "reference": "f875fa9457ebadf8f24b683b226848b660407f8f", + "shasum": "" + }, + "require": { + "illuminate/support": "5.0.*|5.1.*", + "illuminate/view": "5.0.*|5.1.*", + "php": ">=5.4.0", + "twig/twig": "~1.15|~2.0" + }, + "require-dev": { + "laravel/framework": "5.0.*", + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "~0.6", + "squizlabs/php_codesniffer": "~1.5" + }, + "suggest": { + "laravelcollective/html": "For bringing back html/form in Laravel 5.x", + "twig/extensions": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.8-dev" + } + }, + "autoload": { + "psr-4": { + "TwigBridge\\": "src", + "TwigBridge\\Tests\\": "tests" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + }, + { + "name": "Rob Crowe", + "email": "hello@vivalacrowe.com" + } + ], + "description": "Adds the power of Twig to Laravel", + "keywords": [ + "laravel", + "twig" + ], + "time": "2015-11-02 17:37:16" + }, { "name": "roumen/feed", "version": "v2.9.7", @@ -3426,6 +3490,67 @@ ], "time": "2015-10-25 17:17:38" }, + { + "name": "twig/twig", + "version": "v1.23.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/d9b6333ae8dd2c8e3fd256e127548def0bc614c6", + "reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6", + "shasum": "" + }, + "require": { + "php": ">=5.2.7" + }, + "require-dev": { + "symfony/debug": "~2.7", + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.23-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "http://twig.sensiolabs.org/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ], + "time": "2015-11-05 12:49:06" + }, { "name": "vlucas/phpdotenv", "version": "v1.1.1", diff --git a/config/app.php b/config/app.php index 5edad018..f4f438fa 100644 --- a/config/app.php +++ b/config/app.php @@ -162,6 +162,7 @@ return [ 'McCool\LaravelAutoPresenter\AutoPresenterServiceProvider', 'PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider', 'Roumen\Feed\FeedServiceProvider', + 'TwigBridge\ServiceProvider', /* * Application Service Providers... diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 1286013e..3c3d00b9 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -74,3 +74,14 @@ $factory->define('CachetHQ\Cachet\Models\Subscriber', function ($faker) { 'verified_at' => Carbon::now(), ]; }); + +$factory->define('CachetHQ\Cachet\Models\IncidentTemplate', function ($faker) { + return [ + 'name' => 'Test Template', + 'slug' => 'test-template', + 'template' => << [ 'name' => 'Navn', 'template' => 'Skabelon', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/de/forms.php b/resources/lang/de/forms.php index 75dd4ceb..0c7224ee 100755 --- a/resources/lang/de/forms.php +++ b/resources/lang/de/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Name', 'template' => 'Vorlage', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/en/forms.php b/resources/lang/en/forms.php index bdf31581..0cc9c2b0 100755 --- a/resources/lang/en/forms.php +++ b/resources/lang/en/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Name', 'template' => 'Template', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/es/forms.php b/resources/lang/es/forms.php index 45faba9d..e2a586b5 100755 --- a/resources/lang/es/forms.php +++ b/resources/lang/es/forms.php @@ -44,6 +44,7 @@ return [ 'templates' => [ 'name' => 'Nombre', 'template' => 'Plantilla', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/fr/forms.php b/resources/lang/fr/forms.php index 3bdb0762..f2d7e27f 100755 --- a/resources/lang/fr/forms.php +++ b/resources/lang/fr/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Nom', 'template' => 'Modéle', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/id/forms.php b/resources/lang/id/forms.php index 7c9dfc0b..37531b2b 100755 --- a/resources/lang/id/forms.php +++ b/resources/lang/id/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Nama', 'template' => 'Template', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/it/forms.php b/resources/lang/it/forms.php index 7f71fe93..fbcca971 100644 --- a/resources/lang/it/forms.php +++ b/resources/lang/it/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Nome', 'template' => 'Modello', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/ko/forms.php b/resources/lang/ko/forms.php index 9842f60e..2f2e52cb 100755 --- a/resources/lang/ko/forms.php +++ b/resources/lang/ko/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => '이름', 'template' => '템플릿', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/nl/forms.php b/resources/lang/nl/forms.php index a10caad0..c69ebfa3 100755 --- a/resources/lang/nl/forms.php +++ b/resources/lang/nl/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Naam', 'template' => 'Sjabloon', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/pl/forms.php b/resources/lang/pl/forms.php index ef2843c6..40b8752f 100755 --- a/resources/lang/pl/forms.php +++ b/resources/lang/pl/forms.php @@ -45,6 +45,7 @@ return [ 'templates' => [ 'name' => 'Nazwa', 'template' => 'Szablon', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/pt-BR/forms.php b/resources/lang/pt-BR/forms.php index bb034a5e..e7a10928 100755 --- a/resources/lang/pt-BR/forms.php +++ b/resources/lang/pt-BR/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Nome', 'template' => 'Template', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/ru/forms.php b/resources/lang/ru/forms.php index 2173f5bb..72cb5114 100644 --- a/resources/lang/ru/forms.php +++ b/resources/lang/ru/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => 'Название', 'template' => 'Шаблон', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/zh-CN/forms.php b/resources/lang/zh-CN/forms.php index 2ec50bd4..e2cf0971 100755 --- a/resources/lang/zh-CN/forms.php +++ b/resources/lang/zh-CN/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => '事件模板名', 'template' => '模板', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/lang/zh-TW/forms.php b/resources/lang/zh-TW/forms.php index 86b655ec..f7bee1b9 100644 --- a/resources/lang/zh-TW/forms.php +++ b/resources/lang/zh-TW/forms.php @@ -51,6 +51,7 @@ return [ 'templates' => [ 'name' => '事件模板名', 'template' => '模板', + 'twig' => 'Incident Templates can make use of the Twig templating language.', ], ], diff --git a/resources/views/dashboard/partials/head.blade.php b/resources/views/dashboard/partials/head.blade.php index 69a5ba87..0406bb96 100644 --- a/resources/views/dashboard/partials/head.blade.php +++ b/resources/views/dashboard/partials/head.blade.php @@ -22,13 +22,7 @@ + @yield('css') @include('partials.crowdin') - - - - diff --git a/resources/views/dashboard/templates/add.blade.php b/resources/views/dashboard/templates/add.blade.php index bc5b0db7..c4b6d67e 100644 --- a/resources/views/dashboard/templates/add.blade.php +++ b/resources/views/dashboard/templates/add.blade.php @@ -1,5 +1,25 @@ @extends('layout.dashboard') +@section('css') + +@stop + +@section('js') + + + + +@stop + @section('content')
-
- -
+ + {!! trans('forms.incidents.templates.twig') !!}
diff --git a/resources/views/dashboard/templates/edit.blade.php b/resources/views/dashboard/templates/edit.blade.php index d96db825..fb7cf9e3 100644 --- a/resources/views/dashboard/templates/edit.blade.php +++ b/resources/views/dashboard/templates/edit.blade.php @@ -1,5 +1,25 @@ @extends('layout.dashboard') +@section('css') + +@stop + +@section('js') + + + + +@stop + @section('content')
-
- -
+ + {!! trans('forms.incidents.templates.twig') !!}
diff --git a/resources/views/layout/dashboard.blade.php b/resources/views/layout/dashboard.blade.php index b78a710d..b186e450 100644 --- a/resources/views/layout/dashboard.blade.php +++ b/resources/views/layout/dashboard.blade.php @@ -9,5 +9,11 @@ @yield('content')
+ + @yield('js') + diff --git a/tests/Api/IncidentTest.php b/tests/Api/IncidentTest.php index 14887912..ddbd1ee5 100644 --- a/tests/Api/IncidentTest.php +++ b/tests/Api/IncidentTest.php @@ -63,6 +63,27 @@ class IncidentTest extends AbstractTestCase $this->assertResponseOk(); } + public function testCreateIncidentWithTemplate() + { + $template = factory('CachetHQ\Cachet\Models\IncidentTemplate')->create(); + $this->beUser(); + + $this->post('/api/v1/incidents', [ + 'name' => 'Foo', + 'status' => 1, + 'visible' => 1, + 'template' => $template->slug, + 'vars' => [ + 'name' => 'Foo', + 'message' => 'Hello there this is a foo!', + ], + ]); + $this->seeJson([ + 'name' => 'Foo', + 'message' => "Name: Foo,\nMessage: Hello there this is a foo!", + ]); + } + public function testGetNewIncident() { $incident = factory('CachetHQ\Cachet\Models\Incident')->create(); @@ -84,6 +105,27 @@ class IncidentTest extends AbstractTestCase $this->assertResponseOk(); } + public function testPutIncidentWithTemplate() + { + $this->beUser(); + $template = factory('CachetHQ\Cachet\Models\IncidentTemplate')->create(); + $component = factory('CachetHQ\Cachet\Models\Incident')->create(); + + $this->put('/api/v1/incidents/1', [ + 'name' => 'Foo', + 'template' => $template->slug, + 'vars' => [ + 'name' => 'Foo', + 'message' => 'Hello there this is a foo!', + ], + ]); + $this->seeJson([ + 'name' => 'Foo', + 'message' => "Name: Foo,\nMessage: Hello there this is a foo!", + ]); + $this->assertResponseOk(); + } + public function testDeleteIncident() { $this->beUser(); diff --git a/tests/Commands/Incident/ReportIncidentCommandTest.php b/tests/Commands/Incident/ReportIncidentCommandTest.php index c6e4bcf7..729ecb0a 100644 --- a/tests/Commands/Incident/ReportIncidentCommandTest.php +++ b/tests/Commands/Incident/ReportIncidentCommandTest.php @@ -33,6 +33,8 @@ class ReportIncidentCommandTest extends AbstractCommandTestCase 'component_status' => 1, 'notify' => false, 'incident_date' => null, + 'template' => null, + 'template_vars' => null, ]; $object = new ReportIncidentCommand( $params['name'], @@ -42,7 +44,9 @@ class ReportIncidentCommandTest extends AbstractCommandTestCase $params['component_id'], $params['component_status'], $params['notify'], - $params['incident_date'] + $params['incident_date'], + $params['template'], + $params['template_vars'] ); return compact('params', 'object'); diff --git a/tests/Commands/Incident/UpdateIncidentCommandTest.php b/tests/Commands/Incident/UpdateIncidentCommandTest.php index fe3eceb7..b7efc893 100644 --- a/tests/Commands/Incident/UpdateIncidentCommandTest.php +++ b/tests/Commands/Incident/UpdateIncidentCommandTest.php @@ -35,6 +35,8 @@ class UpdateIncidentCommandTest extends AbstractCommandTestCase 'component_status' => 1, 'notify' => false, 'incident_date' => null, + 'template' => null, + 'template_vars' => null, ]; $object = new UpdateIncidentCommand( $params['incident'], @@ -45,7 +47,9 @@ class UpdateIncidentCommandTest extends AbstractCommandTestCase $params['component_id'], $params['component_status'], $params['notify'], - $params['incident_date'] + $params['incident_date'], + $params['template'], + $params['template_vars'] ); return compact('params', 'object');