Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Note for committers:
This was merged with #2082103: Convert drupal_clean_css_identifier() to a component, please use the following commit message:
Issue #2121713 by tim.plunkett, dawehner, jiv_e, nick_schuch, splatio: Move drupal_html_id() and drupal_html_class() to \Drupal\Component\Utility\Html.
Updated: Comment #4
Problem/Motivation
drupal_html_id() and drupal_html_class() are non-Drupal-specific functionality and are good candidates for a Utility class
Proposed resolution
Move these functions to a Utility helper:
drupal_html_class() => \Drupal\Component\Utility\Html::getClass()
drupal_html_id() => \Drupal\Component\Utility\Html::getId()
drupal_clean_css_identifier() => \Drupal\Component\Utility\Html::cleanCssIdentifier()
Remaining tasks
User interface changes
N/A
API changes
N/A
Related Issues
Comment | File | Size | Author |
---|---|---|---|
#50 | html_id-2121713-50.patch | 38.89 KB | tim.plunkett |
#44 | html_id-2121713-44.patch | 38.89 KB | dawehner |
#44 | interdiff.txt | 585 bytes | dawehner |
Comments
Comment #1
tim.plunkettI might also move some of our web tests to unit tests, or at least write some new ones.
Comment #2
tim.plunkettOkay, I moved HtmlIdentifierUnitTest to PHPUnit, and replaced assertIdentical with assertSame.
It provided 73% coverage, missing the parts that check $_POST['ajax_html_ids'].
Still needs naming feedback.
Comment #3
dawehnerNeeds some docs ... is there any way to get rid of the statics, I fear not.
Is there a reason this is needed in here?
We could and should use data providers here.
Comment #4
tim.plunkett1) Added docs, and rewrapped to 80 chars.
2) I was originally checking that $form['#id'] was populated correctly, but that's not actually what I was trying to assert, just that $form['#id'] existed. So, fixed.
3) Done.
I also decided to renamed the class and methods after further discussion at badcamp. I will update the issue summary shortly.
Comment #4.0
tim.plunkettUpdated summary
Comment #5
tim.plunkettComment #6
ParisLiakos CreditAttribution: ParisLiakos commentedshouldnt this be just HtmlTest.
Also an @group Drupal :)
shouldnt we say Html::getClass here? :)
this is a red flag for a component..Maybe move this to the DIC and make it request aware
Comment #7
dawehnerThe dx of that would though dramatically degresse. I wonder whether we can have an event listener which sets the current active ajax html IDs onto a static property
Here is a current rerole after some test additions that landed.
In case we want to have the service, we might should just move the html IDs into a service but keep the other function in a component?
Comment #8
ParisLiakos CreditAttribution: ParisLiakos commentedThis sounds pretty good i guess. Add a
public static function setAjaxHtmlIds(array $ids)
then call it from an event subscriber:)Which means the component knows nothing of the Request
Comment #11
jiv_e CreditAttribution: jiv_e commentedI would like to work on this. I accidentally created dublicate issue, where you can see some of my ideas. https://drupal.org/node/2167261
Some thoughts:
First, I think the following function calls would be easy to read and understand. They are also abstract enough to use in different situations and not restricted to only on classes and ids. I'm not sure if the word validate can be used here though. It could be seen as just checking if the string is valid. What would be a better word?
I see no reason to not cache already validated identifiers. So we can combine drupal_html_class and drupal_clean_css_identifier. At the moment drupal_html_id dublicates code from drupal_clean_css_identifier. My plan would be to call validate() inside validateUnique().
Comment #12
jiv_e CreditAttribution: jiv_e commentedAfter fast review of the provided patches I could also go for this naming convention.
Comment #13
Damien Tournoud CreditAttribution: Damien Tournoud commented@jiv_e: CSS classes and HTML IDs are not the same. Let's not mix them (if I remember correctly, we used to in previous versions of Drupal).
Also, it's not about validating (which imply a true / false result), but about (1) generating for HTML ids, (2) cleaning up for CSS identifiers.
Comment #14
Damien Tournoud CreditAttribution: Damien Tournoud commentedIf we want to have both CSS and IDs in the same component (I could go either way), let's just keep the method names that @dawehner had in #7.
Comment #15
jiv_e CreditAttribution: jiv_e commentedAfter considering what Damien said I also think that we should keep the ID and class in the function names e.g. like this.
I'm not sure if 'html' as service name is too generic. It could be misleading.
But I'd argue that cleanCssIdentifier could be private method and called by both public methods above to avoid code duplication.
At the moment drupal_clean_css_identifier is called 23 times in core excluding tests. The frequencies seem to be:
Getting ID: 2
Getting class: 20
Getting views template path: 1
After thinking about it I can't see any other correct use case for this function than getting class or ID. Also getting ID with this function seems wrong, because the uniqueness is not ensured.
Comment #17
Damien Tournoud CreditAttribution: Damien Tournoud commented@jiv_e: HTML5 dropped all the requirements on IDs, so it makes sense to use the same requirements as CSS class names so that we guarantee that there is no need to escape characters in CSS and Javascript selectors. So ok to make cleanCssIdentifier protected and have both getId and getClass leverage it.
I wonder if we shouldn't drop the caching in getClass, or at least move it to cleanCssIdentifier and move the drupal_strtolower there too.
Comment #18
jiv_e CreditAttribution: jiv_e commentedComment #19
jiv_e CreditAttribution: jiv_e commentedComment #20
dawehnerRerolled the patch.
Comment #21
dawehnerWrong patch file.
Comment #24
tim.plunkettReroll.
Comment #26
tim.plunkettMore fixes.
Comment #28
dawehnerThis fixes it.
Comment #29
jiv_e CreditAttribution: jiv_e commentedLast patch was outdated so I recreated it. Basically the tests were changed a little bit. As we went through them with @ohthehugemanatee. They seemed friendly.
I had some issues with interdiff though. I got this error:
The mentioned rejection file contained this:
I think this won't matter because these functions are removed in both patches (28 and 29).
Comment #30
jiv_e CreditAttribution: jiv_e commentedComment #32
rteijeiro CreditAttribution: rteijeiro commentedAnother re-roll.
Comment #34
jiv_e CreditAttribution: jiv_e commentedI finally managed to debug the tests with PHPStorm and Xdebug. I found out why there were two tests failing in the last patch. During the test run forms with same ids are created multiple times. For some reason those are cached and id-numbers added. Even if I think they shouldn't they don't represent the case of rendering multiple forms on the same page. I don't yet know why the behaviour is changed.
Fails because
Expected: test-form
Actual: test-form--2
Fails because
Expected: test-form-id
Actual: test-form-id--3
Comment #35
jiv_e CreditAttribution: jiv_e commentedDawehner, have you intentionally replaced the more general cache clearing function with the more spesific one?
This seems to be ok even though I can't see how the cache name 'drupal_html_id' corresponds to static::$seenIds.
Same here.
But here drupalStaticReset is meant to empty the whole static cache. How can this be replaced with only Html::resetSeenIds() ?
Comment #38
dawehnerPreviously drupal_html_id() used __FUNCTION__ for its static cache key.
Comment #40
dawehnermuh
Comment #42
dawehnermeh.
Comment #43
tim.plunkettNice work on the AjaxSubscriber!
I added test coverage for that part of getUniqueId, removed the old getInfo, and updated the deprecated comments.
Comment #44
dawehnerJust nitpicks.
Comment #45
tim.plunkettI think this is finally ready. Thanks again to @dawehner for solving this elegantly, and getting it going again.
Comment #46
dawehnerCool, thank you for the review.
Comment #47
jiv_e CreditAttribution: jiv_e commentedThanks for taking this forward! I got too busy.
Comment #48
tim.plunkettUpdated suggested commit message.
Comment #50
tim.plunkettRerolled, no changes.
Comment #52
webchickI was a little turned around with why we touched AjaxRequestSubscriber in this patch. Tim explained on IRC that a) there's only one Ajax subscriber, so just call it what it is, b) the current code for determining HTML IDs has to go through backflips to see what HTML IDs might've been used on an Ajax request, the new version of the code just announces it. Seems fair.
Committed and pushed to 8.x. Thanks!
Comment #54
iMiksuCleaning up drupalcampfi tags.