Skip to content
This repository was archived by the owner on Jul 28, 2022. It is now read-only.

Add methods to be used by AdminBundle#233

Closed
VincentLanglet wants to merge 1 commit intosonata-project:masterfrom
VincentLanglet:improveInterface
Closed

Add methods to be used by AdminBundle#233
VincentLanglet wants to merge 1 commit intosonata-project:masterfrom
VincentLanglet:improveInterface

Conversation

@VincentLanglet
Copy link
Member

Subject

I am targeting this branch, because BC-break.

The AdminBundle and the DatagridBundle has a lot of classes in common.
I would like that the AdminBundle requires the DatagridBundle and use his classes.

But currently some methods are missing in the interface, so I added them.

Changelog

### Added
- Added hasDisplayableFilters in DatagridInterface and Datagrid
- Added getFieldOption, setFieldOption, getParentAssociationMappings, getFieldMapping, getAssociationMapping in FilterInterface and BaseFilter
- Added getUniqueParameterId, entityJoin in ProxyQueryInterface and BaseProxyQuery

### Changed
- BaseProxyQuery::setSortBy and ProxyQueryInterface::setSortBy signature

@VincentLanglet VincentLanglet requested review from a team, core23 and greg0ire May 21, 2020 10:08
@VincentLanglet
Copy link
Member Author

VincentLanglet commented May 21, 2020

I have only one issue.

SonataAdminBundle Datagrid use in the buildPager methods

$this->formBuilder->get('_sort_by')->addViewTransformer(new CallbackTransformer(
    static function ($value) {
        return $value;
    },
    static function ($value) {
        return $value instanceof FieldDescriptionInterface ? $value->getName() : $value;
    }
));

And

if (isset($this->values['_sort_by'])) {
    if (!$this->values['_sort_by'] instanceof FieldDescriptionInterface) {
        throw new UnexpectedTypeException($this->values['_sort_by'], FieldDescriptionInterface::class);
    }

    if ($this->values['_sort_by']->isSortable()) {
        $this->query->setSortBy($this->values['_sort_by']->getSortParentAssociationMapping(), $this->values['_sort_by']->getSortFieldMapping());

        $this->values['_sort_order'] = $this->values['_sort_order'] ?? 'ASC';
        $this->query->setSortOrder($this->values['_sort_order']);
    }
}

That's why the AdminBundle Datagrid works with FieldDescriptionInterface, the Datagrid from DatagridBundle work with a string value and the ProxyQuery didn't had the same setSortBy signature.

I wouldlike that the DatagridBundle Datagrid works with FieldDescriptionInterface but I don't know how to import this class.

  • If I require the admin bundle, I won't be able to require the datagrid bundle in the admin bundle because it will lead to circular references, isn't it ?
  • If I move the FieldDescriptionInterface in the DatagridBundle, I don't know if this change makes sens. And some methods of the FieldDescriptionInterface is using the AdminInterface so I would need a way to avoid moving the AdminInterface too 😅. Maybe splitting the FieldDescriptionInterface in two...

Any advice @greg0ire ?

@greg0ire
Copy link

Maybe splitting the FieldDescriptionInterface in two...

This should be BC, and sounds good to me. You could have the admin interface extend the datagrid interface.

@VincentLanglet
Copy link
Member Author

Maybe splitting the FieldDescriptionInterface in two...

This should be BC, and sounds good to me. You could have the admin interface extend the datagrid interface.

Let's go with this

