WP Manifestindependent plugin directory
manifest / events / intramurals

LeagueFlow

★ 1stars
3release downloads
v1.0.2latest · 7d ago

Install

Download leagueflow-1.0.2.zip From the v1.0.2 release on GitHub, Oct 7, 2026

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/amirrad98/intramurals/releases/download/v1.0.2/leagueflow-1.0.2.zip
Updates itself. It ships its own updater, so new versions appear under Dashboard → Updates.

LeagueFlow is a classic WordPress plugin for running multi-sport leagues with teams, players, fixtures, derived standings, and knockout brackets. It uses WordPress-native admin screens, metaboxes, taxonomies, dynamic Gutenberg blocks, and shortcodes.

GitHub releases and WordPress updates

Requires WordPress 6.5+ and PHP 8.1+. Download the attached leagueflow-X.Y.Z.zip from GitHub Releases. Install it through Plugins → Add New → Upload Plugin. The package contains the stable leagueflow/ directory. Use this asset rather than GitHub's generated source archives, which contain development tooling and have a different directory name.

Sites running 1.0.1 or earlier must upload the updater-enabled 1.0.2 release once and replace the existing installation. While LeagueFlow is active, later stable releases appear through WordPress's normal plugin update checks. Dashboard → Updates → Check again requests a check; successful release metadata is cached for five minutes. A site does not need a GitHub token. Administrators choose when to install updates or enable WordPress's automatic updates. Updates replace plugin files; they do not uninstall LeagueFlow, migrate websites or replace league data.

The updater uses the native Update URI hooks and the public release asset releases/latest/download/latest.json. It accepts stable versions only and verifies the downloaded ZIP against the specific version's manifest SHA-256. Failed checks are cached for one minute; an unavailable or invalid feed supplies no update. Keep the repository public and keep published assets immutable. Inactive plugins do not load their update hooks; activate LeagueFlow before checking for GitHub updates.

The approach follows the deterministic packaging and verified-download design in Zoer Connect, with assets served directly from LeagueFlow's existing repository. No separate feed repository or deploy key is needed. HTTPS and checksums verify transport/integrity; they are not independent publisher signatures.

Build and release

php tests/github-updater.php
python3 -m unittest discover -s tests -p 'test_*.py' -v
python3 scripts/build.py

Outputs in ignored dist/ are a deterministic plugin ZIP, .zip.sha256 checksum and latest.json manifest. Packaging includes the plugin entry point, uninstall file, existing plugin documentation and runtime directories. It excludes Git, workflows, audit documents, scripts and tests; unsafe runtime entries fail.

For a new stable release:

  1. Update the plugin header and LEAGUEFLOW_VERSION to the same new X.Y.Z.
  2. Add releases/X.Y.Z.md release notes, run the local checks, commit and push.
  3. Wait for branch CI: PHP 8.1–8.4, package/publication tests, native security regressions and upgrade integration on disposable WordPress 6.5 and current stable sites.
  4. Create an annotated matching tag (git tag -a vX.Y.Z -m 'LeagueFlow X.Y.Z') and push it (git push origin vX.Y.Z).

The tag workflow repeats all checks before publishing. It creates a draft, verifies all three assets and then makes the release public. Reruns compare bytes and can finish incomplete drafts; they never overwrite different existing assets. An older release cannot displace a newer latest version. Prerelease/non-semantic tags fail validation and do not publish. Never move a published tag or replace its ZIP; increment the version instead. Branch and pull-request builds upload test artifacts but do not publish releases. No additional GitHub secrets are required.

Native integration sets LEAGUEFLOW_TEST_PACKAGE to the built ZIP and runs wp eval-file tests/wordpress-security.php, followed by wp eval-file tests/wordpress-update.php on an isolated http://leagueflow.test installation with MySQL, PHP 8.2, WP-CLI, zip, mysqli and the built plugin activated. Controlled HTTP fixtures exercise real WordPress update hooks and Plugin_Upgrader: both checksum rejection without file changes and a successful next-version installation preserving active status and stored data. Local isolated tests supplement this integration; they do not certify every host, theme or league workflow.

Architecture

  • lf_team, lf_player, and lf_match are shared custom post types used across all sports.
  • lf_sport is the core taxonomy that assigns every team, player, and match to a sport module.
  • lf_league_level assigns teams, players, matches, and calendar events to league levels such as Recreational and Competitive inside each sport.
  • lf_competition and lf_season are taxonomies shared by teams and matches.
  • Sports_Manager defines built-in sports, enables or disables sport modules, creates sport-specific admin menus, and exposes sport-specific match fields and icons.
  • Standings are calculated from finished match scores and are never entered manually.
  • Knockout brackets are built from match meta (lf_is_knockout, lf_round_label, lf_round_order, lf_next_match_id, lf_next_match_slot).
  • Frontend blocks and shortcodes use the same server-side renderer for consistent output.
  • LeagueFlow ships portable public templates for team pages, match pages, and match archives. Classic themes use the bundled PHP wrappers, and block themes receive plugin-registered block templates unless the active theme or Site Editor provides a more specific override.

