diff --git a/app/views/setup.blade.php b/app/views/setup.blade.php
index 4b1c81b8..111fbcce 100644
--- a/app/views/setup.blade.php
+++ b/app/views/setup.blade.php
@@ -78,6 +78,12 @@
{{ trans("setup.show_support") }}
+
+
+
diff --git a/composer.json b/composer.json
index 3d888eb1..e56e9bbb 100644
--- a/composer.json
+++ b/composer.json
@@ -14,6 +14,7 @@
"ext-mcrypt": "*",
"ext-openssl": "*",
"laravel/framework": "4.2.*",
+ "cachethq/segment": "1.0.*@dev",
"dingo/api": "0.8.*",
"doctrine/dbal": "2.5.*",
"graham-campbell/binput": "2.1.*",
diff --git a/composer.lock b/composer.lock
index 9ec0536d..69b65cab 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,63 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "3752fec41d40201f38e46974caa27d62",
+ "hash": "b32031bb1053f393308be4f68d1d0c94",
"packages": [
+ {
+ "name": "cachethq/segment",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cachethq/Laravel-Segment.git",
+ "reference": "39121d7953cb91197f0474b9cf43ae198fca1e26"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cachethq/Laravel-Segment/zipball/39121d7953cb91197f0474b9cf43ae198fca1e26",
+ "reference": "39121d7953cb91197f0474b9cf43ae198fca1e26",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/config": "~4.1",
+ "illuminate/support": "~4.1",
+ "php": ">=5.4.7",
+ "segmentio/analytics-php": "~1.1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "CachetHQ\\Segment\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "James Brooks",
+ "email": "james@cachethq.io"
+ }
+ ],
+ "description": "Segment.com wrapper written for Laravel 4",
+ "keywords": [
+ "CachetHQ",
+ "Laravel Segment",
+ "api",
+ "cachet",
+ "framework",
+ "laravel",
+ "segment",
+ "segment.com",
+ "segment.io"
+ ],
+ "time": "2015-01-23 22:49:00"
+ },
{
"name": "classpreloader/classpreloader",
"version": "1.0.2",
@@ -2108,6 +2163,51 @@
],
"time": "2014-12-09 14:53:34"
},
+ {
+ "name": "segmentio/analytics-php",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/segmentio/analytics-php.git",
+ "reference": "db24fa9a2e1110570c338fea7a6f46bbb7ef105c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/segmentio/analytics-php/zipball/db24fa9a2e1110570c338fea7a6f46bbb7ef105c",
+ "reference": "db24fa9a2e1110570c338fea7a6f46bbb7ef105c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/Segment.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Segment.io ",
+ "homepage": "https://segment.io/"
+ }
+ ],
+ "description": "Segmentio Analytics PHP Library",
+ "homepage": "https://segment.io/libraries/php",
+ "keywords": [
+ "analytics",
+ "analytics.js",
+ "segmentio"
+ ],
+ "time": "2015-01-07 07:11:38"
+ },
{
"name": "stack/builder",
"version": "v1.0.3",
@@ -3997,7 +4097,9 @@
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {
+ "cachethq/segment": 20
+ },
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
diff --git a/src/Console/Commands/OneClickDeployCommand.php b/src/Console/Commands/OneClickDeployCommand.php
index fbd0d7ca..9ec52b93 100644
--- a/src/Console/Commands/OneClickDeployCommand.php
+++ b/src/Console/Commands/OneClickDeployCommand.php
@@ -50,7 +50,13 @@ class OneClickDeployCommand extends Command
public function fire()
{
if ($this->migrate) {
- return $this->runMigrations();
+ $migrations = $this->runMigrations();
+
+ segment_track('Installation', [
+ 'event' => 'Heroku Deployment',
+ ]);
+
+ return $migrations;
}
$this->info('Please run "php artisan migrate" to finish the installation.');
diff --git a/src/Http/Controllers/DashComponentController.php b/src/Http/Controllers/DashComponentController.php
index e73998c5..33f6a866 100644
--- a/src/Http/Controllers/DashComponentController.php
+++ b/src/Http/Controllers/DashComponentController.php
@@ -109,6 +109,11 @@ class DashComponentController extends Controller
$component->update($_component);
if (! $component->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Edit Component',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::all())
->with('title', sprintf(
'%s %s',
@@ -118,6 +123,11 @@ class DashComponentController extends Controller
->with('errors', $component->getErrors());
}
+ segment_track('Dashboard', [
+ 'event' => 'Edit Component',
+ 'success' => true,
+ ]);
+
// The component was added successfully, so now let's deal with the tags.
$tags = preg_split('/ ?, ?/', $tags);
@@ -168,6 +178,11 @@ class DashComponentController extends Controller
$component = Component::create($_component);
if (! $component->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Created Component',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::all())
->with('title', sprintf(
'%s %s',
@@ -177,6 +192,11 @@ class DashComponentController extends Controller
->with('errors', $component->getErrors());
}
+ segment_track('Dashboard', [
+ 'event' => 'Created Component',
+ 'success' => true,
+ ]);
+
// The component was added successfully, so now let's deal with the tags.
$tags = preg_split('/ ?, ?/', $tags);
@@ -207,6 +227,10 @@ class DashComponentController extends Controller
*/
public function deleteComponentAction(Component $component)
{
+ segment_track('Dashboard', [
+ 'event' => 'Deleted Component',
+ ]);
+
$component->delete();
return Redirect::back();
@@ -221,6 +245,10 @@ class DashComponentController extends Controller
*/
public function deleteComponentGroupAction(ComponentGroup $group)
{
+ segment_track('Dashboard', [
+ 'event' => 'Deleted Component Group',
+ ]);
+
$group->delete();
return Redirect::back();
@@ -248,6 +276,11 @@ class DashComponentController extends Controller
$group = ComponentGroup::create(Binput::get('group'));
if (! $group->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Created Component Group',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::all())
->with('title', sprintf(
'%s %s',
@@ -257,6 +290,11 @@ class DashComponentController extends Controller
->with('errors', $group->getErrors());
}
+ segment_track('Dashboard', [
+ 'event' => 'Created Component Group',
+ 'success' => true,
+ ]);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
diff --git a/src/Http/Controllers/DashIncidentController.php b/src/Http/Controllers/DashIncidentController.php
index ac16851d..77228ba6 100644
--- a/src/Http/Controllers/DashIncidentController.php
+++ b/src/Http/Controllers/DashIncidentController.php
@@ -66,6 +66,11 @@ class DashIncidentController extends Controller
$incident = Incident::create($incidentData);
if (! $incident->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Created Incident',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::all())
->with('title', sprintf(
'%s %s',
@@ -82,6 +87,11 @@ class DashIncidentController extends Controller
]);
}
+ segment_track('Dashboard', [
+ 'event' => 'Created Incident',
+ 'success' => true,
+ ]);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
@@ -127,6 +137,10 @@ class DashIncidentController extends Controller
*/
public function deleteTemplateAction(IncidentTemplate $template)
{
+ segment_track('Dashboard', [
+ 'event' => 'Deleted Incident Template',
+ ]);
+
$template->delete();
return Redirect::back();
@@ -143,6 +157,11 @@ class DashIncidentController extends Controller
$template = IncidentTemplate::create($_template);
if (! $template->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Created Incident Template',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::all())
->with('title', sprintf(
'%s %s',
@@ -152,6 +171,11 @@ class DashIncidentController extends Controller
->with('errors', $template->getErrors());
}
+ segment_track('Dashboard', [
+ 'event' => 'Created Incident Template',
+ 'success' => true,
+ ]);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
@@ -170,6 +194,10 @@ class DashIncidentController extends Controller
*/
public function deleteIncidentAction(Incident $incident)
{
+ segment_track('Dashboard', [
+ 'event' => 'Deleted Incident',
+ ]);
+
$incident->delete();
return Redirect::back();
@@ -204,6 +232,11 @@ class DashIncidentController extends Controller
$incident->update($_incident);
if (! $incident->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Edited Incident',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::all())
->with('title', sprintf(
'%s %s',
@@ -213,6 +246,11 @@ class DashIncidentController extends Controller
->with('errors', $incident->getErrors());
}
+ segment_track('Dashboard', [
+ 'event' => 'Edited Incident',
+ 'success' => true,
+ ]);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
@@ -231,6 +269,10 @@ class DashIncidentController extends Controller
*/
public function editTemplateAction(IncidentTemplate $template)
{
+ segment_track('Dashboard', [
+ 'event' => 'Edited Incident Template',
+ ]);
+
$template->update(Binput::get('template'));
return Redirect::back()->with('updatedTemplate', $template);
diff --git a/src/Http/Controllers/DashTeamController.php b/src/Http/Controllers/DashTeamController.php
index b3533a4f..7f504113 100644
--- a/src/Http/Controllers/DashTeamController.php
+++ b/src/Http/Controllers/DashTeamController.php
@@ -60,6 +60,11 @@ class DashTeamController extends Controller
$user = User::create(Binput::all());
if (! $user->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Added User',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::except('password'))
->with('title', sprintf(
'%s %s',
@@ -69,6 +74,11 @@ class DashTeamController extends Controller
->with('errors', $user->getErrors());
}
+ segment_track('Dashboard', [
+ 'event' => 'Added User',
+ 'success' => true,
+ ]);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
@@ -98,6 +108,11 @@ class DashTeamController extends Controller
$user->update($items);
if (! $user->isValid()) {
+ segment_track('Dashboard', [
+ 'event' => 'Updated User',
+ 'success' => false,
+ ]);
+
return Redirect::back()->withInput(Binput::except('password'))
->with('title', sprintf(
'%s %s',
@@ -107,6 +122,11 @@ class DashTeamController extends Controller
->with('errors', $user->getErrors());
}
+ segment_track('Dashboard', [
+ 'event' => 'Updated User',
+ 'success' => true,
+ ]);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
diff --git a/src/Http/Controllers/DashUserController.php b/src/Http/Controllers/DashUserController.php
index bf95039b..a5a2c250 100644
--- a/src/Http/Controllers/DashUserController.php
+++ b/src/Http/Controllers/DashUserController.php
@@ -39,8 +39,18 @@ class DashUserController extends Controller
// Let's enable/disable auth
if ($enable2FA && ! Auth::user()->hasTwoFactor) {
$items['google_2fa_secret'] = Google2FA::generateSecretKey();
+
+ segment_track('User Management', [
+ 'event' => 'enabled_two_factor',
+ 'value' => true,
+ ]);
} elseif (! $enable2FA) {
$items['google_2fa_secret'] = '';
+
+ segment_track('User Management', [
+ 'event' => 'enabled_two_factor',
+ 'value' => false,
+ ]);
}
if (trim($passwordChange) === '') {
@@ -76,6 +86,10 @@ class DashUserController extends Controller
*/
public function regenerateApiKey(User $user)
{
+ segment_track('User Management', [
+ 'event' => 'regenrated_api_token'
+ ]);
+
$user->api_key = User::generateApiKey();
$user->save();
diff --git a/src/Http/Controllers/HomeController.php b/src/Http/Controllers/HomeController.php
index 09e7cd25..f186d493 100644
--- a/src/Http/Controllers/HomeController.php
+++ b/src/Http/Controllers/HomeController.php
@@ -22,6 +22,10 @@ class HomeController extends Controller
*/
public function showIndex()
{
+ segment_track('Status Page', [
+ 'event' => 'Landed',
+ ]);
+
$components = Component::orderBy('order')->orderBy('created_at')->get();
$allIncidents = [];
@@ -38,6 +42,21 @@ class HomeController extends Controller
try {
// If date provided is valid
$oldDate = Date::createFromFormat('Y-m-d', Binput::get('start_date'));
+
+ segment_track('Status Page', [
+ 'start_date' => $oldDate->format('Y-m-d'),
+ ]);
+
+ if (Setting::get('app_tracking')) {
+ Segment::track([
+ 'userId' => Config::get('app.key'),
+ 'event' => 'Home Page',
+ 'properties' => [
+ 'start_date' => $oldDate,
+ ],
+ ]);
+ }
+
// If trying to get a future date fallback to today
if ($today->gt($oldDate)) {
$startDate = $oldDate;
diff --git a/src/Http/Controllers/SetupController.php b/src/Http/Controllers/SetupController.php
index f2094375..b1aae56c 100644
--- a/src/Http/Controllers/SetupController.php
+++ b/src/Http/Controllers/SetupController.php
@@ -47,6 +47,10 @@ class SetupController extends Controller
{
$postData = Binput::all();
+ segment_track('Setup', [
+ 'step' => '1',
+ ]);
+
$v = Validator::make($postData, [
'settings.app_name' => 'required',
'settings.app_domain' => 'required',
@@ -72,6 +76,10 @@ class SetupController extends Controller
{
$postData = Binput::all();
+ segment_track('Setup', [
+ 'step' => '2',
+ ]);
+
$v = Validator::make($postData, [
'settings.app_name' => 'required',
'settings.app_domain' => 'required',
diff --git a/src/Providers/LoadConfigServiceProvider.php b/src/Providers/LoadConfigServiceProvider.php
index 63b29887..0e0ac0ad 100644
--- a/src/Providers/LoadConfigServiceProvider.php
+++ b/src/Providers/LoadConfigServiceProvider.php
@@ -25,6 +25,10 @@ class LoadConfigServiceProvider extends ServiceProvider
// Don't throw any errors, we may not be setup yet.
}
+ // Set the Segment.com settings.
+ $segmentRepository = $this->app->make('CachetHQ\Cachet\Segment\RepositoryInterface');
+ $this->app->config->set('cachethq/segment::write_key', $segmentRepository->fetch());
+
// Override default app values.
$this->app->config->set('app.url', $appDomain ?: $this->app->config->get('app.url'));
$this->app->config->set('app.locale', $appLocale ?: $this->app->config->get('app.locale'));
diff --git a/src/Providers/SegmentApiServiceProvider.php b/src/Providers/SegmentApiServiceProvider.php
new file mode 100644
index 00000000..33c639b0
--- /dev/null
+++ b/src/Providers/SegmentApiServiceProvider.php
@@ -0,0 +1,37 @@
+app->singleton('CachetHQ\Cachet\Segment\RepositoryInterface', function () {
+ $url = 'https://gist.githubusercontent.com/jbrooksuk/5de24bc1cf90fb1a3d57/raw/cachet.json';
+ $guzzleClient = new Client();
+ $client = new HttpRepository($guzzleClient, $url);
+
+ return new CacheRepository($client);
+ });
+ }
+}
diff --git a/src/Segment/CacheRepository.php b/src/Segment/CacheRepository.php
new file mode 100644
index 00000000..5908daef
--- /dev/null
+++ b/src/Segment/CacheRepository.php
@@ -0,0 +1,55 @@
+repository = $repository;
+ }
+
+ /**
+ * Determines whether to use the segment_write_key setting or to fetch a new.
+ *
+ * @return string
+ */
+ public function fetch()
+ {
+ // Firstly, does the setting exist?
+ if (false === ($writeKey = Setting::get('segment_write_key'))) {
+ // No, let's go fetch it.
+ $writeKey = $this->repository->fetch();
+ Setting::set('segment_write_key', $writeKey);
+ } else {
+ // It does, but how old is it?
+ $setting = SettingModel::where('name', 'segment_write_key')->first();
+
+ // It's older than an hour, let's refresh
+ if ($setting->updated_at->lt(Carbon::now()->subHour())) {
+ $writeKey = $this->repository->fetch();
+
+ // Update the setting. This is done manual to make sure updated_at is overwritten.
+ $setting->value = $writeKey;
+ $setting->updated_at = Carbon::now();
+ $setting->save();
+ }
+ }
+
+ return $writeKey;
+ }
+}
diff --git a/src/Segment/HttpRepository.php b/src/Segment/HttpRepository.php
new file mode 100644
index 00000000..85309505
--- /dev/null
+++ b/src/Segment/HttpRepository.php
@@ -0,0 +1,40 @@
+client = $client;
+ $this->url = $url;
+ }
+
+ /**
+ * Fetches the segment_write_key from the given url.
+ *
+ * @return string
+ */
+ public function fetch()
+ {
+ return $this->client->get($this->url)->json()['segment_write_key'];
+ }
+}
diff --git a/src/Segment/RepositoryInterface.php b/src/Segment/RepositoryInterface.php
new file mode 100644
index 00000000..f02abc1e
--- /dev/null
+++ b/src/Segment/RepositoryInterface.php
@@ -0,0 +1,13 @@
+ Config::get('app.key'),
+ 'context' => [
+ 'locale' => Config::get('app.locale'),
+ 'timezone' => Setting::get('app_timezone'),
+ ],
+ ]);
+ } else {
+ return false;
+ }
+ }
+}
+
+if (!function_exists('segment_track')) {
+ /**
+ * Tracks events in Segment.com.
+ *
+ * @param string $event
+ * @param array $properties
+ *
+ * @return bool
+ */
+ function segment_track($event, array $properties)
+ {
+ if (Setting::get('app_track')) {
+ return Segment::track([
+ 'anonymousId' => Config::get('app.key'),
+ 'event' => $event,
+ 'properties' => $properties,
+ 'context' => [
+ 'locale' => Config::get('app.locale'),
+ 'timezone' => Setting::get('app_timezone'),
+ ],
+ ]);
+ } else {
+ return false;
+ }
+ }
+}
+
+if (!function_exists('segment_page')) {
+ /**
+ * Tracks pages in Segment.com.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ function segment_page($page)
+ {
+ if (Setting::get('app_track')) {
+ return Segment::page([
+ 'anonymousId' => Config::get('app.key'),
+ 'page' => $page,
+ 'context' => [
+ 'locale' => Config::get('app.locale'),
+ 'timezone' => Setting::get('app_timezone'),
+ ],
+ ]);
+ } else {
+ return false;
+ }
+ }
+}