Ok I managed to get this working eventually. I wasn't able to benefit from using the $parentAssociationMapping
property of the CommentAdmin class, as the parent entity of a comment is a concrete instance of the Thread entity whereas the parent 'admin' class in this case is a Story (which is linked via the StoryThread). Plus this will need to remain dynamic for when I implement comments on other types of entity.
First of all, I had to configure my StoryAdmin (and any other admin classes that will have CommentAdmin as a child) to call the addChild method:
acme_story.admin.story:
class: Acme\Bundle\StoryBundle\Admin\StoryAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: content, label: Stories }
arguments: [null, Acme\Bundle\StoryBundle\Entity\Story, AcmeStoryBundle:StoryAdmin]
calls:
- [ addChild, [ @acme_comment.admin.comment ] ]
- [ setSecurityContext, [ @security.context ] ]
This allowed me to link to the child admin section from the story admin, in my case from a side menu, like so:
protected function configureSideMenu(MenuItemInterface $menu, $action, Admin $childAdmin = null)
{
// ...other side menu stuff
$menu->addChild(
'comments',
array('uri' => $admin->generateUrl('acme_comment.admin.comment.list', array('id' => $id)))
);
}
Then, in my CommentAdmin class, I had to access the relevant Thread entity based on the parent object (e.g a StoryThread in this case) and set this as a filter parameter. This is essentially what is done automatically using the $parentAssociationMapping
property if the parent entity is the same as the parent admin, which it most likely will be if you aren't using inheritance mapping. Here is the required code from CommentAdmin:
/**
* @param \Sonata\AdminBundle\Datagrid\DatagridMapper $filter
*/
protected function configureDatagridFilters(DatagridMapper $filter)
{
$filter->add('thread');
}
/**
* @return array
*/
public function getFilterParameters()
{
$parameters = parent::getFilterParameters();
return array_merge($parameters, array(
'thread' => array('value' => $this->getThread()->getId())
));
}
public function getNewInstance()
{
$comment = parent::getNewInstance();
$comment->setThread($this->getThread());
$comment->setAuthor($this->securityContext->getToken()->getUser());
return $comment;
}
/**
* @return CommentableInterface
*/
protected function getParentObject()
{
return $this->getParent()->getObject($this->getParent()->getRequest()->get('id'));
}
/**
* @return object Thread
*/
protected function getThread()
{
/** @var $threadRepository ThreadRepository */
$threadRepository = $this->em->getRepository($this->getParentObject()->getThreadEntityName());
return $threadRepository->findOneBy(array(
$threadRepository->getObjectColumn() => $this->getParentObject()->getId()
));
}
/**
* @param \Doctrine\ORM\EntityManager $em
*/
public function setEntityManager($em)
{
$this->em = $em;
}
/**
* @param \Symfony\Component\Security\Core\SecurityContextInterface $securityContext
*/
public function setSecurityContext(SecurityContextInterface $securityContext)
{
$this->securityContext = $securityContext;
}