Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
# Consistent line endings
* text=auto eol=lf
*.mo binary
*.woff2 binary
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ jobs:
cache: npm
- run: npm ci
- run: npm run format:check
- name: WireLayer CSS up to date
# assets/wirelayer/ is committed – it has to match the package version and the component list
run: |
npm run build:css
git diff --exit-code assets/wirelayer
test -z "$(git status --porcelain assets/wirelayer)"

plugin-check:
name: Plugin Check
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ db-data
vendor
dist
languages
assets/wirelayer
Binary file modified .wordpress-org/screenshot-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .wordpress-org/screenshot-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .wordpress-org/screenshot-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .wordpress-org/screenshot-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .wordpress-org/screenshot-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ WordPress plugin, published on wordpress.org (slug `wirecore-disable-rest`) and

- Static classes `WireCore_DR_*` in `includes/class-wirecore-dr-*.php`, no autoloader, no namespaces. Each class has an `init()` that registers its hooks.
- Prefix everything global: functions/options/hooks/nonces `wirecore_dr_`, constants `WIRECORE_DR_`, CSS classes/IDs `wirecore-dr-`, text domain `wirecore-disable-rest`, WP-CLI command `wp wirecore-dr`.
- Admin pages in plain PHP with `admin-post.php` forms, nonces, `wp_safe_redirect()` plus a notice query arg. No build step for JS/CSS.
- Admin pages in plain PHP with `admin-post.php` forms, nonces, `wp_safe_redirect()` plus a notice query arg. No build step for JS; the only CSS build is `npm run build:css` (below).
- UI in the WireLayer corporate design: the markup uses the `.wc-*` classes of `@wirecore/wirelayer-css` (class reference: `node_modules/@wirecore/wirelayer-css/llms-full.txt`). `npm run build:css` writes the used components, scoped to `#wirecore-dr`, to `assets/wirelayer/` – committed, CI checks it is up to date. Add a component to the list in `package.json` before using its classes, and run the command again after updating the package. `wirecore-dr-*` classes are hooks for `admin.js` and page layout in `assets/admin.css` (scoped to `#wirecore-dr`, colors and spacing from WireLayer variables). Icons are inline Lucide SVGs (`WireCore_DR_Admin::icon()`).
- Minimum versions: WordPress 5.8, PHP 7.4 (verified with PHPCompatibility and a WP 5.8/PHP 7.4 instance) – do not use newer functions without raising them.
- Formatting with Prettier (tabs, single quotes). Plugin Check must stay free of errors and warnings; justified exceptions are marked with `phpcs:ignore`/`phpcs:disable` plus a comment explaining why.

Expand Down Expand Up @@ -42,7 +43,7 @@ Only `wirecore-disable-rest.php`, `uninstall.php`, `index.php`, `readme.txt`, `L

## Checks

CI (`.github/workflows/ci.yml`) must stay green: PHP lint 7.4–8.4, `composer phpcs` (PHPCompatibilityWP, `phpcs.xml.dist`), PHPUnit on PHP 7.4 and 8.3, `npm run format:check`, Plugin Check in strict mode on the package built from `.distignore`.
CI (`.github/workflows/ci.yml`) must stay green: PHP lint 7.4–8.4, `composer phpcs` (PHPCompatibilityWP, `phpcs.xml.dist`), PHPUnit on PHP 7.4 and 8.3, `npm run format:check`, `assets/wirelayer/` up to date with `npm run build:css`, Plugin Check in strict mode on the package built from `.distignore`.

Tests live in `tests/` (`test-*.php`, base class `WireCore_DR_TestCase`). They are integration tests against the WordPress test suite: dispatch requests through `rest_get_server()->dispatch()` (the bootstrap defines `REST_REQUEST`), and register fixture routes in `tests/bootstrap.php` – the route list is cached, so routes must exist before the first REST server is created. Run them inside the Docker container (see README) against the separate database `wordpress_test`.

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,15 @@ Rules: `inherit`, `public`, `auth`, `admin`, `blocked` (`inherit` is not allowed

## Development

Requirements: Docker, Node.js (for Prettier).
Requirements: Docker, Node.js (for Prettier and the WireLayer CSS).

```bash
docker compose up -d # WordPress on http://localhost:8092, phpMyAdmin on :8093
npm install # Prettier with the PHP plugin
npm install # Prettier with the PHP plugin, @wirecore/wirelayer-css
```

The settings page uses the [WireLayer](https://github.com/WireCore/WireLayer) components (`.wc-*` classes). `npm run build:css` writes the components listed in `package.json`, scoped to `#wirecore-dr`, with their fonts to `assets/wirelayer/`. The output is committed, so the plugin needs no build step; run the command again after adding a component or updating `@wirecore/wirelayer-css`.

