Jump to content

Automatically link page titles


MoritzLost
 Share

Recommended Posts

This is a textformatter module that will automatically replace titles of other pages on your site with links to those pages. For example, if you have a template glossary-term, and mention the exact title of one page using that template in a textfield, the title will be automatically linked to that page (if the textfield uses that formatter). This is good for SEO, and saves you some manual labour. You can configure which templates should get automatically linked, and of course the formatter is only active for the fields you add this formatter to. Note that if you need more manual control over when and where titles are automatically linked, you're probably better of using Autolink from a Glossary by @mr-fan.

Features

  • Allows you to limit the automatic links by template.
  • Only includes published & visible pages by default, with an option to include hidden pages.
  • Automatically excludes the current page, with an option to change that behaviour.
  • Allows you to configure the minimum title length for linked pages.
  • Doesn't overwrite existing links, and detects most edge cases (titles inside other tag's attributes, titles inside existing links et c.).
  • Supports multi-language sites. Titles will only be linked if a title in the current language is set.
  • Can add configurable attributes to all automatically created links. This includes the ability to use page fields as replacement patterns for attributes. For example, you can create CSS classes that include the name of the template of the linked page.
  • Extensive options and hooks to change the generated markup completely. Need <mark> elements with a title attribute based on a page field instead of a link? No problem. See the example project below.
  • Prefer oldest or newest page in the case of duplicate titles.
  • Queries the database directly for improved performance.
  • Has options to switch between case sensitive and case insensitive modes, and force case sensitive behaviour even for case insensitive database collations.
  • Allows you to overwrite the module configuration via the API to call the module with different settings for different requirements on the same site.

Download & Documentation

The module is now available in the modules directory: https://modules.processwire.com/modules/textformatter-page-title-links/
You can download & install it through the backend using the classname TextformatterPageTitleLinks.

To install it manually, download or clone the module from the Github repository into your site/modules folder and install through the backend.

The complete documentation can be found in the README in the repository. Make sure to check out the module configuration page after installing the module.

Requirements

  • PHP 7.1 or higher
  • ProcessWire 3+ (it will probably work in older versions, I haven't tested those though).

This is my first module, I hope it may become useful to some of you ?

If you find any errors or have some other suggestions or feedback, let me know!

  • Like 11
Link to comment
Share on other sites

  • 1 month later...

I just pushed version 2.1.0 to Github & the modules directory! Includes a minimum length settings for linkable titles, a preference to link the oldest or most recent page if multiple pages have the same title, and an important bugfix for older MySQL versions. Check out the full changelog above ?

Link to comment
Share on other sites

I just pushed a big update to the textformatter with version 3.0.0!
I'm not sure if anyone is actually using this module, but at least for my own projects it has been useful, and it's good training for MySQL intricacies, so I'm still updating it when I think of new stuff to add ?

With the updated version, it's now possible to overwrite any option from the module configuration when calling the module manually in your template code. That way, you can automatically link to pages of different templates in different contexts on the same site, or customize the behaviour of the textformatter any way you want! Also, there's now an option to toggle case insensitive behaviour, if needed, as well as an option to force case sensitive queries for case insensitive database collations. The changelog is now included in the repository itself, I also updated the readme with instructions on how to call the module manually. Make sure to check out the full changelog for version 3.0.0, as well as the readme section on manual usage.

Let me know if the module is or isn't working for you, and any suggestions you have on how to improve it!

  • Like 2
Link to comment
Share on other sites

I just published version 4.0.0 of this module, a large update that makes it possible to completely customize the markup created for detected page titles. For example, let's say you have a glossary and want glossary terms that appear anywhere on your site to display a popover with the term's definition. This update allows you to do that! Previously, the module always created an <a> tag with an href attribute, and always checked if the page was viewable before doing anything. This update comes with configuration options to change the HTML tag, disable the automatic href attribute and disable the visibility check. This allows you to use the module for a wider range of use-cases. If you need even more control, the methods the module uses to create markup are now hookable, so you can customize the output format even further! Here are some additional links to help you get started:

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...
  • 2 months later...

Ahoi @MoritzLost,

just installed your module/textformatter again in a new project. I knew it from previous installations but now... I can't get it working as expected. 

I set up the templates, added the textformatter to my textarea fields but there is no chance internal pages get any links.

What would be the best way to debug that?

I'm running a 3.0.165 on a PHP 7.4 and MySQL 5.6 environment.

I almost know that isn't a bug in the module itself but I really don't know how to trace down the problem.

Any ideas are welcome.

  • Like 1
Link to comment
Share on other sites

@wbmnfktr Hm, if you're using the latest version (4.1.0), there are a couple of settings you can check (Modules -> Configure -> TextformatterPageTitleLinks). Here's a list of all settings and what they do: https://github.com/MoritzLost/TextformatterPageTitleLinks#all-settings

A couple of possible reasons:

  • Have you selected the templates you want to be linkable? With no templates selected, the module does nothing.
  • In your template output, is output formatting turned on? With output formatting disabled, textformatters aren't applied.
  • Since you said "internal pages", are those visible (not hidden) and does the corresponding PHP template file exist? Templates without a template file are not viewable by default, so they won't get linked. In this case, you may need to check both Include hidden pages and Disable automatic visibility check.
  • There are other options that limit which pages may be linked, especially Minimum length for linkable titles and Use case insensitive mode, make sure none of those are the culprit.
  • Is your site multi-language? The module only links titles in the current language and doesn't fall back to the default language if the current language title is empty. So if you're checking in a non-default language and your pages have empty titles in that language, nothing will get linked.

If all those settings are correct, I'd start by checking which pages the module selects as candidates for automatic links. If you're using Tracy Debugger, you can check with barDump (otherwise, just use var_dump). Insert this in TextformatterPageTitleLinks.module#L101-L103:

// get all pages of the selected templates as an associative id => title array
$id_title_array = $this->getTitleIdArrayForCurrentLanguage($template_ids, $options);
bd($id_title_array);

This should dump the array of pages (keyed by page ID) to the Tracy Debugger bar. If you don't see anything, the textformatter isn't being executed at all. If you see an empty array or the pages you want to link to aren't there, the reason is likely one of the settings above.

If the pages you want to link to are included in the array but still don't get linked, it might just be the viewable check (see above). In this case, check what buildTitleMarkup returns in TextformatterPageTitleLinks.module#L147-L148.

Hope this helps! If it's still not working, please post the output of the debug statements and preferably a screenshot of your module settings and I'll take a look.

Link to comment
Share on other sites

So... even though it will embarass me to new heights... I will post the details to this issue and the details to resolve them.

I used and tried each and every measure @MoritzLost posted in his previous post BUT...

NO RESULTS at all or as Moritz would say The module isn't running at all.

His assumption was 100% correct. The module wasn't evoked, triggered or called at all. Lucky me... the jackpot.

All debug-measures resulted in zero results. So... I went back to the classic debugging once again (which I should have done before).

1. module setup defaults - fine!
2. field setup defaults - fine!
3. module setup details, each and every possible setup option tried - fine!
4. field setup details, each and every Textformatter enabled/disabled - whooops!!!

My body field (textarea, CKEditor) with Hanna, PrivacyWire and ALPT formatter didnt't play well together.
Re-Ordering each and every textformatter didn't help.
Removing all and re-assinging each of those, one after the other, worked out fine!

In my case ... in all setups and versions (based on the non-working setup) this helped:

  1. Deleting all Textformatters from field -> save field
  2. Adding ALPT -> save field
  3. Adding PrivacyWire -> save field
  4. Adding Hanna -> save field

Everything is working now as expected!

I don't know which textformatter might have been the issue or whatever details caused this BUT... if this happens again to me, I will probably reset, remove and add all textformatters to make it work again.

Thank you @MoritzLost - for the debugging details and the module again!

  • Like 1
Link to comment
Share on other sites

To be honest... I don't know as well. This kind of behaviour is totally new to me but on the other side... I almost never have to deal with almost any textformatter plugins/modules/extensions.

I guess it was a huge hickup or some kind of this as it was the first time ever I had to deal with this kind of problem in any of my setups.

Nontheless your module does a pretty good job - as soon as it runs in a setup.

  • Thanks 1
Link to comment
Share on other sites

  • 3 weeks later...

Hi,

Thanks for your module. It works really, maybe too much! ? I'm wondering if there a way I can limit to the first occurrence of a link in a page by a hook or something. I like the automatic behavior of the module, however I have pages where I repeat the same word each 2-3 sentences, rendering the paragraph looks as a big link to the same page.

Thanks

Mel

Link to comment
Share on other sites

5 hours ago, mel47 said:

Thanks for your module. It works really, maybe too much! ? I'm wondering if there a way I can limit to the first occurrence of a link in a page by a hook or something. I like the automatic behavior of the module, however I have pages where I repeat the same word each 2-3 sentences, rendering the paragraph looks as a big link to the same page.

Maybe this module would be a better fit then? 

 

Link to comment
Share on other sites

6 hours ago, mel47 said:

Thanks for your module. It works really, maybe too much! ? I'm wondering if there a way I can limit to the first occurrence of a link in a page by a hook or something. I like the automatic behavior of the module, however I have pages where I repeat the same word each 2-3 sentences, rendering the paragraph looks as a big link to the same page.

@mel47 Hi Mel, glad the module is working well for you! You can change the way links are created or prevent them entirely using the hook TextformatterPageTitleLinks::buildTitleMarkup (see the link for the documentation). This method is called for every title found in a text field and returns the HTML to replace the link. You can overwrite this to just return the title in certain conditions, which means no link will be created. Here's a hook that will keep track of which titles have already been linked and prevent more than one link per occurance of each page title:

// limit automatic links to one per individual title, even if the title appears multiple times on the page
wire()->addHookAfter('TextformatterPageTitleLinks::buildTitleMarkup', function (HookEvent $e) {
    $title = $e->arguments(0);
    $page = $e->arguments(1);
    $options = $e->arguments(2);

    // keep track of all the titles that have already been linked
    static $alreadyLinkedTitles = [];

    if (in_array($title, $alreadyLinkedTitles)) {
        // if the title has already been linked, overwrite the HTML markup with the plain title
        $e->return = $title;
    } else {
        // otherwise, just add the title to the array of linked titles
        $alreadyLinkedTitles[] = $title;
    }
});

A couple of caveats:

  1. The static array will not distinguish between fields, so this will limit the automatic links to one link per title on the whole page, not one link per title within one field (though it sounds like this is what you want).
  2. If you access the same field multiple times in your template, it will only contain links the first time.

Another solution, if the word you're repeating multiple times is very short, you can just use the minimum length setting to prevent it getting linked, or use the hook above to prevent automatic links for a few specific pages.

I hope this works for you! If you need even more fine control, it might be simpler to create the links manually or use another module as suggested by @bernhard.

  • Like 2
Link to comment
Share on other sites

  • 3 weeks later...

Hi @MoritzLost

Thanks for making the module. It's really handy for sites that have majorly a lot of pages. 

I'm working on a game site where there are heroes and their special abilities, items, etc. . Was totally delighted that it was working on my test environment but I noticed that (sorry if it feels snobbish but itemizing helps me think lol)

  1.  hyperlinking only works on the Body textarea
  2.  it only works on one page template so it seems 

I have two templates - hero and hero-ability. They're both in the module settings. 

I've also counter checked that my textarea fields have the same settings as the Body textarea.

Did I do something wrong? Or did I misunderstand something? Thanks. 

screenshot-d2g-2020_12.22-23_26_26.thumb.png.59bccb50585a6579e28622a8339c1469.pngscreenshot-d2g-2020_12.22-23_28_50.thumb.png.c61da2491d25e4c923c8e5ed5c433203.png

1770033707_screenshot-d2g-2020_12.22-23_28_50(1).thumb.png.a577895c155f96dde17bf43310b4403b.png

1335448505_download(2).thumb.png.343aed1a4f9f9741ed95939fa416bd30.png

  • Like 1
Link to comment
Share on other sites

Hi @Pip, thanks for reaching out, I think I know what the problem is. The module should work with any number of templates and on any number of fields. However, before creating a link for a given title, the module checks if the page the title belongs to is actually viewable. I made this the default because for a "normal" use case it doesn't make sense to create a link to a page the current user can't actually view. Based on your screenshots it looks like you display all hero abilities on the page for that hero, so I'm guessing the hero abilities don't have their own sub-pages in the frontend? If there's no hero-ability.php template, no hero-ability pages will be viewable, so the module will not create any links for those.

In version 4.0.0 of the module I added a checkbox to disable the viewable checks for use cases like this one. Your screenshot looks like your site has an older version installed, so make sure to update to the latest version if you don't see the checkbox. After the update the option should appear in the new configuration fieldset Markup and output settings.

By the way if my assumption is correct, you may want to use the hook TextformatterPageTitleLinks::buildTitleMarkup to modify the link for hero-ability pages to point to that ability on the hero page instead (using anchor links). See my answer here for details.

If that doesn't solve the problem: I've written a bit about how to check what the module is doing in my answer here, use that to determine whether the module (a) is not finding the desired titles or (b) is finding the titles but not creating links for them. This can help you find out what's going wrong. Let me know if you need more help!

  • Like 2
Link to comment
Share on other sites

On 12/23/2020 at 1:41 AM, MoritzLost said:

Hi @Pip, thanks for reaching out, I think I know what the problem is. The module should work with any number of templates and on any number of fields. However, before creating a link for a given title, the module checks if the page the title belongs to is actually viewable. I made this the default because for a "normal" use case it doesn't make sense to create a link to a page the current user can't actually view. Based on your screenshots it looks like you display all hero abilities on the page for that hero, so I'm guessing the hero abilities don't have their own sub-pages in the frontend? If there's no hero-ability.php template, no hero-ability pages will be viewable, so the module will not create any links for those.

In version 4.0.0 of the module I added a checkbox to disable the viewable checks for use cases like this one. Your screenshot looks like your site has an older version installed, so make sure to update to the latest version if you don't see the checkbox. After the update the option should appear in the new configuration fieldset Markup and output settings.

By the way if my assumption is correct, you may want to use the hook TextformatterPageTitleLinks::buildTitleMarkup to modify the link for hero-ability pages to point to that ability on the hero page instead (using anchor links). See my answer here for details.

If that doesn't solve the problem: I've written a bit about how to check what the module is doing in my answer here, use that to determine whether the module (a) is not finding the desired titles or (b) is finding the titles but not creating links for them. This can help you find out what's going wrong. Let me know if you need more help!

Hi @MoritzLost Tried your recommendation. You're right the hero-ability.php was non existing. Recreated it and is now linking automatically! Thanks so much! Happy Holidays!

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...