1 | <?php |
||
2 | |||
3 | /* |
||
4 | * @copyright 2014 Mautic Contributors. All rights reserved |
||
5 | * @author Mautic |
||
6 | * |
||
7 | * @link http://mautic.org |
||
8 | * |
||
9 | * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html |
||
10 | */ |
||
11 | |||
12 | namespace Mautic\CoreBundle\Controller; |
||
13 | |||
14 | use Mautic\CoreBundle\CoreEvents; |
||
15 | use Mautic\CoreBundle\Event\CommandListEvent; |
||
16 | use Mautic\CoreBundle\Event\GlobalSearchEvent; |
||
17 | use Mautic\CoreBundle\Event\UpgradeEvent; |
||
18 | use Mautic\CoreBundle\Helper\CookieHelper; |
||
19 | use Mautic\CoreBundle\Helper\InputHelper; |
||
20 | use Mautic\CoreBundle\Helper\LanguageHelper; |
||
21 | use Mautic\CoreBundle\Helper\PathsHelper; |
||
22 | use Mautic\CoreBundle\Helper\UpdateHelper; |
||
23 | use Mautic\CoreBundle\IpLookup\AbstractLocalDataLookup; |
||
24 | use Mautic\CoreBundle\IpLookup\AbstractLookup; |
||
25 | use Mautic\CoreBundle\IpLookup\IpLookupFormInterface; |
||
26 | use Mautic\CoreBundle\Security\Permissions\CorePermissions; |
||
27 | use Symfony\Bundle\FrameworkBundle\Console\Application; |
||
28 | use Symfony\Component\Console\Input\ArgvInput; |
||
29 | use Symfony\Component\Console\Output\BufferedOutput; |
||
30 | use Symfony\Component\HttpFoundation\JsonResponse; |
||
31 | use Symfony\Component\HttpFoundation\Request; |
||
32 | use Symfony\Component\PropertyAccess\PropertyAccess; |
||
33 | |||
34 | /** |
||
35 | * Class AjaxController. |
||
36 | */ |
||
37 | class AjaxController extends CommonController |
||
38 | { |
||
39 | /** |
||
40 | * @param array $dataArray |
||
41 | * @param int $statusCode |
||
42 | * @param bool $addIgnoreWdt |
||
43 | * |
||
44 | * @return JsonResponse |
||
45 | * |
||
46 | * @throws \Exception |
||
47 | */ |
||
48 | protected function sendJsonResponse($dataArray, $statusCode = null, $addIgnoreWdt = true) |
||
49 | { |
||
50 | $response = new JsonResponse(); |
||
51 | |||
52 | if ('dev' == $this->container->getParameter('kernel.environment') && $addIgnoreWdt) { |
||
53 | $dataArray['ignore_wdt'] = 1; |
||
54 | } |
||
55 | |||
56 | if (null !== $statusCode) { |
||
57 | $response->setStatusCode($statusCode); |
||
58 | } |
||
59 | |||
60 | $response->setData($dataArray); |
||
61 | |||
62 | return $response; |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Executes an action requested via ajax. |
||
67 | * |
||
68 | * @return JsonResponse |
||
69 | */ |
||
70 | public function delegateAjaxAction() |
||
71 | { |
||
72 | //process ajax actions |
||
73 | $authenticationChecker = $this->get('security.authorization_checker'); |
||
74 | $action = $this->request->get('action'); |
||
75 | $bundleName = null; |
||
76 | if (empty($action)) { |
||
77 | //check POST |
||
78 | $action = $this->request->request->get('action'); |
||
79 | } |
||
80 | |||
81 | if ($authenticationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) { |
||
82 | if (false !== strpos($action, ':')) { |
||
83 | //call the specified bundle's ajax action |
||
84 | $parts = explode(':', $action); |
||
85 | $namespace = 'Mautic'; |
||
86 | $isPlugin = false; |
||
87 | |||
88 | if (3 == count($parts) && 'plugin' == $parts['0']) { |
||
89 | $namespace = 'MauticPlugin'; |
||
90 | array_shift($parts); |
||
91 | $isPlugin = true; |
||
92 | } |
||
93 | |||
94 | if (2 == count($parts)) { |
||
95 | $bundleName = $parts[0]; |
||
96 | $bundle = ucfirst($bundleName); |
||
97 | $action = $parts[1]; |
||
98 | if (!$classExists = class_exists($namespace.'\\'.$bundle.'Bundle\\Controller\\AjaxController')) { |
||
99 | // Check if a plugin is prefixed with Mautic |
||
100 | $bundle = 'Mautic'.$bundle; |
||
101 | $classExists = class_exists($namespace.'\\'.$bundle.'Bundle\\Controller\\AjaxController'); |
||
102 | } elseif (!$isPlugin) { |
||
103 | $bundle = 'Mautic'.$bundle; |
||
104 | } |
||
105 | |||
106 | if ($classExists) { |
||
107 | return $this->forward( |
||
108 | "{$bundle}Bundle:Ajax:executeAjax", |
||
109 | [ |
||
110 | 'action' => $action, |
||
111 | //forward the request as well as Symfony creates a subrequest without GET/POST |
||
112 | 'request' => $this->request, |
||
113 | 'bundle' => $bundleName, |
||
114 | ] |
||
115 | ); |
||
116 | } |
||
117 | } |
||
118 | } |
||
119 | |||
120 | return $this->executeAjaxAction($action, $this->request, $bundleName); |
||
121 | } |
||
122 | |||
123 | return $this->sendJsonResponse(['success' => 0]); |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * @param $action |
||
128 | * @param null $bundle |
||
129 | * |
||
130 | * @return JsonResponse |
||
131 | */ |
||
132 | public function executeAjaxAction($action, Request $request, $bundle = null) |
||
133 | { |
||
134 | if (method_exists($this, "{$action}Action")) { |
||
135 | return $this->{"{$action}Action"}($request, $bundle); |
||
136 | } |
||
137 | |||
138 | return $this->sendJsonResponse(['success' => 0]); |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * @return JsonResponse |
||
143 | */ |
||
144 | protected function globalSearchAction(Request $request) |
||
145 | { |
||
146 | $dataArray = ['success' => 1]; |
||
147 | $searchStr = InputHelper::clean($request->query->get('global_search', '')); |
||
148 | $this->get('session')->set('mautic.global_search', $searchStr); |
||
149 | |||
150 | $event = new GlobalSearchEvent($searchStr, $this->get('translator')); |
||
151 | $this->get('event_dispatcher')->dispatch(CoreEvents::GLOBAL_SEARCH, $event); |
||
152 | |||
153 | $dataArray['newContent'] = $this->renderView( |
||
154 | 'MauticCoreBundle:GlobalSearch:results.html.php', |
||
155 | ['results' => $event->getResults()] |
||
156 | ); |
||
157 | |||
158 | return $this->sendJsonResponse($dataArray); |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * @return JsonResponse |
||
163 | */ |
||
164 | protected function commandListAction(Request $request) |
||
165 | { |
||
166 | $model = InputHelper::clean($request->query->get('model')); |
||
167 | $commands = $this->getModel($model)->getCommandList(); |
||
168 | $dataArray = []; |
||
169 | $translator = $this->get('translator'); |
||
170 | foreach ($commands as $k => $c) { |
||
171 | if (is_array($c)) { |
||
172 | foreach ($c as $subc) { |
||
173 | $command = $translator->trans($k); |
||
174 | $command = (false === strpos($command, ':')) ? $command.':' : $command; |
||
175 | |||
176 | $dataArray[$command.$translator->trans($subc)] = ['value' => $command.$translator->trans($subc)]; |
||
177 | } |
||
178 | } else { |
||
179 | $command = $translator->trans($c); |
||
180 | $command = (false === strpos($command, ':')) ? $command.':' : $command; |
||
181 | |||
182 | $dataArray[$command] = ['value' => $command]; |
||
183 | } |
||
184 | } |
||
185 | sort($dataArray); |
||
186 | |||
187 | return $this->sendJsonResponse($dataArray); |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * @return JsonResponse |
||
192 | */ |
||
193 | protected function globalCommandListAction(Request $request) |
||
194 | { |
||
195 | $dispatcher = $this->get('event_dispatcher'); |
||
196 | $event = new CommandListEvent(); |
||
197 | $dispatcher->dispatch(CoreEvents::BUILD_COMMAND_LIST, $event); |
||
198 | $allCommands = $event->getCommands(); |
||
199 | $translator = $this->get('translator'); |
||
200 | $dataArray = []; |
||
201 | $dupChecker = []; |
||
202 | foreach ($allCommands as $commands) { |
||
203 | //@todo if/when figure out a way for typeahead dynamic headers |
||
204 | //$header = $translator->trans($header); |
||
205 | //$dataArray[$header] = array(); |
||
206 | foreach ($commands as $k => $c) { |
||
207 | if (is_array($c)) { |
||
208 | $command = $translator->trans($k); |
||
209 | $command = (false === strpos($command, ':')) ? $command.':' : $command; |
||
210 | |||
211 | foreach ($c as $subc) { |
||
212 | $subcommand = $command.$translator->trans($subc); |
||
213 | if (!in_array($subcommand, $dupChecker)) { |
||
214 | $dataArray[] = ['value' => $subcommand]; |
||
215 | $dupChecker[] = $subcommand; |
||
216 | } |
||
217 | } |
||
218 | } else { |
||
219 | $command = $translator->trans($k); |
||
220 | $command = (false === strpos($command, ':')) ? $command.':' : $command; |
||
221 | |||
222 | if (!in_array($command, $dupChecker)) { |
||
223 | $dataArray[] = ['value' => $command]; |
||
224 | $dupChecker[] = $command; |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | //sort($dataArray[$header]); |
||
229 | } |
||
230 | //ksort($dataArray); |
||
231 | sort($dataArray); |
||
232 | |||
233 | return $this->sendJsonResponse($dataArray); |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * @return JsonResponse |
||
238 | */ |
||
239 | protected function togglePublishStatusAction(Request $request) |
||
240 | { |
||
241 | $dataArray = ['success' => 0]; |
||
242 | $name = InputHelper::clean($request->request->get('model')); |
||
243 | $id = InputHelper::clean($request->request->get('id')); |
||
244 | $customToggle = InputHelper::clean($request->request->get('customToggle')); |
||
245 | $model = $this->getModel($name); |
||
246 | |||
247 | $post = $request->request->all(); |
||
248 | unset($post['model'], $post['id'], $post['action']); |
||
249 | if (!empty($post)) { |
||
250 | $extra = http_build_query($post); |
||
251 | } else { |
||
252 | $extra = ''; |
||
253 | } |
||
254 | |||
255 | $entity = $model->getEntity($id); |
||
256 | if (null !== $entity) { |
||
257 | $permissionBase = $model->getPermissionBase(); |
||
258 | |||
259 | /** @var CorePermissions $security */ |
||
260 | $security = $this->get('mautic.security'); |
||
261 | $createdBy = (method_exists($entity, 'getCreatedBy')) ? $entity->getCreatedBy() : null; |
||
262 | |||
263 | if ($security->checkPermissionExists($permissionBase.':publishown')) { |
||
264 | $hasPermission = $security->hasEntityAccess($permissionBase.':publishown', $permissionBase.':publishother', $createdBy); |
||
265 | } elseif ($security->checkPermissionExists($permissionBase.':publish')) { |
||
266 | $hasPermission = $security->isGranted($permissionBase.':publish'); |
||
267 | } elseif ($security->checkPermissionExists($permissionBase.':manage')) { |
||
268 | $hasPermission = $security->isGranted($permissionBase.':manage'); |
||
269 | } elseif ($security->checkPermissionExists($permissionBase.':full')) { |
||
270 | $hasPermission = $security->isGranted($permissionBase.':full'); |
||
271 | } elseif ($security->checkPermissionExists($permissionBase.':editown')) { |
||
272 | $hasPermission = $security->hasEntityAccess($permissionBase.':editown', $permissionBase.':editother', $createdBy); |
||
273 | } elseif ($security->checkPermissionExists($permissionBase.':edit')) { |
||
274 | $hasPermission = $security->isGranted($permissionBase.':edit'); |
||
275 | } else { |
||
276 | $hasPermission = false; |
||
277 | } |
||
278 | |||
279 | if ($hasPermission) { |
||
280 | $dataArray['success'] = 1; |
||
281 | //toggle permission state |
||
282 | if ($customToggle) { |
||
283 | $accessor = PropertyAccess::createPropertyAccessor(); |
||
284 | $accessor->setValue($entity, $customToggle, !$accessor->getValue($entity, $customToggle)); |
||
285 | $model->getRepository()->saveEntity($entity); |
||
286 | } else { |
||
287 | $refresh = $model->togglePublishStatus($entity); |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
288 | } |
||
289 | if (!empty($refresh)) { |
||
290 | $dataArray['reload'] = 1; |
||
291 | } else { |
||
292 | //get updated icon HTML |
||
293 | $html = $this->renderView( |
||
294 | 'MauticCoreBundle:Helper:publishstatus_icon.html.php', |
||
295 | [ |
||
296 | 'item' => $entity, |
||
297 | 'model' => $name, |
||
298 | 'query' => $extra, |
||
299 | 'size' => (isset($post['size'])) ? $post['size'] : '', |
||
300 | ] |
||
301 | ); |
||
302 | $dataArray['statusHtml'] = $html; |
||
303 | } |
||
304 | } |
||
305 | } |
||
306 | |||
307 | $dataArray['flashes'] = $this->getFlashContent(); |
||
308 | |||
309 | return $this->sendJsonResponse($dataArray); |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * Unlock an entity locked by the current user. |
||
314 | * |
||
315 | * @return JsonResponse |
||
316 | */ |
||
317 | protected function unlockEntityAction(Request $request) |
||
318 | { |
||
319 | $dataArray = ['success' => 0]; |
||
320 | $name = InputHelper::clean($request->request->get('model')); |
||
321 | $id = (int) $request->request->get('id'); |
||
322 | $extra = InputHelper::clean($request->request->get('parameter')); |
||
323 | $model = $this->getModel($name); |
||
324 | $entity = $model->getEntity($id); |
||
325 | $currentUser = $this->user; |
||
326 | |||
327 | if (method_exists($entity, 'getCheckedOutBy')) { |
||
328 | $checkedOut = $entity->getCheckedOutBy(); |
||
329 | if (null !== $entity && !empty($checkedOut) && $checkedOut === $currentUser->getId()) { |
||
330 | //entity exists, is checked out, and is checked out by the current user so go ahead and unlock |
||
331 | $model->unlockEntity($entity, $extra); |
||
332 | $dataArray['success'] = 1; |
||
333 | } |
||
334 | } |
||
335 | |||
336 | return $this->sendJsonResponse($dataArray); |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Sets the page layout to the update layout. |
||
341 | * |
||
342 | * @return JsonResponse |
||
343 | */ |
||
344 | protected function updateSetUpdateLayoutAction(Request $request) |
||
345 | { |
||
346 | $dataArray = [ |
||
347 | 'success' => 1, |
||
348 | 'content' => $this->renderView('MauticCoreBundle:Update:update.html.php'), |
||
349 | ]; |
||
350 | |||
351 | // A way to keep the upgrade from failing if the session is lost after |
||
352 | // the cache is cleared by upgrade.php |
||
353 | /** @var \Mautic\CoreBundle\Helper\CookieHelper $cookieHelper */ |
||
354 | $cookieHelper = $this->container->get('mautic.helper.cookie'); |
||
355 | $cookieHelper->setCookie('mautic_update', 'setupUpdate', 300); |
||
356 | |||
357 | return $this->sendJsonResponse($dataArray); |
||
358 | } |
||
359 | |||
360 | /** |
||
361 | * Downloads the update package. |
||
362 | * |
||
363 | * @return JsonResponse |
||
364 | */ |
||
365 | protected function updateDownloadPackageAction(Request $request) |
||
366 | { |
||
367 | $dataArray = ['success' => 0]; |
||
368 | $translator = $this->translator; |
||
369 | |||
370 | /** @var \Mautic\CoreBundle\Helper\UpdateHelper $updateHelper */ |
||
371 | $updateHelper = $this->container->get('mautic.helper.update'); |
||
372 | |||
373 | // Fetch the update package |
||
374 | $update = $updateHelper->fetchData(); |
||
375 | $package = $updateHelper->fetchPackage($update['package']); |
||
376 | |||
377 | /** @var \Mautic\CoreBundle\Helper\CookieHelper $cookieHelper */ |
||
378 | $cookieHelper = $this->container->get('mautic.helper.cookie'); |
||
379 | |||
380 | if ($package['error']) { |
||
381 | $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed'); |
||
382 | $dataArray['message'] = $translator->trans('mautic.core.update.error', ['%error%' => $translator->trans($package['message'])]); |
||
383 | |||
384 | // A way to keep the upgrade from failing if the session is lost after |
||
385 | // the cache is cleared by upgrade.php |
||
386 | $cookieHelper->deleteCookie('mautic_update'); |
||
387 | } else { |
||
388 | $dataArray['success'] = 1; |
||
389 | $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.success'); |
||
390 | $dataArray['nextStep'] = $translator->trans('mautic.core.update.step.extracting.package'); |
||
391 | $dataArray['nextStepStatus'] = $translator->trans('mautic.core.update.step.in.progress'); |
||
392 | |||
393 | // A way to keep the upgrade from failing if the session is lost after |
||
394 | // the cache is cleared by upgrade.php |
||
395 | $cookieHelper->setCookie('mautic_update', 'downloadPackage', 300); |
||
396 | } |
||
397 | |||
398 | return $this->sendJsonResponse($dataArray); |
||
399 | } |
||
400 | |||
401 | /** |
||
402 | * Extracts the update package. |
||
403 | * |
||
404 | * @return JsonResponse |
||
405 | */ |
||
406 | protected function updateExtractPackageAction(Request $request) |
||
407 | { |
||
408 | $dataArray = ['success' => 0]; |
||
409 | $translator = $this->translator; |
||
410 | |||
411 | /** @var UpdateHelper $updateHelper */ |
||
412 | $updateHelper = $this->container->get('mautic.helper.update'); |
||
413 | |||
414 | /** @var CookieHelper $cookieHelper */ |
||
415 | $cookieHelper = $this->container->get('mautic.helper.cookie'); |
||
416 | |||
417 | /** @var PathsHelper $pathsHelper */ |
||
418 | $pathsHelper = $this->container->get('mautic.helper.paths'); |
||
419 | |||
420 | // Fetch the package data |
||
421 | $update = $updateHelper->fetchData(); |
||
422 | $zipFile = $pathsHelper->getSystemPath('cache').'/'.basename($update['package']); |
||
423 | |||
424 | $zipper = new \ZipArchive(); |
||
425 | $archive = $zipper->open($zipFile); |
||
426 | |||
427 | if (true !== $archive) { |
||
428 | // Get the exact error |
||
429 | switch ($archive) { |
||
430 | case \ZipArchive::ER_EXISTS: |
||
431 | $error = 'mautic.core.update.archive_file_exists'; |
||
432 | break; |
||
433 | case \ZipArchive::ER_INCONS: |
||
434 | case \ZipArchive::ER_INVAL: |
||
435 | case \ZipArchive::ER_MEMORY: |
||
436 | $error = 'mautic.core.update.archive_zip_corrupt'; |
||
437 | break; |
||
438 | case \ZipArchive::ER_NOENT: |
||
439 | $error = 'mautic.core.update.archive_no_such_file'; |
||
440 | break; |
||
441 | case \ZipArchive::ER_NOZIP: |
||
442 | $error = 'mautic.core.update.archive_not_valid_zip'; |
||
443 | break; |
||
444 | case \ZipArchive::ER_READ: |
||
445 | case \ZipArchive::ER_SEEK: |
||
446 | case \ZipArchive::ER_OPEN: |
||
447 | default: |
||
448 | $error = 'mautic.core.update.archive_could_not_open'; |
||
449 | break; |
||
450 | } |
||
451 | |||
452 | $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed'); |
||
453 | $dataArray['message'] = $translator->trans('mautic.core.update.error', ['%error%' => $translator->trans($error)]); |
||
454 | |||
455 | // A way to keep the upgrade from failing if the session is lost after |
||
456 | // the cache is cleared by upgrade.php |
||
457 | $cookieHelper->deleteCookie('mautic_update'); |
||
458 | } else { |
||
459 | // Extract the archive file now |
||
460 | if (!$zipper->extractTo(dirname($this->container->getParameter('kernel.root_dir')).'/upgrade')) { |
||
461 | $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed'); |
||
462 | $dataArray['message'] = $translator->trans( |
||
463 | 'mautic.core.update.error', |
||
464 | ['%error%' => $translator->trans('mautic.core.update.error_extracting_package')] |
||
465 | ); |
||
466 | } else { |
||
467 | $zipper->close(); |
||
468 | |||
469 | $dataArray['success'] = 1; |
||
470 | $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.success'); |
||
471 | $dataArray['nextStep'] = $translator->trans('mautic.core.update.step.moving.package'); |
||
472 | $dataArray['nextStepStatus'] = $translator->trans('mautic.core.update.step.in.progress'); |
||
473 | |||
474 | // A way to keep the upgrade from failing if the session is lost after |
||
475 | // the cache is cleared by upgrade.php |
||
476 | $cookieHelper->setCookie('mautic_update', 'extractPackage', 300); |
||
477 | } |
||
478 | } |
||
479 | |||
480 | return $this->sendJsonResponse($dataArray); |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * Migrate the database to the latest version. |
||
485 | * |
||
486 | * @return JsonResponse |
||
487 | */ |
||
488 | public function updateDatabaseMigrationAction(Request $request) |
||
489 | { |
||
490 | $dataArray = ['success' => 0]; |
||
491 | $translator = $this->translator; |
||
492 | $result = 0; |
||
493 | |||
494 | // Also do the last bit of filesystem cleanup from the upgrade here |
||
495 | if (is_dir(dirname($this->container->getParameter('kernel.root_dir')).'/upgrade')) { |
||
496 | $iterator = new \FilesystemIterator( |
||
497 | dirname($this->container->getParameter('kernel.root_dir')).'/upgrade', \FilesystemIterator::SKIP_DOTS |
||
498 | ); |
||
499 | |||
500 | /** @var \FilesystemIterator $file */ |
||
501 | foreach ($iterator as $file) { |
||
502 | // Sanity checks |
||
503 | if ($file->isFile()) { |
||
504 | @unlink($file->getPath().'/'.$file->getFilename()); |
||
505 | } |
||
506 | } |
||
507 | |||
508 | // Should be empty now, nuke the folder |
||
509 | @rmdir(dirname($this->container->getParameter('kernel.root_dir')).'/upgrade'); |
||
510 | } |
||
511 | |||
512 | $cacheDir = $this->container->get('mautic.helper.paths')->getSystemPath('cache'); |
||
513 | |||
514 | // Cleanup the update cache data now too |
||
515 | if (file_exists($cacheDir.'/lastUpdateCheck.txt')) { |
||
516 | @unlink($cacheDir.'/lastUpdateCheck.txt'); |
||
517 | } |
||
518 | |||
519 | if (file_exists($cacheDir.'/'.MAUTIC_VERSION.'.zip')) { |
||
520 | @unlink($cacheDir.'/'.MAUTIC_VERSION.'.zip'); |
||
521 | } |
||
522 | |||
523 | // Update languages |
||
524 | /** @var LanguageHelper $languageHelper */ |
||
525 | $languageHelper = $this->container->get('mautic.helper.language'); |
||
526 | $supportedLanguages = $languageHelper->getSupportedLanguages(); |
||
527 | |||
528 | // If there is only one language, assume it is 'en_US' and skip this |
||
529 | if (count($supportedLanguages) > 1) { |
||
530 | // First, update the cached language data |
||
531 | $result = $languageHelper->fetchLanguages(true); |
||
532 | |||
533 | // Only continue if not in error |
||
534 | if (!isset($result['error'])) { |
||
535 | foreach ($supportedLanguages as $locale => $name) { |
||
536 | // We don't need to update en_US, that comes with the main package |
||
537 | if ('en_US' == $locale) { |
||
538 | continue; |
||
539 | } |
||
540 | |||
541 | // Update time |
||
542 | $extractResult = $languageHelper->extractLanguagePackage($locale); |
||
543 | |||
544 | if ($extractResult['error']) { |
||
545 | // TODO - Need to look at adding messages during update... |
||
546 | } |
||
547 | } |
||
548 | } |
||
549 | } |
||
550 | |||
551 | $iterator = new \FilesystemIterator($this->container->getParameter('kernel.root_dir').'/migrations', \FilesystemIterator::SKIP_DOTS); |
||
552 | |||
553 | if (iterator_count($iterator)) { |
||
554 | $args = ['console', 'doctrine:migrations:migrate', '--no-interaction', '--env='.MAUTIC_ENV]; |
||
555 | |||
556 | if ('prod' === MAUTIC_ENV) { |
||
557 | $args[] = '--no-debug'; |
||
558 | } |
||
559 | |||
560 | $input = new ArgvInput($args); |
||
561 | $application = new Application($this->container->get('kernel')); |
||
562 | $application->setAutoExit(false); |
||
563 | $output = new BufferedOutput(); |
||
564 | |||
565 | $minExecutionTime = 300; |
||
566 | $maxExecutionTime = (int) ini_get('max_execution_time'); |
||
567 | if ($maxExecutionTime > 0 && $maxExecutionTime < $minExecutionTime) { |
||
568 | ini_set('max_execution_time', $minExecutionTime); |
||
569 | } |
||
570 | |||
571 | $result = $application->run($input, $output); |
||
572 | } |
||
573 | |||
574 | /** @var CookieHelper $cookieHelper */ |
||
575 | $cookieHelper = $this->container->get('mautic.helper.cookie'); |
||
576 | |||
577 | if (0 !== $result) { |
||
578 | // Log the output |
||
579 | $outputBuffer = trim(preg_replace('/\n\s*\n/s', ' \\ ', $output->fetch())); |
||
580 | $outputBuffer = preg_replace('/\s\s+/', ' ', trim($outputBuffer)); |
||
581 | $this->container->get('monolog.logger.mautic')->log('error', '[UPGRADE ERROR] Exit code '.$result.'; '.$outputBuffer); |
||
582 | |||
583 | $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.failed'); |
||
584 | $dataArray['message'] = $translator->trans( |
||
585 | 'mautic.core.update.error', |
||
586 | ['%error%' => $translator->trans('mautic.core.update.error_performing_migration')] |
||
587 | ).' <a href="'.$this->generateUrl('mautic_core_update_schema', ['update' => 1]) |
||
588 | .'" class="btn btn-primary btn-xs" data-toggle="ajax">'.$translator->trans('mautic.core.retry').'</a>'; |
||
589 | |||
590 | // A way to keep the upgrade from failing if the session is lost after |
||
591 | // the cache is cleared by upgrade.php |
||
592 | $cookieHelper->deleteCookie('mautic_update'); |
||
593 | } else { |
||
594 | // A way to keep the upgrade from failing if the session is lost after |
||
595 | // the cache is cleared by upgrade.php |
||
596 | /* @var CookieHelper $cookieHelper */ |
||
597 | $cookieHelper->setCookie('mautic_update', 'schemaMigration', 300); |
||
598 | |||
599 | if ($request->get('finalize', false)) { |
||
600 | // Go to the finalize step |
||
601 | $dataArray['success'] = 1; |
||
602 | $dataArray['stepStatus'] = $translator->trans('mautic.core.update.step.success'); |
||
603 | $dataArray['nextStep'] = $translator->trans('mautic.core.update.step.finalizing'); |
||
604 | $dataArray['nextStepStatus'] = $translator->trans('mautic.core.update.step.in.progress'); |
||
605 | } else { |
||
606 | // Upgrading from 1.0.5 |
||
607 | |||
608 | return $this->updateFinalizationAction($request); |
||
609 | } |
||
610 | } |
||
611 | |||
612 | return $this->sendJsonResponse($dataArray); |
||
613 | } |
||
614 | |||
615 | /** |
||
616 | * Finalize update. |
||
617 | * |
||
618 | * @return JsonResponse |
||
619 | */ |
||
620 | public function updateFinalizationAction(Request $request) |
||
621 | { |
||
622 | $dataArray = ['success' => 0]; |
||
623 | $translator = $this->translator; |
||
624 | |||
625 | // Here as a just in case it's needed for a future upgrade |
||
626 | $dataArray['success'] = 1; |
||
627 | $dataArray['message'] = $translator->trans('mautic.core.update.update_successful', ['%version%' => $this->factory->getVersion()]); |
||
628 | |||
629 | // Check for a post install message |
||
630 | if ($postMessage = $this->container->get('session')->get('post_upgrade_message', false)) { |
||
631 | $this->container->get('session')->remove('post_upgrade_message'); |
||
632 | $postMessage = sprintf('<h4 class="mt-lg">%s</h4><p>%s</p>', $this->container->get('translator')->trans('mautic.core.update.post_message'), $postMessage); |
||
633 | $dataArray['postmessage'] = $postMessage; |
||
634 | } |
||
635 | |||
636 | // Execute the mautic.post_upgrade event |
||
637 | $this->dispatcher->dispatch(CoreEvents::POST_UPGRADE, new UpgradeEvent($dataArray)); |
||
638 | |||
639 | // A way to keep the upgrade from failing if the session is lost after |
||
640 | // the cache is cleared by upgrade.php |
||
641 | /** @var CookieHelper $cookieHelper */ |
||
642 | $cookieHelper = $this->container->get('mautic.helper.cookie'); |
||
643 | $cookieHelper->deleteCookie('mautic_update'); |
||
644 | |||
645 | // Set a redirect to force a page reload to get new menu items, assets, etc |
||
646 | $dataArray['redirect'] = $this->container->get('router')->generate('mautic_core_update'); |
||
647 | |||
648 | return $this->sendJsonResponse($dataArray); |
||
649 | } |
||
650 | |||
651 | /** |
||
652 | * @return JsonResponse |
||
653 | */ |
||
654 | protected function clearNotificationAction(Request $request) |
||
655 | { |
||
656 | $id = (int) $request->get('id', 0); |
||
657 | |||
658 | /** @var \Mautic\CoreBundle\Model\NotificationModel $model */ |
||
659 | $model = $this->getModel('core.notification'); |
||
660 | $model->clearNotification($id, 200); |
||
661 | |||
662 | return $this->sendJsonResponse(['success' => 1]); |
||
663 | } |
||
664 | |||
665 | /** |
||
666 | * @return JsonResponse |
||
667 | */ |
||
668 | protected function getBuilderTokensAction(Request $request) |
||
669 | { |
||
670 | $tokens = []; |
||
671 | |||
672 | if (method_exists($this, 'getBuilderTokens')) { |
||
673 | $query = $request->get('query'); |
||
674 | $tokens = $this->getBuilderTokens($query); |
||
675 | } |
||
676 | |||
677 | return $this->sendJsonResponse($tokens); |
||
678 | } |
||
679 | |||
680 | /** |
||
681 | * Fetch remote data store. |
||
682 | * |
||
683 | * @return JsonResponse |
||
684 | */ |
||
685 | protected function downloadIpLookupDataStoreAction(Request $request) |
||
686 | { |
||
687 | $dataArray = ['success' => 0]; |
||
688 | |||
689 | if ($request->request->has('service')) { |
||
690 | $serviceName = $request->request->get('service'); |
||
691 | $serviceAuth = $request->request->get('auth'); |
||
692 | |||
693 | /** @var \Mautic\CoreBundle\Factory\IpLookupFactory $ipServiceFactory */ |
||
694 | $ipServiceFactory = $this->container->get('mautic.ip_lookup.factory'); |
||
695 | $ipService = $ipServiceFactory->getService($serviceName, $serviceAuth); |
||
696 | |||
697 | if ($ipService instanceof AbstractLocalDataLookup) { |
||
698 | if ($ipService->downloadRemoteDataStore()) { |
||
699 | $dataArray['success'] = 1; |
||
700 | $dataArray['message'] = $this->container->get('translator')->trans('mautic.core.success'); |
||
701 | } else { |
||
702 | $remoteUrl = $ipService->getRemoteDateStoreDownloadUrl(); |
||
703 | $localPath = $ipService->getLocalDataStoreFilepath(); |
||
704 | |||
705 | if ($remoteUrl && $localPath) { |
||
706 | $dataArray['error'] = $this->container->get('translator')->trans( |
||
707 | 'mautic.core.ip_lookup.remote_fetch_error', |
||
708 | [ |
||
709 | '%remoteUrl%' => $remoteUrl, |
||
710 | '%localPath%' => $localPath, |
||
711 | ] |
||
712 | ); |
||
713 | } else { |
||
714 | $dataArray['error'] = $this->container->get('translator')->trans( |
||
715 | 'mautic.core.ip_lookup.remote_fetch_error_generic' |
||
716 | ); |
||
717 | } |
||
718 | } |
||
719 | } |
||
720 | } |
||
721 | |||
722 | return $this->sendJsonResponse($dataArray); |
||
723 | } |
||
724 | |||
725 | /** |
||
726 | * Fetch IP Lookup form. |
||
727 | * |
||
728 | * @return JsonResponse |
||
729 | */ |
||
730 | protected function getIpLookupFormAction(Request $request) |
||
731 | { |
||
732 | $dataArray = ['html' => '', 'attribution' => '']; |
||
733 | |||
734 | if ($request->request->has('service')) { |
||
735 | $serviceName = $request->request->get('service'); |
||
736 | |||
737 | /** @var \Mautic\CoreBundle\Factory\IpLookupFactory $ipServiceFactory */ |
||
738 | $ipServiceFactory = $this->container->get('mautic.ip_lookup.factory'); |
||
739 | $ipService = $ipServiceFactory->getService($serviceName); |
||
740 | |||
741 | if ($ipService instanceof AbstractLookup) { |
||
742 | $dataArray['attribution'] = $ipService->getAttribution(); |
||
743 | if ($ipService instanceof IpLookupFormInterface) { |
||
744 | if ($formType = $ipService->getConfigFormService()) { |
||
745 | $themes = $ipService->getConfigFormThemes(); |
||
746 | $themes[] = 'MauticCoreBundle:FormTheme\Config'; |
||
747 | |||
748 | $form = $this->get('form.factory')->create($formType, [], ['ip_lookup_service' => $ipService]); |
||
749 | $html = $this->renderView( |
||
750 | 'MauticCoreBundle:FormTheme\Config:ip_lookup_config_row.html.php', |
||
751 | [ |
||
752 | 'form' => $this->setFormTheme($form, 'MauticCoreBundle:FormTheme\Config:ip_lookup_config_row.html.php', $themes), |
||
753 | ] |
||
754 | ); |
||
755 | |||
756 | $html = str_replace($formType.'_', 'config_coreconfig_ip_lookup_config_', $html); |
||
757 | $html = str_replace($formType, 'config[coreconfig][ip_lookup_config]', $html); |
||
758 | $dataArray['html'] = $html; |
||
759 | } |
||
760 | } |
||
761 | } |
||
762 | } |
||
763 | |||
764 | return $this->sendJsonResponse($dataArray); |
||
765 | } |
||
766 | } |
||
767 |