interface FieldDescriptionInterface
{
    public function setFieldName($fieldName);
    public function getFieldName();
    public function setName($name);
    public function getName();
    public function getOption($name, $default = null);
    public function setOption($name, $value);
    public function setOptions(array $options);
    public function getOptions();
    public function setTemplate($template);
    public function getTemplate();
    public function setType($type);
    public function getType();
    public function setParent(AdminInterface $parent);
    public function getParent();
    public function setAssociationMapping($associationMapping);
    public function getAssociationMapping();
    public function getTargetEntity();
    public function setFieldMapping($fieldMapping);
    public function getFieldMapping();
    public function setParentAssociationMappings(array $parentAssociationMappings);
    public function getParentAssociationMappings();
    public function setAssociationAdmin(AdminInterface $associationAdmin);
    public function getAssociationAdmin();
    public function isIdentifier();
    public function getValue($object);
    public function setAdmin(AdminInterface $admin);
    public function getAdmin();
    public function mergeOption($name, array $options = []);
    public function mergeOptions(array $options = []);
    public function setMappingType($mappingType);
    public function getMappingType();
    public function getLabel();
    public function getTranslationDomain();
    public function isSortable();
    public function getSortFieldMapping();
    public function getSortParentAssociationMapping();
    public function getFieldValue($object, $fieldName);
}

For the Datagrid, I only need the methods

  • getName()
  • getSortParentAssociationMapping
  • getSortFieldMapping

If I want to add the getSortParameters/getPaginationParameters to the DatagridInterface, I'll need to support

  • getName()
  • getOption('sortable')

So I can make a smaller interface

interface FieldInterface
{
    public function setName($name);
    public function getName();
    public function getOption($name, $default = null);
    public function setOption($name, $value);
    public function setOptions(array $options);
    public function getOptions();
    public function mergeOption($name, array $options = []);
    public function mergeOptions(array $options = []);
    public function getLabel();
    public function getTranslationDomain();
    public function isSortable();
    public function getSortFieldMapping();
    public function getSortParentAssociationMapping();
}

I just don't know if I should have in this interface

    public function getLabel()
    {
        return $this->getOption('label');
    }

    public function getTranslationDomain()
    {
        return $this->getOption('translation_domain');
    }

Or if this should be in the Admin one. Any idea @greg0ire ?

And I don't think these methods

    public function isSortable(): bool
    {
        return false !== $this->getOption('sortable', false);
    }

    public function getSortFieldMapping()
    {
        return $this->getOption('sort_field_mapping');
    }

    public function getSortParentAssociationMapping()
    {
        return $this->getOption('sort_parent_association_mappings');
    }

Are needed in the interface, since it's just helpers called once ; in the datagrid.

if ($this->values['_sort_by']->isSortable()) {
    $this->query->setSortBy($this->values['_sort_by']->getSortParentAssociationMapping(), $this->values['_sort_by']->getSortFieldMapping());

    $this->values['_sort_order'] = $this->values['_sort_order'] ?? 'ASC';
    $this->query->setSortOrder($this->values['_sort_order']);
}

And I could use getOption instead.
Or I can also create a special Interface SortableFieldInterface extending FieldInterface.
What do you prefer @greg0ire ?

After these decisions, I'll start the PR :)

@greg0ire
Copy link

Or if this should be in the Admin one. Any idea @greg0ire ?

I don't know either, it's unclear to me what the scope of datagrid is, and what these methods do. Let's see if other @sonata-project/contributors that also, you know, use Sonata think :P

@VincentLanglet
Copy link
Member Author

VincentLanglet commented May 21, 2020

I don't know either, it's unclear to me what the scope of datagrid is, and what these methods do. Let's see if other @sonata-project/contributors that also, you know, use Sonata think :P

I feel sad for your company for not using the excellent Sonata bundles !
You should try to convince them :P

@core23 Made some PR on this bundle, maybe he'll know.

return false;
}

public function hasDisplayableFilters(): bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we should add this method. Showing a filter or not is logic for the UI, not the general lib

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of the library ?

hasActiveFilters and hasDisplayableFilters are really similar. I think it's better to have the two methods in the same Interface/class.

Currently we have a loooot of duplicated code/really similar code. I want to deal with this, and I think we'll have to make some small trade-off.

There are some others UI method in this bundle, like Filter::getRenderSettings, or getTranslationDomain. The Datagrid class is also mainly a UI class, and is never use by others bundle. They only use the Pager and the ProxyQuery.

@VincentLanglet
Copy link
Member Author

Closing in favor of #239

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants