|
|
@@ -0,0 +1,244 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace Opentalent\OtStats\Domain\Repository;
|
|
|
+
|
|
|
+use Opentalent\OtCore\Page\OtPageRepository;
|
|
|
+use Opentalent\OtStats\Domain\Model\MatomoWebsite;
|
|
|
+use PDO;
|
|
|
+use TYPO3\CMS\Core\Database\ConnectionPool;
|
|
|
+use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
|
+use TYPO3\CMS\Extbase\Persistence\Repository;
|
|
|
+
|
|
|
+class MatomoWebsiteRepository
|
|
|
+{
|
|
|
+ const MATOMO_DB_HOST = 'tools';
|
|
|
+ const MATOMO_DB_NAME = 'matomo';
|
|
|
+ const MATOMO_DB_USER = 'root';
|
|
|
+ const MATOMO_DB_PWD = 'mysql2iopenservice369566';
|
|
|
+
|
|
|
+ const DOMAIN_VALIDATION = '/^(https?:\/\/)?([a-zA-Z0-9]+\.)+[a-zA-Z]{2,}$/';
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Connection to the matomo DB
|
|
|
+ *
|
|
|
+ * @var PDO
|
|
|
+ */
|
|
|
+ private $matomoCnn;
|
|
|
+
|
|
|
+ public function __construct()
|
|
|
+ {
|
|
|
+ // Connection to the Matomo DB
|
|
|
+ $this->matomoCnn = new PDO(
|
|
|
+ "mysql:host=" . self::MATOMO_DB_HOST . ";dbname=" . self::MATOMO_DB_NAME,
|
|
|
+ self::MATOMO_DB_USER,
|
|
|
+ self::MATOMO_DB_PWD,
|
|
|
+ array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')
|
|
|
+ );
|
|
|
+ $this->matomoCnn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create a new MatomoWebsite from an array
|
|
|
+ *
|
|
|
+ * @param array $data
|
|
|
+ * @return MatomoWebsite
|
|
|
+ */
|
|
|
+ private function fromArray(array $data) {
|
|
|
+ $matomoSite = new MatomoWebsite();
|
|
|
+ $matomoSite->setId($data['idsite']);
|
|
|
+ $matomoSite->setName($data['name']);
|
|
|
+ $matomoSite->setMainUrl($data['main_url']);
|
|
|
+ $matomoSite->setExcludedIps($data['exluded_ips']);
|
|
|
+ $matomoSite->setType($data['type']);
|
|
|
+ $matomoSite->setCreatorLogin($data['creator_login']);
|
|
|
+ return $matomoSite;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retrieve the MatomoWebsite object by id, otherwise, returns Null
|
|
|
+ *
|
|
|
+ * @param int $id
|
|
|
+ * @return MatomoWebsite|null
|
|
|
+ */
|
|
|
+ public function findById(int $id) {
|
|
|
+ $stmt = $this->matomoCnn->prepare(
|
|
|
+ "SELECT s.idsite, s.name, s.main_url, s.excluded_ips, s.type, s.creator_login
|
|
|
+ FROM matomo.matomo_site s
|
|
|
+ WHERE s.idsite=" . $id . ";"
|
|
|
+ );
|
|
|
+ $stmt->execute();
|
|
|
+ $stmt->setFetchMode(PDO::FETCH_ASSOC);
|
|
|
+ $data = $stmt->fetch();
|
|
|
+ if (!$data) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return $this->fromArray($data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retrieve the MatomoWebsite object by uri, otherwise, returns Null
|
|
|
+ *
|
|
|
+ * @param string $uri
|
|
|
+ * @return MatomoWebsite|null
|
|
|
+ */
|
|
|
+ public function findByUri(string $uri) {
|
|
|
+ $stmt = $this->matomoCnn->prepare(
|
|
|
+ "SELECT s.idsite, s.name, s.main_url, s.excluded_ips, s.type, s.creator_login
|
|
|
+ FROM matomo.matomo_site s
|
|
|
+ WHERE s.main_url='" . $uri . "';"
|
|
|
+ );
|
|
|
+ $stmt->execute();
|
|
|
+ $stmt->setFetchMode(PDO::FETCH_ASSOC);
|
|
|
+ $data = $stmt->fetch();
|
|
|
+ if (!$data) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return $this->fromArray($data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retrieve the MatomoWebsite object for the typo3 website with
|
|
|
+ * the given rootUid, otherwise, returns Null
|
|
|
+ *
|
|
|
+ * @param int $rootUid
|
|
|
+ * @return MatomoWebsite|null
|
|
|
+ */
|
|
|
+ public function findByRootUid(int $rootUid) {
|
|
|
+ $otPageRepository = GeneralUtility::makeInstance(OtPageRepository::class);
|
|
|
+
|
|
|
+ // Just to make sure this page is actually the root page
|
|
|
+ $rootPage = $otPageRepository->getRootPageFor($rootUid);
|
|
|
+
|
|
|
+ if ($rootPage['tx_opentalent_matomo_id'] == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return $this->findById($rootPage['tx_opentalent_matomo_id']);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create a new matomo's website for the Typo3 site (or retrieve the existing if any),
|
|
|
+ * store its id in the Typo3 DB and return it
|
|
|
+ *
|
|
|
+ * @param int $rootUid
|
|
|
+ * @return int|string The matomo site's id
|
|
|
+ * @throws \Exception
|
|
|
+ */
|
|
|
+ public function createFor(int $rootUid) {
|
|
|
+ $otPageRepository = GeneralUtility::makeInstance(OtPageRepository::class);
|
|
|
+
|
|
|
+ // Just to make sure this page is actually the root page
|
|
|
+ $rootPage = $otPageRepository->getRootPageFor($rootUid);
|
|
|
+ $rootUid = $rootPage['uid'];
|
|
|
+
|
|
|
+ // Retrieve current site informations
|
|
|
+ $site = $otPageRepository->getSiteFor($rootUid);
|
|
|
+ $title = $site->getIdentifier();
|
|
|
+ $uri = $site->getConfiguration()['base'];
|
|
|
+ if (!preg_match(self::DOMAIN_VALIDATION, $uri)) {
|
|
|
+ throw new \RuntimeException("The domain's name is not valid: " . $uri);
|
|
|
+ }
|
|
|
+ if (!preg_match('/https?:\/\//', $uri)) {
|
|
|
+ $uri = 'https://' . $uri;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Make sure the current typo3 website has no existing configured matomo website
|
|
|
+ if ($rootPage['tx_opentalent_matomo_id'] != null) {
|
|
|
+ // Check if the registered matomo site still exist. If it does, throw an error.
|
|
|
+ if ($this->findById($rootPage['tx_opentalent_matomo_id']) != null) {
|
|
|
+ throw new \RuntimeException('This website has already been registered (matomo id: ' . $rootPage['tx_opentalent_matomo_id'] . ')');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if there is already an existing matomo record for this url
|
|
|
+ $existingMatomoSite = $this->findByUri($uri);
|
|
|
+ if ($existingMatomoSite) {
|
|
|
+ // Verify that the names match (just to be sure)
|
|
|
+ if (!$existingMatomoSite->getName() != $title) {
|
|
|
+ throw new \RuntimeException('A website with this URL has already been registered: ' . $uri);
|
|
|
+ }
|
|
|
+ $matomoSiteId = $existingMatomoSite->getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set up a connection to the typo3 DB
|
|
|
+ $cnnPool = GeneralUtility::makeInstance(ConnectionPool::class);
|
|
|
+
|
|
|
+ // Create a new website record in the matomo DB, and store its id
|
|
|
+ $this->matomoCnn->beginTransaction();
|
|
|
+ $cnnPool->getConnectionByName('Default')->beginTransaction();
|
|
|
+ try {
|
|
|
+
|
|
|
+ if ($existingMatomoSite == null) {
|
|
|
+ // Create the new website
|
|
|
+ $stmt = $this->matomoCnn->prepare(
|
|
|
+ "INSERT INTO matomo.matomo_site
|
|
|
+ (`name`, main_url, ts_created, ecommerce, sitesearch, sitesearch_keyword_parameters,
|
|
|
+ sitesearch_category_parameters, timezone,
|
|
|
+ currency, excluded_ips, excluded_parameters, excluded_user_agents, `group`, `type`, creator_login)
|
|
|
+ VALUES ('" . $title . "', '" . $uri . "', NOW(), 0, 1, '', '', 'Europe/Paris',
|
|
|
+ 'EUR', '10.8.0.*', '', '', '', 'website', 'typo3');");
|
|
|
+ $stmt->execute();
|
|
|
+
|
|
|
+ // Get the new site's id
|
|
|
+ $matomoSiteId = $this->matomoCnn->lastInsertId();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update typo3 DB
|
|
|
+ $queryBuilder = $cnnPool->getQueryBuilderForTable('pages');
|
|
|
+ $queryBuilder
|
|
|
+ ->update('pages')
|
|
|
+ ->where($queryBuilder->expr()->eq('uid', $rootUid))
|
|
|
+ ->set('tx_opentalent_matomo_id', $matomoSiteId)
|
|
|
+ ->execute();
|
|
|
+
|
|
|
+ // finalize
|
|
|
+ $this->matomoCnn->commit();
|
|
|
+ $cnnPool->getConnectionByName('Default')->commit();
|
|
|
+
|
|
|
+ return $matomoSiteId;
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // An error happened, rollback and throw
|
|
|
+ $this->matomoCnn->rollBack();
|
|
|
+ $cnnPool->getConnectionByName('Default')->rollback();
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Disable the matomo monitoring for the website
|
|
|
+ * > Data wont be deleted from the matomo DB, but no more data will
|
|
|
+ * be collected unless it is reactivated with the 'createFor' method
|
|
|
+ *
|
|
|
+ * @param int $rootUid
|
|
|
+ * @throws \Exception
|
|
|
+ */
|
|
|
+ public function disableFor(int $rootUid) {
|
|
|
+ $matomoSite = $this->findByRootUid($rootUid);
|
|
|
+ if ($matomoSite == null) {
|
|
|
+ throw new \RuntimeException('Activity monitoring is already disabled for this website');
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set up a connection to the typo3 DB
|
|
|
+ $cnnPool = GeneralUtility::makeInstance(ConnectionPool::class);
|
|
|
+ $cnnPool->getConnectionByName('Default')->beginTransaction();
|
|
|
+ try {
|
|
|
+ // Update typo3 DB
|
|
|
+ $queryBuilder = $cnnPool->getQueryBuilderForTable('pages');
|
|
|
+ $queryBuilder
|
|
|
+ ->update('pages')
|
|
|
+ ->where($queryBuilder->expr()->eq('uid', $rootUid))
|
|
|
+ ->set('tx_opentalent_matomo_id', null)
|
|
|
+ ->execute();
|
|
|
+
|
|
|
+ // finalize
|
|
|
+ $cnnPool->getConnectionByName('Default')->commit();
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // An error happened, rollback and throw
|
|
|
+ $cnnPool->getConnectionByName('Default')->rollback();
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|