Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLATTA-4940 use twig for link title only when needed #119

Merged
merged 4 commits into from
Aug 14, 2023

Conversation

dragos-dumi-ibm
Copy link
Contributor

@dragos-dumi-ibm dragos-dumi-ibm commented Jun 22, 2023

Currently all type link elements gets the title pass trough a twig.
This causes unnecessary load time, especially if toolbar is present, or a page with lots of links.
One title link rendering takes 0.8- 1.4ms as profiled, and some pages may have 150link + toolbar 300-400 links

I've taken a look into hdbt link twig and replicated the conditions where there's more things printed out besides the title -
Only in this case it makes sense to actually overwrite the title with a twig.
https://github.com/City-of-Helsinki/drupal-hdbt/blob/main/templates/module/helfi_api_base/helfi-link.html.twig

After we merge this, I'll open a PR into hdbt theme with the a comment in helfi-link.html.twig to warn as conditions in this link processor needs to be updated if conditions in twig changes.

@dragos-dumi-ibm dragos-dumi-ibm requested a review from tuutti June 22, 2023 13:58
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

No Coverage information No Coverage information
0.0% 0.0% Duplication

Copy link
Member

@tuutti tuutti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should check this with our frontend team (Mikko / Tero / Markus etc.) because I'm not 100% sure if we want to do this since we'd have to maintain two different templates for links. This feature was originally done so ALL links are run through same template.

Link filter might need an exception too: https://github.com/City-of-Helsinki/drupal-module-helfi-api-base/blob/main/src/Plugin/Filter/LinkConverter.php

I'm wondering if we could just exit early if the link has a route or somehow check if the link is internal, like

if ($url->isRouted()) { 
   return parent::preRenderLink($element);
}

since they cannot be external anyways.

@@ -35,7 +34,30 @@ public static function preRenderLink($element) : array {
$element['#attributes']['data-protocol'] = $scheme;
}
}
$element['#title']['#attributes'] = $element['#attributes'] ?? [];

if (!empty($element['#attributes']['data-is-external'])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be simplified by moving $use_helfi_link = TRUE inside previous if condition:

      if ($resolver->isExternal($element['#url'])) {
        $element['#attributes']['data-is-external'] = 'true';

        if ($scheme = $resolver->getProtocol($element['#url'])) {
          $element['#attributes']['data-protocol'] = $scheme;
        }
        $use_helfi_link = TRUE;
      }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tuutti yes, but I wasn't sure if there's any case where the $element['#attributes'] 'data-protocol' or 'data-is-external' could come already populated from the render array for an internal link !? cause basically if that's the case, then twig conditions would already cover that case...
I can do it like that if you think it should not be the case that an internal link could have these data- attributes

/** @var \Drupal\Core\Url $url */
$url = $element['#url'];
$url_attributes = $url->getOption('attributes');
if (!empty($url_attributes['data-selected-icon'])
Copy link
Member

@tuutti tuutti Jun 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this condition necessary? I think data-selected-icon it's set in https://github.com/City-of-Helsinki/drupal-hdbt/blob/main/templates/module/helfi_api_base/helfi-link.html.twig#L4 and the template is only used when the link is rendered through this preprocess.

EDIT: Nevermind.

@dragos-dumi-ibm
Copy link
Contributor Author

I'm wondering if we could just exit early if the link has a route or somehow check if the link is internal, like

@tuutti the isRouted would not cover the internal links that have "data-selected-icon"
ALso not sure if isRouted works with the links to the other drupals.. or is seen as external / not routed

@dragos-dumi-ibm dragos-dumi-ibm requested a review from tuutti June 26, 2023 11:35
@tuutti
Copy link
Member

tuutti commented Jul 6, 2023

@dragos-dumi-ibm One option would be to change this to be opt-in rather than apply to all links by default. I'll look into this today and let you know if it's possible.

@dragos-dumi-ibm
Copy link
Contributor Author

@tuutti do you have any suggestions / updates on this opt-in? the idea is good one, although I'm bit concerned on the impact on each site, if there's something more than the 'base' in certain ones.

@tuutti
Copy link
Member

tuutti commented Jul 25, 2023

@dragos-dumi-ibm not yet. I didn't actually have to time to investigate this before my vacation. I'll get back to this at some point next week.

@tuutti
Copy link
Member

tuutti commented Jul 31, 2023

@dragos-dumi-ibm Looks like we have a pretty good control over code using this feature. Here's some features using this:

  1. Link fields
  2. Regular menu links. I think we can add a boolean field to Menu configuration entities to indicate whether the menu should be processed
  3. Global navigation links
  4. Formatted (html) text fields. This is probably covered by link converted text processor already: https://github.com/City-of-Helsinki/drupal-module-helfi-api-base/blob/main/src/Plugin/Filter/LinkConverter.php

We can either add a flag to Url options to indicate whether the url should be processed, or remove the preprocessor altogether and run it manually against those feature.

@dragos-dumi-ibm
Copy link
Contributor Author

@tuutti
I was checking the code using this prerender link feature, but I'm not sure if doing the opt-in will be better for all cases.
An example is for menu links or global navigations

  • let's say we 'flag' all links from these modules to be processed with the twig, than we still apply unnecessary twig for internal links without icons - so still 'waisting' some time.
    • another option would be to flag individual links - but here would mean to code the conditions for processing in each module / scenario - i.e for 'ifExternal' and 'if has icon'
      Similarly would be for the other cases aswell.

Can't really tell which one is best:

  1. to have the conditions in the processing / prerender link applied for all links (as it is in this PR)
  2. or to 'duplicate' the conditions of when it should be processed or not in each module / feature

Or another option - not sure if this is what you had in mind. To keep what is currently in this PR, just in addition to only do the external / icon checks we are doing in preRender for the 'opt-in' / 'flagged' links ?

@tuutti
Copy link
Member

tuutti commented Aug 1, 2023

@dragos-dumi-ibm correct me if I'm wrong, but I think the icon logic is only used in formatted text fields (CKEditor link plugin):

image

We could probably remove the icon logic here just by explicitly running the link through helfi_link theme instead of Link::fromTextAndUrl() here: https://github.com/City-of-Helsinki/drupal-module-helfi-api-base/blob/main/src/Plugin/Filter/LinkConverter.php#L92

EDIT: Looks like it's used in Banner paragraph too.

@dragos-dumi-ibm
Copy link
Contributor Author

dragos-dumi-ibm commented Aug 1, 2023

@tuutti
so for icons, I see it being used also at least in 1 paragraph - banner - button
for menu links I see an icon attribute, but I don't find it being used (maybe it's a plan for it?)
the external link icon auto-added it seems is applicable to all features (menus, buttons)
the protocol icon, it is applicable for all in terms of markup, but not of css.

@tuutti
Copy link
Member

tuutti commented Aug 1, 2023

@dragos-dumi-ibm Hmm, my only problem with the current approach is that we have to add an exception for every new feature using this. Maybe we could just change the data-selected-icon check to something more generic, like $url->getOption('helfi_link')

Then just change the data-selected-icon to also set helfi_link = TRUE here:
https://github.com/City-of-Helsinki/drupal-helfi-platform-config/blob/main/modules/hdbt_admin_tools/hdbt_admin_tools.module#L722 and create a corresponding update hook to update existing links.

@dragos-dumi-ibm
Copy link
Contributor Author

@tuutti I've made some changes.
I also had to do this PR - https://github.com/City-of-Helsinki/drupal-hdbt/pull/718/files
I didn't found an easy way to add the option to the url in the twig, so I had do also write this https://github.com/City-of-Helsinki/drupal-module-helfi-api-base/pull/119/files#diff-51299ad5c80d835772eac05738b89d27831c83457c041d8fb38b19cc2e4fe6d0R43

@tuutti
Copy link
Member

tuutti commented Aug 3, 2023

@dragos-dumi-ibm OK, I had time to actually test this yesterday and I now get why you've done this the way you did it originally. Should've actually tested this before to not to waste your time, sorry!

I think we have three options here:

  1. Revert this back to the original and live with the icon exception logic
  2. Create a new twig function helfi_link and convert all existing link() function calls in twig templates to use it
  3. link() call from twig seems to convert the $element['#title'] to Drupal\Core\Render\Markup object, so in theory we could use that to filter out "system" links, like toolbar etc.

I did some rudimentary testing with this:

  public static function preRenderLink($element) : array {
    $useTemplate = FALSE;

    if (isset($element['#url']) && $element['#url'] instanceof Url) {
      $url = $element['#url'];

      if ($element['#title'] instanceof Markup) {
        $useTemplate = TRUE;
      }

      /** @var \Drupal\helfi_api_base\Link\InternalDomainResolver $resolver */
      $resolver = \Drupal::service('helfi_api_base.internal_domain_resolver');

      // We can't set URI's 'external' property to FALSE, because it will
      // break the URL validation.
      if ($resolver->isExternal($url)) {
        $element['#attributes']['data-is-external'] = 'true';

        if ($scheme = $resolver->getProtocol($url)) {
          $element['#attributes']['data-protocol'] = $scheme;
        }
        $useTemplate = TRUE;
      }
    }

    if ($useTemplate) {
      $element['#title'] = [
        '#theme' => 'helfi_link',
        '#url' => $element['#url'],
        '#title' => $element['#title'],
      ];
      $element['#title']['#attributes'] = $element['#attributes'] ?? [];
    }

    return parent::preRenderLink($element);
  }

and it seemed to cover all our use cases I can think of.

@dragos-dumi-ibm dragos-dumi-ibm force-pushed the PLATTA-4940-LinkProcessor-fix branch from 2c0addd to 26eff25 Compare August 8, 2023 08:28
@codecov-commenter
Copy link

codecov-commenter commented Aug 8, 2023

Codecov Report

Merging #119 (4d7e475) into main (b178224) will increase coverage by 1.82%.
Report is 10 commits behind head on main.
The diff coverage is 96.51%.

❗ Current head 4d7e475 differs from pull request most recent head f9dcc96. Consider uploading reports for the commit f9dcc96 to get more accurate results

@@             Coverage Diff              @@
##               main     #119      +/-   ##
============================================
+ Coverage     62.46%   64.29%   +1.82%     
- Complexity      441      468      +27     
============================================
  Files            64       65       +1     
  Lines          1564     1641      +77     
============================================
+ Hits            977     1055      +78     
+ Misses          587      586       -1     
Files Changed Coverage Δ
src/Plugin/migrate/source/HttpSourcePluginBase.php 29.57% <ø> (ø)
src/EventSubscriber/MigrationSubscriber.php 87.50% <50.00%> (ø)
src/Link/LinkProcessor.php 91.66% <88.23%> (-8.34%) ⬇️
src/Commands/MigrateHookCommands.php 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@dragos-dumi-ibm
Copy link
Contributor Author

@tuutti I've reverted to the initial version with the updates you've suggested

@tuutti
Copy link
Member

tuutti commented Aug 9, 2023

@dragos-dumi-ibm Thanks! I think the if title instanceof Markup check should cover the icon as well.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Aug 9, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@dragos-dumi-ibm
Copy link
Contributor Author

indeed, but just because currently any other icon than external is attached to a title that has markup. I removed it now.

just to mention, with this markup check, the internal buttons are still sent to twig, although is not necesary... but thinking that can't be that many in one page, it probably has minimal impact.

Thanks,

Copy link
Member

@tuutti tuutti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I think we can move forward with this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants