Sonata Custom Action - php

I use Sonata Admin and in list entity I need add my custom action, I did like the sonata document screen, but when I use filter field or click for page, screen, pagination my action disappears, and I have button select. How add custom action and how to make that is not lost?
class CRUDController extends Controller
{
public function cloneAction()
{
$object = $this->admin->getSubject();
$id = $object->getId();
return new RedirectResponse($this->generateUrl('admin_index', array('id' => $id))); //this is my custom action
}
}
add in service CRUD
<service id="sonata.admin.developer" class="Artel\AdminBundle\Controller\DeveloperSonataController">
<tag name="sonata.admin" manager_type="orm" group="Content" label="Developer"/>
<argument />
<argument>Artel\ProfileBundle\Entity\Developer</argument>
<argument>ArtelAdminBundle:CRUD</argument>
<argument />
<call method="setTranslationDomain">
<argument>ArtelAdminBundle</argument>
</call>
<call method="addChild">
<argument type="service" id="sonata.news.admin.comment" />
</call>
</service>
create template
{# src/AppBundle/Resources/views/CRUD/list__action_clone.html.twig #}
//<a class="btn btn-sm" href="{{ admin.generateObjectUrl('clone', object) }}">clone</a>
add routing
class DeveloperSonataController extends Admin
{
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
and in finished I have controller
class DeveloperSonataController extends Admin
{
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('firstName', null, array('label' => 'Developer\'s First Name', 'max_length' => 255))
->add('lastName', null, array('label' => 'Developer\'s Last Name', 'max_length' => 255))
->add('qualification', 'choice', array('label' => 'Speciality',
'choices' => array('Frontend' => 'Frontend', 'Backend' => 'Backend', 'Full stack' => 'Full stack'),'attr'=> array('class'=>'qualif'), 'required' => false))
->add('level', 'choice', array('label' => 'Professional Level', 'max_length' => 255,
'choices' => array('Junior' => 'Junior', 'Middle' => 'Middle', 'Senior' => 'Senior')))
->add('tags', 'tags', array('label' => 'Tags','required' => false))
->add('main_skill', 'mainSkill', array('label' => 'Main Skill', 'required' => true, 'mapped' => true, 'attr' => array('placeholder' => 'Select your skills ...', 'class'=>'main_skill') ))
->add('skills', 'skills', array('label' => 'Skills','required' => false))
->add('english', 'choice', array('label' => 'English Level', 'max_length' => 255,
'choices' => array('Basic' => 'Basic', 'Intermediate' => 'Intermediate', 'Advanced' => 'Advanced')))
->add('rate', null, array('label' => 'Rate $/h', 'max_length' => 255))
;
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('email')
->add('telephone')
->add('skype')
->add('username')
->add('firstName')
->add('lastName')
->add('main_skill')
->add('skills')
->add('level')
->add('rate')
->add('english')
->add('location')
->add('country')
->add('created', 'doctrine_orm_date_range', array('field_type'=>'sonata_type_date_range_picker',))
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')//how change routig in addIdentifier??
->add('username')
->add('firstName')
->add('lastName')
->add('main_skill')
->add('level')
->add('rate')
->add('english')
->add('email')
->add('location')
->add('country')
->add('created')
->add('image', 'string', array('template' => 'SonataMediaBundle:MediaAdmin:list_image.html.twig'))
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'edit' => array(),
'clone' => array(
'template' => 'ArtelAdminBundle:CRUD:list__action_clone.html.twig'
)
)
))
;
}
}

Related

Sonata/AdminBundle: Selected Option

