Skip to content

Commit

Permalink
@dypa: working new item button for nested (> 2nd level) inline collec…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
Jorge Luis Gomez (desktop 1) committed Jun 6, 2015
1 parent 16474a3 commit ea12654
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 151 deletions.
118 changes: 42 additions & 76 deletions Admin/AdminHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use Sonata\AdminBundle\Exception\NoValueException;
use Sonata\AdminBundle\Util\FormViewIterator;
use Sonata\AdminBundle\Util\FormBuilderIterator;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Doctrine\Common\Collections\ArrayCollection;

/**
* Class AdminHelper
Expand All @@ -37,25 +39,6 @@ public function __construct(Pool $pool)
$this->pool = $pool;
}

/**
* @throws \RuntimeException
*
* @param \Symfony\Component\Form\FormBuilderInterface $formBuilder
* @param string $elementId
*
* @return \Symfony\Component\Form\FormBuilderInterface
*/
public function getChildFormBuilder(FormBuilderInterface $formBuilder, $elementId)
{
foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) {
if ($name == $elementId) {
return $formBuilder;
}
}

return null;
}

/**
* @param \Symfony\Component\Form\FormView $formView
* @param string $elementId
Expand Down Expand Up @@ -108,82 +91,65 @@ public function appendFormFieldElement(AdminInterface $admin, $subject, $element
$form->setData($subject);
$form->handleRequest($admin->getRequest());

// get the field element
$childFormBuilder = $this->getChildFormBuilder($formBuilder, $elementId);

// retrieve the FieldDescription
$fieldDescription = $admin->getFormFieldDescription($childFormBuilder->getName());

try {
$value = $fieldDescription->getValue($form->getData());
} catch (NoValueException $e) {
$value = null;
}

// retrieve the posted data
$data = $admin->getRequest()->get($formBuilder->getName());

if (!isset($data[$childFormBuilder->getName()])) {
$data[$childFormBuilder->getName()] = array();
}

$objectCount = count($value);
$postCount = count($data[$childFormBuilder->getName()]);

$fields = array_keys($fieldDescription->getAssociationAdmin()->getFormFieldDescriptions());
$elementId = preg_replace('#.(\d+)#', '[$1]', implode('.', explode('_', substr($elementId, strpos($elementId, '_') + 1))));

// for now, not sure how to do that
$value = array();
foreach ($fields as $name) {
$value[$name] = '';
}

// add new elements to the subject
while ($objectCount < $postCount) {
// append a new instance into the object
$this->addNewInstance($form->getData(), $fieldDescription);
$objectCount++;
}

$this->addNewInstance($form->getData(), $fieldDescription);
// append a new instance into the object
$this->addNewInstance($admin, $elementId);

// return new form with empty row
$finalForm = $admin->getFormBuilder()->getForm();
$finalForm->setData($subject);

// bind the data
$finalForm->setData($form->getData());

return array($fieldDescription, $finalForm);
return $finalForm;
}

/**
* Add a new instance to the related FieldDescriptionInterface value
* Add a new instance
*
* @param object $object
* @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
* @param AdminInterface $admin
* @param string $elementId
*
* @throws \RuntimeException
* @throws \Exception
*/
public function addNewInstance($object, FieldDescriptionInterface $fieldDescription)
public function addNewInstance(AdminInterface $admin, $elementId)
{
$instance = $fieldDescription->getAssociationAdmin()->getNewInstance();
$mapping = $fieldDescription->getAssociationMapping();
$entity = $admin->getSubject();

$method = sprintf('add%s', $this->camelize($mapping['fieldName']));
$propertyAccessor = new PropertyAccessor();

if (!method_exists($object, $method)) {
$method = rtrim($method, 's');
$collection = $propertyAccessor->getValue($entity, $elementId);

if (!method_exists($object, $method)) {
$method = sprintf('add%s', $this->camelize(Inflector::singularize($mapping['fieldName'])));
if ($collection instanceof \Doctrine\ORM\PersistentCollection || $collection instanceof \Doctrine\ODM\MongoDB\PersistentCollection) {
//since doctrine 2.4
$entityClassName = $collection->getTypeClass()->getName();
} elseif ($collection instanceof \Doctrine\Common\Collections\Collection) {
$entityClassName = $this->entityClassNameFinder($admin, explode('.', preg_replace('#\[\d*?\]#', '', $elementId)));
} else {
return;
}

if (!method_exists($object, $method)) {
throw new \RuntimeException(sprintf('Please add a method %s in the %s class!', $method, ClassUtils::getClass($object)));
}
}
if (!method_exists($collection, 'add')){
return;
}

$object->$method($instance);
$collection->add(new $entityClassName);

$propertyAccessor->setValue($entity, $elementId, $collection);
}


protected function entityClassNameFinder(AdminInterface $admin, $elements)
{
$element = array_shift($elements);

$associationAdmin = $admin->getFormFieldDescription($element)->getAssociationAdmin();

if (count($elements) == 0) {
return $associationAdmin->getClass();
} else {
return $this->entityClassNameFinder($associationAdmin, $elements);
}
}

/**
Expand Down
8 changes: 2 additions & 6 deletions Controller/HelperController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Sonata\AdminBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
Expand Down Expand Up @@ -98,7 +99,7 @@ public function appendFormFieldElementAction(Request $request)

$admin->setSubject($subject);

list(, $form) = $this->helper->appendFormFieldElement($admin, $subject, $elementId);
$form = $this->helper->appendFormFieldElement($admin, $subject, $elementId);

/** @var $form \Symfony\Component\Form\Form */
$view = $this->helper->getChildFormView($form->createView(), $elementId);
Expand Down Expand Up @@ -229,7 +230,6 @@ public function setObjectFieldValueAction(Request $request)

$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'));
Expand Down Expand Up @@ -270,7 +270,6 @@ public function setObjectFieldValueAction(Request $request)
// 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);
Expand All @@ -282,16 +281,13 @@ public function setObjectFieldValueAction(Request $request)

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');
Expand Down
Loading

0 comments on commit ea12654

Please sign in to comment.