Issue #1898426 by Floydm, Cottser, jenlampton, chrisjlee, kattekrab, jerdavis, derheap, hussainweb: link.module - Convert theme_ functions to Twig.

Task

Use Twig instead of PHPTemplate

Remaining

  • Revised patch needed based on feedback in #28
  • Manual testing (see below)

Theme function name/template path Conversion status
theme_link_formatter_link_separate converted

To test this code...

1) enable the link module (admin/modules)
2) add a link field to a content type (admin/structure/types)
3) change the display format to 'Separate title and URL'
3) add a piece of content (node/add)
4) view the piece of content to confirm the link is being rendered through link-formatter-link-separate.html.twig

#1757550: [Meta] Convert core theme functions to Twig templates

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

c4rl’s picture

Issue tags: +Twig

Tagging

rcaracaus’s picture

Assigned: Unassigned » rcaracaus
rcaracaus’s picture

Assigned: rcaracaus » Unassigned
floydm’s picture

Status: Active » Needs review
FileSize
1.46 KB

I've been trying to learn a bit about D8 and Twig this evening, so I checked out the Twig sandbox and tried following the conversion instructions for the simplest module needing to be ported I could find, this one. My patch is attached. We'll see if this is at all on the right track.

floydm’s picture

Yay, I may not have totally completed the job, but at least I didn't blow anything up.

BTW I punted on dealing with l() since it looks like there are some big discussions happening around it.

#1812562: Create best practices about use of the l() function and the url() function in templates
#1922454: Gut l(), fix theme('link'), have a working framework for consistently generated links inside and outside of Twig

jenlampton’s picture

Hi Floydm, and thanks for jumping right in! :)

A few notes..
- In the Twig sandbox all the templates lived in the stark theme, but as part of the move to core we're putting them "back where they belong" so in this case there needs to be templates directory added into link module, and your new template goes there.
- We also need to remove the theme function, since we are replacing it with the preprocess + template file. (We did not remove the theme function in the sandbox, for testing purposes)
- We're going to remove the process layer, so we need to remove any reference to template_process * @see template_process()
- We changed our minds about checking variables a few times, but in the end we decided not to use 'is defined' anymore in {% if title is defined %}
- When using a filter, we don't want any space around the pipe character {{ title | striptags }}
- But, rather than use a striptags filter, let's preprocess that baby so we can just print title.
- We need to add a 'template' in our hook_theme implementation.

Here's a re-roll of this patch, with the above changed. Let's see if it works!

Status: Needs review » Needs work

The last submitted patch, core-update_link_to_use_twig-1898426-6.patch, failed testing.

floydm’s picture

Thanks @jenlampton, for the explanation.

I updated my twig sandbox and applied this patch in the hope of helping take it farther, but I think I'm in over my head. It looks like this is failing in the unit tests, so I figured out how to run them on my box today, which is *something*, but ... I'm not quite sure how/where to take it from here. More reading up to do, I guess. :)

jenlampton’s picture

@Floydm,

The next step would be to take this patch and apply it to a local install of Drupal 8 HEAD (not the sandbox), and then run only the test(s) that failed. I'd start with LinkFieldTest. Find out what that code is testing, and see if those conditions actually exist after this patch.

From the test result it looks like the first test is looking for the exact string <div class="link-item"><div class="link-url"><a href="http://www.example.com/content/articles/archive?author=John&amp;year=2012#com">http://www.example.com/content/articles/archive?author=John&amp;year=2012#com</a></div></div>.

If we have whitespace in there, or are missing a class or something, those are reasons we could be causing this test to fail.

That might be a simple fix, do you want to give it a shot?

floydm’s picture

Status: Needs work » Needs review
FileSize
5.23 KB

Hi @jenlampton. Thanks for the follow up.

I don't quite get what is going on, but I get errors like "Fatal error: Call to a member function entityType() on a non-object in /www/d8/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php on line 475" and "FATAL Drupal\link\Tests\LinkFieldTest: test runner returned a non-zero error code (255)." when I try to run the test on my box with "php ./run-tests.sh --module --verbose link". Then I get all sorts of failures in the tests, like userLogin fails. Is that not the correct way to run the test?

So I haven't tested this locally, but I *think* it is just a whitespace issue in the tests. The new template introduces whitespace where previously there was none, so the attached patch attempts to copy the whitespace changes from the template into the tests.

