From 592b62b39999155a3aca1ec6d0e12e2f8e1e0de7 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 7 Nov 2015 13:15:28 +0000 Subject: [PATCH 1/6] Added date factory --- app/Dates/DateFactory.php | 77 ++++++++++++++++++++++++++++ app/Providers/AppServiceProvider.php | 18 ++++++- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 app/Dates/DateFactory.php diff --git a/app/Dates/DateFactory.php b/app/Dates/DateFactory.php new file mode 100644 index 00000000..0df460b5 --- /dev/null +++ b/app/Dates/DateFactory.php @@ -0,0 +1,77 @@ +appTimezone = $appTimezone; + $this->cachetTimezone = $cachetTimezone; + } + + /** + * Create a Carbon instance from a specific format. + * + * @param string $format + * @param string $time + * + * @throws \InvalidArgumentException + * + * @return \Carbon\Carbon + */ + public function create($format, $time) + { + return Date::createFromFormat($format, $time, $this->cachetTimezone)->setTimezone($this->appTimezone); + } + + /** + * Create a Carbon instance from a specific format. + * + * We're also going to make sure the timezone information is correct. + * + * @param string $format + * @param string $time + * + * @throws \InvalidArgumentException + * + * @return \Carbon\Carbon + */ + public function createNormalized($format, $time) + { + return $this->createFromFormat($format, $time)->setTimezone($this->appTimezone); + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 61a874ac..b6542bcb 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -11,6 +11,7 @@ namespace CachetHQ\Cachet\Providers; +use CachetHQ\Cachet\Dates\DateFactory; use Illuminate\Bus\Dispatcher; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; @@ -40,6 +41,21 @@ class AppServiceProvider extends ServiceProvider */ public function register() { - // + $this->registerDateFactory(); + } + + /** + * Register the date factory. + * + * @return void + */ + protected function registerDateFactory() + { + $this->app->singleton(DateFactory::class, function ($app) { + $appTimezone = $app->config->get('app.timezone'); + $cacheTimezone = $app->config->get('cachet.timezone'); + + return new DateFactory($appTimezone, $cacheTimezone); + }); } } From 6a73d6268d12af5760bf30439e35a52b41d3415d Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 7 Nov 2015 13:16:39 +0000 Subject: [PATCH 2/6] Use the date factory in the commands --- .../Incident/ReportIncidentCommandHandler.php | 24 +++++++++++++++--- .../ReportMaintenanceCommandHandler.php | 25 ++++++++++++++++--- .../Incident/UpdateIncidentCommandHandler.php | 24 +++++++++++++++--- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php b/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php index e0f6e8c3..6ac350d3 100644 --- a/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php +++ b/app/Handlers/Commands/Incident/ReportIncidentCommandHandler.php @@ -12,14 +12,32 @@ namespace CachetHQ\Cachet\Handlers\Commands\Incident; use CachetHQ\Cachet\Commands\Incident\ReportIncidentCommand; +use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Events\Incident\IncidentWasReportedEvent; use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\Incident; -use Illuminate\Support\Facades\Config; -use Jenssegers\Date\Date; class ReportIncidentCommandHandler { + /** + * The date factory instance. + * + * @var \CachetHQ\Cachet\Dates\DateFactory + */ + protected $dates; + + /** + * Create a new report incident command handler instance. + * + * @param \CachetHQ\Cachet\Dates\DateFactory $dates + * + * @return void + */ + public function __construct(DateFactory $dates) + { + $this->dates = $dates; + } + /** * Handle the report incident command. * @@ -43,7 +61,7 @@ class ReportIncidentCommandHandler // The incident occurred at a different time. if ($command->incident_date) { - $incidentDate = Date::createFromFormat('d/m/Y H:i', $command->incident_date, config('cachet.timezone'))->setTimezone(Config::get('app.timezone')); + $incidentDate = $this->dates->createNormalized('d/m/Y H:i', $command->incident_date); $data['created_at'] = $incidentDate; $data['updated_at'] = $incidentDate; diff --git a/app/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php b/app/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php index 2239cf8c..d1f0a793 100644 --- a/app/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php +++ b/app/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php @@ -12,13 +12,31 @@ namespace CachetHQ\Cachet\Handlers\Commands\Incident; use CachetHQ\Cachet\Commands\Incident\ReportMaintenanceCommand; +use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Events\Incident\MaintenanceWasScheduledEvent; use CachetHQ\Cachet\Models\Incident; -use Illuminate\Support\Facades\Config; -use Jenssegers\Date\Date; class ReportMaintenanceCommandHandler { + /** + * The date factory instance. + * + * @var \CachetHQ\Cachet\Dates\DateFactory + */ + protected $dates; + + /** + * Create a new report maintanance command handler instance. + * + * @param \CachetHQ\Cachet\Dates\DateFactory $dates + * + * @return void + */ + public function __construct(DateFactory $dates) + { + $this->dates = $dates; + } + /** * Handle the report maintenance command. * @@ -28,8 +46,7 @@ class ReportMaintenanceCommandHandler */ public function handle(ReportMaintenanceCommand $command) { - $scheduledAt = Date::createFromFormat('d/m/Y H:i', $command->timestamp, config('cachet.timezone')) - ->setTimezone(Config::get('app.timezone')); + $scheduledAt = $this->dates->createNormalized('d/m/Y H:i', $command->timestamp); $maintenanceEvent = Incident::create([ 'name' => $command->name, diff --git a/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php b/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php index dc3af1ca..dbc8ecfe 100644 --- a/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php +++ b/app/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php @@ -12,14 +12,32 @@ namespace CachetHQ\Cachet\Handlers\Commands\Incident; use CachetHQ\Cachet\Commands\Incident\UpdateIncidentCommand; +use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Events\Incident\IncidentWasUpdatedEvent; use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\Incident; -use Illuminate\Support\Facades\Config; -use Jenssegers\Date\Date; class UpdateIncidentCommandHandler { + /** + * The date factory instance. + * + * @var \CachetHQ\Cachet\Dates\DateFactory + */ + protected $dates; + + /** + * Create a new update incident command handler instance. + * + * @param \CachetHQ\Cachet\Dates\DateFactory $dates + * + * @return void + */ + public function __construct(DateFactory $dates) + { + $this->dates = $dates; + } + /** * Handle the update incident command. * @@ -34,7 +52,7 @@ class UpdateIncidentCommandHandler // The incident occurred at a different time. if ($command->incident_date) { - $incidentDate = Date::createFromFormat('d/m/Y H:i', $command->incident_date, config('cachet.timezone'))->setTimezone(Config::get('app.timezone')); + $incidentDate = $this->dates->createNormalized('d/m/Y H:i', $command->incident_date); $incident->update([ 'created_at' => $incidentDate, From d379e41edfb72d4fa7e6f1753f8d6dc6c09b6601 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 7 Nov 2015 13:16:54 +0000 Subject: [PATCH 3/6] Use the date factory in the schedule controller --- app/Http/Controllers/Dashboard/ScheduleController.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/Dashboard/ScheduleController.php b/app/Http/Controllers/Dashboard/ScheduleController.php index a49fe98b..3bab83a6 100644 --- a/app/Http/Controllers/Dashboard/ScheduleController.php +++ b/app/Http/Controllers/Dashboard/ScheduleController.php @@ -13,12 +13,12 @@ namespace CachetHQ\Cachet\Http\Controllers\Dashboard; use AltThree\Validator\ValidationException; use CachetHQ\Cachet\Commands\Incident\ReportMaintenanceCommand; +use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Models\Incident; use CachetHQ\Cachet\Models\IncidentTemplate; use GrahamCampbell\Binput\Facades\Binput; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller; -use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\View; use Illuminate\Support\MessageBag; @@ -130,16 +130,17 @@ class ScheduleController extends Controller /** * Updates the given incident. * - * @param \CachetHQ\Cachet\Models\Incident $schedule + * @param \CachetHQ\Cachet\Models\Incident $schedule + * @param \CachetHQ\Cachet\Dates\DateFactory $dates * * @return \Illuminate\Http\RedirectResponse */ - public function editScheduleAction(Incident $schedule) + public function editScheduleAction(Incident $schedule, DateFactory $dates) { $scheduleData = Binput::get('incident'); + // Parse the schedule date. - $scheduledAt = Date::createFromFormat('d/m/Y H:i', $scheduleData['scheduled_at'], config('cachet.timezone')) - ->setTimezone(Config::get('app.timezone')); + $scheduledAt = $dates->createNormalized('d/m/Y H:i', $scheduleData['scheduled_at']); if ($scheduledAt->isPast()) { $messageBag = new MessageBag(); From 2d648e44aea946c3b9b70817ceb44a9b355dd9c6 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 7 Nov 2015 13:18:38 +0000 Subject: [PATCH 4/6] Make sure metrics use the correct timezone Closes #1032 --- .../Metric/AddMetricPointCommandHandler.php | 23 +++++++++++++++++-- .../UpdateMetricPointCommandHandler.php | 23 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/app/Handlers/Commands/Metric/AddMetricPointCommandHandler.php b/app/Handlers/Commands/Metric/AddMetricPointCommandHandler.php index 962b1623..048f85a0 100644 --- a/app/Handlers/Commands/Metric/AddMetricPointCommandHandler.php +++ b/app/Handlers/Commands/Metric/AddMetricPointCommandHandler.php @@ -12,12 +12,31 @@ namespace CachetHQ\Cachet\Handlers\Commands\Metric; use CachetHQ\Cachet\Commands\Metric\AddMetricPointCommand; +use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Events\Metric\MetricPointWasAddedEvent; use CachetHQ\Cachet\Models\MetricPoint; -use Carbon\Carbon; class AddMetricPointCommandHandler { + /** + * The date factory instance. + * + * @var \CachetHQ\Cachet\Dates\DateFactory + */ + protected $dates; + + /** + * Create a new add metric point command handler instance. + * + * @param \CachetHQ\Cachet\Dates\DateFactory $dates + * + * @return void + */ + public function __construct(DateFactory $dates) + { + $this->dates = $dates; + } + /** * Handle the add metric point command. * @@ -36,7 +55,7 @@ class AddMetricPointCommandHandler ]; if ($createdAt) { - $data['created_at'] = Carbon::createFromFormat('U', $createdAt)->format('Y-m-d H:i:s'); + $data['created_at'] = $this->dates->create('U', $createdAt)->format('Y-m-d H:i:s'); } $metricPoint = MetricPoint::create($data); diff --git a/app/Handlers/Commands/Metric/UpdateMetricPointCommandHandler.php b/app/Handlers/Commands/Metric/UpdateMetricPointCommandHandler.php index 823d254e..4a9fc156 100644 --- a/app/Handlers/Commands/Metric/UpdateMetricPointCommandHandler.php +++ b/app/Handlers/Commands/Metric/UpdateMetricPointCommandHandler.php @@ -12,11 +12,30 @@ namespace CachetHQ\Cachet\Handlers\Commands\Metric; use CachetHQ\Cachet\Commands\Metric\UpdateMetricPointCommand; +use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Events\Metric\MetricPointWasUpdatedEvent; -use Carbon\Carbon; class UpdateMetricPointCommandHandler { + /** + * The date factory instance. + * + * @var \CachetHQ\Cachet\Dates\DateFactory + */ + protected $dates; + + /** + * Create a new update metric point command handler instance. + * + * @param \CachetHQ\Cachet\Dates\DateFactory $dates + * + * @return void + */ + public function __construct(DateFactory $dates) + { + $this->dates = $dates; + } + /** * Handle the update metric point command. * @@ -36,7 +55,7 @@ class UpdateMetricPointCommandHandler ]; if ($createdAt) { - $data['created_at'] = Carbon::createFromFormat('U', $createdAt)->format('Y-m-d H:i:s'); + $data['created_at'] = $this->dates->create('U', $createdAt)->format('Y-m-d H:i:s'); } $point->update($data); From bb691ec4272b3ad9ca94e731f75abfc63ed13643 Mon Sep 17 00:00:00 2001 From: Joseph Cohen Date: Sat, 7 Nov 2015 13:20:06 +0000 Subject: [PATCH 5/6] Test setting timezone on the api for metric points Signed-off-by: Graham Campbell --- tests/Api/MetricPointTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Api/MetricPointTest.php b/tests/Api/MetricPointTest.php index 2c7bb81a..39569d7a 100644 --- a/tests/Api/MetricPointTest.php +++ b/tests/Api/MetricPointTest.php @@ -11,6 +11,7 @@ namespace CachetHQ\Tests\Cachet\Api; +use Carbon\Carbon; use CachetHQ\Tests\Cachet\AbstractTestCase; use Illuminate\Foundation\Testing\DatabaseMigrations; @@ -72,6 +73,24 @@ class MetricPointTest extends AbstractTestCase $this->seeJson(['value' => $metricPoint->value, 'created_at' => $datetime]); } + public function testPostMetricPointTimestampTimezone() + { + $this->beUser(); + + $timezone = 'America/Mexico_City'; + $metric = factory('CachetHQ\Cachet\Models\Metric')->create(); + $timestamp = Carbon::now()->timezone($timezone)->timestamp; + $datetime = Carbon::now()->toDateTimeString(); + $metricPoint = factory('CachetHQ\Cachet\Models\MetricPoint')->make([ + 'metric_id' => $metric->id, + ]); + $postData = $metricPoint->toArray(); + $postData['timestamp'] = $timestamp; + + $this->post("/api/v1/metrics/{$metric->id}/points", $postData, ['Time-Zone' => $timezone]); + $this->seeJson(['value' => $metricPoint->value, 'created_at' => $datetime]); + } + public function testPutMetricPoint() { $this->beUser(); From 8cd8c351250e7e0aa564a7d8b2dd43d119d7cd9e Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 7 Nov 2015 15:37:06 +0000 Subject: [PATCH 6/6] Fixes --- app/Dates/DateFactory.php | 4 ++-- tests/Api/MetricPointTest.php | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Dates/DateFactory.php b/app/Dates/DateFactory.php index 0df460b5..17c276f5 100644 --- a/app/Dates/DateFactory.php +++ b/app/Dates/DateFactory.php @@ -9,9 +9,9 @@ * file that was distributed with this source code. */ -namespace CachetHQ\Cachet\Date; +namespace CachetHQ\Cachet\Dates; -use Jenssegers\Date\Date +use Jenssegers\Date\Date; class DateFactory { diff --git a/tests/Api/MetricPointTest.php b/tests/Api/MetricPointTest.php index 39569d7a..29b20919 100644 --- a/tests/Api/MetricPointTest.php +++ b/tests/Api/MetricPointTest.php @@ -11,8 +11,8 @@ namespace CachetHQ\Tests\Cachet\Api; -use Carbon\Carbon; use CachetHQ\Tests\Cachet\AbstractTestCase; +use Carbon\Carbon; use Illuminate\Foundation\Testing\DatabaseMigrations; class MetricPointTest extends AbstractTestCase @@ -75,6 +75,10 @@ class MetricPointTest extends AbstractTestCase public function testPostMetricPointTimestampTimezone() { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('Timezones are broken on HHVM.'); + } + $this->beUser(); $timezone = 'America/Mexico_City';