1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Actualys\Bundle\DrupalCommerceConnectorBundle\Manager; |
4
|
|
|
|
5
|
|
|
use PDO; |
6
|
|
|
use Doctrine\Common\Persistence\ObjectManager; |
7
|
|
|
use Doctrine\ORM\EntityManager; |
8
|
|
|
use Pim\Bundle\CatalogBundle\Model\AbstractProduct; |
9
|
|
|
use Akeneo\Bundle\BatchBundle\Entity\JobInstance; |
10
|
|
|
use Pim\Bundle\CatalogBundle\Repository\ReferableEntityRepositoryInterface; |
11
|
|
|
use PimEnterprise\Bundle\WorkflowBundle\Model\PublishedProduct; |
12
|
|
|
|
13
|
|
|
|
14
|
|
|
class ProductExportManager |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var boolean |
18
|
|
|
*/ |
19
|
|
|
protected $productValueDelta; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var EntityManager |
23
|
|
|
*/ |
24
|
|
|
protected $entityManager; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $productExportClass; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var EntityRepository |
33
|
|
|
*/ |
34
|
|
|
protected $productExportRepository; |
35
|
|
|
|
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var EntityRepository |
39
|
|
|
*/ |
40
|
|
|
protected $productRepository; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Constructor |
44
|
|
|
* |
45
|
|
|
* @param EntityManager $entityManager Entity manager for other entitites |
46
|
|
|
* @param string $productExportClass ProductExport class |
47
|
|
|
* @param string $productClass Product class |
48
|
|
|
* @param boolean $productValueDelta Should we do a delta on product values |
49
|
|
|
*/ |
50
|
|
|
public function __construct( |
51
|
|
|
EntityManager $entityManager, |
|
|
|
|
52
|
|
|
$productExportClass, |
53
|
|
|
$productClass, |
54
|
|
|
$productValueDelta = false |
55
|
|
|
) { |
56
|
|
|
$this->entityManager = $entityManager; |
57
|
|
|
$this->productExportClass = $productExportClass; |
58
|
|
|
$this->productExportRepository = $this->entityManager->getRepository($this->productExportClass); |
|
|
|
|
59
|
|
|
$this->productRepository = $this->entityManager->getRepository($productClass); |
|
|
|
|
60
|
|
|
$this->productValueDelta = $productValueDelta; |
61
|
|
|
} |
62
|
|
|
/** |
63
|
|
|
* Update product export dates for the given products |
64
|
|
|
* @param array $products |
65
|
|
|
* @param JobInstance $jobInstance |
66
|
|
|
*/ |
67
|
|
|
public function updateProductExports($products, JobInstance $jobInstance) |
68
|
|
|
{ |
69
|
|
|
foreach ($products as $product) { |
70
|
|
|
$this->updateProductExport($product->getIdentifier(), $jobInstance); |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Update product export date for the given product |
76
|
|
|
* @param string $identifier |
77
|
|
|
* @param JobInstance $jobInstance |
78
|
|
|
*/ |
79
|
|
|
public function updateProductExport($identifier, JobInstance $jobInstance) |
80
|
|
|
{ |
81
|
|
|
$now = new \DateTime('now', new \DateTimeZone('UTC')); |
82
|
|
|
$product = $this->productRepository->findByReference((string) $identifier); |
83
|
|
|
if (class_exists('\PimEnterprise\Bundle\WorkflowBundle\Model\PublishedProduct')) { |
84
|
|
|
if ($product instanceof \PimEnterprise\Bundle\WorkflowBundle\Model\PublishedProduct ) { |
|
|
|
|
85
|
|
|
/**@var \PimEnterprise\Bundle\WorkflowBundle\Model\PublishedProduct $product **/ |
86
|
|
|
$productId = $product->getOriginalProduct()->getId(); |
|
|
|
|
87
|
|
|
$product = $product->getOriginalProduct(); |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
if (null != $product) { |
92
|
|
|
$productExport = $this->productExportRepository->findOneBy(array( |
93
|
|
|
'product' => $product, |
94
|
|
|
'jobInstance' => $jobInstance |
95
|
|
|
)); |
96
|
|
|
|
97
|
|
|
$conn = $this->entityManager->getConnection(); |
98
|
|
|
|
99
|
|
|
$jobInstance->getId(); |
|
|
|
|
100
|
|
|
$product->getId(); |
101
|
|
|
|
102
|
|
|
|
103
|
|
|
if (null === $productExport) { |
104
|
|
|
$sql = ' |
105
|
|
|
INSERT INTO pim_delta_product_export |
106
|
|
|
(product_id, job_instance_id, date) |
107
|
|
|
VALUES (:product_id, :job_instance_id, :date) |
108
|
|
|
'; |
109
|
|
|
} else { |
110
|
|
|
$sql = ' |
111
|
|
|
UPDATE pim_delta_product_export |
112
|
|
|
SET date = :date |
113
|
|
|
WHERE product_id = :product_id AND job_instance_id = :job_instance_id |
114
|
|
|
'; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$q = $conn->prepare($sql); |
118
|
|
|
$date = $now->format('Y-m-d H:i:s'); |
119
|
|
|
$productId = $product->getId(); |
120
|
|
|
$jobInstanceId = $jobInstance->getId(); |
121
|
|
|
|
122
|
|
|
|
123
|
|
|
|
124
|
|
|
$q->bindParam(':date', $date, PDO::PARAM_STR); |
125
|
|
|
$q->bindParam(':product_id', $productId, PDO::PARAM_INT); |
126
|
|
|
$q->bindParam(':job_instance_id', $jobInstanceId, PDO::PARAM_INT); |
127
|
|
|
$q->execute(); |
128
|
|
|
} |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Filter products to export |
133
|
|
|
* @param array $products |
134
|
|
|
* @param JobInstance $jobInstance |
135
|
|
|
* |
136
|
|
|
* @return AbstractProduct |
137
|
|
|
*/ |
138
|
|
|
public function filterProducts($products, JobInstance $jobInstance) |
139
|
|
|
{ |
140
|
|
|
$productsToExport = array(); |
141
|
|
|
|
142
|
|
|
foreach ($products as $product) { |
143
|
|
|
$product = $this->filterProduct($product, $jobInstance); |
144
|
|
|
|
145
|
|
|
if (null !== $product) { |
146
|
|
|
$productsToExport[] = $product; |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
return $productsToExport; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Filter a product (return null if the product got exported after his last edit) |
155
|
|
|
* @param AbstractProduct $product |
156
|
|
|
* @param JobInstance $jobInstance |
157
|
|
|
* |
158
|
|
|
* @return AbstractProduct|null |
159
|
|
|
*/ |
160
|
|
|
public function filterProduct(AbstractProduct $product, JobInstance $jobInstance) |
161
|
|
|
{ |
162
|
|
|
if ($product instanceof \PimEnterprise\Bundle\WorkflowBundle\Model\PublishedProduct ) { |
|
|
|
|
163
|
|
|
/**@var \PimEnterprise\Bundle\WorkflowBundle\Model\PublishedProduct $product **/ |
164
|
|
|
$productExport = $this->productExportRepository->findProductExportAfterEdit( |
165
|
|
|
$product->getOriginalProduct(), |
166
|
|
|
$jobInstance, |
167
|
|
|
$product->getUpdated() |
168
|
|
|
); |
169
|
|
|
|
170
|
|
|
if (0 === count($productExport)) { |
171
|
|
|
if ($this->productValueDelta) { |
172
|
|
|
$product = $this->filterProductValues($product); |
173
|
|
|
} |
174
|
|
|
} else { |
175
|
|
|
$product = null; |
176
|
|
|
} |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
return $product; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Filter on product values |
184
|
|
|
* |
185
|
|
|
* @param AbstractProduct $product |
186
|
|
|
* |
187
|
|
|
* @return AbstractProduct |
188
|
|
|
*/ |
189
|
|
|
public function filterProductValues(AbstractProduct $product) |
190
|
|
|
{ |
191
|
|
|
$this->entityManager->detach($product); |
192
|
|
|
$productValues = $product->getValues(); |
193
|
|
|
$identifierType = $product->getIdentifier()->getAttribute()->getAttributeType(); |
194
|
|
|
|
195
|
|
|
foreach ($productValues as $productValue) { |
196
|
|
|
|
197
|
|
|
if ($identifierType != $productValue->getAttribute()->getAttributeType() && ( |
198
|
|
|
null == $productValue->getUpdated() || ( |
199
|
|
|
null != $productValue->getUpdated() && |
200
|
|
|
$product->getUpdated()->getTimestamp() - $productValue->getUpdated()->getTimestamp() > 60 |
201
|
|
|
) |
202
|
|
|
) |
203
|
|
|
) { |
204
|
|
|
$product->removeValue($productValue); |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
return $product; |
209
|
|
|
} |
210
|
|
|
} |
211
|
|
|
|
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.