Status: Needs review » Needs work

The last submitted patch, core-update_link_to_use_twig-1898426-10.patch, failed testing.

star-szr’s picture

@Floydm - Thanks for your work on this! I think it will probably be more instructive to run the relevant tests through the UI after enabling the Testing module.

floydm’s picture

Status: Needs work » Needs review
FileSize
3.8 KB

Thank you, @ jenlampton and @Cottser, for your help.

This now passes all tests on my box. There was one legitimate error in the template (two closing a tags) and the rest of the issues were new white space and carriage returns. I fixed the closing tag and added the white space to the tests.

aspilicious’s picture

Status: Needs review » Needs work
+++ b/core/modules/link/templates/link-formatter-link-separate.html.twigundefined
@@ -0,0 +1,19 @@
+  {% if title %}<div class="link-title">{{ title }}</div>{% endif %}

Why write all this logic in one line. I would place the actual printing of the div between the if statement

+++ b/core/modules/link/templates/link-formatter-link-separate.html.twigundefined
@@ -0,0 +1,19 @@
\ No newline at end of file

You need to end a file with a newline

floydm’s picture

Status: Needs review » Needs work
floydm’s picture

Status: Needs work » Needs review
FileSize
3.81 KB
floydm’s picture

Status: Needs review » Needs work

hang on. fixing newline too.

floydm’s picture

Status: Needs work » Needs review
FileSize
3.79 KB

Added newline to template.

The last submitted patch, core-update_link_to_use_twig-1898426-18.patch, failed testing.

floydm’s picture

Status: Needs work » Needs review
FileSize
3.79 KB

This patch passes all tests on my machine.

star-szr’s picture

Looking at sandbox issues and commits, I couldn't find anyone else to credit. So no commit message added to the summary for this issue.

jenlampton’s picture

This is looking good, but I'm not sure about the way new lines are added in the tests. I mean, it passed, so that's obviously good :) But can we check in the other core tests and see how the \n is usually added? Maybe we can just stick it on the end of the previous line, like:

-             $expected = '<div class="link-item">';
+            $expected = "<div class=\"link-item\">\n    ";

That would look a little better, anyway. But I'm curious to see how it's done elsewhere.

star-szr’s picture

The block rendering tests use implode() to add the newlines, not sure if that's the rule or the exception though. See the interdiff in #1898034-16: block.module - Convert PHPTemplate templates to Twig.

floydm’s picture

Agreed, @jenlampton, I'm not fond of the newlines either.

Thank you, @Cottser, for pointing out the block example. That seems like a better approach to me but we'll see what others think.

Rerolled the patch with the approach to newlines found in the blocks interdiff referenced in #23.

Status: Needs review » Needs work

The last submitted patch, core-update_link_to_use_twig-1898426-24.patch, failed testing.

star-szr’s picture

@Floydm - You're probably missing some blank lines now. I found it helpful to use debug() while working on the test to compare the expected output vs. the actual output.

floydm’s picture

Status: Needs work » Needs review
FileSize
4.46 KB

No I just made a dumb mistake. This time after fixing it I ran it to verify it passes all the tests, then built the patch and applied it to the 8.x branch to verify it applied cleanly, then ran the tests against the 8.x branch to verify it passed there too. So, really, this time it should work.

Thank you both, @Cottser and @jenlampton, for your patience and coaching.

steveoliver’s picture

Status: Needs review » Needs work

Here's a thorough review from my end.

On the test:

