Advertisement
Guest User

Untitled

a guest
Jun 24th, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.95 KB | None | 0 0
  1. <?php
  2.  
  3. namespace frontend\components\behaviors;
  4.  
  5. use common\helpers\ArrayHelper;
  6. use common\helpers\UserAgent;
  7. use common\models\View;
  8. use frontend\components\base\Controller;
  9. use Yii;
  10. use yii\base\Behavior;
  11. use yii\web\Cookie;
  12.  
  13. /**
  14. * Class ViewsBehavior
  15. *
  16. * @package frontend\components\behaviors
  17. */
  18. class ViewsBehavior extends Behavior
  19. {
  20. /** Наименование cookie просмотров */
  21. const COOKIE_NAME = 'history-views';
  22.  
  23. /** Время истечения куки (сутки) */
  24. const EXPIRE_COOKIE = 24 * 60 * 60;
  25.  
  26. /** @var integer */
  27. private $objectId;
  28.  
  29. /** @var integer */
  30. private $type;
  31.  
  32. /** @var array */
  33. private $watchActions;
  34.  
  35. /** @var string */
  36. private $userCookie;
  37.  
  38. /** @var string */
  39. private $currentAction;
  40.  
  41. /** @var integer */
  42. private $viewId;
  43.  
  44. /**
  45. * @return array
  46. */
  47. public function events()
  48. {
  49. return [
  50. Controller::EVENT_AFTER_ACTION => 'viewSender',
  51. ];
  52. }
  53.  
  54. /**
  55. * Сбор статистики просмотров
  56. */
  57. public function viewSender()
  58. {
  59. $this->getObjectId();
  60. $this->getWatcherActions();
  61. $this->getCurrentAction();
  62.  
  63. if ($this->validateTargetAction()) {
  64. if (!UserAgent::isIgnore(UserAgent::ALL_USER_AGENTS_LIST)) {
  65. $this->addStatistic();
  66. }
  67. }
  68. }
  69.  
  70. /**
  71. * Проверка на наличие текущего экшена в списке наблюдаемых
  72. *
  73. * @return bool
  74. */
  75. public function validateTargetAction()
  76. {
  77. if (!empty($this->watchActions) && in_array($this->currentAction, $this->watchActions)) {
  78. return true;
  79. }
  80.  
  81. return false;
  82. }
  83.  
  84. /**
  85. * Получение списка наблюдаемых экшенов
  86. */
  87. private function getWatcherActions()
  88. {
  89. $this->watchActions = ArrayHelper::getValue(Yii::$app->params, 'watcherActions', '');
  90. }
  91.  
  92. /**
  93. * Добавление данных статистики
  94. * Если кука есть, то ничего не произойдет
  95. * Добавляет запись о новом наблюдаемом объекте в View или обновляет существующий
  96. *
  97. * @return bool
  98. */
  99. private function addStatistic()
  100. {
  101. $isValidCookie = false;
  102.  
  103. $this->getUserCookie();
  104. $this->getTypeViews();
  105.  
  106. if ($this->validateHistoryActions()) {
  107. $isValidCookie = true;
  108. }
  109.  
  110. $view = View::findOne([
  111. 'object_id' => $this->objectId,
  112. 'type' => $this->type,
  113. ]);
  114.  
  115. if (!empty($view) && $isValidCookie) {
  116. $this->viewId = $view->id;
  117.  
  118. if (!$this->validateHistoryActions(true)) {
  119. return false;
  120. }
  121. }
  122.  
  123. if (empty($view)) {
  124. $view = new View([
  125. 'object_id' => $this->objectId,
  126. 'type' => $this->type,
  127. 'count' => 1,
  128. ]);
  129.  
  130. if (!$view->save()) {
  131. Yii::error(Yii::t('common', "Error created view for object_id '{$this->objectId}' and type '{$this->type}'"));
  132.  
  133. return false;
  134. }
  135. } else {
  136. $view->count += 1;
  137.  
  138. if (!$view->save()) {
  139. Yii::error(Yii::t('common', "Error saved view for object_id '{$this->objectId}' and type '{$this->type}'"));
  140.  
  141. return false;
  142. }
  143. }
  144.  
  145. $this->viewId = $view->id;
  146.  
  147. $this->setUserCookie();
  148.  
  149. return true;
  150. }
  151.  
  152. /**
  153. * Устанавливает куку пользователю
  154. */
  155. private function setUserCookie()
  156. {
  157. if (empty($this->userCookie)) {
  158. $this->setCookie();
  159. } else {
  160. $this->addCookie();
  161. }
  162. }
  163.  
  164. /**
  165. * Установка куки
  166. * Если существующая кука уже содержит текущую или невалидна, то установка не будет произведена
  167. *
  168. * @return bool
  169. */
  170. private function setCookie()
  171. {
  172. $newCookie[] = $this->viewId;
  173.  
  174. Yii::$app->response->cookies->add(new Cookie([
  175. 'name' => self::COOKIE_NAME,
  176. 'value' => serialize($newCookie),
  177. 'expire' => $this->getTimeExpireCookie(),
  178. ]));
  179.  
  180. return true;
  181. }
  182.  
  183. /**
  184. * Добавить куку к существующему массиву
  185. * Если кука существует, то будет проигнорировано
  186. * Если кука невалидна, то она будет пересоздана с текущим элементом
  187. *
  188. * @return bool
  189. */
  190. private function addCookie()
  191. {
  192. $issetCookie = unserialize($this->userCookie);
  193.  
  194. if ($this->validateHistoryActions()) {
  195. $issetCookie[] = $this->viewId;
  196.  
  197. Yii::$app->response->cookies->add(new Cookie([
  198. 'name' => self::COOKIE_NAME,
  199. 'value' => serialize($issetCookie),
  200. 'expire' => $this->getTimeExpireCookie(),
  201. ]));
  202.  
  203. return true;
  204. }
  205.  
  206. if (!$this->validateHistoryActions()) {
  207. $this->removeCookie();
  208. $this->setCookie();
  209.  
  210. return true;
  211. }
  212.  
  213. return false;
  214. }
  215.  
  216. /**
  217. * Удаление куки
  218. */
  219. private function removeCookie()
  220. {
  221. Yii::$app->response->cookies->remove(self::COOKIE_NAME);
  222.  
  223. $this->userCookie = '';
  224. }
  225.  
  226. /**
  227. * Получаем куку истории посещаемости
  228. */
  229. private function getUserCookie()
  230. {
  231. $this->userCookie = Yii::$app->request->cookies->getValue(self::COOKIE_NAME);
  232. }
  233.  
  234. /**
  235. * Получаем тип просматриваемого объекта
  236. */
  237. private function getTypeViews()
  238. {
  239. $this->type = ArrayHelper::getValue(array_flip($this->watchActions), $this->currentAction);
  240. }
  241.  
  242. /**
  243. * Получение типа объекта
  244. */
  245. private function getObjectId()
  246. {
  247. $this->objectId = ArrayHelper::getValue(Yii::$app->controller, 'recordId');
  248. }
  249.  
  250. /**
  251. * Собираем данные о текущей странице
  252. */
  253. private function getCurrentAction()
  254. {
  255. $app = Yii::$app;
  256. $controller = $app->controller->id;
  257. $action = $app->controller->action->id;
  258.  
  259. $this->currentAction = "{$controller}/{$action}";
  260. }
  261.  
  262. /**
  263. * Валидация истории посещения
  264. *
  265. * @param boolean $withCheckIssetCurrentPage - проверять ли наличие текущей статистики в списке посещенных
  266. * @return bool
  267. */
  268. private function validateHistoryActions($withCheckIssetCurrentPage = false)
  269. {
  270. if (empty($this->userCookie)) {
  271. return false;
  272. }
  273.  
  274. $historyActions = unserialize($this->userCookie);
  275.  
  276. if (empty($historyActions) || !is_array($historyActions)) {
  277. return false;
  278. }
  279.  
  280. if (!$withCheckIssetCurrentPage) {
  281. return true;
  282. }
  283.  
  284. if (!empty($this->viewId)) {
  285. if (in_array($this->viewId, $historyActions)) {
  286. return false;
  287. }
  288. }
  289.  
  290. return true;
  291. }
  292.  
  293. /**
  294. * Получение времени истечения куки
  295. *
  296. * @param int $time
  297. * @return float|int
  298. */
  299. private function getTimeExpireCookie($time = 0)
  300. {
  301. if (empty($time)) {
  302. $time = time();
  303. }
  304.  
  305. return $time + self::EXPIRE_COOKIE;
  306. }
  307. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement