SuperGeekery: A blog probably of interest only to nerds by John F Morton.

A blog prob­a­bly of inter­est only to nerds by John F Mor­ton.

Entry Editor Links, a new Craft CMS plugin

Entry editor link example
Example of the Entry Editor Links plugin. For authorized users, each entry title includes a link to edit the post.

I have pub­lished a new plu­g­in on the Craft CMS plu­g­in store: Entry Edi­tor Links. This plu­g­in is designed to help devel­op­ers quick­ly cre­ate links to an entry’s edit page in the con­trol pan­el for autho­rized users on the front end of a Craft site.

Use Twig instead

If you’re not sta­t­i­cal­ly caching your site, you can achieve a link in your Twig tem­plates and avoid adding anoth­er plu­g­in. One Darn­ley Road­’s starter tem­plate has a con­cise exam­ple of how to cre­ate an edi­tor link in their GitHub repo. I used their tech­nique on my site ini­tial­ly.

Here’s the snip­pet for quick ref­er­ence:

  {# Element edit button
     requires a currentUser, who can access the CP, and the request should not be an iframe live preview #}
  {% if currentUser
        and currentUser.can('accessCp')
        and not (craft.app.request.getIsPreview() and craft.app.request.headers.get('sec-fetch-dest') == 'iframe') %}
    {% html at endBody %}
      {% set element = craft.app.getUrlManager().getMatchedElement() %}
      {% if element and element.canSave(currentUser) %}
        <a href="{{ element.getCpEditUrl() }}"
           target="_blank"
           class="fixed left-0 bg-black text-white bottom-0 px-5 py-2 mb-6 ml-6 font-mono uppercase">
          Edit this page
        </a>
      {% endif %}
    {% endhtml %}
  {% endif %}

As you can see above, the snip­pet will only ren­der the edit link when the logged-in user has per­mis­sion to edit the post and is view­ing the page on the site’s front end.

Static caching is great.

This Twig snip­pet worked for me until I imple­ment­ed FastC­GI Cache, as out­lined in this post by nystudio107. How dos it work? Sta­t­ic page caching ren­ders each page only once, and then, on sub­se­quent vis­its, the pre­vi­ous­ly ren­dered HTML is served instead.

This sta­t­ic cache helps a site per­form well, even an under­pow­ered serv­er, because the serv­er isn’t eval­u­at­ing any­thing most of the time. It just pro­vides a sim­ple HTML doc­u­ment to the user. There is no page log­ic to both­er with.

Static caching is great, but not in all cases.

Using the page you’re read­ing now as an exam­ple, the prob­lem is that if I vis­it this page before you do, the link to edit this entry will be part of the sta­t­i­cal­ly cached page. I’ll see the link to edit this entry, and so will you. Craft CMS is secure, so if you clicked the edit this entry” link, you would not gain access to the site’s back end. You’d be stuck at the login page.

Even so, the edit link should be pre­sent­ed only to me. Ren­der­ing that link to every­one would look like an error (because it would be an error!) and expose infor­ma­tion about the site struc­ture that I don’t want to be exposed.

JavaScript to the rescue

JavaScript allows a page to be altered after it’s ren­dered, and the Entry Edi­tor Links plu­g­in pro­vides a helper method and a sim­ple end­point to query to help make this a easy process.

There are three steps to imple­ment this on your site. (These instruc­tions are also in the doc­u­men­ta­tion for the Entry Edi­tor Links plu­g­in.

  1. Down­load and install the Entry Edi­tor Links plu­g­in. It’s free. :beer:
  2. Add a data attribute, data-edit-link, to the ele­ment that con­tains your entry’s head­line and set the val­ue to the ID of the entry in Craft. The plu­g­in pro­vides a helper method, isFrontEndPageView(), to ensure you’re ren­der­ing the data attribute only to the front end of the page site and not in a pre­view win­dow of the site. This means the full Twig looks like this: {% if isFrontEndPageView() %}data-edit-link="{{ entry.id }}"{% endif %}.
  3. Final­ly, you need some JavaScript that will look through the page for the pres­ence of this data attribute. If you find one or more of them, loop through them, hit­ting the plug­in’s API end­point. This will deter­mine if the user is logged in and if they can edit an entry. If they do, you’ll receive the URL to edit the page in the con­trol pan­el. In the exam­ple JavaScript I pro­vide in the doc­u­men­ta­tion, you’ll cre­ate a new a ele­ment and insert it into the DOM right after the head­line.

Customize the JavaScript

The JavaScript I include in the doc­u­men­ta­tion is only an exam­ple. You may want the edit link to live else­where. You may want it to have dif­fer­ent link text. Change it how­ev­er you want. The exam­ple JS is to get you start­ed.

If you have prob­lems or sug­ges­tions, sub­mit an issue on GitHub. Cheers.

I have pub­lished a new plu­g­in on the Craft CMS plu­g­in store: Entry Edi­tor Links. This plu­g­in is designed to help devel­op­ers quick­ly cre­ate links to an entry’s edit page in the con­trol pan­el for autho­rized users on the front end of a Craft site.

Use Twig instead #

If you’re not sta­t­i­cal­ly caching your site, you can achieve a link in your Twig tem­plates and avoid adding anoth­er plu­g­in. One Darn­ley Road’s starter tem­plate has a con­cise exam­ple of how to cre­ate an edi­tor link in their GitHub repo. I used their tech­nique on my site ini­tial­ly. 

Here’s the snip­pet for quick ref­er­ence:

  {# Element edit button
     requires a currentUser, who can access the CP, and the request should not be an iframe live preview #}
  {% if currentUser
        and currentUser.can('accessCp')
        and not (craft.app.request.getIsPreview() and craft.app.request.headers.get('sec-fetch-dest') == 'iframe') %}
    {% html at endBody %}
      {% set element = craft.app.getUrlManager().getMatchedElement() %}
      {% if element and element.canSave(currentUser) %}
        <a href="{{ element.getCpEditUrl() }}"
           target="_blank"
           class="fixed left-0 bg-black text-white bottom-0 px-5 py-2 mb-6 ml-6 font-mono uppercase">
          Edit this page
        </a>
      {% endif %}
    {% endhtml %}
  {% endif %}

As you can see above, the snip­pet will only ren­der the edit link when the logged-in user has per­mis­sion to edit the post and is view­ing the page on the site’s front end. 

Sta­t­ic caching is great. #

This Twig snip­pet worked for me until I imple­ment­ed FastC­GI Cache, as out­lined in this post by nys­tu­dio107. How dos it work? Sta­t­ic page caching ren­ders each page only once, and then, on sub­se­quent vis­its, the pre­vi­ous­ly ren­dered HTML is served instead. 

This sta­t­ic cache helps a site per­form well, even an under­pow­ered serv­er, because the serv­er isn’t eval­u­at­ing any­thing most of the time. It just pro­vides a sim­ple HTML doc­u­ment to the user. There is no page log­ic to both­er with.

Sta­t­ic caching is great, but not in all cas­es. #

Using the page you’re read­ing now as an exam­ple, the prob­lem is that if I vis­it this page before you do, the link to edit this entry will be part of the sta­t­i­cal­ly cached page. I’ll see the link to edit this entry, and so will you. Craft CMS is secure, so if you clicked the edit this entry” link, you would not gain access to the site’s back end. You’d be stuck at the login page. 

Even so, the edit link should be pre­sent­ed only to me. Ren­der­ing that link to every­one would look like an error (because it would be an error!) and expose infor­ma­tion about the site struc­ture that I don’t want to be exposed.

JavaScript to the res­cue #

JavaScript allows a page to be altered after it’s ren­dered, and the Entry Edi­tor Links plu­g­in pro­vides a helper method and a sim­ple end­point to query to help make this a easy process. 

There are three steps to imple­ment this on your site. (These instruc­tions are also in the doc­u­men­ta­tion for the Entry Edi­tor Links plu­g­in.

  1. Down­load and install the Entry Edi­tor Links plu­g­in. It’s free. :beer:
  2. Add a data attribute, data-edit-link, to the ele­ment that con­tains your entry’s head­line and set the val­ue to the ID of the entry in Craft. The plu­g­in pro­vides a helper method, isFrontEndPageView(), to ensure you’re ren­der­ing the data attribute only to the front end of the page site and not in a pre­view win­dow of the site. This means the full Twig looks like this: {% if isFrontEndPageView() %}data-edit-link="{{ entry.id }}"{% endif %}.
  3. Final­ly, you need some JavaScript that will look through the page for the pres­ence of this data attribute. If you find one or more of them, loop through them, hit­ting the plugin’s API end­point. This will deter­mine if the user is logged in and if they can edit an entry. If they do, you’ll receive the URL to edit the page in the con­trol pan­el. In the exam­ple JavaScript I pro­vide in the doc­u­men­ta­tion, you’ll cre­ate a new a ele­ment and insert it into the DOM right after the head­line. 

Cus­tomize the JavaScript #

The JavaScript I include in the doc­u­men­ta­tion is only an exam­ple. You may want the edit link to live else­where. You may want it to have dif­fer­ent link text. Change it how­ev­er you want. The exam­ple JS is to get you start­ed. 

If you have prob­lems or sug­ges­tions, sub­mit an issue on GitHub. Cheers.