diff --git a/app/Composers/ThemeComposer.php b/app/Composers/ThemeComposer.php index 6e5dc170..78d6a258 100644 --- a/app/Composers/ThemeComposer.php +++ b/app/Composers/ThemeComposer.php @@ -25,8 +25,8 @@ class ThemeComposer */ public function compose(View $view) { - $view->with('themeBackgroundColor', Setting::get('style_background_color') ?: null); - $view->with('themeTextColor', Setting::get('style_text_color') ?: null); + $view->with('themeBackgroundColor', Setting::get('style_background_color')); + $view->with('themeTextColor', Setting::get('style_text_color')); $viewData = $view->getData(); $themeView = array_only($viewData, preg_grep('/^theme/', array_keys($viewData))); diff --git a/app/Config/Repository.php b/app/Config/Repository.php index 1e4b1c7a..785f9b7d 100644 --- a/app/Config/Repository.php +++ b/app/Config/Repository.php @@ -44,12 +44,13 @@ class Repository /** * Returns a setting from the database. * - * @param string $name - * @param bool $checkEnv + * @param string $name + * @param string|null $default + * @param bool $checkEnv * * @return string|null */ - public function get($name, $checkEnv = true) + public function get($name, $default = null, $checkEnv = true) { // if we've not loaded the settings, load them now if (!$this->settings) { @@ -65,6 +66,8 @@ class Repository if ($checkEnv) { return $this->settings[$name] = env(strtoupper($name)); } + + return $default; } /** diff --git a/app/Http/Controllers/Api/AbstractApiController.php b/app/Http/Controllers/Api/AbstractApiController.php index 2cccc15c..6a41b84a 100644 --- a/app/Http/Controllers/Api/AbstractApiController.php +++ b/app/Http/Controllers/Api/AbstractApiController.php @@ -15,8 +15,11 @@ namespace CachetHQ\Cachet\Http\Controllers\Api; use CachetHQ\Cachet\Http\Controllers\AbstractController as BaseController; use Illuminate\Contracts\Pagination\Paginator; +use Illuminate\Contracts\Support\Arrayable; use Illuminate\Http\Request; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Response; +use McCool\LaravelAutoPresenter\Facades\AutoPresenter; abstract class AbstractApiController extends BaseController { @@ -37,9 +40,9 @@ abstract class AbstractApiController extends BaseController /** * The HTTP response data. * - * @var array + * @var mixed */ - protected $data = []; + protected $data = null; /** * The HTTP response status code. @@ -83,7 +86,7 @@ abstract class AbstractApiController extends BaseController * * @return $this */ - protected function setData(array $data) + protected function setData($data) { $this->data = $data; @@ -104,6 +107,30 @@ abstract class AbstractApiController extends BaseController return $this; } + /** + * Respond with an item response. + * + * @param mixed + * + * @return \Illuminate\Http\JsonResponse + */ + public function item($item) + { + return $this->setData(AutoPresenter::decorate($item))->respond(); + } + + /** + * Respond with a collection response. + * + * @param \Illuminate\Support\Collection $collection + * + * @return \Illuminate\Http\JsonResponse + */ + public function collection(Collection $collection) + { + return $this->setData(AutoPresenter::decorate($collection))->respond(); + } + /** * Respond with a pagination response. * @@ -134,7 +161,7 @@ abstract class AbstractApiController extends BaseController ], ]; - return $this->setMetaData($pagination)->setData($paginator->items())->respond(); + return $this->setMetaData($pagination)->setData(AutoPresenter::decorate($paginator->getCollection()))->respond(); } /** diff --git a/app/Http/Controllers/Api/ComponentController.php b/app/Http/Controllers/Api/ComponentController.php index a6fe8c6c..e7b46c94 100644 --- a/app/Http/Controllers/Api/ComponentController.php +++ b/app/Http/Controllers/Api/ComponentController.php @@ -16,6 +16,7 @@ namespace CachetHQ\Cachet\Http\Controllers\Api; use CachetHQ\Cachet\Models\Tag; use CachetHQ\Cachet\Repositories\Component\ComponentRepository; use GrahamCampbell\Binput\Facades\Binput; +use Illuminate\Contracts\Auth\Guard; use Illuminate\Http\Request; class ComponentController extends AbstractApiController @@ -58,18 +59,20 @@ class ComponentController extends AbstractApiController */ public function getComponent($id) { - return $this->component->findOrFail($id); + return $this->item($this->component->findOrFail($id)); } /** * Create a new component. * + * @param \Illuminate\Contracts\Auth\Guard $auth + * * @return \CachetHQ\Cachet\Models\Component */ - public function postComponents() + public function postComponents(Guard $auth) { $component = $this->component->create( - $this->auth->user()->id, + $auth->user()->id, Binput::except('tags') ); @@ -87,7 +90,7 @@ class ComponentController extends AbstractApiController $component->tags()->sync($componentTags); } - return $component; + return $this->item($component); } /** @@ -114,7 +117,7 @@ class ComponentController extends AbstractApiController $component->tags()->sync($componentTags); } - return $component; + return $this->item($component); } /** diff --git a/app/Http/Controllers/Api/IncidentController.php b/app/Http/Controllers/Api/IncidentController.php index ac6f5b2c..b06fd085 100644 --- a/app/Http/Controllers/Api/IncidentController.php +++ b/app/Http/Controllers/Api/IncidentController.php @@ -15,6 +15,7 @@ namespace CachetHQ\Cachet\Http\Controllers\Api; use CachetHQ\Cachet\Repositories\Incident\IncidentRepository; use GrahamCampbell\Binput\Facades\Binput; +use Illuminate\Contracts\Auth\Guard; use Illuminate\Http\Request; class IncidentController extends AbstractApiController @@ -57,17 +58,19 @@ class IncidentController extends AbstractApiController */ public function getIncident($id) { - return $this->incident->findOrFail($id); + return $this->item($this->incident->findOrFail($id)); } /** * Create a new incident. * + * @param \Illuminate\Contracts\Auth\Guard $auth + * * @return \CachetHQ\Cachet\Models\Incident */ - public function postIncidents() + public function postIncidents(Guard $auth) { - return $this->incident->create($this->auth->user()->id, Binput::all()); + return $this->item($this->incident->create($auth->user()->id, Binput::all())); } /** @@ -79,7 +82,7 @@ class IncidentController extends AbstractApiController */ public function putIncident($id) { - return $this->incident->update($id, Binput::all()); + return $this->item($this->incident->update($id, Binput::all())); } /** diff --git a/app/Http/Controllers/Api/MetricController.php b/app/Http/Controllers/Api/MetricController.php index 7f91af3e..b6058594 100644 --- a/app/Http/Controllers/Api/MetricController.php +++ b/app/Http/Controllers/Api/MetricController.php @@ -57,7 +57,7 @@ class MetricController extends AbstractApiController */ public function getMetric($id) { - return $this->metric->findOrFail($id); + return $this->item($this->metric->findOrFail($id)); } /** @@ -69,7 +69,7 @@ class MetricController extends AbstractApiController */ public function getMetricPoints($id) { - return $this->metric->points($id); + return $this->collection($this->metric->points($id)); } /** @@ -79,7 +79,7 @@ class MetricController extends AbstractApiController */ public function postMetrics() { - return $this->metric->create(Binput::all()); + return $this->item($this->metric->create(Binput::all())); } /** @@ -91,7 +91,7 @@ class MetricController extends AbstractApiController */ public function putMetric($id) { - return $this->metric->update($id, Binput::all()); + return $this->item($this->metric->update($id, Binput::all())); } /** diff --git a/app/Http/Controllers/Api/MetricPointController.php b/app/Http/Controllers/Api/MetricPointController.php index 12f2b0d3..0c579dc4 100644 --- a/app/Http/Controllers/Api/MetricPointController.php +++ b/app/Http/Controllers/Api/MetricPointController.php @@ -44,7 +44,7 @@ class MetricPointController extends AbstractApiController */ public function getMetricPoints($id) { - return $this->metricPoint->findOrFail($id); + return $this->item($this->metricPoint->findOrFail($id)); } /** @@ -56,7 +56,7 @@ class MetricPointController extends AbstractApiController */ public function postMetricPoints($id) { - return $this->metricPoint->create($id, Binput::all()); + return $this->item($this->metricPoint->create($id, Binput::all())); } /** @@ -72,7 +72,7 @@ class MetricPointController extends AbstractApiController $metricPoint = $this->metricPoint->findOrFail($pointId); $metricPoint->update(Binput::all()); - return $metricPoint; + return $this->item($metricPoint); } /** diff --git a/app/Http/helpers.php b/app/Http/helpers.php index 59fad44f..e6758790 100644 --- a/app/Http/helpers.php +++ b/app/Http/helpers.php @@ -142,7 +142,7 @@ if (!function_exists('formatted_date')) { */ function formatted_date($date) { - $dateFormat = Setting::get('date_format') ?: 'jS F Y'; + $dateFormat = Setting::get('date_format', 'jS F Y'); return (new Date($date))->format($dateFormat); } diff --git a/app/Models/Component.php b/app/Models/Component.php index bdbf9dad..e5a8cd8c 100644 --- a/app/Models/Component.php +++ b/app/Models/Component.php @@ -16,6 +16,7 @@ namespace CachetHQ\Cachet\Models; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; +use McCool\LaravelAutoPresenter\HasPresenter; use Watson\Validating\ValidatingTrait; /** @@ -31,7 +32,7 @@ use Watson\Validating\ValidatingTrait; * @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $deleted_at */ -class Component extends Model +class Component extends Model implements HasPresenter { use SoftDeletes, ValidatingTrait; @@ -161,4 +162,14 @@ class Component extends Model return implode(', ', $tags->toArray()); } + + /** + * Get the presenter class. + * + * @return string + */ + public function getPresenterClass() + { + return 'CachetHQ\Cachet\Presenters\ComponentPresenter'; + } } diff --git a/app/Models/Metric.php b/app/Models/Metric.php index 7f442bb6..37547215 100644 --- a/app/Models/Metric.php +++ b/app/Models/Metric.php @@ -13,11 +13,13 @@ namespace CachetHQ\Cachet\Models; +use CachetHQ\Cachet\Facades\Setting; use DateInterval; -use DateTime; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\DB; +use Jenssegers\Date\Date; +use McCool\LaravelAutoPresenter\HasPresenter; use Watson\Validating\ValidatingTrait; /** @@ -31,7 +33,7 @@ use Watson\Validating\ValidatingTrait; * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at */ -class Metric extends Model +class Metric extends Model implements HasPresenter { use ValidatingTrait; @@ -88,8 +90,8 @@ class Metric extends Model */ public function getValues($hour) { - $dateTime = new DateTime(); - $dateTime->sub(new DateInterval('PT'.$hour.'H')); + $dateTimeZone = Setting::get('app_timezone'); + $dateTime = (new Date())->setTimezone($dateTimeZone)->sub(new DateInterval('PT'.$hour.'H')); $hourInterval = $dateTime->sub(new DateInterval('PT'.$hour.'H'))->format('YmdH'); @@ -140,4 +142,14 @@ class Metric extends Model { return $this->display_chart === 1; } + + /** + * Get the presenter class. + * + * @return string + */ + public function getPresenterClass() + { + return 'CachetHQ\Cachet\Presenters\MetricPresenter'; + } } diff --git a/app/Models/MetricPoint.php b/app/Models/MetricPoint.php index ecf32f9d..53f101f8 100644 --- a/app/Models/MetricPoint.php +++ b/app/Models/MetricPoint.php @@ -14,6 +14,7 @@ namespace CachetHQ\Cachet\Models; use Illuminate\Database\Eloquent\Model; +use McCool\LaravelAutoPresenter\HasPresenter; use Watson\Validating\ValidatingTrait; /** @@ -23,7 +24,7 @@ use Watson\Validating\ValidatingTrait; * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at */ -class MetricPoint extends Model +class MetricPoint extends Model implements HasPresenter { use ValidatingTrait; @@ -52,4 +53,14 @@ class MetricPoint extends Model { return $this->belongsTo('CachetHQ\Cachet\Models\Metric', 'id', 'metric_id'); } + + /** + * Get the presenter class. + * + * @return string + */ + public function getPresenterClass() + { + return 'CachetHQ\Cachet\Presenters\MetricPointPresenter'; + } } diff --git a/app/Presenters/AbstractPresenter.php b/app/Presenters/AbstractPresenter.php new file mode 100644 index 00000000..01786014 --- /dev/null +++ b/app/Presenters/AbstractPresenter.php @@ -0,0 +1,40 @@ + + * (c) Joseph Cohen + * (c) Graham Campbell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CachetHQ\Cachet\Presenters; + +use CachetHQ\Cachet\Facades\Setting; +use Illuminate\Contracts\Support\Arrayable; +use McCool\LaravelAutoPresenter\BasePresenter as BaseLaravelAutoPresenter; + +abstract class AbstractPresenter extends BaseLaravelAutoPresenter implements Arrayable +{ + /** + * The setting repository. + * + * @var \CachetHQ\Cachet\Config\Repository + */ + protected $setting; + + /** + * Create a incident presenter instance. + * + * @param object $resource + */ + public function __construct($resource) + { + parent::__construct($resource); + + $this->setting = app('setting'); + } +} diff --git a/app/Presenters/ComponentPresenter.php b/app/Presenters/ComponentPresenter.php new file mode 100644 index 00000000..96bb31b4 --- /dev/null +++ b/app/Presenters/ComponentPresenter.php @@ -0,0 +1,34 @@ + + * (c) Joseph Cohen + * (c) Graham Campbell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CachetHQ\Cachet\Presenters; + +use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait; + +class ComponentPresenter extends AbstractPresenter +{ + use TimestampsTrait; + + /** + * Convert the presenter instance to an array. + * + * @return string[] + */ + public function toArray() + { + return array_merge($this->wrappedObject->toArray(), [ + 'created_at' => $this->created_at(), + 'updated_at' => $this->updated_at(), + ]); + } +} diff --git a/app/Presenters/IncidentPresenter.php b/app/Presenters/IncidentPresenter.php index b995210d..5238f028 100644 --- a/app/Presenters/IncidentPresenter.php +++ b/app/Presenters/IncidentPresenter.php @@ -14,32 +14,13 @@ namespace CachetHQ\Cachet\Presenters; use CachetHQ\Cachet\Facades\Setting; -use CachetHQ\Cachet\Models\Incident; +use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait; use GrahamCampbell\Markdown\Facades\Markdown; use Jenssegers\Date\Date; -use McCool\LaravelAutoPresenter\BasePresenter; -class IncidentPresenter extends BasePresenter +class IncidentPresenter extends AbstractPresenter { - /** - * Time zone setting. - * - * @var string - */ - protected $tz; - - /** - * Create a incident presenter instance. - * - * @param object $resource - */ - public function __construct($resource) - { - parent::__construct($resource); - - $this->tz = Setting::get('app_timezone'); - $this->format = Setting::get('incident_date_format') ?: 'l jS F Y H:i:s'; - } + use TimestampsTrait; /** * Renders the message from Markdown into HTML. @@ -59,7 +40,7 @@ class IncidentPresenter extends BasePresenter public function created_at_diff() { return (new Date($this->wrappedObject->created_at)) - ->setTimezone($this->tz) + ->setTimezone($this->setting->get('app_timezone')) ->diffForHumans(); } @@ -71,8 +52,8 @@ class IncidentPresenter extends BasePresenter public function created_at_formatted() { return ucfirst((new Date($this->wrappedObject->created_at)) - ->setTimezone($this->tz) - ->format($this->format)); + ->setTimezone($this->setting->get('app_timezone')) + ->format($this->setting->get('incident_date_format', 'l jS F Y H:i:s'))); } /** @@ -82,7 +63,7 @@ class IncidentPresenter extends BasePresenter */ public function created_at_datetimepicker() { - return $this->wrappedObject->created_at->setTimezone($this->tz)->format('d/m/Y H:i'); + return $this->wrappedObject->created_at->setTimezone($this->setting->get('app_timezone'))->format('d/m/Y H:i'); } /** @@ -92,7 +73,18 @@ class IncidentPresenter extends BasePresenter */ public function created_at_iso() { - return $this->wrappedObject->created_at->setTimezone($this->tz)->toISO8601String(); + return $this->wrappedObject->created_at->setTimezone($this->setting->get('app_timezone'))->toISO8601String(); + } + + /** + * Present formatted date time. + * + * @return string + */ + public function scheduled_at() + { + return (new Date($this->wrappedObject->scheduled_at)) + ->setTimezone($this->setting->get('app_timezone'))->toDateTimeString(); } /** @@ -103,7 +95,7 @@ class IncidentPresenter extends BasePresenter public function scheduled_at_diff() { return (new Date($this->wrappedObject->scheduled_at)) - ->setTimezone($this->tz) + ->setTimezone($this->setting->get('app_timezone')) ->diffForHumans(); } @@ -115,8 +107,8 @@ class IncidentPresenter extends BasePresenter public function scheduled_at_formatted() { return ucfirst((new Date($this->wrappedObject->scheduled_at)) - ->setTimezone($this->tz) - ->format($this->format)); + ->setTimezone($this->setting->get('app_timezone')) + ->format($this->setting->get('incident_date_format', 'l jS F Y H:i:s'))); } /** @@ -126,7 +118,7 @@ class IncidentPresenter extends BasePresenter */ public function scheduled_at_iso() { - return $this->wrappedObject->scheduled_at->setTimezone($this->tz)->toISO8601String(); + return $this->wrappedObject->scheduled_at->setTimezone($this->setting->get('app_timezone'))->toISO8601String(); } /** @@ -136,7 +128,7 @@ class IncidentPresenter extends BasePresenter */ public function scheduled_at_datetimepicker() { - return $this->wrappedObject->scheduled_at->setTimezone($this->tz)->format('d/m/Y H:i'); + return $this->wrappedObject->scheduled_at->setTimezone($this->setting->get('app_timezone'))->format('d/m/Y H:i'); } /** @@ -161,4 +153,18 @@ class IncidentPresenter extends BasePresenter return ''; } } + + /** + * Convert the presenter instance to an array. + * + * @return string[] + */ + public function toArray() + { + return array_merge($this->wrappedObject->toArray(), [ + 'scheduled_at' => $this->created_at(), + 'created_at' => $this->created_at(), + 'updated_at' => $this->updated_at(), + ]); + } } diff --git a/app/Presenters/MetricPointPresenter.php b/app/Presenters/MetricPointPresenter.php new file mode 100644 index 00000000..5bf232b0 --- /dev/null +++ b/app/Presenters/MetricPointPresenter.php @@ -0,0 +1,34 @@ + + * (c) Joseph Cohen + * (c) Graham Campbell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CachetHQ\Cachet\Presenters; + +use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait; + +class MetricPointPresenter extends AbstractPresenter +{ + use TimestampsTrait; + + /** + * Convert the presenter instance to an array. + * + * @return string[] + */ + public function toArray() + { + return array_merge($this->wrappedObject->toArray(), [ + 'created_at' => $this->created_at(), + 'updated_at' => $this->updated_at(), + ]); + } +} diff --git a/app/Presenters/MetricPresenter.php b/app/Presenters/MetricPresenter.php new file mode 100644 index 00000000..d117cff1 --- /dev/null +++ b/app/Presenters/MetricPresenter.php @@ -0,0 +1,34 @@ + + * (c) Joseph Cohen + * (c) Graham Campbell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CachetHQ\Cachet\Presenters; + +use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait; + +class MetricPresenter extends AbstractPresenter +{ + use TimestampsTrait; + + /** + * Convert the presenter instance to an array. + * + * @return string[] + */ + public function toArray() + { + return array_merge($this->wrappedObject->toArray(), [ + 'created_at' => $this->created_at(), + 'updated_at' => $this->updated_at(), + ]); + } +} diff --git a/app/Presenters/Traits/TimestampsTrait.php b/app/Presenters/Traits/TimestampsTrait.php new file mode 100644 index 00000000..bf6833d6 --- /dev/null +++ b/app/Presenters/Traits/TimestampsTrait.php @@ -0,0 +1,52 @@ + + * (c) Joseph Cohen + * (c) Graham Campbell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CachetHQ\Cachet\Presenters\Traits; + +use Jenssegers\Date\Date; + +trait TimestampsTrait +{ + /** + * Present formatted date time. + * + * @return string + */ + public function created_at() + { + return (new Date($this->wrappedObject->created_at)) + ->setTimezone($this->setting->get('app_timezone'))->toDateTimeString(); + } + + /** + * Present formatted date time. + * + * @return string + */ + public function updated_at() + { + return (new Date($this->wrappedObject->updated_at)) + ->setTimezone($this->setting->get('app_timezone'))->toDateTimeString(); + } + + /** + * Present formatted date time. + * + * @return string + */ + public function deleted_at() + { + return (new Date($this->wrappedObject->deleted_at)) + ->setTimezone($this->setting->get('app_timezone'))->toDateTimeString(); + } +}