{"id":366786,"date":"2026-09-23T10:43:12","date_gmt":"2026-09-23T10:43:12","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/pcio-vis-boat\/"},"modified":"2026-10-02T20:01:34","modified_gmt":"2026-10-02T20:01:34","slug":"pcio-vis-boat","status":"publish","type":"plugin","link":"https:\/\/vec.wordpress.org\/plugins\/pcio-vis-boat\/","author":20981457,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.1","stable_tag":"1.1.1","tested":"7.1.2","requires":"6.2","requires_php":"8.1","requires_plugins":null,"header_name":"PCIO VIS Boat","header_author":"PCIO","header_description":"Extends PCIO VIS Member Event with a boat club register: boats linked to an owner member, optional crew members per boat with subscription activity tracking, and a Boat Register admin page. Fields: home harbour, boat name, type, model, build year, sail number and MMSI.","assets_banners_color":"000000","last_updated":"2026-10-02 20:01:34","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/www.pcio.dk\/","header_author_uri":"https:\/\/www.pcio.dk","rating":0,"author_block_rating":0,"active_installs":0,"downloads":139,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.1":{"tag":"1.0.1","author":"pcio","date":"2026-09-23 16:04:22","revision":3709639},"1.1.0":{"tag":"1.1.0","author":"pcio","date":"2026-10-02 19:53:43","revision":3725419},"1.1.1":{"tag":"1.1.1","author":"pcio","date":"2026-10-02 20:01:34","revision":3725428}},"upgrade_notice":{"1.1":"<p>Boat records are migrated automatically. The owner column becomes the membership number, the free-text home harbour column is removed, and the membership number is made unique. Boats needing manual attention are listed in the PHP error log \u2014 see the changelog.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3709070,"resolution":"128x128","location":"assets","locale":"","width":1100,"height":1100},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3709070,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3709070,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3709070,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.1","1.1.0","1.1.1"],"block_files":[],"assets_screenshots":{"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":3709070,"resolution":"1","location":"assets","locale":"","width":1243,"height":1059},"screenshot-2.jpg":{"filename":"screenshot-2.jpg","revision":3709070,"resolution":"2","location":"assets","locale":"","width":1149,"height":643},"screenshot-3.jpg":{"filename":"screenshot-3.jpg","revision":3709070,"resolution":"3","location":"assets","locale":"","width":1313,"height":1058}},"screenshots":{"1":"New register for boat data","2":"Map showing members home habour","3":"Advanced member statistics and sponsor activity (number of link clicks)"}},"plugin_section":[],"plugin_tags":[13696,14241,1919,132457],"plugin_category":[58],"plugin_contributors":[265152],"plugin_business_model":[],"class_list":["post-366786","plugin","type-plugin","status-publish","hentry","plugin_tags-boats","plugin_tags-club","plugin_tags-members","plugin_tags-nautical","plugin_category-user-management","plugin_contributors-pcio","plugin_committers-pcio"],"banners":{"banner":"https:\/\/ps.w.org\/pcio-vis-boat\/assets\/banner-772x250.png?rev=3709070","banner_2x":"https:\/\/ps.w.org\/pcio-vis-boat\/assets\/banner-1544x500.png?rev=3709070","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/pcio-vis-boat\/assets\/icon-128x128.png?rev=3709070","icon_2x":"https:\/\/ps.w.org\/pcio-vis-boat\/assets\/icon-256x256.png?rev=3709070","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/pcio-vis-boat\/assets\/screenshot-1.jpg?rev=3709070","caption":"New register for boat data"},{"src":"https:\/\/ps.w.org\/pcio-vis-boat\/assets\/screenshot-2.jpg?rev=3709070","caption":"Map showing members home habour"},{"src":"https:\/\/ps.w.org\/pcio-vis-boat\/assets\/screenshot-3.jpg?rev=3709070","caption":"Advanced member statistics and sponsor activity (number of link clicks)"}],"raw_content":"<!--section=description-->\n<p>Adds a <strong>Boat Register<\/strong> to PCIO VIS Member Event for sailing clubs and other\nboat-oriented organisations.<\/p>\n\n<p><strong>Features<\/strong><\/p>\n\n<ul>\n<li>Register boats with: home harbour, name, type, model, build year, sail\nnumber and MMSI number.<\/li>\n<li>A boat belongs to a <strong>membership number<\/strong>. Everyone who shares that membership\nnumber is crew on the boat, so the crew group and the subscription follow the\nsame number \u2014 there is no separate crew table to keep in sync.<\/li>\n<li>The home harbour is picked from the shared harbour list and stored by id, so\nthe same harbour name cannot drift across boats.<\/li>\n<li>Members can maintain their own boat and crew from the core member profile \u2014\nno administrator needed.<\/li>\n<li>When a core member is deleted their boat is removed only if they were the\nlast member on that membership number; otherwise the boat stays with the\nremaining crew.<\/li>\n<li>Boat Register admin page at <code>\/vis\/boats<\/code>, access-controlled by the\n  vis_boat_manage capability (granted to Editor and Administrator on\nactivation).<\/li>\n<li>Harbours management page at <code>\/vis\/harbours<\/code> \u2014 list, create, edit, and delete\nharbours on a map, with duplicate-name protection and delete-guard against\nharbours still in use.<\/li>\n<li>Boat name appears in the core member list; clicking it opens a read-only\npopup with the full boat details and the crew group.<\/li>\n<\/ul>\n\n<p>This plugin stores all its data locally in two custom database tables. It does not\ncommunicate with any external service, apart from the harbour map tiles listed\nunder <strong>External services<\/strong> below.<\/p>\n\n<h3>Uninstall<\/h3>\n\n<p>Deleting the plugin from <strong>Plugins<\/strong> removes its <code>pcio_me_boat_db_version<\/code> option, so a reinstall rebuilds the tables from scratch.<\/p>\n\n<p>The database tables are deliberately <strong>kept<\/strong>, because they hold your club's boat register and harbour list. These tables survive:<\/p>\n\n<ul>\n<li><code>{prefix}me_boat_boats<\/code><\/li>\n<li><code>{prefix}me_boat_harbours<\/code><\/li>\n<\/ul>\n\n<p>If you want a full wipe, drop both tables manually from phpMyAdmin or a SQL client. Also delete the leftover <code>{prefix}me_boat_crew<\/code> table if your site was created before 1.1 \u2014 it is no longer used and is dropped automatically on the 1.1 upgrade.<\/p>\n\n<h3>External services<\/h3>\n\n<p>The plugin itself makes no outbound requests: all boat, harbour and member data stays in your local database, no analytics or tracking is included, and no account with any third party is required.<\/p>\n\n<p>The one exception is the harbour map on <code>\/vis\/boats<\/code> and <code>\/vis\/harbours<\/code>, which displays map tiles in your browser:<\/p>\n\n<ul>\n<li><strong>OpenStreetMap<\/strong> \u2014 <code>https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png<\/code>. Your browser's IP address is visible to OpenStreetMap, along with the map area you pan to. No boat or member data is sent. Their <a href=\"https:\/\/operations.osmfoundation.org\/policies\/tiles\/\">tile usage policy<\/a> applies.<\/li>\n<li><strong>OpenSeaMap<\/strong> \u2014 <code>https:\/\/tiles.openseamap.org\/seamark\/{z}\/{x}\/{y}.png<\/code>, a transparent overlay of seamarks. Same conditions as above; see the <a href=\"https:\/\/openseamap.org\">OpenSeaMap site<\/a>.<\/li>\n<\/ul>\n\n<p>The map is only used in wp-admin and requires the <code>vis_boat_manage<\/code> capability. You can replace both tile URLs in <code>assets\/harbour-map.js<\/code> and <code>assets\/harbours-admin.js<\/code> with your own tile server or a local tile set if you would rather not contact them at all.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Make sure <strong>PCIO VIS Member Event<\/strong> is installed and active.<\/li>\n<li>Upload the <code>pcio-vis-boat<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin in WordPress.<\/li>\n<li>Navigate to <code>\/vis\/boats<\/code> to start managing the boat register.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"where%20do%20i%20manage%20boats%3F\"><h3>Where do I manage boats?<\/h3><\/dt>\n<dd><p>Go to <code>\/vis\/boats<\/code> on the front end. A \"Boats\" link also appears in the Vis\nnavigation and as a tile on the <code>\/vis\/<\/code> landing page for users with the\n    vis_boat_manage capability.<\/p><\/dd>\n<dt id=\"where%20do%20i%20manage%20harbours%3F\"><h3>Where do I manage harbours?<\/h3><\/dt>\n<dd><p>Go to <code>\/vis\/harbours<\/code> on the front end. A \"Harbours\" link appears in the Vis\nnavigation and as a tile on the <code>\/vis\/<\/code> landing page for users with the\n    vis_boat_manage capability. A \"Vis \u2192 Harbours\" submenu in wp-admin redirects\nthere. Harbour names must be unique; existing duplicates are merged on upgrade.<\/p><\/dd>\n<dt id=\"can%20crew%20members%20see%20their%20own%20boats%3F\"><h3>Can crew members see their own boats?<\/h3><\/dt>\n<dd><p>Yes. <code>GET \/pcio-vis\/v1\/boat\/member\/{member_id}<\/code> returns the boat registered for\nthat member's membership number \u2014 an empty list when they have none, otherwise\none boat with a <code>crew<\/code> array listing everyone on that number. The endpoint is\navailable to administrators and to the member themselves when they are logged\nin. Members can also edit their own boat and add or remove crew at\n    \/vis\/members \u2192 their profile.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20send%20any%20data%20externally%3F\"><h3>Does this plugin send any data externally?<\/h3><\/dt>\n<dd><p>No boat, member or order data ever leaves your server. The only outbound requests are the OpenStreetMap and OpenSeaMap map tiles drawn by the harbour map in wp-admin \u2014 see <strong>External services<\/strong> below for the details.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20a%20member%20is%20deleted%20from%20the%20core%20plugin%3F\"><h3>What happens when a member is deleted from the core plugin?<\/h3><\/dt>\n<dd><p>If they were the only member on their membership number, the boat is deleted.\nIf other members still share that number, the boat is kept and stays with the\nremaining crew.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1<\/h4>\n\n<ul>\n<li>Added: <strong>Member boat profile.<\/strong> Signed-in members can now edit their own boat\nand manage their crew directly on the core member profile page, with no\nadministrator involved. New \"Boat details\" and \"Crew\" sections appear there,\nbacked by a new <code>[pcio_boat_edit_profile]<\/code> shortcode alias.<\/li>\n<li>Added: <strong>Crew management for members.<\/strong> New self-service routes\n  GET\/POST \/pcio-vis\/v1\/boat\/my-boat\/{id}\/crew and\n  DELETE \/pcio-vis\/v1\/boat\/my-boat\/{id}\/crew\/{member_id} let a boat owner add\nand remove crew. A new crew member is created in the core member register,\ngiven a WordPress login and the welcome email; an existing WordPress user\nwithout <code>vis_member<\/code> is accepted and promoted. Removing a crew member clears\ntheir membership number and revokes <code>vis_member<\/code>.<\/li>\n<li>Added: <strong>Boat detail popup<\/strong> in the core member list. The Boat cell is now a\nbutton that opens a read-only dialog with type, model, home harbour, build\nyear, sail number, MMSI, membership number, note and the full crew group.<\/li>\n<li>Added: <strong>Harbour list navigation<\/strong> \u2014 a \"Harbours\" entry in the Vis navigation\nand a tile on the <code>\/vis\/<\/code> landing page, both gated on <code>vis_boat_manage<\/code>.<\/li>\n<li>Added: <strong>Shortcode reference<\/strong> \u2014 the Boat plugins are documented in the core\nshortcode reference with a dedicated sidebar group.<\/li>\n<li>Changed: <strong>Crew is now the membership number.<\/strong> The <code>me_boat_crew<\/code> table is\ngone; every member carrying the boat's membership number is crew on that\nboat, so the crew group and the subscription always agree. A boat's owner\ncolumn is the membership number and is unique \u2014 one boat per membership\nnumber.<\/li>\n<li>Changed: <strong>Home harbour is stored by id.<\/strong> The free-text <code>home_harbour<\/code>\ncolumn is removed from <code>me_boat_boats<\/code> and the harbour name is resolved by\njoining the harbours table, so the same harbour cannot be spelled differently\non two boats. The sign-up form and the boat form now save only the selection;\ntyping free text without picking a harbour no longer stores a name.<\/li>\n<li>Changed: <strong>Harbour names are unique.<\/strong> A case-insensitive unique index is\nadded to <code>me_boat_harbours.name<\/code>, and any duplicates found on upgrade are\nmerged \u2014 boats are repointed to the surviving harbour before the duplicate rows\nare removed.<\/li>\n<li>Changed: <strong>Harbour picker is keyboard-navigable.<\/strong> The autocomplete supports\nArrow Up\/Down, Enter and Escape with <code>aria-activedescendant<\/code>, and editing the\ntext after picking clears the selection so a typo cannot save the wrong\nharbour.<\/li>\n<li>Changed: The Boat Register table shows a Crew column instead of an Owner\ncolumn, with each crew name linking to the member directory when the viewer\nis allowed to see it.<\/li>\n<li>Improved: Boat form validation now reports a missing boat name, an MMSI that\nis not exactly 9 digits, a build year outside 1900\u2013this year, and invalid\nharbour coordinates, inline on the offending field.<\/li>\n<li>Improved: The <code>\/shop\/accepted<\/code> style confirmation is unchanged, but a crew\nmember without their own subscription now inherits the shared membership's\nstatus instead of showing an unknown state.<\/li>\n<li>Security: a harbour placed on the map is now created only when the caller is\nentitled to it \u2014 a confirmed order for sign-ups, or a signed-in member for\nprofile saves. Previously a sign-up that completed without a payment (no\nactive membership product, or Stripe not configured) could write a harbour\nrow from the anonymous form post.<\/li>\n<li>Fixed: The harbour map could show no members for any harbour, because it\nmatched the boat's owner column against the member id while the rest of the\nplugin had moved to membership numbers.<\/li>\n<li>Fixed: Boats whose owner membership number no longer existed were silently\norphaned by the ownership check on the REST routes.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Added a Harbours management page at <code>\/vis\/harbours<\/code> (capability <code>vis_boat_manage<\/code>):\nlist, create, edit and delete harbours with a Leaflet draggable-marker map.<\/li>\n<li>Deleting a harbour that still has boats is blocked with a 409 response showing\nthe boat count; move the boats first.<\/li>\n<li>Creating or editing a harbour rejects duplicate names (case-insensitive) with a\n409 response, and a unique index on <code>me_boat_harbours.name<\/code> was added.<\/li>\n<li>\"Boats\" column on the management page shows the boat-row count for each harbour.<\/li>\n<li>A \"Vis \u2192 Harbours\" wp-admin submenu entry redirects to the front-end page.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Security: the harbour map endpoint that lists member names and membership\nnumbers now requires the <code>vis_member<\/code> capability instead of being public.<\/li>\n<li>Security: creating a shared harbour now requires the <code>vis_boat_manage<\/code>\ncapability. Harbours added on the map during sign-up are stored only after\nmembership is confirmed, removing the unauthenticated write path.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Extends PCIO VIS Member Event with a boat club register.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/366786","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=366786"}],"author":[{"embeddable":true,"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/pcio"}],"wp:attachment":[{"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=366786"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=366786"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=366786"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=366786"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=366786"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/vec.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=366786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}