backports murph-skeleton
This commit is contained in:
parent
45dab306d6
commit
2b7479cb40
|
@ -16,12 +16,12 @@
|
||||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||||
"doctrine/orm": "^2.8",
|
"doctrine/orm": "^2.8",
|
||||||
"friendsofsymfony/jsrouting-bundle": "^2.7",
|
"friendsofsymfony/jsrouting-bundle": "^2.7",
|
||||||
"jaybizzle/crawler-detect": "^1.2",
|
|
||||||
"knplabs/doctrine-behaviors": "^2.2",
|
"knplabs/doctrine-behaviors": "^2.2",
|
||||||
"knplabs/knp-markdown-bundle": "^1.9",
|
"knplabs/knp-markdown-bundle": "^1.9",
|
||||||
"knplabs/knp-menu-bundle": "^3.1",
|
"knplabs/knp-menu-bundle": "^3.1",
|
||||||
"knplabs/knp-paginator-bundle": "^5.8",
|
"knplabs/knp-paginator-bundle": "^5.8",
|
||||||
"liip/imagine-bundle": "^2.6",
|
"liip/imagine-bundle": "^2.6",
|
||||||
|
"matomo/device-detector": "^5.0",
|
||||||
"phpdocumentor/reflection-docblock": "^5.2",
|
"phpdocumentor/reflection-docblock": "^5.2",
|
||||||
"scheb/2fa-google-authenticator": "^5.7",
|
"scheb/2fa-google-authenticator": "^5.7",
|
||||||
"scheb/2fa-qr-code": "^5.7",
|
"scheb/2fa-qr-code": "^5.7",
|
||||||
|
|
|
@ -57,8 +57,6 @@ class DateRangeAnalytic
|
||||||
$datas[$index] += $entity->getViews();
|
$datas[$index] += $entity->getViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
arsort($datas, SORT_NUMERIC);
|
|
||||||
|
|
||||||
return $datas;
|
return $datas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +71,29 @@ class DateRangeAnalytic
|
||||||
$index = $entity->getPath();
|
$index = $entity->getPath();
|
||||||
|
|
||||||
if (!isset($datas[$index])) {
|
if (!isset($datas[$index])) {
|
||||||
$datas[$index] = 0;
|
$datas[$index] = [
|
||||||
|
'views' => 0,
|
||||||
|
'desktopViews' => 0,
|
||||||
|
'mobileViews' => 0,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$datas[$index] += $entity->getViews();
|
$datas[$index]['views'] += $entity->getViews();
|
||||||
|
$datas[$index]['desktopViews'] += $entity->getDesktopViews();
|
||||||
|
$datas[$index]['mobileViews'] += $entity->getMobileViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
arsort($datas, SORT_NUMERIC);
|
uasort($datas, function($a, $b) {
|
||||||
|
if ($a['views'] > $b['views']) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($a['views'] < $b['views']) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
return $datas;
|
return $datas;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Referer implements EntityInterface
|
||||||
protected $id;
|
protected $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=Node::class, inversedBy="nodeViews")
|
* @ORM\ManyToOne(targetEntity=Node::class, inversedBy="analyticReferers")
|
||||||
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
||||||
*/
|
*/
|
||||||
protected $node;
|
protected $node;
|
||||||
|
|
|
@ -21,7 +21,7 @@ class View implements EntityInterface
|
||||||
protected $id;
|
protected $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=Node::class, inversedBy="nodeViews")
|
* @ORM\ManyToOne(targetEntity=Node::class, inversedBy="analyticViews")
|
||||||
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
||||||
*/
|
*/
|
||||||
protected $node;
|
protected $node;
|
||||||
|
@ -36,6 +36,16 @@ class View implements EntityInterface
|
||||||
*/
|
*/
|
||||||
protected $views = 0;
|
protected $views = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer", options={"default"=0})
|
||||||
|
*/
|
||||||
|
protected $desktopViews = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer", options={"default"=0})
|
||||||
|
*/
|
||||||
|
protected $mobileViews = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="date")
|
* @ORM\Column(type="date")
|
||||||
*/
|
*/
|
||||||
|
@ -89,6 +99,44 @@ class View implements EntityInterface
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDesktopViews(): ?int
|
||||||
|
{
|
||||||
|
return $this->desktopViews;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDesktopViews(int $desktopViews): self
|
||||||
|
{
|
||||||
|
$this->desktopViews = $desktopViews;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addDesktopView(): self
|
||||||
|
{
|
||||||
|
++$this->desktopViews;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMobileViews(): ?int
|
||||||
|
{
|
||||||
|
return $this->mobileViews;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMobileViews(int $mobileViews): self
|
||||||
|
{
|
||||||
|
$this->mobileViews = $mobileViews;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addMobileView(): self
|
||||||
|
{
|
||||||
|
++$this->mobileViews;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function getDate(): ?\DateTimeInterface
|
public function getDate(): ?\DateTimeInterface
|
||||||
{
|
{
|
||||||
return $this->date;
|
return $this->date;
|
||||||
|
|
|
@ -65,12 +65,12 @@ class Redirect implements EntityInterface
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean")
|
||||||
*/
|
*/
|
||||||
private $isEnabled;
|
protected $isEnabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean")
|
||||||
*/
|
*/
|
||||||
private $reuseQueryString;
|
protected $reuseQueryString;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,18 +2,19 @@
|
||||||
|
|
||||||
namespace App\Core\EventListener;
|
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;
|
use App\Core\Entity\EntityInterface;
|
||||||
use Jaybizzle\CrawlerDetect\CrawlerDetect;
|
use App\Core\Entity\Site\Node;
|
||||||
|
use App\Core\Factory\Analytic\RefererFactory;
|
||||||
|
use App\Core\Factory\Analytic\ViewFactory;
|
||||||
|
use App\Core\Manager\EntityManager;
|
||||||
|
use App\Core\Repository\Analytic\RefererRepositoryQuery;
|
||||||
|
use App\Core\Repository\Analytic\ViewRepositoryQuery;
|
||||||
|
use App\Core\Repository\Site\NodeRepository;
|
||||||
|
use DeviceDetector\Cache\PSR6Bridge;
|
||||||
|
use DeviceDetector\DeviceDetector;
|
||||||
|
use Symfony\Component\Cache\Adapter\ApcuAdapter;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class AnalyticListener.
|
* class AnalyticListener.
|
||||||
|
@ -28,7 +29,7 @@ class AnalyticListener
|
||||||
protected RefererRepositoryQuery $refererRepositoryQuery;
|
protected RefererRepositoryQuery $refererRepositoryQuery;
|
||||||
protected RefererFactory $refererFactory;
|
protected RefererFactory $refererFactory;
|
||||||
protected EntityManager $manager;
|
protected EntityManager $manager;
|
||||||
protected CrawlerDetect $crawlerDetect;
|
protected DeviceDetector $deviceDetector;
|
||||||
protected Request $request;
|
protected Request $request;
|
||||||
protected Node $node;
|
protected Node $node;
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ class AnalyticListener
|
||||||
$this->refererRepositoryQuery = $refererRepositoryQuery;
|
$this->refererRepositoryQuery = $refererRepositoryQuery;
|
||||||
$this->refererFactory = $refererFactory;
|
$this->refererFactory = $refererFactory;
|
||||||
$this->manager = $manager;
|
$this->manager = $manager;
|
||||||
$this->crawlerDetect = new CrawlerDetect();
|
$this->createDeviceDetector();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onKernelRequest(RequestEvent $event)
|
public function onKernelRequest(RequestEvent $event)
|
||||||
|
@ -57,7 +58,10 @@ class AnalyticListener
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->crawlerDetect->isCrawler($request->headers->get('user-agent'))) {
|
$this->deviceDetector->setUserAgent($request->headers->get('user-agent'));
|
||||||
|
$this->deviceDetector->parse();
|
||||||
|
|
||||||
|
if ($this->deviceDetector->isBot()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +81,14 @@ class AnalyticListener
|
||||||
$this->createReferer();
|
$this->createReferer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function createDeviceDetector()
|
||||||
|
{
|
||||||
|
$cache = new ApcuAdapter();
|
||||||
|
|
||||||
|
$this->deviceDetector = new DeviceDetector();
|
||||||
|
$this->deviceDetector->setCache(new PSR6Bridge($cache));
|
||||||
|
}
|
||||||
|
|
||||||
protected function createView()
|
protected function createView()
|
||||||
{
|
{
|
||||||
$entity = $this->viewRepositoryQuery->create()
|
$entity = $this->viewRepositoryQuery->create()
|
||||||
|
@ -90,6 +102,13 @@ class AnalyticListener
|
||||||
}
|
}
|
||||||
|
|
||||||
$entity->addView();
|
$entity->addView();
|
||||||
|
|
||||||
|
if ($this->deviceDetector->isDesktop()) {
|
||||||
|
$entity->addDesktopView();
|
||||||
|
} elseif ($this->deviceDetector->isMobile()) {
|
||||||
|
$entity->addMobileView();
|
||||||
|
}
|
||||||
|
|
||||||
$this->save($entity);
|
$this->save($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,18 +47,22 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ 'Path'|trans }}</th>
|
<th>{{ 'Path'|trans }}</th>
|
||||||
<th width="100" class="text-right">{{ 'Views'|trans }}</th>
|
<th width="50" class="text-right">{{ 'Views'|trans }}</th>
|
||||||
|
<th width="50" class="text-right"><span class="fa fa-desktop"></span></th>
|
||||||
|
<th width="50" class="text-right"><span class="fa fa-mobile-alt"></span></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for path, views in pathViews %}
|
{% for path, views in pathViews %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ path }}</td>
|
<td>{{ path }}</td>
|
||||||
<td class="text-right">{{ views }}</td>
|
<td class="text-right">{{ views.views }}</td>
|
||||||
|
<td class="text-right">{{ views.desktopViews }}</td>
|
||||||
|
<td class="text-right">{{ views.mobileViews }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="col-12 text-center p-4 text-black-50" colspan="2">
|
<td class="col-12 text-center p-4 text-black-50" colspan="4">
|
||||||
<div class="display-1">
|
<div class="display-1">
|
||||||
<span class="fa fa-search"></span>
|
<span class="fa fa-search"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -62,7 +62,7 @@ class RoutingExtension extends AbstractExtension
|
||||||
|
|
||||||
public function getNodePath(Node $node, array $parameters = [], bool $relative = false): ?string
|
public function getNodePath(Node $node, array $parameters = [], bool $relative = false): ?string
|
||||||
{
|
{
|
||||||
if ($node->hasExternalUrl()) {
|
if ($node->hasExternalUrl() || $node->hasAppUrl()) {
|
||||||
return $node->getUrl();
|
return $node->getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class RoutingExtension extends AbstractExtension
|
||||||
|
|
||||||
public function getNodeUrl(Node $node, array $parameters = [], bool $schemeRelative = false): ?string
|
public function getNodeUrl(Node $node, array $parameters = [], bool $schemeRelative = false): ?string
|
||||||
{
|
{
|
||||||
if ($node->hasExternalUrl()) {
|
if ($node->hasExternalUrl() || $node->hasAppUrl()) {
|
||||||
return $node->getUrl();
|
return $node->getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,9 +132,6 @@
|
||||||
"imagine/imagine": {
|
"imagine/imagine": {
|
||||||
"version": "1.2.4"
|
"version": "1.2.4"
|
||||||
},
|
},
|
||||||
"jaybizzle/crawler-detect": {
|
|
||||||
"version": "v1.2.110"
|
|
||||||
},
|
|
||||||
"khanamiryan/qrcode-detector-decoder": {
|
"khanamiryan/qrcode-detector-decoder": {
|
||||||
"version": "1.0.4"
|
"version": "1.0.4"
|
||||||
},
|
},
|
||||||
|
@ -172,12 +169,18 @@
|
||||||
"config/routes/liip_imagine.yaml"
|
"config/routes/liip_imagine.yaml"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"matomo/device-detector": {
|
||||||
|
"version": "5.0.4"
|
||||||
|
},
|
||||||
"michelf/php-markdown": {
|
"michelf/php-markdown": {
|
||||||
"version": "1.9.0"
|
"version": "1.9.0"
|
||||||
},
|
},
|
||||||
"monolog/monolog": {
|
"monolog/monolog": {
|
||||||
"version": "2.2.0"
|
"version": "2.2.0"
|
||||||
},
|
},
|
||||||
|
"mustangostang/spyc": {
|
||||||
|
"version": "0.6.3"
|
||||||
|
},
|
||||||
"myclabs/php-enum": {
|
"myclabs/php-enum": {
|
||||||
"version": "1.8.0"
|
"version": "1.8.0"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue