]> Raphaƫl G. Git Repositories - airbundle/blob - Controller/SnippetController.php
Replace dropped calls with checker, factory and security replacements
[airbundle] / Controller / SnippetController.php
1 <?php
2
3 namespace Rapsys\AirBundle\Controller;
4
5 use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
6 use Symfony\Component\Filesystem\Filesystem;
7 use Symfony\Component\HttpFoundation\File\Exception\FileException;
8 use Symfony\Component\HttpFoundation\Request;
9 use Symfony\Component\HttpFoundation\Response;
10 use Symfony\Component\Routing\Exception\MethodNotAllowedException;
11 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
12 use Symfony\Component\Routing\RequestContext;
13
14 use Rapsys\AirBundle\Entity\Location;
15 use Rapsys\AirBundle\Entity\Snippet;
16 use Rapsys\AirBundle\Entity\User;
17
18 class SnippetController extends DefaultController {
19 /**
20 * Add snippet
21 *
22 * @desc Persist snippet in database
23 *
24 * @param Request $request The request instance
25 *
26 * @return Response The rendered view or redirection
27 *
28 * @throws \RuntimeException When user has not at least guest role
29 */
30 public function add(Request $request) {
31 //Without guest role
32 if (!$this->checker->isGranted('ROLE_GUEST')) {
33 //Throw 403
34 throw $this->createAccessDeniedException($this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Guest')]));
35 }
36
37 //Create SnippetType form
38 $form = $this->container->get('form.factory')->createNamed(
39 //Set name
40 'snipped_'.$request->getLocale().'_'.$request->get('location'),
41 //Set type
42 'Rapsys\AirBundle\Form\SnippetType',
43 //Set data
44 null,
45 //Set options
46 [
47 //Set the action
48 'action' => $this->generateUrl('rapsys_air_snippet_add', ['location' => $request->get('location')]),
49 //Set the form attribute
50 'attr' => []
51 ]
52 );
53
54 //Refill the fields in case of invalid form
55 $form->handleRequest($request);
56
57 //Prevent creating snippet for other user unless admin
58 if ($form->get('user')->getData() !== $this->getUser()) {
59 //Without admin role
60 if (!$this->checker->isGranted('ROLE_ADMIN')) {
61 //Throw 403
62 throw $this->createAccessDeniedException($this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Admin')]));
63 }
64 }
65
66 //Handle invalid form
67 if (!$form->isSubmitted() || !$form->isValid()) {
68 //Set section
69 $section = $this->translator->trans('Snippet add');
70
71 //Set title
72 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
73
74 //Render the view
75 return $this->render('@RapsysAir/snippet/add.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+$this->context);
76 }
77
78 //Get doctrine
79 $doctrine = $this->getDoctrine();
80
81 //Get manager
82 $manager = $doctrine->getManager();
83
84 //Get snippet
85 $snippet = $form->getData();
86
87 //Set created
88 $snippet->setCreated(new \DateTime('now'));
89
90 //Set updated
91 $snippet->setUpdated(new \DateTime('now'));
92
93 //Queue snippet save
94 $manager->persist($snippet);
95
96 //Flush to get the ids
97 $manager->flush();
98
99 //Add notice
100 $this->addFlash('notice', $this->translator->trans('Snippet in %locale% %location% for %user% created', ['%locale%' => $snippet->getLocale(), '%location%' => $this->translator->trans('at '.$snippet->getLocation()), '%user%' => $snippet->getUser()]));
101
102 //Extract and process referer
103 if ($referer = $request->headers->get('referer')) {
104 //Create referer request instance
105 $req = Request::create($referer);
106
107 //Get referer path
108 $path = $req->getPathInfo();
109
110 //Get referer query string
111 $query = $req->getQueryString();
112
113 //Remove script name
114 $path = str_replace($request->getScriptName(), '', $path);
115
116 //Try with referer path
117 try {
118 //Save old context
119 $oldContext = $this->router->getContext();
120
121 //Force clean context
122 //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42
123 $this->router->setContext(new RequestContext());
124
125 //Retrieve route matching path
126 $route = $this->router->match($path);
127
128 //Reset context
129 $this->router->setContext($oldContext);
130
131 //Clear old context
132 unset($oldContext);
133
134 //Extract name
135 $name = $route['_route'];
136
137 //Remove route and controller from route defaults
138 unset($route['_route'], $route['_controller']);
139
140 //Check if snippet view route
141 if ($name == 'rapsys_air_user_view' && !empty($route['id'])) {
142 //Replace id
143 $route['id'] = $snippet->getUser()->getId();
144 //Other routes
145 } else {
146 //Set snippet
147 $route['snippet'] = $snippet->getId();
148 }
149
150 //Generate url
151 return $this->redirectToRoute($name, $route);
152 //No route matched
153 } catch(MethodNotAllowedException|ResourceNotFoundException $e) {
154 //Unset referer to fallback to default route
155 unset($referer);
156 }
157 }
158
159 //Redirect to cleanup the form
160 return $this->redirectToRoute('rapsys_air', ['snippet' => $snippet->getId()]);
161 }
162
163 /**
164 * Edit snippet
165 *
166 * @desc Persist snippet in database
167 *
168 * @param Request $request The request instance
169 *
170 * @return Response The rendered view or redirection
171 *
172 * @throws \RuntimeException When user has not at least guest role
173 */
174 public function edit(Request $request, $id) {
175 //Without guest role
176 if (!$this->checker->isGranted('ROLE_GUEST')) {
177 //Throw 403
178 throw $this->createAccessDeniedException($this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Guest')]));
179 }
180
181 //Get doctrine
182 $doctrine = $this->getDoctrine();
183
184 //Get snippet
185 if (empty($snippet = $doctrine->getRepository(Snippet::class)->findOneById($id))) {
186 throw $this->createNotFoundException($this->translator->trans('Unable to find snippet: %id%', ['%id%' => $id]));
187 }
188
189 //Create SnippetType form
190 $form = $this->container->get('form.factory')->createNamed(
191 //Set name
192 'snipped_'.$request->getLocale().'_'.$snippet->getLocation()->getId(),
193 //Set type
194 'Rapsys\AirBundle\Form\SnippetType',
195 //Set data
196 $snippet,
197 //Set options
198 [
199 //Set the action
200 'action' => $this->generateUrl('rapsys_air_snippet_edit', ['id' => $id]),
201 //Set the form attribute
202 'attr' => []
203 ]
204 );
205
206 //Refill the fields in case of invalid form
207 $form->handleRequest($request);
208
209 //Prevent creating snippet for other user unless admin
210 if ($form->get('user')->getData() !== $this->getUser()) {
211 //Without admin role
212 if (!$this->checker->isGranted('ROLE_ADMIN')) {
213 //Throw 403
214 throw $this->createAccessDeniedException($this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Admin')]));
215 }
216 }
217
218 //Handle invalid form
219 if (!$form->isSubmitted() || !$form->isValid()) {
220 //Set section
221 $section = $this->translator->trans('Snippet %id%', ['%id%' => $id]);
222
223 //Set title
224 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
225
226 //Render the view
227 return $this->render('@RapsysAir/snippet/edit.html.twig', ['id' => $id, 'title' => $title, 'section' => $section, 'form' => $form->createView()]+$this->context);
228 }
229
230 //With image
231 //TODO: add delete button ???
232 if ($image = $form->get('image')->getData()) {
233 //Get public path
234 #$public = $this->container->get('kernel')->getBundle('RapsysAirBundle')->getPath().'/Resources/public';
235 #$public = $this->container->get('kernel')->locateResource('@RapsysAirBundle/Resources/public');
236 $public = $this->getPublicPath();
237
238 //Create imagick object
239 $imagick = new \Imagick();
240
241 //Read image
242 $imagick->readImage($image->getRealPath());
243
244 //Set destination
245 //XXX: uploaded path location/<userId>/<locationId>.png and session image location/<userId>/<locationId>/<sessionId>.jpeg
246 //XXX: default path location/default.png and session location/default/<sessionId>.jpeg
247 $destination = $public.'/location/'.$snippet->getUser()->getId().'/'.$snippet->getLocation()->getId().'.png';
248
249 //Check target directory
250 if (!is_dir($dir = dirname($destination))) {
251 //Create filesystem object
252 $filesystem = new Filesystem();
253
254 try {
255 //Create dir
256 //XXX: set as 0775, symfony umask (0022) will reduce rights (0755)
257 $filesystem->mkdir($dir, 0775);
258 } catch (IOExceptionInterface $e) {
259 //Throw error
260 throw new \Exception(sprintf('Output directory "%s" do not exists and unable to create it', $dir), 0, $e);
261 }
262 }
263
264 //Save image
265 if (!$imagick->writeImage($destination)) {
266 //Throw error
267 throw new \Exception(sprintf('Unable to write image "%s"', $destination));
268 }
269 }
270
271 //Get manager
272 $manager = $doctrine->getManager();
273
274 //Set updated
275 $snippet->setUpdated(new \DateTime('now'));
276
277 //Queue snippet save
278 $manager->persist($snippet);
279
280 //Flush to get the ids
281 $manager->flush();
282
283 //Add notice
284 $this->addFlash('notice', $this->translator->trans('Snippet %id% in %locale% %location% for %user% updated', ['%id%' => $id, '%locale%' => $snippet->getLocale(), '%location%' => $this->translator->trans('at '.$snippet->getLocation()), '%user%' => $snippet->getUser()]));
285
286 //Extract and process referer
287 if ($referer = $request->headers->get('referer')) {
288 //Create referer request instance
289 $req = Request::create($referer);
290
291 //Get referer path
292 $path = $req->getPathInfo();
293
294 //Get referer query string
295 $query = $req->getQueryString();
296
297 //Remove script name
298 $path = str_replace($request->getScriptName(), '', $path);
299
300 //Try with referer path
301 try {
302 //Save old context
303 $oldContext = $this->router->getContext();
304
305 //Force clean context
306 //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42
307 $this->router->setContext(new RequestContext());
308
309 //Retrieve route matching path
310 $route = $this->router->match($path);
311
312 //Reset context
313 $this->router->setContext($oldContext);
314
315 //Clear old context
316 unset($oldContext);
317
318 //Extract name
319 $name = $route['_route'];
320
321 //Remove route and controller from route defaults
322 unset($route['_route'], $route['_controller']);
323
324 //Check if snippet view route
325 if ($name == 'rapsys_air_user_view' && !empty($route['id'])) {
326 //Replace id
327 $route['id'] = $snippet->getUser()->getId();
328 //Other routes
329 } else {
330 //Set snippet
331 $route['snippet'] = $snippet->getId();
332 }
333
334 //Generate url
335 return $this->redirectToRoute($name, $route);
336 //No route matched
337 } catch(MethodNotAllowedException|ResourceNotFoundException $e) {
338 //Unset referer to fallback to default route
339 unset($referer);
340 }
341 }
342
343 //Redirect to cleanup the form
344 return $this->redirectToRoute('rapsys_air', ['snippet' => $snippet->getId()]);
345 }
346 }