Problem/Motivation
If a developer is adding a CSS library, and forgets to nest the assets under one of the existing categories (component, theme, etc), the following error is thrown:
Error: Cannot use assign-op operators with overloaded objects nor string offsets in Drupal\Core\Asset\LibraryDiscoveryParser->buildByExtension() (line 138 of core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php).
this happens, for instance, with the following (incorrect) code in foo.libraries.yml:
bootstrap-cdn:
remote: http://getbootstrap.com
version: 3.3.6
license:
name: MIT
url: https://github.com/twbs/bootstrap/blob/master/LICENSE
gpl-compatible: false
css:
https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css: { type: external, minified: true }
js:
https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js: { type: external, minified: true }
dependencies:
- core/jquery
Note the CSS needs to be nested like so:
...
css:
theme:
https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css: { type: external, minified: true }
Proposed resolution
Add an assertion to make sure $options is an array.
Remaining tasks
User interface changes
API changes
Data model changes
Comments
Comment #2
jhedstromThis adds an assertion which at least gives a hint as to what is happening. Another possibility would be to assert that the constant is defined.
Comment #3
dawehnerOh yeah, that is super annoying if this happens. I wonder whether we could give a slightly better tip, aka. explaining them that a category/scope is needed with maybe a link to some documentation about it?
Comment #4
jhedstromThis checks that the category constant is defined, and if not links to https://www.drupal.org/node/2274843.
Comment #6
jhedstromThis found an error in one of our test fixtures.
Comment #7
dawehnerThis is IMHO a quite good win for the theming experience!
I would be even better if we have a test for the assertion (just test for the thrown exception).
Comment #8
jhedstromThis adds a test for the assertion. (I wasn't sure if there's a better way to check for failed
assert()calls in PHPUnit or not.) The test-only file is the interdiff.Comment #10
dawehnerIMHO it would be nice if we could distinct between the invalid category (but right level of nesting) and the case on which someone forgot about the nesting, given that this allow much better error messages.
Comment #11
dawehnerComment #12
jhedstromre #11 I think the checks cannot both happen. If we check instead that
$optionsis an array, that assertion will always fail before we then check valid category. On the other hand, if we check for valid category first, that will always fail before we check if$optionsis an array...I have updated the test to fail more dramatically, as the IS shows.
Comment #14
dawehner@jhedstrom
Can't we just check for max depth of the array?
Treat this as 1
Treat this as 1
Treat this as 2
This should IMHO fix at least the common usecases
Comment #15
dawehnerI hope its okay to set it to needs work
Comment #16
jhedstromThis doesn't quite check the max depth of the array (I wasn't sure how to readily implement that in this particular bit of code w/o adding a new method for max array depth). However, it does properly differentiate between bad categories and improper nesting.
Comment #17
jhedstromHmm, this new re-work doesn't catch this failure:
Comment #19
jhedstromWhat if we went back to a single assertion and just updated the message to something like:
Invalid CSS category (CATEGORY) or CSS may be improperly nested. See https://...?I'm not seeing an elegant way to cover all the possible failures.
Comment #20
jhedstromThis adds a separate validation method as discussed with @dawehner at Drupalcon. This checks for improper option arrays, and then once those are verified, individual categories are asserted. Hopefully this results in clearer information for devs and frontenders.
Comment #21
dawehnerNote: https://thephp.cc/news/2016/02/questioning-phpunit-best-practices claims $this->setExpectedException should be used.
I had an idea for another case which could happen easily and we maybe should test:
Comment #22
jhedstromI didn't know about
setExpectedException. This seems much nicer. (Note, core is using a mix of both approaches at this time).Comment #25
jhedstromI wonder if there's a better way to move along these super-simple DX related fixes?
Comment #26
wim leersThank you so much!
We need this so bad!
Comment #27
larowlanIs there any reason we can't use constants here instead of integers?
These three methods essentially duplicate the same logic - the only difference is the extension name and the exception message - Can we change to a single method with a
@dataProvider?nit: whitespace at end of line here
nice catch - question why this is a js file in a css blob though - perhaps it should be 'js' as key (no nesting required) instead of css?
Comment #28
jhedstromIt seems to me adding constants that are only used in an assert call would be unnecessary overhead?
Comment #29
jhedstromI think this addresses the remaining feedback from #27. Good call on the data provider. Initial versions of the patch were using annotation for expected exceptions, for which a data provider wouldn't have worked.
I think originally
example.jswas just an oversight, so I've renamed that toexample.cssto avoid future confusion.Comment #30
wim leersGood call on the data provider indeed :)
Just one nit:
This can become
PHPUnit will then no longer say "Test case #1", but it will use that label!
Comment #31
dinesh18 commentedHere is an updated patch and interdiff which implemented #30
Comment #32
wim leersThanks! But then please also delete the now-pointless comments and whitespace.
So remove these, and remove the newlines between them.
Also, we don't want the interdiff to be in the patch :)
Comment #33
dinesh18 commentedHere is an updated patch and interdiff.txt
Sorry I haved added the interdiff in the patch.
Comment #34
wim leersPerfect! And no worries :) Thanks again!
Comment #35
larowlanUpdating issue credits to include reviewers that shaped the final patch.
Comment #36
larowlanCommitted 04573c0 and pushed to 8.4.x.
Thanks everyone for working on this, will make themer experience much nicer.
Comment #38
wim leersThis will make such a huge DX difference. Tentatively tagging .