diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93695c4..e68498f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,8 +26,6 @@ jobs: test-js: name: JS Tests & Build runs-on: ubuntu-latest - env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: - name: Checkout @@ -46,7 +44,7 @@ jobs: run: npm run test:js -- --coverage - name: Upload JS coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage/lcov.info @@ -56,7 +54,7 @@ jobs: run: npm run build - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: js-build path: | @@ -94,7 +92,7 @@ jobs: run: npm run wp-env -- run tests-cli --env-cwd=wp-content/plugins/Spotmap sh -c "XDEBUG_MODE=coverage composer run test:coverage" - name: Upload PHP coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage/clover.xml diff --git a/.github/workflows/deploy_plugin.yaml b/.github/workflows/deploy_plugin.yaml index 55756da..9577b20 100644 --- a/.github/workflows/deploy_plugin.yaml +++ b/.github/workflows/deploy_plugin.yaml @@ -76,13 +76,13 @@ jobs: if: steps.tag_check.outputs.exists == 'false' run: npm ci - - name: Start wp-env + - name: Install PHP dependencies if: steps.tag_check.outputs.exists == 'false' - run: npm run wp-env start + run: composer install --no-dev --optimize-autoloader --ignore-platform-reqs - - name: Install PHP dependencies + - name: Start wp-env if: steps.tag_check.outputs.exists == 'false' - run: npm run composer -- install --no-dev --optimize-autoloader --ignore-platform-reqs + run: npm run wp-env start - name: Build if: steps.tag_check.outputs.exists == 'false' && github.event_name == 'workflow_dispatch' diff --git a/README-SHORTCODE.md b/README-SHORTCODE.md new file mode 100644 index 0000000..cc3148a --- /dev/null +++ b/README-SHORTCODE.md @@ -0,0 +1,168 @@ +# Spotmap Shortcode Reference + +Two shortcodes are available: + +- `[spotmap]` — embeds an interactive Leaflet map +- `[spotmessages]` — embeds a table of SPOT messages/events + +--- + +## `[spotmap]` + +### Map Content + +| Attribute | Type | Default | Possible values / notes | +| --- | --- | --- | --- | +| `feeds` | comma-separated strings | all feeds | Feed names as configured in Spotmap admin, e.g. `feeds="alice,bob"` | +| `date` | `YYYY-MM-DD` | — | Show only points from a single day. Expands internally to a full-day range. Cannot be combined with `date-range-from`/`to`. | +| `date-range-from` | string | — | Start of date/time filter. Accepts an absolute datetime (`2024-07-01 08:00:00`) or a relative value (`last-7-days`, `last-2-hours`, `last-30-minutes`). See [Relative time values](#relative-time-values). | +| `date-range-to` | string | — | End of date/time filter. Same formats as `date-range-from`. Use a relative value here to exclude the most recent points, e.g. `date-range-to="last-30-minutes"` hides the live position. | +| `filter-points` | integer (metres) | `5` (admin default) | Removes GPS noise: skips points closer than this distance to the previous point | + +### Map Style / Appearance + +| Attribute | Type | Default | Possible values / notes | +| --- | --- | --- | --- | +| `height` | integer (px) | `500` | Height of the map container in pixels | +| `width` | string | `"normal"` | `"normal"` · `"full"` (100% container width) | +| `mapcenter` | string | `"all"` | See [mapcenter values](#mapcenter-values) below | +| `maps` | comma-separated strings | `"openstreetmap,opentopomap"` | Tile layer IDs from `config/maps.yaml`, e.g. `maps="openstreetmap,satellite"`. First entry is the initial layer; additional entries appear in the layer switcher. | +| `map-overlays` | comma-separated strings | — | Overlay tile layer IDs from `config/maps.yaml` to enable on top of the base layer | +| `colors` | comma-separated strings | `"blue,red"` | Line/marker color per feed. Named colors (`blue`, `red`, `green`, `gold`, `orange`, `yellow`, `violet`, `black`, `white`) or hex values. Cycles if fewer values than feeds. | +| `splitlines` | comma-separated integers (hours) | `"12"` | Hours gap that splits a GPS track into separate polyline segments, per feed. Use `0` to disable splitting. Cycles if fewer values than feeds. | + +### GPX Tracks + +| Attribute | Type | Default | Possible values / notes | +| --- | --- | --- | --- | +| `gpx-url` | comma-separated URLs | — | One or more GPX file URLs to overlay on the map | +| `gpx-name` | comma-separated strings | `"GPX"` | Display label per GPX track. Cycles if fewer than URLs. | +| `gpx-color` | comma-separated strings | `"blue,gold,red,green,orange,yellow,violet"` | Color per GPX track. Cycles if fewer than URLs. | + +### Map Controls & Interaction + +| Attribute | Type | Default | Possible values / notes | +| --- | --- | --- | --- | +| `fullscreen-button` | boolean | `true` | `true` · `false` — show a fullscreen toggle button | +| `locate-button` | boolean | `false` | `true` · `false` — show a "locate me" button (jumps to the user's GPS position) | +| `navigation-buttons` | boolean | `true` | `true` · `false` — show the zoom-to cycling button (see [Navigation buttons](#navigation-buttons) below) | +| `scroll-wheel-zoom` | boolean | `true` | `true` · `false` — enable mouse-wheel zoom. Set to `false` to prevent the map from consuming scroll events on long pages. | +| `enable-panning` | boolean | `true` | `true` · `false` — enable drag-to-pan. Set to `false` for a static, non-interactive map. | +| `last-point` | flag (no value) | `false` | Add attribute to highlight the latest GPS point of every feed with a large circle marker | +| `auto-reload` | flag (no value) | `false` | Add attribute to auto-refresh map data periodically | + +### Debug + +| Attribute | Type | Default | Possible values / notes | +| --- | --- | --- | --- | +| `debug` | flag (no value) | `false` | Add attribute to enable verbose debug output in the browser console | + +--- + +### Relative time values + +`date-range-from` and `date-range-to` accept relative values using the format `last-{n}-{unit}`, where unit is any value PHP's `strtotime` understands (hyphens replace spaces). + +| Example | Meaning | +| --- | --- | +| `last-30-minutes` | 30 minutes ago | +| `last-2-hours` | 2 hours ago | +| `last-7-days` | 7 days ago | +| `last-1-month` | 1 month ago | + +**Common patterns:** + +``` +// Show only the last 24 hours of track data +[spotmap date-range-from="last-24-hours"] + +// Show last 7 days but hide the live position (last 30 minutes) +[spotmap date-range-from="last-7-days" date-range-to="last-30-minutes"] + +// Show a fixed window in the past — absolute datetimes still work too +[spotmap date-range-from="2024-07-01 00:00:00" date-range-to="2024-07-31 23:59:59"] +``` + +--- + +### `mapcenter` values + +Controls which area the map initially fits/zooms to after data loads. + +| Value | Behaviour | +| --- | --- | +| `all` | Fit all GPS points **and** GPX tracks (default) | +| `feeds` | Fit GPS feed points only (ignores GPX tracks) | +| `gpx` | Fit GPX tracks only (ignores feed points) | +| `last` | Zoom to the single latest GPS point across all feeds | +| `last-trip` | Fit the last polyline segment of each feed (points since the last split) | +| `lat,lng` | Center on exact coordinates, e.g. `mapcenter="47.3769,8.5417"` — no auto-zoom | + +--- + +### Navigation buttons + +When `navigation-buttons="true"` (default), a cycling zoom-to button appears on the map. Each click cycles through the enabled targets: + +| Target | Behaviour | +| --- | --- | +| All points | `fitBounds` to all GPS points + GPX tracks | +| Latest point | `fitBounds` to the most recent GPS point | +| GPX tracks | `fitBounds` to GPX track extent (only shown if GPX tracks are present) | + +--- + +### Examples + +``` +[spotmap] + +[spotmap feeds="alice" height="400" mapcenter="last"] + +[spotmap feeds="alice,bob" colors="blue,red" splitlines="6,6" date="2024-07-15"] + +[spotmap date-range-from="2024-07-01 00:00:00" date-range-to="2024-07-31 23:59:59" maps="openstreetmap,satellite"] + +[spotmap gpx-url="https://example.com/track.gpx" gpx-name="My Hike" gpx-color="green" mapcenter="gpx"] + +[spotmap scroll-wheel-zoom="false" enable-panning="false"] + +[spotmap auto-reload last-point debug] +``` + +--- + +## `[spotmessages]` + +Renders a table of SPOT message events (OK check-ins, HELP alerts, custom messages, etc.). + +| Attribute | Type | Default | Possible values / notes | +| --- | --- | --- | --- | +| `feeds` | comma-separated strings | all feeds | Feed names to include | +| `count` | integer | `10` | Maximum number of rows to display | +| `types` | comma-separated strings | `"HELP,HELP-CANCEL,OK,CUSTOM"` | Message types to filter: `HELP` · `HELP-CANCEL` · `OK` · `CUSTOM` · `UNLIMITED-TRACK` · `TRACK` · `NEWMOVEMENT` | +| `group` | comma-separated strings | `"type,feed_name"` | Column(s) to group by. Allowed values: any DB column name (`type`, `feed_name`, `time`, etc.). Set to empty string to disable grouping. | +| `date` | `YYYY-MM-DD` | — | Show only messages from a single day | +| `date-range-from` | string | — | Start of date/time filter. Accepts absolute (`2024-07-01 08:00:00`) or relative (`last-7-days`, `last-2-hours`) values. | +| `date-range-to` | string | — | End of date/time filter. Same formats as `date-range-from`. | +| `filter-points` | integer (metres) | admin default | Minimum distance filter passed through to the query | +| `auto-reload` | flag (no value) | `false` | Add attribute to auto-refresh the table periodically | + +### Examples + +``` +[spotmessages] + +[spotmessages count="5" types="HELP,OK" feeds="alice"] + +[spotmessages date-range-from="2024-07-01 00:00:00" date-range-to="2024-07-31 23:59:59" auto-reload] +``` + +--- + +## Notes + +- **Flag attributes** (`auto-reload`, `last-point`, `debug`) activate when the attribute name is present with no value: `[spotmap auto-reload]`. Providing a truthy value also works: `auto-reload="1"`. +- **Comma-separated lists** (`feeds`, `colors`, `splitlines`, `maps`, `gpx-url`, etc.) are split on `,`; empty entries are stripped. +- **`colors` and `splitlines`** are padded to match the number of feeds by repeating the first value if too few entries are supplied. +- **Admin defaults** for `height`, `width`, `mapcenter`, `maps`, `color`, `splitlines`, and `filter-points` come from *Spotmap → Settings* and can be overridden per-shortcode instance. diff --git a/composer.json b/composer.json index e8cdb13..1f5e0dc 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "techtimo/spotmap", "description": "Spotmap WordPress plugin", - "version": "1.0.0", + "version": "1.0.0-rc.2", "type": "wordpress-plugin", "require": { "symfony/yaml": "^7.0", diff --git a/package-lock.json b/package-lock.json index a34c1c4..32d7c5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3859,36 +3859,6 @@ } } }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@jest/reporters/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmmirror.com/@jest/schemas/-/schemas-29.6.3.tgz", @@ -12040,20 +12010,23 @@ } }, "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmmirror.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/babel-plugin-istanbul/-/babel-plugin-istanbul-8.0.0.tgz", + "integrity": "sha512-18wCskrN3DgbuBmp1gr7LBGT8xdz5xhQQqFvFhVxbkl8VBCrMKQ2YtqBWtUal1Zrc1HTuX0011+Brjw78TCFkg==", "dev": true, "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=18" } }, "node_modules/babel-plugin-jest-hoist": { @@ -18596,20 +18569,33 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmmirror.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/istanbul-lib-report": { @@ -26717,18 +26703,18 @@ } }, "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-7.0.2.tgz", + "integrity": "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==", "dev": true, "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "glob": "^10.4.1", + "minimatch": "^10.2.2" }, "engines": { - "node": ">=8" + "node": ">=18" } }, "node_modules/text-decoder": { diff --git a/package.json b/package.json index 62a5318..610dffa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "spotmap", - "version": "1.0.0", + "version": "1.0.0-rc.2", "description": "[![WordPress Plugin: Version](https://img.shields.io/wordpress/plugin/v/spotmap?color=green&logo=wordpress) ![WordPress Plugin: Tested WP Version](https://img.shields.io/wordpress/plugin/tested/spotmap?color=green&logo=wordpress)](https://wordpress.org/plugins/spotmap/)", "author": "Timo Giese", "license": "GPL-2.0-or-later", @@ -85,6 +85,7 @@ "serialize-javascript": "^7.0.3", "minimatch": "^9.0.7", "glob": "^10.5.0", - "phin": "^3.7.1" + "phin": "^3.7.1", + "babel-plugin-istanbul": "^8.0.0" } } diff --git a/pluginreadme.md b/pluginreadme.md index 4834586..be9ac95 100644 --- a/pluginreadme.md +++ b/pluginreadme.md @@ -101,6 +101,17 @@ To reduce the risk of token abuse, **restrict each token to your domain using th All database queries use prepared statements as of version 1.0. +## Shortcodes + +Spotmap ships two shortcodes for themes or page builders that don't use the block editor. + +**`[spotmap]`** — embeds an interactive map +**`[spotmessages]`** — embeds a table of SPOT messages and check-ins + +The shortcodes have **full feature parity with the Gutenberg block**: every option available in the block sidebar — feeds, time filtering, map tiles, GPX overlays, colors, line splitting, navigation buttons, scroll-wheel zoom, panning control, and more — can also be set as a shortcode attribute. + +For the full attribute reference, see **[README-SHORTCODE.md](https://github.com/techtimo/Spotmap/blob/main/README-SHORTCODE.md)** on GitHub. + ## Frequently Asked Questions ### Which GPS devices are supported? diff --git a/public/class-spotmap-public.php b/public/class-spotmap-public.php index e1d26b1..7a7b872 100644 --- a/public/class-spotmap-public.php +++ b/public/class-spotmap-public.php @@ -182,7 +182,7 @@ function show_point_overview($atts){ 'count'=> 10, 'types'=>'HELP,HELP-CANCEL,OK,CUSTOM', 'feeds' => $this->db->get_all_feednames(), - 'group'=>'', + 'group'=>'type,feed_name', 'date-range-from' => '', 'date' => '', 'date-range-to' => '', @@ -268,6 +268,8 @@ public function show_spotmap($atts,$content = null){ 'locate-button' => FALSE, 'fullscreen-button' => TRUE, 'navigation-buttons' => TRUE, + 'scroll-wheel-zoom' => TRUE, + 'enable-panning' => TRUE, ], $atts ), $atts); if (array_key_exists('feeds',$atts)){ @@ -394,6 +396,8 @@ public function show_spotmap($atts,$content = null){ 'locateButton' => (bool) $a['locate-button'], 'fullscreenButton' => (bool) $a['fullscreen-button'], 'navigationButtons' => $a['navigation-buttons'] ? [ 'enabled' => true, 'allPoints' => true, 'latestPoint' => true, 'gpxTracks' => true ] : [ 'enabled' => false ], + 'scrollWheelZoom' => (bool) $a['scroll-wheel-zoom'], + 'enablePanning' => (bool) $a['enable-panning'], 'mapId' => $map_id ]); // error_log($options); diff --git a/scripts/bump-version.js b/scripts/bump-version.js index 6fee5e8..3d48d19 100644 --- a/scripts/bump-version.js +++ b/scripts/bump-version.js @@ -4,7 +4,7 @@ * Syncs the version from package.json into: * - spotmap.php (Plugin header "Version:" and SPOTMAP_VERSION constant) * - composer.json ("version" field) - * - readme.txt (Stable tag: — skipped for pre-release versions) + * - pluginreadme.md (Stable tag: — skipped for pre-release versions) * - tests/bootstrap.php (SPOTMAP_VERSION constant) * * Usage: node scripts/bump-version.js @@ -37,18 +37,18 @@ php = php.replace( fs.writeFileSync( phpFile, php ); console.log( ` spotmap.php updated` ); -// --- readme.txt --- -const readmeFile = path.join( root, 'readme.txt' ); +// --- pluginreadme.md --- +const readmeFile = path.join( root, 'pluginreadme.md' ); let readme = fs.readFileSync( readmeFile, 'utf8' ); // Only update Stable tag for stable releases (no pre-release suffix) if ( /^[\d]+\.[\d]+\.[\d]+$/.test( version ) ) { readme = readme.replace( /^(Stable tag:\s*)[\d.]+/m, `$1${ version }` ); fs.writeFileSync( readmeFile, readme ); - console.log( ` readme.txt Stable tag updated` ); + console.log( ` pluginreadme.md Stable tag updated` ); } else { console.log( - ` readme.txt Stable tag skipped (pre-release: ${ version })` + ` pluginreadme.md Stable tag skipped (pre-release: ${ version })` ); } diff --git a/spotmap.php b/spotmap.php index b9149fd..d4966cb 100644 --- a/spotmap.php +++ b/spotmap.php @@ -4,7 +4,7 @@ * Plugin Name: Spotmap * Plugin URI: https://github.com/techtimo/spotmap * Description: Self-hosted GPS tracking for WordPress. Display live positions from SPOT, OsmAnd, and Teltonika devices on interactive Leaflet maps — with a Gutenberg block, time filtering, GPX overlays, and full data ownership. - * Version: 1.0.0-rc.1 + * Version: 1.0.0-rc.2 * Author: Timo Giese * Author URI: https://github.com/techtimo * License: GPL-2.0-or-later @@ -19,7 +19,7 @@ // Block direct access defined('ABSPATH') or die(); -define('SPOTMAP_VERSION', '1.0.0-rc.1'); +define('SPOTMAP_VERSION', '1.0.0-rc.2'); define('SPOTMAP_PLUGIN_BASENAME', plugin_basename(__FILE__)); require_once plugin_dir_path(__FILE__) . 'vendor-prefixed/autoload.php'; diff --git a/tests/SpotmapRenderingTest.php b/tests/SpotmapRenderingTest.php index 2798af2..5aba823 100644 --- a/tests/SpotmapRenderingTest.php +++ b/tests/SpotmapRenderingTest.php @@ -198,7 +198,7 @@ public function test_all_shared_defaults_match(bool $with_feeds): void $block = $this->extract_options($this->render_block([])); // Keys intentionally present only in the block (no shortcode equivalent). - $block_only = [ 'height', 'enablePanning', 'scrollWheelZoom' ]; + $block_only = [ 'height' ]; // Keys intentionally present only in the shortcode (no block equivalent). // NOTE: shortcode 'last-point' is a convenience flag that PHP expands into diff --git a/tests/bootstrap.php b/tests/bootstrap.php index be3de2d..0b3296b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -15,7 +15,7 @@ require_once dirname(__DIR__) . '/includes/class-spotmap-ingest.php'; // Matches the constant defined in spotmap.php — needed by Spotmap_Migrator::run(). -define('SPOTMAP_VERSION', '1.0.0-rc.1'); +define('SPOTMAP_VERSION', '1.0.0-rc.2'); // Recreate the plugin table from the authoritative schema before all tests. // DROP + CREATE ensures a stale schema from a previous run never causes column errors.