CountyCollective Reference

Reference Overview

Explains what was copied from WordPress and what County Collective needs from it.

Back to CountyCollective Reference

README.md

# CountyCollective Reference — WordPress Plugin Generation Code

**Date copied:** 2026-06-08
**Source plugin version:** 0.3.6

---

## What this folder is

These files are **not active WordPress code**. They are reference material copied
from the `county-gop-core` plugin before the map-generation subsystems were removed.

They exist here so the CountyCollective project can use them as:
- Implementation reference for the generation algorithms being rebuilt outside WordPress
- Specification for what the generated GeoJSON files must look like for consumption
- Reference for data formats (option keys, file paths, manifest structure) that
  WordPress still reads after generation

**Do not include these files in any WordPress require/include chain.**
WordPress no longer loads any file from this directory.

---

## Why generation moved out of WordPress

Map generation (Beacon GIS fetch, ArcGIS FeatureServer import, WKT → GeoJSON
coordinate conversion, composite map building) is moving to a new project called
**CountyCollective**. Kinsta (the WordPress host) should not run Python, make live
Beacon requests, or maintain ArcGIS polling crons. WordPress now consumes finished
GeoJSON files only, uploaded directly via the District Map Imports admin page.

---

## Files in this reference

### `wordpress-plugin/includes/gis/class-cgop-gis-boundary-import.php`

**Original path:** `plugins/county-gop-core/includes/gis/class-cgop-gis-boundary-import.php`
**Lines:** 3,032

What it did:
- Registered and managed **Beacon GIS layer** definitions (layer ID, output dir,
  field templates)
- Fetched raw WKT geometry from Beacon's `GetVectorLayer` API endpoint using
  QPS auth, Cookie header, and User-Agent spoofing
- Spawned a Python subprocess (`convert_beacon_wkt_to_geojson.py`) to convert
  EPSG:2965 WKT → EPSG:4326 GeoJSON
- Wrote one `.geojson` file per feature into `wp-content/uploads/county-gop-maps/`
- Built and registered **composite maps** (merge multiple generated files into one)
- Registered **direct GeoJSON upload** handler (this portion is kept and carried
  forward in the new lean `class-cgop-map-file-import.php`)
- Generated `manifest.json` index of all known files
- Registered the admin submenu page "GIS Boundary Import" under `CGOP_SETUP_MENU_SLUG`
- All generation admin-post handlers: `CGOP_gis_regenerate`, `CGOP_gis_add_custom_layer`,
  `CGOP_gis_delete_custom_layer`, `CGOP_gis_delete_generated_file`,
  `CGOP_gis_create_composite`, `CGOP_gis_rebuild_composite`, `CGOP_gis_delete_composite`

What CountyCollective needs from this:
- Beacon API request format (`CGOP_gis_fetch_beacon_layer`) — endpoint, QPS param,
  JSON body shape, Cookie/User-Agent handling, `d[]` response envelope
- WKT geometry field name: `WktGeometry` key in each Beacon record
- Coordinate system: input EPSG:2965 (Indiana State Plane), output EPSG:4326 (WGS84)
- Output file structure: one FeatureCollection per district, with `position_id`,
  `source_layer_id`, `source_layer_name`, `label`, `name`, `position_type`, `level`
  in the feature properties
- Composite algorithm: `CGOP_gis_build_composite_geojson` — plain feature merge,
  no dissolve, adds `composite_id` / `composite_label` / `composite_source_file`
  properties
- Manifest format: `CGOP_gis_write_manifest` — JSON with `generated_at`, `source`,
  `source_crs`, `target_crs`, `layers[]`, `direct[]`, `composites[]`

WordPress option keys still read by the active plugin after generation:
- `CGOP_gis_direct_geojson_imports` — direct-upload records (consumed by kept code)
- `CGOP_gis_composite_maps` — composite map records (may remain until composites are
  re-evaluated for CountyCollective)
- `CGOP_GIS_IMPORT_STATUS_OPTION` (`CGOP_gis_boundary_import_status`) — Beacon layer
  status; **no longer updated** by active plugin; old data remains readable

---

### `wordpress-plugin/includes/gis/class-cgop-arcgis-boundary-import.php`

