Events with additional dimensions
<?php
namespace CherrycakeApp;
class StatsEventUserLogin extends \Cherrycake\Stats\StatsEvent {
protected $timeResolution = \Cherrycake\Stats\STATS_EVENT_TIME_RESOLUTION_DAY;
protected $typeDescription = "User login";
protected $isSecondaryId = true;
protected $secondaryIdDescription = "User id";
function loadInline($data = false) {
if ($data["userId"] ?? false)
$this->secondary_id = $data["userId"];
return parent::loadInline($data);
}
}
<?php
namespace CherrycakeApp\LoginGuide;
class LoginGuide extends \Cherrycake\Module {
protected $dependentCoreModules = [
"HtmlDocument",
"Login",
"Stats"
];
public static function mapActions() {
global $e;
$e->Actions->mapAction(
"loginGuideHome",
new \Cherrycake\Actions\ActionHtml([
"moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
"moduleName" => "LoginGuide",
"methodName" => "home",
"request" => new \Cherrycake\Actions\Request([
"pathComponents" => [
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "login-guide"
])
]
])
])
);
$e->Actions->mapAction(
"loginGuideLoginPage",
new \Cherrycake\Actions\ActionHtml([
"moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
"moduleName" => "LoginGuide",
"methodName" => "loginPage",
"request" => new \Cherrycake\Actions\Request([
"pathComponents" => [
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "login-guide"
]),
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "login-page"
])
]
])
])
);
$e->Actions->mapAction(
"loginGuideDoLogin",
new \Cherrycake\Actions\ActionHtml([
"moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
"moduleName" => "LoginGuide",
"methodName" => "doLogin",
"request" => new \Cherrycake\Actions\Request([
"isSecurityCsrf" => true,
"pathComponents" => [
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "login-guide"
]),
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "do-login"
])
],
"parameters" => [
new \Cherrycake\Actions\RequestParameter([
"name" => "email",
"type" => \Cherrycake\REQUEST_PARAMETER_TYPE_POST
]),
new \Cherrycake\Actions\RequestParameter([
"name" => "password",
"type" => \Cherrycake\REQUEST_PARAMETER_TYPE_POST
])
]
]),
"isSensibleToBruteForceAttacks" => true
])
);
$e->Actions->mapAction(
"loginGuideLogout",
new \Cherrycake\Actions\ActionHtml([
"moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
"moduleName" => "LoginGuide",
"methodName" => "logout",
"request" => new \Cherrycake\Actions\Request([
"pathComponents" => [
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "login-guide"
]),
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "logout"
])
]
])
])
);
}
function home() {
global $e;
$e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
"code" => \Cherrycake\Output\RESPONSE_OK,
"payload" =>
$e->HtmlDocument->header().
($e->Login->isLogged() ?
"You are logged in as {$e->Login->user->name}".
"<a href=\"{$e->Actions->getAction("loginGuideLogout")->request->buildUrl()}\" class=button>Logout</a>"
:
"You are not logged in".
"<a href=\"{$e->Actions->getAction("loginGuideLoginPage")->request->buildUrl()}\" class=button>Login</a>"
).
$e->HtmlDocument->footer()
]));
}
function loginPage() {
global $e;
$e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
"code" => \Cherrycake\Output\RESPONSE_OK,
"payload" =>
$e->HtmlDocument->header().
"
<form method=post action=\"{$e->Actions->getAction("loginGuideDoLogin")->request->buildUrl()}\">
<input name=email type=text name=email placeholder=\"Email\" />
<input name=password type=password name=password placeholder=\"Password\" />
<input type=submit value=\"Login\"/>
</form>
".
$e->HtmlDocument->footer()
]));
}
function doLogin($request) {
global $e;
$result = $e->Login->doLogin($request->email, $request->password);
if (
$result == \Cherrycake\LOGIN_RESULT_FAILED_UNKNOWN_USER
||
$result == \Cherrycake\LOGIN_RESULT_FAILED_WRONG_PASSWORD
) {
$e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
"code" => \Cherrycake\Output\RESPONSE_OK,
"payload" => $e->HtmlDocument->header()."Login error".$e->HtmlDocument->footer()
]));
}
else {
$e->Stats->trigger(new \CherrycakeApp\StatsEventUserLogin(["userId" => $e->Login->user->id]));
$e->Output->setResponse(new \Cherrycake\Actions\Response([
"code" => \Cherrycake\Output\RESPONSE_REDIRECT_FOUND,
"url" => $e->Actions->getAction("loginGuideHome")->request->buildUrl()
]));
}
}
function logout() {
global $e;
$e->Login->logoutUser();
$e->Output->setResponse(new \Cherrycake\Actions\Response([
"code" => \Cherrycake\Output\RESPONSE_REDIRECT_FOUND,
"url" => $e->Actions->getAction("loginGuideHome")->request->buildUrl()
]));
}
}
<?php
namespace CherrycakeApp\StatsGuide;
class StatsGuide extends \Cherrycake\Module {
var $dependentCoreModules = [
"Locale",
"Stats"
];
public static function mapActions() {
global $e;
$e->Actions->mapAction(
"statsGuideTriggeringEvent",
new \Cherrycake\Actions\ActionHtml([
"moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
"moduleName" => "StatsGuide",
"methodName" => "triggeringEvent",
"request" => new \Cherrycake\Actions\Request([
"pathComponents" => [
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "stats-guide"
]),
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "triggering-event"
])
]
])
])
);
$e->Actions->mapAction(
"statsGuideAdditionalDimensions",
new \Cherrycake\Actions\ActionHtml([
"moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
"moduleName" => "StatsGuide",
"methodName" => "additionalDimensions",
"request" => new \Cherrycake\Actions\Request([
"pathComponents" => [
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "stats-guide"
]),
new \Cherrycake\Actions\RequestPathComponent([
"type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
"string" => "additional-dimensions"
])
]
])
])
);
}
function triggeringEvent() {
global $e;
$e->Stats->trigger(new \CherrycakeApp\StatsEventStatsGuideTriggeringExample);
$statsEventItems = new \Cherrycake\Stats\StatsEvents([
"p" => [
"type" => "CherrycakeApp\StatsEventStatsGuideTriggeringExample",
"limit" => 100
]
]);
$payload = "";
foreach ($statsEventItems as $statsEvent) {
$payload .=
$e->Locale->formatTimestamp($statsEvent->timestamp).
": ".$statsEvent->typeDescription.
": ".$statsEvent->count.
"\n";
}
$e->Output->setResponse(new \Cherrycake\Actions\ResponseTextPlain([
"code" => \Cherrycake\Output\RESPONSE_OK,
"payload" => $payload
]));
}
function additionalDimensions() {
global $e;
$e->Stats->trigger(new \CherrycakeApp\StatsEventStatsGuideTriggeringExample);
$statsEventItems = new \Cherrycake\Stats\StatsEvents([
"p" => [
"type" => "CherrycakeApp\StatsEventUserLogin",
"limit" => 100
]
]);
$payload = "";
foreach ($statsEventItems as $statsEvent) {
$user = new \CherrycakeApp\User([
"loadMethod" => "fromId",
"id" => $statsEvent->secondary_id
]);
$payload .=
$e->Locale->formatTimestamp($statsEvent->timestamp).
": ".$user->name.
" logged in ".$statsEvent->count." times".
"\n";
}
$e->Output->setResponse(new \Cherrycake\Actions\ResponseTextPlain([
"code" => \Cherrycake\Output\RESPONSE_OK,
"payload" => $payload
]));
}
}