/**
  * Retrieves the menu based on the group options.
  *
  * @param string $name
  * @param array  $options
  *
  * @return \Knp\Menu\ItemInterface
  *
  * @throws \InvalidArgumentException if the menu does not exists
  */
 public function get($name, array $options = array())
 {
     $group = $options['group'];
     $menuItem = $this->menuFactory->createItem($options['name'], array('label' => $group['label']));
     foreach ($group['items'] as $item) {
         if (isset($item['admin']) && !empty($item['admin'])) {
             $admin = $this->pool->getInstance($item['admin']);
             // skip menu item if no `list` url is available or user doesn't have the LIST access rights
             if (!$admin->hasRoute('list') || !$admin->isGranted('LIST')) {
                 continue;
             }
             $label = $admin->getLabel();
             $options = $admin->generateMenuUrl('list');
             $options['extras'] = array('translation_domain' => $admin->getTranslationDomain(), 'admin' => $admin);
         } else {
             $label = $item['label'];
             $options = array('route' => $item['route'], 'routeParameters' => $item['route_params'], 'extras' => array('translation_domain' => $group['label_catalogue']));
         }
         $menuItem->addChild($label, $options);
     }
     if (false === $menuItem->hasChildren()) {
         $menuItem->setDisplay(false);
     }
     return $menuItem;
 }
 /**
  * {@inheritDoc}
  */
 public function load($resource, $type = null)
 {
     $collection = new SymfonyRouteCollection();
     foreach ($this->adminServiceIds as $id) {
         $admin = $this->pool->getInstance($id);
         foreach ($admin->getRoutes()->getElements() as $code => $route) {
             $collection->add($route->getDefault('_sonata_name'), $route);
         }
         $reflection = new \ReflectionObject($admin);
         $collection->addResource(new FileResource($reflection->getFileName()));
     }
     $reflection = new \ReflectionObject($this->container);
     $collection->addResource(new FileResource($reflection->getFileName()));
     return $collection;
 }
Exemple #3
0
 /**
  * @param ItemInterface $menu
  * @param AdminMenu[] $tree
  * @param int $level
  */
 protected function generateMenu(&$menu, &$tree, $level = 0)
 {
     while (!empty($tree)) {
         $item = array_shift($tree);
         $type = $item->getType();
         $itemLabel = $item->getTitle();
         $itemLevel = $item->getLevel();
         if ($itemLevel == $level) {
             $options = [];
             if (AdminMenu::TYPE_FOLDER !== $type) {
                 $admin = $this->pool->getInstance($item->getServiceId());
                 if ($admin) {
                     $options = $admin->generateMenuUrl('list');
                     $options['extras'] = ['admin' => $admin];
                 } else {
                     $this->logger->alert('Admin not found for class', [$item->getServiceId()]);
                 }
             }
             $child = $menu->addChild($itemLabel, $options);
         } elseif ($itemLevel > $level) {
             array_unshift($tree, $item);
             $this->generateMenu($child, $tree, $itemLevel);
         } else {
             array_unshift($tree, $item);
             break;
         }
     }
 }
 /**
  * Get KnpMenu
  *
  * @param Request $request
  *
  * @return ItemInterface
  */
 public function getKnpMenu(Request $request = null)
 {
     $menuFactory = new MenuFactory();
     $menu = $menuFactory->createItem('root')->setExtra('request', $request);
     foreach ($this->pool->getAdminGroups() as $name => $group) {
         $menu->addChild($name, array('label' => $group['label']))->setAttributes(array('icon' => $group['icon'], 'label_catalogue' => $group['label_catalogue']))->setExtra('roles', $group['roles']);
         foreach ($group['items'] as $item) {
             if (array_key_exists('admin', $item) && $item['admin'] != null) {
                 $admin = $this->pool->getInstance($item['admin']);
                 // skip menu item if no `list` url is available or user doesn't have the LIST access rights
                 if (!$admin->hasRoute('list') || !$admin->isGranted('LIST')) {
                     continue;
                 }
                 $label = $admin->getLabel();
                 $route = $admin->generateUrl('list');
                 $translationDomain = $admin->getTranslationDomain();
             } else {
                 $label = $item['label'];
                 $route = $this->router->generate($item['route'], $item['route_params']);
                 $translationDomain = $group['label_catalogue'];
                 $admin = null;
             }
             $menu[$name]->addChild($label, array('uri' => $route))->setExtra('translationdomain', $translationDomain)->setExtra('admin', $admin);
         }
     }
     return $menu;
 }
 /**
  * @return array
  */
 public function getRoles()
 {
     $roles = array();
     $rolesReadOnly = array();
     if (!$this->securityContext->getToken()) {
         return array($roles, $rolesReadOnly);
     }
     // get roles from the Admin classes
     foreach ($this->pool->getAdminServiceIds() as $id) {
         try {
             $admin = $this->pool->getInstance($id);
         } catch (\Exception $e) {
             continue;
         }
         $isMaster = $admin->isGranted('MASTER');
         $securityHandler = $admin->getSecurityHandler();
         // TODO get the base role from the admin or security handler
         $baseRole = $securityHandler->getBaseRole($admin);
         if (strlen($baseRole) == 0) {
             // the security handler related to the admin does not provide a valid string
             continue;
         }
         foreach ($admin->getSecurityInformation() as $role => $permissions) {
             $role = sprintf($baseRole, $role);
             if ($isMaster) {
                 // if the user has the MASTER permission, allow to grant access the admin roles to other users
                 $roles[$role] = $role;
             } elseif ($this->securityContext->isGranted($role)) {
                 // although the user has no MASTER permission, allow the currently logged in user to view the role
                 $rolesReadOnly[$role] = $role;
             }
         }
     }
     $isMaster = $this->securityContext->isGranted('ROLE_SUPER_ADMIN');
     // get roles from the service container
     foreach ($this->rolesHierarchy as $name => $rolesHierarchy) {
         if ($this->securityContext->isGranted($name) || $isMaster) {
             $roles[$name] = $name . ': ' . implode(', ', $rolesHierarchy);
             foreach ($rolesHierarchy as $role) {
                 if (!isset($roles[$role])) {
                     $roles[$role] = $role;
                 }
             }
         }
     }
     return array($roles, $rolesReadOnly);
 }
 /**
  * Builds sidebar menu.
  *
  * @return ItemInterface
  */
 public function createSidebarMenu()
 {
     $menu = $this->factory->createItem('root', array('extras' => array('request' => $this->request)));
     foreach ($this->pool->getAdminGroups() as $name => $group) {
         $attributes = array();
         $extras = array('icon' => $group['icon'], 'label_catalogue' => $group['label_catalogue'], 'roles' => $group['roles']);
         // Check if the menu group is built by a menu provider
         if (isset($group['provider'])) {
             $subMenu = $this->provider->get($group['provider']);
             $menu->addChild($subMenu)->setExtras(array_merge($subMenu->getExtras(), $extras))->setAttributes(array_merge($subMenu->getAttributes(), $attributes));
             continue;
         }
         // The menu group is built by config
         $menu->addChild($name, array('label' => $group['label'], 'attributes' => $attributes, 'extras' => $extras));
         foreach ($group['items'] as $item) {
             if (isset($item['admin']) && !empty($item['admin'])) {
                 $admin = $this->pool->getInstance($item['admin']);
                 // skip menu item if no `list` url is available or user doesn't have the LIST access rights
                 if (!$admin->hasRoute('list') || !$admin->isGranted('LIST')) {
                     continue;
                 }
                 $label = $admin->getLabel();
                 $options = $admin->generateMenuUrl('list');
                 $options['extras'] = array('translation_domain' => $admin->getTranslationDomain(), 'admin' => $admin);
             } else {
                 $label = $item['label'];
                 $options = array('route' => $item['route'], 'routeParameters' => $item['route_params'], 'extras' => array('translation_domain' => $group['label_catalogue']));
             }
             $menu[$name]->addChild($label, $options);
         }
         if (0 === count($menu[$name]->getChildren())) {
             $menu->removeChild($name);
         }
     }
     $event = new ConfigureMenuEvent($this->factory, $menu);
     $this->eventDispatcher->dispatch(ConfigureMenuEvent::SIDEBAR, $event);
     return $event->getMenu();
 }
 /**
  * @param \Symfony\Component\HttpFoundation\Request $request
  * @return \Symfony\Component\HttpFoundation\Response
  */
 public function setObjectFieldValueAction(Request $request)
 {
     $field = $request->get('field');
     $code = $request->get('code');
     $objectId = $request->get('objectId');
     $value = $request->get('value');
     $context = $request->get('context');
     $admin = $this->pool->getInstance($code);
     // alter should be done by using a post method
     if ($request->getMethod() != 'POST') {
         return new Response(json_encode(array('status' => 'KO', 'message' => 'Expected a POST Request')), 200, array('Content-Type' => 'application/json'));
     }
     $object = $admin->getObject($objectId);
     if (!$object) {
         return new Response(json_encode(array('status' => 'KO', 'message' => 'Object does not exist')), 200, array('Content-Type' => 'application/json'));
     }
     // check user permission
     if (false === $admin->isGranted('EDIT', $object)) {
         return new Response(json_encode(array('status' => 'KO', 'message' => 'Invalid permissions')), 200, array('Content-Type' => 'application/json'));
     }
     if ($context == 'list') {
         $fieldDescription = $admin->getListFieldDescription($field);
     } else {
         return new Response(json_encode(array('status' => 'KO', 'message' => 'Invalid context')), 200, array('Content-Type' => 'application/json'));
     }
     if (!$fieldDescription) {
         return new Response(json_encode(array('status' => 'KO', 'message' => 'The field does not exist')), 200, array('Content-Type' => 'application/json'));
     }
     if (!$fieldDescription->getOption('editable')) {
         return new Response(json_encode(array('status' => 'KO', 'message' => 'The field cannot be edit, editable option must be set to true')), 200, array('Content-Type' => 'application/json'));
     }
     // TODO : call the validator component ...
     $propertyPath = new PropertyPath($field);
     $propertyPath->setValue($object, $value);
     $admin->update($object);
     // render the widget
     // todo : fix this, the twig environment variable is not set inside the extension ...
     $extension = $this->twig->getExtension('sonata_admin');
     $extension->initRuntime($this->twig);
     $content = $extension->renderListElement($object, $fieldDescription);
     return new Response(json_encode(array('status' => 'OK', 'content' => $content)), 200, array('Content-Type' => 'application/json'));
 }
 /**
  * Retrieve list of items for autocomplete form field.
  *
  * @param Request $request
  *
  * @return JsonResponse
  *
  * @throws \RuntimeException
  * @throws AccessDeniedException
  */
 public function retrieveAutocompleteItemsAction(Request $request)
 {
     $admin = $this->pool->getInstance($request->get('admin_code'));
     $admin->setRequest($request);
     $context = $request->get('_context', '');
     if ($context === 'filter' && false === $admin->isGranted('LIST')) {
         throw new AccessDeniedException();
     }
     if ($context !== 'filter' && false === $admin->isGranted('CREATE') && false === $admin->isGranted('EDIT')) {
         throw new AccessDeniedException();
     }
     // subject will be empty to avoid unnecessary database requests and keep autocomplete function fast
     $admin->setSubject($admin->getNewInstance());
     if ($context === 'filter') {
         // filter
         $fieldDescription = $this->retrieveFilterFieldDescription($admin, $request->get('field'));
         $filterAutocomplete = $admin->getDatagrid()->getFilter($fieldDescription->getName());
         $property = $filterAutocomplete->getFieldOption('property');
         $callback = $filterAutocomplete->getFieldOption('callback');
         $minimumInputLength = $filterAutocomplete->getFieldOption('minimum_input_length', 3);
         $itemsPerPage = $filterAutocomplete->getFieldOption('items_per_page', 10);
         $reqParamPageNumber = $filterAutocomplete->getFieldOption('req_param_name_page_number', '_page');
         $toStringCallback = $filterAutocomplete->getFieldOption('to_string_callback');
     } else {
         // create/edit form
         $fieldDescription = $this->retrieveFormFieldDescription($admin, $request->get('field'));
         $formAutocomplete = $admin->getForm()->get($fieldDescription->getName());
         if ($formAutocomplete->getConfig()->getAttribute('disabled')) {
             throw new AccessDeniedException('Autocomplete list can`t be retrieved because the form element is disabled or read_only.');
         }
         $property = $formAutocomplete->getConfig()->getAttribute('property');
         $callback = $formAutocomplete->getConfig()->getAttribute('callback');
         $minimumInputLength = $formAutocomplete->getConfig()->getAttribute('minimum_input_length');
         $itemsPerPage = $formAutocomplete->getConfig()->getAttribute('items_per_page');
         $reqParamPageNumber = $formAutocomplete->getConfig()->getAttribute('req_param_name_page_number');
         $toStringCallback = $formAutocomplete->getConfig()->getAttribute('to_string_callback');
     }
     $searchText = $request->get('q');
     $targetAdmin = $fieldDescription->getAssociationAdmin();
     // check user permission
     if (false === $targetAdmin->isGranted('LIST')) {
         throw new AccessDeniedException();
     }
     if (mb_strlen($searchText, 'UTF-8') < $minimumInputLength) {
         return new JsonResponse(array('status' => 'KO', 'message' => 'Too short search string.'), 403);
     }
     $targetAdmin->setPersistFilters(false);
     $datagrid = $targetAdmin->getDatagrid();
     if ($callback !== null) {
         if (!is_callable($callback)) {
             throw new \RuntimeException('Callback does not contain callable function.');
         }
         call_user_func($callback, $targetAdmin, $property, $searchText);
     } else {
         if (is_array($property)) {
             // multiple properties
             foreach ($property as $prop) {
                 if (!$datagrid->hasFilter($prop)) {
                     throw new \RuntimeException(sprintf('To retrieve autocomplete items, you should add filter "%s" to "%s" in configureDatagridFilters() method.', $prop, get_class($targetAdmin)));
                 }
                 $filter = $datagrid->getFilter($prop);
                 $filter->setCondition(FilterInterface::CONDITION_OR);
                 $datagrid->setValue($prop, null, $searchText);
             }
         } else {
             if (!$datagrid->hasFilter($property)) {
                 throw new \RuntimeException(sprintf('To retrieve autocomplete items, you should add filter "%s" to "%s" in configureDatagridFilters() method.', $property, get_class($targetAdmin)));
             }
             $datagrid->setValue($property, null, $searchText);
         }
     }
     $datagrid->setValue('_per_page', null, $itemsPerPage);
     $datagrid->setValue('_page', null, $request->query->get($reqParamPageNumber, 1));
     $datagrid->buildPager();
     $pager = $datagrid->getPager();
     $items = array();
     $results = $pager->getResults();
     foreach ($results as $entity) {
         if ($toStringCallback !== null) {
             if (!is_callable($toStringCallback)) {
                 throw new \RuntimeException('Option "to_string_callback" does not contain callable function.');
             }
             $label = call_user_func($toStringCallback, $entity, $property);
         } else {
             $resultMetadata = $targetAdmin->getObjectMetadata($entity);
             $label = $resultMetadata->getTitle();
         }
         $items[] = array('id' => $admin->id($entity), 'label' => $label);
     }
     return new JsonResponse(array('status' => 'OK', 'more' => !$pager->isLastPage(), 'items' => $items));
 }
 /**
  * @deprecated
  *
  * @param string $code
  *
  * @return AdminInterface
  */
 public function getAdmin($code)
 {
     return $this->pool->getInstance($code);
 }
 /**
  * @expectedException \InvalidArgumentException
  * @expectedExceptionMessage Admin service "sonata.news.admin.post" not found in admin pool.
  */
 public function testGetInstanceWithUndefinedServiceId()
 {
     $this->pool->getInstance('sonata.news.admin.post');
 }
 /**
  * @param Request $request
  *
  * @return Response
  *
  * @throws AccessDeniedException
  */
 public function autoCompleteAction(Request $request)
 {
     /** @var Admin $admin */
     $admin = $this->pool->getInstance($request->get('code'));
     $admin->setRequest($request);
     // check user permission
     if (false === $admin->isGranted('LIST')) {
         throw new AccessDeniedException();
     }
     // subject will be empty to avoid unnecessary database requests and keep auto-complete function fast
     $admin->setSubject($admin->getNewInstance());
     $fieldDescription = $this->retrieveFieldDescription($admin, $request->get('field'));
     $formAutocomplete = $admin->getForm()->get($fieldDescription->getName());
     if ($formAutocomplete->getConfig()->getAttribute('disabled')) {
         throw new AccessDeniedException('Autocomplete list can`t be retrieved because the form element is disabled or read_only.');
     }
     $class = $formAutocomplete->getConfig()->getOption('class');
     $property = $formAutocomplete->getConfig()->getAttribute('property');
     $minimumInputLength = $formAutocomplete->getConfig()->getAttribute('minimum_input_length');
     $itemsPerPage = $formAutocomplete->getConfig()->getAttribute('items_per_page');
     $reqParamPageNumber = $formAutocomplete->getConfig()->getAttribute('req_param_name_page_number');
     $toStringCallback = $formAutocomplete->getConfig()->getAttribute('to_string_callback');
     $searchText = $request->get('q');
     if (mb_strlen($searchText, 'UTF-8') < $minimumInputLength) {
         return new JsonResponse(array('status' => 'KO', 'message' => 'Too short search string.'), 403);
     }
     $page = $request->get($reqParamPageNumber);
     $offset = ($page - 1) * $itemsPerPage;
     /** @var ModelManager $modelManager */
     $modelManager = $formAutocomplete->getConfig()->getOption('model_manager');
     $dm = $modelManager->getDocumentManager();
     if ($class) {
         /** @var $qb \Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder */
         $qb = $dm->getRepository($class)->createQueryBuilder('a');
         $qb->where()->fullTextSearch("a.{$property}", '*' . $searchText . '*');
         $qb->setFirstResult($offset);
         //fetch one more to determine if there are more pages
         $qb->setMaxResults($itemsPerPage + 1);
         $query = $qb->getQuery();
         $results = $query->execute();
     } else {
         /** @var $qb \PHPCR\Util\QOM\QueryBuilder */
         $qb = $dm->createPhpcrQueryBuilder();
         // TODO: node type should probably be configurable
         $qb->from($qb->getQOMFactory()->selector('a', 'nt:unstructured'));
         $qb->where($qb->getQOMFactory()->fullTextSearch('a', $property, '*' . $searchText . '*'));
         // handle attribute translation
         $qb->orWhere($qb->getQOMFactory()->fullTextSearch('a', $dm->getTranslationStrategy('attribute')->getTranslatedPropertyName($request->getLocale(), $property), '*' . $searchText . '*'));
         $qb->setFirstResult($offset);
         //fetch one more to determine if there are more pages
         $qb->setMaxResults($itemsPerPage + 1);
         $results = $dm->getDocumentsByPhpcrQuery($qb->getQuery());
     }
     //did we max out x+1
     $more = count($results) == $itemsPerPage + 1;
     $method = $request->get('_method_name');
     $items = array();
     foreach ($results as $path => $document) {
         // handle child translation
         if (strpos(PathHelper::getNodeName($path), Translation::LOCALE_NAMESPACE . ':') === 0) {
             $document = $dm->find(null, PathHelper::getParentPath($path));
         }
         if (!method_exists($document, $method)) {
             continue;
         }
         $label = $document->{$method}();
         if ($toStringCallback !== null) {
             if (!is_callable($toStringCallback)) {
                 throw new \RuntimeException('Option "to_string_callback" does not contain callable function.');
             }
             $label = call_user_func($toStringCallback, $document, $property);
         }
         $items[] = array('id' => $admin->id($document), 'label' => $label);
     }
     return new JsonResponse(array('status' => 'OK', 'more' => $more, 'items' => $items));
 }
 /**
  * @param  \Symfony\Component\HttpFoundation\Request $request
  *
  * @return \Symfony\Component\HttpFoundation\Response
  */
 public function setObjectFieldValueAction(Request $request)
 {
     $field = $request->get('field');
     $code = $request->get('code');
     $objectId = $request->get('objectId');
     $value = $request->get('value');
     $context = $request->get('context');
     $admin = $this->pool->getInstance($code);
     $admin->setRequest($request);
     // alter should be done by using a post method
     if (!$request->isXmlHttpRequest()) {
         return new JsonResponse(array('status' => 'KO', 'message' => 'Expected a XmlHttpRequest request header'));
     }
     if ($request->getMethod() != 'POST') {
         return new JsonResponse(array('status' => 'KO', 'message' => 'Expected a POST Request'));
     }
     $rootObject = $object = $admin->getObject($objectId);
     if (!$object) {
         return new JsonResponse(array('status' => 'KO', 'message' => 'Object does not exist'));
     }
     // check user permission
     if (false === $admin->isGranted('EDIT', $object)) {
         return new JsonResponse(array('status' => 'KO', 'message' => 'Invalid permissions'));
     }
     if ($context == 'list') {
         $fieldDescription = $admin->getListFieldDescription($field);
     } else {
         return new JsonResponse(array('status' => 'KO', 'message' => 'Invalid context'));
     }
     if (!$fieldDescription) {
         return new JsonResponse(array('status' => 'KO', 'message' => 'The field does not exist'));
     }
     if (!$fieldDescription->getOption('editable')) {
         return new JsonResponse(array('status' => 'KO', 'message' => 'The field cannot be edit, editable option must be set to true'));
     }
     $propertyAccessor = PropertyAccess::createPropertyAccessor();
     $propertyPath = new PropertyPath($field);
     // If property path has more than 1 element, take the last object in order to validate it
     if ($propertyPath->getLength() > 1) {
         $object = $propertyAccessor->getValue($object, $propertyPath->getParent());
         $elements = $propertyPath->getElements();
         $field = end($elements);
         $propertyPath = new PropertyPath($field);
     }
     $propertyAccessor->setValue($object, $propertyPath, '' !== $value ? $value : null);
     $violations = $this->validator->validateProperty($object, $field);
     if (count($violations)) {
         $messages = array();
         foreach ($violations as $violation) {
             $messages[] = $violation->getMessage();
         }
         return new JsonResponse(array('status' => 'KO', 'message' => implode("\n", $messages)));
     }
     $admin->update($object);
     // render the widget
     // todo : fix this, the twig environment variable is not set inside the extension ...
     $extension = $this->twig->getExtension('sonata_admin');
     $extension->initRuntime($this->twig);
     $content = $extension->renderListElement($rootObject, $fieldDescription);
     return new JsonResponse(array('status' => 'OK', 'content' => $content));
 }
 /**
  * {@inheritdoc}
  */
 public function warmUp($cacheDir)
 {
     foreach ($this->pool->getAdminServiceIds() as $id) {
         $this->cache->load($this->pool->getInstance($id));
     }
 }