Folder Structure

leagueflow/
├── assets/
│   ├── css/
│   └── js/
├── blocks/
│   ├── knockout-bracket/
│   ├── league-table/
│   ├── match-card/
│   ├── match-list/
│   ├── team-list/
│   └── team-roster/
├── includes/
│   ├── class-activator.php
│   ├── class-admin.php
│   ├── class-assets.php
│   ├── class-blocks.php
│   ├── class-knockout-service.php
│   ├── class-plugin.php
│   ├── class-post-types.php
│   ├── class-renderer.php
│   ├── class-rest-controller.php
│   ├── class-seeder.php
│   ├── class-settings.php
│   ├── class-shortcodes.php
│   ├── class-sports-manager.php
│   ├── class-standings-service.php
│   ├── class-taxonomies.php
│   ├── class-template-loader.php
│   └── helpers.php
├── templates/
├── SPORTS.md
├── leagueflow.php
├── README.md
└── uninstall.php

Installation

  1. Copy the leagueflow folder into wp-content/plugins/.
  2. Activate LeagueFlow in WordPress admin.
  3. Visit LeagueFlow > Sports and enable the sports you want to support.
  4. Review LeagueFlow > Settings for points, display defaults, and slug settings.
  5. Create competitions and seasons from the LeagueFlow admin menu.

Data Model

  • Sport: taxonomy term used to modularize one shared data model across soccer, basketball, football, baseball, hockey, volleyball, cricket, rugby, and future sport modules.
  • League Level: taxonomy term used with Sport to split each sport into levels such as Recreational and Competitive.
  • Competition: taxonomy term.
  • Season: taxonomy term.
  • Team: post with short name, city, coach, founded year, description, and featured image as logo.
  • Player: post with team assignment, jersey number, position, age, nationality, captain flag, and featured image as photo.
  • Match: post with fixture data, scores, status, sport-specific notes, and optional knockout settings.
  • Field Availability: saved admin availability windows that describe when a field or venue can host matches. Matches can link back to the availability window used by the scheduling assistant.

Admin Usage

Sports Setup

  • Start at LeagueFlow > Sports.
  • Enable the sports you want active in the plugin.
  • Each enabled sport gets its own left-hand WordPress admin menu with a sport-specific icon, overview page, and filtered team, player, match, standings, and bracket views.
  • Disabled sports stay out of the menu so one install can be tailored to the sports you actually run.

Teams

  • Add teams from LeagueFlow > Teams.
  • Sport-specific menus also provide sport-scoped team screens and Add Team links.
  • Assign each team to a league level from the team details box.
  • Use the main content editor for the team description.
  • Use the featured image for the team logo.

Players

  • Add players from LeagueFlow > Players.
  • Sport-specific menus also provide sport-scoped player screens and Add Player links.
  • Assign each player to a team from the metabox.
  • Mark captains with the captain checkbox.
  • Administrators can link an eligible subscriber or portal account, or provision a new account using the player's valid, unused email. New users receive a WordPress password-setup link. Linking keeps existing passwords unchanged. Account controls require leagueflow_manage_player_accounts, edit_users and promote_users; provisioning also requires create_users. Privileged users and your own account cannot be linked as player identities.

Matches

  • Add fixtures from LeagueFlow > Matches.
  • Sport-specific menus also provide sport-scoped match screens and Add Match links.
  • Assign competition and season terms in the sidebar.
  • Match sport is inherited from the selected teams so cross-sport fixtures are blocked.
  • Match league level is inherited from the selected teams so recreational and competitive fixtures remain separate.
  • Use the Scheduling Assistant in the match details box to auto-fill date/time and venue from field availability, or edit those fields manually to override the assistant.
  • Mark a fixture as finished to have it counted in the league table.
  • For knockout fixtures, enable Knockout Match, define the round label and order, and optionally choose the next match and slot.
  • The match events box changes by sport. Soccer can store scorers and cards, basketball can store quarter scores and foul summaries, baseball can store inning lines, and so on.

Field Availability

  • Open LeagueFlow > Field Availability, or the sport-specific Field Availability page, to define recurring weekday or one-off date windows for each site field.
  • Availability rules include field/venue name, sport scope, start and end times, match length, and optional buffer time.
  • Use Auto Schedule Matches to fill missing match dates, venues, or both for a sport, competition, season, date range, or specific date.
  • Existing matches and calendar events at the same venue are treated as conflicts, and teams are not placed into overlapping match slots.
  • Manual match edits remain the override path unless the overwrite option is intentionally selected.
  • Global field configuration requires leagueflow_manage_field_availability. Bulk scheduling requires leagueflow_manage_schedule and permission to edit every affected match; overwrite also requires leagueflow_overwrite_schedule. Fixture generation requires leagueflow_manage_fixtures and readable teams. Users without WordPress publication permission generate drafts.

These management capabilities are granted to administrators automatically on upgrade. Explicitly grant them when delegating to custom roles. Field availability permission authorizes changes across the whole site, including sport menu pages.

