Problem/Motivation

Currently if we want to get a Link object from a LinkItem object (i.e. field item of the "link" type), we have to get the Url and Title properties of the LinkItem separately and create instantiate a Link object ourselves:

$title = $link_item->get('title');
$url = $link_item->getUrl();
$link = \Drupal::Link->fromTextAndUrl($title, $url);

Steps to reproduce

Try to get a Link object from a LinkItem object

Proposed resolution

Make it possible to get the Link object with a single method call:

$link = $link_item->toLink()

Remaining tasks

None

User interface changes

None

API changes

A new toLink() method is added to Drupal\link\LinkItemInterface and Drupal\link\Plugin\Field\FieldType\LinkItem. It returns a Drupal\Core\Link object.

Data model changes

None

Release notes snippet

It is now possible to get a Link object from the LinkItem object.

Changed record drafted here: https://www.drupal.org/node/3458241

Issue fork drupal-2752187

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

thlor created an issue. See original summary.

thlor’s picture

thlor’s picture

Status: Needs work » Needs review
dawehner’s picture

Status: Needs review » Reviewed & tested by the community

I really like this feature. I'm just a bit worries about the potential BC break, mhhhh

thlor’s picture

Can you elaborate on your worry about potential BC break? Since this feature doesn't remove or modify anything preexisting, my understanding is that it does not break BC. https://www.drupal.org/core/d8-allowed-changes#bc-break

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 2: link_object_from_link_field-2752187-0.patch, failed testing.

thlor’s picture

Status: Needs work » Needs review

Seems to me the test failure is caused by the testing automation's error (https://dispatcher.drupalci.org/job/default/163826/ "FATAL: Unable to delete script file /tmp/hudson5317119343148217404.sh").

dawehner’s picture

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

Yeah that failure was a purely random one. Now that I look at this patch again we should ideally add some test coverage for it.
\Drupal\Tests\link\Kernel\LinkItemTest would be a perfect place for it. Sorry :)

pashupathi nath gajawada’s picture

Status: Needs work » Needs review
StatusFileSize
new1.68 KB

Hi Daniel Wehner,

As suggested in #8,
I have added the Drupal\Tests\link\Kernel\LinkItemTest.
Please find the updated patch.

Thanks,

thlor’s picture

Issue tags: -Needs tests

Removing "Needs tests" tag; test is supplied in #2752187-9: Add \Drupal\link\LinkItemInterface::toLink method.

bojanz’s picture

The idea makes sense.

Question: would toLink() make more sense than getLink()? getLink() makes me think it's giving me a property, but it's actually constructing a link object with the data contained by the field.

dawehner’s picture

toLink sounds better indeed.

bojanz’s picture

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

Let's do the rename then, and add the test coverage. #9 did not provide it.

It would also make sense to optionally allow setting a Link object as the LinkItem value. We have a value object, let's use it fully.

sharique’s picture

Status: Needs work » Needs review
StatusFileSize
new2.21 KB

Added test for getLink method.

Status: Needs review » Needs work

The last submitted patch, 14: getting_a_link_object-2752187-14.patch, failed testing.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

michaellenahan’s picture

StatusFileSize
new2.25 KB

Hi there, this is basically a reroll of Sharique's #14.
Changed getLink() to toLink() as suggested in #11 and #12.
I notice that Entity has a toLink() as well, so that's better for consistency.

I think the test will fail, it did when I ran this locally.
I think that line 179 in LinkItemTest.php
$link = $entity->toLink();
... is referencing Entity toLink(); not LinkItem toLink();

thlor’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 17: getting_a_link_object-2752187-17.patch, failed testing.

michaellenahan’s picture

StatusFileSize
new2.46 KB

@thlor thank you for setting that last patch to "needs review".

I think I have this working now ...

michaellenahan’s picture

Status: Needs work » Needs review
riddhi.addweb’s picture

Issue tags: +drupal core
tedbow’s picture

Issue tags: -drupal core

@Jigar.tanna there is no need to tag issues with "drupal core", I have seen you add this tag to a few issue today. Drupal.org issue are in projects. Since this one is in "Drupal core (3060)" that is what determines it deals with "drupal core".

By that way would be interested in your help on Outside In issues if you have the time and desire.

dawehner’s picture

+++ b/core/modules/link/tests/src/Kernel/LinkItemTest.php
@@ -89,6 +90,12 @@ public function testLinkItem() {
+    $this->assertTrue($link->getUrl()->toString(), $url, 'Link has expected url.');
+    $this->assertTrue($link->getText(), $title, 'Link has expected title.');

Nitpick which can be fixed on the commit: The order for these for these parameters are: $expected_value, $actual_value
This gives you some warm and readable output when this test might ever break.

michaellenahan’s picture

StatusFileSize
new140.29 KB
new91.29 KB
new2.46 KB
new877 bytes

Thanks, Daniel. New patch attached.

Although, I notice that assertTrue() actually only has two parameters ... at least from what I see here in phpstorm ...

https://www.drupal.org/files/issues/2752187-1.png

https://www.drupal.org/files/issues/2752187-2.png

dawehner’s picture

You are right about the message not existing in many phpunit assertions. These kind of messages don't add that many value, IMHO anyway.

dawehner’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests

Although, I notice that assertTrue() actually only has two parameters .

+++ b/core/modules/link/tests/src/Kernel/LinkItemTest.php
@@ -89,6 +90,12 @@ public function testLinkItem() {
+    $this->assertTrue($url, $link->getUrl()->toString(), 'Link has expected url.');
+    $this->assertTrue($title, $link->getText(), 'Link has expected title.');

This should use assertEquals instead :) There 3 parameters make more sense

michaellenahan’s picture

StatusFileSize
new7.22 KB
new5.61 KB

Yes :). While I was at it, I removed the other deprecated methods in the test.

michaellenahan’s picture

Status: Needs work » Needs review
michaellenahan’s picture

StatusFileSize
new948 bytes
new5.64 KB
new2.5 KB

While I was at it, I removed the other deprecated methods in the test.

Hmm. I guess I shouldn't do that. Removing those changes, because they are not relevant to the current issue.

dawehner’s picture

Hmm. I guess I shouldn't do that. Removing those changes, because they are not relevant to the current issue.

Exactly :) Please open up a new issue for that maybe. To be honest though it would be great to do those deprecation replacements in one big go. So one method but over the entirety of the codebase maybe.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

pasan.gamage’s picture

Status: Needs review » Reviewed & tested by the community

Tested the patch #30 on 8.7 branch.
Tests passed.

Runtime: PHP 7.2.10 with Xdebug 2.6.1
Configuration: /data/app/core/phpunit.xml.dist

Testing
Test 'Drupal\Tests\link\Kernel\LinkItemTest::testLinkItem' started
Test 'Drupal\Tests\link\Kernel\LinkItemTest::testLinkItem' ended

Time: 1.68 minutes, Memory: 686.50MB

OK (1 test, 36 assertions)

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: -link field +Needs change record

This is a great addition, I could literally use this and the chained ::toRenderable on at least 5 client projects tomorrow!

But we need to advertise its availability with a change record.

Can someone create one heralding the new feature with much fanfare.

Thanks

Lee

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

jennypanighetti’s picture

What is the current status of this? Should I attempt to re-roll the patch with 8.9.x? I really need this and thought I was going crazy that I have a LinkItem and I couldn't find a way to get an actual, renderable link from it.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

This issue is being reviewed by the kind folks in Slack, #need-reveiw-queue. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge require as a guide.

Believe it or not it appears patch #30 still applies to 10.1.x cleanly. Just triggered the tests for this.

From reading the comments sounds like this was all but done but never got a change record so sending to NW for that.

smustgrave’s picture

Status: Needs review » Needs work

Moving to NW for the change record please. Can mark this once that happens.

bircher’s picture

Issue summary: View changes
Status: Needs work » Reviewed & tested by the community

Omg! I follow this issue since probably six years.
I just went ahead and created the change record.

I checked the code too and it also looks RTBC to me, so setting the state to that.

xjm’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs followup

Thanks for proposing this addition!

