Skip to content

Commit bc17096

Browse files
authored
Merge pull request #7 from vapvarun/docs/1.4.x-coverage
docs(website): cover 1.4.x features + clear stale references
2 parents db4ff20 + e4d802a commit bc17096

16 files changed

Lines changed: 1328 additions & 14 deletions

docs/website/admin-settings/01-general.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Turn this off if your community is members-only and you do not want any content
7272
**Default:** `true` (on)
7373
**Location:** General tab → Access section
7474

75-
When enabled, any action that writes data (posting, replying, voting, following) requires the user to be logged in. Guests are redirected to the WordPress login page.
75+
When enabled, any action that writes data (posting, replying, voting, following) requires the user to be logged in. Guests are routed to Jetonomy's in-page sign-in form (no wp-login.php bounce) and returned to whatever they were doing once they sign in.
7676

7777
This is always recommended on. Disable it only if you are running a very specific open-participation setup where anonymous contributions make sense.
7878

docs/website/admin-settings/04-appearance.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,50 @@ When on, the `--jt-accent` token pulls from `--wp--preset--color--primary` in yo
4949

5050
Turn this off if you have set a custom accent color above and do not want theme updates to override it.
5151

52+
## Layout
53+
54+
Jetonomy 1.4.0 added a Layout panel with three controls that decide how the community canvas sits inside your active theme. Every option defaults to **Theme Default**, so existing installs see no visual change after the upgrade. When you do change a value, Jetonomy emits a small block of CSS scoped to `body.jt-page` - the rules only apply on community routes and never leak into the rest of your site.
55+
56+
### Container Width
57+
58+
**Setting:** `container_width`
59+
**Default:** Theme Default
60+
**Options:** Theme Default, Full Width, Custom (px)
61+
**Location:** Appearance tab → Layout section
62+
63+
Controls how wide the community canvas can grow before it stops expanding.
64+
65+
- **Theme Default** - Inherits the host theme's content container width. Use this when your theme's reading width already feels right.
66+
- **Full Width** - Lets the community stretch edge-to-edge of the viewport. Best for kanban-style spaces, leaderboards, and dense feeds that benefit from horizontal room.
67+
- **Custom (px)** - Pins the canvas to a specific pixel width (e.g. `1280`). Useful when you want a wider reading column than the theme provides without going fully edge-to-edge.
68+
69+
### Theme Sidebar
70+
71+
**Setting:** `theme_sidebar`
72+
**Default:** Theme Default
73+
**Options:** Theme Default, Hide on community pages
74+
**Location:** Appearance tab → Layout section
75+
76+
Decides whether the host theme's sidebar shows on community routes.
77+
78+
- **Theme Default** - Leaves the theme's sidebar exactly where the theme renders it.
79+
- **Hide on community pages** - Suppresses the host theme's sidebar across `/community/*` so the forum renders at full width even when the rest of the site has a sidebar everywhere. Pair this with **Full Width** above when you want a true full-bleed community experience.
80+
81+
### Page Padding
82+
83+
**Setting:** `page_padding`
84+
**Default:** Theme Default
85+
**Options:** Theme Default, None, Comfortable
86+
**Location:** Appearance tab → Layout section
87+
88+
Adjusts the inline padding around the community canvas.
89+
90+
- **Theme Default** - Uses whatever inline padding the theme provides.
91+
- **None** - Removes the inline padding so the community sits flush against the viewport edges. Good for themes that already hug the edges.
92+
- **Comfortable** - Adds a generous inline padding. Useful for themes that hug the edges too tightly and leave content butting against the screen on mobile.
93+
94+
> **Tip:** If your theme has a sidebar everywhere but you want the community to feel like a standalone app, set **Container Width** to Full Width, **Theme Sidebar** to Hide on community pages, and **Page Padding** to Comfortable. The rest of your site keeps the original theme layout.
95+
5296
## Layout Density
5397

5498
**Setting:** `layout_density`

docs/website/admin-settings/05-seo.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ Private, hidden, and archived spaces are excluded. Draft and scheduled posts are
4545

4646
> **Tip:** Check **Settings → Reading → Search engine visibility** is not set to "Discourage search engines" or your sitemap will be disregarded.
4747
48+
### Sitemap Link
49+
50+
**Location:** SEO tab → Sitemap section
51+
52+
Right next to the toggle is a button that surfaces the live sitemap URL for your install (typically `https://example.com/wp-sitemap.xml`). Copy the URL straight from the admin and submit it to:
53+
54+
- [Google Search Console](https://search.google.com/search-console) - the standard sitemap submission flow under Index → Sitemaps
55+
- [Bing Webmaster Tools](https://www.bing.com/webmasters) - submit under Sitemaps in the left nav
56+
57+
You only need to submit the sitemap once per search engine. Google and Bing both recrawl the file automatically after the first submission, so new posts and spaces appear in the index without any further action.
58+
4859
## Schema Markup
4960

5061
**Setting:** `seo_schema`
@@ -107,6 +118,35 @@ Jetonomy outputs Open Graph and Twitter Card meta tags automatically on all publ
107118

108119
> **Note:** If you use an SEO plugin like Yoast SEO, RankMath, or The SEO Framework, its OG tags may override Jetonomy's. This is fine - SEO plugin output takes priority via standard WordPress `wp_head` hook priority ordering.
109120
121+
### Twitter / X Handle
122+
123+
**Setting:** `seo_twitter_handle`
124+
**Default:** Empty
125+
**Location:** SEO tab → Twitter handle
126+
127+
Enter your community's Twitter or X handle (with or without the leading `@`). When set, Jetonomy emits `twitter:site` and `twitter:creator` meta tags on every community page that does not already declare a per-page override. This gives X / Twitter a verified attribution to display alongside link previews and unlocks richer card layouts.
128+
129+
Leave this empty if the community has no Twitter / X presence - Jetonomy simply omits the tags instead of emitting empty ones.
130+
131+
### Default Share Image
132+
133+
**Setting:** `seo_default_share_image`
134+
**Default:** Empty
135+
**Location:** SEO tab → Default share image
136+
137+
Pick an image from the WordPress media library to use as the fallback `og:image` whenever a specific post does not have an image of its own. Posts that already include their own image continue to use that image - this setting only kicks in when there is nothing else to show.
138+
139+
**Recommended specs:**
140+
141+
| Property | Value |
142+
|---|---|
143+
| Dimensions | 1200 x 630 px |
144+
| Format | PNG or JPG |
145+
| File size | Under 5 MB |
146+
| Aspect ratio | 1.91:1 |
147+
148+
Twitter / X, Facebook, LinkedIn, and Slack all read this image when generating link previews, so picking a branded fallback (logo + community name on a clean background) keeps shared links recognizable.
149+
110150
## What's Next?
111151

112152
Set up anti-spam protection to keep your community clean without frustrating legitimate members.
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
Jetonomy 1.4.1 introduced the **Public / Private community toggle** documented in [Access Control Settings](../admin-settings/07-access-control.md). On the code side that toggle is enforced through two pieces:
2+
3+
1. A small helper class - `Jetonomy\Visibility` - that every front-end template and REST permission callback can call to decide "is this caller allowed to see community content right now?"
4+
2. A shell script - `bin/access-matrix-check.sh` - that walks every public REST route as every role in both modes and asserts the responses match the documented contract.
5+
6+
This page covers both.
7+
8+
**Namespace:** `Jetonomy\`
9+
**Source:** `includes/class-visibility.php`, `bin/access-matrix-check.sh`
10+
11+
---
12+
13+
## Why the helper exists
14+
15+
Before 1.4.1 the public/private check was sprinkled across templates, the template loader, and individual REST controllers. Each call site had its own "is the community private and the user a guest?" expression, and any new endpoint had to remember to repeat the pattern. The fastest way to ship a leak was to forget the check.
16+
17+
`Jetonomy\Visibility` consolidates that into one read of `jetonomy_settings.guest_read`. The front-end template loader and every public-read REST endpoint route through the same helper, so they answer the same question with the same logic. New endpoints opt into the gate with a single line.
18+
19+
The helper deliberately does **not** look at per-resource visibility (private spaces, blocked users, restricted posts). Those remain the responsibility of individual controllers - `Visibility` only answers the global "can this caller see ANY community content right now?" question.
20+
21+
---
22+
23+
## API Reference
24+
25+
### `Visibility::can_view_community()`
26+
27+
Returns `true` if the current request should be allowed to see community content, `false` otherwise. In public mode this is always `true`. In private mode it requires the caller to be authenticated.
28+
29+
**Returns:** `bool`
30+
31+
**Example - gating a custom template fragment:**
32+
33+
```php
34+
add_action( 'jetonomy_sidebar_before', function () {
35+
if ( ! \Jetonomy\Visibility::can_view_community() ) {
36+
return;
37+
}
38+
echo do_shortcode( '[my_member_only_widget]' );
39+
} );
40+
```
41+
42+
The check is global, not per-resource - you do not need to pass a user ID or a post ID. Per-resource visibility (private spaces, restricted access rules) is enforced separately inside the relevant controllers.
43+
44+
---
45+
46+
### `Visibility::get_mode()`
47+
48+
Returns the active visibility mode as a string. Useful when you want to render a different UI in private mode (e.g. a "Members only" badge in the site header) without duplicating the option read.
49+
50+
**Returns:** `string` - `'public'` or `'private'`
51+
52+
**Example - tagging the body class:**
53+
54+
```php
55+
add_filter( 'body_class', function ( array $classes ): array {
56+
$classes[] = 'jt-mode-' . \Jetonomy\Visibility::get_mode();
57+
return $classes;
58+
} );
59+
```
60+
61+
The function defaults to `'public'` on a fresh install - an unset, null, or `true` value of `guest_read` all resolve to public. Only an explicit `false` flips the community to private.
62+
63+
---
64+
65+
### `Visibility::rest_check()`
66+
67+
Designed to be used as a REST `permission_callback`. Returns `true` when the caller may proceed, or a 401 `WP_Error` with code `community_private` when the community is in private mode and the caller is not logged in.
68+
69+
**Returns:** `true|\WP_Error`
70+
71+
**Example - protecting your own REST route:**
72+
73+
```php
74+
register_rest_route( 'my-plugin/v1', '/community-events', [
75+
'methods' => 'GET',
76+
'callback' => 'my_plugin_list_events',
77+
'permission_callback' => [ '\Jetonomy\Visibility', 'rest_check' ],
78+
] );
79+
```
80+
81+
**Example - chaining with an existing capability check:**
82+
83+
```php
84+
'permission_callback' => static function ( $request ) {
85+
$vis = \Jetonomy\Visibility::rest_check( $request );
86+
if ( is_wp_error( $vis ) ) {
87+
return $vis;
88+
}
89+
return current_user_can( 'read' );
90+
},
91+
```
92+
93+
Anonymous calls in private mode return:
94+
95+
```json
96+
{
97+
"code": "community_private",
98+
"message": "This community is private. Please log in to view content.",
99+
"data": { "status": 401 }
100+
}
101+
```
102+
103+
Authenticated calls fall through to your route's own permission logic.
104+
105+
> **Note:** `/auth/*` and `/admin/*` endpoints intentionally do not route through this helper. Locking `/auth/*` would lock users out forever, and admin endpoints have their own capability gates. Apply `Visibility::rest_check` to public-read endpoints only.
106+
107+
---
108+
109+
## The Access Matrix Runner
110+
111+
`bin/access-matrix-check.sh` is the regression safety net that proves the helper actually works. It walks a representative subset of every Jetonomy REST route as every role, makes the real HTTP call, and asserts the response code matches the documented expectation.
112+
113+
### What it covers
114+
115+
- **78 checks** across the public REST surface
116+
- **6 roles** - anonymous, subscriber, author, editor (space-admin), moderator, administrator
117+
- **Both modes** - the runner can flip `jetonomy_settings.guest_read` to private for the duration of the run and restore it on exit (even if a check fails midway)
118+
119+
In public mode the runner asserts that anonymous reads return `200`. In private mode it asserts the same anonymous reads return `401` from the central `Visibility::rest_check` gate. Logged-in calls are mode-independent and stay unchanged in either mode.
120+
121+
### Running it locally
122+
123+
```bash
124+
# From the plugin root:
125+
bin/access-matrix-check.sh # public mode (default)
126+
bin/access-matrix-check.sh --mode=private # private community gate
127+
bin/access-matrix-check.sh --quiet # only show failures
128+
```
129+
130+
Sample output:
131+
132+
```
133+
PASS GET /spaces [anon] expected=200 got=200
134+
PASS GET /spaces [subscriber] expected=200 got=200
135+
PASS POST /posts/123/vote [anon] expected=401 got=401
136+
FAIL GET /posts/recent [anon] expected=401 got=200 <- regression
137+
138+
Summary: 77 passed, 1 failed (78 total)
139+
```
140+
141+
A regression is any row where the actual response code does not match the documented expectation. Exit code is `0` on a clean run, `1` if any row fails.
142+
143+
### Release gating
144+
145+
`bin/build-release.sh` invokes the access matrix runner before producing the release zip. If any row regresses, the build aborts and no zip is produced - the gate exists so we never ship a release that quietly opens up a previously-locked endpoint or quietly locks a previously-open one.
146+
147+
Run the matrix locally before every commit that touches `permission_callback` wiring, the `Visibility` helper, or REST route registration.
148+
149+
---
150+
151+
## What's Next?
152+
153+
- [Hooks Reference](./02-hooks-reference.md) - All `jetonomy_*` actions and filters
154+
- [REST API Reference](./01-rest-api.md) - Full endpoint listing with permission contracts
155+
- [Modal Toolkit](./09-modal-toolkit.md) - Front-end `jetonomyConfirm` / `jetonomyAlert` / `jetonomyPrompt` API

0 commit comments

Comments
 (0)