Problem/Motivation
We have more and more configurable entities in core some of them have "weighting" so their administrative listings are forms that allows to drug-n-drop items.
Vocabularies, Contact category, Roles
Proposed resolution
Implement a generic form()/validate()/submit() methids in ConfigEntityListController.
This change have to allow config entity type's list controller implementations to simply it's administrative tasks.
Just override a buildHeader(), buildRow(), getOperations() methods to injects own columns.
Also there's should be a room for a kind of mixed form and list controller overrides for #663946: Merge "List links" page into "Edit menu" page
Also operations|actions should be integrated latter #1798540: Add link to add a new entity in an empty entity list controller table
Related issues
#1803586: Give all entities their own URI
#1783964-7: Allow entity types to provide menu items
#1798540: Add link to add a new entity in an empty entity list controller table
#1839516: Introduce entity operation providers
#1016056: Hide tabledrag handle and "Show row weights" when there is only one item in list
#663946: Merge "List links" page into "Edit menu" page
Depends on this issue
#1891690: Use EntityListController for vocabularies
#599770-15: Clean up the contact forms listing UI: Allow to set the default category and weights on the listing page
#1809376-15: Use EntityListController for image styles
#1872870: Implement a RoleListController and RoleFormController
#1787942-41: Allow assigning layouts to pages
Original report by @sun
We need that functionality in many places in core and contrib so let's refactor it and make it a part of the ConfigEntityListController.
Comment | File | Size | Author |
---|---|---|---|
#100 | tabledrag-1855402-100.patch | 23.25 KB | tim.plunkett |
#100 | interdiff.txt | 2.52 KB | tim.plunkett |
#97 | interdiff.txt | 7.77 KB | tim.plunkett |
#97 | tabledrag-1855402-96.patch | 23.08 KB | tim.plunkett |
#93 | tabledrag-1855402-93.patch | 25.66 KB | tim.plunkett |
Comments
Comment #1
sunShould be piece of cake once #80855: Add element #type table and merge tableselect/tabledrag into it has landed.
Comment #2
fubhy CreditAttribution: fubhy commentedLet's postpone this and wait for #80855: Add element #type table and merge tableselect/tabledrag into it to land.
Comment #3
fubhy CreditAttribution: fubhy commentedSince that other issue is already RTBC I started writing a patch for this real quick.
We still need to do something about ConfigEntityBase::sort() if we agree on this approach:
Comment #5
fubhy CreditAttribution: fubhy commentedJust fixing the fails in the previous patch. This still needs test and we should also directly implement all this for all the places where we using weighting with config entities in core.
Comment #6
tim.plunkettAwesome!
Needs the full namespace \Drupal\Core\Entity\EntityListController
Each of these empty() checks feel like they should just be !$this->weightKey
This could just be
Comment #7
fubhy CreditAttribution: fubhy commentedThe latest iteration of http://drupal.org/coding-standards/docs#classes suggests we don't use full namespaces in cases like this!
Will get back to this issue once #80855: Add element #type table and merge tableselect/tabledrag into it has been commited.
Comment #8
fubhy CreditAttribution: fubhy commented#80855: Add element #type table and merge tableselect/tabledrag into it got committed. Will provide a new patch tomorrow!
Comment #9
tim.plunkettTagging.
Comment #10
sunLet's see how it goes.
Comment #12
andypostFixed broken test by moving sorting support exactly to ConfigEntityListController
This shows that #theme(table) and #type(table) still different in render
Comment #13
andypostPatch now green again so here doc-block fixes following current http://drupal.org/coding-standards/docs#classes
Comment #14
andypostThere's a some suggestions to fix JS for tabledrag
#1869328-32: Restore simplicity of language list
Comment #15
andypostDoes not mean to change a status
Comment #16
tstoecklerIf we're already changing this, it should be "Contains" instead of "Definition of"
To be consistent with system_config_form_submit() this should be 'The configuration options have been saved.'
Leaving at needs review, because those are minor, and since I think this is blocking stuff elsewhere, might be adjusted in a follow-up.
Comment #17
fubhy CreditAttribution: fubhy commentedAddressing #16.
Comment #18
sunThis looks awesome to me.
Let's move forward with this patch, and perform any possible improvements in follow-up issues.
Existing test coverage should be sufficient here, I think.
Comment #19
tim.plunkettAbsolutely none of this is in scope.
Can we have an actual comment here about what the array_slice is doing, beyond linking to that issue?
This needs to be documented in EntityManager, under entity_keys
Comment #20
dawehnerLet's fix the stuff in the review.
One problem is that currently we just have a single entityManager so weight just for on config entities.
Comment #21
sunThanks! Let's get this in now.
With this, the need for #1876718: Allow modules to inject columns into tables more easily becomes more apparent. (already linked in the @todos)
Once filter formats are converted (#1779026: Convert Text Formats to Configuration System), we can leverage it there, which means that we can remove even more unnecessary custom code.
Comment #22
Dries CreditAttribution: Dries commentedThis looks a bit messy to me. It's both slow (un-doing work) and pretty ugly to read. Is there a way we can improve this? Sounds like #1876718: Allow modules to inject columns into tables more easily could help with this, although I'm skeptical it would make it a lot easier.
Comment #23
andypostRelated #1887582: update #type=table for language list to simplify tables
Comment #24
tstoecklerRe #22: Actually #1876718: Allow modules to inject columns into tables more easily will (almost certainly) allow to completely remove/revert that hunk entirely. What is done in addition to the array_splice()ing in that hunk is the usage of render elements (albeit #type => 'markup') instead of a pure string. That might (or might not) be retained, but that can be discussed independently.
Comment #25
sunYes, that's a known issue (hence the @todos). #1876718: Allow modules to inject columns into tables more easily will clean that up, and we're actively discussing the best solution over there already.
I'd prefer if we could move forward here and accept the
array_slice()
ugliness as a temporary thing only.Comment #26
fubhy CreditAttribution: fubhy commentedAlso, I would like point out that #1833716: WYSIWYG: Introduce "Text editors" as part of filter format configuration got committed with the same, temporary hack :)
Comment #27
andypostMaybe better to store columns & operations separate? so we can inject weight column only when needed
Comment #27.0
andypostUpdated issue summary.
Comment #28
andypostAnother list that needs this added to summary #1891690: Use EntityListController for vocabularies
Comment #29
andypostI think this issues should investigate most common needs for configurable entities, probably some code could be moved to EntityListController. We have a lot of implementations in Core that could be generalized also taking into account translatability of the entities.
Current implementations are Views, PictureMappingListController, Menus, Contact, vocabularies, imagestyles
For vocabularies, contact, filters, languages, layout-pages we need forms with weight.
For menus, shortcuts, image-styles - we use simple render-tables
For forums, menu-items, image-effects - sortable trees
For most of fieldable entities we need 2 menu-items + edit and delete operations
Also we need a way to remove Save button and table-weight behavior when there's only 1 item in list.
There's a lot of issues waiting for this and more menu-routers could be simplified
Related issues:
#1787942-41: Allow assigning layouts to pages
#599770-15: Clean up the contact forms listing UI: Allow to set the default category and weights on the listing page
#1809376-15: Use EntityListController for image styles
#1783964-7: Allow entity types to provide menu items
#1891690: Use EntityListController for vocabularies
#1798540: Add link to add a new entity in an empty entity list controller table
#1803586: Give all entities their own URI
#1479454: Convert user roles to configurables
Comment #29.0
andypostUpdated issue summary.
Comment #29.1
andypostUpdated
Comment #29.2
andypostUpdated issue summary.
Comment #29.3
andypostUpdated issue summary.
Comment #30
tim.plunkettI don't see the reason to do anything more in this issue. Furthermore, we'd ideally not use EntityListController for non-config, using Views. See #1864980: [meta] Figure out how to integrate Views into core
Comment #31
andypostThis patch changes a contact listing by adding a machine name which seems wrong. see screens attached
Before
After
EDITED
Also I tried to implement controller for vocabularies and it works #1891690-5: Use EntityListController for vocabularies
Why not use
#type=weight
for weight field?Comment #32
andypostPatch limits the scope of "column-injection" to buildHeader() only by adding sorting for each row by table header so no matter in order the buildRow() adds additional data.
The weight field added at the end of table because mostly they hidded in UI.
This affects all configurables, vocabulary part could be out of scope but issue should care all cases.
Let's see how many tests is broken by this.
Comment #34
andypostFix broken tests
Comment #36
sunCan we please go back to #20 and get that in first?
Regarding the "regression" of an additional machine name being output in the contact category listing (as depicted in #31), IMHO that's perfectly acceptable for now. I think we want to re-evaluate what the default listing for config entities should contain and look like either way. Quite potentially, we actually want to output the machine name (but not necessarily in an own column).
Comment #37
sun#20: drupal-1855402-20.patch queued for re-testing.
Comment #38
dawehnerSo first here is an interdiff from 34 to 20. Thanks andypost for improving the entity list controllers in all that places.
The changes for vocabularies seems to be fine, but maybe out of scope, as we can improve the actual instances later?
The same can be said for pieces like the menu list controller etc.
Let the patch size be as small as possible, and iterate on it. That's the proper way to get progress at the end.
I don't see the point why adding the machine name in the tabledrag issue makes any sense.
Comment #39
andypostSo ok, I moved mack machine name but into responsive column and no taxonomy now to minimize a patch
Patch adds back #20 way to insert columns with @todo for follow-up
Also conversion columns to render is the same for label and id because we need a way to play easily with css rules like Menu does.
Also let's get reviews from usability and mobile team!
PS: there's no reason to rush this patch, we need a generic implementation
Comment #40
sun@andypost:
I've the impression you're mistaking this issue as the issue that wants to introduce a super-generic/catch-all ConfigEntityListController implementation for all config entities... but that's not the case. We're trying to focus on the tabledrag/weighting aspect only. (As the issue title states.) Evaluating what the generic default implementation for config entity listings should be is left for a separate issue. The original patch in #20 does not affect any config entity listings, unless they specifically opt-in for the weight/tabledrag handling. That's really all we want to achieve in this issue.
Comment #41
andypost@sun #39 is the same as #20 but fixes regressions in UI and tests.
And the main difference that better to remove
array_slice()
code fromrender()
see code below. Custom List controllers are just add own columns in buildRow() but the order is defined in header so this change should improve DX.Changes in default controller are affects current implementations so patch must fix this regressions.
this
this
Comment #42
Bojhan CreditAttribution: Bojhan commentedI dont get what you want me to review
Comment #43
andypost@Bojhan the UI changes in #31 #39 for contact category listing. Menus in #39 gets new Machine name column. Is there any suggestions for machine names?
Comment #45
andypost#39: 1855402-config-sort-39.patch queued for re-testing.
EDIT can't reproduce translation test failure locally
Comment #46
Bojhan CreditAttribution: Bojhan commentedI see no reason to have a machine name column, I'm sure there are loads of usecases that you would need them - I do not see a 80% usecase. I would side against them for now, because 1) its relatively easy to have them show up, through a custom view, or just adjusting this listing through a module, 2) you can get the machine name, if you click edit, 3) the consistent pattern we employ in core currently and received no negative feedback is to edit the thing to see the machine name (albeit not on content types, but the Field UI is a one off).
Comment #46.0
Bojhan CreditAttribution: Bojhan commentedUpdated issue summary.
Comment #47
andypostShould be postpone this for #1876718: Allow modules to inject columns into tables more easily ?
Or implement a generic and use it for a all form-tables like #1876712: [meta] Convert all tables in core to new #type 'table'
Comment #48
andypostpatch without machine names
Contact categories
Menus
Comment #49
gddAndypost asked me to weigh in on the machine name issue and I pretty much agree with everything Bojhan said.
Comment #51
andypostFixed broken test
Comment #52
andypostMerge HEAD after #1826602: Allow all configuration entities to be enabled/disabled
Comment #53
andypostNow we should wait for #1913084: Introduce a Form interface for building, validating, and submitting forms to land and probably #1913618: Convert EntityFormControllerInterface to extend FormInterface
Comment #54
andypostI think EntityFormController is not related to ListController so any reviews are welcome because other issues depends on this one
Comment #55
andypostBuild on top of FormInterface like BlockListController does
Comment #56
andypostRemove copy/paste error
Comment #57
andypost#56: 1855402-config-sort-56.patch queued for re-testing.
Comment #59
andypost#56: 1855402-config-sort-56.patch queued for re-testing.
Comment #60
andypostCurrent doc blocks
Comment #61
andypostRe-roll
Comment #62
tim.plunkettYou could just start with
protected $weightKey = FALSE;
and skip the elseShould switch to
$entities = \Drupal::service('plugin.manager.entity')->getStorageController($this->entitytType)->load(array_keys($values));
to make it easier to inject later.
$entity_info = $this->container->get('plugin.entity.manager')->getDefinition('config_test');
Comment #63
andypostHere it is
Comment #64
andypostDefault value moved out of constructor
Comment #66
andypostcopy/paste error :(
Comment #67
andypost#66: 1855402-sort-config-66.patch queued for re-testing.
Comment #68
andypostAlso currently in core we provide links only to "Content Entities"
Is strict but #1876718-7: Allow modules to inject columns into tables more easily seems better
still depends on it
Comment #70
jibran#66: 1855402-sort-config-66.patch queued for re-testing.
Comment #72
andypostre-roll
Comment #74
andypostRelated issues #2027117: Always use parent::buildRow($entity) in EntityListController and #2019071: EntityListController::buildRow() should return secure label
Comment #75
andypostreroll
Comment #77
andypostFix tests
Comment #78
andypostpatch
Comment #79
andypostRemove debug
Comment #80
andypostRender needed to alter properly
Comment #82
andypostFix broken tests
Comment #84
andypostFix taxonomy test
Comment #85
andypost#84: 1855402-sort-config-84.patch queued for re-testing.
Comment #87
andypostmerge HEAD
Comment #88
tim.plunkettI still don't see how this is reasonable. If EntityListController changes its header, we'll have plenty of other problems. As a base class, why not just dictate the header and row data?
Double check_plain'd now.
Are we sure we want to go this direction, and not just have a separate base class? This certainly convolutes this class.
This seems more reasonable, since we *don't* want to overwrite the parent.
Comment #89
andypostFixed double escape after
@tim.plunkett I've no idea how to implement this in base class, also please point the files you are referring in dreditor
The change applies to config entities only, so this is a base class that dictates behavior
Comment #90
tim.plunkettNot all config entities need tabledrag. And some content entities do.
The 1st and 3rd hunks are both in ConfigEntityListController, the 2nd you fixed and the 4th was an observation.
I think it should be a separate class, WeightedConfigEntityListController or something.
Comment #91
tim.plunkett#2064557: Improve strange coupling in EntityListControllers by improving buildRow() and buildHeader() will make this code way way way simpler.
Comment #92
tim.plunkettWorking on this.
Comment #93
tim.plunkettSince #2064557: Improve strange coupling in EntityListControllers by improving buildRow() and buildHeader() went in, this didn't apply at all.
I also took a different approach, in order to keep ConfigEntityListController as is.
Comment #94
tim.plunkettOops!
Also, I'm not expecting this to pass the first time, I'll update for any failures.
Comment #95
tim.plunkettIf we're really concerned about backward compatibility, I can introduce a key like
DefaultPluginBag::$pluginKey
has, something likeDraggableListController::$entitiesKey
, set the default to 'entities', and let these two override it...Comment #97
tim.plunkettYep, #95 works nicely and should resolve most if not all of those failures.
Comment #98
andypostLooks awesome!
This needs follow-up at least to display only columns that have header (allowing to re-sort table columns by weight too)
Comment #100
tim.plunkettI only tested the language list without locale on, whoops.
Not sure what you mean in #98, that seems out of scope.
Comment #101
andypostYep, follow-up in #1876718: Allow modules to inject columns into tables more easily
I found no nitpicks with code
Comment #102
tstoecklerCouldn't we just document that entities using this need a weight key? I like the split classes but it's sad to have all those checks in there, as without a weight key the whole class is pointless.
Also it seems $this->weightKey is already used unconditionally in submitForm() so...
Since this has been sitting for so long, I'm not downgrading this. I'm fine with doing this as a follow-up. I couldn't find anything substantially wrong with this patch and my proposal would merely be a minor code clean-up not actual technical debt in any sense of the word.
Comment #103
tim.plunkettWe can't and shouldn't assume that the key will be called
weight
, it could beorder
orposition
.Also, submitForm() is only called if the weightKey is set during render(), hence the lack of check for it.
Comment #104
tstoecklerAhh, I totally missed render(). Yes, that makes sense.
But I still think we should just remove the checks. No, we can't enforce that weightKey == 'weight', but IMO we can enforce that !empty(weightKey) == TRUE. Then we just set $this->weightKey in __construct() and be done with it.
Comment #105
tim.plunkettAnd what if weightKey isn't set? Random notices? A thrown exception (of what type)?
Comment #106
tim.plunkettAlso, VocabularyListController has the pre-existing functionality of NOT being a draggable form when there is only one vocab.
It relies on these weightKey checks to function.
Comment #107
tstoecklerRe #105: Since the DraggableListController is explicitly opt-in I think a "Undefined index 'weightKey'" would actually be quite helpful.
Re #106: I think that should be handled generically in #1016056: Hide tabledrag handle and "Show row weights" when there is only one item in list
But apparently my suggestion is more controversial than I had anticipated so I opened a follow-up issue. Let's discuss there and finally get this one in:
#2070621: Make the existence of a weight key mandatory in DraggableListController
Comment #108
tim.plunkettSure, #1016056: Hide tabledrag handle and "Show row weights" when there is only one item in list can block #2070621: Make the existence of a weight key mandatory in DraggableListController, that's fine.
Comment #109
alexpottCommitted 9e01ce3 and pushed to 8.x. Thanks!
Comment #110
BerdirThis should probably get a change notice? I can use this in contrib modules and others probably too.
Using $this->entities seems to be pretty weird here? That means we serialize all of them and then save the version that was previously serialized, so that could be an older version that was already changed in the meantime. Wouldn't be hard to just load them again? This was introduced in #100, without further discussion on it... I see that it's also used in one other method, that probably makes sense there, but not so sure about the submit method.
Comment #111
andypostAbout
$entities
in submit - each time when submit should be called the build happens, there's no serializationBy the same time 100 introduces
so we have 2 lists of languages and probably other types affected.
PS: seems there's a room for follow-up to clean-up things for better contrib DX ("entities" stored in form array could be changed via form alter so we need a competent list of entities)
Comment #112
andypostFiled follow-up #2074875: Reload entities in DraggableListController::submitForm()
Comment #113
andypostTaxonomy page should be updated when there's only one vocabulary to hide weight header column
Comment #114
catch#2083415: [META] Write up all outstanding change notices before release
Comment #115
tim.plunketthttps://drupal.org/node/2089283
Comment #116
BerdirLooks fine, added a bit example code as an entity type always needs a custom subclass. Also changing the issue title to contain the name of the class that was added.
Comment #117.0
(not verified) CreditAttribution: commentedUpdated issue summary.