**Original path:** `plugins/county-gop-core/includes/gis/class-cgop-arcgis-boundary-import.php`
**Lines:** 1,714

What it did:
- Managed **ArcGIS Portal / FeatureServer** sources (item IDs, portal base URLs,
  service URL discovery)
- Fetched layer lists and feature geometry from ArcGIS REST API
- Converted ArcGIS JSON geometry (`rings`/`paths`) to GeoJSON natively (no Python)
- Wrote ArcGIS-imported GeoJSON files to `county-gop-maps/{slug}/generated/arcgis/`
- Ran a **daily WP-Cron** (`CGOP_daily_arcgis_boundary_check`) to detect upstream
  source changes
- Showed admin notices when ArcGIS sources changed
- Auto-assigned imported maps to matching Position Keys by label

WordPress option keys used:
- `CGOP_arcgis_boundary_sources` — ArcGIS source definitions
- `CGOP_arcgis_generated_maps` — ArcGIS-generated map metadata
  Both options remain in DB as inert data; cron was unscheduled when plugin was
  deactivated/reactivated after this code was removed.

What CountyCollective needs from this:
- ArcGIS REST query format: `CGOP_arcgis_fetch_layer_geojson` — tries native GeoJSON
  (`f=geojson`), falls back to ArcGIS JSON + `CGOP_arcgis_convert_esri_to_geojson`
- Template system: `CGOP_arcgis_render_template` — `{FIELD}` / `{FIELD_slug}` tokens
  for filename and label generation
- Source hash: `CGOP_arcgis_build_source_hash` — detects upstream changes via item
  modified timestamp, url, size, layer names

---

### `wordpress-plugin/tools/gis/convert_beacon_wkt_to_geojson.py`

**Original path:** `plugins/county-gop-core/tools/gis/convert_beacon_wkt_to_geojson.py`
**Lines:** 46

What it did:
- Reads `{"wkt": "MULTIPOLYGON (...)"}` on stdin
- Converts EPSG:2965 → EPSG:4326 using `pyproj` + `shapely`
- Outputs `{"ok": true, "geometry": {...}}` on stdout

Dependencies: `pyproj`, `shapely`

CountyCollective should implement this natively rather than shelling to Python.
The coordinate transformation is: `Transformer.from_crs("EPSG:2965", "EPSG:4326", always_xy=True)`.

---

### `wordpress-plugin/includes/csv-tools/class-cgop-csv-tools.php`

**Original path:** `plugins/county-gop-core/includes/csv-tools/class-cgop-csv-tools.php`
**Lines:** 3,042+

This file is **still active** in WordPress — it was not deleted. Only the
Beacon-layer stat display in `CGOP_csv_tools_get_counts()` was removed (lines
138–149 in the original). The rest of the CSV Tools (Position Keys export/import,
Representatives export/import, wipe tools) are unchanged.

This reference copy shows the original state including those stat lines in case
CountyCollective needs the stat-gathering logic.

---

## Output file format WordPress expects

After CountyCollective generates a GeoJSON file, you upload it via the WordPress
admin: **GOP Setup → District Map Imports → Import GeoJSON Map**.

WordPress stores uploaded files at:
```
wp-content/uploads/county-gop-maps/{county_slug}/generated/imported/{slug}.geojson
```

The file must be a valid GeoJSON `FeatureCollection`, `Feature`, `Polygon`, or
`MultiPolygon`. There is no required property schema — WordPress reads the file
as an opaque map boundary and assigns it to Position Keys via the admin UI.

Once imported, the map appears in Position Keys dropdowns under **Uploaded GeoJSON**.
Existing files already generated by the old Beacon/ArcGIS workflow remain readable
as long as the files exist on disk and their records are in the option tables.

---

## Migration note for existing generated files

Files already on disk at `wp-content/uploads/county-gop-maps/*/generated/` were
written by the old generation code and remain intact. WordPress will continue to
serve them as static files. Position Key assignments that pointed to them remain
valid. No action is needed unless you want to re-generate them via CountyCollective
and re-import.

To re-import an existing file, either:
1. Upload it again via District Map Imports → Import GeoJSON Map (creates a new
   import record pointing to the new copy), or
2. Leave the old file and its existing Position Key assignment in place.