I'm new in Symfony and Sonata/AdminBundle. I would like to know how to mark selected an option when the entity has a field from other entity. For example: I have two entities: Shop and City. The Shop entity has a field called id_city.
My problem is when I'm rendering the edit form Shop because always the first id_city in the option is selected.
This is the piece of code where I'm rendering the configuration form in AdminStores class:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->tab('Tiendas')
->with('Content', array('class' => 'col-md-9'))
->add('nombreTienda', 'text')
->add('cifTienda', 'text')
->add('direccionTienda', 'text')
->add('personaContacto', 'text', array('required' => false,'empty_data' => ''))
->add('cp', 'text', array('label' => 'Código Postal', 'required' => false, 'empty_data' => '00000'))
->add('urlTienda', 'text', array('required' => false, 'empty_data' => ''))
->add('emailTienda', 'text')
->add('telefonoTienda', 'text')
->add('login', 'text')
->add('pass', 'password', array('required' => false))
->add('idMunicipio', 'entity', array(
'class' => 'AppBundle:Municipios',
'choice_label' => 'municipio',
'query_builder' => function (EntityRepository $er) {
$lista = $er->createQueryBuilder('ss')
->orderBy('ss.municipio', 'ASC');
},
'data' => $this->subject->getIdMunicipio()
)) // end array idMunicipio y add()
->add('idProvincia', EntityType::class, array(
'class' => 'AppBundle:Provincias',
'label' => 'Provincia',
'choice_label' => 'provincia',
'choice_value' => 'getId',
'by_reference' => true,
))
->add('descripcionTienda', 'textarea')
->end()
->end()
->tab('Multimedia')
->with('Content', array('class' => 'col-md-3'))
->add('fotoTienda', 'file', array(
'label' => 'Imagenes (puedes subir hasta 6 imágenes)',
'attr' =>array('class' => 'form-control', 'multiple' => 'multiple', 'accept' => 'image/*'),
'data_class' => null,
'required' => false,
'empty_data' => 'noDisponible',
));
}
In this piece of code, I'm recovering all cities in AdminStores class:
->add('idMunicipio', 'entity', array(
'class' => 'AppBundle:Municipios',
'choice_label' => 'municipio',
'query_builder' => function (EntityRepository $er) {
$lista = $er->createQueryBuilder('ss')
->orderBy('ss.municipio', 'ASC');
},
'data' => $this->subject->getIdMunicipio()
)) // end array idMunicipio y add()
I would like to know, please, the logic for " if this->id_city == entity->id_city then, option is selected".
Thanks in advance
I edit this comment because I think that I solved it.
In my AdminController called ShopsAdmin I have created a method called getAllMunicipios which return an array with their name and id:
$allCities = array(
'Tokyo' => 1
'Madrid => 2
);
This is the method:
protected function getAllMunicipios()
{
$municipios = $this->getConfigurationPool()
->getContainer()
->get('doctrine')
->getRepository('AppBundle:Municipios')
->findBy([], ['municipio' => 'ASC']);
$todosmunicipios = array();
foreach ($municipios as $municipio) {
$todosmunicipios[(string)$municipio->getMunicipio()] = (int)$municipio->getId();
}
return $todosmunicipios;
}
Now my AdminStores::configureFormFields method like that this:
->add('idMunicipio', 'choice', array(
'choices' => $this->getAllMunicipios(),
'required' => false,
'by_reference' => false,
'data' => $this->subject->getIdMunicipio()
))
It is a good way to do it? I think that the method that return all, must be placed into the entity and not int the controller but I dont know how do it static
just call setCity(\AppBundle\Entity\City $city) in your Shop entity. and give the right city entity as the first and only parameter. Do this before you render the form

Symfony Sonata admin find by some field

I install SonataAdminBundle and create controller extends Admin and function configureFormFields, configureDatagridFilters, configureListFields. And in field list I use field image but I see only url for image, my image live in amazon S3 I want see image in table. How I do this? And I have filter for find by colums, my entity developer have array skill and by one skill find good but how find for two or many skill ?
And I add for admin can do upload avatar for developer but in my action(not extends Admin) I upload like this for(field image in Developer = string and I set just url for S3)
$url = sprintf(
'%s%s',
$this->container->getParameter('acme_storage.amazon_s3.base_url'),
$this->getPhotoUploader()->upload($request->files->get('file'), $user_company_name)
);
$user->setImage($url);
how I can do for sonata, reload controller? How I do this ?
this my action:
class DeveloperAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('firstName', null, array('label' => 'Developer\'s First Name', 'max_length' => 255))
->add('lastName', null, array('label' => 'Developer\'s Last Name', 'max_length' => 255))
->add('qualification', 'choice', array('label' => 'Speciality',
'choices' => array('Frontend' => 'Frontend', 'Backend' => 'Backend', 'Full stack' => 'Full stack'),'attr'=> array('class'=>'qualif'), 'required' => false))
->add('level', 'choice', array('label' => 'Professional Level', 'max_length' => 255,
'choices' => array('Junior' => 'Junior', 'Middle' => 'Middle', 'Senior' => 'Senior')))
->add('tags', 'tags', array('label' => 'Tags','required' => false))
->add('main_skill', 'mainSkill', array('label' => 'Main Skill', 'required' => true, 'mapped' => true, 'attr' => array('placeholder' => 'Select your skills ...', 'class'=>'main_skill') ))
->add('skills', 'skills', array('label' => 'Skills','required' => false))
->add('english', 'choice', array('label' => 'English Level', 'max_length' => 255,
'choices' => array('Basic' => 'Basic', 'Intermediate' => 'Intermediate', 'Advanced' => 'Advanced')))
->add('rate', null, array('label' => 'Rate $/h', 'max_length' => 255));
$image = $this->getSubject();
$fileFieldOptions = array('required' => false);
if ($image && ($webPath = $image->getImage())) {
dump($image);exit; //I have all user and field image local url /temp/sdgsdg
$container = $this->getConfigurationPool()->getContainer();
$fullPath = $container->get('request')->getBasePath().'/'.$webPath;
$fileFieldOptions['help'] = '<img src="'.$fullPath.'" class="admin-preview" />';
}
$formMapper
->add('image', 'file', $fileFieldOptions)
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('firstName')
->add('lastName')
->add('main_skill')
->add('skills')
;
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')
->add('username')
->add('firstName')
->add('lastName')
->add('main_skill')
->add('skills')
->add('image', 'string', array('template' => 'SonataMediaBundle:MediaAdmin:list_image.html.twig'))
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'edit' => array(),
)
))
;
}
}
How find by two or many skill ????
this is my entity:
class Developer extends CustomUser
{
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, unique=false, nullable=true)
* #Assert\Length(min=3, max=255)
*/
protected $email;
////
/**
* #var string
*
* #ORM\Column(name="skills", type="array")
*/
private $skills = array();
and in table for my developer in colum skill I see:
[0 => SOAP] [1 => Cisco] [2 => PHP] [3 => Sugar Crm] [4 => Hibernate] [5 => Java ME]
but when I add developer I use my service for skill and I see norm skill:
xPHP, xJava
How can fix this problem, reload template or controller ? Help please
For this task use https://sonata-project.org/bundles/media/2-2/doc/index.html . It's very easy

