Problem/Motivation
Although datetime_extras hides the daterange_duration widget if duration_field isn't installed, there's no check for the right version. We require the 8.x-2.x series. The .info.yml file defines a test dependency, but we don't want a hard dependency enforced by core. However, if a site builder installs duration_field version 8.x-1.*, they get really confusing and obtuse error messages about it (if they know where to even look):
The website encountered an unexpected error. Please try again later.
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "duration_field.granularity.service" in Drupal\Component\DependencyInjection\Container->get() (line 153 of core/lib/Drupal/Component/DependencyInjection/Container.php).
Proposed resolution
Inside datetime_extras_field_widget_info_alter() check for the right version of duration_field (perhaps by seeing if we have the required services) and hide the widget if we don't.
Perhaps generate a warning if we see an earlier version of duration_field? Not sure where that warning should go? Status report?
Remaining tasks
Finalize scope of the fixCode- Tests?
ReviewCommit
User interface changes
TBD. Probably site builders never see the widget as an option unless the proper version of duration_field is installed. Perhaps a warning is generated if the module is installed but it's from the wrong minor version release series.
API changes
None.
Data model changes
None.
Release notes snippet
?
Original report by @MrPaulDriver
After installing the duration module I am unable to add the daterange offset widget to the form display. After selecting the widget I see that the blue throbber is stuck in a spin and I also see two console messages referring to jquery errors, as below. I am running Drupal 8.7.3
Console message
...
The website encountered an unexpected error. Please try again later.
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "duration_field.granularity.service" in Drupal\Component\DependencyInjection\Container->get() (line 153 of core/lib/Drupal/Component/DependencyInjection/Container.php).
...
| Comment | File | Size | Author |
|---|---|---|---|
| #13 | 3061411.11_13.interdiff.txt | 1.1 KB | dww |
| #13 | 3061411-13.patch | 1.28 KB | dww |
Comments
Comment #2
mrpauldriver commentedComment #3
dwwThere's an awful lot of noise in those console messages. :( Thanks Symfony + D8. :/
The relevant part is this:
That's because you installed duration_field version 8.x-1.*, not the 8.x-2.* branch (as indicated in the README.md file as a requirement for this widget).
datetime_extras.info.yml says this:
But we don't enforce that as a hard module-level requirement, since we don't *require* that you use this widget. There's code to check for the module being installed before the widget is visible, but that doesn't also verify the version. To be more humane to site builders, we should also check the installed version (and/or ensure the existence of the services we're relying on).
Updated the summary and title to be a task about making this more user-friendly.
Meanwhile, if you upgrade to duration_field 8.x-2.0-rc2 or later, your problems should go away.
Thanks/sorry,
-Derek
p.s. I also updated the text in the project page about this version requirement to help avoid confusion.
Comment #4
mrpauldriver commentedThanks for that @dww
Comment #5
dww@MrPaulDriver: you're welcome. Sorry for the hassles/confusion.
To get this started, here's a fairly simple patch. Tested locally and working well.
Still TODO:
- Automated tests? Not sure how to do this since we have to get the testbot to install 8.x-2.0-rc2 for the actual tests to work. I guess we could do something unholy like a hook_system_info_alter(), but I'm inclined not to care about trying to have automated tests for this.
- Do we warn users if they've installed duration_field but have an old/stale version? If so, where/how?
Anyone have any opinions / thoughts on these?
Thanks,
-Derek
Comment #6
dwwAlso possible TODO:
system_get_info()returns an empty array if the requested module isn't installed. So, we could refactor this function a bit to drop the\Drupal::moduleHandler()->moduleExists('duration_field')call and only usesystem_get_info().Comment #7
dwwAutomated tests are being weird and annoying. See #3062037: [PP-1] datetime_extras automated tests are confused about PHP versions for more on that.
Meanwhile, manual testing of this patch and feedback on the questions/TODOs in #5 would be welcome.
Comment #8
mrpauldriver commentedJust circling back round to this, sorry for the delay.
After applying the patch, I see that the widget is not available and therefore not capable of giving errors. This much better, but still a bit confusing.
But now that the requirement for 8.x-2.x is documented on the project page, I question if it is necessary to do more work on this?
Isn't the real problem that
composer require drupal/duration_fieldfetches the 8.x-1.x branch even though 8.x-2.0-rc2 is available and is actually recommended by the project’s maintainer?Comment #9
dwwYeah, that's an unfortunate symptom of the duration_field maintainer not releasing 8.x-2.0 official. So long as it's an RC, even if d.o says that's the recommended branch, composer won't fetch it for you unless you say something like:
composer require 'drupal/duration_field:^2.0'Anyway, yeah, I'm also not too motivated to spend much more time on this. Would love some feedback from the other datetime_extras maintainers before I simply commit and move on.
Thanks,
-Derek
Comment #11
dwwI updated both README.md and the project page with the specific
composer requirecommand to use to get the right duration_field.Meanwhile, I suspected
system_get_info()was on the way out, and lo: #2940189: Deprecate system_get_info()So here's a new patch to use
\Drupal::service('extension.list.module')->getExtensionInfo().Also took out the @todo that the test bot is flagging as a CS failure.
RTBC?
Comment #13
dwwWhoops,
\Drupal::service('extension.list.module')->getExtensionInfo()throws an exception if the module isn't enabled, not just returning an empty array (likesystem_get_info()did). This should be better.Comment #14
mrpauldriver commentedWould you like this this testing Derek?
Comment #15
dww@MrPaulDriver: If you like. ;) I've tested, but more testing doesn't hurt.
I think once #3064009: Fix test deprecation notices in datetime_extras for 8.8.x core is committed and the 8.8 tests are actually passing again, we could commit this as-is.
Perhaps it's worth adding test coverage that we hide the widget when duration_field isn't enabled at all?
Neither this nor #2845081: Provide a datetime_range widget to define end time via a duration offset added any.
Maybe a new test method inside tests/src/Functional/LoadTest.php?
Or even add more assertions to testLoad() so we don't have to reinstall?
Comment #17
dwwAfter resolving #3064009: Fix test deprecation notices in datetime_extras for 8.8.x core, tests are passing properly on both 8.7.x and 8.8.x core, locally and on the d.o testbot.
Hearing no objections in here, committed and pushed #13 to 8.x-1.x branch.
If someone wants to add a test for the disappearing widget, we can do that in a follow-up.
Cheers,
-Derek
Comment #18
heddnA bit late, but there's a
existsmethod in extension list that would obviate the need for try/catch.Comment #19
heddnThere's also a core version constraint and API. See https://www.drupal.org/node/2756875
Comment #20
dww@heddn: thanks for the review. Further clean-up patches welcome if anyone is inspired, or maybe I'll be able to circle back soon.
Cheers,
-Derek
Comment #21
dwwI'm gonna take a quick stab at this.
Comment #22
dwwI'm bailing. The code in 8.x-1.x is working fine.
Re: #18:
Sadly, nope. :( the
ExtensionList::exists()method returns TRUE for a module that's present in the file system but not enabled. :( We need to ensure the module is actually enabled. I see nothing in that service that tells us what we want in 1 pass. So try/catch it is, since it does exactly what we need.Re: #19:
The docs @ https://www.drupal.org/node/2756875 are pretty sad. The inline code comments make no sense. I tried using this:
I then kept messing with the version key in duration_field.info.yml. I couldn't get a version string that this code found incompatible. It claimed that all of these are compatible:
...
WTF? I'm giving up. This dependency/constraint API is either thoroughly broken, or the docs are so unclear that it's unusable. Either way, I've gotta get back to real work.
Restoring the status.
Cheers,
-Derek