From 4b9e0141e8ec9ed2915d7e7012acda6bb8431111 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 19:23:53 +0100 Subject: [PATCH 1/8] Create meta table and model --- app/Models/Meta.php | 68 +++++++++++++++++++ .../2017_06_13_181049_CreateMetaTable.php | 46 +++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 app/Models/Meta.php create mode 100644 database/migrations/2017_06_13_181049_CreateMetaTable.php diff --git a/app/Models/Meta.php b/app/Models/Meta.php new file mode 100644 index 000000000000..b590ef82a988 --- /dev/null +++ b/app/Models/Meta.php @@ -0,0 +1,68 @@ + + */ +class Meta extends Model +{ + use ValidatingTrait; + + /** + * The attributes that should be casted to native types. + * + * @var string[] + */ + protected $casts = [ + 'id' => 'int', + 'key' => 'string', + 'value' => 'json', + 'meta_id' => 'int', + 'meta_type' => 'string', + ]; + + /** + * The validation rules. + * + * @var string[] + */ + public $rules = [ + 'id' => 'nullable|int|min:1', + 'key' => 'required|string', + 'value' => 'nullable', + 'meta_id' => 'required|int', + 'meta_type' => 'required|string', + ]; + + /** + * The table associated with the model. + * + * @var string + */ + protected $table = 'meta'; + + /** + * Get all of the owning meta models. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphTo + */ + public function meta() + { + return $this->morphTo(); + } +} diff --git a/database/migrations/2017_06_13_181049_CreateMetaTable.php b/database/migrations/2017_06_13_181049_CreateMetaTable.php new file mode 100644 index 000000000000..30f73b14c760 --- /dev/null +++ b/database/migrations/2017_06_13_181049_CreateMetaTable.php @@ -0,0 +1,46 @@ +increments('id'); + $table->string('key')->index(); + $table->string('value'); + $table->integer('meta_id')->unsigned(); + $table->string('meta_type'); + $table->timestamps(); + + $table->index(['meta_id', 'meta_type']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('meta'); + } +} From 9cd5faaa6b77f78a62a409ea2e8a870ca1507755 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 19:24:21 +0100 Subject: [PATCH 2/8] Register the relations morph map --- app/Foundation/Providers/AppServiceProvider.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/Foundation/Providers/AppServiceProvider.php b/app/Foundation/Providers/AppServiceProvider.php index 77bf2906e8e2..a1bfcd9c4474 100644 --- a/app/Foundation/Providers/AppServiceProvider.php +++ b/app/Foundation/Providers/AppServiceProvider.php @@ -14,6 +14,7 @@ use AltThree\Bus\Dispatcher; use CachetHQ\Cachet\Bus\Middleware\UseDatabaseTransactions; use CachetHQ\Cachet\Services\Dates\DateFactory; +use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; @@ -42,6 +43,14 @@ public function boot(Dispatcher $dispatcher) Str::macro('canonicalize', function ($url) { return preg_replace('/([^\/])$/', '$1/', $url); }); + + Relation::morphMap([ + 'components' => \CachetHQ\Cachet\Models\Component::class, + 'incidents' => \CachetHQ\Cachet\Models\Incident::class, + 'metrics' => \CachetHQ\Cachet\Models\Metric::class, + 'schedules' => \CachetHQ\Cachet\Models\Schedule::class, + 'subscriber' => \CachetHQ\Cachet\Models\Subscriber::class, + ]); } /** From 1faee910f34cb6a177447bc7f8c346f8d100a743 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 19:25:16 +0100 Subject: [PATCH 3/8] Add test for meta model --- tests/Models/MetaTest.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/Models/MetaTest.php diff --git a/tests/Models/MetaTest.php b/tests/Models/MetaTest.php new file mode 100644 index 000000000000..72bc47f440a2 --- /dev/null +++ b/tests/Models/MetaTest.php @@ -0,0 +1,31 @@ + + */ +class MetaTest extends AbstractTestCase +{ + use ValidationTrait; + + public function testValidation() + { + $this->checkRules(new Meta()); + } +} From 507ae3e4ed1dd97be333e00d05a1ab13a57a90a0 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 19:25:43 +0100 Subject: [PATCH 4/8] Add meta relation to all models --- app/Models/Component.php | 10 ++++++++++ app/Models/Incident.php | 15 ++++++++++++++- app/Models/Metric.php | 10 ++++++++++ app/Models/Schedule.php | 30 ++++++++++++++++++++---------- app/Models/Subscriber.php | 10 ++++++++++ 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/app/Models/Component.php b/app/Models/Component.php index 783d426d70b5..3d898afb2572 100644 --- a/app/Models/Component.php +++ b/app/Models/Component.php @@ -134,6 +134,16 @@ public function incidents() return $this->hasMany(Incident::class, 'component_id', 'id'); } + /** + * Get all of the meta relation. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function meta() + { + return $this->morphMany(Meta::class, 'meta'); + } + /** * Get the tags relation. * diff --git a/app/Models/Incident.php b/app/Models/Incident.php index 1816f850a60b..93b4be67f001 100644 --- a/app/Models/Incident.php +++ b/app/Models/Incident.php @@ -145,7 +145,10 @@ class Incident extends Model implements HasPresenter * * @var string[] */ - protected $with = ['updates']; + protected $with = [ + 'meta', + 'updates', + ]; /** * Get the component relation. @@ -157,6 +160,16 @@ public function component() return $this->belongsTo(Component::class, 'component_id', 'id'); } + /** + * Get all of the meta relation. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function meta() + { + return $this->morphMany(Meta::class, 'meta'); + } + /** * Get the updates relation. * diff --git a/app/Models/Metric.php b/app/Models/Metric.php index ce3a6f466d5d..a126ab3742e3 100644 --- a/app/Models/Metric.php +++ b/app/Models/Metric.php @@ -165,6 +165,16 @@ public static function boot() }); } + /** + * Get all of the meta relation. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function meta() + { + return $this->morphMany(Meta::class, 'meta'); + } + /** * Get the points relation. * diff --git a/app/Models/Schedule.php b/app/Models/Schedule.php index 3154c4e9d0cf..020c15059dbc 100644 --- a/app/Models/Schedule.php +++ b/app/Models/Schedule.php @@ -131,6 +131,26 @@ class Schedule extends Model implements HasPresenter */ protected $with = ['components']; + /** + * Get the components relation. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function components() + { + return $this->hasMany(ScheduleComponent::class); + } + + /** + * Get all of the meta relation. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function meta() + { + return $this->morphMany(Meta::class, 'meta'); + } + /** * Scopes schedules to those in the future. * @@ -155,16 +175,6 @@ public function scopePastSchedules($query) return $query->where('status', '<', self::COMPLETE)->where('scheduled_at', '<=', Carbon::now()); } - /** - * Get the components relation. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany - */ - public function components() - { - return $this->hasMany(ScheduleComponent::class); - } - /** * Get the presenter class. * diff --git a/app/Models/Subscriber.php b/app/Models/Subscriber.php index de3e3838c105..964a73ebad48 100644 --- a/app/Models/Subscriber.php +++ b/app/Models/Subscriber.php @@ -90,6 +90,16 @@ public static function boot() }); } + /** + * Get all of the meta relation. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function meta() + { + return $this->morphMany(Meta::class, 'meta'); + } + /** * Get the subscriptions relation. * From 27e390ec17207322fd1c26d05f13216fe4067ecc Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 19:34:31 +0100 Subject: [PATCH 5/8] Make the meta model fillable --- app/Models/Meta.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/Models/Meta.php b/app/Models/Meta.php index b590ef82a988..fe3f8bcafdb9 100644 --- a/app/Models/Meta.php +++ b/app/Models/Meta.php @@ -36,6 +36,18 @@ class Meta extends Model 'meta_type' => 'string', ]; + /** + * The fillable properties. + * + * @var string[] + */ + protected $fillable = [ + 'key', + 'value', + 'meta_id', + 'meta_type', + ]; + /** * The validation rules. * From 63e38a4b2c5587b4ca048c7e426a39f2c09f506b Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 19:34:42 +0100 Subject: [PATCH 6/8] Format meta for incidents as key/value pairs --- app/Presenters/IncidentPresenter.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/Presenters/IncidentPresenter.php b/app/Presenters/IncidentPresenter.php index 227acb1bdaed..d2e013dbc3e8 100644 --- a/app/Presenters/IncidentPresenter.php +++ b/app/Presenters/IncidentPresenter.php @@ -279,6 +279,16 @@ public function duration() return 0; } + /** + * Return the meta in a key value pair. + * + * @return array + */ + public function meta() + { + return $this->wrappedObject->meta->pluck('value', 'key')->all(); + } + /** * Convert the presenter instance to an array. * @@ -294,6 +304,7 @@ public function toArray() 'latest_icon' => $this->latest_icon(), 'permalink' => $this->permalink(), 'duration' => $this->duration(), + 'meta' => $this->meta(), 'occurred_at' => $this->occurred_at(), 'created_at' => $this->created_at(), 'updated_at' => $this->updated_at(), From f11c1edeee1a5aa9f8827939473d7658a039f8b1 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 19:34:50 +0100 Subject: [PATCH 7/8] Implement creating of meta data and tests --- .../Incident/CreateIncidentCommand.php | 12 ++++++++++- .../Incident/CreateIncidentCommandHandler.php | 13 ++++++++++++ .../Controllers/Api/IncidentController.php | 3 ++- tests/Api/IncidentTest.php | 20 +++++++++++++++++++ .../Incident/CreateIncidentCommandTest.php | 4 +++- 5 files changed, 49 insertions(+), 3 deletions(-) diff --git a/app/Bus/Commands/Incident/CreateIncidentCommand.php b/app/Bus/Commands/Incident/CreateIncidentCommand.php index ae8f5f97a1a6..5ed21694f91b 100644 --- a/app/Bus/Commands/Incident/CreateIncidentCommand.php +++ b/app/Bus/Commands/Incident/CreateIncidentCommand.php @@ -96,6 +96,13 @@ final class CreateIncidentCommand */ public $template_vars; + /** + * Meta key/value pairs. + * + * @var array + */ + public $meta = []; + /** * The validation rules. * @@ -112,6 +119,7 @@ final class CreateIncidentCommand 'stickied' => 'required|bool', 'occurred_at' => 'nullable|string', 'template' => 'nullable|string', + 'meta' => 'required|array', ]; /** @@ -128,10 +136,11 @@ final class CreateIncidentCommand * @param string|null $occurred_at * @param string|null $template * @param array $template_vars + * @param array $meta * * @return void */ - public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $occurred_at, $template, array $template_vars = []) + public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $occurred_at, $template, array $template_vars = [], $meta = []) { $this->name = $name; $this->status = $status; @@ -144,5 +153,6 @@ public function __construct($name, $status, $message, $visible, $component_id, $ $this->occurred_at = $occurred_at; $this->template = $template; $this->template_vars = $template_vars; + $this->meta = $meta; } } diff --git a/app/Bus/Handlers/Commands/Incident/CreateIncidentCommandHandler.php b/app/Bus/Handlers/Commands/Incident/CreateIncidentCommandHandler.php index d8b36af2b3dc..4504d905cacf 100644 --- a/app/Bus/Handlers/Commands/Incident/CreateIncidentCommandHandler.php +++ b/app/Bus/Handlers/Commands/Incident/CreateIncidentCommandHandler.php @@ -18,6 +18,7 @@ use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\Incident; use CachetHQ\Cachet\Models\IncidentTemplate; +use CachetHQ\Cachet\Models\Meta; use CachetHQ\Cachet\Services\Dates\DateFactory; use Carbon\Carbon; use Illuminate\Contracts\Auth\Guard; @@ -100,6 +101,18 @@ public function handle(CreateIncidentCommand $command) // Create the incident $incident = Incident::create($data); + // Store any meta? + if ($meta = $command->meta) { + foreach ($meta as $key => $value) { + Meta::create([ + 'key' => $key, + 'value' => $value, + 'meta_type' => 'incidents', + 'meta_id' => $incident->id, + ]); + } + } + // Update the component. if ($component = Component::find($command->component_id)) { dispatch(new UpdateComponentCommand( diff --git a/app/Http/Controllers/Api/IncidentController.php b/app/Http/Controllers/Api/IncidentController.php index 98b66cc2ffb5..ac5cd82a5940 100644 --- a/app/Http/Controllers/Api/IncidentController.php +++ b/app/Http/Controllers/Api/IncidentController.php @@ -78,7 +78,8 @@ public function postIncidents() Binput::get('stickied', false), Binput::get('occurred_at'), Binput::get('template'), - Binput::get('vars', []) + Binput::get('vars', []), + Binput::get('meta', []) )); } catch (QueryException $e) { throw new BadRequestHttpException(); diff --git a/tests/Api/IncidentTest.php b/tests/Api/IncidentTest.php index dea3d3d79d8e..1ea01c8ef8c6 100644 --- a/tests/Api/IncidentTest.php +++ b/tests/Api/IncidentTest.php @@ -154,4 +154,24 @@ public function testDeleteIncident() $this->delete('/api/v1/incidents/1'); $this->assertResponseStatus(204); } + + public function testCreateIncidentWithMeta() + { + $this->beUser(); + + $this->post('/api/v1/incidents', [ + 'name' => 'Foo', + 'message' => 'Lorem ipsum dolor sit amet', + 'status' => 1, + 'meta' => [ + 'id' => 123456789, + ], + ]); + $this->seeJson([ + 'meta' => [ + 'id' => 123456789, + ], + ]); + $this->assertResponseOk(); + } } diff --git a/tests/Bus/Commands/Incident/CreateIncidentCommandTest.php b/tests/Bus/Commands/Incident/CreateIncidentCommandTest.php index e52796c3f536..ee84d3865a5f 100644 --- a/tests/Bus/Commands/Incident/CreateIncidentCommandTest.php +++ b/tests/Bus/Commands/Incident/CreateIncidentCommandTest.php @@ -40,6 +40,7 @@ protected function getObjectAndParams() 'occurred_at' => null, 'template' => null, 'template_vars' => [], + 'meta' => [], ]; $object = new CreateIncidentCommand( @@ -53,7 +54,8 @@ protected function getObjectAndParams() $params['stickied'], $params['occurred_at'], $params['template'], - $params['template_vars'] + $params['template_vars'], + $params['meta'] ); return compact('params', 'object'); From c9c462be00349472f8b754533361efd2f2c176cb Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 13 Jun 2017 18:34:51 +0000 Subject: [PATCH 8/8] Apply fixes from StyleCI [ci skip] [skip ci] --- app/Models/Meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Meta.php b/app/Models/Meta.php index fe3f8bcafdb9..b7f242837a92 100644 --- a/app/Models/Meta.php +++ b/app/Models/Meta.php @@ -68,7 +68,7 @@ class Meta extends Model */ protected $table = 'meta'; - /** + /** * Get all of the owning meta models. * * @return \Illuminate\Database\Eloquent\Relations\MorphTo