backports murph-skeleton

This commit is contained in:
Simon Vieille 2022-02-20 13:49:18 +01:00
parent dbe9287314
commit d540572a64
14 changed files with 326 additions and 160 deletions

View file

@ -23,7 +23,7 @@ services:
tags:
- { name: kernel.event_listener, event: kernel.exception }
App\Core\EventListener\NodeViewListener:
App\Core\EventListener\AnalyticListener:
tags:
- { name: kernel.event_listener, event: kernel.request }

View file

@ -0,0 +1,103 @@
<?php
namespace App\Core\Entity\Analytic;
use App\Core\Entity\Site\Node;
use App\Repository\Entity\Analytic\NodeViewRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Core\Entity\EntityInterface;
/**
* @ORM\Entity(repositoryClass=ViewRepository::class)
* @ORM\Table(name="analytic_referer")
*/
class Referer implements EntityInterface
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=Node::class, inversedBy="nodeViews")
* @ORM\JoinColumn(nullable=false)
*/
private $node;
/**
* @ORM\Column(type="string", length=255)
*/
private $uri;
/**
* @ORM\Column(type="integer", options={"default"=0})
*/
private $views = 0;
/**
* @ORM\Column(type="date")
*/
private $date;
public function getId(): ?int
{
return $this->id;
}
public function getNode(): ?Node
{
return $this->node;
}
public function setNode(?Node $node): self
{
$this->node = $node;
return $this;
}
public function getUri(): ?string
{
return $this->uri;
}
public function setUri(string $uri): self
{
$this->uri = $uri;
return $this;
}
public function getViews(): ?int
{
return $this->views;
}
public function setViews(int $views): self
{
$this->views = $views;
return $this;
}
public function addView(): self
{
++$this->views;
return $this;
}
public function getDate(): ?\DateTimeInterface
{
return $this->date;
}
public function setDate(\DateTimeInterface $date): self
{
$this->date = $date;
return $this;
}
}

View file

@ -1,16 +1,17 @@
<?php
namespace App\Core\Entity;
namespace App\Core\Entity\Analytic;
use App\Core\Entity\Site\Node;
use App\Repository\Entity\NodeViewRepository;
use App\Repository\Entity\Analytic\NodeViewRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Core\Entity\EntityInterface;
/**
* @ORM\Entity(repositoryClass=NodeViewRepository::class)
* @ORM\Entity(repositoryClass=ViewRepository::class)
* @ORM\Table(name="analytic_view")
*/
class NodeView implements EntityInterface
class View implements EntityInterface
{
/**
* @ORM\Id

View file

@ -145,16 +145,10 @@ class Node implements EntityInterface
*/
private $enableViewCounter = false;
/**
* @ORM\OneToMany(targetEntity=NodeView::class, mappedBy="node", orphanRemoval=true)
*/
private $nodeViews;
public function __construct()
{
$this->children = new ArrayCollection();
$this->aliasNodes = new ArrayCollection();
$this->nodeViews = new ArrayCollection();
}
public function getId(): ?int
@ -572,34 +566,4 @@ class Node implements EntityInterface
return $this;
}
/**
* @return Collection|NodeView[]
*/
public function getNodeViews(): Collection
{
return $this->nodeViews;
}
public function addNodeView(NodeView $nodeView): self
{
if (!$this->nodeViews->contains($nodeView)) {
$this->nodeViews[] = $nodeView;
$nodeView->setNode($this);
}
return $this;
}
public function removeNodeView(NodeView $nodeView): self
{
if ($this->nodeViews->removeElement($nodeView)) {
// set the owning side to null (unless already changed)
if ($nodeView->getNode() === $this) {
$nodeView->setNode(null);
}
}
return $this;
}
}

View file

