diff --git a/Api/Data/ReportInterface.php b/Api/Data/ReportInterface.php
index 865747a..23e378f 100644
--- a/Api/Data/ReportInterface.php
+++ b/Api/Data/ReportInterface.php
@@ -9,7 +9,6 @@
interface ReportInterface extends \Magento\Framework\Api\ExtensibleDataInterface
{
-
const VIOLATED_DIRECTIVE = 'violated_directive';
const REPORT_ID = 'report_id';
const DOCUMENT_URI = 'document_uri';
@@ -17,6 +16,7 @@ interface ReportInterface extends \Magento\Framework\Api\ExtensibleDataInterface
const ORIGINAL_POLICY = 'original_policy';
const DATE = 'date';
const BLOCKED_URI = 'blocked_uri';
+ const COUNT = 'count';
/**
* Get report_id
@@ -124,5 +124,17 @@ public function getDate();
*/
public function setDate($date);
+ /**
+ * Get Count
+ * @return string|null
+ */
+ public function getCount();
+
+ /**
+ * @param $count
+ * @return \Experius\Csp\Api\Data\ReportInterface
+ */
+ public function setCount($count);
+
}
diff --git a/Model/Data/Report.php b/Model/Data/Report.php
index ee47d4a..b7b8f33 100644
--- a/Model/Data/Report.php
+++ b/Model/Data/Report.php
@@ -165,5 +165,24 @@ public function setDate($date)
return $this->setData(self::DATE, $date);
}
+ /**
+ * Get count
+ * @return string|null
+ */
+ public function getCount()
+ {
+ return $this->_get(self::COUNT);
+ }
+
+ /**
+ * Set count
+ * @param string $count
+ * @return \Experius\Csp\Api\Data\ReportInterface
+ */
+ public function setCount($count)
+ {
+ return $this->setData(self::COUNT, $count);
+ }
+
}
diff --git a/Model/ReportRepository.php b/Model/ReportRepository.php
index 944ffb1..908c9cf 100644
--- a/Model/ReportRepository.php
+++ b/Model/ReportRepository.php
@@ -7,6 +7,7 @@
namespace Experius\Csp\Model;
+use Experius\Csp\Api\Data\ReportInterface;
use Experius\Csp\Api\Data\ReportInterfaceFactory;
use Experius\Csp\Api\Data\ReportSearchResultsInterfaceFactory;
use Experius\Csp\Api\ReportRepositoryInterface;
@@ -16,11 +17,13 @@
use Magento\Framework\Api\ExtensibleDataObjectConverter;
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
+use Magento\Framework\Exception\AbstractAggregateException;
use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Reflection\DataObjectProcessor;
use Magento\Store\Model\StoreManagerInterface;
+use Magento\Framework\Api\SearchCriteriaBuilder;
class ReportRepository implements ReportRepositoryInterface
{
@@ -46,8 +49,10 @@ class ReportRepository implements ReportRepositoryInterface
private $collectionProcessor;
+ protected $searchCriteriaBuilder;
/**
+ * ReportRepository constructor.
* @param ResourceReport $resource
* @param ReportFactory $reportFactory
* @param ReportInterfaceFactory $dataReportFactory
@@ -59,6 +64,7 @@ class ReportRepository implements ReportRepositoryInterface
* @param CollectionProcessorInterface $collectionProcessor
* @param JoinProcessorInterface $extensionAttributesJoinProcessor
* @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
+ * @param SearchCriteriaBuilder $searchCriteriaBuilder
*/
public function __construct(
ResourceReport $resource,
@@ -71,7 +77,8 @@ public function __construct(
StoreManagerInterface $storeManager,
CollectionProcessorInterface $collectionProcessor,
JoinProcessorInterface $extensionAttributesJoinProcessor,
- ExtensibleDataObjectConverter $extensibleDataObjectConverter
+ ExtensibleDataObjectConverter $extensibleDataObjectConverter,
+ SearchCriteriaBuilder $searchCriteriaBuilder
) {
$this->resource = $resource;
$this->reportFactory = $reportFactory;
@@ -84,36 +91,40 @@ public function __construct(
$this->collectionProcessor = $collectionProcessor;
$this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
$this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
+ $this->searchCriteriaBuilder = $searchCriteriaBuilder;
}
/**
* {@inheritdoc}
*/
public function save(
- \Experius\Csp\Api\Data\ReportInterface $report
+ ReportInterface $report
) {
- /* if (empty($report->getStoreId())) {
- $storeId = $this->storeManager->getStore()->getId();
- $report->setStoreId($storeId);
- } */
-
- $reportData = $this->extensibleDataObjectConverter->toNestedArray(
- $report,
- [],
- \Experius\Csp\Api\Data\ReportInterface::class
- );
-
- $reportModel = $this->reportFactory->create()->setData($reportData);
-
- try {
- $this->resource->save($reportModel);
- } catch (\Exception $exception) {
- throw new CouldNotSaveException(__(
- 'Could not save the report: %1',
- $exception->getMessage()
- ));
+ // @TODO: [Should have] Move detection if already exists outside of the save() function
+ // @TODO: [Nice to have] Find the reason csp reports are sent directly at the same time, to prevent having to
+ // to use the usleep() mechanic to de-synchronise saving.
+
+ // Sleep for a random millisecond to prevent double saves
+ $sleep = rand(1000, 1000000);
+ usleep($sleep);
+ $existingReport = $this->doesReportExistAlready($report);
+
+ if(!$existingReport) {
+ try {
+ $report = $this->resource->save($this->createReportModel($report));
+ } catch (\Exception $exception) {
+ throw new CouldNotSaveException(__(
+ 'Could not save the report: %1',
+ $exception->getMessage()
+ ));
+ }
+ return $report;
+ } else {
+ $existingReport->setCount($existingReport->getCount() + 1);
+ $existingReport = $this->resource->save($this->createReportModel($existingReport));
+
+ return $existingReport;
}
- return $reportModel->getDataModel();
}
/**
@@ -139,7 +150,7 @@ public function getList(
$this->extensionAttributesJoinProcessor->process(
$collection,
- \Experius\Csp\Api\Data\ReportInterface::class
+ ReportInterface::class
);
$this->collectionProcessor->process($criteria, $collection);
@@ -161,7 +172,7 @@ public function getList(
* {@inheritdoc}
*/
public function delete(
- \Experius\Csp\Api\Data\ReportInterface $report
+ ReportInterface $report
) {
try {
$reportModel = $this->reportFactory->create();
@@ -183,5 +194,45 @@ public function deleteById($reportId)
{
return $this->delete($this->get($reportId));
}
+
+ /**
+ * Does report exist already?
+ *
+ * @param $report
+ * @return ReportInterface|false
+ */
+ public function doesReportExistAlready($report)
+ {
+ if (!$report || $report instanceof ReportInterface == false) {
+ return false;
+ }
+
+ $searchCriteria = $this->searchCriteriaBuilder
+ ->addFilter(ReportInterface::VIOLATED_DIRECTIVE, $report->getViolatedDirective())
+ ->addFilter(ReportInterface::BLOCKED_URI, $report->getBlockedUri())
+ ->addFilter(ReportInterface::DOCUMENT_URI, $report->getDocumentUri())
+ ->create();
+
+ if ($this->getList($searchCriteria)->getTotalCount() < 1) {
+ return false;
+ }
+
+ // Return first match if found
+ foreach ($this->getList($searchCriteria)->getItems() as $item) {
+ return $item;
+ }
+ return false;
+ }
+
+ public function createReportModel($report)
+ {
+ $reportData = $this->extensibleDataObjectConverter->toNestedArray(
+ $report,
+ [],
+ ReportInterface::class
+ );
+
+ return $this->reportFactory->create()->setData($reportData);
+ }
}
diff --git a/etc/db_schema.xml b/etc/db_schema.xml
index 1405c0f..1749f75 100644
--- a/etc/db_schema.xml
+++ b/etc/db_schema.xml
@@ -23,5 +23,6 @@
+