-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathViewsBehavior.php
158 lines (132 loc) · 4.51 KB
/
ViewsBehavior.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?php
namespace common\behaviors;
use Yii;
use yii\base\Behavior;
use yii\db\ActiveRecord;
use yii\web\Controller;
use yii\db\Expression;
use yii\web\Cookie;
/**
* Class ViewsBehavior
* Активирует счетчик статистики по событию EVENT_BEFORE_ACTION
* для указанных действий контроллера в методе behaviors()
* @package common\behaviors
*/
class ViewsBehavior extends Behavior
{
/**
* Имя модели просмотры которого необходимо учитывать
*
* @var ActiveRecord
*/
public $targetModel;
/**
* Имя модели хранения просмотров
*
* @var ActiveRecord
*/
public $viewsModel;
/**
* Имя атрибута хранящий timestamp создания записи модели хранения просмотров
*
* @var string
*/
public $createTimeAttribute = 'created_at';
/**
* Ключ по которому сохранять запись в куки о просмотре модели
*
* @var string
*/
public $cookieName = '';
/**
* Время на которое ставить куки о просмотре модели (по умолчанию 1 год)
*
* @var int
*/
public $cookieExpireTime = 31536000;
/**
* По дефолту экшен view, можно указать свое имя экшена для просмотра модели
*
* @var string
*/
public $action = 'view';
/**
* Привязка вызова метода add к событию
*
* @return array
*/
public function events()
{
return [
Controller::EVENT_AFTER_ACTION => 'add',
];
}
/**
* Сохранение данных посетителя в БД
*
* @return void
*/
public function add()
{
if (!$this->targetModel || !$this->viewsModel || !$this->cookieName) {
Yii::warning(
"Empty required parametr. targetModel => '{$this->targetModel}', viewsModel => '{$this->viewsModel}', cookieName => '{$this->cookieName}'",
'ViewBehaviors.add'
);
return;
}
/** @var Controller $controller */
$controller = $this->owner;
/**
* ID текущего действия
* Обрываем если не тот контроллер (см. @property $action)
*
* @var string $action_name
*/
$action_name = $controller->action->id;
if($action_name != $this->action) {
return;
}
/**
* Получаем аттрибут и значение аттрибута используемого экшеном просмотра модели (см. @property $action)
*
* @var array $action_params
*/
$action_params = $controller->actionParams;
/**
* Поиск просматриваемой модели по атрибуту и значению атрибута который зашел в экшен
* Обрываем выполнение если не нашлась модель
*
* @var null|ActiveRecord $model
*/
$model = $this->targetModel::findOne(
[
array_keys($action_params)[0] => array_values($action_params)[0]
]
);
if (null === $model) {
return;
}
/** @var null|int $cookieValue */
$cookieValue = Yii::$app->getRequest()->getCookies()->getValue($this->cookieName);
//Не учитываем просмотры если уже смотрели текущую модель
if ($cookieValue && $model->id == $cookieValue) {
return;
}
try {
//Ставим куки о просмотре текущей модели
$cookie = new Cookie([
'name' => $this->cookieName,
'value' => $model->id,
'expire' => time() + $this->cookieExpireTime,
]);
Yii::$app->getResponse()->getCookies()->add($cookie);
/** @var ActiveRecord $modelViews */
$modelViews = new $this->viewsModel;
$modelViews->model_id = $model->id;
$modelViews->save();
} catch (\Exception $e) {
Yii::$app->errorHandler->logException($e);
}
}
}