Link to panel page from front end

I want to have an edit button on the front end, so logged in users can click it and go right to editing the page in the panel.

Is this possible in Kirby 3?

You can use $page->panelUrl() like that:

<?php if(kirby()->user()): ?>
    <a href="<?php echo $page->panelUrl(); ?>">Edit Page</a>
<?php endif; ?>
2 Likes

perfect, thanks!

@_gareth_j:

A solution with gear wheels you can find at HowTo: Working with contextual links to the panel.

The hardcopies at the beginning are from a very old Kirby 2 version, but you see “the four gear wheels in purple” in the first hardcopy, which are the “edit buttons” on the front end for a logged in user.
The new code runs on Kirby 3.

[Added:]
I updated the code in my linked solution.
And you should change the colour of the gear wheels…

I think it’s important to check if the user has panel access.

I would change:
<?php if(kirby()->user()): ?>
to
<?php if($user = kirby()->user() and $user->role()->permissions()->for('access', 'panel')): ?>

Otherwise the link must not work.

That’s only relevant if there are users without Panel access, so not necessarily needed.

1 Like

I agree, but a general solution must not, in my view, exclude such cases.

And the addition is simple and effective to produce without problems.

I wouldn’t use more code than is necessary for my use case and a user without Panel access cannot log in, anyway.

Then don’t forget to check if the user has read access to each page as well before rendering your button.

1 Like

@texnixe:

Thank you for your great hint to add a check if the user has read access to the panel page.
Now I have added it in my linked solution HowTo: Working with contextual links to the panel

Interesting discussion.

Is there a global way to only show the site to logged in users?

That’s a different thing from what @anon77445132 is trying to discuss here.

But yes, you can check at the top of your header (that is used anywhere) if a user is logged in or not and redirect them to the login page if not. If you only have Panel users, you do not need additional checks per user role or permission. But of course your checks always have to be in line with what you want to achieve.

1 Like

@_gareth_j:
look at Protecting entire pages, if you want to follow @texnixe’s answer.

You can outsource the link code into a field method. Useful if you need such a link in multiple locations:

  1. Create a field method in a plugin:
<?php 
Kirby::plugin('my/methods', [
    'fieldMethods' => [
      'editLink' => function($field) {
          $page = $field->parent();
          $title = $page->title();
          if (kirby()->user()) {
            $title .= ' ' . Html::a($page->panelUrl(), 'Edit page', ['class' => 'editlink']);
          }
          return $title;
      }
    ]
]);
  1. Then in your template where needed
<h1><?= $page->title()->editLink() ?></h1>

Adapt as needed to show only an edit icon (with accessible text) or add more checks (e.g. for user permissions), use another field etc…

1 Like

@_gareth_j Another way to protect your content globally would be via a catch-all route. This would then also cover content that is not template-based.

I got the very same question, I’d like to link panel pages for logged-in users. The answer fits perfectly. Thank you so far.
But when using the function $page->panelUrl(), my IDE complains that this function is marked “Internal”. And indeed, this is in the source code:

    /**
     * Returns the url to the editing view
     * in the panel
     *
     * @internal
     * @param bool $relative
     * @return string
     */
    public function panelUrl(bool $relative = false): string
    {
        return $this->parent()->panelUrl($relative) . '/' . $this->panelPath();
    }

I wonder whether it is safe to use this function anyway for a production environment.

Yes, you can safely use it. The @internal marker is used for filtering between most used and all items in the documentation.