<?php
/**
* This file is part of the TchoulomViewCounterBundle package.
*
* @package TchoulomViewCounterBundle
* @author Original Author <tchoulomernest@yahoo.fr>
*
* (c) Ernest TCHOULOM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Tchoulom\ViewCounterBundle\Counter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Tchoulom\ViewCounterBundle\Entity\ViewCounterInterface;
use Tchoulom\ViewCounterBundle\Model\ViewCountable;
use Tchoulom\ViewCounterBundle\Manager\CounterManager;
use Tchoulom\ViewCounterBundle\Model\ViewcounterConfig;
use Tchoulom\ViewCounterBundle\Manager\StatsManager;
use Tchoulom\ViewCounterBundle\Util\Date;
/**
* Class AbstractViewCounter
*/
abstract class AbstractViewCounter
{
/**
* CounterManager
*/
protected $counterManager;
/**
* @var RequestStack
*/
protected $requestStack;
/**
* @var StatsManager
*/
protected $statsManager;
/**
* The View counter configs.
*
* @var ViewcounterConfig
*/
protected $viewcounterConfig;
/**
* The viewCounter
*/
protected $viewCounter = null;
/**
* The class namespace
*/
protected $class = null;
/**
* The property
*/
protected $property = null;
/**
* The current Page
*/
protected $page = null;
const ON_REFRESH = 'on_refresh';
const DAILY_VIEW = 'daily_view';
const UNIQUE_VIEW = 'unique_view';
const HOURLY_VIEW = 'hourly_view';
const WEEKLY_VIEW = 'weekly_view';
const MONTHLY_VIEW = 'monthly_view';
const YEARLY_VIEW = 'yearly_view';
const VIEW_PER_MINUTE = 'view_per_minute';
const VIEW_PER_SECOND = 'view_per_second';
/**
* AbstractViewCounter constructor.
*
* @param CounterManager $counterManager
* @param RequestStack $requestStack
* @param ViewcounterConfig $viewcounterConfig
*/
public function __construct(
CounterManager $counterManager,
RequestStack $requestStack,
ViewcounterConfig $viewcounterConfig
)
{
$this->counterManager = $counterManager;
$this->requestStack = $requestStack;
$this->viewcounterConfig = $viewcounterConfig;
}
/**
* Determines whether the view is new.
*
* @param ViewCounterInterface $viewCounter
*
* @return mixed
*/
abstract public function isNewView(ViewCounterInterface $viewCounter);
/**
* Loads the ViewCounter.
*
* @param ViewCountable $page The counted object(a tutorial or course...)
*
* @return ViewCounterInterface
*/
protected function loadViewCounter(ViewCountable $page): ViewCounterInterface
{
$this->counterManager->loadMetadata($page);
$this->property = $this->counterManager->getProperty();
$this->class = $this->counterManager->getClass();
$clientIP = $this->getClientIp();
$viewCounter = $this->counterManager->findOneBy($criteria = [$this->property => $page, 'ip' => $clientIP],
$orderBy = ['viewDate' => 'DESC'], $limit = null, $offset = null);
if ($viewCounter instanceof ViewCounterInterface) {
return $viewCounter;
}
return $this->createViewCounterObject($page);
}
/**
* Creates the ViewCounter Object from the class namespace.
*
* @param ViewCountable $page The given page.
*
* @return ViewCounterInterface
*/
protected function createViewCounterObject(ViewCountable $page): ViewCounterInterface
{
$this->counterManager->loadMetadata($page);
$class = $this->counterManager->getClass();
$viewCounterObject = new $class();
return $viewCounterObject;
}
/**
* Gets the ViewCounter.
*
* @param ViewCountable null $page The counted object(a tutorial or course...)
*
* @return ViewCounterInterface
*/
public function getViewCounter(ViewCountable $page = null): ViewCounterInterface
{
$viewCounter = $this->loadViewCounter($page);
return $viewCounter;
}
/**
* Gets the page Views.
*
* @param ViewCountable $page The counted object(a tutorial or course...)
*
* @return int
*/
public function getViews(ViewCountable $page): int
{
$viewCounter = $this->getViewCounter($page);
if (null == $viewCounter || $this->isNewView($viewCounter)) {
return $page->getViews() + 1;
}
return $page->getViews();
}
/**
* Saves the View
*
* @param ViewCountable $page The counted object(a tutorial or course...)
*
* @return ViewCountable
*
* @throws \ReflectionException
*/
public function saveView(ViewCountable $page): ViewCountable
{
$viewcounter = $this->getViewCounter($page);
if ($this->isNewView($viewcounter)) {
$viewcounter = $this->createViewCounterObject($page);
$views = $this->getViews($page);
$viewcounter->setIp($this->getClientIp());
$property = $this->getProperty();
$viewcounter->setProperty($property);
$viewcounter->setPage($page);
$viewcounter->setViewDate(Date::getNowDate());
$page->setViews($views);
$this->counterManager->save($viewcounter);
$this->counterManager->save($page);
// Statistics
if (true === $this->isStatsEnabled()) {
$this->handleStatistics($viewcounter);
}
}
return $page;
}
/**
* Handles statistics.
*
* @param ViewCounterInterface $viewcounter The viewcounter entity.
*
* @throws \ReflectionException
*/
public function handleStatistics(ViewCounterInterface $viewcounter)
{
$this->statsManager->register($viewcounter);
}
/**
* Gets the current Request.
*
* @return Request|null
*/
protected function getRequest(): ?Request
{
return $this->requestStack->getCurrentRequest();
}
/**
* Gets the view strategy.
*
* @return mixed
*/
protected function getViewStrategy()
{
$viewcounterNodeConfig = $this->viewcounterConfig->getViewcounterNodeConfig();
$viewStrategy = $viewcounterNodeConfig->getViewStrategy();
return $viewStrategy;
}
/**
* Is stats enabled ?
*
* @return bool Is stats enabled ?
*/
protected function isStatsEnabled(): bool
{
$statisticsNodeConfig = $this->viewcounterConfig->getStatisticsNodeConfig();
$isStatsEnabled = $statisticsNodeConfig->isStatsEnabled();
return $isStatsEnabled;
}
/**
* Gets the class namespace.
*
* @return mixed
*/
protected function getClass()
{
return $this->class;
}
/**
* Gets the property.
*
* @return mixed
*/
protected function getProperty()
{
return $this->property;
}
/**
* Sets the current Page The counted object(a tutorial or course...)
*
* @param ViewCountable $page
*
* @return self
*/
protected function setPage(ViewCountable $page): self
{
$this->page = $page;
return $this;
}
/**
* Gets the current Page The counted object(a tutorial or course...)
*
* @return ViewCountable|null
*/
protected function getPage(): ?ViewCountable
{
return $this->page;
}
/**
* Gets the client IP.
*
* @return null|string
*/
public function getClientIp(): ?string
{
return $this->getRequest()->getClientIp();
}
/**
* Sets the StatsManager.
*
* @param StatsManager $statsManager
*
* @return self
*/
public function setStatsManager(StatsManager $statsManager): self
{
$this->statsManager = $statsManager;
return $this;
}
}