Problem/Motivation
#2807785: Move global constants from *.module files into interfaces deprecated a bunch of constants but it did not actually replace their usage. We should do this. This issue handles REGIONS_VISIBLE, and REGIONS_ALL. This is a bug because we've deprecated something but we've not completed the task and, more importantly, the old constants are in the System module and used by it but the new constants are in the Block module. That does not work.
Regions are properties of themes not blocks. They are declared in a theme's .info.yml file in the regions key and hidden via the regions_hidden key.
Proposed resolution
Current solution
Add a new Theme class that extends Extension and replaces the extension object in theme lists.
See API changes for a full scope of all the changes.
Other possible solutions
- Add a new ThemeRegion service.
Add an object just to handle the theme extension's info array- discounted in #24 - we have code that depends on this being an array.Add- discounted in #13ThemeHandler::listAllRegions($name),ThemeHandler::listVisibleRegions($name)andThemeHandler::getDefaultRegion($name)
Remaining tasks
User interface changes
None
API changes
The main changes are:
system_region_list()use\Drupal::service('theme_handler')->getTheme()->listAllRegions()or\Drupal::service('theme_handler')->getTheme()->listVisibleRegions()instead.system_default_region()use\Drupal::service('theme_handler')->getTheme()->getDefaultRegion()instead.REGIONS_ALL,REGIONS_VISIBLE,\Drupal\block\BlockRepositoryInterface::REGIONS_ALLand\Drupal\block\BlockRepositoryInterface::REGIONS_VISIBLEare deprecated and should not be used.
As a result several objects that had helper methods to the global functions also have API deprecations:
\Drupal\block\BlockListBuilder::systemRegionList()use$this->themeHandler->getTheme()->listAllRegions()or$this->themeHandler->getTheme()->listVisibleRegions()instead.\Drupal\block\Controller\BlockController::getVisibleRegionNames()use$this->themeHandler->getTheme()->listVisibleRegions()instead.\Drupal\block_place\Plugin\DisplayVariant\PlaceBlockPageVariant::getVisibleRegionNames()use$this->themeHandler->getTheme()->listVisibleRegions()instead.
Several methods on the ThemeHandler return an array of Theme objects instead of Extension objects. As Theme extends from Extension this is allowed. These methods are:
\Drupal\Core\Extension\ThemeHandlerInterface::listInfo()\Drupal\Core\Extension\ThemeHandlerInterface::rebuildThemeData()
\Drupal\Core\Extension\ThemeHandlerInterface::getTheme() now returns a Theme object.
The one "breaking" change is \Drupal\Core\Extension\ThemeHandlerInterface::addTheme() which now only accepts a Theme object. This change is worth it because this is an incredibly low level method that only exists so that maintenance pages and install pages can use themes before anything is installed. The hard break would help any custom or contrib code in the very unlikely event that they are using it.
New \Drupal\Core\Extension\Theme that extends \Drupal\Core\Extension\Extension and we can build up the abilities of over time so eventually we can replace everything with methods. No more $theme->info['foo'] and we can remove the public properties and turn them into value objects.
Data model changes
None
| Comment | File | Size | Author |
|---|
Issue fork drupal-3015812
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
alexpottI think we should re-consider how we have deprecated REGIONS_ALL and REGIONS_VISIBLE. Regions are properties of themes not blocks. Yes blocks are placed in regions but the list of regions are determined by the theme not blocks.
The patch attached deprecated system_region_list() and system_default_region() and places the methods on the ThemeHandler - that because they are easiest to implement there and as you can see from some of the changes there are places where with what is already injected into objects this makes sense. I'm not sure - other ideas more than welcome.
Comment #3
andypostThat looks great and much cleaner
Maybe instead of
new Translatable($label)extension api could provide thatalso needs testing for deprecated BC + exception
Comment #4
andypostAdded
regions_hiddento theme initAs all of this methods getters - then let's call them not "list"
A bit of clean-up
Comment #5
andypostClean-up renaming
Comment #6
andypostDeletegated in theme init, hidden is not used in active theme so every usage should use theme handler
Comment #7
andypostmake translation inline with core
Comment #8
alexpott@andypost I think listBlah() is great for a getter that returns an array. But whatevs we don't have a standard here.
I think #6 and any changes to ActiveTheme is out-of-scope and should be done in another issue.
#7 is also out-of-scope.
This is the original code... the Layout stuff has added
'context' => 'layout_region'but that is an experimental module and there needs to be separate issue to introduce this to system_region_list().All told I'm going to revert to #2 with improvements to block_rebuild() from #4.
Added a new change record and started to write it https://www.drupal.org/node/3015925 and added proper deprecation notices.
I still think we need to discuss whether the ThemeHandler is the correct place for this. For me a potentially better way would a Theme object that was built from the Extension object so you could do something like
$this->themeHandler->getTheme($name)->listAllRegions()but this requires massive changes to the the theme listing system which are afoot in #2659940: Extension System, Part III: ThemeExtensionList and ThemeEngineExtensionList but even those changes have not yet given us properly typed Extensions objects ie Module / Theme / Profile. So maybe this is the best we can do at the moment. I think that changes toblock_rebuild()show that putting this on the theme handler is not that bad a compromise.Need to add deprecation tests.
Comment #9
alexpottI guess the other option is to have a ThemeRegion service. It would depend on the theme_handler and string_translation services.
Comment #10
alexpottHere's a test for region listing both via theme_handler and the legacy methods.
Comment #11
alexpottUpdated issue summary.
Comment #12
alexpottComment #13
tim.plunkettThis sounds preferable, and also avoiding a BC break by not expanding ThemeHandlerInterface.
Comment #14
andypostTim do you have any thoughts about how to swap it later for #2924058: Discuss using Layout Builder to control full site layout and replace Block UI
Comment #15
andypost@alexpott what if we add extension getFeatures() which will return specific extension info.yml parsing and validation object - surely followup
On my side I'd like to split theme info which is already dumplicated in activetheme class object
Comment #16
tim.plunkettMaking it a new service could probably help with that (as Layout Builder could swap out the service), but that issue isn't a current focus of the Layout Initiative
Comment #17
alexpottNot sure about this being a service. I prefer the
option.
Here's a patch doing that. It introduces an ThemeInfo value object that handles the
->infopart of the Theme extension object. That's let's us have methods :)No interdiff because it is a fresh approach.
Comment #18
alexpottComment #19
alexpottComment #21
alexpottAccounting for the case where a block exists for a theme that is not installed :(
Comment #23
alexpottWe need PHP 7.1's iterable type hint :( oh well. This is work aroundable.
Comment #24
alexpottDoh.
Comment #27
alexpottOkay so array_intersect_key() doesn't work on \ArrayAccess objects :(
Here's another approach that confers quite a few advantages. It adds a Theme extension object that extends from Extension and documents the public properties. This will allow us to properly deprecate them and move to a value object.
No interdiff because it'd be every single line.
Comment #28
alexpottFixing some tests from #27.
Comment #30
alexpottUpdated the issue summary with the current state.
Comment #31
alexpottIgnore the patch in #28 it's the same as #27 :( - here are the fixes.
Comment #34
alexpottSo the
LanguageBlockSettingsVisibilityTestis using a theme that is not installed. It shouldn't be doing that the link is not available in the UI and it would be impossible to add a block for a theme that is not installed because you'll get a dependency error.Comment #35
alexpott#2659940: Extension System, Part III: ThemeExtensionList and ThemeEngineExtensionList is back to RTBC - we should definitely do that one first as it is more important and will mean lots of changes to this one.
Comment #36
alexpottHere's a rebase on top of #2659940: Extension System, Part III: ThemeExtensionList and ThemeEngineExtensionList
Need to update the issue summary a little with the impact. No interdiff because the changes are extensive and need to be reviewed in the context on the new theme extension list.
Comment #37
alexpottAlso this incorporates #3016968: Remove weight public property from theme extensions
Comment #39
alexpottComment #40
alexpottRerolled now the weight patch landed.
Comment #41
alexpottLet's kick another test off - I rebased my branch on the latest 8.7.x... no changes to #40.
The issue summary is up-to-date with the current patch. Changed title to reflect scope.
Comment #42
phenaproximaNit: Why split this into two lines?
Should be "This may be overridden..."
Nit: "Theme" should be "theme".
To facilitate the removal of the property, maybe this would be a good time to add an isEnabled() method to replace it?
Should this default to an empty array?
"Owner" seems like a strange name for this property. Maybe we should take this opportunity to rename it and add a magic __get() wrapper around "owner", if external code relies on it.
Same here.
Should this be a boolean?
Passing an Extension object to this constructor seems strange. It almost feels like it should be a static createFromExtension() method...
What if 'base theme' is an empty string, or null? Maybe this should be an empty() check instead.
Why does the return value need to be casted to a string?
Where is this used?
Isn't there a method to retrieve the list of installed themes?
Comment #43
markhalliwellA little overlap from #42:
These should really be a part of
Extension, they're not theme specific: http://cgit.drupalcode.org/drupal/tree/core/includes/common.inc?id=8.6.5...This is really weird and feels like a huge anti-pattern.
The
Themeobject extends fromExtension, it shouldn't need anExtensionobject to create aThemeobject.Decorating something shouldn't return a whole new object.
I'm also wondering if maybe this shouldn't be postponed on #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation and #3023131: [PP-1] Extension System, Part IV: ExtensionHandler and ExtensionHandlerInterface. These issues will clear up a lot of how extensions are constructed/handled by
ExtensionListand eliminate some of the weird hackery that's going on currently and the extended proposed changes that only add to the nightmare.Comment #44
alexpottThanks for the reviews
Re #42
$this->moduleHandler->alter('system_info', $extension->info, $extension, $this->type);- you are only supposed to be able to alter the info - not the extension object itself.key([])returns NULL. Again this is BC it is what system_default_region() does withreturn isset($regions[0]) ? $regions[0] : '';RE #43
For me this shouldn't be postponed on #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation that is make extensive changes whereas this is a small change in the object returned from the extension list which allows us to gives these extension object type specific functionality which is a nice change because it makes code easier to understand and will allow us to finally move forward and refactor the public properties we've been jamming on to this object for too long.
Comment #45
markhalliwellNot entirely sure how this is issue scope when it's introducing official properties that belong to the parent class in the first place.
I don't use it that much lol I wasn't aware that you were attempting to turn the Extension objects into decorated classes, which is why it looked quite odd for a sub-class to require a parent class. I tend to think of Extensions as stand-alone objects; able to be created using scalar values.
Please forgive my ignorance, I'm still not all that familiar with decorators as they aren't as prevalent on the FE (yet). Regardless, if this were to be a decorator, I think it'd need that name appended to the class to clarify what it's supposed to be doing. Given that it wasn't, I think that's what confused me the most.
True, I was thinking to postpone more on #3023131: [PP-1] Extension System, Part IV: ExtensionHandler and ExtensionHandlerInterface as that will likely change a lot of how Extensions are listed/handled as a whole.
edit: separating this out because I think it got overlooked.
Perhaps instead of postponing we should mark
Themeas@internaltemporarily?I suspect this object will undergo quite a lot of changes over several issues once it's introduced.
My only real concern is introducing something that isn't yet fully flushed out for the sake of expediency.
Comment #46
alexpottAdded @todo to #3026232: Deprecate Theme extension object public properties to deprecate public property usage.
I've thought about making
\Drupal\Core\Extension\ExtensionDiscoveryreturn Theme objects instead of Extension objects but I think that that should continue to work with raw Extension object and leave decorating to the ExtensionList classes because:Comment #47
dawehnerTo be honest decoration is a really weird word. We do composition here and the extension has a clear limited scope. Inheritance isn't the only way how you can architect your data structures :)
Comment #48
alexpott@markcarver it is fine for us to move the public properties up to extension but there really is out of scope here because that will involve tackling the module system - we don't have to here so let's not.
Wrt to change on the Theme object at the moment in HEAD everything is determined from the info array, the extension object and the theme status - the patch does not change that. And I've not seen future plans to change that. So the important thing here is that we agree the names of the public methods added to the Theme object and what public methods to add because that's what would be hard to change. Adding new method in future releases as we deprecate the public properties and provide decent getters for other things is allowed.
The new methods are:
I think the first 3 are well placed and named but I'm conflicted about the other two. Actually as
is never used outside the class we could make it a class property and be done. And we could leave _system_default_theme_features() in place and handle in a follow-up if we like. I've done that in the patch attached. Nice less new API and we can add similar stuff in the future if we like.
@dawehner yeah it is tricky - in the \Drupal\Core\Extension\ExtensionList::decorateExtension() I think the future will be always replacing the extension object with something specific like Theme / Module / Profile / ThemeEngine but we're not there yet. But I agree we're not doing the decorator pattern here. And no we're not taking an Extension object in the constructor we're doing less of a decorator pattern. Maybe I should go back to doing a proper decorate pattern and hand off calls to the wrapped Extension object?
Comment #49
alexpottComment #50
alexpottSo I think the important discussion to have is the name and documentation of
\Drupal\Core\Extension\ExtensionList::decorateExtensionHere's the default implementation:
Here's the theme override:
In the future when all extension types have their own object I think we should consider deprecating the base implementation and marking it abstract in a future major release.
Comment #51
markhalliwellI'm not sure what the name should be. Personally, I don't believe replacing
createExtensionInfois necessarily the right move here.In fact,
$info['mtime'] = $extension->getMTime();is missing from theThemeExtensionListimplementation.Maybe it should be its own new method that invokes
createExtensionInfo?I know this is out of scope, but food for thought... ExtensionInfo from #2186491: [meta] D8 Extension System: Discovery/Listing/Info was pretty much sidelined and merged with ExtensionList (which is already doing way too much IMO). It may be beneficial to rethink introducing this in another issue?
---
I think we should temporarily mark Theme as @internal.
I suspect this object will undergo quite a lot of changes over several issues once it's introduced.
My only real concern is introducing something that isn't yet fully flushed out for the sake of expediency.
Comment #52
phenaproxima+1 for this. I can't imagine too many people will extend or muck around with it, but we should at least make it as "sealed" and private as we realistically can, at least for now.
Comment #53
andypostAbout naming field api using notion of "massage" to extend fields to widgets
Comment #54
alexpottNot it's not - see Theme::__construct()
Wrt to marking it @internal - the problem with that is that is not really what I think you mean. People will interact with these objects. So they are not @internal - but what we don't what is for people to think this is an extensible API. So I think that we could argue that Theme should be final but the final debate is for another day because the topic of final seems contentious in the other issues it has come up in.
Comment #55
markhalliwellThat isn't ThemeExtensionList. I was referring to the code snippets in #50 and how it's a little confusing that it splits the responsibility of populating the info array between ThemeExtensionList and Theme.
People already interact with ExtensionList and it's marked @internal because we haven't yet finalized the service and for good reason. I don't see why we can't do that here as well. I don't see a reason why backing us into a corner is necessary just yet.
Ins't this technically a BC break (changing existing interfaces)?
Comment #56
andypostComment #57
claudiu.cristea@alexpott, @andypost
Do you think that the actual
theme_get_setting()could be moved as a method in the newThemeobject, as it has been suggested in #3035288-7: Deprecate theme_get_setting()?Comment #58
andypost@claudiu.cristea I think it is because of encapsulation of this logic related exactly to theme - and Mark already explained it in #3035288-11: Deprecate theme_get_setting()
So makes sense to figure #2024043: Add Module, Theme, Profile, and Extension value objects
Comment #60
andypostComment #61
vacho commentedI contrib to this cause rerolling.
Comment #62
vacho commentedComment #63
volegerFix CS issues
Comment #64
ravi.shankar commentedComment #66
ravi.shankar commentedHere is a re-roll of patch #63.
Comment #67
gábor hojtsyHm, so in #3111942: Remove all remaining @deprecated code from system module I attempted to remove the region constants. They were deprecated with a suggestion to use
\Drupal\block\BlockRepositoryInterface::instead. So if we are adding this new API in 8.9 that changes what the resolution for the deprecation is. How is that compatible with defining deprecations up until Drupal 8.8? Tagging for release manager review.Comment #68
berdirYes, this missed the deadline and therefore the solution is likely to undeprecate that constant or change it to a D10 removal.
Comment #69
alexpottOpened #3112263: Undeprecate REGIONS_* constants to remove the deprecation. We can then do something like this in Drupal 9.
Comment #70
gábor hojtsyMoving to Drupal 9.1 then :)
Comment #71
daffie commentedComment #72
hardik_patel_12 commentedRe-rolled for 9.1.x
Comment #73
ravi.shankar commentedRemoved needs re-roll tag.
Comment #74
daffie commentedThe patch fails the testbot.
Comment #76
andypostfor 9.2.0
Comment #77
suresh prabhu parkala commentedRe-roll against 9.2.x. Please review.
Comment #78
andypost+ * @expectedDeprecation system_region_list() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. UseWrong reroll
Comment #80
nikitagupta commentedComment #81
daffie commentedThe testbot is not happy.
Comment #82
jofitzLet's start by re-rolling the patch from #80...
Comment #83
daffie commentedThe patch is failing the testbot. See: https://dispatcher.drupalci.org/job/drupal_patches/93500/.
Comment #85
volegerRerolled #82
No interdiff.
Comment #86
andypostre-roll went wrong
Comment #87
volegerSince #63 patch lost some important parts, another rerolling based on #63
Comment #88
volegerFix CS
Comment #89
volegerComment #91
volegerFixed missing parts
Comment #92
alexpottI always liked this patch. Really nice to see it moving again. Thanks @voleger. Now we're targeting Drupal 9 we can use return typehints and scalar typehints.
Can add a return typehint.
Can add scalar typehints
Can add return typehint
Will need a return typehint.
Comment #93
volegerAddressed #92
Comment #94
volegerMoved optional construct argument into the end of the list
Comment #95
volegerTests passed. Ready for the review
Comment #96
andyposts/Gets/Returns
s/Gets/Returns
s/Gets/Returns
wondering why theme handler used to access extension instead of
\Drupal\Core\Extension\ExtensionList::get(), it may not need decoration and could use built-in caching. It reminds me abou #2941155: ModuleHandler should not maintain list of installed modules now that ModuleExtensionList existsshould use 9.4.0, not clear why 8.8.0 used
Comment #97
andypostnot sure this properties should remain public
Comment #98
alexpottRe #97 yes they should - we have to address this in a follow-up to deprecate public access (or make them read-only). The issue here is that they are already in use like this. So we shouldn't change that here.
Re #96.4 and .5 - that's this patch showing it's age :)
Comment #99
alexpottAlso...
Gets a list of all regions for the theme.could beLists all the theme's regions.And
Gets a list of visible regions for the theme.could beLists all the theme's visible regions.Gets and Returns seem unnecessary... we can use the verb from the method name.
Comment #100
volegerAddressed #96 .1 .2 .5
Comment #101
sourabhjainComment #103
andypostre-roll for 9.5
Comment #105
andypostthe failed test does not work with stark somehow but classy is missing
Comment #106
catch9.5 is closed to new code deprecations (modules and themes are still fair game) to give contrib a stable API to port against.
So I think this needs to be targeted at 10.1.x now.
Also I think this is probably more in 'major task' territory than 'major bug', seems like the 'bug' aspect of this is just a docs issue.
Comment #107
volegerrerolled for drupal:10.1.x
Comment #108
smustgrave commentedRerolling so I can work on https://www.drupal.org/project/drupal/issues/3035288
Comment #109
andypostsystemRegionList($themeshould be deprecated as wellComment #110
anybodyNW as of #109
Comment #111
smustgrave commentedRerolled but for #109 can you provide more detail? I see that systemRegionList is deprecated.
Comment #112
andypostsomehow phpstan giving false positive here as the method executed via magic
\Drupal\Core\Extension\Extension::__call()Comment #113
smustgrave commentedSo this a bug with something else?
Comment #114
andypostLet's see if this will allow to pass, thanks to @mglaman
Comment #115
andypostSorry for assigning, the ref is https://github.com/guzzle/guzzle/blob/6.5/src/Client.php#L13
Comment #116
andypostFix CS
Comment #118
smustgrave commentedFixed failing test.
Comment #119
andypostI think it's ready for RM review
There's issue for that #2959989: Deprecate Extension::__call() magic
Comment #120
volegerAdded deprecation tests for protected methods from the Block module
Comment #121
volegerFixed the typo in the test method name
Comment #122
quietone commentedSorry folks, the CR has an @todo. Can someone attend to that?
And I think the deprecation notices for the constants needs to be changed.
While I do not see a specific case for deprecating constants, I also see no reason that this can't be same as for deprecating method parameters. That would mean the second @see in each case is removed as is "it will not exist in Drupal 1".
Comment #123
smustgrave commentedTook the description of this ticket for the CR.
Updated the comments too based on #122
Comment #124
andypostcould be removed as already commited #2959989: Deprecate Extension::__call() magic
needs fix
Comment #125
akram khanUpdated Patch and address #124
Comment #126
akram khanSorry for added wrong in #125
when applied patch #123 on 10.1.x it throwing some error added screen shot as well
Comment #127
viappidu commentedWorked 3015812-123.patch addressing comments on #124
Main difference (after #2959989: Deprecate Extension::__call() magic):
$this->info['mtime'] = $this->getMTime();
Becomes
$this->info['mtime'] = $this->getFileInfo()->getMTime();
Comment #128
andypostChecked last patch and looks like it's ready
Comment #129
quietone commentedSorry folks. The patch is fail commit code checks.
Comment #130
ameymudras commented#127 was not getting applied, I have made changes and hopefully, it should work. Couldn't generate the interdiff here because of "Whitespace damage detected in input"
Comment #131
ameymudras commentedComment #132
quietone commentedThis is tagged for a release manager review. In #67 a question was asked regarding the compatibility of the deprecation being added with the one added in the previous minor version. At that time that this was adding a deprecation to 8.9. Those concerns are no longer relevant because there isn't a supported version of Drupal with those deprecations. I discussed this issue with xjm and we agree.
I am removing the 'Needs release manager review' tag.
Comment #133
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #135
volegerIntroduced MR which contains #130 patch.
Comment #137
andypostComment #138
andypostbtw when core will require PHP 8.5 we can deprecate constants https://wiki.php.net/rfc/attributes-on-constants
Comment #139
nicxvan commentedComment #140
xjmFor the RM review mentioned in #132.
Comment #142
berdirUpdated and rebased, still running tests, but I think in a state where it can be reviewed.
Comment #143
claudiu.cristeaI think the const replacing enum is missing
Comment #144
berdirEnum is not missing. Issue summary has an overview of all the changes here. Still expecting some test fails, but the worst one should hopefully be fixed now.
Comment #145
nicxvan commentedGot some comments on the MR, I need to think about this approach a bit,
It is nice to remove the need entirely of these constants.
In not sure about the decorating pattern, but it seems to make sense.
Comment #146
berdirI think the main remaining thing for me is the decorate naming/concept. This has been discussed quite a bit already, in #46/#47 for example. I don't think this is a decorator. Yes, a decorator does return a new object, but it's IMHO one that adheres to the original interface. That's not the case there. Theme is a child class that adds its own methods and concepts that do not exist on the parent. Decorator specifically allows to decorate the same object multiple times.
@dawehner in #47 also talks that we use composition and not inheritance, but that's not true, neither then nor now. Theme extends Extension, so it is inheritance. We're working with value objects and not interfaces, as far as I see it's impossible to use composition here if we want Theme objects to be used as more generic Extension objects too.
The only idea I have right now is to use a less opinionated, more generic term for this method, possibly just alterExtension(), which would kind of match the system_info_alter hook. Possibly wrap, *if* it were actually composition. Is there a verb that we could use that translates to "Use specific subclass"?
I'm also wondering if we should split the info parsing from the altering/subclassing. I'm not really convinced of the move of the defaults and mtime from ThemeExtensionList to the Theme constructor. I think we could keep it where it is and then we have to change fewer things. This started before ThemeExtensionList existed, so the context here changed quite a bit.
I think my proposal would be something like this:
I thought about using $info and passing that around as a second argument, but that's no longer an alter then and it's doing multiple things again.
Speaking of mtime, I was confused about that one too, because I don't see any usage of this in core outside of tests. This was added 14 years ago in #1355526: Add a way to determine the date a module was added so the modules page can use it for sort, even then it was just verified in tests. I'd assume that mtime is rarely useful with composer and modern deployment processes. And package manager and stuff is going to deal with "enable a recently enabled module" in its own way.
Comment #147
berdirI implemented my suggested change now, essentially restoring createExtensionInfo() and introducing subClassExtension() per suggestion from @alexpott This significantly simplifies the required changes in the Extension component.
There is more that could be done in ThemeExtensionList. This moves the status and only the status from doList() to subClassExtension() as that was in decorate before as well. We could:
a) further reduce the required changes here by restoring how status is set now and deal with that later.
b) keep it as is.
c) Move more logic from doList and set them through the constructor/methods. There are still several dynamic properties being set there, like module_dependencies, base_themes and sub_themes. But we can't move everything as parts depend on having all themes and then adding that information.
I think c) is a rabbit hole that will blow this up considerably. I don't care much between a) or b). What I would suggest is that we mark Theme as either @final or real final, to make it clear that we do not support subclassing this. We want to change the constructor, add methods and properties later without having to worry about subclasses.
There are possibly even more options. We could do the subclass in doList() and not introduce subClassExtension() at all, then the parent would not need any changes, but I think this is fine as an extension point for other extension types later on.
Comment #148
nicxvan commentedYeah a or b make sense.
To be honest this feels manageable at this point so leaving it as is is probably fine.
If we want to be extra careful rolling that bit back it's the way to go.
@final makes sense too, I'm strongly against real final.
Comment #149
alexpottRe #147 I guess reading that and thinking about my comment about readonly - means that actually I'd be in favour of (a). Let's do a minimal change.
Also +1 to final or @final. I think in this case a real final might be better considering we know that this issue is the start of quite a few changes necessary to make the Theme class behave the way we'd like.
Comment #150
berdir@alexpott, see updates, is that what you had in mind? I also added a @final, I agree with you, but I'm doing my best to avoid any holy wars around final, either is fine for me.
Comment #151
alexpottThis looks great and yeah avoiding holy wars seems like a good idea.
Comment #152
nicxvan commentedI think this is ready for the next steps, I took another in depth look at the code, and it's come together very nicely!
I also edited the CR pretty heavily, it was targeted towards 8.7!!!
Comment #153
godotislateNW for merge conflict.
Comment #154
nicxvan commentedRebased, it was a comment on a deprecated method that was removed in the deprecation removal bunch of issues.
Comment #155
godotislateThe phpstan baseline needs a rebase. I also added comments to the MR.
Also, I know the "decorate" or "subclassExtension" terminology has already been much discussed, so I don't want to block this, but I have an alternate idea that could be done in a follow up if people think it's worthwhile. Instead of copying an Extension object to a subclass object, we could do this:
Add an optional "
$extensionClass" constructor parameter and class property to ExtensionDiscovery, so that it looks like this:And in ExtensionDiscovery::scanDirectory() change
new Extension($this->root, $type, $pathname, $filename)to
new $this->extensionClass($this->root, $type, $pathname, $filename).The constructor of Theme would need to be changed to match Extension, so there'd be some brittleness there. The alternative would be to put it in a createExtension() method, but then every ExtensionList would need a corresponding discovery class with createExtension overridden.
In
ThemeExtensionList::getExtensionDiscovery():Comment #156
nicxvan commentedThank you for the review!
I reviewed all of your suggestions they look great. I will hold off on applying them to preserve my ability to rtbc.
In reviewing your suggestions I noticed there are two properties we no longer need in the theme extension object as well.
Happy to create a follow up for: 155.
Comment #157
berdirI think the main concern I have with #155 and pushing the Theme object down into discovery is that we'd need to forever support partial theme objects. All the theme stuff that depends on the .info.yml content would need to be optional/nullable and then added during a later build phase, so we'd need to keep track of partial/finalized objects or something like that. If not for that I'd be fine exploring this also in this issue, but a follow-up to try that seems fine.
Comment #158
godotislateDiscussed with @nicxvan: prefix and owner properties on Theme should be deprecated here and then removed in a follow up for D12.
Consulting with other release managers about the deprecated constants and protected methods.
Comment #159
berdirAs discussed on slack, removed two properties, I realized that extension objects allow dynamic properties and we have plenty of those, so it's fine to remove them, should not cause any issues in 11.x, although we might want to do do a 11.x MR just to be certain before merging.
The remaining thing then is the deprecated controller/form method and how to handle that.
Comment #160
nicxvan commentedI reviewed this, looks great. I'm not going to mark it since we are waiting on the protected method question.
Comment #161
godotislateDiscussed with @catch and @xjm, and the general sentiment is that we care a lot about removing usage of deprecated code paths when they are being deprecated, to help make sure that they actually can be deprecated.
So I gave this issue some more though in light of that. Since protected methods are not part of our BC promise, I looked at whether we could just remove them directly in 11.4. In contrib, there is of
BlockListBuilder::systemRegionList()(https://git.drupalcode.org/project/block_ajax/-/blob/3.x/src/AjaxBlockLi...), so to minimize disruption, I think it's fine to go with deprecate the methods. But I still think it's best to remove the usage of thesystem_region_list()and the constants in those methods, and it's consistent with the change toBlockController::getVisibleRegionNames()anyway. I also took a quick peek at #1452100: Private file download returns access denied, when file attached to revision other than current, and compared to there, removing the deprecated function usage is straightforward enough.Comment #162
berdirAccepted the two suggestions for the implementation of the method, but not the constant changes, did I understand you correctly with that?
> and compared to there, removing the deprecated function usage is straightforward enough.
It certainly is. I'm happy as long as we don't imply that doing it here also means we must do it there and evaluate that separately considering the complexity there.
Comment #163
godotislateIt's fine to go forward without the constant changes.
Comment #164
nicxvan commentedIn that case I think this is ready again!
Comment #167
godotislateThanks to everyone who helped on this one over. Did my best to update credit.
Committed b30fe98 and pushed to main. Thanks!
There's a merge conflict on block.module for 11.x, so moving to Patch to be ported for that.
Also just noticed that the URLs for the CR for the constant deprecations in system.module are wrong. Will push a fix for that shortly. Please make sure to include those changes in the 11.x port.
Comment #170
berdirCreated a new 11.x MR, including the follow-up.
Had to fix/reintroduce a few additional changes that aren't in main. The migrate tests need the fix for new BlockHooks(), and deprecatation test method in core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php needed to be adjusted as well.
Comment #171
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #172
berdirbot is confused about the 11.x branch I think.
Comment #173
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #174
smustgrave commentedSurprised it ignored the tag
Comment #175
smustgrave commentedMeant review per the bot
Comment #176
nicxvan commentedOk I reviewed this, pretty tedious.
Only differences were:
One additional case in ThemeHandlerTest needed updating to Theme.
3 or 4 Migrate tests needed fixing for the block rebuild call.
The tests are failing, but only committers have access to review this branch right now so please kick it back if it's a real failure.
Comment #177
nicxvan commentedComment #180
godotislateCommitted 0f4d171 and pushed to 11.x. Thanks!