Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add condition type to doctrine_orm_callback filter #422

Closed
webdevilopers opened this issue Feb 4, 2015 · 9 comments
Closed

Add condition type to doctrine_orm_callback filter #422

webdevilopers opened this issue Feb 4, 2015 · 9 comments

Comments

@webdevilopers
Copy link
Contributor

Currently a callback filter can be setup like this:

        $datagridMapper
            ->add('currentState', 'doctrine_orm_callback', array(
                'callback' => array($this, 'getCurrentStateFilter'),
                'field_type' => 'choice',
                'field_options' => array('choices'=> ContractState::getStateList()),
            ))
        ;

The callback receives four parameters:

public function getCurrentStateFilter($queryBuilder, $alias, $field, $value)

Unfortunately it is not possible to retrieve the type that is parsed to the filter. For instance this this default filter:

use Sonata\CoreBundle\Form\Type\EqualType;

class ContractAdmin extends Admin
{
    public function getFilterParameters()
    {
        // Set default filter for current state to "in progress"
        $this->datagridValues = array_merge(array(
                'currentState' => array (
                    'type'  => EqualType::TYPE_IS_NOT_EQUAL,
                    'value' => ContractState::STATE_CONTRACT_ACCEPTED
                )
            ), $this->datagridValues);

        return parent::getFilterParameters();
    }
}

Please also note that this filter does not use the default EqualType::TYPE_IS_EQUAL type but the EqualType::TYPE_IS_NOT_EQUAL.

By default the doctrine_orm_callback filter will hide the operator:
https://github.com/sonata-project/SonataDoctrineORMAdminBundle/blob/master/Filter/CallbackFilter.php#L46

To make it visible and manually set some options you can do this:

        $datagridMapper
            ->add('currentState', 'doctrine_orm_callback', array(
                'callback' => array($this, 'getCurrentStateFilter'),
                'field_type' => 'choice',
                'field_options' => array('choices'=> ContractState::getStateList()),
                'operator_type' => 'choice',
                'operator_options' => array(
                    'choices' => array(
                        EqualType::TYPE_IS_EQUAL => '=',
                        EqualType::TYPE_IS_NOT_EQUAL => '!='
                    )
                )
            ))
        ;

It's even easier using the sonata_type_equal type directly:
https://github.com/sonata-project/SonataCoreBundle/blob/master/Form/Type/EqualType.php#L42-43

        $datagridMapper
            ->add('currentState', 'doctrine_orm_callback', array(
                'callback' => array($this, 'getCurrentStateFilter'),
                'field_type' => 'choice',
                'field_options' => array('choices'=> ContractState::getStateList()),
                'operator_type' => 'sonata_type_equal',
            ))
        ;

The filter now shows and selects the TYPE_IS_NOT_EQUAL type.

The problem is that the type is not available inside the callback function itself.

It should be added to the filter method inside https://github.com/sonata-project/SonataAdminBundle/blob/master/Filter/FilterInterface.php#L32.

This will allow something like:

public function getCurrentStateFilter($queryBuilder, $alias, $field, $value, $type)
{
    if (!$value['value']) {
        return;
    }

    if ($type === EqualType::TYPE_IS_NOT_EQUAL) {
        $queryBuilder
            ->where($alias . '.foo != :value')
            ->setParameter('value', $value)
        ;

        return true;
    }
}
@pulzarraider
Copy link
Contributor

The problem is that the type is not available inside the callback function itself.

The currently selected type is available in $value['type']. I agree that it is not very intuitive.

@webdevilopers
Copy link
Contributor Author

I could add it to the docs I changed some time ago:
https://github.com/sonata-project/SonataDoctrineORMAdminBundle/pull/385/files

I will think about an example implementing the type and the post it here before making an PR.

@webdevilopers
Copy link
Contributor Author

Created PR. Closing.

@mausly
Copy link

mausly commented May 20, 2016

Sorry for the delay and for the question but what is the Contract State :: setState List () function and does it contain? she brings the entities according to the amended motion?

@webdevilopers
Copy link
Contributor Author

Not sure what you mean @mausly but this was the static method behind it:

/**
 * @ORM\Entity
 * @ORM\Table(name="contract_states")
 */
class ContractState
{
    const STATE_ACCEPTED        = 'contract_accepted';
    const STATE_APPROVED        = 'contract_approved';
    const STATE_QUOTE_SUBMITTED = 'quote_submitted';
    const STATE_IN_PROGRESS     = 'in_progress';
    const STATE_PENDING         = 'pending';
    const STATE_CLOSED          = 'closed';

    public static function getStateList()
    {
        return array(
            self::STATE_ACCEPTED        => self::STATE_ACCEPTED,
            self::STATE_APPROVED        => self::STATE_APPROVED,
            self::STATE_QUOTE_SUBMITTED => self::STATE_QUOTE_SUBMITTED,
            self::STATE_IN_PROGRESS     => self::STATE_IN_PROGRESS,
            self::STATE_PENDING         => self::STATE_PENDING,
            self::STATE_CLOSED          => self::STATE_CLOSED
        );
    }
}

@mausly
Copy link

mausly commented May 20, 2016

Thank you for the speed.

I am looking to do the same kind of thing but instead of your statements I would have dynamic data.

My problem is the kind of country, region, city.

I am looking to be able to do a search on my cities according to two filters: the country and the region. When I select a country, regions automatically update to avoid having regions of a country not selected.

So unlike you, my regions (thine states) are dynamic (recorded in the database). I try to recharge based on the / my filters selected regions.

So according to your data, I understand that your work load wholes the elements are eliminated and items that do not come into account in the filter.

@webdevilopers
Copy link
Contributor Author

webdevilopers commented May 20, 2016

Looks like you need dependent fields. Normally you use events for that. But I think you can get any Request or Filter parameter that you need to build pre-populated choices. Maybe using the callback filter and w/ use $request->get('country').

@mausly
Copy link

mausly commented May 20, 2016

Do you have an example to advice me ?

I never use event with symfony.

@webdevilopers
Copy link
Contributor Author

Events are for the Form. Don't think they are available for filters. Just take a normal callback filter like this one by @bobman38
sonata-project/SonataAdminBundle#2513 (comment)

And then add a request param or take your variable from the filter parameters:

    $filterParameters = $this->getFilterParameters();
    // $countryId = $this->getRequest()->request->get('countryId');
    $countryId = $filterParameters['countryId'];

    $datagridMapper->add('regions', 'doctrine_orm_callback', array(
        'callback' => function($queryBuilder, $alias, $field, $value) use ($countryId) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants