verbb / events

Craft CMS Plugin for events management and ticketing.
Other
22 stars 13 forks source link

Bug: infinite loop when adding event to cart if event has supertable data #21

Closed KatieMFritz closed 4 years ago

KatieMFritz commented 5 years ago

Description

I can create events and purchase tickets using the default templates from the craft commerce 3 alpha templates folder and the Events plugin suggested templates. However, if I save supertable data in an event, then adding a ticket for that event to my cart causes an infinite loop and a 504 gateway time-out error.

Here's an example of the code that's repeated over and over in 5 web.log files after I do this (my supertable field is called "continuingEducation":

2019-08-09 08:02:43 [-][1][la82j0df3dc7limrn3uuo4orir][profile begin][yii\db\Command::query] SELECT "elements"."id", "elements"."fieldLayoutId", "elements"."uid", "elements"."enabled", "elements"."archived", "elements"."dateCreated", "elements"."dateUpdated", "elements_sites"."slug", "elements_sites"."siteId", "elements_sites"."uri", "elements_sites"."enabled" AS "enabledForSite", "supertableblocks"."fieldId", "supertableblocks"."ownerId", "supertableblocks"."typeId", "supertableblocks"."sortOrder", "content"."id" AS "contentId", "content"."field_headline", "content"."field_details"
FROM (SELECT "elements"."id" AS "elementsId", "elements_sites"."id" AS "elementsSitesId", "content"."id" AS "contentId"
FROM "elements" "elements"
INNER JOIN "supertableblocks" "supertableblocks" ON "supertableblocks"."id" = "elements"."id"
INNER JOIN "elements_sites" "elements_sites" ON "elements_sites"."elementId" = "elements"."id"
INNER JOIN "stc_continuingeducation" "content" ON ("content"."elementId" = "elements"."id") AND ("content"."siteId" = "elements_sites"."siteId")
WHERE ("supertableblocks"."fieldId"=158) AND ("supertableblocks"."ownerId"=835) AND ("elements_sites"."siteId"=1) AND ("elements"."archived"=FALSE) AND ("elements"."enabled"=TRUE) AND ("elements"."dateDeleted" IS NULL) AND ("elements_sites"."enabled"=TRUE) AND ("elements"."draftId" IS NULL) AND ("elements"."revisionId" IS NULL)
ORDER BY "supertableblocks"."sortOrder"
LIMIT 1) "subquery"
INNER JOIN "supertableblocks" "supertableblocks" ON "supertableblocks"."id" = "subquery"."elementsId"
INNER JOIN "elements" "elements" ON "elements"."id" = "subquery"."elementsId"
INNER JOIN "elements_sites" "elements_sites" ON "elements_sites"."id" = "subquery"."elementsSitesId"
INNER JOIN "stc_continuingeducation" "content" ON "content"."id" = "subquery"."contentId"
ORDER BY "supertableblocks"."sortOrder"

I've tested a few times and can reliable reproduce the issue with different supertable fields. All other fields seem to work fine.

Steps to reproduce

  1. Create an event type with date in the future and tickets enabled.
  2. Add a supertable field to the event type.
  3. Add data to the supertable field and save.
  4. Using the default templates provided in commerce 3 alpha and the events plugin documentation, click "add to cart" on front end for the event.

Additional info

KatieMFritz commented 5 years ago

I just added a SuperTable field to a product (the clothing product type that comes with Craft Commerce) and tested it. No issues there.

Here is my code for _event.html:

{% extends 'shop/_layouts/main' %}

{% block main %}
<div class="mt-8">
  <a href="{{ url('shop/events') }}">&larr; All Events</a>
</div>

<div class="flex -mx-6 mt-8 product-details">
  <div class="w-1/2 mx-6 p-8">

  </div>
  <div class="w-1/2 mx-6 p-8">
    <h1>{{ event.title }}</h1>

    {% if event.isAvailable %}
    <form method="POST">
      <input type="hidden" name="action" value="commerce/cart/update-cart">
      {{ redirectInput('shop/cart') }}
      {{ csrfInput() }}

      <input type="number" name="qty" value="1">

      <div class="field">
        <select name="purchasableId">
          {% for ticket in event.tickets %}
          <option value="{{ ticket.purchasableId }}" {% if not ticket.isAvailable %}disabled{% endif %}>
            {{ ticket.name }} - {{ ticket.price | commerceCurrency(cart.currency) }}
          </option>
          {% endfor %}
        </select>
      </div>
      <div class="buttons">
        <input type="submit" value="Add to cart" class="button"/>
      </div>
    </form>
    {% else %}
    <strong>Sold out</strong>
    {% endif %}
  </div>
</div>
{% endblock %}
KatieMFritz commented 5 years ago

Hi @engram-design, any updates on this?

engram-design commented 4 years ago

@KatieMFritz Sorry for the delay in getting back to you. I've just tried a few combination of Super Table fields and can't seem to immediately replicate the issue. Can you share the Super Table field you have attached to your events? Hopefully with that, I can replicate this.

It does sounds like some sort of serialisation loop though. When you add something to your cart, the line item stores a current copy of the purchasable "thing" alongside the line item, which can also include custom fields.

I've made some improvements in 1.1.7 that might be worth trying out as well.

KatieMFritz commented 4 years ago

Sorry, haven't been able to test again lately! We've installed the latest version and I'll report back if we have problems.

engram-design commented 4 years ago

Closing until further notice. Have also tested with 1.2.0