Skip to content
Next
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Minds Backend - Engine
Project
Project
Details
Activity
Releases
Cycle Analytics
Insights
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
232
Issues
232
List
Boards
Labels
Service Desk
Milestones
Merge Requests
40
Merge Requests
40
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Security & Compliance
Security & Compliance
Dependency List
Packages
Packages
List
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Minds
Minds Backend - Engine
Compare Revisions
c35ce16a63325644ddddadaf1d046f81bdd0c488...aa5930670bd7f6b049fc7230fb68f399fe6af5bc
Source
aa5930670bd7f6b049fc7230fb68f399fe6af5bc
Select Git revision
...
Target
c35ce16a63325644ddddadaf1d046f81bdd0c488
Select Git revision
Compare
Commits (2)
Analytics Dashboard
· d65aab29
Mark Harding
authored
30 minutes ago
d65aab29
Merge branch 'feat/entity-centric-metrics' into 'epic/pro-affiliate-launch'
· aa593067
Mark Harding
authored
30 minutes ago
Analytics Dashboard See merge request
!343
aa593067
Hide whitespace changes
Inline
Side-by-side
Showing
59 changed files
with
3847 additions
and
6 deletions
+3847
-6
Controllers/Cli/PartnerEarnings.php
Controllers/Cli/PartnerEarnings.php
+42
-0
Controllers/api/v2/analytics/dashboards.php
Controllers/api/v2/analytics/dashboards.php
+59
-0
Core/Analytics/AnalyticsProvider.php
Core/Analytics/AnalyticsProvider.php
+4
-0
Core/Analytics/Dashboards/DashboardCollectionInterface.php
Core/Analytics/Dashboards/DashboardCollectionInterface.php
+12
-0
Core/Analytics/Dashboards/DashboardInterface.php
Core/Analytics/Dashboards/DashboardInterface.php
+20
-0
Core/Analytics/Dashboards/EarningsDashboard.php
Core/Analytics/Dashboards/EarningsDashboard.php
+107
-0
Core/Analytics/Dashboards/Engagement.php
Core/Analytics/Dashboards/Engagement.php
+0
-0
Core/Analytics/Dashboards/Filters/AbstractFilter.php
Core/Analytics/Dashboards/Filters/AbstractFilter.php
+58
-0
Core/Analytics/Dashboards/Filters/ChannelFilter.php
Core/Analytics/Dashboards/Filters/ChannelFilter.php
+39
-0
Core/Analytics/Dashboards/Filters/FilterGroup.php
Core/Analytics/Dashboards/Filters/FilterGroup.php
+0
-0
Core/Analytics/Dashboards/Filters/FilterInterface.php
Core/Analytics/Dashboards/Filters/FilterInterface.php
+0
-0
Core/Analytics/Dashboards/Filters/FilterOptions.php
Core/Analytics/Dashboards/Filters/FilterOptions.php
+40
-0
Core/Analytics/Dashboards/Filters/FilterOptionsOption.php
Core/Analytics/Dashboards/Filters/FilterOptionsOption.php
+43
-0
Core/Analytics/Dashboards/Filters/FiltersCollection.php
Core/Analytics/Dashboards/Filters/FiltersCollection.php
+123
-0
Core/Analytics/Dashboards/Filters/PlatformFilter.php
Core/Analytics/Dashboards/Filters/PlatformFilter.php
+33
-0
Core/Analytics/Dashboards/Filters/ViewTypeFilter.php
Core/Analytics/Dashboards/Filters/ViewTypeFilter.php
+37
-0
Core/Analytics/Dashboards/Manager.php
Core/Analytics/Dashboards/Manager.php
+21
-0
Core/Analytics/Dashboards/Metrics/AbstractMetric.php
Core/Analytics/Dashboards/Metrics/AbstractMetric.php
+104
-0
Core/Analytics/Dashboards/Metrics/ActiveUsersMetric.php
Core/Analytics/Dashboards/Metrics/ActiveUsersMetric.php
+211
-0
Core/Analytics/Dashboards/Metrics/Earnings/AbstractEarningsMetric.php
...cs/Dashboards/Metrics/Earnings/AbstractEarningsMetric.php
+181
-0
Core/Analytics/Dashboards/Metrics/Earnings/ReferralsEarningsMetric.php
...s/Dashboards/Metrics/Earnings/ReferralsEarningsMetric.php
+27
-0
Core/Analytics/Dashboards/Metrics/Earnings/SalesEarningsMetric.php
...ytics/Dashboards/Metrics/Earnings/SalesEarningsMetric.php
+27
-0
Core/Analytics/Dashboards/Metrics/Earnings/TotalEarningsMetric.php
...ytics/Dashboards/Metrics/Earnings/TotalEarningsMetric.php
+27
-0
Core/Analytics/Dashboards/Metrics/Earnings/ViewsEarningsMetric.php
...ytics/Dashboards/Metrics/Earnings/ViewsEarningsMetric.php
+27
-0
Core/Analytics/Dashboards/Metrics/MetricSummary.php
Core/Analytics/Dashboards/Metrics/MetricSummary.php
+41
-0
Core/Analytics/Dashboards/Metrics/MetricTimeseries.php
Core/Analytics/Dashboards/Metrics/MetricTimeseries.php
+22
-0
Core/Analytics/Dashboards/Metrics/MetricsCollection.php
Core/Analytics/Dashboards/Metrics/MetricsCollection.php
+149
-0
Core/Analytics/Dashboards/Metrics/PageviewsMetric.php
Core/Analytics/Dashboards/Metrics/PageviewsMetric.php
+178
-0
Core/Analytics/Dashboards/Metrics/SignupsMetric.php
Core/Analytics/Dashboards/Metrics/SignupsMetric.php
+191
-0
Core/Analytics/Dashboards/Metrics/ViewsMetric.php
Core/Analytics/Dashboards/Metrics/ViewsMetric.php
+188
-0
Core/Analytics/Dashboards/Metrics/ViewsTableMetric.php
Core/Analytics/Dashboards/Metrics/ViewsTableMetric.php
+176
-0
Core/Analytics/Dashboards/Metrics/Visualisations/AbstractVisualisation.php
...shboards/Metrics/Visualisations/AbstractVisualisation.php
+18
-0
Core/Analytics/Dashboards/Metrics/Visualisations/ChartVisualisation.php
.../Dashboards/Metrics/Visualisations/ChartVisualisation.php
+46
-0
Core/Analytics/Dashboards/Metrics/Visualisations/TableVisualisation.php
.../Dashboards/Metrics/Visualisations/TableVisualisation.php
+34
-0
Core/Analytics/Dashboards/Metrics/Visualisations/VisualisationInterface.php
...hboards/Metrics/Visualisations/VisualisationInterface.php
+6
-0
Core/Analytics/Dashboards/Timespans/AbstractTimespan.php
Core/Analytics/Dashboards/Timespans/AbstractTimespan.php
+52
-0
Core/Analytics/Dashboards/Timespans/MtdTimespan.php
Core/Analytics/Dashboards/Timespans/MtdTimespan.php
+25
-0
Core/Analytics/Dashboards/Timespans/TimespansCollection.php
Core/Analytics/Dashboards/Timespans/TimespansCollection.php
+72
-0
Core/Analytics/Dashboards/Timespans/TodayTimespan.php
Core/Analytics/Dashboards/Timespans/TodayTimespan.php
+30
-0
Core/Analytics/Dashboards/Timespans/YtdTimespan.php
Core/Analytics/Dashboards/Timespans/YtdTimespan.php
+25
-0
Core/Analytics/Dashboards/Timespans/_1yTimespan.php
Core/Analytics/Dashboards/Timespans/_1yTimespan.php
+25
-0
Core/Analytics/Dashboards/Timespans/_30dTimespan.php
Core/Analytics/Dashboards/Timespans/_30dTimespan.php
+25
-0
Core/Analytics/Dashboards/TrafficDashboard.php
Core/Analytics/Dashboards/TrafficDashboard.php
+109
-0
Core/Analytics/Dashboards/TrendingDashboard.php
Core/Analytics/Dashboards/TrendingDashboard.php
+106
-0
Core/Analytics/EntityCentric/EntityCentricRecord.php
Core/Analytics/EntityCentric/EntityCentricRecord.php
+8
-0
Core/Analytics/EntityCentric/Manager.php
Core/Analytics/EntityCentric/Manager.php
+17
-2
Core/Analytics/EntityCentric/PartnerEarningsSynchroniser.php
Core/Analytics/EntityCentric/PartnerEarningsSynchroniser.php
+71
-0
Core/Analytics/EntityCentric/Sums.php
Core/Analytics/EntityCentric/Sums.php
+107
-0
Core/Analytics/Metrics/Retention.php
Core/Analytics/Metrics/Retention.php
+4
-4
Core/Monetization/Partners/EarningsDeposit.php
Core/Monetization/Partners/EarningsDeposit.php
+44
-0
Core/Monetization/Partners/Manager.php
Core/Monetization/Partners/Manager.php
+95
-0
Core/Monetization/Partners/Repository.php
Core/Monetization/Partners/Repository.php
+131
-0
Spec/Core/Analytics/Dashboards/Filters/FiltersCollectionSpec.php
...re/Analytics/Dashboards/Filters/FiltersCollectionSpec.php
+37
-0
Spec/Core/Analytics/Dashboards/Metrics/ActiveUsersMetricSpec.php
...re/Analytics/Dashboards/Metrics/ActiveUsersMetricSpec.php
+126
-0
Spec/Core/Analytics/Dashboards/Metrics/MetricsCollectionSpec.php
...re/Analytics/Dashboards/Metrics/MetricsCollectionSpec.php
+82
-0
Spec/Core/Analytics/Dashboards/Metrics/SignupsMetricSpec.php
Spec/Core/Analytics/Dashboards/Metrics/SignupsMetricSpec.php
+126
-0
Spec/Core/Analytics/Dashboards/Metrics/ViewsMetricSpec.php
Spec/Core/Analytics/Dashboards/Metrics/ViewsMetricSpec.php
+120
-0
Spec/Core/Analytics/Dashboards/Timespans/TimespansCollectionSpec.php
...nalytics/Dashboards/Timespans/TimespansCollectionSpec.php
+51
-0
Spec/Core/Analytics/Dashboards/TrafficDashboardSpec.php
Spec/Core/Analytics/Dashboards/TrafficDashboardSpec.php
+68
-0
No files found.
Controllers/Cli/PartnerEarnings.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Controllers\Cli
;
use
Minds\Core
;
use
Minds\Core\Monetization\Partners\Manager
;
use
Minds\Cli
;
use
Minds\Interfaces
;
use
Minds\Exceptions
;
use
Minds\Entities
;
class
PartnerEarnings
extends
Cli\Controller
implements
Interfaces\CliControllerInterface
{
public
function
__construct
()
{
}
public
function
help
(
$command
=
null
)
{
$this
->
out
(
'TBD'
);
}
public
function
exec
()
{
$this
->
out
(
'Missing subcommand'
);
}
public
function
sync
()
{
error_reporting
(
E_ALL
);
ini_set
(
'display_errors'
,
1
);
$daysAgo
=
$this
->
getOpt
(
'daysAgo'
)
?:
0
;
$from
=
$this
->
getOpt
(
'from'
)
?:
strtotime
(
"midnight
$daysAgo
days ago"
);
$manager
=
new
Manager
();
$i
=
0
;
foreach
(
$manager
->
issueDeposits
([
'from'
=>
$from
])
as
$record
)
{
$this
->
out
(
++
$i
);
}
}
}
This diff is collapsed.
Click to expand it.
Controllers/api/v2/analytics/dashboards.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Controllers\api\v2\analytics
;
use
Minds\Api\Factory
;
use
Minds\Core
;
use
Minds\Core\Session
;
use
Minds\Core\Di\Di
;
use
Minds\Common\Cookie
;
use
Minds\Entities
;
use
Minds\Helpers\Counters
;
use
Minds\Interfaces
;
class
dashboards
implements
Interfaces\Api
{
public
function
get
(
$pages
)
{
$dashboardsManager
=
Di
::
_
()
->
get
(
'Analytics\Dashboards\Manager'
);
$id
=
$pages
[
0
]
??
'unknown'
;
$dashboard
=
$dashboardsManager
->
getDashboardById
(
$id
);
$dashboard
->
setUser
(
Session
::
getLoggedInUser
());
if
(
isset
(
$_GET
[
'timespan'
]))
{
$dashboard
->
setTimespanId
(
$_GET
[
'timespan'
]);
}
if
(
isset
(
$_GET
[
'filter'
]))
{
$filterIds
=
explode
(
','
,
$_GET
[
'filter'
]);
$dashboard
->
setFilterIds
(
$filterIds
);
}
if
(
isset
(
$_GET
[
'metric'
]))
{
$dashboard
->
setMetricId
(
$_GET
[
'metric'
]);
}
return
Factory
::
response
([
'dashboard'
=>
$dashboard
->
export
(),
]);
}
public
function
post
(
$pages
)
{
return
Factory
::
response
([]);
}
public
function
put
(
$pages
)
{
return
Factory
::
response
([]);
}
public
function
delete
(
$pages
)
{
return
Factory
::
response
([]);
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/AnalyticsProvider.php
View file @
aa593067
...
...
@@ -16,5 +16,9 @@ class AnalyticsProvider extends Provider
$this
->
di
->
bind
(
'Analytics\Graphs\Repository'
,
function
(
$di
)
{
return
new
Graphs\Repository
();
},
[
'useFactory'
=>
true
]);
$this
->
di
->
bind
(
'Analytics\Dashboards\Manager'
,
function
(
$di
)
{
return
new
Dashboards\Manager
();
},
[
'useFactory'
=>
true
]);
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/DashboardCollectionInterface.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards
;
interface
DashboardCollectionInterface
{
/**
* Export everything in the collection
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
;
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/DashboardInterface.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards
;
interface
DashboardInterface
{
/**
* Build the dashboard
* NOTE: return type not specified due to php
* having terrible typing support
* @return self
*/
public
function
build
();
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
;
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/EarningsDashboard.php
0 → 100644
View file @
aa593067
<?php
/**
* Earnings Dashboard
*/
namespace
Minds\Core\Analytics\Dashboards
;
use
Minds\Entities\User
;
use
Minds\Traits\MagicAttributes
;
/**
* @method EarningsDashboard setTimespanId(string $timespanId)
* @method EarningsDashboard setFilterIds(array $filtersIds)
* @method EarningsDashboard setUser(User $user)
*/
class
EarningsDashboard
implements
DashboardInterface
{
use
MagicAttributes
;
/** @var string */
private
$timespanId
=
'30d'
;
/** @var string[] */
private
$filterIds
=
[
'platform::browser'
];
/** @var string */
private
$metricId
=
'active_users'
;
/** @var Timespans\TimespansCollection */
private
$timespansCollection
;
/** @var Metrics\MetricsCollection */
private
$metricsCollection
;
/** @var Filters\FiltersCollection */
private
$filtersCollection
;
/** @var User */
private
$user
;
public
function
__construct
(
$timespansCollection
=
null
,
$metricsCollection
=
null
,
$filtersCollection
=
null
)
{
$this
->
timespansCollection
=
$timespansCollection
??
new
Timespans\TimespansCollection
();
$this
->
metricsCollection
=
$metricsCollection
??
new
Metrics\MetricsCollection
();
$this
->
filtersCollection
=
$filtersCollection
??
new
Filters\FiltersCollection
();
}
/**
* Build the dashboard
* @return self
*/
public
function
build
()
:
self
{
$this
->
timespansCollection
->
setSelectedId
(
$this
->
timespanId
)
->
addTimespans
(
new
Timespans\TodayTimespan
(),
new
Timespans\_30dTimespan
(),
new
Timespans\_1yTimespan
(),
new
Timespans\MtdTimespan
(),
new
Timespans\YtdTimespan
()
);
$this
->
filtersCollection
->
setSelectedIds
(
$this
->
filterIds
)
->
setUser
(
$this
->
user
)
->
addFilters
(
new
Filters\ChannelFilter
()
);
$this
->
metricsCollection
->
setTimespansCollection
(
$this
->
timespansCollection
)
->
setFiltersCollection
(
$this
->
filtersCollection
)
->
setSelectedId
(
$this
->
metricId
)
->
setUser
(
$this
->
user
)
->
addMetrics
(
new
Metrics\Earnings\TotalEarningsMetric
(),
new
Metrics\Earnings\ViewsEarningsMetric
(),
new
Metrics\Earnings\ReferralsEarningsMetric
(),
new
Metrics\Earnings\SalesEarningsMetric
()
)
->
build
();
return
$this
;
}
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
$this
->
build
();
return
[
'category'
=>
'earnings'
,
'label'
=>
'Pro Earnings'
,
'description'
=>
'Earnings for PRO members will be paid out within 30 days upon reaching a minumum balance of $100.00.'
,
'timespan'
=>
$this
->
timespansCollection
->
getSelected
()
->
getId
(),
'timespans'
=>
$this
->
timespansCollection
->
export
(),
'metric'
=>
$this
->
metricsCollection
->
getSelected
()
->
getId
(),
'metrics'
=>
$this
->
metricsCollection
->
export
(),
'filter'
=>
$this
->
filtersCollection
->
getSelectedIds
(),
'filters'
=>
$this
->
filtersCollection
->
export
(),
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Engagement.php
0 → 100644
View file @
aa593067
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/AbstractFilter.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Filters
;
use
Minds\Traits\MagicAttributes
;
abstract
class
AbstractFilter
{
use
MagicAttributes
;
/** @var string */
protected
$id
;
/** @var string */
protected
$label
;
/** @var string */
protected
$description
;
/** @var array */
protected
$permissions
=
[
'user'
,
'admin'
];
/** @var FilterOptions */
protected
$options
;
/** @var string */
protected
$selectedOption
;
/**
* Set the selected option and toggle if selected
* @param string $selectedOptionId
* @return self
*/
public
function
setSelectedOption
(
string
$selectedOptionId
)
:
self
{
$this
->
selectedOption
=
$selectedOptionId
;
foreach
(
$this
->
options
->
getOptions
()
as
$k
=>
$option
)
{
if
(
$option
->
getId
()
===
$selectedOptionId
)
{
$option
->
setSelected
(
true
);
}
}
return
$this
;
}
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
$extras
=
[])
:
array
{
return
[
'id'
=>
(
string
)
$this
->
id
,
'label'
=>
(
string
)
$this
->
label
,
'description'
=>
(
string
)
$this
->
description
,
'options'
=>
(
array
)
$this
->
options
->
export
(),
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/ChannelFilter.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Filters
;
class
ChannelFilter
extends
AbstractFilter
{
/** @var string */
protected
$id
=
"channel"
;
/** @var string */
protected
$label
=
"Channel"
;
/** @var array */
protected
$permissions
=
[
'admin'
];
/** @var string */
protected
$description
=
"Filter by channels or by the full site"
;
/** @var string */
protected
$selectedOption
=
"all"
;
public
function
__construct
()
{
$this
->
options
=
(
new
FilterOptions
())
->
setOptions
(
(
new
FilterOptionsOption
())
->
setId
(
"all"
)
->
setLabel
(
"All"
)
->
setDescription
(
"Global, site-wide metrics"
),
(
new
FilterOptionsOption
())
->
setId
(
"self"
)
->
setLabel
(
"Me"
)
->
setDescription
(
"Your currently logged in user"
),
(
new
FilterOptionsOption
())
->
setId
(
"custom"
)
->
setLabel
(
"Custom (Search)"
)
->
setDescription
(
"Search for a channel to view their metrics"
)
);
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/FilterGroup.php
0 → 100644
View file @
aa593067
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/FilterInterface.php
0 → 100644
View file @
aa593067
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/FilterOptions.php
0 → 100644
View file @
aa593067
<?php
/**
*
*/
namespace
Minds\Core\Analytics\Dashboards\Filters
;
use
Minds\Traits\MagicAttributes
;
class
FilterOptions
{
use
MagicAttributes
;
/** @var FilterOptionsOption[] */
private
$options
=
[];
/**
* Set options
* @param FilterOptionsOption $options
* @return self
*/
public
function
setOptions
(
FilterOptionsOption
...
$options
)
:
self
{
$this
->
options
=
$options
;
return
$this
;
}
/**
* Export
* @param array $export
* @return array
*/
public
function
export
(
array
$export
=
[])
:
array
{
$options
=
[];
foreach
(
$this
->
options
as
$option
)
{
$options
[]
=
$option
->
export
();
}
return
$options
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/FilterOptionsOption.php
0 → 100644
View file @
aa593067
<?php
/**
*
*/
namespace
Minds\Core\Analytics\Dashboards\Filters
;
use
Minds\Traits\MagicAttributes
;
class
FilterOptionsOption
{
use
MagicAttributes
;
/** @var string */
private
$id
;
/** @var string */
private
$label
;
/** @var string */
private
$description
;
/** @var bool */
private
$available
=
true
;
/** @var bool */
private
$selected
=
false
;
/**
* Export
* @param array $export
* @return array
*/
public
function
export
(
array
$export
=
[])
:
array
{
return
[
'id'
=>
$this
->
id
,
'label'
=>
$this
->
label
,
'description'
=>
$this
->
description
,
'available'
=>
(
bool
)
$this
->
available
,
'selected'
=>
(
bool
)
$this
->
selected
,
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/FiltersCollection.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Filters
;
use
Minds\Entities\User
;
use
Minds\Core\Analytics\Dashboards\DashboardCollectionInterface
;
class
FiltersCollection
implements
DashboardCollectionInterface
{
/** @var AbstractFilter[] */
private
$filters
=
[];
/** @var string[] */
private
$selectedIds
;
/** @var User */
private
$user
;
/**
* Set the selected metric id
* @param string[]
* @return self
*/
public
function
setSelectedIds
(
array
$selectedIds
)
:
self
{
$this
->
selectedIds
=
$selectedIds
;
return
$this
;
}
/**
* Selected ids
* @return string[]
*/
public
function
getSelectedIds
()
:
array
{
return
$this
->
selectedIds
;
}
/**
* @param User $user
* @return self
*/
public
function
setUser
(
User
$user
)
:
self
{
$this
->
user
=
$user
;
return
$this
;
}
public
function
getSelected
()
:
array
{
// Filters have scoped key pairs like
// key::value
// platform::browser
$selected
=
[];
foreach
(
$this
->
selectedIds
as
$selectedId
)
{
list
(
$key
,
$value
)
=
explode
(
'::'
,
$selectedId
);
if
(
!
isset
(
$this
->
filters
[
$key
]))
{
continue
;
}
$selected
[
$key
]
=
$this
->
filters
[
$key
];
$selected
[
$key
]
->
setSelectedOption
(
$value
);
}
return
$selected
;
}
/**
* Set the filters
* @param AbstractFilter[] $filters
* @return self
*/
public
function
addFilters
(
AbstractFilter
...
$filters
)
:
self
{
foreach
(
$filters
as
$filter
)
{
if
(
in_array
(
'admin'
,
$filter
->
getPermissions
(),
true
)
&&
!
$this
->
user
->
isAdmin
()
&&
!
in_array
(
'user'
,
$filter
->
getPermissions
(),
true
)
)
{
continue
;
}
$this
->
filters
[
$filter
->
getId
()]
=
$filter
;
}
return
$this
;
}
/**
* Return the set metrics
* @return AbstractFilter[]
*/
public
function
getFilters
()
:
array
{
return
$this
->
filters
;
}
public
function
clear
()
:
self
{
$this
->
filters
=
[];
$this
->
selectedIds
=
[];
return
$this
;
}
// public function build(): self
// {
// foreach ($this->filters as $filter) {
// $filter->build();
// }
// return $this;
// }
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
$export
=
[];
foreach
(
$this
->
filters
as
$filter
)
{
$export
[]
=
$filter
->
export
();
}
return
$export
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/PlatformFilter.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Filters
;
class
PlatformFilter
extends
AbstractFilter
{
/** @var string */
protected
$id
=
"platform"
;
/** @var string */
protected
$label
=
"Platform"
;
/** @var string */
protected
$description
=
"Filter by device types"
;
public
function
__construct
()
{
$this
->
options
=
(
new
FilterOptions
())
->
setOptions
(
(
new
FilterOptionsOption
())
->
setId
(
"all"
)
->
setLabel
(
"All"
)
->
setDescription
(
"Browsers, Mobile and APIs"
),
(
new
FilterOptionsOption
())
->
setId
(
"browser"
)
->
setLabel
(
"Browser"
)
->
setDescription
(
"Browsers"
),
(
new
FilterOptionsOption
())
->
setId
(
"mobile"
)
->
setLabel
(
"Mobile"
)
->
setDescription
(
"Native mobile applications"
)
);
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Filters/ViewTypeFilter.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Filters
;
class
ViewTypeFilter
extends
AbstractFilter
{
/** @var string */
protected
$id
=
"view_type"
;
/** @var string */
protected
$label
=
"View types"
;
/** @var string */
protected
$description
=
"Filter by the breakdown of views"
;
public
function
__construct
()
{
$this
->
options
=
(
new
FilterOptions
())
->
setOptions
(
(
new
FilterOptionsOption
())
->
setId
(
"total"
)
->
setLabel
(
"Total"
)
->
setDescription
(
"All views recorded on assets"
),
(
new
FilterOptionsOption
())
->
setId
(
"organic"
)
->
setLabel
(
"Organic"
)
->
setDescription
(
"Views on assets that excludes boosted impressions"
),
(
new
FilterOptionsOption
())
->
setId
(
"boosted"
)
->
setLabel
(
"Boosted"
)
->
setDescription
(
"Views recorded on assets that were boosted"
),
(
new
FilterOptionsOption
())
->
setId
(
"single"
)
->
setLabel
(
"Pageview"
)
->
setDecription
(
"Views recorded on single pages, not in feeds"
)
);
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Manager.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards
;
class
Manager
{
const
DASHBOARDS
=
[
'traffic'
=>
TrafficDashboard
::
class
,
'trending'
=>
TrendingDashboard
::
class
,
'earnings'
=>
EarningsDashboard
::
class
,
];
/**
* @param string $id
* @return DashboardInterface
*/
public
function
getDashboardById
(
string
$id
)
:
DashboardInterface
{
$class
=
self
::
DASHBOARDS
[
$id
];
return
new
$class
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/AbstractMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Entities\User
;
use
Minds\Traits\MagicAttributes
;
/**
* @method AbstractMetric setTimespansCollection(TimespansCollection $timespansCollection)
* @method AbstractMetric setFiltersCollection(FiltersCollection $filtersCollection)
* @method string getId()
* @method string getLabel()
* @method MetricSummary getSummary()
* @method array getPermissions()
* @method AbstractMetric setUser(User $user)
*/
abstract
class
AbstractMetric
{
use
MagicAttributes
;
/** @var string */
protected
$id
;
/** @var string */
protected
$label
;
/** @var string */
protected
$description
;
/** @var string */
protected
$unit
=
'number'
;
/** @var string[] */
protected
$permissions
;
/** @var MetricSummary */
protected
$summary
;
/** @var VisualisationInterface */
protected
$visualisation
;
/** @var TimespansCollection */
protected
$timespansCollection
;
/** @var FiltersCollection */
protected
$filtersCollection
;
/** @var User */
protected
$user
;
/**
* Return the usd guid for metrics
* @return string
*/
protected
function
getUserGuid
()
:
?
string
{
$filters
=
$this
->
filtersCollection
->
getSelected
();
$channelFilter
=
$filters
[
'channel'
]
??
null
;
if
(
!
$channelFilter
)
{
if
(
!
$this
->
user
)
{
throw
new
\Exception
(
"You must be loggedin"
);
}
if
(
$this
->
user
->
isAdmin
())
{
return
""
;
}
return
$this
->
user
->
getGuid
();
}
if
(
$channelFilter
->
getSelectedOption
()
===
'all'
)
{
if
(
$this
->
user
->
isAdmin
())
{
return
""
;
}
$channelFilter
->
setSelectedOption
(
'self'
);
}
if
(
$channelFilter
->
getSelectedOption
()
===
'self'
)
{
return
$this
->
user
->
getGuid
();
}
// TODO: check permissions first
return
$channelFilter
->
getSelectedOption
();
}
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
$extras
=
[])
:
array
{
return
[
'id'
=>
(
string
)
$this
->
id
,
'label'
=>
(
string
)
$this
->
label
,
'description'
=>
(
string
)
$this
->
description
,
'unit'
=>
(
string
)
$this
->
unit
,
'permissions'
=>
(
array
)
$this
->
permissions
,
'summary'
=>
$this
->
summary
?
(
array
)
$this
->
summary
->
export
()
:
null
,
'visualisation'
=>
$this
->
visualisation
?
(
array
)
$this
->
visualisation
->
export
()
:
null
,
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/ActiveUsersMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Data\ElasticSearch
;
class
ActiveUsersMetric
extends
AbstractMetric
{
/** @var ElasticSearch\Client */
private
$es
;
/** @var string */
protected
$id
=
'active_users'
;
/** @var string */
protected
$label
=
'Active Users'
;
/** @var string */
protected
$description
=
'Users who make at least one single request to Minds'
;
/** @var array */
protected
$permissions
=
[
'admin'
];
public
function
__construct
(
$es
=
null
)
{
$this
->
es
=
$es
??
Di
::
_
()
->
get
(
'Database\ElasticSearch'
);
}
/**
* Build the metric summary
* @return self
*/
public
function
buildSummary
()
:
self
{
if
(
$this
->
getUserGuid
())
{
return
$this
;
}
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$filters
=
$this
->
filtersCollection
->
getSelected
();
$comparisonTsMs
=
strtotime
(
"-
{
$timespan
->
getComparisonInterval
()
}
days"
,
$timespan
->
getFromTsMs
()
/
1000
)
*
1000
;
$currentTsMs
=
$timespan
->
getFromTsMs
();
// Field name to use for the aggregation
$aggField
=
"active::total"
;
// The aggregation type, this differs by resolution
$aggType
=
"sum"
;
// The resolution to use
$resolution
=
'day'
;
switch
(
$timespan
->
getId
())
{
case
'today'
:
$resolution
=
'day'
;
$aggType
=
"sum"
;
break
;
case
'30d'
:
case
'mtd'
:
$resolution
=
'month'
;
$aggType
=
"max"
;
break
;
case
'1y'
:
case
'ytd'
:
$resolution
=
'month'
;
$aggType
=
"avg"
;
break
;
}
$values
=
[];
foreach
([
'value'
=>
$currentTsMs
,
'comparison'
=>
$comparisonTsMs
]
as
$key
=>
$tsMs
)
{
$must
=
[];
// Specify the resolution to avoid duplicates
$must
[]
=
[
'term'
=>
[
'resolution'
=>
$resolution
,
],
];
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$tsMs
,
'lte'
=>
strtotime
(
"midnight +
{
$timespan
->
getComparisonInterval
()
}
days"
,
$tsMs
/
1000
)
*
1000
,
],
];
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
$aggType
=>
[
'field'
=>
$aggField
,
],
],
],
],
];
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$values
[
$key
]
=
$response
[
'aggregations'
][
'1'
][
'value'
];
}
$this
->
summary
=
new
MetricSummary
();
$this
->
summary
->
setValue
(
$values
[
'value'
])
->
setComparisonValue
(
$values
[
'comparison'
])
->
setComparisonInterval
(
$timespan
->
getComparisonInterval
());
return
$this
;
}
/**
* Build a visualisation for the metric
* @return self
*/
public
function
buildVisualisation
()
:
self
{
if
(
$this
->
getUserGuid
())
{
$this
->
visualisation
=
(
new
Visualisations\ChartVisualisation
());
return
$this
;
}
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$xValues
=
[];
$yValues
=
[];
$must
=
[];
// Range must be from previous period
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$timespan
->
getFromTsMs
(),
],
];
// Use our global metrics
$must
[][
'term'
]
=
[
'entity_urn'
=>
'urn:metric:global'
];
// Specify the resolution to avoid duplicates
$must
[]
=
[
'term'
=>
[
'resolution'
=>
$timespan
->
getInterval
(),
],
];
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'date_histogram'
=>
[
'field'
=>
'@timestamp'
,
'interval'
=>
$timespan
->
getInterval
(),
'min_doc_count'
=>
1
,
],
'aggs'
=>
[
'2'
=>
[
'sum'
=>
[
'field'
=>
'active::total'
,
],
],
],
],
],
],
];
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$buckets
=
[];
foreach
(
$response
[
'aggregations'
][
'1'
][
'buckets'
]
as
$bucket
)
{
$date
=
date
(
Visualisations\ChartVisualisation
::
DATE_FORMAT
,
$bucket
[
'key'
]
/
1000
);
$xValues
[]
=
$date
;
$yValues
[]
=
$bucket
[
'2'
][
'value'
];
$buckets
[]
=
[
'key'
=>
$bucket
[
'key'
],
'date'
=>
date
(
'c'
,
$bucket
[
'key'
]
/
1000
),
'value'
=>
$bucket
[
'2'
][
'value'
]
];
}
$this
->
visualisation
=
(
new
Visualisations\ChartVisualisation
())
->
setXValues
(
$xValues
)
->
setYValues
(
$yValues
)
->
setXLabel
(
'Date'
)
->
setYLabel
(
'Count'
)
->
setBuckets
(
$buckets
);
return
$this
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Earnings/AbstractEarningsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Earnings
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Core\Data\ElasticSearch
;
use
Minds\Core\Analytics\Dashboards\Metrics\AbstractMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\MetricSummary
;
use
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
abstract
class
AbstractEarningsMetric
extends
AbstractMetric
{
/** @var Elasticsearch\Client */
private
$es
;
/** @var string */
protected
$id
=
''
;
/** @var string */
protected
$label
=
''
;
/** @var string */
protected
$description
=
''
;
/** @var array */
protected
$permissions
=
[
'user'
,
'admin'
];
/** @var string */
protected
$unit
=
'usd'
;
/** @var string */
protected
$aggField
=
''
;
public
function
__construct
(
$es
=
null
)
{
$this
->
es
=
$es
??
Di
::
_
()
->
get
(
'Database\ElasticSearch'
);
}
/**
* Build the metrics
* @return self
*/
public
function
buildSummary
()
:
self
{
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$filters
=
$this
->
filtersCollection
->
getSelected
();
$comparisonTsMs
=
strtotime
(
"midnight -
{
$timespan
->
getComparisonInterval
()
}
days"
,
$timespan
->
getFromTsMs
()
/
1000
)
*
1000
;
$currentTsMs
=
$timespan
->
getFromTsMs
();
$values
=
[];
foreach
([
'value'
=>
$currentTsMs
,
'comparison'
=>
$comparisonTsMs
]
as
$key
=>
$tsMs
)
{
$must
=
[];
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$tsMs
,
'lte'
=>
strtotime
(
"midnight +
{
$timespan
->
getComparisonInterval
()
}
days"
,
$tsMs
/
1000
)
*
1000
,
],
];
if
(
$userGuid
=
$this
->
getUserGuid
())
{
$must
[]
=
[
'term'
=>
[
'owner_guid'
=>
$userGuid
,
],
];
}
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'sum'
=>
[
'field'
=>
$this
->
aggField
,
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$values
[
$key
]
=
$response
[
'aggregations'
][
'1'
][
'value'
];
}
$this
->
summary
=
new
MetricSummary
();
$this
->
summary
->
setValue
(
$values
[
'value'
])
->
setComparisonValue
(
$values
[
'comparison'
])
->
setComparisonInterval
(
$timespan
->
getComparisonInterval
())
->
setComparisonPositivity
(
true
);
return
$this
;
}
/**
* Build a visualisation for the metric
* @return self
*/
public
function
buildVisualisation
()
:
self
{
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$filters
=
$this
->
filtersCollection
->
getSelected
();
$must
=
[];
// Range must be from previous period
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$timespan
->
getFromTsMs
(),
],
];
if
(
$userGuid
=
$this
->
getUserGuid
())
{
$must
[]
=
[
'term'
=>
[
'owner_guid'
=>
$userGuid
,
],
];
}
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'date_histogram'
=>
[
'field'
=>
'@timestamp'
,
'interval'
=>
$timespan
->
getInterval
(),
'min_doc_count'
=>
1
,
],
'aggs'
=>
[
'2'
=>
[
'sum'
=>
[
'field'
=>
$this
->
aggField
,
],
],
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$buckets
=
[];
foreach
(
$response
[
'aggregations'
][
'1'
][
'buckets'
]
as
$bucket
)
{
$date
=
date
(
Visualisations\ChartVisualisation
::
DATE_FORMAT
,
$bucket
[
'key'
]
/
1000
);
$buckets
[]
=
[
'key'
=>
$bucket
[
'key'
],
'date'
=>
date
(
'c'
,
$bucket
[
'key'
]
/
1000
),
'value'
=>
$bucket
[
'2'
][
'value'
]
];
}
$this
->
visualisation
=
(
new
Visualisations\ChartVisualisation
())
->
setXLabel
(
'Date'
)
->
setYLabel
(
'Count'
)
->
setBuckets
(
$buckets
);
return
$this
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Earnings/ReferralsEarningsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Earnings
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Core\Data\ElasticSearch
;
use
Minds\Core\Analytics\Dashboards\Metrics\AbstractMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\MetricSummary
;
use
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
class
ReferralsEarningsMetric
extends
AbstractEarningsMetric
{
/** @var string */
protected
$id
=
'earnings_referrals'
;
/** @var string */
protected
$label
=
'Referrals USD'
;
/** @var string */
protected
$description
=
'Referral earnings for PRO users'
;
/** @var array */
protected
$permissions
=
[
'user'
,
'admin'
];
/** @var string */
protected
$aggField
=
'usd_earnings::referrals'
;
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Earnings/SalesEarningsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Earnings
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Core\Data\ElasticSearch
;
use
Minds\Core\Analytics\Dashboards\Metrics\AbstractMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\MetricSummary
;
use
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
class
SalesEarningsMetric
extends
AbstractEarningsMetric
{
/** @var string */
protected
$id
=
'earnings_sales'
;
/** @var string */
protected
$label
=
'Sales USD'
;
/** @var string */
protected
$description
=
'Sales earnings for PRO users'
;
/** @var array */
protected
$permissions
=
[
'user'
,
'admin'
];
/** @var string */
protected
$aggField
=
'usd_earnings::sales'
;
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Earnings/TotalEarningsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Earnings
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Core\Data\ElasticSearch
;
use
Minds\Core\Analytics\Dashboards\Metrics\AbstractMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\MetricSummary
;
use
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
class
TotalEarningsMetric
extends
AbstractEarningsMetric
{
/** @var string */
protected
$id
=
'earnings_total'
;
/** @var string */
protected
$label
=
'Total Earnings'
;
/** @var string */
protected
$description
=
'Total earnings for PRO users'
;
/** @var array */
protected
$permissions
=
[
'user'
,
'admin'
];
/** @var string */
protected
$aggField
=
'usd_earnings::total'
;
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Earnings/ViewsEarningsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Earnings
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Core\Data\ElasticSearch
;
use
Minds\Core\Analytics\Dashboards\Metrics\AbstractMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\MetricSummary
;
use
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
class
ViewsEarningsMetric
extends
AbstractEarningsMetric
{
/** @var string */
protected
$id
=
'earnings_views'
;
/** @var string */
protected
$label
=
'Pageviews USD'
;
/** @var string */
protected
$description
=
'Pageview earnings for PRO users'
;
/** @var array */
protected
$permissions
=
[
'user'
,
'admin'
];
/** @var string */
protected
$aggField
=
'usd_earnings::views'
;
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/MetricSummary.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Traits\MagicAttributes
;
/**
* @method MetricSummary setValue(int $value)
* @method MetricSummary setComparisonValue(int $value)
* @method MetricSummary setComparisonInterval(int $interval)
*/
class
MetricSummary
{
use
MagicAttributes
;
/** @var int */
private
$value
=
0
;
/** @var int */
private
$comparisonValue
=
0
;
/** @var int */
private
$comparisonInterval
=
1
;
/** @var bool */
private
$comparisonPositivity
=
true
;
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
return
[
'current_value'
=>
(
int
)
$this
->
value
,
'comparison_value'
=>
(
int
)
$this
->
comparisonValue
,
'comparison_interval'
=>
(
int
)
$this
->
comparisonInterval
,
'comparison_positive_inclination'
=>
(
bool
)
$this
->
comparisonPositivity
,
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/MetricTimeseries.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Traits\MagicAttributes
;
class
MetricTimeseries
{
/** @var array */
private
$dateHistogram
=
[];
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
return
[
'date_histogram'
=>
(
array
)
$this
->
dateHistogram
,
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/MetricsCollection.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Entities\User
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Analytics\Dashboards\Filters\FiltersCollection
;
use
Minds\Core\Analytics\Dashboards\DashboardCollectionInterface
;
class
MetricsCollection
implements
DashboardCollectionInterface
{
/** @var AbstractMetric[] */
private
$metrics
=
[];
/** @var string */
private
$selectedId
;
/** @var TimespansCollection */
private
$timespansCollection
;
/** @var FiltersCollection */
private
$filtersCollection
;
/** @var User */
private
$user
;
/**
* @param TimespansCollection $timespansCollection
* @return self
*/
public
function
setTimespansCollection
(
TimespansCollection
$timespansCollection
)
:
self
{
$this
->
timespansCollection
=
$timespansCollection
;
return
$this
;
}
/**
* @param FiltersCollection $filtersCollection
* @return self
*/
public
function
setFiltersCollection
(
?
FiltersCollection
$filtersCollection
)
:
self
{
$this
->
filtersCollection
=
$filtersCollection
;
return
$this
;
}
/**
* @param User $user
* @return self
*/
public
function
setUser
(
User
$user
)
:
self
{
$this
->
user
=
$user
;
return
$this
;
}
/**
* Set the selected metric id
* @param string
* @return self
*/
public
function
setSelectedId
(
string
$selectedId
)
:
self
{
$this
->
selectedId
=
$selectedId
;
return
$this
;
}
/**
* Set the metrics
* @param AbstractMetric[] $metric
* @return self
*/
public
function
addMetrics
(
AbstractMetric
...
$metrics
)
:
self
{
foreach
(
$metrics
as
$metric
)
{
if
(
in_array
(
'admin'
,
$metric
->
getPermissions
(),
true
)
&&
!
$this
->
user
->
isAdmin
()
&&
!
in_array
(
'user'
,
$metric
->
getPermissions
(),
true
)
)
{
continue
;
}
$metric
->
setUser
(
$this
->
user
);
$this
->
metrics
[
$metric
->
getId
()]
=
$metric
;
}
return
$this
;
}
/**
* Return the selected metric
* @return AbstractMetric
*/
public
function
getSelected
()
:
AbstractMetric
{
if
(
!
isset
(
$this
->
metrics
[
$this
->
selectedId
]))
{
$this
->
selectedId
=
key
(
$this
->
metrics
);
}
return
$this
->
metrics
[
$this
->
selectedId
];
}
/**
* Return the set metrics
* @return AbstractMetric[]
*/
public
function
getMetrics
()
:
array
{
return
$this
->
metrics
;
}
/**
* Build the metrics
* @return self
*/
public
function
build
()
:
self
{
// Build all summaries
$this
->
buildSummaries
();
// Build current visualisation
$this
->
getSelected
()
->
buildVisualisation
();
return
$this
;
}
public
function
buildSummaries
()
:
self
{
foreach
(
$this
->
metrics
as
$metric
)
{
$metric
->
setTimespansCollection
(
$this
->
timespansCollection
)
->
setFiltersCollection
(
$this
->
filtersCollection
)
->
buildSummary
();
}
return
$this
;
}
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
$export
=
[];
foreach
(
$this
->
metrics
as
$metric
)
{
$export
[]
=
$metric
->
export
();
}
return
$export
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/PageviewsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Core\Data\ElasticSearch
;
class
PageviewsMetric
extends
AbstractMetric
{
/** @var Elasticsearch\Client */
private
$es
;
/** @var string */
protected
$id
=
'pageviews'
;
/** @var string */
protected
$label
=
'Pageviews'
;
/** @var string */
protected
$description
=
'Pageviews on channel assets. A pageview is visit to a single assets on either desktop or mobile.'
;
/** @var array */
protected
$permissions
=
[
'admin'
,
'user'
];
public
function
__construct
(
$es
=
null
)
{
$this
->
es
=
$es
??
Di
::
_
()
->
get
(
'Database\ElasticSearch'
);
}
/**
* Build the metrics
* @return self
*/
public
function
buildSummary
()
:
self
{
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$filters
=
$this
->
filtersCollection
->
getSelected
();
$comparisonTsMs
=
strtotime
(
"midnight -
{
$timespan
->
getComparisonInterval
()
}
days"
,
$timespan
->
getFromTsMs
()
/
1000
)
*
1000
;
$currentTsMs
=
$timespan
->
getFromTsMs
();
// TODO: Allow this to be changed based on supplied filters
$aggField
=
"views::single"
;
$values
=
[];
foreach
([
'value'
=>
$currentTsMs
,
'comparison'
=>
$comparisonTsMs
]
as
$key
=>
$tsMs
)
{
$must
=
[];
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$tsMs
,
'lte'
=>
strtotime
(
"midnight +
{
$timespan
->
getComparisonInterval
()
}
days"
,
$tsMs
/
1000
)
*
1000
,
],
];
if
(
$userGuid
=
$this
->
getUserGuid
())
{
$must
[]
=
[
'term'
=>
[
'owner_guid'
=>
$userGuid
,
],
];
}
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'sum'
=>
[
'field'
=>
$aggField
,
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$values
[
$key
]
=
$response
[
'aggregations'
][
'1'
][
'value'
];
}
$this
->
summary
=
new
MetricSummary
();
$this
->
summary
->
setValue
(
$values
[
'value'
])
->
setComparisonValue
(
$values
[
'comparison'
])
->
setComparisonInterval
(
$timespan
->
getComparisonInterval
())
->
setComparisonPositivity
(
true
);
return
$this
;
}
/**
* Build a visualisation for the metric
* @return self
*/
public
function
buildVisualisation
()
:
self
{
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$this
->
filtersCollection
->
clear
();
// TODO: make this respect the filters
$field
=
"views::single"
;
$must
=
[];
// Range must be from previous period
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$timespan
->
getFromTsMs
(),
],
];
if
(
$userGuid
=
$this
->
getUserGuid
())
{
$must
[]
=
[
'term'
=>
[
'owner_guid'
=>
$userGuid
,
],
];
}
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'date_histogram'
=>
[
'field'
=>
'@timestamp'
,
'interval'
=>
$timespan
->
getInterval
(),
'min_doc_count'
=>
1
,
],
'aggs'
=>
[
'2'
=>
[
'sum'
=>
[
'field'
=>
$field
,
],
],
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$buckets
=
[];
foreach
(
$response
[
'aggregations'
][
'1'
][
'buckets'
]
as
$bucket
)
{
$date
=
date
(
Visualisations\ChartVisualisation
::
DATE_FORMAT
,
$bucket
[
'key'
]
/
1000
);
$buckets
[]
=
[
'key'
=>
$bucket
[
'key'
],
'date'
=>
date
(
'c'
,
$bucket
[
'key'
]
/
1000
),
'value'
=>
$bucket
[
'2'
][
'value'
]
];
}
$this
->
visualisation
=
(
new
Visualisations\ChartVisualisation
())
->
setXLabel
(
'Date'
)
->
setYLabel
(
'Count'
)
->
setBuckets
(
$buckets
);
return
$this
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/SignupsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Data\Elasticsearch
;
class
SignupsMetric
extends
AbstractMetric
{
/** @var Elasticsearch\Client */
private
$es
;
/** @var string */
protected
$id
=
'signups'
;
/** @var string */
protected
$label
=
'Signups'
;
/** @var string */
protected
$description
=
'New accounts registered'
;
/** @var array */
protected
$permissions
=
[
'admin'
];
public
function
__construct
(
$es
=
null
)
{
$this
->
es
=
$es
??
Di
::
_
()
->
get
(
'Database\ElasticSearch'
);
}
/**
* Build the metrics
* @return self
*/
public
function
buildSummary
()
:
self
{
if
(
$this
->
getUserGuid
())
{
return
$this
;
}
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$comparisonTsMs
=
strtotime
(
"-
{
$timespan
->
getComparisonInterval
()
}
days"
,
$timespan
->
getFromTsMs
()
/
1000
)
*
1000
;
$currentTsMs
=
$timespan
->
getFromTsMs
();
$aggField
=
"signups::total"
;
$values
=
[];
foreach
([
'value'
=>
$currentTsMs
,
'comparison'
=>
$comparisonTsMs
]
as
$key
=>
$tsMs
)
{
$must
=
[];
// Return our global metrics
$must
[][
'term'
]
=
[
'entity_urn'
=>
'urn:metric:global'
,
];
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$tsMs
,
'lte'
=>
strtotime
(
"midnight +
{
$timespan
->
getComparisonInterval
()
}
days"
,
$tsMs
/
1000
)
*
1000
,
],
];
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'sum'
=>
[
'field'
=>
$aggField
,
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$values
[
$key
]
=
$response
[
'aggregations'
][
'1'
][
'value'
];
}
$this
->
summary
=
new
MetricSummary
();
$this
->
summary
->
setValue
(
$values
[
'value'
])
->
setComparisonValue
(
$values
[
'comparison'
])
->
setComparisonInterval
(
$timespan
->
getComparisonInterval
());
return
$this
;
}
/**
* Build a visualisation for the metric
* @return self
*/
public
function
buildVisualisation
()
:
self
{
if
(
$this
->
getUserGuid
())
{
$this
->
visualisation
=
(
new
Visualisations\ChartVisualisation
());
return
$this
;
}
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$xValues
=
[];
$yValues
=
[];
// TODO: make this respect the filters
$field
=
"signups::total"
;
$must
=
[];
// Range must be from previous period
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$timespan
->
getFromTsMs
(),
],
];
// Use our global metrics
$must
[][
'term'
]
=
[
'entity_urn'
=>
'urn:metric:global'
];
// Specify the resolution to avoid duplicates
/*$must[] = [
'term' => [
'resolution' => $timespan->getInterval(),
],
];*/
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'date_histogram'
=>
[
'field'
=>
'@timestamp'
,
'interval'
=>
$timespan
->
getInterval
(),
'min_doc_count'
=>
1
,
],
'aggs'
=>
[
'2'
=>
[
'sum'
=>
[
'field'
=>
$field
,
],
],
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$buckets
=
[];
foreach
(
$response
[
'aggregations'
][
'1'
][
'buckets'
]
as
$bucket
)
{
$date
=
date
(
Visualisations\ChartVisualisation
::
DATE_FORMAT
,
$bucket
[
'key'
]
/
1000
);
$xValues
[]
=
$date
;
$yValues
[]
=
$bucket
[
'2'
][
'value'
];
$buckets
[]
=
[
'key'
=>
$bucket
[
'key'
],
'date'
=>
date
(
'c'
,
$bucket
[
'key'
]
/
1000
),
'value'
=>
$bucket
[
'2'
][
'value'
]
];
}
$this
->
visualisation
=
(
new
Visualisations\ChartVisualisation
())
->
setXValues
(
$xValues
)
->
setYValues
(
$yValues
)
->
setXLabel
(
'Date'
)
->
setYLabel
(
'Count'
)
->
setBuckets
(
$buckets
);
return
$this
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/ViewsMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Session
;
use
Minds\Core\Data\ElasticSearch
;
class
ViewsMetric
extends
AbstractMetric
{
/** @var Elasticsearch\Client */
private
$es
;
/** @var string */
protected
$id
=
'views'
;
/** @var string */
protected
$label
=
'Impressions'
;
/** @var string */
protected
$description
=
'Impressions on channel assets. Impressions include pageviews and feed views.'
;
/** @var array */
protected
$permissions
=
[
'admin'
,
'user'
];
public
function
__construct
(
$es
=
null
)
{
$this
->
es
=
$es
??
Di
::
_
()
->
get
(
'Database\ElasticSearch'
);
}
/**
* Build the metrics
* @return self
*/
public
function
buildSummary
()
:
self
{
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$filters
=
$this
->
filtersCollection
->
getSelected
();
$comparisonTsMs
=
strtotime
(
"midnight -
{
$timespan
->
getComparisonInterval
()
}
days"
,
$timespan
->
getFromTsMs
()
/
1000
)
*
1000
;
$currentTsMs
=
$timespan
->
getFromTsMs
();
// TODO: Allow this to be changed based on supplied filters
$aggField
=
"views::total"
;
if
(
$filters
[
'view_type'
]
??
false
)
{
$aggField
=
"views::"
.
$filters
[
'view_type'
]
->
getSelectedOption
();
}
$values
=
[];
foreach
([
'value'
=>
$currentTsMs
,
'comparison'
=>
$comparisonTsMs
]
as
$key
=>
$tsMs
)
{
$must
=
[];
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$tsMs
,
'lte'
=>
strtotime
(
"midnight +
{
$timespan
->
getComparisonInterval
()
}
days"
,
$tsMs
/
1000
)
*
1000
,
],
];
if
(
$userGuid
=
$this
->
getUserGuid
())
{
$must
[]
=
[
'term'
=>
[
'owner_guid'
=>
$userGuid
,
],
];
}
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'sum'
=>
[
'field'
=>
$aggField
,
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$values
[
$key
]
=
$response
[
'aggregations'
][
'1'
][
'value'
];
}
$this
->
summary
=
new
MetricSummary
();
$this
->
summary
->
setValue
(
$values
[
'value'
])
->
setComparisonValue
(
$values
[
'comparison'
])
->
setComparisonInterval
(
$timespan
->
getComparisonInterval
())
->
setComparisonPositivity
(
true
);
return
$this
;
}
/**
* Build a visualisation for the metric
* @return self
*/
public
function
buildVisualisation
()
:
self
{
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$filters
=
$this
->
filtersCollection
->
getSelected
();
$xValues
=
[];
$yValues
=
[];
// TODO: make this respect the filters
$field
=
"views::total"
;
if
(
$filters
[
'view_type'
]
??
false
)
{
$field
=
"views::"
.
$filters
[
'view_type'
]
->
getSelectedOption
();
}
$must
=
[];
// Range must be from previous period
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$timespan
->
getFromTsMs
(),
],
];
if
(
$userGuid
=
$this
->
getUserGuid
())
{
$must
[]
=
[
'term'
=>
[
'owner_guid'
=>
$userGuid
,
],
];
}
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'date_histogram'
=>
[
'field'
=>
'@timestamp'
,
'interval'
=>
$timespan
->
getInterval
(),
'min_doc_count'
=>
1
,
],
'aggs'
=>
[
'2'
=>
[
'sum'
=>
[
'field'
=>
$field
,
],
],
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$buckets
=
[];
foreach
(
$response
[
'aggregations'
][
'1'
][
'buckets'
]
as
$bucket
)
{
$date
=
date
(
Visualisations\ChartVisualisation
::
DATE_FORMAT
,
$bucket
[
'key'
]
/
1000
);
$buckets
[]
=
[
'key'
=>
$bucket
[
'key'
],
'date'
=>
date
(
'c'
,
$bucket
[
'key'
]
/
1000
),
'value'
=>
$bucket
[
'2'
][
'value'
]
];
}
$this
->
visualisation
=
(
new
Visualisations\ChartVisualisation
())
->
setXLabel
(
'Date'
)
->
setYLabel
(
'Count'
)
->
setBuckets
(
$buckets
);
return
$this
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/ViewsTableMetric.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Data\ElasticSearch
;
use
Minds\Core\Entities\Resolver
;
use
Minds\Common\Urn
;
class
ViewsTableMetric
extends
AbstractMetric
{
/** @var Elasticsearch\Client */
private
$es
;
/** @var Resolver */
private
$entitiesResolver
;
/** @var string */
protected
$id
=
'views_table'
;
/** @var string */
protected
$label
=
'Views breakdown'
;
/** @var string */
protected
$description
=
'Views by post'
;
/** @var array */
protected
$permissions
=
[
'user'
,
'admin'
];
public
function
__construct
(
$es
=
null
)
{
$this
->
es
=
$es
??
Di
::
_
()
->
get
(
'Database\ElasticSearch'
);
$this
->
entitiesResolver
=
$entitiesResolver
??
new
Resolver
();
}
/**
* Build the metrics
* @return self
*/
public
function
buildSummary
()
:
self
{
$this
->
summary
=
new
MetricSummary
();
$this
->
summary
->
setValue
(
0
)
->
setComparisonValue
(
0
)
->
setComparisonInterval
(
null
);
return
$this
;
}
/**
* Build a visualisation for the metric
* @return self
*/
public
function
buildVisualisation
()
:
self
{
$timespan
=
$this
->
timespansCollection
->
getSelected
();
$filters
=
$this
->
filtersCollection
->
getSelected
();
// TODO: make this respect the filters
$field
=
"views::total"
;
if
(
$filters
[
'view_type'
])
{
$field
=
"views::"
.
$filters
[
'view_type'
]
->
getSelectedOption
();
}
$must
=
[];
// Range must be from previous period
$must
[][
'range'
]
=
[
'@timestamp'
=>
[
'gte'
=>
$timespan
->
getFromTsMs
(),
],
];
// Specify the resolution to avoid duplicates
// $must[] = [
// 'term' => [
// 'resolution' => $timespan->getInterval(),
// ],
// ];
if
(
$userGuid
=
$this
->
getUserGuid
())
{
$must
[]
=
[
'term'
=>
[
'owner_guid'
=>
$userGuid
,
],
];
}
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'terms'
=>
[
'field'
=>
'entity_urn'
,
'min_doc_count'
=>
1
,
'order'
=>
[
$field
=>
'desc'
,
],
],
'aggs'
=>
[
'views::total'
=>
[
'sum'
=>
[
'field'
=>
'views::total'
,
],
],
'views::organic'
=>
[
'sum'
=>
[
'field'
=>
'views::organic'
,
],
],
'views::single'
=>
[
'sum'
=>
[
'field'
=>
'views::single'
,
],
],
],
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
$buckets
=
[];
foreach
(
$response
[
'aggregations'
][
'1'
][
'buckets'
]
as
$bucket
)
{
$entity
=
$this
->
entitiesResolver
->
single
(
new
Urn
(
$bucket
[
'key'
]));
$buckets
[]
=
[
'key'
=>
$bucket
[
'key'
],
'values'
=>
[
'entity'
=>
$entity
?
$entity
->
export
()
:
null
,
'views::total'
=>
$bucket
[
'views::total'
][
'value'
],
'views::organic'
=>
$bucket
[
'views::organic'
][
'value'
],
'views::single'
=>
$bucket
[
'views::single'
][
'value'
],
],
];
}
$this
->
visualisation
=
(
new
Visualisations\TableVisualisation
())
->
setBuckets
(
$buckets
)
->
setColumns
([
[
'id'
=>
'entity'
,
'label'
=>
''
,
'order'
=>
0
,
],
[
'id'
=>
'views::total'
,
'label'
=>
'Total Views'
,
'order'
=>
1
,
],
[
'id'
=>
'views::organic'
,
'label'
=>
'Organic'
,
'order'
=>
2
,
],
[
'id'
=>
'views::single'
,
'label'
=>
'Pageviews'
,
'order'
=>
3
,
]
]);
return
$this
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Visualisations/AbstractVisualisation.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
use
Minds\Traits\MagicAttributes
;
abstract
class
AbstractVisualisation
implements
VisualisationInterface
{
use
MagicAttributes
;
/** @var string */
private
$type
;
public
function
export
(
array
$extras
=
[])
:
array
{
return
[
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Visualisations/ChartVisualisation.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
use
Minds\Traits\MagicAttributes
;
class
ChartVisualisation
extends
AbstractVisualisation
{
use
MagicAttributes
;
const
DATE_FORMAT
=
"d-m-Y"
;
/** @var string */
private
$type
=
'chart'
;
/** @var string */
private
$xLabel
=
'Date'
;
/** @var array */
private
$xValues
;
/** @var string */
private
$yLabel
=
'count'
;
/** @var array */
private
$yValues
;
/** @var array */
private
$buckets
=
[];
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
return
[
'type'
=>
$this
->
type
,
'segments'
=>
[
[
'buckets'
=>
(
array
)
$this
->
buckets
,
],
]
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Visualisations/TableVisualisation.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
use
Minds\Traits\MagicAttributes
;
class
TableVisualisation
extends
AbstractVisualisation
{
use
MagicAttributes
;
const
DATE_FORMAT
=
"d-m-Y"
;
/** @var string */
private
$type
=
'table'
;
/** @var array */
private
$buckets
;
/** @var array */
private
$columns
;
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
return
[
'type'
=>
$this
->
type
,
'buckets'
=>
(
array
)
$this
->
buckets
,
'columns'
=>
(
array
)
$this
->
columns
,
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Metrics/Visualisations/VisualisationInterface.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Metrics\Visualisations
;
interface
VisualisationInterface
{
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Timespans/AbstractTimespan.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Timespans
;
use
Minds\Traits\MagicAttributes
;
/**
* @method string getId()
* @method string getLabel()
* @method string getInterval()
* @method int getComparisonInterval()
* @method int getFromTsMs()
*/
abstract
class
AbstractTimespan
{
use
MagicAttributes
;
/** @var string */
protected
$id
;
/** @var string */
protected
$label
;
/** @var string */
protected
$interval
;
/** @var bool */
protected
$selected
=
false
;
/** @var int */
protected
$fromTsMs
;
/** @var string */
protected
$comparisonInterval
=
'day'
;
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
$extras
=
[])
:
array
{
return
[
'id'
=>
(
string
)
$this
->
id
,
'label'
=>
(
string
)
$this
->
label
,
'interval'
=>
(
string
)
$this
->
interval
,
'selected'
=>
(
bool
)
$this
->
selected
,
'comparison_interval'
=>
(
int
)
$this
->
comparisonInterval
,
'from_ts_ms'
=>
(
int
)
$this
->
fromTsMs
,
'from_ts_iso'
=>
date
(
'c'
,
$this
->
fromTsMs
/
1000
),
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Timespans/MtdTimespan.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Timespans
;
class
MtdTimespan
extends
AbstractTimespan
{
/** @var string */
protected
$id
=
'mtd'
;
/** @var string */
protected
$label
=
'month to date'
;
/** @var string */
protected
$interval
=
'day'
;
/** @var int */
protected
$fromTsMs
;
/** @var int */
protected
$comparisonInterval
=
28
;
public
function
__construct
()
{
$this
->
fromTsMs
=
strtotime
(
'midnight first day of this month'
)
*
1000
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Timespans/TimespansCollection.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Timespans
;
use
Minds\Core\Analytics\Dashboards\DashboardCollectionInterface
;
class
TimespansCollection
implements
DashboardCollectionInterface
{
/** @var AbstractTimespan[] */
private
$timespans
=
[];
/** @var string */
private
$selectedId
;
/**
* Set the current timespan we are using
* @param string $selectedId
* @return self
*/
public
function
setSelectedId
(
string
$selectedId
)
:
self
{
$this
->
selectedId
=
$selectedId
;
return
$this
;
}
/**
* Return the selected timespan
* @return AbstractTimespan
*/
public
function
getSelected
()
:
AbstractTimespan
{
return
$this
->
timespans
[
$this
->
selectedId
];
}
/**
* Set the timespans
* @param AbstractTimespan[] $timespans
* @return self
*/
public
function
addTimespans
(
AbstractTimespan
...
$timespans
)
:
self
{
foreach
(
$timespans
as
$timespan
)
{
$this
->
timespans
[
$timespan
->
getId
()]
=
$timespan
;
}
return
$this
;
}
/**
* Return the set timestamps
* @return TimestampAbstract[]
*/
public
function
getTimespans
()
:
array
{
return
$this
->
timespans
;
}
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
$export
=
[];
foreach
(
$this
->
timespans
as
$timespan
)
{
if
(
$timespan
->
getId
()
===
$this
->
selectedId
)
{
$timespan
->
setSelected
(
true
);
}
$export
[]
=
$timespan
->
export
();
}
return
$export
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Timespans/TodayTimespan.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Timespans
;
/**
* @method string getId()
* @method string getLabel()
* @method string getInterval()
*/
class
TodayTimespan
extends
AbstractTimespan
{
/** @var string */
protected
$id
=
'today'
;
/** @var string */
protected
$label
=
'today'
;
/** @var string */
protected
$interval
=
'day'
;
/** @var int */
protected
$fromTsMs
;
/** @var int */
protected
$comparisonInterval
=
1
;
public
function
__construct
()
{
$this
->
fromTsMs
=
strtotime
(
'midnight'
)
*
1000
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Timespans/YtdTimespan.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Timespans
;
class
YtdTimespan
extends
AbstractTimespan
{
/** @var string */
protected
$id
=
'ytd'
;
/** @var string */
protected
$label
=
'year to date'
;
/** @var string */
protected
$interval
=
'month'
;
/** @var int */
protected
$fromTsMs
;
/** @var string */
protected
$comparisonInterval
=
365
;
public
function
__construct
()
{
$this
->
fromTsMs
=
strtotime
(
'midnight first day of January'
)
*
1000
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Timespans/_1yTimespan.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Timespans
;
class
_1yTimespan
extends
AbstractTimespan
{
/** @var string */
protected
$id
=
'1y'
;
/** @var string */
protected
$label
=
'1 year ago'
;
/** @var string */
protected
$interval
=
'month'
;
/** @var int */
protected
$fromTsMs
;
/** @var int */
protected
$comparisonInterval
=
365
;
public
function
__construct
()
{
$this
->
fromTsMs
=
strtotime
(
'midnight 365 days ago'
)
*
1000
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/Timespans/_30dTimespan.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\Dashboards\Timespans
;
class
_30dTimespan
extends
AbstractTimespan
{
/** @var string */
protected
$id
=
'30d'
;
/** @var string */
protected
$label
=
'Last 30 days'
;
/** @var string */
protected
$interval
=
'day'
;
/** @var int */
protected
$fromTsMs
;
/** @var int */
protected
$comparisonInterval
=
28
;
public
function
__construct
()
{
$this
->
fromTsMs
=
strtotime
(
'midnight 30 days ago'
)
*
1000
;
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/TrafficDashboard.php
0 → 100644
View file @
aa593067
<?php
/**
* Traffic Dashboard
*/
namespace
Minds\Core\Analytics\Dashboards
;
use
Minds\Entities\User
;
use
Minds\Traits\MagicAttributes
;
/**
* @method TrafficDashboard setTimespanId(string $timespanId)
* @method TrafficDashboard setFilterIds(array $filtersIds)
* @method TrafficDashboard setUser(User $user)
*/
class
TrafficDashboard
implements
DashboardInterface
{
use
MagicAttributes
;
/** @var string */
private
$timespanId
=
'30d'
;
/** @var string[] */
private
$filterIds
=
[
'platform::browser'
];
/** @var string */
private
$metricId
=
'active_users'
;
/** @var Timespans\TimespansCollection */
private
$timespansCollection
;
/** @var Metrics\MetricsCollection */
private
$metricsCollection
;
/** @var Filters\FiltersCollection */
private
$filtersCollection
;
/** @var User */
private
$user
;
public
function
__construct
(
$timespansCollection
=
null
,
$metricsCollection
=
null
,
$filtersCollection
=
null
)
{
$this
->
timespansCollection
=
$timespansCollection
??
new
Timespans\TimespansCollection
();
$this
->
metricsCollection
=
$metricsCollection
??
new
Metrics\MetricsCollection
();
$this
->
filtersCollection
=
$filtersCollection
??
new
Filters\FiltersCollection
();
}
/**
* Build the dashboard
* @return self
*/
public
function
build
()
:
self
{
$this
->
timespansCollection
->
setSelectedId
(
$this
->
timespanId
)
->
addTimespans
(
new
Timespans\TodayTimespan
(),
new
Timespans\_30dTimespan
(),
new
Timespans\_1yTimespan
(),
new
Timespans\MtdTimespan
(),
new
Timespans\YtdTimespan
()
);
$this
->
filtersCollection
->
setSelectedIds
(
$this
->
filterIds
)
->
setUser
(
$this
->
user
)
->
addFilters
(
// new Filters\PlatformFilter(),
new
Filters\ViewTypeFilter
(),
new
Filters\ChannelFilter
()
);
$this
->
metricsCollection
->
setTimespansCollection
(
$this
->
timespansCollection
)
->
setFiltersCollection
(
$this
->
filtersCollection
)
->
setSelectedId
(
$this
->
metricId
)
->
setUser
(
$this
->
user
)
->
addMetrics
(
new
Metrics\ActiveUsersMetric
(),
new
Metrics\SignupsMetric
(),
new
Metrics\PageviewsMetric
(),
new
Metrics\ViewsMetric
()
)
->
build
();
return
$this
;
}
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
$this
->
build
();
return
[
'category'
=>
'traffic'
,
'label'
=>
'Traffic'
,
'description'
=>
null
,
'timespan'
=>
$this
->
timespansCollection
->
getSelected
()
->
getId
(),
'timespans'
=>
$this
->
timespansCollection
->
export
(),
'metric'
=>
$this
->
metricsCollection
->
getSelected
()
->
getId
(),
'metrics'
=>
$this
->
metricsCollection
->
export
(),
'filter'
=>
$this
->
filtersCollection
->
getSelectedIds
(),
'filters'
=>
$this
->
filtersCollection
->
export
(),
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Dashboards/TrendingDashboard.php
0 → 100644
View file @
aa593067
<?php
/**
* Trending Dashboard
*/
namespace
Minds\Core\Analytics\Dashboards
;
use
Minds\Entities\User
;
use
Minds\Traits\MagicAttributes
;
/**
* @method TrendingDashboard setTimespanId(string $timespanId)
* @method TrendingDashboard setFilterIds(array $filtersIds)
* @method TrendingDashboard setUser(User $user)
*/
class
TrendingDashboard
implements
DashboardInterface
{
use
MagicAttributes
;
/** @var string */
private
$timespanId
=
'30d'
;
/** @var string[] */
private
$filterIds
=
[
'platform::browser'
];
/** @var string */
private
$metricId
=
'views_table'
;
/** @var Timespans\TimespansCollection */
private
$timespansCollection
;
/** @var Metrics\MetricsCollection */
private
$metricsCollection
;
/** @var Filters\FiltersCollection */
private
$filtersCollection
;
/** @var User */
private
$user
;
public
function
__construct
(
$timespansCollection
=
null
,
$metricsCollection
=
null
,
$filtersCollection
=
null
)
{
$this
->
timespansCollection
=
$timespansCollection
??
new
Timespans\TimespansCollection
();
$this
->
metricsCollection
=
$metricsCollection
??
new
Metrics\MetricsCollection
();
$this
->
filtersCollection
=
$filtersCollection
??
new
Filters\FiltersCollection
();
}
/**
* Build the dashboard
* @return self
*/
public
function
build
()
:
self
{
$this
->
timespansCollection
->
setSelectedId
(
$this
->
timespanId
)
->
addTimespans
(
new
Timespans\TodayTimespan
(),
new
Timespans\_30dTimespan
(),
new
Timespans\_1yTimespan
(),
new
Timespans\MtdTimespan
(),
new
Timespans\YtdTimespan
()
);
$this
->
filtersCollection
->
setSelectedIds
(
$this
->
filterIds
)
->
setUser
(
$this
->
user
)
->
addFilters
(
// new Filters\PlatformFilter(),
new
Filters\ViewTypeFilter
(),
new
Filters\ChannelFilter
()
);
$this
->
metricsCollection
->
setTimespansCollection
(
$this
->
timespansCollection
)
->
setFiltersCollection
(
$this
->
filtersCollection
)
->
setSelectedId
(
$this
->
metricId
)
->
setUser
(
$this
->
user
)
->
addMetrics
(
new
Metrics\ViewsTableMetric
()
)
->
build
();
return
$this
;
}
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
array
$extras
=
[])
:
array
{
$this
->
build
();
return
[
'category'
=>
'trending'
,
'label'
=>
'Trending'
,
'description'
=>
null
,
'timespan'
=>
$this
->
timespansCollection
->
getSelected
()
->
getId
(),
'timespans'
=>
$this
->
timespansCollection
->
export
(),
'metric'
=>
$this
->
metricsCollection
->
getSelected
()
->
getId
(),
'metrics'
=>
$this
->
metricsCollection
->
export
(),
'filter'
=>
$this
->
filtersCollection
->
getSelectedIds
(),
'filters'
=>
$this
->
filtersCollection
->
export
(),
];
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/EntityCentric/EntityCentricRecord.php
View file @
aa593067
...
...
@@ -60,4 +60,12 @@ class EntityCentricRecord
$this
->
sums
[
$metric
]
=
$this
->
sums
[
$metric
]
+
$value
;
return
$this
;
}
/**
* @return string
*/
public
function
getUrn
()
:
string
{
return
(
string
)
implode
(
'-'
,
[
$this
->
getEntityUrn
(),
$this
->
getResolution
(),
$this
->
getTimestamp
()
]);
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/EntityCentric/Manager.php
View file @
aa593067
...
...
@@ -13,6 +13,7 @@ class Manager
{
/** @var array */
const
SYNCHRONISERS
=
[
PartnerEarningsSynchroniser
::
class
,
SignupsSynchroniser
::
class
,
ActiveUsersSynchroniser
::
class
,
ViewsSynchroniser
::
class
,
...
...
@@ -21,6 +22,9 @@ class Manager
/** @var Repository */
protected
$repository
;
/** @var Sums */
protected
$sums
;
/** @var int */
private
$from
;
...
...
@@ -28,9 +32,11 @@ class Manager
private
$to
;
public
function
__construct
(
$repository
=
null
$repository
=
null
,
$sums
=
null
)
{
$this
->
repository
=
$repository
?:
new
Repository
();
$this
->
repository
=
$repository
??
new
Repository
();
$this
->
sums
=
$sums
??
new
Sums
();
}
/**
...
...
@@ -81,4 +87,13 @@ class Manager
public
function
getAggregateByQuery
(
array
$query
)
:
array
{
}
/**
* @param array $opts
* @retun iterable
*/
public
function
getListAggregatedByOwner
(
array
$opts
=
[])
:
iterable
{
return
$this
->
sums
->
getByOwner
(
$opts
);
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/EntityCentric/PartnerEarningsSynchroniser.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Analytics\EntityCentric
;
use
Minds\Core\Monetization\Partners\Manager
as
PartnersManager
;
use
DateTime
;
use
Exception
;
class
PartnerEarningsSynchroniser
{
/** @var PartnersManager */
private
$partnersManager
;
public
function
__construct
(
$partnersManager
=
null
)
{
$this
->
partnersManager
=
$partnersManager
??
new
PartnersManager
;
}
/**
* @param int $from
* @return self
*/
public
function
setFrom
(
$from
)
:
self
{
$this
->
from
=
$from
;
return
$this
;
}
/**
* Convert to records
* @return iterable
*/
public
function
toRecords
()
:
iterable
{
$opts
=
[];
$opts
[
'from'
]
=
$this
->
from
;
$records
=
[];
$i
=
0
;
while
(
true
)
{
$result
=
$this
->
partnersManager
->
getList
(
$opts
);
$opts
[
'offset'
]
=
$result
->
getPagingToken
();
foreach
(
$result
as
$deposit
)
{
$urn
=
"urn:user:
{
$deposit
->
getUserGuid
()
}
"
;
$record
=
new
EntityCentricRecord
();
$record
->
setEntityUrn
(
$urn
)
->
setOwnerGuid
(
$deposit
->
getUserGuid
())
->
setTimestamp
(
$deposit
->
getTimestamp
())
// TODO: confirm if this should be rounded to midnight
->
setResolution
(
'day'
);
// In order to increment sums, replace with what has already been seen
if
(
isset
(
$records
[
$record
->
getUrn
()]))
{
$record
=
$records
[
$record
->
getUrn
()];
}
$record
->
incrementSum
(
'usd_earnings::total'
,
$deposit
->
getAmountCents
());
$record
->
incrementSum
(
"usd_earnings::
{
$deposit
->
getItem
()
}
"
,
$deposit
->
getAmountCents
());
$records
[
$record
->
getUrn
()]
=
$record
;
}
if
(
$result
->
isLastPage
())
{
break
;
}
}
foreach
(
$records
as
$record
)
{
var_dump
(
$record
);
yield
$record
;
}
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/EntityCentric/Sums.php
0 → 100644
View file @
aa593067
<?php
/**
* EntityCentric Sums
* @author Mark
*/
namespace
Minds\Core\Analytics\EntityCentric
;
use
DateTime
;
use
DateTimeZone
;
use
Exception
;
use
Minds\Common\Repository\Response
;
use
Minds\Core\Data\ElasticSearch\Client
as
ElasticClient
;
use
Minds\Core\Data\ElasticSearch
;
use
Minds\Core\Di\Di
;
class
Sums
{
/** @var ElasticClient */
protected
$es
;
/**
* Repository constructor.
* @param ElasticClient $es
*/
public
function
__construct
(
$es
=
null
)
{
$this
->
es
=
$es
?:
Di
::
_
()
->
get
(
'Database\ElasticSearch'
);
}
public
function
getByOwner
(
array
$opts
=
[])
:
iterable
{
$opts
=
array_merge
([
'fields'
=>
[],
'from'
=>
time
(),
],
$opts
);
$must
=
[];
$must
[]
=
[
'range'
=>
[
'@timestamp'
=>
[
'gte'
=>
$opts
[
'from'
]
*
1000
,
'lt'
=>
strtotime
(
'+1 day'
,
$opts
[
'from'
])
*
1000
,
],
],
];
$termsAgg
=
[];
foreach
(
$opts
[
'fields'
]
as
$field
)
{
$termsAgg
[
$field
]
=
[
'sum'
=>
[
'field'
=>
$field
,
],
];
$must
[]
=
[
'exists'
=>
[
'field'
=>
$field
,
],
];
}
$partition
=
0
;
$partitions
=
100
;
$partitionSize
=
5000
;
// Allows for 500,000 users
while
(
++
$partition
<
$partitions
)
{
// Do the query
$query
=
[
'index'
=>
'minds-entitycentric-*'
,
'size'
=>
0
,
'body'
=>
[
'query'
=>
[
'bool'
=>
[
'must'
=>
$must
,
],
],
'aggs'
=>
[
'1'
=>
[
'terms'
=>
[
'field'
=>
'owner_guid'
,
'min_doc_count'
=>
1
,
'size'
=>
$partitionSize
,
'include'
=>
[
'partition'
=>
$partition
,
'num_partitions'
=>
$partitions
,
],
],
'aggs'
=>
$termsAgg
,
],
],
],
];
// Query elasticsearch
$prepared
=
new
ElasticSearch\Prepared\Search
();
$prepared
->
query
(
$query
);
$response
=
$this
->
es
->
request
(
$prepared
);
foreach
(
$response
[
'aggregations'
][
'1'
][
'buckets'
]
as
$bucket
)
{
yield
$bucket
;
}
}
}
}
This diff is collapsed.
Click to expand it.
Core/Analytics/Metrics/Retention.php
View file @
aa593067
...
...
@@ -49,7 +49,7 @@ class Retention implements AnalyticsMetric
$startTs
=
$timestamps
[
$x
+
1
];
$signups
=
[];
$offset
=
""
;
echo
"
\n
Gathering signups
\n
"
;
//
echo "\n Gathering signups \n";
while
(
true
)
{
$data
=
$this
->
db
->
getRow
(
"analytics:signup:day:
$startTs
"
,
[
'limit'
=>
200
,
'offset'
=>
$offset
]);
if
(
count
(
$data
)
<=
1
)
{
...
...
@@ -61,13 +61,13 @@ class Retention implements AnalyticsMetric
$offset
=
$k
;
}
}
echo
" (done)"
;
//
echo " (done)";
//now get active users from each interval after this date
$endTs
=
$timestamps
[
$x
-
$x
+
1
];
//echo "[$x]:: actives: " . date('d-m-Y', $endTs) . " signups: " . date('d-m-Y', $startTs) . "\n";
$offset
=
""
;
echo
"
\n
Gathering actives
\n
"
;
//
echo "\n Gathering actives \n";
foreach
(
$signups
as
$signup
=>
$ts
)
{
if
(
$this
->
wasActive
(
$signup
,
$now
))
{
$this
->
db
->
insert
(
"
{
$this
->
namespace
}
:
$x
:
$now
"
,
[
$signup
=>
time
()]);
...
...
@@ -76,7 +76,7 @@ class Retention implements AnalyticsMetric
echo
"
\r
$x
:
$signup
(not active)
$offset
"
;
}
}
echo
"(done)"
;
//
echo "(done)";
}
return
true
;
...
...
This diff is collapsed.
Click to expand it.
Core/Monetization/Partners/EarningsDeposit.php
0 → 100644
View file @
aa593067
<?php
/**
* EarningsDeposit
*/
namespace
Minds\Core\Monetization\Partners
;
use
Minds\Traits\MagicAttributes
;
class
EarningsDeposit
{
use
MagicAttributes
;
/** @var string */
private
$userGuid
;
/** @var int */
private
$timestamp
;
/** @var string */
private
$item
;
/** @var int */
private
$amountCents
;
/** @var int */
private
$amountTokens
;
/**
* Export
* @param array $extras
* @return array
*/
public
function
export
(
$extras
=
[])
:
array
{
return
[
'user_guid'
=>
$this
->
userGuid
,
'timestamp'
=>
$this
->
timestamp
,
'item'
=>
$this
->
item
,
'amount_cents'
=>
(
int
)
$this
->
amountCents
,
'amount_usd'
=>
(
int
)
$this
->
amountCents
/
100
,
'amount_tokens'
=>
(
string
)
$this
->
amountTokens
,
];
}
}
This diff is collapsed.
Click to expand it.
Core/Monetization/Partners/Manager.php
0 → 100644
View file @
aa593067
<?php
/**
* Manager
*/
namespace
Minds\Core\Monetization\Partners
;
use
Minds\Core\Analytics\EntityCentric\Manager
as
EntityCentricManager
;
use
Minds\Core\EntitiesBuilder
;
use
Minds\Common\Repository\Response
;
use
Minds\Core\Di\Di
;
use
DateTime
;
class
Manager
{
const
VIEWS_RPM_CENTS
=
100
;
// $1 USD
/** @var Repository */
private
$repository
;
/** @var EntityCentricManager */
private
$entityCentricManager
;
/** @var EntitiesBuilder */
private
$entitiesBuilder
;
public
function
__construct
(
$repository
=
null
,
$entityCentricManager
=
null
,
$entitiesBuilder
=
null
)
{
$this
->
repository
=
$repository
??
new
Repository
();
$this
->
entityCentricManager
=
$entityCentricManager
??
new
EntityCentricManager
();
$this
->
entitiesBuilder
=
$entitiesBuilder
??
Di
::
_
()
->
get
(
'EntitiesBuilder'
);
}
/**
* Return a list of earning deposits
* @param array $opts
* @return Response
*/
public
function
getList
(
array
$opts
=
[])
:
Response
{
return
$this
->
repository
->
getList
(
$opts
);
}
/**
* Add an earnings deposit
* @param EarningsDeposit $deposit
* @return bool
*/
public
function
add
(
EarningsDeposit
$deposit
)
:
bool
{
$this
->
repository
->
add
(
$deposit
);
return
true
;
}
/**
* @param array $opts
* @return iterable
*/
public
function
issueDeposits
(
array
$opts
=
[])
:
iterable
{
$opts
=
array_merge
([
'from'
=>
strtotime
(
'midnight'
),
],
$opts
);
$users
=
[];
foreach
(
$this
->
entityCentricManager
->
getListAggregatedByOwner
([
'fields'
=>
[
'views::single'
],
'from'
=>
$opts
[
'from'
],
])
as
$ownerSum
)
{
$views
=
$ownerSum
[
'views::single'
][
'value'
];
$amountCents
=
(
$views
/
1000
)
*
static
::
VIEWS_RPM_CENTS
;
if
(
$amountCents
<
1
)
{
// Has to be at least 1 cent / $0.01
continue
;
}
// Is this user in the pro program?
$owner
=
$this
->
entitiesBuilder
->
single
(
$ownerSum
[
'key'
]);
if
(
!
$owner
||
!
$owner
->
isPro
())
{
continue
;
}
$deposit
=
new
EarningsDeposit
();
$deposit
->
setTimestamp
(
$opts
[
'from'
])
->
setUserGuid
(
$ownerSum
[
'key'
])
->
setAmountCents
(
$amountCents
)
->
setItem
(
"views"
);
$this
->
repository
->
add
(
$deposit
);
yield
$deposit
;
}
}
}
This diff is collapsed.
Click to expand it.
Core/Monetization/Partners/Repository.php
0 → 100644
View file @
aa593067
<?php
namespace
Minds\Core\Monetization\Partners
;
use
Minds\Core\Data\Cassandra\Client
;
use
Minds\Core\Data\Cassandra\Prepared\Custom
as
Prepared
;
use
Minds\Common\Repository\Response
;
use
Minds\Core\Di\Di
;
use
Cassandra\Bigint
;
use
Cassandra\Timestamp
;
class
Repository
{
/** @var Client */
private
$db
;
public
function
__construct
(
$db
=
null
)
{
$this
->
db
=
$db
??
Di
::
_
()
->
get
(
'Database\Cassandra\Cql'
);
}
/**
* @param array $opts
* @return Response
*/
public
function
getList
(
array
$opts
=
[])
:
Response
{
$opts
=
array_merge
([
'from'
=>
null
,
'to'
=>
null
,
'user_guid'
=>
null
,
'allow_filtering'
=>
false
,
],
$opts
);
$statement
=
"SELECT * FROM partner_earnings_ledger"
;
$values
=
[];
$where
=
[];
if
(
$opts
[
'user_guid'
])
{
$where
[]
=
"user_guid = ?"
;
$values
[]
=
new
Bigint
(
$opts
[
'user_guid'
]);
}
if
(
$opts
[
'from'
])
{
$where
[]
=
"timestamp >= ?"
;
$values
[]
=
new
Timestamp
(
$opts
[
'from'
]);
if
(
!
$opts
[
'user_guid'
])
{
// This is a temporary work around (MH)
$opts
[
'allow_filtering'
]
=
true
;
}
}
if
(
$opts
[
'to'
])
{
$where
[]
=
"timestamp < ?"
;
$values
[]
=
new
Timestamp
(
$opts
[
'to'
]);
}
$statement
.=
" WHERE "
.
implode
(
' '
,
$where
);
if
(
$opts
[
'allow_filtering'
])
{
$statement
.=
" ALLOW FILTERING"
;
}
$prepared
=
new
Prepared
();
$prepared
->
query
(
$statement
,
$values
);
$result
=
$this
->
db
->
request
(
$prepared
);
if
(
!
$result
||
!
$result
[
0
])
{
return
(
new
Response
())
->
setLastPage
(
true
);
}
$response
=
new
Response
();
foreach
(
$result
as
$row
)
{
$deposit
=
new
EarningsDeposit
();
$deposit
->
setTimestamp
(
$row
[
'timestamp'
]
->
time
())
->
setItem
(
$row
[
'item'
])
->
setUserGuid
((
string
)
$row
[
'user_guid'
])
->
setAmountCents
(
$row
[
'amount_cents'
])
->
setAmountTokens
(
$row
[
'amount_tokens'
]
?
$row
[
'amount_tokens'
]
->
value
()
:
0
);
$response
[]
=
$deposit
;
}
$response
->
setLastPage
(
$result
->
isLastPage
());
return
$response
;
}
/**
* @param string $urn
* @return EarningsDeposit
*/
public
function
get
(
$urn
)
:
EarningsDeposit
{
// TODO
}
/**
* @param EarningsDeposit $deposit
* @return bool
*/
public
function
add
(
EarningsDeposit
$deposit
)
:
bool
{
$prepared
=
new
Prepared
();
$prepared
->
query
(
"INSERT INTO partner_earnings_ledger (user_guid, timestamp, item, amount_cents, amount_tokens) VALUES (?,?,?,?,?)"
,
[
new
Bigint
(
$deposit
->
getUserGuid
()),
new
Timestamp
(
$deposit
->
getTimestamp
()),
$deposit
->
getItem
(),
$deposit
->
getAmountCents
()
?
(
int
)
$deposit
->
getAmountCents
()
:
null
,
$deposit
->
getAmountTokens
()
?
new
Bigint
(
$deposit
->
getAmountTokens
())
:
null
,
]);
return
(
bool
)
$this
->
db
->
request
(
$prepared
);
}
/**
* @param EarningsDeposit $deposit
* @param array $fields
* @return bool
*/
public
function
update
(
EarningsDeposit
$deposit
,
$fields
=
[])
:
bool
{
}
/**
* @param EarningsDeposit $deposit
* @return bool
*/
public
function
delete
(
EarningsDeposit
$deposit
)
:
bool
{
}
}
This diff is collapsed.
Click to expand it.
Spec/Core/Analytics/Dashboards/Filters/FiltersCollectionSpec.php
0 → 100644
View file @
aa593067
<?php
namespace
Spec\Minds\Core\Analytics\Dashboards\Filters
;
use
Minds\Entities\User
;
use
Minds\Core\Analytics\Dashboards\Filters\FiltersCollection
;
use
Minds\Core\Analytics\Dashboards\Filters\ViewTypeFilter
;
use
PhpSpec\ObjectBehavior
;
use
Prophecy\Argument
;
class
FiltersCollectionSpec
extends
ObjectBehavior
{
public
function
it_is_initializable
()
{
$this
->
shouldHaveType
(
FiltersCollection
::
class
);
}
public
function
it_should_add_filters_to_collection
()
{
$this
->
setUser
(
new
User
());
$this
->
addFilters
(
new
ViewTypeFilter
);
$filters
=
$this
->
getFilters
();
$filters
[
'view_type'
]
->
getId
()
->
shouldBe
(
'view_type'
);
}
public
function
it_should_export_filters
()
{
$this
->
setUser
(
new
User
());
$this
->
addFilters
(
new
ViewTypeFilter
);
$export
=
$this
->
export
();
$export
[
0
][
'id'
]
->
shouldBe
(
'view_type'
);
$export
[
0
][
'options'
]
->
shouldHaveCount
(
4
);
}
}
This diff is collapsed.
Click to expand it.
Spec/Core/Analytics/Dashboards/Metrics/ActiveUsersMetricSpec.php
0 → 100644
View file @
aa593067
<?php
namespace
Spec\Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Analytics\Dashboards\Metrics\ActiveUsersMetric
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Analytics\Dashboards\Timespans\AbstractTimespan
;
use
Minds\Core\Analytics\Dashboards\Filters\FiltersCollection
;
use
Minds\Core\Analytics\Dashboards\Filters\AbstractFilter
;
use
Minds\Core\Data\Elasticsearch\Client
;
use
Minds\Entities\User
;
use
PhpSpec\ObjectBehavior
;
use
Prophecy\Argument
;
class
ActiveUsersMetricSpec
extends
ObjectBehavior
{
private
$es
;
private
$timespansCollection
;
private
$filtersCollection
;
public
function
let
(
Client
$es
,
TimespansCollection
$timespansCollection
,
FiltersCollection
$filtersCollection
)
{
$this
->
beConstructedWith
(
$es
);
$this
->
es
=
$es
;
$this
->
setTimespansCollection
(
$timespansCollection
);
$this
->
setFiltersCollection
(
$filtersCollection
);
$this
->
timespansCollection
=
$timespansCollection
;
$this
->
filtersCollection
=
$filtersCollection
;
}
public
function
it_is_initializable
()
{
$this
->
shouldHaveType
(
ActiveUsersMetric
::
class
);
}
public
function
it_should_build_summary
(
AbstractTimespan
$mockTimespan
,
AbstractFilter
$mockFilter
)
{
$this
->
setUser
(
new
User
());
$this
->
timespansCollection
->
getSelected
()
->
willReturn
(
$mockTimespan
);
$this
->
filtersCollection
->
getSelected
()
->
willReturn
([
$mockFilter
]);
$this
->
es
->
request
(
Argument
::
any
())
->
willReturn
(
[
'aggregations'
=>
[
'1'
=>
[
'value'
=>
128
,
],
]
],
[
'aggregations'
=>
[
'1'
=>
[
'value'
=>
256
,
],
]
]
);
$this
->
buildSummary
();
$this
->
getSummary
()
->
getValue
()
->
shouldBe
(
128
);
$this
->
getSummary
()
->
getComparisonValue
()
->
shouldBe
(
256
);
}
public
function
it_should_build_visualisation
(
AbstractTimespan
$mockTimespan
,
AbstractFilter
$mockFilter
)
{
$this
->
setUser
(
new
User
());
$this
->
timespansCollection
->
getSelected
()
->
willReturn
(
$mockTimespan
);
$this
->
filtersCollection
->
getSelected
()
->
willReturn
([
$mockFilter
]);
$this
->
es
->
request
(
Argument
::
any
())
->
willReturn
([
'aggregations'
=>
[
'1'
=>
[
'buckets'
=>
[
[
'key'
=>
strtotime
(
'Midnight 1st December 2018'
)
*
1000
,
'2'
=>
[
'value'
=>
256
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st January 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
128
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st February 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
4
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st March 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
685
,
],
],
],
],
]
]);
$this
->
buildVisualisation
();
$xValues
=
$this
->
getVisualisation
()
->
getXValues
();
$xValues
[
0
]
->
shouldBe
(
'01-12-2018'
);
$xValues
[
1
]
->
shouldBe
(
'01-01-2019'
);
$xValues
[
2
]
->
shouldBe
(
'01-02-2019'
);
$xValues
[
3
]
->
shouldBe
(
'01-03-2019'
);
$yValues
=
$this
->
getVisualisation
()
->
getYValues
();
$yValues
[
0
]
->
shouldBe
(
256
);
$yValues
[
1
]
->
shouldBe
(
128
);
$yValues
[
2
]
->
shouldBe
(
4
);
$yValues
[
3
]
->
shouldBe
(
685
);
}
}
This diff is collapsed.
Click to expand it.
Spec/Core/Analytics/Dashboards/Metrics/MetricsCollectionSpec.php
0 → 100644
View file @
aa593067
<?php
namespace
Spec\Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Analytics\Dashboards\Metrics\MetricsCollection
;
use
Minds\Core\Analytics\Dashboards\Metrics\ActiveUsersMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\SignupsMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\ViewsMetric
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Analytics\Dashboards\Filters\FiltersCollection
;
use
Minds\Core\Analytics\Dashboards\Timespans\TodayTimespan
;
use
Minds\Entities\User
;
use
PhpSpec\ObjectBehavior
;
use
Prophecy\Argument
;
class
MetricsCollectionSpec
extends
ObjectBehavior
{
private
$timespansCollection
;
private
$todayTimespan
;
public
function
let
(
TimespansCollection
$timespansCollection
,
TodayTimespan
$todayTimespan
)
{
$this
->
timespansCollection
=
$timespansCollection
;
$this
->
todayTimespan
=
$todayTimespan
;
$this
->
setTimespansCollection
(
$timespansCollection
);
$this
->
setFiltersCollection
(
new
FiltersCollection
());
$this
->
timespansCollection
->
setSelectedId
(
'today'
);
}
public
function
it_is_initializable
()
{
$this
->
shouldHaveType
(
MetricsCollection
::
class
);
}
public
function
it_should_add_metrics_to_collection
()
{
$this
->
setUser
(
new
User
());
$this
->
addMetrics
(
// new ActiveUsersMetric,
// new SignupsMetric,
new
ViewsMetric
);
$metrics
=
$this
->
getMetrics
();
$metrics
[
'views'
]
->
getId
()
->
shouldBe
(
'views'
);
}
public
function
it_should_export_metrics
()
{
$this
->
setUser
(
new
User
());
$this
->
addMetrics
(
new
ActiveUsersMetric
,
// Not admin so won't export
new
SignupsMetric
,
// Not admin so wont export
new
ViewsMetric
);
$export
=
$this
->
export
();
$export
[
0
][
'id'
]
->
shouldBe
(
'views'
);
}
public
function
it_should_build_metrics
(
ActiveUsersMetric
$activeUsersMetric
)
{
$this
->
setUser
(
new
User
());
$activeUsersMetric
->
getId
()
->
shouldBeCalled
()
->
willReturn
(
'active_users'
);
$activeUsersMetric
->
setTimespansCollection
(
$this
->
timespansCollection
)
->
shouldBeCalled
()
->
willReturn
(
$activeUsersMetric
);
$activeUsersMetric
->
setFiltersCollection
(
Argument
::
type
(
FiltersCollection
::
class
))
->
shouldBeCalled
()
->
willReturn
(
$activeUsersMetric
);
$activeUsersMetric
->
buildSummary
()
->
shouldBeCalled
();
$activeUsersMetric
->
getPermissions
()
->
willReturn
([
'user '
]);
$activeUsersMetric
->
setUser
(
Argument
::
any
())
->
wilLReturn
(
$activeUsersMetric
);
$this
->
addMetrics
(
$activeUsersMetric
);
$this
->
buildSummaries
();
}
}
This diff is collapsed.
Click to expand it.
Spec/Core/Analytics/Dashboards/Metrics/SignupsMetricSpec.php
0 → 100644
View file @
aa593067
<?php
namespace
Spec\Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Analytics\Dashboards\Metrics\SignupsMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\ActiveUsersMetric
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Analytics\Dashboards\Timespans\AbstractTimespan
;
use
Minds\Core\Analytics\Dashboards\Filters\FiltersCollection
;
use
Minds\Core\Analytics\Dashboards\Filters\AbstractFilter
;
use
Minds\Core\Data\Elasticsearch\Client
;
use
Minds\Entities\User
;
use
PhpSpec\ObjectBehavior
;
use
Prophecy\Argument
;
class
SignupsMetricSpec
extends
ObjectBehavior
{
private
$es
;
private
$timespansCollection
;
private
$filtersCollection
;
public
function
let
(
Client
$es
,
TimespansCollection
$timespansCollection
,
FiltersCollection
$filtersCollection
)
{
$this
->
beConstructedWith
(
$es
);
$this
->
es
=
$es
;
$this
->
setTimespansCollection
(
$timespansCollection
);
$this
->
setFiltersCollection
(
$filtersCollection
);
$this
->
timespansCollection
=
$timespansCollection
;
$this
->
filtersCollection
=
$filtersCollection
;
}
public
function
it_is_initializable
()
{
$this
->
shouldHaveType
(
SignupsMetric
::
class
);
}
public
function
it_should_build_summary
(
AbstractTimespan
$mockTimespan
,
AbstractFilter
$mockFilter
)
{
$this
->
setUser
(
new
User
());
$this
->
timespansCollection
->
getSelected
()
->
willReturn
(
$mockTimespan
);
$this
->
filtersCollection
->
getSelected
()
->
willReturn
([
$mockFilter
]);
$this
->
es
->
request
(
Argument
::
any
())
->
willReturn
(
[
'aggregations'
=>
[
'1'
=>
[
'value'
=>
128
,
],
],
],
[
'aggregations'
=>
[
'1'
=>
[
'value'
=>
256
,
],
],
]);
$this
->
buildSummary
();
$this
->
getSummary
()
->
getValue
()
->
shouldBe
(
128
);
$this
->
getSummary
()
->
getComparisonValue
()
->
shouldBe
(
256
);
}
public
function
it_should_build_visualisation
(
AbstractTimespan
$mockTimespan
,
AbstractFilter
$mockFilter
)
{
$this
->
setUser
(
new
User
());
$this
->
timespansCollection
->
getSelected
()
->
willReturn
(
$mockTimespan
);
$this
->
filtersCollection
->
getSelected
()
->
willReturn
([
$mockFilter
]);
$this
->
es
->
request
(
Argument
::
any
())
->
willReturn
([
'aggregations'
=>
[
'1'
=>
[
'buckets'
=>
[
[
'key'
=>
strtotime
(
'Midnight 1st December 2018'
)
*
1000
,
'2'
=>
[
'value'
=>
256
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st January 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
128
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st February 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
4
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st March 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
685
,
],
],
],
],
]
]);
$this
->
buildVisualisation
();
$xValues
=
$this
->
getVisualisation
()
->
getXValues
();
$xValues
[
0
]
->
shouldBe
(
'01-12-2018'
);
$xValues
[
1
]
->
shouldBe
(
'01-01-2019'
);
$xValues
[
2
]
->
shouldBe
(
'01-02-2019'
);
$xValues
[
3
]
->
shouldBe
(
'01-03-2019'
);
$yValues
=
$this
->
getVisualisation
()
->
getYValues
();
$yValues
[
0
]
->
shouldBe
(
256
);
$yValues
[
1
]
->
shouldBe
(
128
);
$yValues
[
2
]
->
shouldBe
(
4
);
$yValues
[
3
]
->
shouldBe
(
685
);
}
}
This diff is collapsed.
Click to expand it.
Spec/Core/Analytics/Dashboards/Metrics/ViewsMetricSpec.php
0 → 100644
View file @
aa593067
<?php
namespace
Spec\Minds\Core\Analytics\Dashboards\Metrics
;
use
Minds\Core\Analytics\Dashboards\Metrics\ViewsMetric
;
use
Minds\Core\Analytics\Dashboards\Metrics\ActiveUsersMetric
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Analytics\Dashboards\Timespans\AbstractTimespan
;
use
Minds\Core\Analytics\Dashboards\Filters\FiltersCollection
;
use
Minds\Core\Analytics\Dashboards\Filters\AbstractFilter
;
use
Minds\Core\Data\Elasticsearch\Client
;
use
Minds\Entities\User
;
use
PhpSpec\ObjectBehavior
;
use
Prophecy\Argument
;
class
ViewsMetricSpec
extends
ObjectBehavior
{
private
$es
;
private
$timespansCollection
;
private
$filtersCollection
;
public
function
let
(
Client
$es
,
TimespansCollection
$timespansCollection
,
FiltersCollection
$filtersCollection
)
{
$this
->
beConstructedWith
(
$es
);
$this
->
es
=
$es
;
$this
->
setTimespansCollection
(
$timespansCollection
);
$this
->
setFiltersCollection
(
$filtersCollection
);
$this
->
timespansCollection
=
$timespansCollection
;
$this
->
filtersCollection
=
$filtersCollection
;
}
public
function
it_is_initializable
()
{
$this
->
shouldHaveType
(
ViewsMetric
::
class
);
}
public
function
it_should_build_summary
(
AbstractTimespan
$mockTimespan
,
AbstractFilter
$mockFilter
)
{
$this
->
setUser
(
new
User
());
$this
->
timespansCollection
->
getSelected
()
->
willReturn
(
$mockTimespan
);
$this
->
filtersCollection
->
getSelected
()
->
willReturn
([
$mockFilter
]);
$this
->
es
->
request
(
Argument
::
any
())
->
willReturn
(
[
'aggregations'
=>
[
'1'
=>
[
'value'
=>
128
,
]
]
],
[
'aggregations'
=>
[
'1'
=>
[
'value'
=>
256
,
]
]
]);
$this
->
buildSummary
();
$this
->
getSummary
()
->
getValue
()
->
shouldBe
(
128
);
$this
->
getSummary
()
->
getComparisonValue
()
->
shouldBe
(
256
);
}
public
function
it_should_build_visualisation
(
AbstractTimespan
$mockTimespan
,
AbstractFilter
$mockFilter
)
{
$this
->
setUser
(
new
User
());
$this
->
timespansCollection
->
getSelected
()
->
willReturn
(
$mockTimespan
);
$this
->
filtersCollection
->
getSelected
()
->
willReturn
([
$mockFilter
]);
$this
->
es
->
request
(
Argument
::
any
())
->
willReturn
([
'aggregations'
=>
[
'1'
=>
[
'buckets'
=>
[
[
'key'
=>
strtotime
(
'Midnight 1st December 2018'
)
*
1000
,
'2'
=>
[
'value'
=>
256
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st January 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
128
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st February 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
4
,
],
],
[
'key'
=>
strtotime
(
'Midnight 1st March 2019'
)
*
1000
,
'2'
=>
[
'value'
=>
685
,
],
],
],
],
]
]);
$this
->
buildVisualisation
();
$buckets
=
$this
->
getVisualisation
()
->
getBuckets
();
// $xValues[0]->shouldBe('01-12-2018');
// $xValues[1]->shouldBe('01-01-2019');
// $xValues[2]->shouldBe('01-02-2019');
// $xValues[3]->shouldBe('01-03-2019');
}
}
This diff is collapsed.
Click to expand it.
Spec/Core/Analytics/Dashboards/Timespans/TimespansCollectionSpec.php
0 → 100644
View file @
aa593067
<?php
namespace
Spec\Minds\Core\Analytics\Dashboards\Timespans
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Analytics\Dashboards\Timespans\TodayTimespan
;
use
Minds\Core\Analytics\Dashboards\Timespans\MtdTimespan
;
use
Minds\Core\Analytics\Dashboards\Timespans\YtdTimespan
;
use
PhpSpec\ObjectBehavior
;
use
Prophecy\Argument
;
class
TimespansCollectionSpec
extends
ObjectBehavior
{
public
function
it_is_initializable
()
{
$this
->
shouldHaveType
(
TimespansCollection
::
class
);
}
public
function
it_should_add_timespans_to_collection
()
{
$this
->
addTimespans
(
new
TodayTimespan
(),
new
MtdTimespan
(),
new
YtdTimespan
()
);
$this
->
getTimespans
()[
'today'
]
->
getId
()
->
shouldBe
(
'today'
);
$this
->
getTimespans
()[
'mtd'
]
->
getId
()
->
shouldBe
(
'mtd'
);
$this
->
getTimespans
()[
'ytd'
]
->
getId
()
->
shouldBe
(
'ytd'
);
}
public
function
it_should_export_timestamps
()
{
$this
->
addTimespans
(
new
TodayTimespan
(),
new
MtdTimespan
(),
new
YtdTimespan
()
);
$exported
=
$this
->
export
();
$exported
[
0
][
'id'
]
->
shouldBe
(
'today'
);
$exported
[
0
][
'from_ts_ms'
]
->
shouldBe
(
strtotime
(
'midnight'
)
*
1000
);
$exported
[
1
][
'id'
]
->
shouldBe
(
'mtd'
);
$exported
[
1
][
'from_ts_ms'
]
->
shouldBe
(
strtotime
(
'midnight first day of this month'
)
*
1000
);
$exported
[
2
][
'id'
]
->
shouldBe
(
'ytd'
);
$exported
[
2
][
'from_ts_ms'
]
->
shouldBe
(
strtotime
(
'midnight first day of January'
)
*
1000
);
$exported
[
2
][
'interval'
]
->
shouldBe
(
'month'
);
}
}
This diff is collapsed.
Click to expand it.
Spec/Core/Analytics/Dashboards/TrafficDashboardSpec.php
0 → 100644
View file @
aa593067
<?php
namespace
Spec\Minds\Core\Analytics\Dashboards
;
use
Minds\Core\Analytics\Dashboards\TrafficDashboard
;
use
Minds\Core\Analytics\Dashboards\Timespans\TimespansCollection
;
use
Minds\Core\Analytics\Dashboards\Metrics\MetricsCollection
;
use
Minds\Core\Analytics\Dashboards\Metrics\AbstractMetric
;
use
Minds\Core\Analytics\Dashboards\Filters\FiltersCollection
;
use
Minds\Entities\User
;
use
PhpSpec\ObjectBehavior
;
use
Prophecy\Argument
;
class
TrafficDashboardSpec
extends
ObjectBehavior
{
private
$timespansCollection
;
private
$metricsCollection
;
private
$filtersCollection
;
public
function
let
(
TimespansCollection
$timespansCollection
,
MetricsCollection
$metricsCollection
,
FiltersCollection
$filtersCollection
)
{
$this
->
beConstructedWith
(
null
,
$metricsCollection
,
null
);
$this
->
timespansCollection
=
$timespansCollection
;
$this
->
metricsCollection
=
$metricsCollection
;
$this
->
filtersCollection
=
$filtersCollection
;
}
public
function
it_is_initializable
()
{
$this
->
shouldHaveType
(
TrafficDashboard
::
class
);
}
public
function
it_should_build_dashboard
(
AbstractMetric
$mockMetric
)
{
$user
=
new
User
();
$this
->
setUser
(
$user
);
$this
->
setTimespanId
(
'today'
);
$this
->
setFilterIds
([
'platform::browser'
]);
// Metrics
$this
->
metricsCollection
->
setTimespansCollection
(
Argument
::
type
(
TimespansCollection
::
class
))
->
willReturn
(
$this
->
metricsCollection
);
$this
->
metricsCollection
->
setFiltersCollection
(
Argument
::
type
(
FiltersCollection
::
class
))
->
willReturn
(
$this
->
metricsCollection
);
$this
->
metricsCollection
->
setSelectedId
(
'active_users'
)
->
willReturn
(
$this
->
metricsCollection
);
$this
->
metricsCollection
->
setUser
(
$user
)
->
willReturn
(
$this
->
metricsCollection
);
$this
->
metricsCollection
->
addMetrics
(
Argument
::
any
(),
Argument
::
any
(),
Argument
::
any
(),
Argument
::
any
())
->
shouldBeCalled
()
->
willReturn
(
$this
->
metricsCollection
);
$this
->
metricsCollection
->
build
()
->
shouldBeCalled
()
->
willReturn
(
$this
->
metricsCollection
);
$this
->
metricsCollection
->
getSelected
()
->
willReturn
(
$mockMetric
);
$this
->
build
();
}
}
This diff is collapsed.
Click to expand it.