As mentioned in #3306201: Add a title getter to LinkItemInterface, adding new methods to an interface is a BC break. However, since the interface has a 1:1 relationship with the LinkItem class, method additions are allowed in minor releases. The change record should mention this BC break. (See my addition to https://www.drupal.org/node/3330231 for comparison.)

  1. +++ b/core/modules/link/src/LinkItemInterface.php
    @@ -33,6 +33,14 @@
    +   * Creates a Link object from the field data.
    +   *
    +   * @return \Drupal\Core\Link
    +   *   Returns a Link object.
    +   */
    +  public function toLink();
    
    +++ b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
    @@ -168,6 +169,13 @@ public static function mainPropertyName() {
    +  public function toLink() {
    

    Since this is a new method we're adding, it should have a return typehint. Reference:

    https://www.drupal.org/docs/develop/standards/php/php-coding-standards#s...

  2. +++ b/core/modules/link/tests/src/Kernel/LinkItemTest.php
    @@ -89,6 +90,13 @@ public function testLinkItem() {
    +    // Test the toLink method.
    

    toLink() should have params in docs.

  3. +++ b/core/modules/link/tests/src/Kernel/LinkItemTest.php
    @@ -89,6 +90,13 @@ public function testLinkItem() {
    +    $this->assertInstanceOf(Link::class, $link, 'Link implements interface.');
    +    $this->assertEquals($url, $link->getUrl()->toString(), 'Link has expected url.');
    +    $this->assertEquals($title, $link->getText(), 'Link has expected title.');
    

    We can drop the assertion messages from these three assertions; core best practice has moved on to omitting them since this issue was first filed. :)

As with the other issue, we can also file a followup issue for the linked_entity_reference module to implement this method as well.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

scott_euser made their first commit to this issue’s fork.

scott_euser’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record, -Needs followup

Created a new change record here (since I don't have access to edit original): https://www.drupal.org/node/3458241

On the feedback in #50:

  1. Typehint added
  2. I'm not sure how to add params to the interface, it does not support any parameters? Or maybe I misunderstand
  3. Updated assertions to remove messages

scott_euser’s picture

Hide patches to avoid confusion with MR (and since this type of action tends to get ignored, anyone coming across this, please do not add a new patch, see this doc page for instructions).

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

Haven't reviewed yet but could issue summary be updated to the standard issue template please

Thank you!

scott_euser’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Updated issue summary

shalini_jha made their first commit to this issue’s fork.

shalini_jha’s picture

Status: Needs work » Needs review

I have checked this issue and issue summary. By calling the newly added toLink() method, I was able to get the link object as expected. I also verified the added test coverage and did not find any additional tags for this issue. I have rebased the MR since it was significantly behind, and the pipeline is now green. Moving this MR for review. Kindly review.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record updates

CR looks like it needs slight tweaking.

Versions seems off
Maybe a before of how users are retrieving this info currently

with an after of how this is easier.

shalini_jha’s picture

i am working for CR Update

shalini_jha’s picture

Status: Needs work » Needs review

Updated the CR according to the feedback based on the issue summary also. Moving this for NR.
let me know if anything else need to update.

nikolay shapovalov’s picture

MR looks good. But should we add test coverage new method at Drupal\Tests\link\Unit\LinkFormatterTest?

oily’s picture

RE: #63 I am starting on that. Used existing Unit test class for DRY reasons as so much setup for each test method. Have added use statement for Link class, Created a mock for it and set an expects() for the new toLink method.

nikolay shapovalov’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, RTBC.

quietone made their first commit to this issue’s fork.

quietone’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs work

I read the IS, comments, the MR and the change record.

I see this is tagged 'Needs change record updates'. That should be resolved before setting an issue to RTBC, thanks.

Continuing to triage, I changed the order of a 'use' statement in the MR. I re-arranged the CR so the most important part, the way things work with this change, is first. I then adding a remaining task to the issue summary. That is an update to the change records, to the tag can remain. I didn't find any unanswered questions. Oh, and I updated credit.

scott_euser’s picture

Issue summary: View changes
Status: Needs work » Needs review

Thanks!

  • Updated the Change Record to match the BC note from https://www.drupal.org/node/3330231 - I added in a strong text to separate it from the other strong texts to keep appearing as a separate point.
  • I removed that as a remaining task from the issue summary.
smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record updates

CR looks fine to me.

I did rebase the MR as it was 600+ commits back, after a few re-tries it's still green.

Believe all feedback has been addressed for this one.

quietone’s picture

Title: Getting a Link object from a "link" field type » Add \Drupal\link\LinkItemInterface::toLink method
xjm’s picture

Amending attribution.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs followup

Left some comments on the MR - I think we need to be defensive here for the edge cases like when getUrl throws an exception or the field-item is empty.

dcam made their first commit to this issue’s fork.

dcam’s picture

Status: Needs work » Needs review

I addressed the feedback.

oily’s picture

Ran the test-only test:

PHPUnit 11.5.39 by Sebastian Bergmann and contributors.
Runtime:       PHP 8.4.13
Configuration: /builds/issue/drupal-2752187/core/phpunit.xml.dist
E                                                                   1 / 1 (100%)
Time: 00:00.928, Memory: 8.00 MB
There was 1 error:
1) Drupal\Tests\link\Kernel\LinkItemTest::testLinkItem
Error: Call to undefined method Drupal\link\Plugin\Field\FieldType\LinkItem::toLink()
/builds/issue/drupal-2752187/core/modules/link/tests/src/Kernel/LinkItemTest.php:98
ERRORS!
Tests: 1, Assertions: 5, Errors: 1.
HTML output directory sites/simpletest/browser_output is not a writable directory.
PHPUnit 11.5.39 by Sebastian Bergmann and contributors.
Runtime:       PHP 8.4.13
Configuration: /builds/issue/drupal-2752187/core/phpunit.xml.dist
EFF                                                                 3 / 3 (100%)
Time: 00:00.027, Memory: 8.00 MB
There was 1 error:
1) Drupal\Tests\link\Unit\LinkItemTest::testToLink
Error: Call to undefined method MockObject_LinkItem_c54c6190::toLink()
/builds/issue/drupal-2752187/core/modules/link/tests/src/Unit/LinkItemTest.php:47
--
There were 2 failures:
1) Drupal\Tests\link\Unit\LinkItemTest::testToLinkWithEmptyField
Failed asserting that exception of type "Error" matches expected exception "InvalidArgumentException". Message was: "Call to undefined method MockObject_LinkItem_0a9ce685::toLink()" at
/builds/issue/drupal-2752187/core/modules/link/tests/src/Unit/LinkItemTest.php:64
.
2) Drupal\Tests\link\Unit\LinkItemTest::testToLinkWithBadUrl
Failed asserting that exception of type "Error" matches expected exception "InvalidArgumentException". Message was: "Call to undefined method MockObject_LinkItem_c54c6190::toLink()" at
/builds/issue/drupal-2752187/core/modules/link/tests/src/Unit/LinkItemTest.php:90
.
ERRORS!
Tests: 3, Assertions: 2, Errors: 1, Failures: 2.