@ -0,0 +1,117 @@
<?php
namespace App\Core\EventListener;
use App\Core\Manager\EntityManager;
use App\Core\Repository\Site\NodeRepositoryQuery;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use App\Core\Repository\Site\NodeRepository;
use App\Core\Repository\Analytic\ViewRepositoryQuery;
use App\Core\Factory\Analytic\ViewFactory;
use App\Core\Entity\Site\Node;
use Symfony\Component\HttpFoundation\Request;
use App\Core\Repository\Analytic\RefererRepositoryQuery;
use App\Core\Factory\Analytic\RefererFactory;
use App\Core\Entity\EntityInterface;
/**
* class AnalyticListener.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class AnalyticListener
{
protected NodeRepository $nodeRepository;
protected ViewRepositoryQuery $viewRepositoryQuery;
protected ViewFactory $viewFactory;
protected RefererRepositoryQuery $refererRepositoryQuery;
protected RefererFactory $refererFactory;
protected EntityManager $manager;
protected Request $request;
protected Node $node;
public function __construct(
NodeRepository $nodeRepository,
ViewRepositoryQuery $viewRepositoryQuery,
ViewFactory $viewFactory,
RefererRepositoryQuery $refererRepositoryQuery,
RefererFactory $refererFactory,
EntityManager $manager
) {
$this->nodeRepository = $nodeRepository;
$this->viewRepositoryQuery = $viewRepositoryQuery;
$this->viewFactory = $viewFactory;
$this->refererRepositoryQuery = $refererRepositoryQuery;
$this->refererFactory = $refererFactory;
$this->manager = $manager;
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if (!$request->attributes->has('_node')) {
return;
}
$node = $this->nodeRepository->findOneBy([
'id' => $request->attributes->get('_node'),
'enableViewCounter' => true,
]);
if (!$node) {
return;
}
$this->node = $node;
$this->request = $request;
$this->createView();
$this->createReferer();
}
protected function createView()
{
$entity = $this->viewRepositoryQuery->create()
->filterByRequest($this->request)
->andWhere('.date=CURRENT_DATE()')
->findOne()
;
if (!$entity) {
$entity = $this->viewFactory->create($this->node, $this->request->getPathInfo());
}
$entity->addView();
$this->save($entity);
}
protected function createReferer()
{
if (!$this->request->headers->has('referer')) {
return;
}
$entity = $this->refererRepositoryQuery->create()
->filterByRequest($this->request)
->andWhere('.date=CURRENT_DATE()')
->findOne()
;
if (!$entity) {
$entity = $this->refererFactory->create($this->node, $this->request->headers->get('referer'));
}
$entity->addView();
$this->save($entity);
}
protected function save(EntityInterface $entity)
{
if ($entity->getId()) {
$this->manager->update($entity);
} else {
$this->manager->create($entity);
}
}
}

View file

@ -1,68 +0,0 @@
<?php
namespace App\Core\EventListener;
use App\Core\Factory\NodeViewFactory;
use App\Core\Manager\EntityManager;
use App\Core\Repository\NodeViewRepositoryQuery;
use App\Core\Repository\Site\NodeRepositoryQuery;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use App\Core\Repository\Site\NodeRepository;
/**
* class NodeViewListener.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class NodeViewListener
{
protected NodeRepository $nodeRepository;
protected NodeViewRepositoryQuery $nodeViewRepositoryQuery;
protected NodeViewFactory $nodeViewFactory;
protected EntityManager $manager;
public function __construct(
NodeRepository $nodeRepository,
NodeViewRepositoryQuery $nodeViewRepositoryQuery,
NodeViewFactory $nodeViewFactory,
EntityManager $manager
) {
$this->nodeRepository = $nodeRepository;
$this->nodeViewRepositoryQuery = $nodeViewRepositoryQuery;
$this->nodeViewFactory = $nodeViewFactory;
$this->manager = $manager;
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if (!$request->attributes->has('_node')) {
return;
}
$node = $this->nodeRepository->findOneById($request->attributes->get('_node'));
if (!$node || !$node->getEnableViewCounter()) {
return;
}
$nodeView = $this->nodeViewRepositoryQuery->create()
->filterByRequest($request)
->andWhere('.date=CURRENT_DATE()')
->findOne()
;
if (!$nodeView) {
$nodeView = $this->nodeViewFactory->create($node, $request->getPathInfo());
}
$nodeView->addView();
if ($nodeView->getId()) {
$this->manager->update($nodeView);
} else {
$this->manager->create($nodeView);
}
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace App\Core\Factory\Analytic;
use App\Core\Entity\Analytic\Referer as Entity;
use App\Core\Entity\Site\Node;
use App\Core\Factory\FactoryInterface;
class RefererFactory implements FactoryInterface
{
public function create(Node $node, string $uri): Entity
{
$entity = new Entity();
$entity
->setNode($node)
->setUri($uri)
->setDate(new \DateTime())
;
return $entity;
}
}

View file

@ -1,11 +1,12 @@
<?php
namespace App\Core\Factory;
namespace App\Core\Factory\Analytic;
use App\Core\Entity\NodeView as Entity;
use App\Core\Entity\Analytic\View as Entity;
use App\Core\Entity\Site\Node;
use App\Core\Factory\FactoryInterface;
class NodeViewFactory implements FactoryInterface
class ViewFactory implements FactoryInterface
{
public function create(Node $node, string $path): Entity
{

View file

@ -0,0 +1,21 @@
<?php
namespace App\Core\Repository\Analytic;
use App\Core\Entity\Analytic\Referer;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Referer|null find($id, $lockMode = null, $lockVersion = null)
* @method Referer|null findOneBy(array $criteria, array $orderBy = null)
* @method Referer[] findAll()
* @method Referer[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class RefererRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Referer::class);
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Core\Repository\Analytic;
use App\Core\Repository\Analytic\RefererRepository as Repository;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpFoundation\Request;
use App\Core\Repository\RepositoryQuery;
class RefererRepositoryQuery extends RepositoryQuery
{
public function __construct(Repository $repository, PaginatorInterface $paginator)
{
parent::__construct($repository, 'n', $paginator);
}
public function filterByRequest(Request $request)
{
return $this
->andWhere('.node = :node')
->andWhere('.uri = :uri')
->setParameters([
':node' => $request->attributes->get('_node'),
':uri' => $request->headers->get('referer'),
])
;
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace App\Core\Repository\Analytic;
use App\Core\Entity\Analytic\View;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method View|null find($id, $lockMode = null, $lockVersion = null)
* @method View|null findOneBy(array $criteria, array $orderBy = null)
* @method View[] findAll()
* @method View[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ViewRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, View::class);
}
}

View file

@ -1,12 +1,13 @@
<?php
namespace App\Core\Repository;
namespace App\Core\Repository\Analytic;
use App\Core\Repository\NodeViewRepository as Repository;
use App\Core\Repository\Analytic\ViewRepository as Repository;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpFoundation\Request;
use App\Core\Repository\RepositoryQuery;
class NodeViewRepositoryQuery extends RepositoryQuery
class ViewRepositoryQuery extends RepositoryQuery
{
public function __construct(Repository $repository, PaginatorInterface $paginator)
{

View file

@ -1,21 +0,0 @@
<?php
namespace App\Core\Repository;
use App\Core\Entity\NodeView;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method NodeView|null find($id, $lockMode = null, $lockVersion = null)
* @method NodeView|null findOneBy(array $criteria, array $orderBy = null)
* @method NodeView[] findAll()
* @method NodeView[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class NodeViewRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, NodeView::class);
}
}

View file

@ -1,24 +0,0 @@
<?php
namespace App\Core\Site;
use App\Repository\Site\NodeRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=NodeRepository::class)
*/
class Node
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
public function getId(): ?int
{
return $this->id;
}
}