WP-CLI is available in the container:

```bash
Expand Down
251 changes: 144 additions & 107 deletions assets/admin.css
Original file line number Diff line number Diff line change
@@ -1,176 +1,213 @@
.wirecore-dr .wirecore-dr-status {
margin: 16px 0;
padding: 8px 12px;
background: #fff;
border-left: 4px solid #2271b1;
}
/*
* Layout of the settings page. The components come from WireLayer
* (assets/wirelayer/wirelayer.css, scoped to #wirecore-dr); colors and
* spacing use its variables.
*/

.wirecore-dr .wirecore-dr-default label {
margin-right: 16px;
/* WordPress styles form controls and links by element (forms.css, common.css);
inside the page the WireLayer components style them */
#wirecore-dr :is(a, button, input, select, textarea) {
box-shadow: none;
min-height: 0;
max-width: none;
}

.wirecore-dr .wirecore-dr-presets .button {
margin-right: 4px;
#wirecore-dr select {
background-image: none;
}

.wirecore-dr .wirecore-dr-toolbar {
#wirecore-dr {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 12px;
flex-direction: column;
gap: 20px;
max-width: 1200px;
margin-top: 12px;
background: transparent;
font-size: 14px;
}

.wirecore-dr .wirecore-dr-toolbar input[type='search'] {
min-width: 280px;
}

.wirecore-dr .wirecore-dr-namespace {
margin-bottom: 8px;
background: #fff;
border: 1px solid #c3c4c7;
#wirecore-dr .wirecore-dr-stack {
display: flex;
flex-direction: column;
gap: 16px;
}

.wirecore-dr .wirecore-dr-namespace-head {
#wirecore-dr .wirecore-dr-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px;
padding: 6px 10px;
gap: 8px 12px;
}

.wirecore-dr .wirecore-dr-toggle {
display: flex;
/* A label in front of its control: "Read [select]" */
#wirecore-dr .wirecore-dr-labeled {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 0;
background: none;
border: 0;
cursor: pointer;
gap: 8px;
color: var(--wc-muted);
font-size: 13px;
font-weight: 500;
}

.wirecore-dr .wirecore-dr-toggle .dashicons {
transition: transform 0.15s;
#wirecore-dr .wirecore-dr-rule {
width: 10rem;
}

.wirecore-dr .wirecore-dr-toggle[aria-expanded='true'] .dashicons {
transform: rotate(90deg);
#wirecore-dr .wirecore-dr-search {
width: 280px;
}

.wirecore-dr .wirecore-dr-meta {
color: #646970;
#wirecore-dr .wirecore-dr-filter {
width: 12rem;
}

.wirecore-dr .wirecore-dr-selects {
margin-left: auto;
/* Form fields in a card keep a readable width */
#wirecore-dr .wc-card > .wc-field {
max-width: 40rem;
}

.wirecore-dr .wirecore-dr-routes {
border-width: 1px 0 0;
#wirecore-dr .wc-card > .wirecore-dr-narrow {
max-width: 24rem;
}

.wirecore-dr .wirecore-dr-routes code {
word-break: break-all;
#wirecore-dr input[type='file']::file-selector-button {
margin-inline-end: 10px;
padding: 4px 12px;
border: 1px solid var(--wc-line-strong);
border-radius: 999px;
background: var(--wc-bg);
color: var(--wc-fg);
font-weight: 600;
cursor: pointer;
}

.wirecore-dr .wirecore-dr-badge {
display: inline-block;
margin: 2px 4px 2px 0;
padding: 1px 6px;
border-radius: 3px;
font-size: 12px;
white-space: nowrap;
background: #f0f0f1;
#wirecore-dr .wirecore-dr-checkbox-title {
display: block;
color: var(--wc-fg);
font-weight: 600;
}

.wirecore-dr .wirecore-dr-badge-public {
background: #edfaef;
color: #00631a;
#wirecore-dr .wirecore-dr-list {
display: flex;
flex-direction: column;
gap: 8px;
padding-inline-start: 1.25rem;
list-style: disc;
line-height: 1.6;
}

.wirecore-dr .wirecore-dr-badge-auth,
.wirecore-dr .wirecore-dr-badge-admin {
background: #fcf9e8;
color: #8a6d00;
#wirecore-dr .wirecore-dr-hint {
margin-inline-end: auto;
color: var(--wc-muted);
font-size: 13px;
}

.wirecore-dr .wirecore-dr-badge-blocked {
background: #fcf0f1;
color: #8a2424;
/* Routes: one card per namespace, the routes as a table below its header */
#wirecore-dr .wirecore-dr-namespaces {
gap: 10px;
}

.wirecore-dr .wirecore-dr-orphans {
margin-top: 8px;
#wirecore-dr .wirecore-dr-namespace {
gap: 0;
padding: 0;
}

#wirecore-dr .wirecore-dr-namespace-head {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
padding: 10px 16px;
}

.wirecore-dr .wirecore-dr-spinner {
float: none;
margin: 0 6px 0 0;
#wirecore-dr .wirecore-dr-toggle {
display: inline-flex;
align-items: center;
gap: 6px;
border-radius: var(--radius-sm);
cursor: pointer;
}

.wirecore-dr .wirecore-dr-selects label {
margin-left: 8px;
#wirecore-dr .wirecore-dr-toggle:focus-visible {
outline: 2px solid var(--wc-fg);
outline-offset: 2px;
}

.wirecore-dr .wirecore-dr-badge-ip {
background: #f0f6fc;
color: #0a4b78;
#wirecore-dr .wirecore-dr-toggle-icon {
width: 16px;
height: 16px;
color: var(--wc-muted);
transition: rotate 0.15s;
}

.wirecore-dr .wirecore-dr-advanced-wrap {
margin-left: 8px;
#wirecore-dr
.wirecore-dr-toggle[aria-expanded='true']
.wirecore-dr-toggle-icon {
rotate: 90deg;
}

.wirecore-dr .wirecore-dr-access-summary .wirecore-dr-badge {
margin-left: 4px;
@media (prefers-reduced-motion: reduce) {
#wirecore-dr .wirecore-dr-toggle-icon {
transition: none;
}
}

.wirecore-dr .wirecore-dr-dialog {
width: min(760px, 90vw);
padding: 16px 24px;
border: 1px solid #c3c4c7;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2);
#wirecore-dr .wirecore-dr-meta {
color: var(--wc-muted);
font-size: 13px;
}

.wirecore-dr .wirecore-dr-dialog::backdrop {
background: rgba(0, 0, 0, 0.4);
#wirecore-dr .wirecore-dr-selects {
display: flex;
flex-wrap: wrap;
gap: 8px 16px;
margin-inline-start: auto;
}

.wirecore-dr .wirecore-dr-dialog h2 {
margin-top: 0;
#wirecore-dr .wirecore-dr-routes {
border-top: 1px solid var(--wc-line);
}

.wirecore-dr .wirecore-dr-dialog-columns {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
#wirecore-dr .wirecore-dr-advanced-wrap,
#wirecore-dr .wirecore-dr-access-summary {
display: inline-flex;
flex-wrap: wrap;
align-items: center;
gap: 4px 6px;
}

.wirecore-dr .wirecore-dr-dialog fieldset {
padding: 8px 12px;
border: 1px solid #dcdcde;
#wirecore-dr .wirecore-dr-route .wirecore-dr-advanced-wrap {
margin-inline-start: 6px;
}

.wirecore-dr .wirecore-dr-dialog legend {
padding: 0 4px;
font-weight: 600;
#wirecore-dr .wirecore-dr-effective .wc-badge {
margin: 2px 4px 2px 0;
}

.wirecore-dr .wirecore-dr-dialog textarea,
.wirecore-dr .wirecore-dr-dialog input[type='text'] {
display: block;
width: 100%;
margin: 4px 0 12px;
/* "Advanced" dialog */
#wirecore-dr .wirecore-dr-columns {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
margin-top: 8px;
}

.wirecore-dr .wirecore-dr-dialog-label {
margin: 0 0 4px;
#wirecore-dr .wirecore-dr-columns > .wc-fieldset {
display: flex;
flex-direction: column;
gap: 12px;
}

.wirecore-dr .wirecore-dr-role {
display: block;
margin-bottom: 2px;
#wirecore-dr #wirecore-dr-advanced .wc-dialog-content {
width: min(760px, calc(100vw - 2rem));
}

.wirecore-dr .wirecore-dr-dialog-actions {
margin-bottom: 0;
@media (max-width: 782px) {
#wirecore-dr .wirecore-dr-columns {
grid-template-columns: 1fr;
}

#wirecore-dr .wirecore-dr-selects {
margin-inline-start: 0;
}
}
Loading
Loading