+++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
@@ -424,19 +425,23 @@ function testLinkSeparateFormatter() {
             $url_title = isset($new_value) ? truncate_utf8($url, $new_value, FALSE, TRUE) : $url;
-            $expected = '<div class="link-item">';
-            $expected .= '<div class="link-url"><a href="' . check_plain($url) . '">' . check_plain($url_title) . '</a></div>';
-            $expected .= '</div>';
-            $this->assertRaw($expected);
+            $expected  = array();
+            $expected[] = '<div class="link-item">';
+            $expected[] = '    <div class="link-url"><a href="' . check_plain($url) . '">' . check_plain($url_title) . '</a></div>';
+            $expected[] = '</div>';
+            $expected_output = implode("\n", $expected);
+            $this->assertRaw($expected_output);
 
             $url = $url2;
             $url_title = isset($new_value) ? truncate_utf8($url, $new_value, FALSE, TRUE) : $url;
             $title = isset($new_value) ? truncate_utf8($title2, $new_value, FALSE, TRUE) : $title2;
-            $expected = '<div class="link-item">';
-            $expected .= '<div class="link-title">' . check_plain($title) . '</div>';
-            $expected .= '<div class="link-url"><a href="' . check_plain($url) . '">' . check_plain($url_title) . '</a></div>';
-            $expected .= '</div>';
-            $this->assertRaw($expected);
+            $expected  = array();
+            $expected[] = '<div class="link-item">';
+            $expected[] = '      <div class="link-title">' . check_plain($title) . '</div>';
+            $expected[] = '    <div class="link-url"><a href="' . check_plain($url) . '">' . check_plain($url_title) . '</a></div>';
+            $expected[] = '</div>';
+            $expected_output = implode("\n", $expected);

I think we should /not/ change the test and instead use the {% spaceless %} tag around the entire codeblock of the template, as previously the markup has had no whitespace.

For the preprocess docblock:

+++ b/core/modules/link/link.module
@@ -408,20 +408,20 @@ function link_theme() {
 /**
- * Formats a link as separate title and URL elements.
+ * Preprocesses variables for link-formatter-link-separate.html.twig.
+ *
+ * @see link-formatter-link-separate.html.twig
  */

As per #1913208: [policy] Standardize template preprocess function documentation:

I think we should edit to this (may or may not want to add the @param $variables in):

/**
 * Prepares variables for separated link field templates.
 *
 * Core template: link-formatter-link-separate.html.twig.
 */

For the preprocess function:

+++ b/core/modules/link/link.module
@@ -408,20 +408,20 @@ function link_theme() {
-  $output .= '<div class="link-url">' . l($vars['url_title'], $vars['href'], $vars['options']) . '</div>';
-  $output .= '</div>';
-  return $output;
+  // @todo revisit this use of l() after http://drupal.org/node/1922454 is resolved.
+  $variables['link'] = l($variables['url_title'], $variables['href'], $variables['options']);

l()/theme('link') should be done soon.

As per Best practices - preprocess functions and templates:

Let's make this l() into a render array, like this:

$variables['link'] = array(
  '#type' => 'link',
  '#title' => $variables['url_title'],
  '#path' => $variables['href'],
  '#options' => $variables['options']
);

And for the template:

--- /dev/null
+++ b/core/modules/link/templates/link-formatter-link-separate.html.twig
@@ -0,0 +1,21 @@
+{#
+/**
+ * @file
+ * Formats a link as separate title and URL elements.
+ *
+ * Available variables:
+ * - link: The link that has already been formatted by l().
+ * - title: The title of the link.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_link_formatter_link_separate()
+ *
+ * @ingroup themeable

Since, once l()/theme('link') works as expected, we'll have all these variables, lets document them such:

/**
 * @file
 * Default theme implementation of a separated (title and URL) link formatter.
 *
 * Available variables:
 *  - link: A renderable link including the following properties:
 *    - title: The actual content of the link.
 *    - path: The base path of the link.
 *    - options: An array of options, including:
 *      - query: An array of query parameters for the link.
 *      - fragment: A string to be placed after a '#' in the link.
 *  - title: A descriptive or alternate title for the link, which may be different than the actual link text.
 *
 * @see template_preprocess()
 * @see template_preprocess_link_formatter_link_separate()
 *
 * @ingroup themeable
 */
+++ b/core/modules/link/templates/link-formatter-link-separate.html.twig
@@ -0,0 +1,21 @@
+<div class="link-item">
+  {% if title %}
+    <div class="link-title">{{ title }}</div>
+  {% endif %}
+  <div class="link-url">{{ link }}</div>
+</div>

Then wrap {% spaceless %} ... {% endspaceless %} around all 6 lines.

NOTE: Until '#type' 'link' returns an active class for links, this won't pass. So we can either:

a. Keep it failing and dependent upon #1888424: Make Drupal's URL generation logic available to HttpKernel, and minimize code repetition/divergence and/or #1922454: Gut l(), fix theme('link'), have a working framework for consistently generated links inside and outside of Twig, or
b. Insert a hack with @todo remove once above issues are fixed.

star-szr’s picture

Any takers for rolling a new patch based on the feedback in #28? If you have questions you can always stop by #drupal-twig on IRC :)

nikkubhai’s picture

Assigned: Unassigned » nikkubhai

I will try.

nikkubhai’s picture

Issue summary: View changes

add how to test

nikkubhai’s picture

Assigned: nikkubhai » Unassigned
star-szr’s picture

Issue tags: +Needs manual testing

Tagging.

star-szr’s picture

Assigned: Unassigned » star-szr

Rolling a new patch based on @steveoliver's feedback.

star-szr’s picture

Assigned: star-szr » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs manual testing
FileSize
2.29 KB
2.29 KB

Leaving the l() in for now. It's not perfect but at this point I'm not sure we have the luxury of waiting for #1922454: Gut l(), fix theme('link'), have a working framework for consistently generated links inside and outside of Twig.

The automated testing for this output is quite thorough as we've discovered, so I'm removing the manual testing tag I added last night.

Status: Needs review » Needs work

The last submitted patch, 1898426-34.patch, failed testing.

star-szr’s picture

Status: Needs work » Needs review
FileSize
2.65 KB

Oops, two interdiffs.

star-szr’s picture

FileSize
713 bytes
2.66 KB

Fixed indent level within {% spaceless %} tag.

chrisjlee’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
146.29 KB
164.05 KB

Seems to work nicely!

chrisjlee’s picture

FileSize
2.69 KB
586 bytes

Followup docs tweaks as per twig docs

star-szr’s picture

Thanks @chrisjlee! I agree this is good to go.

Status: Reviewed & tested by the community » Needs work
Issue tags: -Twig

The last submitted patch, 1898426-39.patch, failed testing.

star-szr’s picture

Status: Needs work » Needs review
Issue tags: +Twig

#39: 1898426-39.patch queued for re-testing.

star-szr’s picture

Status: Needs review » Reviewed & tested by the community
star-szr’s picture

Issue summary: View changes

Add conversion summary table

star-szr’s picture

+++ b/core/modules/link/link.moduleundefined
@@ -417,20 +417,31 @@ function link_theme() {
+  // @todo Revisit this use of l() after http://drupal.org/node/1922454 is
+  //   resolved.
+  $variables['link'] = l($variables['url_title'], $variables['href'], $variables['options']);

#1922454: Gut l(), fix theme('link'), have a working framework for consistently generated links inside and outside of Twig is resolved :)

What do we want to do with this now? #type link?

c4rl’s picture

c4rl’s picture

Title: Convert link module to Twig » link.module - Convert theme_ functions to Twig

Per #1757550-44: [Meta] Convert core theme functions to Twig templates, retitling to indicate this issue applies to theme_ functions, which are lower in priority than PHPTemplate conversion issues.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +needs profiling
jstoller’s picture

Status: Needs work » Needs review

#39: 1898426-39.patch queued for re-testing.

jerdavis’s picture

Assigned: Unassigned » jerdavis

Profiling

jerdavis’s picture

Issue tags: -needs profiling

Results, tested as described in summary

=== 8.x..8.x compared (519fbb3f5c2a0..519fbca569199):

ct  : 50,343|50,343|0|0.0%
wt  : 221,119|220,482|-637|-0.3%
cpu : 209,215|208,928|-287|-0.1%
mu  : 14,598,272|14,598,272|0|0.0%
pmu : 14,762,624|14,762,624|0|0.0%

http://www.lionsad.de/xhprof-kit/xhprof/xhprof_html/?run1=519fbb3f5c2a0&...

Run 519fbb3f5c2a0 uploaded successfully for drupal-perf-drupalcon.
Run 519fbcb7249d1 uploaded successfully for drupal-perf-drupalcon.
=== 8.x..1898426-39-field-link compared (519fbb3f5c2a0..519fbcb7249d1):

ct  : 50,343|50,430|87|0.2%
wt  : 221,119|221,500|381|0.2%
cpu : 209,215|209,535|320|0.2%
mu  : 14,598,272|14,642,552|44,280|0.3%
pmu : 14,762,624|14,805,968|43,344|0.3%

http://www.lionsad.de/xhprof-kit/xhprof/xhprof_html/?run1=519fbb3f5c2a0&...

kattekrab’s picture

Manually testing this now.

kattekrab’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
1.84 KB

HTML output identical.

See attached diff.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, twiglink_output.diff, failed testing.

jerdavis’s picture

Status: Needs work » Reviewed & tested by the community

Back to RTBC as testbot wasn't actually supposed to test that. See patch in #39

jerdavis’s picture

Issue summary: View changes

Remove sandbox link

kattekrab’s picture

thanks @jerdavis

star-szr’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Novice, +Needs reroll

#39 doesn't apply, needs a reroll.

star-szr’s picture

Assigned: jerdavis » Unassigned

Unassigning, anyone can work on the reroll.

scor’s picture

regarding #39:

+++ b/core/modules/link/link.module
@@ -417,20 +417,31 @@ function link_theme() {
+  // @todo Revisit this use of l() after http://drupal.org/node/1922454 is
+  //   resolved.

This issue was fixed: #1922454: Gut l(), fix theme('link'), have a working framework for consistently generated links inside and outside of Twig.

derheap’s picture

Assigned: Unassigned » derheap
derheap’s picture

Assigned: derheap » Unassigned
Status: Needs work » Needs review
Issue tags: -Novice, -Needs reroll
FileSize
3.36 KB

Rerolled the patch.
Removed the following comment.

+  // @todo Revisit this use of l() after http://drupal.org/node/1922454 is
+  //   resolved.

As far I have understood l(), the call is ok by now.

derheap’s picture

FileSize
3.27 KB

Made an error with the patchfile.
Removed comment is now really removed.

joelpittet’s picture

@derheap seems like something went a bit sideways with the re-roll. There is an extra bit at the end with "NodeTestStorageController.php" and "Prepares variables for separated link field templates." rewrite is missing.

Would you mind trying again from #39?
http://drupal.org/patch/reroll

I have a feeling maybe your repo wasn't rebased to origin/8.x, just a guess though...

joelpittet’s picture

Status: Needs review » Needs work
Issue tags: +Novice, +Needs reroll

retagging

hussainweb’s picture

Status: Needs work » Needs review
FileSize
2.6 KB

Attaching a reroll of patch from #39 and removed the comment as per #60.

derheap’s picture

@joelpittet: I had some problems with merge conflict. I am just a novice …
@hussainweb: thanks for fixing my reroll.

star-szr’s picture

Okay so this has been profiled, would like one more round of manual testing please.

Thanks everyone for moving this forward :)

joelpittet’s picture

@derheap no worries, thanks for the patch:) Merge conflicts can sometimes suck

joelpittet’s picture

Issue summary: View changes

Updated issue summary.

star-szr’s picture

Issue summary: View changes

Update commit message

hussainweb’s picture

FileSize
15.07 KB
12.51 KB

I just ran a quick test.

  1. I applied the patch from from #64.
  2. I enabled the Link module.
  3. I added a link field to Article content type and created test content. I changed the display formatter to 'Separate title and link' and verified it.

After above steps, I changed the twig file with arbitrary text.

Modified Twig file

Finally, cleared the cache and refreshed the content page and verified the arbitrary text:

Modified link output

hussainweb’s picture

Status: Needs review » Reviewed & tested by the community

Test result in comment #68.

star-szr’s picture

Status: Reviewed & tested by the community » Needs review

Sorry, you can't RTBC your own patch @hussainweb. Thanks for testing! We should also ensure the markup is the same before and after applying the patch :)

hussainweb’s picture

Got it. I thought it would be fine here because I just rerolled the patch. I will try and compare the markup shortly.

hussainweb’s picture

This is the default markup:

<div class="link-item"><div class="link-title">Google</div><div class="link-url"><a href="http://www.google.com/">http://www.google.com/</a></div></div>

This is the markup after applying the patch and clearing the cache. I also added random text and removed it from the twig file to ensure it was being used.

<div class="link-item"><div class="link-title">Google</div><div class="link-url"><a href="http://www.google.com/">http://www.google.com/</a></div></div>

They match exactly as far as I can see.

eromero1’s picture

Status: Needs review » Reviewed & tested by the community

The patch was implemented and tested and ran perfectly. Everything seems to be working.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 6ff8caa and pushed to 8.x. Thanks!

kattekrab’s picture

whoohoo! Thanks @alexpott - and thanks everyone for writing, testing, re-rolling, re-testing!

+ Snacks for the testbots :)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

Capitalization in commit message