1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the Blast Project package. |
5
|
|
|
* |
6
|
|
|
* Copyright (C) 2015-2017 Libre Informatique |
7
|
|
|
* |
8
|
|
|
* This file is licenced under the GNU LGPL v3. |
9
|
|
|
* For the full copyright and license information, please view the LICENSE.md |
10
|
|
|
* file that was distributed with this source code. |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
namespace Blast\CoreBundle\Controller; |
14
|
|
|
|
15
|
|
|
use Sonata\AdminBundle\Controller\CRUDController as SonataController; |
16
|
|
|
use Symfony\Component\HttpFoundation\JsonResponse; |
17
|
|
|
use Symfony\Component\HttpFoundation\Request; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Class CRUDController. |
21
|
|
|
* |
22
|
|
|
* @author Thomas Rabaix <[email protected]> |
23
|
|
|
*/ |
24
|
|
|
class CRUDController extends SonataController |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* The related Admin class. |
28
|
|
|
* |
29
|
|
|
* @var AdminInterface |
30
|
|
|
*/ |
31
|
|
|
protected $admin; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Duplicate action. |
35
|
|
|
* |
36
|
|
|
* @return response |
37
|
|
|
*/ |
38
|
|
|
public function duplicateAction() |
39
|
|
|
{ |
40
|
|
|
$id = $this->getRequest()->get($this->admin->getIdParameter()); |
41
|
|
|
$object = clone $this->admin->getObject($id); |
42
|
|
|
|
43
|
|
|
$preResponse = $this->preDuplicate($object); |
44
|
|
|
if ($preResponse !== null) { |
45
|
|
|
return $preResponse; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
return $this->createAction($object); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Create action. |
53
|
|
|
* |
54
|
|
|
* @param object $object |
55
|
|
|
* |
56
|
|
|
* @return Response |
57
|
|
|
* |
58
|
|
|
* @throws AccessDeniedException If access is not granted |
59
|
|
|
*/ |
60
|
|
|
public function createAction($object = null) |
61
|
|
|
{ |
62
|
|
|
$request = $this->getRequest(); |
63
|
|
|
// the key used to lookup the template |
64
|
|
|
$templateKey = 'edit'; |
65
|
|
|
|
66
|
|
|
$this->admin->checkAccess('create'); |
67
|
|
|
|
68
|
|
|
$class = new \ReflectionClass($this->admin->hasActiveSubClass() ? $this->admin->getActiveSubClass() : $this->admin->getClass()); |
69
|
|
|
|
70
|
|
|
if ($class->isAbstract()) { |
71
|
|
|
return $this->render( |
|
|
|
|
72
|
|
|
'SonataAdminBundle:CRUD:select_subclass.html.twig', |
73
|
|
|
array( |
74
|
|
|
'base_template' => $this->getBaseTemplate(), |
75
|
|
|
'admin' => $this->admin, |
76
|
|
|
'action' => 'create', |
77
|
|
|
), |
78
|
|
|
null, |
79
|
|
|
$request |
|
|
|
|
80
|
|
|
); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
$object = $object ? $object : $this->admin->getNewInstance(); |
84
|
|
|
|
85
|
|
|
$preResponse = $this->preCreate($request, $object); |
86
|
|
|
if ($preResponse !== null) { |
87
|
|
|
return $preResponse; |
|
|
|
|
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
$this->admin->setSubject($object); |
91
|
|
|
|
92
|
|
|
/** @var $form \Symfony\Component\Form\Form */ |
93
|
|
|
$form = $this->admin->getForm(); |
94
|
|
|
$form->setData($object); |
95
|
|
|
$form->handleRequest($request); |
96
|
|
|
|
97
|
|
|
if ($form->isSubmitted()) { |
98
|
|
|
//TODO: remove this check for 4.0 |
99
|
|
|
if (method_exists($this->admin, 'preValidate')) { |
100
|
|
|
$this->admin->preValidate($object); |
101
|
|
|
} |
102
|
|
|
$isFormValid = $form->isValid(); |
103
|
|
|
|
104
|
|
|
// persist if the form was valid and if in preview mode the preview was approved |
105
|
|
|
if ($isFormValid && (!$this->isInPreviewMode($request) || $this->isPreviewApproved($request))) { |
|
|
|
|
106
|
|
|
$this->admin->checkAccess('create', $object); |
107
|
|
|
|
108
|
|
|
try { |
109
|
|
|
$object = $this->admin->create($object); |
110
|
|
|
|
111
|
|
|
if ($this->isXmlHttpRequest()) { |
112
|
|
|
return $this->renderJson(array( |
|
|
|
|
113
|
|
|
'result' => 'ok', |
114
|
|
|
'objectId' => $this->admin->getNormalizedIdentifier($object), |
115
|
|
|
), 200, array()); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$this->addFlash( |
119
|
|
|
'sonata_flash_success', |
120
|
|
|
$this->admin->trans( |
121
|
|
|
'flash_create_success', |
122
|
|
|
array('%name%' => $this->escapeHtml($this->admin->toString($object))), |
123
|
|
|
'SonataAdminBundle' |
124
|
|
|
) |
125
|
|
|
); |
126
|
|
|
|
127
|
|
|
// redirect to edit mode |
128
|
|
|
return $this->redirectTo($object); |
|
|
|
|
129
|
|
|
} catch (ModelManagerException $e) { |
|
|
|
|
130
|
|
|
$this->handleModelManagerException($e); |
131
|
|
|
|
132
|
|
|
$isFormValid = false; |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
// show an error message if the form failed validation |
137
|
|
|
if (!$isFormValid) { |
138
|
|
|
if (!$this->isXmlHttpRequest()) { |
139
|
|
|
$this->addFlash( |
140
|
|
|
'sonata_flash_error', |
141
|
|
|
$this->admin->trans( |
142
|
|
|
'flash_create_error', |
143
|
|
|
array('%name%' => $this->escapeHtml($this->admin->toString($object))), |
144
|
|
|
'SonataAdminBundle' |
145
|
|
|
) |
146
|
|
|
); |
147
|
|
|
} |
148
|
|
|
} elseif ($this->isPreviewRequested()) { |
149
|
|
|
// pick the preview template if the form was valid and preview was requested |
150
|
|
|
$templateKey = 'preview'; |
151
|
|
|
$this->admin->getShow(); |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
$view = $form->createView(); |
156
|
|
|
|
157
|
|
|
// set the theme for the current Admin Form |
158
|
|
|
$this->defineFormTheme($view, $this->admin->getFormTheme()); |
159
|
|
|
|
160
|
|
|
return $this->render($this->admin->getTemplate($templateKey), array( |
|
|
|
|
161
|
|
|
'action' => 'create', |
162
|
|
|
'form' => $view, |
163
|
|
|
'object' => $object, |
164
|
|
|
), null); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Generate Entity Code action. |
169
|
|
|
* |
170
|
|
|
* @param int|string|null $id |
171
|
|
|
* |
172
|
|
|
* @return JsonResponse |
173
|
|
|
*/ |
174
|
|
|
public function generateEntityCodeAction($id = null) |
|
|
|
|
175
|
|
|
{ |
176
|
|
|
$request = $this->getRequest(); |
177
|
|
|
|
178
|
|
|
$id = $request->get($this->admin->getIdParameter()); |
179
|
|
|
if ($id) { |
180
|
|
|
$subject = $this->admin->getObject($id); |
181
|
|
|
if (!$subject) { |
182
|
|
|
$error = sprintf('unable to find the object with id : %s', $id); |
183
|
|
|
|
184
|
|
|
return new JsonResponse(['error' => $error]); |
185
|
|
|
} |
186
|
|
|
try { |
187
|
|
|
$this->admin->checkAccess('edit', $subject); // TODO: is it necessary ? (we are not editing the entity) |
188
|
|
|
} catch (Exception $exc) { |
|
|
|
|
189
|
|
|
$error = $exc->getMessage(); |
190
|
|
|
|
191
|
|
|
return new JsonResponse(['error' => $error]); |
192
|
|
|
} |
193
|
|
|
} else { |
194
|
|
|
$subject = $this->admin->getNewInstance(); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
$this->admin->setSubject($subject); |
198
|
|
|
|
199
|
|
|
$form = $this->admin->getForm(); |
200
|
|
|
$form->setData($subject); |
201
|
|
|
$form->submit($request->request->get($form->getName())); |
202
|
|
|
$entity = $form->getData(); |
203
|
|
|
|
204
|
|
|
$field = $request->query->get('field', 'code'); |
205
|
|
|
$registry = $this->get('blast_core.code_generators'); |
206
|
|
|
$generator = $registry::getCodeGenerator(get_class($entity), $field); |
207
|
|
|
try { |
208
|
|
|
$code = $generator::generate($entity); |
209
|
|
|
|
210
|
|
|
return new JsonResponse(['code' => $code]); |
211
|
|
|
} catch (\Exception $exc) { |
212
|
|
|
$error = $this->get('translator')->trans($exc->getMessage()); |
213
|
|
|
|
214
|
|
|
return new JsonResponse(['error' => $error, 'generator' => get_class($generator)]); |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* This method can be overloaded in your custom CRUD controller. |
220
|
|
|
* It's called from createAction. |
221
|
|
|
* |
222
|
|
|
* @param Request $request |
223
|
|
|
* @param mixed $object |
224
|
|
|
* |
225
|
|
|
* @return Response|null |
226
|
|
|
*/ |
227
|
|
|
protected function preCreate(Request $request, $object) |
228
|
|
|
{ |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* This method can be overloaded in your custom CRUD controller. |
233
|
|
|
* It's called from editAction. |
234
|
|
|
* |
235
|
|
|
* @param Request $request |
236
|
|
|
* @param mixed $object |
237
|
|
|
* |
238
|
|
|
* @return Response|null |
239
|
|
|
*/ |
240
|
|
|
protected function preEdit(Request $request, $object) |
241
|
|
|
{ |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* This method can be overloaded in your custom CRUD controller. |
246
|
|
|
* It's called from deleteAction. |
247
|
|
|
* |
248
|
|
|
* @param Request $request |
249
|
|
|
* @param mixed $object |
250
|
|
|
* |
251
|
|
|
* @return Response|null |
252
|
|
|
*/ |
253
|
|
|
protected function preDelete(Request $request, $object) |
254
|
|
|
{ |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* This method can be overloaded in your custom CRUD controller. |
259
|
|
|
* It's called from showAction. |
260
|
|
|
* |
261
|
|
|
* @param Request $request |
262
|
|
|
* @param mixed $object |
263
|
|
|
* |
264
|
|
|
* @return Response|null |
265
|
|
|
*/ |
266
|
|
|
protected function preShow(Request $request, $object) |
267
|
|
|
{ |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* This method can be overloaded in your custom CRUD controller. |
272
|
|
|
* It's called from listAction. |
273
|
|
|
* |
274
|
|
|
* @param Request $request |
275
|
|
|
* |
276
|
|
|
* @return Response|null |
277
|
|
|
*/ |
278
|
|
|
protected function preList(Request $request) |
279
|
|
|
{ |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* This method can be overloaded in your custom CRUD controller. |
284
|
|
|
* It's called from duplicateAction. |
285
|
|
|
* |
286
|
|
|
* @param mixed $object |
287
|
|
|
* |
288
|
|
|
* @return Response|null |
289
|
|
|
*/ |
290
|
|
|
protected function preDuplicate($object) |
|
|
|
|
291
|
|
|
{ |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
protected function defineFormTheme($formView, $formTheme) |
295
|
|
|
{ |
296
|
|
|
$twig = $this->get('twig'); |
297
|
|
|
|
298
|
|
|
$renderer = ($twig->hasExtension('Symfony\Bridge\Twig\Form\TwigRenderer')) ? |
299
|
|
|
$twig->getRuntime('Symfony\Bridge\Twig\Form\TwigRenderer') : |
300
|
|
|
$twig->getExtension('Symfony\Bridge\Twig\Extension\FormExtension')->renderer; |
301
|
|
|
$renderer->setTheme($formView, $formTheme); |
302
|
|
|
} |
303
|
|
|
} |
304
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.