ycloudyusa/yusaopeny_ymca360

There is no license information available for the latest version (2.1.0) of this package.

YUSA OpenY YMCA360 integration

Maintainers

Package info

github.com/YCloudYUSA/yusaopeny_ymca360

Type:drupal-module

pkg:composer/ycloudyusa/yusaopeny_ymca360

Statistics

Installs: 815

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 2

2.1.0 2026-05-06 12:07 UTC

README

πŸ‡ΊπŸ‡¦

This module is maintained by Ukrainian developers. Please consider supporting Ukraine in a fight for their freedom and the safety of Europe.

Pulls YMCA360 schedule occurrences (in-studio + live stream) into the YMCA Website Services Program Event Framework as session nodes, using a windowed, reconciliation-based syncer.

Table of contents

Highlights

Windowed sync Native API filters (start_at, end_at, scheduled_from) β€” fetches only the next N days, no client-side cap, no unbounded paging.
Source-of-truth reconciliation Mappings missing from the current extract are flagged as orphans and removed. Cap (max_deletes_per_run, default 500) protects against misconfigurations.
Empty-extract circuit breaker Skips orphan reconciliation until N consecutive empty extracts confirm emptiness β€” prevents a single API blip from wiping the schedule.
Trash-aware deletes Deletes are wrapped in trash.manager->executeInTrashContext('ignore', …) so reconciliation performs real deletes instead of soft-trashing.
Configurable canceled UX Canceled occurrences stay published with a CANCELED: prefix by default, mirroring the Y360 app behaviour.
Optional theming hooks Writes field_session_status and field_session_original_instructor when the session bundle exposes them, letting themes apply strikethrough or substitute-instructor labels.
Drush surface y360:status, y360:sync, y360:reset-hashes, y360:ping β€” operators no longer need php:eval.

Requirements

Requirement Version
Drupal core ^11
YMCA Website Services (yusaopeny) 11.x
drupal/trash optional, recommended

Note

When the trash module is present, the syncer detects trash.manager at runtime and bypasses soft-delete during reconciliation only β€” user-initiated deletes of other bundles continue to be captured by Trash.

Installation

composer require ycloudyusa/yusaopeny_ymca360
drush en yusaopeny_ymca360 yusaopeny_ymca360_instudio -y
drush updb -y

The submodule's install hook adds yusaopeny_ymca360_instudio.syncer to ymca_sync.settings.active_syncers and (when the trash module is enabled) removes syncer-owned bundles from trash.settings.enabled_entity_types.node so reconciliation deletes are real.

Update hooks (run on existing installs after upgrade)
Hook Purpose
yusaopeny_ymca360_instudio_update_10001 Backfills the new sync settings (window_days, page_size, max_deletes_per_run, canceled_title_prefix, canceled_publish_behavior) when missing.
yusaopeny_ymca360_instudio_update_10002 Removes the syncer-owned bundles (session, activity, class, program, program_subcategory) from trash.settings.enabled_entity_types.node if Trash is enabled and tracks nodes. Other bundles the site has opted into Trash for are preserved.

Configuration

Administration Β» YMCA Website Services Β» Integrations Β» YMCA360

  • Credentials & Schedules β€” API credentials and the schedule_id allow-list (Group Fitness, Pool, Racquetball, etc.).
  • Locations mapping β€” maps Y360 branches and studios onto site location nodes.

Administration Β» YMCA Website Services Β» Integrations Β» YMCA360 In-Studio

Automatic Sync
Setting Default Notes
enable_cron off When on, the submodule's hook_cron runs the syncer on every Drupal cron tick.
Sync Window
Setting Default Notes
window_days 14 How many days ahead of now to pull. Items before now are never extracted, so reconciliation removes them on the next run.
page_size 500 Items per API page. Larger pages = fewer requests but more memory per request.
max_deletes_per_run 500 Hard cap on deletions per sync cycle. Excess is logged and deferred to subsequent runs. Set to 0 to disable.
empty_extract_threshold 2 How many consecutive empty extracts must occur before reconciliation runs against an empty set. Lower it to 1 to disable the circuit breaker.
Canceled sessions
Setting Default Notes
canceled_title_prefix CANCELED: Prepended to the session title when the occurrence is canceled. Empty string = no prefix.
canceled_publish_behavior keep_published One of keep_published (canceled stays visible with prefix), follow_api (respects API published flag), always_unpublish (hides canceled).