League Levels

  • Manage level terms from LeagueFlow > League Levels.
  • Recreational and Competitive levels are created automatically.
  • Use the level selector in standings, bracket, block, shortcode, and REST contexts to filter a sport into one level.

Competitions and Seasons

  • Manage competition terms from LeagueFlow > Competitions.
  • Manage season terms from LeagueFlow > Seasons.
  • Assign a sport to each competition and season so sport-specific pages, blocks, and filters stay consistent.
  • Apply them to teams and matches so blocks, archives, standings, and brackets can filter correctly.

Standings

  • Visit LeagueFlow > Standings to preview calculated tables in admin.
  • Points are controlled by plugin settings.

Knockout Brackets

  • Visit LeagueFlow > Knockout Brackets to preview the visual bracket.
  • Winners can advance automatically into the next match when a knockout fixture is marked finished.
  • If a match is decided by penalties or a ruling, use Winner Override.

Gutenberg Blocks

  • League Table
  • Sport Standings
  • Team List
  • Team Roster
  • Match List
  • Match Card
  • Knockout Bracket

All blocks are dynamic server-side blocks and inherit the classic frontend styling from the plugin. League table, team list, match list, calendar, and knockout bracket blocks support sport and league_level attributes so editors can target a specific sport module and level. Sport Standings displays enabled sports split by league level as expandable standings panels.

Shortcodes

  • [league_table competition="spring-league" season="2026-spring" sport="soccer" league_level="recreational"]
  • [sport_standings competition="spring-league" season="2026-spring"]
  • [sport_standings sports="soccer,volleyball"]
  • [team_roster team="123"]
  • [match_list competition="spring-league" season="2026-spring" sport="soccer" league_level="competitive"]
  • [knockout_bracket competition="2026-cup" season="2026-spring" sport="soccer" league_level="competitive"]
  • [team_list competition="spring-league" season="2026-spring" sport="soccer" league_level="recreational"]
  • [match_card match="456"]

Shortcode attributes accept IDs or slugs where appropriate.

REST API

Public read-only endpoints are available under:

  • /wp-json/leagueflow/v1/standings
  • /wp-json/leagueflow/v1/matches
  • /wp-json/leagueflow/v1/teams
  • /wp-json/leagueflow/v1/bracket
  • /wp-json/leagueflow/v1/league-levels
  • /wp-json/leagueflow/v1/events
  • /wp-json/leagueflow/v1/calendar/events

Supported query parameters include sport, league_level, competition, season, status, team, limit, and include_knockout.

Matches use limit and page; calendar endpoints use per_page and page. The default is 20 records per page and the maximum is 100. Zero/negative limits use the default; oversized limits use the maximum. Calendar responses include total, pages and pagination; filter metadata describes the requested page. Date ranges (start_date, end_date), status, team, type and taxonomy filters apply before database pagination. Calendar search includes titles, descriptions, venues, teams and taxonomy labels. Match archives have page navigation.

Anonymous general collections omit fixtures referencing private or protected teams, including when a password cookie exists. An explicit team filter verifies that team's WordPress password cookie and includes its fixtures once unlocked; the team's unlocked profile and recent matches remain available. Staff retain private-team access through WordPress's normal permissions.

Embedded match lists and [match_calendar] also default to 20 and are capped at 100 records through their limit attribute. They no longer load all historical records; use date/taxonomy scopes or the paginated REST endpoints for larger feeds.

Both POST /calendar/events and POST /events/create-calendar-event require WordPress event creation/editing permission. Users who can publish default to published events; other authors default to draft. Explicit publication, scheduled publication and private status require their corresponding WordPress permissions. Existing terms require assignment permission, and new terms additionally require taxonomy management permission.

Demo Data

Use LeagueFlow > Settings > Generate Demo Data to create:

  • Sample competitions and a season
  • Recreational and Competitive league levels
  • Four teams
  • Five players per team
  • League fixtures
  • Cup semifinals and a final with automatic winner advancement
  • Example frontend pages using sport-aware shortcodes

Local Testing Notes

  1. Activate the plugin locally.
  2. Generate demo data from settings.
  3. Visit the generated pages:
    • League Table
    • Fixtures & Results
    • Cup Bracket
  4. Edit a finished match score and confirm the standings update.
  5. Edit a knockout match, mark it finished, and confirm the winner advances into the configured next match.
  6. Insert LeagueFlow blocks in the block editor, select a sport, and compare frontend output.
  7. Review SPORTS.md for the built-in sport model notes and research references that shaped the modular field design.

Security and Standards

  • Uses capability checks and nonces for admin actions.
  • Sanitizes and escapes data in admin and frontend output.
  • Translation-ready with the leagueflow text domain.
  • Avoids external frameworks and uses WordPress-native APIs.

Releases

1 release. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
v1.0.2 latest
Oct 7, 2026 7d ago
latest.json +2 assets
30
latest.json24
leagueflow-1.0.2.zip3
leagueflow-1.0.2.zip.sha2563