Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- namespace frontend\components\behaviors;
- use common\helpers\ArrayHelper;
- use common\helpers\UserAgent;
- use common\models\View;
- use frontend\components\base\Controller;
- use Yii;
- use yii\base\Behavior;
- use yii\web\Cookie;
- /**
- * Class ViewsBehavior
- *
- * @package frontend\components\behaviors
- */
- class ViewsBehavior extends Behavior
- {
- /** Наименование cookie просмотров */
- const COOKIE_NAME = 'history-views';
- /** Время истечения куки (сутки) */
- const EXPIRE_COOKIE = 24 * 60 * 60;
- /** @var integer */
- private $objectId;
- /** @var integer */
- private $type;
- /** @var array */
- private $watchActions;
- /** @var string */
- private $userCookie;
- /** @var string */
- private $currentAction;
- /** @var integer */
- private $viewId;
- /**
- * @return array
- */
- public function events()
- {
- return [
- Controller::EVENT_AFTER_ACTION => 'viewSender',
- ];
- }
- /**
- * Сбор статистики просмотров
- */
- public function viewSender()
- {
- $this->getObjectId();
- $this->getWatcherActions();
- $this->getCurrentAction();
- if ($this->validateTargetAction()) {
- if (!UserAgent::isIgnore(UserAgent::ALL_USER_AGENTS_LIST)) {
- $this->addStatistic();
- }
- }
- }
- /**
- * Проверка на наличие текущего экшена в списке наблюдаемых
- *
- * @return bool
- */
- public function validateTargetAction()
- {
- if (!empty($this->watchActions) && in_array($this->currentAction, $this->watchActions)) {
- return true;
- }
- return false;
- }
- /**
- * Получение списка наблюдаемых экшенов
- */
- private function getWatcherActions()
- {
- $this->watchActions = ArrayHelper::getValue(Yii::$app->params, 'watcherActions', '');
- }
- /**
- * Добавление данных статистики
- * Если кука есть, то ничего не произойдет
- * Добавляет запись о новом наблюдаемом объекте в View или обновляет существующий
- *
- * @return bool
- */
- private function addStatistic()
- {
- $isValidCookie = false;
- $this->getUserCookie();
- $this->getTypeViews();
- if ($this->validateHistoryActions()) {
- $isValidCookie = true;
- }
- $view = View::findOne([
- 'object_id' => $this->objectId,
- 'type' => $this->type,
- ]);
- if (!empty($view) && $isValidCookie) {
- $this->viewId = $view->id;
- if (!$this->validateHistoryActions(true)) {
- return false;
- }
- }
- if (empty($view)) {
- $view = new View([
- 'object_id' => $this->objectId,
- 'type' => $this->type,
- 'count' => 1,
- ]);
- if (!$view->save()) {
- Yii::error(Yii::t('common', "Error created view for object_id '{$this->objectId}' and type '{$this->type}'"));
- return false;
- }
- } else {
- $view->count += 1;
- if (!$view->save()) {
- Yii::error(Yii::t('common', "Error saved view for object_id '{$this->objectId}' and type '{$this->type}'"));
- return false;
- }
- }
- $this->viewId = $view->id;
- $this->setUserCookie();
- return true;
- }
- /**
- * Устанавливает куку пользователю
- */
- private function setUserCookie()
- {
- if (empty($this->userCookie)) {
- $this->setCookie();
- } else {
- $this->addCookie();
- }
- }
- /**
- * Установка куки
- * Если существующая кука уже содержит текущую или невалидна, то установка не будет произведена
- *
- * @return bool
- */
- private function setCookie()
- {
- $newCookie[] = $this->viewId;
- Yii::$app->response->cookies->add(new Cookie([
- 'name' => self::COOKIE_NAME,
- 'value' => serialize($newCookie),
- 'expire' => $this->getTimeExpireCookie(),
- ]));
- return true;
- }
- /**
- * Добавить куку к существующему массиву
- * Если кука существует, то будет проигнорировано
- * Если кука невалидна, то она будет пересоздана с текущим элементом
- *
- * @return bool
- */
- private function addCookie()
- {
- $issetCookie = unserialize($this->userCookie);
- if ($this->validateHistoryActions()) {
- $issetCookie[] = $this->viewId;
- Yii::$app->response->cookies->add(new Cookie([
- 'name' => self::COOKIE_NAME,
- 'value' => serialize($issetCookie),
- 'expire' => $this->getTimeExpireCookie(),
- ]));
- return true;
- }
- if (!$this->validateHistoryActions()) {
- $this->removeCookie();
- $this->setCookie();
- return true;
- }
- return false;
- }
- /**
- * Удаление куки
- */
- private function removeCookie()
- {
- Yii::$app->response->cookies->remove(self::COOKIE_NAME);
- $this->userCookie = '';
- }
- /**
- * Получаем куку истории посещаемости
- */
- private function getUserCookie()
- {
- $this->userCookie = Yii::$app->request->cookies->getValue(self::COOKIE_NAME);
- }
- /**
- * Получаем тип просматриваемого объекта
- */
- private function getTypeViews()
- {
- $this->type = ArrayHelper::getValue(array_flip($this->watchActions), $this->currentAction);
- }
- /**
- * Получение типа объекта
- */
- private function getObjectId()
- {
- $this->objectId = ArrayHelper::getValue(Yii::$app->controller, 'recordId');
- }
- /**
- * Собираем данные о текущей странице
- */
- private function getCurrentAction()
- {
- $app = Yii::$app;
- $controller = $app->controller->id;
- $action = $app->controller->action->id;
- $this->currentAction = "{$controller}/{$action}";
- }
- /**
- * Валидация истории посещения
- *
- * @param boolean $withCheckIssetCurrentPage - проверять ли наличие текущей статистики в списке посещенных
- * @return bool
- */
- private function validateHistoryActions($withCheckIssetCurrentPage = false)
- {
- if (empty($this->userCookie)) {
- return false;
- }
- $historyActions = unserialize($this->userCookie);
- if (empty($historyActions) || !is_array($historyActions)) {
- return false;
- }
- if (!$withCheckIssetCurrentPage) {
- return true;
- }
- if (!empty($this->viewId)) {
- if (in_array($this->viewId, $historyActions)) {
- return false;
- }
- }
- return true;
- }
- /**
- * Получение времени истечения куки
- *
- * @param int $time
- * @return float|int
- */
- private function getTimeExpireCookie($time = 0)
- {
- if (empty($time)) {
- $time = time();
- }
- return $time + self::EXPIRE_COOKIE;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement