getgrav / grav-plugin-form

Grav Form Plugin
http://getgrav.org
MIT License
53 stars 79 forks source link

Slug based URLs, forms and multi-language #492

Open Karmalakas opened 3 years ago

Karmalakas commented 3 years ago

So I'm actually not sure how to explain the issue very clearly, but I'll try

Grav 1.7.3 + Form 4.3.0 plugin. All freshly installed

Basically, trying to implement one feature on website (building personal page from scratch) encountered an issue, which uncovered a bunch of problems with Gravs core and how in handles URLs, routes, redirects and pages.

First: the only way to get slug based URL, is page.route() (at least that's what I figured), but that's not always an option, because sometimes you want to add a link just from some saved pages field, which saves slug value without language code. That wouldn't be a problem in a normal page, because we can just pages.find([SLUG]).route or pages.find([FOLDER]).route, but there's a problem - pages === null in modules of modular pages.

OK, we can't get to page.route, then lets try redirects. Yes, even though they are one of the worst enemies of SEO, but still - we don't have much of a choice. When in system.yaml you have pages.redirect_default_route: true, when you get to folder based URL, this setting enabled, redirects to correct slug based URL. OK it seems we have a really dirty workaround, BUT...

After redirect, forms() will return null no matter how you try to get the form - by name or by route. And only cache clearing helps. But it helps only if you have a single language page and won't navigate to folder based URLs (so that redirect wouldn't happen). If you have at least two languages and want to switch it on page with a form, again there's no easy way to get slug URL for same page in different language and you have to use whatever URL you can get (most likely folder based URL). After clicking on new language redirect happens and form is gone.

Same applies if you want to implement AJAX form and have different slugs than folder name. You can't use common frontmatter.yaml for all languages, because you need to have separate actions for form in each language depending on slug, because if you use folder based action URL, after submit it redirects to correct slug based URL and whole payload is gone - form never gets submitted.

It's kind of a closed loop You need to have correct (slug based) URLs to be somewhat good to SEO. There's no way to get slug URLs, because you can't access page.route in some situations (especially for different language). So you just use folder based URLs with redirects, but you can't use them either not only because of SEO, but because of redirects after which you lose form payload or lose forms all together.

I was already liking Grav and even considering a donation, but no no matter how easy it is to extend, I'm starting to find it pretty much unusable if you want to have beautiful multilingual SEO friendly slugs and at least a contact form.

BTW, missing forms issue dates 4 years back


Here's my setup to reproduce the issue (copy from discourse, where I initially raised a question)

In Quark templates add two files:

fom.html.twig

{% if pageForm %}
    {% include "forms/form.html.twig" with {form: pageForm} %}
{% endif %}

contact-us.html.twig

{% extends 'partials/base.html.twig' %}

{% block content %}
    {% include "form.html.twig" with {pageForm: forms({"route": '/contact-us/form'})} %}
{% endblock %}

System.yaml

Uncomment redirect and navigate to folder based URL to reproduce the missing form issue

languages:
  supported:
    - lt
    - en
  default_lang: lt
  include_default_lang: false
  content_fallback:
    en: en
#pages:
#  redirect_default_route: true

Folder user/pages/03.contact-us

contact-us.en.md

---
title: 'Contact me'
slug: contact-me
cache_enable: false
---

##### Text

contact-us.lt.md

---
title: Susisiekime
slug: susisiekime
cache_enable: false
---

##### Tekstas

Folder user/pages/03.contact-us/form

form.en.md

---
title: Form
visible: false
form:
    name: contact-form
    action: /contact-me/form
debugger: false
cache_enable: false
---

form.lt.md

---
title: Form
visible: false
form:
    name: contact-form
    action: /susisiekime/form
debugger: false
cache_enable: false
---

frontmatter.yaml

form:
  name: contact-form
  action: '/contact-us/form'
  client_side_validation: false
  inline_errors: true
  keep_alive: true

  fields:
    -
      id: contact-name
      name: name
      label: CONTACT_FORM.NAME
      placeholder: CONTACT_FORM.NAME_PLACEHOLDER
      autocomplete: true
      type: text
      validate:
        required: true

  buttons:
    -
      type: submit
      value: CONTACT_FORM.BUTTON.SUBMIT
      classes: "btn-primary"
    -
      type: reset
      value: CONTACT_FORM.BUTTON.RESET
      classes: "btn-secondary"

  process:
    -
      message: CONTACT_FORM.THANK_YOU
    -
      reset: true

Hope this can be fixed before I need to publish my page :(

pamtbaau commented 3 years ago

@Karmalakas, Trying to replay your steps and it seems it contains a design flaw.

Note: I removed the cache_enable: false setting everywhere.

Karmalakas commented 3 years ago

I might have multiple different forms in the future (most likely I will), so I want contact form to stay under /contact-us folder.

forms({"route": '/contact-us/form'}) is just an example and, as mentioned, it works perfectly fine after cache is cleared or you go directly to slug URL without any redirect. I also tried:

All variations work perfectly fine when there's no redirect, but none of them work after redirect. So moving to /form isn't solving the core issue anyway.

Actions also have to be separate for each language and slug related, so there wouldn't be a redirect, because, as mentioned, after redirect, payload is gone. There was no 404 error, because Grav handles folder based URLs fine - it's just that redirect ruins everything.

Karmalakas commented 3 years ago

I'm thinking now, being able to get correct routes of any pages anywhere in the templates or PHP classes for any language would eliminate redirects (unless of course you'll link some place not by route). Eliminating redirects by linking to the correct URLs from the beginning, would solve all of the above described missing forms and missing submit payloads. Also language switcher could be updated to get correct route and wouldn't need all the concatenation with base_url, which also leads to redirect now.

pamtbaau commented 3 years ago

Updated previous post: Added alternative to including 'form.html.twig'

{% include "form.html.twig" with { pageForm: forms({"route": page.route ~ '/form' }) } %}
Karmalakas commented 3 years ago

Still doesn't work. No matter how you try to get a form, forms() can't find any after redirect

Karmalakas commented 3 years ago

Created a draft PR Not very familiar with Grav core, so it might be completely wrong, and it's not really working yet, because of the $this->parent, but I think someone might take a look at the approach and say something

Karmalakas commented 3 years ago

Now I'm thinking, if it's easier to fix, maybe just making forms() actually find forms after redirect would do for now, but getting different language slug routes is a must. Will see later, maybe I'll check how forms work :/

Karmalakas commented 3 years ago

Just encountered, if I have maintenance plugin and maintenance mode active, and try to get to a page with a form, I'm asked to login. After login, redirect happens and form isn't there. So it's not just multi-language issue, but any redirect (or maybe just from folder to slug - not sure how maintenance plugin redirects).

Anyway, I believe getting slug URL from any place for any language for any page is a must still

Karmalakas commented 3 years ago

Created a PR, that partially fixes missing form issue, but it still won't work if form is searched by name, because $this->forms is empty there.

Also slug URLs still needs to be implemented

rhukster commented 3 years ago

Can you please provide a sample user folder (zipped) so I don’t have to spend time setting this up manually?

Karmalakas commented 3 years ago

Sure - Grav_missing_forms_setup.zip

Just add this structure to fresh Grav install and

And there's really no way currently to get correct slug based URL for current page, but different language, hence redirects from folder based URLs

NicoHood commented 3 years ago

I am not 100% sure, but is this issue related? https://github.com/getgrav/grav-plugin-form/issues/484

Karmalakas commented 3 years ago

I am not 100% sure, but is this issue related?

484

I doubt.. You have both forms visible, but submission is messed up, and here - when forms are not visible at all

rhukster commented 3 years ago

Will take a look at this after the next release.