1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Kunstmaan\NodeBundle\Helper\NodeAdmin; |
4
|
|
|
|
5
|
|
|
use Doctrine\ORM\EntityManager; |
6
|
|
|
use Kunstmaan\AdminBundle\Entity\BaseUser; |
7
|
|
|
use Kunstmaan\AdminBundle\Helper\CloneHelper; |
8
|
|
|
use Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionMap; |
9
|
|
|
use Kunstmaan\NodeBundle\Entity\HasNodeInterface; |
10
|
|
|
use Kunstmaan\NodeBundle\Entity\Node; |
11
|
|
|
use Kunstmaan\NodeBundle\Entity\NodeTranslation; |
12
|
|
|
use Kunstmaan\NodeBundle\Entity\NodeVersion; |
13
|
|
|
use Kunstmaan\NodeBundle\Entity\QueuedNodeTranslationAction; |
14
|
|
|
use Kunstmaan\NodeBundle\Event\Events; |
15
|
|
|
use Kunstmaan\NodeBundle\Event\NodeEvent; |
16
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
17
|
|
|
use Symfony\Component\HttpFoundation\Request; |
18
|
|
|
use Symfony\Component\HttpFoundation\Session\Session; |
19
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; |
20
|
|
|
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; |
21
|
|
|
use Symfony\Component\Security\Core\Exception\AccessDeniedException; |
22
|
|
|
use Symfony\Component\Translation\TranslatorInterface; |
23
|
|
|
use Kunstmaan\AdminBundle\FlashMessages\FlashTypes; |
24
|
|
|
|
25
|
|
|
class NodeAdminPublisher |
26
|
|
|
{ |
27
|
|
|
/** |
28
|
|
|
* @var EntityManager |
29
|
|
|
*/ |
30
|
|
|
private $em; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var TokenStorageInterface |
34
|
|
|
*/ |
35
|
|
|
private $tokenStorage; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var AuthorizationCheckerInterface |
39
|
|
|
*/ |
40
|
|
|
private $authorizationChecker; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @var EventDispatcherInterface |
44
|
|
|
*/ |
45
|
|
|
private $eventDispatcher; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var CloneHelper |
49
|
|
|
*/ |
50
|
|
|
private $cloneHelper; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param EntityManager $em The entity manager |
54
|
|
|
* @param TokenStorageInterface $tokenStorage The security token storage |
55
|
|
|
* @param AuthorizationCheckerInterface $authorizationChecker The security authorization checker |
56
|
|
|
* @param EventDispatcherInterface $eventDispatcher The Event dispatcher |
57
|
|
|
* @param CloneHelper $cloneHelper The clone helper |
58
|
|
|
*/ |
59
|
|
|
public function __construct( |
60
|
|
|
EntityManager $em, |
|
|
|
|
61
|
|
|
TokenStorageInterface $tokenStorage, |
62
|
|
|
AuthorizationCheckerInterface $authorizationChecker, |
63
|
|
|
EventDispatcherInterface $eventDispatcher, |
64
|
|
|
CloneHelper $cloneHelper |
65
|
|
|
) { |
66
|
|
|
$this->em = $em; |
67
|
|
|
$this->tokenStorage = $tokenStorage; |
68
|
|
|
$this->authorizationChecker = $authorizationChecker; |
69
|
|
|
$this->eventDispatcher = $eventDispatcher; |
70
|
|
|
$this->cloneHelper = $cloneHelper; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* If there is a draft version it'll try to publish the draft first. Makse snese because if you want to publish the public version you don't publish but you save. |
75
|
|
|
* |
76
|
|
|
* @param NodeTranslation $nodeTranslation |
77
|
|
|
* @param null|BaseUser $user |
78
|
|
|
* |
79
|
|
|
* @throws AccessDeniedException |
80
|
|
|
*/ |
81
|
|
|
public function publish(NodeTranslation $nodeTranslation, $user = null) |
82
|
|
|
{ |
83
|
|
|
if (false === $this->authorizationChecker->isGranted(PermissionMap::PERMISSION_PUBLISH,$nodeTranslation->getNode())) { |
84
|
|
|
throw new AccessDeniedException(); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if (is_null($user)) { |
88
|
|
|
$user = $this->tokenStorage->getToken()->getUser(); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
$node = $nodeTranslation->getNode(); |
92
|
|
|
|
93
|
|
|
$nodeVersion = $nodeTranslation->getNodeVersion('draft'); |
94
|
|
|
if (!is_null($nodeVersion)) { |
95
|
|
|
$page = $nodeVersion->getRef($this->em); |
96
|
|
|
/** @var $nodeVersion NodeVersion */ |
97
|
|
|
$nodeVersion = $this->createPublicVersion($page, $nodeTranslation, $nodeVersion, $user); |
|
|
|
|
98
|
|
|
$nodeTranslation = $nodeVersion->getNodeTranslation(); |
99
|
|
|
} else { |
100
|
|
|
$nodeVersion = $nodeTranslation->getPublicNodeVersion(); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
$page = $nodeVersion->getRef($this->em); |
104
|
|
|
|
105
|
|
|
$this->eventDispatcher->dispatch( |
106
|
|
|
Events::PRE_PUBLISH, |
107
|
|
|
new NodeEvent($node, $nodeTranslation, $nodeVersion, $page) |
|
|
|
|
108
|
|
|
); |
109
|
|
|
$nodeTranslation |
110
|
|
|
->setOnline(true) |
111
|
|
|
->setPublicNodeVersion($nodeVersion) |
112
|
|
|
->setUpdated(new \DateTime()); |
113
|
|
|
$this->em->persist($nodeTranslation); |
114
|
|
|
$this->em->flush(); |
115
|
|
|
|
116
|
|
|
// Remove scheduled task |
117
|
|
|
$this->unSchedulePublish($nodeTranslation); |
118
|
|
|
|
119
|
|
|
$this->eventDispatcher->dispatch( |
120
|
|
|
Events::POST_PUBLISH, |
121
|
|
|
new NodeEvent($node, $nodeTranslation, $nodeVersion, $page) |
|
|
|
|
122
|
|
|
); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @param NodeTranslation $nodeTranslation The NodeTranslation |
127
|
|
|
* @param \DateTime $date The date to publish |
128
|
|
|
* |
129
|
|
|
* @throws AccessDeniedException |
130
|
|
|
*/ |
131
|
|
View Code Duplication |
public function publishLater(NodeTranslation $nodeTranslation, \DateTime $date) |
|
|
|
|
132
|
|
|
{ |
133
|
|
|
$node = $nodeTranslation->getNode(); |
134
|
|
|
if (false === $this->authorizationChecker->isGranted(PermissionMap::PERMISSION_PUBLISH, $node)) { |
135
|
|
|
throw new AccessDeniedException(); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
//remove existing first |
139
|
|
|
$this->unSchedulePublish($nodeTranslation); |
140
|
|
|
|
141
|
|
|
$user = $this->tokenStorage->getToken()->getUser(); |
142
|
|
|
$queuedNodeTranslationAction = new QueuedNodeTranslationAction(); |
143
|
|
|
$queuedNodeTranslationAction |
144
|
|
|
->setNodeTranslation($nodeTranslation) |
145
|
|
|
->setAction(QueuedNodeTranslationAction::ACTION_PUBLISH) |
146
|
|
|
->setUser($user) |
147
|
|
|
->setDate($date); |
148
|
|
|
$this->em->persist($queuedNodeTranslationAction); |
149
|
|
|
$this->em->flush(); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* @param NodeTranslation $nodeTranslation |
154
|
|
|
* |
155
|
|
|
* @throws AccessDeniedException |
156
|
|
|
*/ |
157
|
|
|
public function unPublish(NodeTranslation $nodeTranslation) |
158
|
|
|
{ |
159
|
|
|
if (false === $this->authorizationChecker->isGranted(PermissionMap::PERMISSION_UNPUBLISH,$nodeTranslation->getNode())) { |
160
|
|
|
throw new AccessDeniedException(); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
$node = $nodeTranslation->getNode(); |
164
|
|
|
$nodeVersion = $nodeTranslation->getPublicNodeVersion(); |
165
|
|
|
$page = $nodeVersion->getRef($this->em); |
166
|
|
|
|
167
|
|
|
$this->eventDispatcher->dispatch( |
168
|
|
|
Events::PRE_UNPUBLISH, |
169
|
|
|
new NodeEvent($node, $nodeTranslation, $nodeVersion, $page) |
|
|
|
|
170
|
|
|
); |
171
|
|
|
$nodeTranslation->setOnline(false); |
172
|
|
|
$this->em->persist($nodeTranslation); |
173
|
|
|
$this->em->flush(); |
174
|
|
|
|
175
|
|
|
// Remove scheduled task |
176
|
|
|
$this->unSchedulePublish($nodeTranslation); |
177
|
|
|
|
178
|
|
|
$this->eventDispatcher->dispatch( |
179
|
|
|
Events::POST_UNPUBLISH, |
180
|
|
|
new NodeEvent($node, $nodeTranslation, $nodeVersion, $page) |
|
|
|
|
181
|
|
|
); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* @param NodeTranslation $nodeTranslation The NodeTranslation |
186
|
|
|
* @param \DateTime $date The date to unpublish |
187
|
|
|
* |
188
|
|
|
* @throws AccessDeniedException |
189
|
|
|
*/ |
190
|
|
View Code Duplication |
public function unPublishLater(NodeTranslation $nodeTranslation, \DateTime $date) |
|
|
|
|
191
|
|
|
{ |
192
|
|
|
$node = $nodeTranslation->getNode(); |
193
|
|
|
if (false === $this->authorizationChecker->isGranted(PermissionMap::PERMISSION_UNPUBLISH, $node)) { |
194
|
|
|
throw new AccessDeniedException(); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
//remove existing first |
198
|
|
|
$this->unSchedulePublish($nodeTranslation); |
199
|
|
|
$user = $this->tokenStorage->getToken()->getUser(); |
200
|
|
|
$queuedNodeTranslationAction = new QueuedNodeTranslationAction(); |
201
|
|
|
$queuedNodeTranslationAction |
202
|
|
|
->setNodeTranslation($nodeTranslation) |
203
|
|
|
->setAction(QueuedNodeTranslationAction::ACTION_UNPUBLISH) |
204
|
|
|
->setUser($user) |
205
|
|
|
->setDate($date); |
206
|
|
|
$this->em->persist($queuedNodeTranslationAction); |
207
|
|
|
$this->em->flush(); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @param NodeTranslation $nodeTranslation |
212
|
|
|
*/ |
213
|
|
|
public function unSchedulePublish(NodeTranslation $nodeTranslation) |
214
|
|
|
{ |
215
|
|
|
/* @var Node $node */ |
216
|
|
|
$queuedNodeTranslationAction = $this->em->getRepository('KunstmaanNodeBundle:QueuedNodeTranslationAction') |
217
|
|
|
->findOneBy(array('nodeTranslation' => $nodeTranslation)); |
218
|
|
|
|
219
|
|
|
if (!is_null($queuedNodeTranslationAction)) { |
220
|
|
|
$this->em->remove($queuedNodeTranslationAction); |
221
|
|
|
$this->em->flush(); |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* This shouldn't be here either but it's an improvement. |
227
|
|
|
* |
228
|
|
|
* @param HasNodeInterface $page The page |
229
|
|
|
* @param NodeTranslation $nodeTranslation The node translation |
230
|
|
|
* @param NodeVersion $nodeVersion The node version |
231
|
|
|
* @param BaseUser $user The user |
232
|
|
|
* |
233
|
|
|
* @return mixed |
234
|
|
|
*/ |
235
|
|
|
public function createPublicVersion( |
236
|
|
|
HasNodeInterface $page, |
237
|
|
|
NodeTranslation $nodeTranslation, |
238
|
|
|
NodeVersion $nodeVersion, |
239
|
|
|
BaseUser $user |
240
|
|
|
) { |
241
|
|
|
$newPublicPage = $this->cloneHelper->deepCloneAndSave($page); |
242
|
|
|
$newNodeVersion = $this->em->getRepository('KunstmaanNodeBundle:NodeVersion')->createNodeVersionFor( |
243
|
|
|
$newPublicPage, |
244
|
|
|
$nodeTranslation, |
245
|
|
|
$user, |
246
|
|
|
$nodeVersion |
247
|
|
|
); |
248
|
|
|
|
249
|
|
|
$newNodeVersion |
250
|
|
|
->setOwner($nodeVersion->getOwner()) |
251
|
|
|
->setUpdated($nodeVersion->getUpdated()) |
252
|
|
|
->setCreated($nodeVersion->getCreated()); |
253
|
|
|
|
254
|
|
|
$nodeVersion |
255
|
|
|
->setOwner($user) |
256
|
|
|
->setCreated(new \DateTime()) |
257
|
|
|
->setOrigin($newNodeVersion); |
258
|
|
|
|
259
|
|
|
$this->em->persist($newNodeVersion); |
260
|
|
|
$this->em->persist($nodeVersion); |
261
|
|
|
$this->em->persist($nodeTranslation); |
262
|
|
|
$this->em->flush(); |
263
|
|
|
$this->eventDispatcher->dispatch( |
264
|
|
|
Events::CREATE_PUBLIC_VERSION, |
265
|
|
|
new NodeEvent($nodeTranslation->getNode(), $nodeTranslation, $nodeVersion, $newPublicPage) |
266
|
|
|
); |
267
|
|
|
|
268
|
|
|
return $newNodeVersion; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/** |
272
|
|
|
* @param Request $request |
273
|
|
|
* @param NodeTranslation $nodeTranslation |
274
|
|
|
*/ |
275
|
|
View Code Duplication |
public function chooseHowToPublish(Request $request, NodeTranslation $nodeTranslation, TranslatorInterface $translator) |
|
|
|
|
276
|
|
|
{ |
277
|
|
|
/** @var Session $session */ |
278
|
|
|
$session = $request->getSession(); |
279
|
|
|
|
280
|
|
|
if ($request->request->has('publish_later') && $request->get('pub_date')) { |
281
|
|
|
$date = new \DateTime( |
282
|
|
|
$request->get('pub_date') . ' ' . $request->get('pub_time') |
283
|
|
|
); |
284
|
|
|
$this->publishLater($nodeTranslation, $date); |
285
|
|
|
$session->getFlashBag()->add( |
286
|
|
|
FlashTypes::SUCCESS, |
287
|
|
|
$translator->trans('kuma_node.admin.publish.flash.success_scheduled') |
288
|
|
|
); |
289
|
|
|
} else { |
290
|
|
|
$this->publish($nodeTranslation); |
291
|
|
|
$session->getFlashBag()->add( |
292
|
|
|
FlashTypes::SUCCESS, |
293
|
|
|
$translator->trans('kuma_node.admin.publish.flash.success_published') |
294
|
|
|
); |
295
|
|
|
} |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* @param Request $request |
300
|
|
|
* @param NodeTranslation $nodeTranslation |
301
|
|
|
*/ |
302
|
|
View Code Duplication |
public function chooseHowToUnpublish(Request $request, NodeTranslation $nodeTranslation, TranslatorInterface $translator) |
|
|
|
|
303
|
|
|
{ |
304
|
|
|
/** @var Session $session */ |
305
|
|
|
$session = $request->getSession(); |
306
|
|
|
|
307
|
|
|
if ($request->request->has('unpublish_later') && $request->get('unpub_date')) { |
308
|
|
|
$date = new \DateTime($request->get('unpub_date') . ' ' . $request->get('unpub_time')); |
309
|
|
|
$this->unPublishLater($nodeTranslation, $date); |
310
|
|
|
$session->getFlashBag()->add( |
311
|
|
|
FlashTypes::SUCCESS, |
312
|
|
|
$translator->trans('kuma_node.admin.unpublish.flash.success_scheduled') |
313
|
|
|
); |
314
|
|
|
} else { |
315
|
|
|
$this->unPublish($nodeTranslation); |
316
|
|
|
$session->getFlashBag()->add( |
317
|
|
|
FlashTypes::SUCCESS, |
318
|
|
|
$translator->trans('kuma_node.admin.unpublish.flash.success_unpublished') |
319
|
|
|
); |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
} |
323
|
|
|
|
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.