Tip

After changing canceled_publish_behavior or canceled_title_prefix, run drush y360:reset-hashes so the next sync rewrites session nodes instead of skipping them via the hash no-op path.

How it works

flowchart LR
    API([YMCA360 API]) --> E[Extractor]
    E -->|items| T[Transformer]
    T -->|create / update / delete| L[Loader]
    L -->|session nodes| D[(Drupal)]
    L -->|y360_mapping| D
    E -.->|circuit breaker streak| KV[(keyvalue)]
Loading
  • Extractor builds the [now, now + window_days] window and calls Y360Client::getSchedulesWindowed() with the API's native filters. Pagination is API-driven. Tracks consecutive empty extracts in the yusaopeny_ymca360_syncer keyvalue collection and toggles DataWrapper::skipOrphanReconciliation until emptiness is confirmed.
  • Transformer classifies the working set:
    • status=deleted β†’ existing mapping queued for delete.
    • hash matches existing mapping β†’ no-op (unchanged item).
    • hash differs β†’ update.
    • no existing mapping β†’ create.
    • mappings whose y360id is missing from the current extract β†’ orphan, queued for delete (capped, may be skipped by the circuit breaker).
  • Loader creates or updates session nodes via applySessionFields() (title with optional cancel prefix, class/activity, time paragraph, location, room, instructor, description, ages, optional fields). Publish state derives from isPublishedSession(). Deletes are wrapped in trash.manager->executeInTrashContext('ignore', …).

The hash on each y360_mapping row is md5(serialize($apiItem)) so any field change in the upstream item triggers an update on the next sync.

Note

Under the hood the module uses YMCA Sync. When the syncer runs on Drupal cron, run cron often (e.g. every 15 minutes). Sites that prefer an explicit job runner can wire one with drush y360:sync.

Drush commands

Command Alias Purpose
drush y360:status y360-st Snapshot of mapping counts (total, in-window, past, future, blank-hash), key config values, last cron run.
drush y360:sync [--syncer=…] y360-sync Runs the syncer once. Defaults to yusaopeny_ymca360_instudio.syncer.
drush y360:reset-hashes y360-rh Clears hash on every mapping row so the next sync re-applies session fields.
drush y360:ping y360-ping Pings the YMCA360 API and prints a one-line OK / failure message.

Upgrading

Important

2.0.0 is a breaking release. Drupal 10 support is dropped (core_version_requirement: ^11). The legacy Y360Cleaner service, the yusaopeny_ymca360_cron hook, and the drush y360:cleanup command have been removed β€” reconciliation now handles past mappings as part of every sync run.

1.x β†’ 2.0.0 checklist
  • Site is on Drupal 11.
  • composer require ycloudyusa/yusaopeny_ymca360:^2.0
  • drush updb -y β€” applies update_10001 (settings backfill) and update_10002 (Trash bundle exclusion).
  • Verify drush y360:status shows the expected window and counts.
  • Run drush y360:sync once and check the watchdog channel yusaopeny_ymca360_syncer.
  • If you maintained a custom ExtractorBase subclass, update its constructor β€” a KeyValueFactoryInterface argument was added.

Development

The module ships with no version: field in composer.json. Composer resolves the package version from the latest git tag β€” keep it that way and tag releases off 2.x.

The pipeline is wired through three abstract base services (yusaopeny_ymca360.{extractor,transformer,loader}) that submodules extend via parent: references in their own *.services.yml. See modules/yusaopeny_ymca360_instudio/yusaopeny_ymca360_instudio.services.yml for the canonical example.

Logs land in the yusaopeny_ymca360_syncer channel; tail with:

drush ws --type=yusaopeny_ymca360_syncer --extended

Maintainers

Issues and pull requests live at https://github.com/YCloudYUSA/yusaopeny_ymca360.

Acknowledgements

The 2.0.0 release β€” windowed sync, reconciliation, Trash-aware deletes, configurable canceled UX, drush commands β€” was sponsored by YMCA of Northern Colorado and delivered by ITCare.