WP Manifestindependent plugin directory

Install

Download reconcile-production-2.0.4.zip From the v2.0.4 release on GitHub, Sep 24, 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/bleedingdeacons/reconcile/releases/download/v2.0.4/reconcile-production-2.0.4.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Licence

Import and export member, group, and position data from spreadsheets using the Unity framework.

Reconcile adds spreadsheet-based import/export workflows to the Unity intergroup management plugin. Upload .xlsx, .xls, or .csv files to bulk-create or update members, groups, and positions; download the current data as formatted spreadsheets for offline editing or reporting.

Requires: WordPress 6.0+ · PHP 8.0+ Dependencies: Unity, Scrutiny License: MIT (Modified — see License) Author: The Bleeding Deacons


Table of Contents


Features

  • Member import — upload a spreadsheet to create or update intergroup members in bulk. Matching is performed by member name or ID; existing records are updated and new ones are created.
  • Member export — download all members as a formatted spreadsheet with group and position data included.
  • Group import — bulk-create or update groups from a spreadsheet with configurable column mapping.
  • Group export — download all groups with their associated metadata.
  • Position import — bulk-create or update intergroup service positions from a spreadsheet.
  • Position export — download all positions to a spreadsheet.
  • Column mapping — each importer uses a dedicated column mapper to translate spreadsheet headers to Unity field names, tolerating variations in column naming.
  • Operation results — every import/export returns a structured OperationResult with counts of created, updated, skipped, and errored rows plus per-row messages.
  • Spreadsheet reader — a unified reader that handles .xlsx, .xls, and .csv formats through a single interface.
  • Audit integration — uses Scrutiny's audit logger to record all import and export operations for GDPR compliance.
  • AJAX handlers — import and export operations are handled via AJAX with progress feedback in the admin UI.

Installation

From a .zip archive

  1. Ensure the Unity and Scrutiny plugins are installed and activated.
  2. Download or build the reconcile.zip archive.
  3. In WordPress, go to Plugins → Add New → Upload Plugin.
  4. Upload the .zip file and click Install Now.
  5. Activate the plugin.

Manual installation

  1. Clone or copy the reconcile directory into wp-content/plugins/.
  2. Activate the plugin from the WordPress admin.

Requirements

  • WordPress 6.0+
  • PHP 8.0+
  • Unity plugin — installed and activated
  • Scrutiny plugin — installed and activated (GDPR compliance)
  • PhpSpreadsheet — included via Composer for reading spreadsheet files

Usage

Importing Data

Navigate to the Reconcile admin pages (under the Intergroup menu). Each entity type (Members, Groups, Positions) has its own import page:

  1. Select a .xlsx, .xls, or .csv file.
  2. Upload the file — Reconcile reads the spreadsheet, maps columns to Unity fields, and displays a preview.
  3. Confirm the import — records are created or updated in bulk. A summary shows how many rows were created, updated, skipped, or failed.

Exporting Data

Each entity type also has an export option:

  1. Click the Export button on the relevant admin page.
  2. Reconcile generates a formatted spreadsheet and triggers a download in your browser.

Exports include related data (e.g. member exports include group and position columns).

Admin Pages

Reconcile registers three admin sub-pages under the Intergroup menu:

  • Members — import/export member data
  • Groups — import/export group data
  • Positions — import/export position data

Each page includes file upload forms, column-mapping feedback, and result summaries.


Architecture

Reconcile follows a service-oriented architecture, registering its services into Unity's existing container via Scrutiny.

reconcile/
├── reconcile.php                        # Plugin bootstrap & hooks
├── composer.json                        # Dependencies & PSR-4 autoloading
├── build.php                            # Cross-platform build/packaging script
├── assets/
│   ├── css/admin.css                    # Admin page styles
│   ├── docs/reconsile.html              # Bundled HTML documentation
│   └── js/
│       ├── admin.js                     # Common admin JS
│       ├── group-admin.js               # Group import/export UI
│       └── position-admin.js            # Position import/export UI
└── src/
    ├── Plugin.php                       # Service registration & menu setup
    ├── Core/
    │   ├── OperationResult.php          # Import/export result value object
    │   └── SpreadsheetReader.php        # Unified xlsx/xls/csv reader
    ├── Admin/
    │   ├── MembersAdmin.php             # Member import/export admin page
    │   ├── GroupsAdmin.php              # Group import/export admin page
    │   └── PositionsAdmin.php           # Position import/export admin page
    ├── Member/
    │   ├── MemberColumnMapper.php       # Spreadsheet → Unity field mapping
    │   ├── MemberImporter.php           # Member create/update logic
    │   ├── MemberImportHandler.php      # AJAX import handler
    │   ├── MemberExporter.php           # Member export builder
    │   └── MemberExportHandler.php      # AJAX export handler
    ├── Group/
    │   ├── GroupColumnMapper.php        # Spreadsheet → Unity field mapping
    │   ├── GroupImporter.php            # Group create/update logic
    │   ├── GroupImportHandler.php       # AJAX import handler
    │   ├── GroupExporter.php            # Group export builder
    │   ├── GroupExportHandler.php       # AJAX export handler
    │   └── GroupLookup.php              # Group resolution by name/ID
    └── Position/
        ├── PositionColumnMapper.php     # Spreadsheet → Unity field mapping
        ├── PositionImporter.php         # Position create/update logic
        ├── PositionImportHandler.php    # AJAX import handler
        ├── PositionExporter.php         # Position export builder
        ├── PositionExportHandler.php    # AJAX export handler
        └── PositionLookup.php           # Position resolution by name/ID

Service dependency graph:

  • SpreadsheetReader — standalone
  • MemberImporter → MemberRepository, MemberFactory, GroupRepository, PositionRepository, AuditLogger
  • GroupImporter → GroupRepository, GroupFactory, AuditLogger
  • PositionImporter → PositionRepository, PositionFactory, AuditLogger
  • All exporters → corresponding repositories and factories
  • All handlers → corresponding importers/exporters

Column Mapping

Each importer uses a dedicated column mapper that translates spreadsheet headers to Unity field names. The mappers are tolerant of common header variations — for example, a member import will recognise First Name, first_name, FirstName, etc. Unmapped columns are ignored.


Building for Production

The included build.php script packages the plugin into a distributable .zip archive, stripping development files.

# Production build
php build.php build:production

# Development build (includes tests)
php build.php build:dev

# Clean the build directory
php build.php clean

You can override the version number with --version=X.X and add --clean to wipe the build directory before packaging.


Testing

Install the dev dependencies and run the suite from the plugin directory:

composer install
Command Description
composer test Run the PHPUnit test suite
composer phpstan Run PHPStan static analysis

The suite uses PHPUnit with Mockery for mocking. It covers the spreadsheet reader (CSV and XLSX), the column mappers and name lookups, the CSV exporters, the AJAX import and admin-post export handlers, the temp-upload handling, and the member/group/position importers. Line coverage is reported to Coveralls on every CI run — see the coverage badge at the top of this file.


License

MIT License (Modified) — Copyright © 2025 The Bleeding Deacons.

This software is provided under the standard MIT license with one additional restriction: the licensee may not sell the Software, alone or as part of an aggregate software distribution containing the Software.

See LICENSE for the full text.

Releases

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

Tag
Published
Assets
Downloads
Sep 24, 2026 29d ago
reconcile-production-2.0.4.zip
3
Sep 24, 2026 29d ago
reconcile-production-2.0.3.zip
0
Sep 22, 2026 1mo ago
reconcile-production-2.0.2.zip
1
Sep 20, 2026 1mo ago
reconcile-production-2.0.1.zip
1
Sep 20, 2026 1mo ago
reconcile-production-2.0.0.zip
1
Sep 8, 2026 1mo ago
reconcile-production-1.17.0.zip
4
Sep 5, 2026 1mo ago
reconcile-production-1.16.18.zip
2
Sep 5, 2026 1mo ago
reconcile-production-1.16.17.zip
3
Sep 5, 2026 1mo ago
reconcile-production-1.16.16.zip
3
Aug 25, 2026 1mo ago
reconcile-production-1.16.15.zip
1
Aug 25, 2026 1mo ago
reconcile-production-1.16.14.zip
0
Aug 17, 2026 2mo ago
reconcile-production-1.16.13.zip
1
Aug 17, 2026 2mo ago
reconcile-production-1.16.12.zip
1
Aug 9, 2026 2mo ago
reconcile-production-1.16.11.zip
1
Aug 8, 2026 2mo ago
reconcile-production-1.16.10.zip
1
Aug 7, 2026 2mo ago
reconcile-production-1.16.9.zip
0
Aug 7, 2026 2mo ago
reconcile-production-1.16.8.zip
1
Aug 7, 2026 2mo ago
reconcile-production-1.16.7.zip
1
Aug 7, 2026 2mo ago
reconcile-production-1.16.6.zip
2
Aug 7, 2026 2mo ago
reconcile-production-1.16.5.zip
1
B grade

Security

Reconcile 2.0.4 · audited by WP Registry

Medium-severity findings.

1 medium
Audited release
2.0.4
Findings
1
Worst severity
medium
Content hash
b978f744dfd705b9019eea54…

Findings

  • medium XXE in XLSX import: sheet XML parsed with LIBXML_NOENT

    file_access

    SpreadsheetReader parses xl/worksheets/sheet1.xml from an uploaded XLSX with simplexml_load_string(..., LIBXML_NONET | LIBXML_NOENT). The code comment assumes libxml's default of not loading external entities protects it, but LIBXML_NOENT explicitly turns entity substitution on. External SYSTEM entities pointing at local resources (file://, php://filter) are then resolved; LIBXML_NONET blocks only network fetches. A crafted spreadsheet, for example a member list supplied by a third party, can pull wp-config.php or other readable files into cell values that are then imported as member/group/position data. Nested internal entities also enable entity-expansion (billion laughs) memory exhaustion. Import requires manage_options, so this is admin-initiated, but the file content is untrusted.

    src/Core/SpreadsheetReader.php:173-182

    Recommendation

    Remove LIBXML_NOENT. Reject any XML containing a <!DOCTYPE before parsing, or use XMLReader with substitution disabled, and parse with LIBXML_NONET only.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.