Problem/Motivation

All sites using hourly-bookable content types — setting availability as "Available"
silently writes "Not available" to the database instead.

createHourlyEvent() accepts the user's chosen state ('available' or 'unavailable') as
the $new_state parameter, but never stores that parameter in the $d working array. All
subsequent logic in the method reads from $d, so when the state check
if ($d['new_state'] == 'available') is evaluated, the key does not exist and the condition
is always false. The method therefore unconditionally writes bee_hourly_not_available to
the database for every Update Availability form submission on an hourly-bookable node,
regardless of whether the user selected "Available" or "Unavailable".

The equivalent method createDailyEvent() does not have this bug — it correctly stores
$d['new_state'] = $new_state; at the top of the method.

Steps to reproduce

  1. Install BEE and configure a hourly bookable content type (e.g. "not available by default" or "generally available").
  2. Create a node of that type.
  3. Go to the node's Update Availability tab.
  4. Set the State to "Available", choose a date/time range, and submit.
  5. Check the node's calendar or query bat_event__event_state_reference in the database.

Expected: The selected time range is recorded with state bee_hourly_available and displays green on the calendar.

Actual: The selected time range is recorded with state bee_hourly_not_available and displays red/N/A on the calendar, regardless of what the user chose. Selecting "Unavailable" produces the same result.

createHourlyEvent() uses a $d array to pass data through the method:

private function createHourlyEvent(Node $node, \DateTime $start_date, \DateTime $end_date, $type_id, $new_state) {

  $d = [];
  $d['node'] = $node;
  $d['type_id'] = $type_id;
  $d['start_date'] = $start_date;
  // $new_state parameter is NEVER stored in $d
  $d['temp_end_date'] = clone($end_date);
  ...

  if ($d['new_state'] == 'available') {          // $d['new_state'] is undefined → null
    $d['state'] = bat_event_load_state_by_machine_name('bee_hourly_available');
  }
  else {
    $d['state'] = bat_event_load_state_by_machine_name('bee_hourly_not_available');
    // ↑ always reached, because null != 'available'
  }

The $new_state parameter arrives with the correct value ('available' or 'unavailable' from the form select element) but is never assigned to $d. When $d['new_state'] is evaluated, PHP treats an undefined array key as null. null == 'available' is false, so execution always falls to the else branch and always writes bee_hourly_not_available.

Comparison: createDailyEvent() is already correct

createDailyEvent() stores the parameter immediately:

private function createDailyEvent(Node $node, \DateTime $start_date, \DateTime $end_date, $type_id, $new_state) {

  $d = [];
  $d['type_id'] = $type_id;
  $d['start_date'] = $start_date;
  $d['node'] = $node;
  $d['new_state'] = $new_state;   // ← correctly stored
  ...

  if ($d['new_state'] == 'available') {   // ← works correctly

createHourlyEvent() is missing this single assignment.

Impact

  • All hourly-bookable nodes on all BEE sites are affected. Any user action to mark a time range as "Available" via the Update Availability form silently writes "Not available" instead.
  • There is no visible error — the form submits successfully, but the stored state is always wrong.
  • "Not available by default" hourly nodes cannot be opened for bookings via the availability form; administrators have no working way to mark time windows as available through the UI.
  • "Generally available" hourly nodes can be marked unavailable correctly (since both selections produce not_available), but attempting to re-open them via "Available" fails silently.
  • The bug is not visible in the form itself and can easily go undetected, particularly on sites where admins assume the form is functioning as labeled.

Proposed resolution

Add $d['new_state'] = $new_state; alongside the other $d assignments at the start of createHourlyEvent(), matching the pattern in createDailyEvent():

Before:

$d = [];
$d['node'] = $node;
$d['type_id'] = $type_id;
$d['start_date'] = $start_date;
$d['temp_end_date'] = clone($end_date);

After:

$d = [];
$d['node'] = $node;
$d['type_id'] = $type_id;
$d['start_date'] = $start_date;
$d['new_state'] = $new_state;
$d['temp_end_date'] = clone($end_date);

No other changes are required. The state-checking and event-writing logic is correct once $d['new_state'] is populated.

Remaining tasks

I have tested on my own system, additional testing and verification would be welcome prior to merging.

User interface changes

none

API changes

none

Data model changes

none

Sponsorship

none

Comments

owens-d created an issue. See original summary.

owens-d’s picture

Priority: Major » Critical
afagioli’s picture

Issue summary: View changes

improve readability

afagioli’s picture

Hi!

Instead of pasting code directly in the issue queue, please follow Drupal best practices:

* Create an issue fork and push your changes there, then open a Merge Request, or
* Create a patch using git diff and attach it to this issue

Thanks

afagioli’s picture

Status: Active » Needs work

  • afagioli committed ee6dda54 on 11.1.x
    Issue #3576452: Refactor module uninstallation logic and clean up route...
afagioli’s picture

Status: Needs work » Needs review