Sonata admin "sonata_type_collection" tries to remove entity

I have two entities and two Admin classes(StripePage and Stripe) for them. Form looks good, it has my fields and button to add new subforms. When "add new" button is clicked, new subform with form from Admin class is rendered, but if you click second time on this button or try to save entity error appears:
Catchable Fatal Error: Argument 1 passed to
Fred\CoreBundle\Entity\StripePage::removeStripe() must be an instance
of Fred\CoreBundle\Entity\Stripe, null given in
C:\Users\lubimov\OpenServer\domains\tappic.dev\src\Fred\CoreBundle\Entity\StripePage.php
So symfony tries to remove entity instead of adding it.
StripePageAdmin class:
class StripePageAdmin extends Admin
{
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id', null, array('label' => 'id'))
->add('name', null, array('label' => 'Page name'));
}
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Page name'))
->add('stripes', 'sonata_type_collection',
array('label' => 'Stripes', 'required' => false, 'by_reference' => false),
array('edit' => 'inline', 'inline' => 'table', 'sortable' => 'pos')
)
->end();
}
}
StripeAdmin class:
class StripeAdmin extends Admin
{
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')
->add('picture', null, array('sortable' => true))
->add('text', null, array('sortable' => true))
->add('deep_link', null, array('sortable' => true));
}
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('file', 'file', array('label' => 'Picture'))
->add('text', null, array('label' => 'Text'))
->add('deep_link', 'choice', array(
'choices' => array('test1' => 'Test1', 'test' => 'Test2'),
'label' => 'Deep Link',
))
->end();
}
}
What is the problem? Stripe form in admin class must be configured by other way?
Well, solution that I use now is to set 'by_reference' => true in 'sonata_type_collection' settings.
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Page name'))
->add('stripes', 'sonata_type_collection',
array('label' => 'Stripes', 'required' => false, 'by_reference' => true),
array('edit' => 'inline', 'inline' => 'table', 'sortable' => 'pos')
)
->end();
}
After this need to declare setStripes() method in entity.
public function setStripes(\Doctrine\Common\Collections\ArrayCollection $stripes) {
$this->stripes = $stripes;
}
If somebody finds how to solve this using addStripe() type of methods, please share it here.

Symfony2 form type entity add extra option

