|
@@ -0,0 +1,184 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace WorkflowBundle\Controller;
|
|
|
+
|
|
|
+use Base\AdminBundle\Controller\CRUDController as BaseCRUDController;
|
|
|
+use Doctrine\Common\Inflector\Inflector;
|
|
|
+use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
|
+use Symfony\Component\HttpFoundation\Response;
|
|
|
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
|
+use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
|
|
|
+use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
|
|
+
|
|
|
+class CRUDController extends BaseCRUDController
|
|
|
+{
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Batch action.
|
|
|
+ *
|
|
|
+ * @return Response|RedirectResponse
|
|
|
+ *
|
|
|
+ * @throws NotFoundHttpException If the HTTP method is not POST
|
|
|
+ * @throws \RuntimeException If the batch action is not defined
|
|
|
+ */
|
|
|
+ public function batchAction()
|
|
|
+ {
|
|
|
+ $request = $this->getRequest();
|
|
|
+ $restMethod = $this->getRestMethod();
|
|
|
+
|
|
|
+ if ('POST' !== $restMethod) {
|
|
|
+ throw $this->createNotFoundException(sprintf('Invalid request type "%s", POST expected', $restMethod));
|
|
|
+ }
|
|
|
+
|
|
|
+ // check the csrf token
|
|
|
+ $this->validateCsrfToken('sonata.batch');
|
|
|
+
|
|
|
+ $confirmation = $request->get('confirmation', false);
|
|
|
+
|
|
|
+ if ($data = json_decode($request->get('data'), true)) {
|
|
|
+ $action = $data['action'];
|
|
|
+ $idx = $data['idx'];
|
|
|
+ $allElements = $data['all_elements'];
|
|
|
+ $request->request->replace(array_merge($request->request->all(), $data));
|
|
|
+ } else {
|
|
|
+ $request->request->set('idx', $request->get('idx', array()));
|
|
|
+ $request->request->set('all_elements', $request->get('all_elements', false));
|
|
|
+
|
|
|
+ $action = $request->get('action');
|
|
|
+ $idx = $request->get('idx');
|
|
|
+ $allElements = $request->get('all_elements');
|
|
|
+ $data = $request->request->all();
|
|
|
+
|
|
|
+ unset($data['_sonata_csrf_token']);
|
|
|
+ }
|
|
|
+
|
|
|
+ // NEXT_MAJOR: Remove reflection check.
|
|
|
+ $reflector = new \ReflectionMethod($this->admin, 'getBatchActions');
|
|
|
+ if ($reflector->getDeclaringClass()->getName() === get_class($this->admin)) {
|
|
|
+ @trigger_error('Override Sonata\AdminBundle\Admin\AbstractAdmin::getBatchActions method'
|
|
|
+ . ' is deprecated since version 3.2.'
|
|
|
+ . ' Use Sonata\AdminBundle\Admin\AbstractAdmin::configureBatchActions instead.'
|
|
|
+ . ' The method will be final in 4.0.', E_USER_DEPRECATED
|
|
|
+ );
|
|
|
+ }
|
|
|
+ $batchActions = $this->admin->getBatchActions();
|
|
|
+ if (!array_key_exists($action, $batchActions)) {
|
|
|
+ throw new \RuntimeException(sprintf('The `%s` batch action is not defined', $action));
|
|
|
+ }
|
|
|
+
|
|
|
+ $camelizedAction = Inflector::classify($action);
|
|
|
+ $isRelevantAction = sprintf('batchAction%sIsRelevant', $camelizedAction);
|
|
|
+
|
|
|
+ if (method_exists($this, $isRelevantAction)) {
|
|
|
+ $nonRelevantMessage = call_user_func(array($this, $isRelevantAction), $idx, $allElements, $request);
|
|
|
+ } else {
|
|
|
+ $nonRelevantMessage = count($idx) != 0 || $allElements; // at least one item is selected
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$nonRelevantMessage) { // default non relevant message (if false of null)
|
|
|
+ $nonRelevantMessage = 'flash_batch_empty';
|
|
|
+ }
|
|
|
+
|
|
|
+ $datagrid = $this->admin->getDatagrid();
|
|
|
+ $datagrid->buildPager();
|
|
|
+
|
|
|
+ if (true !== $nonRelevantMessage) {
|
|
|
+ $this->addFlash('sonata_flash_info', $nonRelevantMessage);
|
|
|
+
|
|
|
+ return new RedirectResponse(
|
|
|
+ $this->admin->generateUrl(
|
|
|
+ 'list', array('filter' => $this->admin->getFilterParameters())
|
|
|
+ )
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ $askConfirmation = isset($batchActions[$action]['ask_confirmation']) ?
|
|
|
+ $batchActions[$action]['ask_confirmation'] :
|
|
|
+ true;
|
|
|
+
|
|
|
+ if ($askConfirmation && $confirmation != 'ok') {
|
|
|
+ $actionLabel = $batchActions[$action]['label'];
|
|
|
+ $batchTranslationDomain = isset($batchActions[$action]['translation_domain']) ?
|
|
|
+ $batchActions[$action]['translation_domain'] :
|
|
|
+ $this->admin->getTranslationDomain();
|
|
|
+
|
|
|
+ $formView = $datagrid->getForm()->createView();
|
|
|
+ $this->setFormTheme($formView, $this->admin->getFilterTheme());
|
|
|
+
|
|
|
+ return $this->render($this->admin->getTemplate('batch_confirmation'), array(
|
|
|
+ 'action' => 'list',
|
|
|
+ 'action_label' => $actionLabel,
|
|
|
+ 'batch_translation_domain' => $batchTranslationDomain,
|
|
|
+ 'datagrid' => $datagrid,
|
|
|
+ 'form' => $formView,
|
|
|
+ 'data' => $data,
|
|
|
+ 'csrf_token' => $this->getCsrfToken('sonata.batch'),
|
|
|
+ ), null);
|
|
|
+ }
|
|
|
+
|
|
|
+ $workflowBatchAction = isset($batchActions[$action]['workflow']) ?: false;
|
|
|
+
|
|
|
+ // execute the action, batchActionXxxxx
|
|
|
+ $finalAction = sprintf('batchAction%s', $camelizedAction);
|
|
|
+ if (!is_callable(array($this, $finalAction)) && !$workflowBatchAction) {
|
|
|
+ throw new \RuntimeException(sprintf('A `%s::%s` method must be callable', get_class($this), $finalAction));
|
|
|
+ }
|
|
|
+
|
|
|
+ $query = $datagrid->getQuery();
|
|
|
+
|
|
|
+ $query->setFirstResult(null);
|
|
|
+ $query->setMaxResults(null);
|
|
|
+
|
|
|
+ $this->allElementsBatch = $allElements;
|
|
|
+ $this->admin->preBatchAction($action, $query, $idx, $allElements);
|
|
|
+
|
|
|
+ if (count($idx) > 0) {
|
|
|
+ $this->admin->getModelManager()->addIdentifiersToQuery($this->admin->getClass(), $query, $idx);
|
|
|
+ } elseif (!$allElements) {
|
|
|
+ $query = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($workflowBatchAction) {
|
|
|
+ return $this->runWorkflowBatchAction($batchActions[$action]['workflow'], $query);
|
|
|
+ }
|
|
|
+
|
|
|
+ return call_user_func(array($this, $finalAction), $query, $request);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param array $workflow
|
|
|
+ * @param ProxyQueryInterface $selectedModelQuery
|
|
|
+ *
|
|
|
+ * @return RedirectResponse
|
|
|
+ */
|
|
|
+ public function runWorkflowBatchAction($workflow, ProxyQueryInterface $selectedModelQuery)
|
|
|
+ {
|
|
|
+ if ($this->admin->isGranted('EDIT') === false || $this->admin->isGranted('DELETE') === false) {
|
|
|
+ throw new AccessDeniedException();
|
|
|
+ }
|
|
|
+ $session = $this->get('session')->getFlashBag();
|
|
|
+ $translator = $this->get('translator');
|
|
|
+ try {
|
|
|
+ $workflowRegistry = $this->get('workflow.registry');
|
|
|
+ $em = $this->get('doctrine.orm.entity_manager');
|
|
|
+
|
|
|
+ $selectedModels = $selectedModelQuery->execute();
|
|
|
+ foreach ($selectedModels as $selectedModel) {
|
|
|
+ if ($workflowRegistry->get($selectedModel, $workflow['name'])->can($selectedModel, $workflow['transition'])) {
|
|
|
+ $workflowName = "{$selectedModel->getWorkflowType()}.{$selectedModel->getWorkflowName()}";
|
|
|
+ $this->get($workflowName)->apply($selectedModel, $workflow['transition']);
|
|
|
+
|
|
|
+ $em->persist($selectedModel);
|
|
|
+ $em->flush($selectedModel);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $session->add('sonata_flash_success', $translator->trans('flash_workflow_batch_success', array(), 'WorkflowBundle'));
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $session->add('sonata_flash_error', $translator->trans('flash_workflow_batch_error', array(), 'WorkflowBundle'));
|
|
|
+ $session->add('sonata_flash_error', $e->getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ return new RedirectResponse($this->admin->generateUrl('list', array('filter' => $this->admin->getFilterParameters())));
|
|
|
+ }
|
|
|
+
|
|
|
+}
|