I think this indicates the Unit test is working?

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs followup

Seems feedback has been addressed with the addition of

if ($this->isEmpty()) {
      throw new \InvalidArgumentException('The field item is empty and cannot be converted to a link.');
    }

Test coverage for new exception added in testBadUrl()

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

I was looking at whether we could use this in core... and I was thinking something along the lines of:

We should file a follow-up that will eventually allow is get rid of a preprocess hook in at the same time...

  • \Drupal\link\Hook\LinkThemeHooks::preprocessLinkFormatterLinkSeparate should trigger a deprecation is $variables['link'] is not set
  • \Drupal\link\Hook\LinkThemeHooks::theme link should be added to the variables
  • \Drupal\link\Plugin\Field\FieldFormatter\LinkSeparateFormatter::viewElements add link to the render array.

BUT!!!!!!

Then I noticed the following code in \Drupal\link\Plugin\Field\FieldFormatter\LinkSeparateFormatter::viewElements

      if (!empty($settings['trim_length'])) {
        $link_title = $link_title !== NULL ? Unicode::truncate($link_title, $settings['trim_length'], FALSE, TRUE) : NULL;
        $url_title = Unicode::truncate($url_title, $settings['trim_length'], FALSE, TRUE);
      }

Which makes this plan unworkable.

Given this and the fact that I can't work out where else to use this in core I wonder if adding this is actually necessary and whether other considers like trimming are always going to prevent it's usefulness?

Setting back to needs review to get an answer to that question.

smustgrave’s picture

Status: Needs review » Needs work

Moving to NW as the MR appears to need a manual rebase, least gitlab isn't doing it right.

Also for an answer to #77, maybe sub-maintainer?

dcam’s picture

Status: Needs work » Needs review

As the subsystem maintainer I don't have an answer to #77. I don't know that anyone had a plan to use this in Core. Reading back through the comments, it sounds like this was something that developers of downstream code wanted. No one offered use cases. But it seemed simple enough that I thought it might be a worthwhile addition.

I rebased the MR. I'm setting the status back to Needs Review.

dcam’s picture

Because this issue has opposing opinions from two framework managers (#37 and #77) I am tagging this for framework manager review.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

larowlan’s picture

from my point of view this is the companion to LinkItemInterface::getUrl() - I have a lot of custom code that uses getUrl and getTitle with a new Link so a utility to combine those is a useful addition in my opinion

Most of our projects have this in a trait EntityWithLinkFieldTrait that we add on a per bundle class case.

I think this is totally fine for @dcam as the subsystem maintainer to be the tie breaker.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new548 bytes

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.