I have the following Symfony form field, it's a drop down that loads from an entity:
->add('measureunit', 'entity', array('label' => 'Measure Unit',
'class' => 'TeamERPBaseBundle:MeasureUnit',
'expanded' => false, 'empty_value' => '',
'multiple' => false, 'property' => 'abreviation'
))
As you can see I have added 'empty_value' => '' and everything works fine. Now, what I want is to have an extra option at the end to add a let say new measure unit. In other words the dropdown should display all the content of my entity, the empty value and other extra option called new measure unit or what ever I want to call it. Is it possible?
Edit: The whole form type file has this:
<?php
namespace TeamERP\StoresBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array('label'=>'Product name', 'required' => true,
'attr' => array('class' => 'form-control')))
->add('code', 'text', array('label'=>'Code', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('description', 'text', array('label'=>'Description', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('cost', 'money', array('label'=>'Cost', 'divisor' => 100, 'currency' => 'BWP'))
->add('category', new CategoryType(), array('required' => false))
->add('measureunit', 'entity', array('label' => 'Measure Unit',
'class' => 'TeamERPBaseBundle:MeasureUnit',
'expanded' => false, 'placeholder' => '',
'multiple' => false, 'property' => 'abreviation'
))
->add('qtyToPurchase', 'number', array('label'=>'Quantity to purchase', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('reorderPoint', 'number', array('label'=>'Reorder point', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('qtyOnSalesOrder', 'number', array('label'=>'Quantity on sales order', 'required' => false,
'attr' => array('class' => 'form-control')));
}
public function getName()
{
return 'product';
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
$new_choice = new ChoiceView(array(), 'add', 'add new'); // <- new option
$view->children['measureunit']->vars['choices'][] = $new_choice;//<- adding the new option
}
}
Error:
Compile Error: Declaration of TeamERP\StoresBundle\Form\Type\ProductType::finishView() must be compatible with Symfony\Component\Form\FormTypeInterface::finishView(Symfony\Component\Form\FormView $view, Symfony\Component\Form\FormInterface $form, array $options)
Edit2 Working form file:
<?php
namespace TeamERP\StoresBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array('label'=>'Product name', 'required' => true,
'attr' => array('class' => 'form-control')))
->add('code', 'text', array('label'=>'Code', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('description', 'text', array('label'=>'Description', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('cost', 'money', array('label'=>'Cost', 'divisor' => 100, 'currency' => 'BWP'))
->add('category', new CategoryType(), array('required' => false))
->add('measureunit', 'entity', array('label' => 'Measure Unit',
'class' => 'TeamERPBaseBundle:MeasureUnit',
'expanded' => false, 'placeholder' => '',
'multiple' => false, 'property' => 'abreviation'
))
->add('qtyToPurchase', 'number', array('label'=>'Quantity to purchase', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('reorderPoint', 'number', array('label'=>'Reorder point', 'required' => false,
'attr' => array('class' => 'form-control')))
->add('qtyOnSalesOrder', 'number', array('label'=>'Quantity on sales order', 'required' => false,
'attr' => array('class' => 'form-control')));
}
public function getName()
{
return 'product';
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
$new_choice = new ChoiceView(array(), 'add', 'add new'); // <- new option
$view->children['measureunit']->vars['choices'][] = $new_choice;//<- adding the new option
}
}
In your form type override the function finishView:
public function buildForm(FormbuilderInterface $builder, array $options){
$builder->add('measureunit', EntityType::class, array(
'label' => 'Measure Unit',
'class' => 'TeamERPBaseBundle:MeasureUnit',
'expanded' => false,
'empty_value' => '',
'multiple' => false,
'property' => 'abbreviation'
));
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
$newChoice = new ChoiceView(array(), 'add', 'Add New'); // <- new option
$view->children['measureunit']->vars['choices'][] = $newChoice;//<- adding the new option
}
You will get a new option 'add new' with value 'add' to the bottom of the field.
In addition to accepted answer:
If you choose the added option you will get validation error (because it's not valid entity), the following snippet can be used to overcome this error:
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) {
if ($event->getData() === 'add') {
$event->setData(null);
}
}
);
Then you can check if selected option is NULL, if it's => take value from additional input field.

SonataAdminBundle do not escape input fields

I am trying to insert a query into an input field and also html code but it gets escaped, this is what i currently use:
class ShopAdmin extends Admin{
protected $datagridValues = array(
'_page' => 1, // display the first page (default = 1)
'_sort_order' => 'DESC', // reverse order (default = 'ASC')
'_sort_by' => 'website' // name of the ordered field
// (default = the model's id field, if any)
// the '_sort_by' key can be of the form 'mySubModel.mySubSubModel.myField'.
);
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Item name'))
->add('description', 'textarea', array(
'label' => 'Item description',
'attr' => array(
'class' => 'redactor-init',
'style' => 'width: 683px;'
)
))
->add('amount', 'text', array('label' => 'Item price'))
->add('visible', 'checkbox', array('label' => 'Item visibility'))
->add('command', 'text', array('label' => 'Item command'))
->add('type', 'text', array('label' => 'Item type (SQL or COMMAND)'))
->add('image', 'text', array('label' => 'Item image'))
->add('reduction', 'text', array('label' => 'Item reduction'))
->add('reduction', 'text', array('label' => 'Item priority'))
->add('section', 'entity', array('class' => 'Maxim\CMSBundle\Entity\Section'))
//->add('server', 'entity', array('class' => 'Maxim\CMSBundle\Entity\Server'))
->add('website', 'entity', array('class' => 'Maxim\CMSBundle\Entity\Website'))
;
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
->add('visible')
->add('section')
//->add('server')
->add('website')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('visible', 'boolean', array('editable' => true))
->add('section')
//->add('server')
->add('website')
;
}
}
However i am trying to make it not escape, i used the types textarea, string and text but none of them seem to correctly work
I need to have this inserted into the db:
"UPDATE `db_perks` SET life_boost=life_boost+10 WHERE name="{USER}";
but it escapes it to:
"UPDATE `db_perks` SET life_boost=life_boost+10 WHERE name=\"{USER}\";

Categories