/**
  * Returns the Response object associated to the acl action.
  *
  * @param int|string|null $id
  *
  * @return Response|RedirectResponse
  *
  * @throws AccessDeniedException If access is not granted.
  * @throws NotFoundHttpException If the object does not exist or the ACL is not enabled
  */
 public function aclAction($id = null)
 {
     if (!$this->admin->isAclEnabled()) {
         throw new NotFoundHttpException('ACL are not enabled for this admin');
     }
     $id = $this->get('request')->get($this->admin->getIdParameter());
     $object = $this->admin->getObject($id);
     if (!$object) {
         throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $id));
     }
     if (false === $this->admin->isGranted('MASTER', $object)) {
         throw new AccessDeniedException();
     }
     $this->admin->setSubject($object);
     $aclUsers = $this->getAclUsers();
     $adminObjectAclManipulator = $this->get('sonata.admin.object.manipulator.acl.admin');
     $adminObjectAclData = new AdminObjectAclData($this->admin, $object, $aclUsers, $adminObjectAclManipulator->getMaskBuilderClass());
     $form = $adminObjectAclManipulator->createForm($adminObjectAclData);
     $request = $this->getRequest();
     if ($request->getMethod() === 'POST') {
         $form->submit($request);
         if ($form->isValid()) {
             $adminObjectAclManipulator->updateAcl($adminObjectAclData);
             $this->addFlash('sonata_flash_success', 'flash_acl_edit_success');
             return new RedirectResponse($this->admin->generateObjectUrl('acl', $object));
         }
     }
     return $this->render($this->admin->getTemplate('acl'), array('action' => 'acl', 'permissions' => $adminObjectAclData->getUserPermissions(), 'object' => $object, 'users' => $aclUsers, 'form' => $form->createView()));
 }
 /**
  * @param \Sonata\AdminBundle\Admin\AdminInterface  $admin
  * @param \Sonata\AdminBundle\Route\RouteCollection $collection
  */
 public function build(AdminInterface $admin, RouteCollection $collection)
 {
     $collection->add('list');
     $collection->add('create');
     $collection->add('batch');
     $collection->add('edit');
     $collection->add('delete');
     $collection->add('show');
     $collection->add('export');
     if ($this->manager->hasReader($admin->getClass())) {
         $collection->add('history', '/audit-history');
         $collection->add('history_view_revision', '/audit-history-view');
     }
     if ($admin->isAclEnabled()) {
         $collection->add('acl', $admin->getRouterIdParameter() . '/acl');
     }
     // an admin can have only one level of nested child
     if ($admin->getParent()) {
         return;
     }
     // add children urls
     foreach ($admin->getChildren() as $children) {
         $collection->addCollection($children->getRoutes());
     }
 }
 /**
  * RouteBuilder that allows slashes in the ids.
  *
  * {@inheritDoc}
  */
 function build(AdminInterface $admin, RouteCollection $collection)
 {
     $collection->add('list');
     $collection->add('create');
     $collection->add('batch', null, array(), array('_method' => 'POST'));
     $collection->add('edit', $admin->getRouterIdParameter() . '/edit', array(), array('id' => '.+'));
     $collection->add('delete', $admin->getRouterIdParameter() . '/delete', array(), array('id' => '.+'));
     $collection->add('export');
     $collection->add('show', $admin->getRouterIdParameter() . '/show', array(), array('id' => '.+', '_method' => 'GET'));
     if ($admin->isAclEnabled()) {
         $collection->add('acl', $admin->getRouterIdParameter() . '/acl', array(), array('id' => '.+'));
     }
     // add children urls
     foreach ($admin->getChildren() as $children) {
         $collection->addCollection($children->getRoutes());
     }
 }
 /**
  * Returns the Response object associated to the acl action.
  *
  * @param int|string|null $id
  * @param Request         $request
  *
  * @return Response|RedirectResponse
  *
  * @throws AccessDeniedException If access is not granted.
  * @throws NotFoundHttpException If the object does not exist or the ACL is not enabled
  */
 public function aclAction($id = null)
 {
     $request = $this->getRequest();
     if (!$this->admin->isAclEnabled()) {
         throw $this->createNotFoundException('ACL are not enabled for this admin');
     }
     $id = $request->get($this->admin->getIdParameter());
     $object = $this->admin->getObject($id);
     if (!$object) {
         throw $this->createNotFoundException(sprintf('unable to find the object with id : %s', $id));
     }
     $this->admin->checkAccess('acl', $object);
     $this->admin->setSubject($object);
     $aclUsers = $this->getAclUsers();
     $aclRoles = $this->getAclRoles();
     $adminObjectAclManipulator = $this->get('sonata.admin.object.manipulator.acl.admin');
     $adminObjectAclData = new AdminObjectAclData($this->admin, $object, $aclUsers, $adminObjectAclManipulator->getMaskBuilderClass(), $aclRoles);
     $aclUsersForm = $adminObjectAclManipulator->createAclUsersForm($adminObjectAclData);
     $aclRolesForm = $adminObjectAclManipulator->createAclRolesForm($adminObjectAclData);
     if ($request->getMethod() === 'POST') {
         if ($request->request->has(AdminObjectAclManipulator::ACL_USERS_FORM_NAME)) {
             $form = $aclUsersForm;
             $updateMethod = 'updateAclUsers';
         } elseif ($request->request->has(AdminObjectAclManipulator::ACL_ROLES_FORM_NAME)) {
             $form = $aclRolesForm;
             $updateMethod = 'updateAclRoles';
         }
         if (isset($form)) {
             $form->handleRequest($request);
             if ($form->isValid()) {
                 $adminObjectAclManipulator->{$updateMethod}($adminObjectAclData);
                 $this->addFlash('sonata_flash_success', 'flash_acl_edit_success');
                 return new RedirectResponse($this->admin->generateObjectUrl('acl', $object));
             }
         }
     }
     return $this->render($this->admin->getTemplate('acl'), array('action' => 'acl', 'permissions' => $adminObjectAclData->getUserPermissions(), 'object' => $object, 'users' => $aclUsers, 'roles' => $aclRoles, 'aclUsersForm' => $aclUsersForm->createView(), 'aclRolesForm' => $aclRolesForm->createView()), null, $request);
 }
 /**
  * Filters with ACL
  *
  * @param  AdminInterface      $admin
  * @param  ProxyQueryInterface $query
  * @param  string              $context
  * @throws \RuntimeException
  */
 public function configureQuery(AdminInterface $admin, ProxyQueryInterface $query = null, $query2 = null, $context = 'list', $isTheMaster = false)
 {
     if (!$query) {
         $query = $query2;
     }
     // Don't filter for admins and for not ACL enabled classes and for command cli
     if (!$admin->isAclEnabled() && !method_exists($admin, 'getMasterAclClass') || !$this->securityContext->getToken() || $admin->isGranted(sprintf($admin->getSecurityHandler()->getBaseRole($admin), 'ADMIN'))) {
         return;
     }
     // Retrieve current logged user SecurityIdentity
     $user = $this->securityContext->getToken()->getUser();
     $securityIdentity = UserSecurityIdentity::fromAccount($user);
     // Get identity ACL identifier
     $identifier = sprintf('%s-%s', $securityIdentity->getClass(), $securityIdentity->getUsername());
     $identityStmt = $this->databaseConnection->prepare('SELECT id FROM acl_security_identities WHERE identifier = :identifier');
     $identityStmt->bindValue('identifier', $identifier);
     $identityStmt->execute();
     $identityId = $identityStmt->fetchColumn();
     // Get class ACL identifier
     $classType = $admin->getClass();
     $classStmt = $this->databaseConnection->prepare('SELECT id FROM acl_classes WHERE class_type = :classType');
     $classStmt->bindValue('classType', $classType);
     $classStmt->execute();
     $classId = $classStmt->fetchColumn();
     if ($identityId && ($classId || method_exists($admin, 'getMasterAclClass'))) {
         $entriesStmt = $this->databaseConnection->prepare('SELECT object_identifier FROM acl_entries AS ae JOIN acl_object_identities AS aoi ON ae.object_identity_id = aoi.id WHERE ae.class_id = :classId AND ae.security_identity_id = :identityId AND (:view = ae.mask & :view OR :operator = ae.mask & :operator OR :master = ae.mask & :master OR :owner = ae.mask & :owner)');
         $entriesStmt->bindValue('classId', $classId);
         $entriesStmt->bindValue('identityId', $identityId);
         $entriesStmt->bindValue('view', MaskBuilder::MASK_VIEW);
         $entriesStmt->bindValue('operator', MaskBuilder::MASK_OPERATOR);
         $entriesStmt->bindValue('master', MaskBuilder::MASK_MASTER);
         $entriesStmt->bindValue('owner', MaskBuilder::MASK_OWNER);
         $entriesStmt->execute();
         $ids = array();
         foreach ($entriesStmt->fetchAll() as $row) {
             $ids[] = $row['object_identifier'];
         }
         //Test if method getMasterAclClass and getMasterAclPath exist on the admin CLASS -> SEE THE DOC
         if (method_exists($admin, 'getMasterAclClass') && method_exists($admin, 'getMasterAclPath')) {
             $classStmt = $this->databaseConnection->prepare('SELECT id FROM acl_classes WHERE class_type = :classType');
             //QUERY ON MASTER ACL CLASS (method $admin->getMasterAclClass() return a string like 'Acme\Bundle\Entity\MasterACLEntity');
             $classStmt->bindValue('classType', $admin->getMasterAclClass());
             $classStmt->execute();
             $classId = $classStmt->fetchColumn();
             $entriesStmt = $this->databaseConnection->prepare('SELECT object_identifier FROM acl_entries AS ae JOIN acl_object_identities AS aoi ON ae.object_identity_id = aoi.id WHERE ae.class_id = :classId AND ae.security_identity_id = :identityId AND (:view = ae.mask & :view OR :operator = ae.mask & :operator OR :master = ae.mask & :master OR :owner = ae.mask & :owner)');
             $entriesStmt->bindValue('classId', $classId);
             $entriesStmt->bindValue('identityId', $identityId);
             $entriesStmt->bindValue('view', MaskBuilder::MASK_VIEW);
             $entriesStmt->bindValue('operator', MaskBuilder::MASK_OPERATOR);
             $entriesStmt->bindValue('master', MaskBuilder::MASK_MASTER);
             $entriesStmt->bindValue('owner', MaskBuilder::MASK_OWNER);
             $entriesStmt->execute();
             //ARRAY OF idsMaster
             $idsMaster = array();
             foreach ($entriesStmt->fetchAll() as $row) {
                 $idsMaster[] = $row['object_identifier'];
             }
             $parents = $admin->getMasterAclPath();
             //HERE UPDATE THE QUERY
             if (!$isTheMaster) {
                 //HERE UPDATE THE QUERY
                 foreach ($parents as $key => $parent) {
                     //FIRST shorcut is 'o'
                     if ($key == 0) {
                         $query->leftJoin('o.' . $parent[0], $parent[1]);
                     } else {
                         //Shortcut is precedent shortcut
                         $query->leftJoin($parents[$key - 1][1] . '.' . $parent[0], $parent[1]);
                     }
                     //HERE WE ARE AFTER THE LEFT JOIN ON MASTER ACL CLASS WE PASS idsMaster array param
                     if ($key + 1 == count($parents)) {
                         //HERE FOR OBJECT CREATED BY CURRENT USER AND WITH STRICT MODE IS OF
                         if (count($ids) && method_exists($admin, 'getMasterAclStrict') && !$admin->getMasterAclStrict()) {
                             //OR EXPRESSION WITH PARENTHESIS
                             $orCondition = $query->expr()->orx();
                             $orCondition->add($query->expr()->in('o.id', ':ids'));
                             $orCondition->add($query->expr()->in($parent[1] . '.id', ':idsMaster'));
                             $query->andWhere($orCondition)->setParameter('ids', $ids)->setParameter('idsMaster', $idsMaster);
                         } else {
                             $query->andWhere($parent[1] . '.id IN (:idsMaster' . $key . ')')->setParameter('idsMaster' . $key, $idsMaster);
                         }
                     }
                 }
             } else {
                 $query->andWhere('o.id IN (:idsMaster)')->setParameter('idsMaster', $idsMaster);
             }
             return;
         } elseif (count($ids)) {
             //NORMAL BEHAVIOR
             $query->andWhere('o.id IN (:ids)')->setParameter('ids', $ids);
             return;
         }
     }
     // Display an empty list
     $query->andWhere('1 = 2');
 }