File: /home/aliazzsr/api.crm.vqode.com/models/search/SessionsStatistics.php
<?php
namespace app\models\search;
use app\components\formatters\DateFormatter;
use app\models\core\Role;
use app\models\core\User;
use app\models\enums\PermissionEnum;
use app\models\Session;
use app\models\enums\StatisticsPeriod as Period;
use app\models\UserIdentity;
use yii\behaviors\AttributeTypecastBehavior;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\web\ForbiddenHttpException;
class SessionsStatistics extends Session
{
/** @var string comma separated */
public $roles;
/** @var array */
protected $_roles;
/** @var string */
public $period;
/** @var integer */
public $user;
protected $_joinAlias;
protected $_bd;
protected $_ed;
public function init()
{
parent::init();
$this->_joinAlias = 'sessst01';
}
/**
* @inheritdoc
*/
public function formName()
{
return '';
}
/**
* @inheritdoc
*/
public function safeAttributes()
{
return [
'roles', 'user', 'period',
];
}
/**
* @inheritdoc
*/
public function attributes()
{
return array_merge(parent::attributes(), [
'login', 'logout',
'name', 'times', 'amount',
]);
}
public function rules()
{
return [
[['roles', 'period'], 'required'],
[['roles', 'period'], 'string'],
[['roles'], 'validateRoles'],
[['period'], 'validatePeriod'],
[['group', 'period', 'group_id'], 'safe'],
];
}
/**
* Validates period and extracts interval limits
*/
public function validatePeriod()
{
if (in_array($this->period, Period::getConstantsByName())) {
return;
}
$dateFormat = '/^\d{2}\/\d{2}\/\d{4}$/';
list($bd, $ed) = explode('-', $this->period);
if (preg_match($dateFormat, $bd) && preg_match($dateFormat, $ed)) {
$this->_bd = DateFormatter::toMysql($bd);
$this->_ed = DateFormatter::toMysql($ed);
} else {
$this->addError('period', 'Invalid period.');
}
}
/**
* @throws
*/
public function validateRoles()
{
$this->_roles = explode(',', $this->roles);
$this->_roles = array_map('intval', $this->_roles);
$this->_roles = array_unique($this->_roles);
$this->checkAccess();
}
/**
* @throws
*/
protected function checkAccess()
{
/** @var UserIdentity $identity */
$identity = \Yii::$app->user->getIdentity();
$hasPermissionManagers = $identity->can(PermissionEnum::DASHBOARD_MANAGERS)->read;
$hasPermissionUsers = $identity->can(PermissionEnum::DASHBOARD_USERS)->read;
$readingManagers = in_array(Role::MANAGER, $this->_roles);
$readingUsers = in_array(Role::USER, $this->_roles);
$cantReadManagers = $readingManagers && !$hasPermissionManagers;
$cantReadUsers = $readingUsers && !$hasPermissionUsers;
if ($cantReadManagers || $cantReadUsers) {
throw new ForbiddenHttpException();
}
}
/**
* @inheritdoc
*/
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['projects_statistics'] = [
'class' => AttributeTypecastBehavior::className(),
'attributeTypes' => [
'times' => AttributeTypecastBehavior::TYPE_INTEGER,
'amount' => AttributeTypecastBehavior::TYPE_INTEGER,
'login' => [DateFormatter::className(), 'toStringWithTime'],
'logout' => [DateFormatter::className(), 'toStringWithTime'],
],
'typecastAfterFind' => true,
];
return $behaviors;
}
public function search()
{
$query = self::find();
$query->joinWith(User::tableName() . ' as ' . $this->_joinAlias);
$query->andFilterWhere([
'IN', $this->_joinAlias . '.role_id', $this->_roles
]);
$query->andWhere($this->getPeriodWhereClause());
if (!$this->user) {
$query->select([
'id' => $this->_joinAlias . '.id',
'name' => 'max(' . $this->_joinAlias . '.name)',
'times' => 'count(*)',
'amount' => 'sum({{session}}.duration)',
]);
$query->groupBy([
$this->_joinAlias . '.id',
]);
} else {
$query->select([
'login' => '{{session}}.login_at',
'logout' => '{{session}}.logout_at',
'duration' => '{{session}}.duration',
]);
$query->andWhere([$this->_joinAlias . '.id' => $this->user]);
}
return $query->all();
}
/**
* @return array
*/
protected function getPeriodWhereClause()
{
$arbitraryClauses = ['BETWEEN', '{{session}}.login_at', $this->_bd, $this->_ed];
$clausesMap = [
Period::MONTH => [
'MONTH({{session}}.login_at)' => new Expression('MONTH(NOW())'),
'YEAR({{session}}.login_at)' => new Expression('YEAR(NOW())'),
],
Period::YEAR => [
'YEAR({{session}}.login_at)' => new Expression('YEAR(NOW())'),
],
Period::TOTAL => [
],
];
return ArrayHelper::getValue($clausesMap, $this->period, $arbitraryClauses);
}
}