Compare commits
48 Commits
df7f303ffb
...
bugfix/iss
| Author | SHA1 | Date | |
|---|---|---|---|
| 29622dd54c | |||
| 1afa6b71d7 | |||
| 8bb4784204 | |||
| b223165012 | |||
| 4228bcc330 | |||
| 7bac0dc63d | |||
| 7c272b5399 | |||
| 81e5b14604 | |||
| 9dca8880cc | |||
| ad03358e2a | |||
| 7d0ee0adea | |||
| 9fdfa7a8a9 | |||
| d6dcda908c | |||
| 7640f01d0c | |||
| 632dda5952 | |||
| 8fda3f1163 | |||
| 79f78882a6 | |||
| e1ee99ac9c | |||
| 6300f1c545 | |||
| c3738a3106 | |||
| e5d2994e40 | |||
| 7eb7aedc39 | |||
| 9cddf28c09 | |||
| a1e5b166ff | |||
| 79829ddce0 | |||
| ef43525c4a | |||
| 708acc39de | |||
| 40f6f596fa | |||
| 0b17fe8ad9 | |||
| a8f968562c | |||
| 595855ce10 | |||
| 1d41af86c3 | |||
| a6db436a48 | |||
| 4a817ab231 | |||
| 1f96fe9965 | |||
| 5d148f8af9 | |||
| 0e906eb981 | |||
| 02a635f72c | |||
| 6625e8ca4a | |||
| 52632ec322 | |||
| 1c1980bb22 | |||
| 41724f72c0 | |||
| 58f5f8f71b | |||
| a9d9c69b65 | |||
| b58036f3f5 | |||
| 3f695bb003 | |||
| 340628877c | |||
| 6684375ea3 |
@@ -8,8 +8,13 @@ This document provides guidance for AI assistants to help with code review for t
|
|||||||
|
|
||||||
Before submitting code for review, test it with WordPress Playground:
|
Before submitting code for review, test it with WordPress Playground:
|
||||||
|
|
||||||
* [ ] Test in single site environment: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=5)
|
* [ ] Test in single site environment:
|
||||||
* [ ] Test in multisite environment: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/multisite-blueprint.json&_t=18)
|
[Open in WordPress Playground][playground-single]
|
||||||
|
* [ ] Test in multisite environment:
|
||||||
|
[Open in WordPress Playground][playground-multisite]
|
||||||
|
|
||||||
|
[playground-single]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=5
|
||||||
|
[playground-multisite]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/multisite-blueprint.json&_t=18
|
||||||
* [ ] Verify plugin functionality works in both environments
|
* [ ] Verify plugin functionality works in both environments
|
||||||
* [ ] Check for any JavaScript errors in the browser console
|
* [ ] Check for any JavaScript errors in the browser console
|
||||||
* [ ] Run Cypress tests locally: `npm run test:playground:single` and `npm run test:playground:multisite`
|
* [ ] Run Cypress tests locally: `npm run test:playground:single` and `npm run test:playground:multisite`
|
||||||
@@ -257,10 +262,20 @@ In function `handle_remove_reference()`:
|
|||||||
3. The success message should be translatable:
|
3. The success message should be translatable:
|
||||||
```php
|
```php
|
||||||
// Change this:
|
// Change this:
|
||||||
add_settings_error('fpden', 'fpden_removed', 'Plugin reference removed successfully.', 'updated');
|
add_settings_error(
|
||||||
|
'fpden',
|
||||||
|
'fpden_removed',
|
||||||
|
'Plugin reference removed successfully.',
|
||||||
|
'updated'
|
||||||
|
);
|
||||||
|
|
||||||
// To this:
|
// To this:
|
||||||
add_settings_error('fpden', 'fpden_removed', __('Plugin reference removed successfully.', 'fix-plugin-does-not-exist-notices'), 'updated');
|
add_settings_error(
|
||||||
|
'fpden',
|
||||||
|
'fpden_removed',
|
||||||
|
__( 'Plugin reference removed successfully.', 'fix-plugin-does-not-exist-notices' ),
|
||||||
|
'updated'
|
||||||
|
);
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -23,34 +23,39 @@ AI assistants can directly monitor GitHub Actions workflows using the GitHub API
|
|||||||
|
|
||||||
This helps identify failures and diagnose issues:
|
This helps identify failures and diagnose issues:
|
||||||
|
|
||||||
```
|
```text
|
||||||
github-api /repos/{owner}/{repo}/actions/runs
|
github-api /repos/{owner}/{repo}/actions/runs
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Step-by-Step Process
|
#### Step-by-Step Process
|
||||||
|
|
||||||
1. **Get Recent Workflow Runs**:
|
1. **Get Recent Workflow Runs**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Filter for Failed Runs**:
|
2. **Filter for Failed Runs**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs?status=failure
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs?status=failure
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Get Details for a Specific Run**:
|
3. **Get Details for a Specific Run**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs/{run_id}
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs/{run_id}
|
||||||
```
|
```
|
||||||
|
|
||||||
4. **Get Jobs for a Workflow Run**:
|
4. **Get Jobs for a Workflow Run**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs/{run_id}/jobs
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/runs/{run_id}/jobs
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Analyze Job Logs** (if accessible via API):
|
5. **Analyze Job Logs** (if accessible via API):
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/jobs/{job_id}/logs
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/jobs/{job_id}/logs
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -61,6 +66,7 @@ github-api /repos/{owner}/{repo}/actions/runs
|
|||||||
**Error**: `Missing download info for actions/upload-artifact@v3`
|
**Error**: `Missing download info for actions/upload-artifact@v3`
|
||||||
|
|
||||||
**Solution**: Update to the latest version of the action:
|
**Solution**: Update to the latest version of the action:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
```
|
```
|
||||||
@@ -70,7 +76,8 @@ uses: actions/upload-artifact@v4
|
|||||||
**Error**: `The current host is 127.0.0.1:8888, but WordPress multisites do not support custom ports.`
|
**Error**: `The current host is 127.0.0.1:8888, but WordPress multisites do not support custom ports.`
|
||||||
|
|
||||||
**Solution**: Use port 80 for multisite environments:
|
**Solution**: Use port 80 for multisite environments:
|
||||||
```yaml
|
|
||||||
|
```bash
|
||||||
npx @wp-playground/cli server --blueprint playground/multisite-blueprint.json --port 80 --login &
|
npx @wp-playground/cli server --blueprint playground/multisite-blueprint.json --port 80 --login &
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -79,6 +86,7 @@ npx @wp-playground/cli server --blueprint playground/multisite-blueprint.json --
|
|||||||
**Error**: Invalid path syntax for artifacts
|
**Error**: Invalid path syntax for artifacts
|
||||||
|
|
||||||
**Solution**: Use multi-line format for better readability:
|
**Solution**: Use multi-line format for better readability:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
path: |
|
path: |
|
||||||
cypress/videos
|
cypress/videos
|
||||||
@@ -90,6 +98,7 @@ path: |
|
|||||||
**Problem**: Redundant workflow runs when multiple commits land quickly
|
**Problem**: Redundant workflow runs when multiple commits land quickly
|
||||||
|
|
||||||
**Solution**: Add concurrency control to cancel in-progress runs:
|
**Solution**: Add concurrency control to cancel in-progress runs:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
concurrency:
|
concurrency:
|
||||||
group: playground-tests-${{ github.ref }}
|
group: playground-tests-${{ github.ref }}
|
||||||
@@ -125,16 +134,19 @@ npm run test:playground:multisite
|
|||||||
### Capturing and Analyzing Test Output
|
### Capturing and Analyzing Test Output
|
||||||
|
|
||||||
1. **Run Tests with Output Capture**:
|
1. **Run Tests with Output Capture**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run test:single > test-output.log 2>&1
|
npm run test:single > test-output.log 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Analyze Output for Errors**:
|
2. **Analyze Output for Errors**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat test-output.log | grep -i 'error\|fail\|exception'
|
grep -E -i '\b(error|fail|exception)' test-output.log
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Parse Structured Test Results** (if available):
|
3. **Parse Structured Test Results** (if available):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat cypress/results/results.json
|
cat cypress/results/results.json
|
||||||
```
|
```
|
||||||
@@ -146,6 +158,7 @@ npm run test:playground:multisite
|
|||||||
**Error**: `The current host is 127.0.0.1:8888, but WordPress multisites do not support custom ports.`
|
**Error**: `The current host is 127.0.0.1:8888, but WordPress multisites do not support custom ports.`
|
||||||
|
|
||||||
**Solution**: Modify the port in the blueprint or test configuration:
|
**Solution**: Modify the port in the blueprint or test configuration:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"features": {
|
"features": {
|
||||||
@@ -159,6 +172,7 @@ npm run test:playground:multisite
|
|||||||
**Error**: `Timed out retrying after 4000ms: expected '<body...>' to have class 'wp-admin'`
|
**Error**: `Timed out retrying after 4000ms: expected '<body...>' to have class 'wp-admin'`
|
||||||
|
|
||||||
**Solution**: Update selectors to be more robust and handle login states:
|
**Solution**: Update selectors to be more robust and handle login states:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
cy.get('body').then(($body) => {
|
cy.get('body').then(($body) => {
|
||||||
if ($body.hasClass('login')) {
|
if ($body.hasClass('login')) {
|
||||||
@@ -199,16 +213,19 @@ npm run lint:css
|
|||||||
### Parsing Code Quality Tool Output
|
### Parsing Code Quality Tool Output
|
||||||
|
|
||||||
1. **Run Code Quality Check**:
|
1. **Run Code Quality Check**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer run phpcs > phpcs-output.log 2>&1
|
composer run phpcs > phpcs-output.log 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Analyze Output for Errors**:
|
2. **Analyze Output for Errors**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat phpcs-output.log | grep -i 'ERROR\|WARNING'
|
grep -E -i '\b(ERROR|WARNING)' phpcs-output.log
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Automatically Fix Issues** (when possible):
|
3. **Automatically Fix Issues** (when possible):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer run phpcbf
|
composer run phpcbf
|
||||||
```
|
```
|
||||||
@@ -221,13 +238,13 @@ AI assistants can check these comments to identify and address issues.
|
|||||||
|
|
||||||
#### Accessing PR Comments via GitHub API
|
#### Accessing PR Comments via GitHub API
|
||||||
|
|
||||||
```
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{pull_number}/comments
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{pull_number}/comments
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Accessing PR Review Comments
|
#### Accessing PR Review Comments
|
||||||
|
|
||||||
```
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{pull_number}/reviews
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{pull_number}/reviews
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -236,7 +253,8 @@ github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{pul
|
|||||||
CodeRabbit provides AI-powered code review comments via the GitHub API.
|
CodeRabbit provides AI-powered code review comments via the GitHub API.
|
||||||
|
|
||||||
1. **Get PR Comments**:
|
1. **Get PR Comments**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{pull_number}/comments
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{pull_number}/comments
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -254,12 +272,14 @@ CodeRabbit provides AI-powered code review comments via the GitHub API.
|
|||||||
These tools provide automated code quality checks and post results as PR comments.
|
These tools provide automated code quality checks and post results as PR comments.
|
||||||
|
|
||||||
1. **Check PR Status Checks**:
|
1. **Check PR Status Checks**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/commits/{sha}/check-runs
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/commits/{sha}/check-runs
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Get Detailed Reports** (if available via API):
|
2. **Get Detailed Reports** (if available via API):
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/commits/{sha}/check-runs/{id}
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/commits/{sha}/check-runs/{id}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -275,7 +295,8 @@ These tools provide automated code quality checks and post results as PR comment
|
|||||||
SonarCloud provides detailed code quality and security analysis.
|
SonarCloud provides detailed code quality and security analysis.
|
||||||
|
|
||||||
1. **Check SonarCloud Status**:
|
1. **Check SonarCloud Status**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/commits/{sha}/check-runs?check_name=SonarCloud
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/commits/{sha}/check-runs?check_name=SonarCloud
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -293,6 +314,7 @@ SonarCloud provides detailed code quality and security analysis.
|
|||||||
**Error**: `ERROR: Expected snake_case for function name, but found camelCase`
|
**Error**: `ERROR: Expected snake_case for function name, but found camelCase`
|
||||||
|
|
||||||
**Solution**: Rename functions to follow snake_case convention:
|
**Solution**: Rename functions to follow snake_case convention:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
// Before
|
// Before
|
||||||
function getPluginVersion() { ... }
|
function getPluginVersion() { ... }
|
||||||
@@ -306,6 +328,7 @@ function get_plugin_version() { ... }
|
|||||||
**Error**: `ERROR: Missing doc comment for function`
|
**Error**: `ERROR: Missing doc comment for function`
|
||||||
|
|
||||||
**Solution**: Add proper docblocks:
|
**Solution**: Add proper docblocks:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
/**
|
/**
|
||||||
* Get the plugin version.
|
* Get the plugin version.
|
||||||
@@ -332,7 +355,8 @@ function get_plugin_version() { ... }
|
|||||||
#### Extracting Actionable Items from PR Comments
|
#### Extracting Actionable Items from PR Comments
|
||||||
|
|
||||||
1. **Collect All Feedback**:
|
1. **Collect All Feedback**:
|
||||||
```
|
|
||||||
|
```text
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{number}/comments
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{number}/comments
|
||||||
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{number}/reviews
|
github-api /repos/wpallstars/wp-plugin-starter-template-for-ai-coding/pulls/{number}/reviews
|
||||||
```
|
```
|
||||||
@@ -364,28 +388,14 @@ function get_plugin_version() { ... }
|
|||||||
|
|
||||||
### Complete Feedback Loop System
|
### Complete Feedback Loop System
|
||||||
|
|
||||||
```
|
```text
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
Code Changes ──► Local Testing ──► GitHub Actions
|
||||||
│ │ │ │ │ │
|
│ │ │
|
||||||
│ Code Changes │────▶│ Local Testing │────▶│ GitHub Actions │
|
▼ ▼ ▼
|
||||||
│ │ │ │ │ │
|
AI Assistant ◀── Error Analysis ◀── Status Check
|
||||||
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
|
│
|
||||||
│ │ │
|
▼
|
||||||
│ │ │
|
Fix Generation ──► Human Review (only when necessary)
|
||||||
│ │ │
|
|
||||||
┌────────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐
|
|
||||||
│ │ │ │ │ │
|
|
||||||
│ AI Assistant │◀────│ Error Analysis │◀────│ Status Check │
|
|
||||||
│ │ │ │ │ │
|
|
||||||
└────────┬────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
┌────────▼────────┐ ┌─────────────────┐
|
|
||||||
│ │ │ │
|
|
||||||
│ Fix Generation │────▶│ Human Review │ (only when necessary)
|
|
||||||
│ │ │ │
|
|
||||||
└─────────────────┘ └─────────────────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Key Components
|
### Key Components
|
||||||
@@ -409,7 +419,7 @@ These can be directly accessed and processed.
|
|||||||
|
|
||||||
#### Example CodeRabbit Feedback
|
#### Example CodeRabbit Feedback
|
||||||
|
|
||||||
```
|
```text
|
||||||
coderabbitai bot left a comment
|
coderabbitai bot left a comment
|
||||||
Actionable comments posted: 1
|
Actionable comments posted: 1
|
||||||
|
|
||||||
@@ -438,14 +448,14 @@ These tools provide structured feedback that can be systematically addressed.
|
|||||||
|
|
||||||
#### Example SonarCloud Feedback
|
#### Example SonarCloud Feedback
|
||||||
|
|
||||||
```
|
```text
|
||||||
SonarCloud Quality Gate failed
|
SonarCloud Quality Gate failed
|
||||||
- 3 Bugs
|
- 3 Bugs
|
||||||
- 5 Code Smells
|
- 5 Code Smells
|
||||||
- 1 Security Hotspot
|
- 1 Security Hotspot
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Processing Steps
|
#### SonarCloud Processing Steps
|
||||||
|
|
||||||
1. **Access Detailed Reports**:
|
1. **Access Detailed Reports**:
|
||||||
* Use the SonarCloud API or web interface
|
* Use the SonarCloud API or web interface
|
||||||
@@ -485,6 +495,78 @@ When consulting humans, provide:
|
|||||||
4. **Specific Questions**: Ask targeted questions rather than open-ended ones
|
4. **Specific Questions**: Ask targeted questions rather than open-ended ones
|
||||||
5. **Recommendations**: Suggest possible solutions for approval
|
5. **Recommendations**: Suggest possible solutions for approval
|
||||||
|
|
||||||
|
## Contributing to External Repositories
|
||||||
|
|
||||||
|
When issues are caused by bugs or missing features in external dependencies or GitHub Actions,
|
||||||
|
AI assistants can contribute fixes upstream.
|
||||||
|
|
||||||
|
### Workflow for External Contributions
|
||||||
|
|
||||||
|
1. **Clone the Repository Locally**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/Git
|
||||||
|
git clone https://github.com/owner/repo.git
|
||||||
|
cd repo
|
||||||
|
git checkout -b feature/descriptive-branch-name
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Make Changes and Commit**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make your changes
|
||||||
|
git add -A
|
||||||
|
git commit -m "Descriptive commit message
|
||||||
|
|
||||||
|
Detailed explanation of what the change does and why.
|
||||||
|
|
||||||
|
Fixes #issue-number"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Fork and Push**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a fork (if not already forked)
|
||||||
|
gh repo fork owner/repo --clone=false --remote=true
|
||||||
|
|
||||||
|
# Add fork as remote
|
||||||
|
git remote add fork https://github.com/your-username/repo.git
|
||||||
|
|
||||||
|
# Push to fork
|
||||||
|
git push fork feature/descriptive-branch-name
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Create Pull Request**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gh pr create \
|
||||||
|
--repo owner/repo \
|
||||||
|
--head your-username:feature/descriptive-branch-name \
|
||||||
|
--title "Clear, descriptive title" \
|
||||||
|
--body "## Summary
|
||||||
|
|
||||||
|
Description of changes...
|
||||||
|
|
||||||
|
Fixes #issue-number"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Best Practices for External Contributions
|
||||||
|
|
||||||
|
* Always clone to `~/Git/` for consistency
|
||||||
|
* Check existing issues and PRs before starting work
|
||||||
|
* Follow the project's contribution guidelines
|
||||||
|
* Keep changes focused and minimal
|
||||||
|
* Include tests if the project has a test suite
|
||||||
|
* Reference the issue number in commits and PR description
|
||||||
|
|
||||||
|
### Local Repository Management
|
||||||
|
|
||||||
|
Keep cloned repositories in `~/Git/` organized:
|
||||||
|
|
||||||
|
* `~/Git/wp-plugin-starter-template-for-ai-coding/` - Main project
|
||||||
|
* `~/Git/wp-performance-action/` - Forked for contributions
|
||||||
|
* Other cloned repos as needed
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
This error checking and feedback loop system creates a comprehensive framework for AI-driven development.
|
This error checking and feedback loop system creates a comprehensive framework for AI-driven development.
|
||||||
|
|||||||
17
.eslintrc.js
17
.eslintrc.js
@@ -2,8 +2,7 @@ module.exports = {
|
|||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
es2021: true,
|
es2021: true,
|
||||||
node: true,
|
node: true
|
||||||
'cypress/globals': true
|
|
||||||
},
|
},
|
||||||
extends: [
|
extends: [
|
||||||
'eslint:recommended'
|
'eslint:recommended'
|
||||||
@@ -16,9 +15,23 @@ module.exports = {
|
|||||||
sourceType: 'module'
|
sourceType: 'module'
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
|
'comma-dangle': ['error', 'always-multiline'],
|
||||||
'no-console': 'warn',
|
'no-console': 'warn',
|
||||||
'no-unused-vars': 'warn'
|
'no-unused-vars': 'warn'
|
||||||
},
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
// cypress.config.js uses CommonJS (require/module.exports).
|
||||||
|
// Override sourceType to 'script' so ESLint does not flag require as undefined.
|
||||||
|
files: ['cypress.config.js', 'cypress.config.cjs'],
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: 'script'
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
node: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
globals: {
|
globals: {
|
||||||
cy: 'readonly',
|
cy: 'readonly',
|
||||||
Cypress: 'readonly',
|
Cypress: 'readonly',
|
||||||
|
|||||||
24
.github/workflows/code-quality.yml
vendored
24
.github/workflows/code-quality.yml
vendored
@@ -1,8 +1,10 @@
|
|||||||
name: Code Quality
|
name: Code Quality
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
# Only run on push to main (not feature branches) to avoid duplicate runs.
|
||||||
|
# Feature branches get CI via pull_request trigger.
|
||||||
push:
|
push:
|
||||||
branches: [ main, feature/* ]
|
branches: [ main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -18,7 +20,7 @@ jobs:
|
|||||||
clean: 'true'
|
clean: 'true'
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2
|
||||||
with:
|
with:
|
||||||
php-version: '8.1'
|
php-version: '8.1'
|
||||||
extensions: mbstring, intl, zip
|
extensions: mbstring, intl, zip
|
||||||
@@ -27,11 +29,6 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: composer install --prefer-dist --no-progress
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
- name: Install WordPress Coding Standards
|
|
||||||
run: |
|
|
||||||
composer require --dev wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer
|
|
||||||
vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs
|
|
||||||
|
|
||||||
- name: Run PHPCS
|
- name: Run PHPCS
|
||||||
run: composer phpcs
|
run: composer phpcs
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -50,7 +47,7 @@ jobs:
|
|||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2
|
||||||
with:
|
with:
|
||||||
php-version: '8.1'
|
php-version: '8.1'
|
||||||
extensions: mbstring, intl, zip
|
extensions: mbstring, intl, zip
|
||||||
@@ -59,9 +56,6 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: composer install --prefer-dist --no-progress
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
- name: Install PHPStan WordPress stubs
|
|
||||||
run: composer require --dev szepeviktor/phpstan-wordpress
|
|
||||||
|
|
||||||
- name: Run PHPStan
|
- name: Run PHPStan
|
||||||
run: composer phpstan
|
run: composer phpstan
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -74,7 +68,7 @@ jobs:
|
|||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2
|
||||||
with:
|
with:
|
||||||
php-version: '8.1'
|
php-version: '8.1'
|
||||||
extensions: mbstring, intl, zip
|
extensions: mbstring, intl, zip
|
||||||
@@ -125,7 +119,7 @@ jobs:
|
|||||||
#
|
#
|
||||||
# - name: SonarCloud Scan
|
# - name: SonarCloud Scan
|
||||||
# if: steps.check_sonar_token.outputs.skip != 'true'
|
# if: steps.check_sonar_token.outputs.skip != 'true'
|
||||||
# uses: SonarSource/sonarqube-scan-action@master
|
# uses: SonarSource/sonarqube-scan-action@9598b8a83feef37de07f549027fab50ecffe6a6e # master
|
||||||
# env:
|
# env:
|
||||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
@@ -158,7 +152,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Run Codacy Analysis CLI
|
- name: Run Codacy Analysis CLI
|
||||||
uses: codacy/codacy-analysis-cli-action@v4
|
uses: codacy/codacy-analysis-cli-action@562ee3e92b8e92df8b67e0a5ff8aa8e261919c08 # v4
|
||||||
with:
|
with:
|
||||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||||
verbose: true
|
verbose: true
|
||||||
@@ -173,7 +167,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload SARIF results file
|
- name: Upload SARIF results file
|
||||||
if: steps.check_codacy_token.outputs.skip_upload != 'true'
|
if: steps.check_codacy_token.outputs.skip_upload != 'true'
|
||||||
uses: github/codeql-action/upload-sarif@v3
|
uses: github/codeql-action/upload-sarif@603b797f8b14b413fe025cd935a91c16c4782713 # v3
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|||||||
6
.github/workflows/phpunit.yml
vendored
6
.github/workflows/phpunit.yml
vendored
@@ -1,8 +1,10 @@
|
|||||||
name: PHPUnit Tests
|
name: PHPUnit Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
# Only run on push to main (not feature branches) to avoid duplicate runs.
|
||||||
|
# Feature branches get CI via pull_request trigger.
|
||||||
push:
|
push:
|
||||||
branches: [ main, feature/* ]
|
branches: [ main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -40,7 +42,7 @@ jobs:
|
|||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: ${{ matrix.php }}
|
||||||
extensions: dom, curl, libxml, mbstring, zip, pdo, mysql, pdo_mysql, bcmath, soap, intl, gd, exif, iconv
|
extensions: dom, curl, libxml, mbstring, zip, pdo, mysql, pdo_mysql, bcmath, soap, intl, gd, exif, iconv
|
||||||
|
|||||||
4
.github/workflows/playground-tests-fix.yml
vendored
4
.github/workflows/playground-tests-fix.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
|||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -98,7 +98,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Cypress artifacts
|
- name: Upload Cypress artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||||
with:
|
with:
|
||||||
name: cypress-playground-results
|
name: cypress-playground-results
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
22
.github/workflows/playground-tests.yml
vendored
22
.github/workflows/playground-tests.yml
vendored
@@ -8,8 +8,10 @@ name: WordPress Playground Tests
|
|||||||
# npm run playground:start:multisite
|
# npm run playground:start:multisite
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
# Only run on push to main (not feature branches) to avoid duplicate runs.
|
||||||
|
# Feature branches get CI via pull_request trigger.
|
||||||
push:
|
push:
|
||||||
branches: [ main, feature/* ]
|
branches: [ main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -38,7 +40,7 @@ jobs:
|
|||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -65,7 +67,7 @@ jobs:
|
|||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -140,7 +142,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Cypress artifacts
|
- name: Upload Cypress artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||||
with:
|
with:
|
||||||
name: cypress-single-site-results
|
name: cypress-single-site-results
|
||||||
path: |
|
path: |
|
||||||
@@ -161,7 +163,7 @@ jobs:
|
|||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -237,7 +239,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Cypress artifacts
|
- name: Upload Cypress artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||||
with:
|
with:
|
||||||
name: cypress-multisite-results
|
name: cypress-multisite-results
|
||||||
path: |
|
path: |
|
||||||
@@ -248,14 +250,18 @@ jobs:
|
|||||||
name: WordPress Performance Tests
|
name: WordPress Performance Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: code-quality
|
needs: code-quality
|
||||||
# Allow failures since performance tests can be flaky in CI environments
|
# DISABLED: Performance tests are flaky in CI due to Lighthouse/Playwright resource constraints.
|
||||||
|
# The wp-performance-action uses WordPress Playground internally and Lighthouse for metrics,
|
||||||
|
# which requires significant resources and is not reliable in shared CI runners.
|
||||||
|
# Run performance tests locally or on dedicated infrastructure for accurate results.
|
||||||
|
if: false
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: WordPress Performance Tests
|
- name: WordPress Performance Tests
|
||||||
uses: swissspidy/wp-performance-action@v2.0.3
|
uses: swissspidy/wp-performance-action@b7e3ffcf0fc4a48b62492e021e0ebeb51430ff11 # v2.0.3
|
||||||
with:
|
with:
|
||||||
plugins: |
|
plugins: |
|
||||||
./
|
./
|
||||||
|
|||||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -14,10 +14,10 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2
|
||||||
with:
|
with:
|
||||||
php-version: '7.4'
|
php-version: '7.4'
|
||||||
extensions: mbstring, intl, zip
|
extensions: mbstring, intl, zip
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
|
||||||
with:
|
with:
|
||||||
files: wp-plugin-starter-template-for-ai-coding-${{ env.VERSION }}.zip
|
files: wp-plugin-starter-template-for-ai-coding-${{ env.VERSION }}.zip
|
||||||
name: v${{ env.VERSION }} - WordPress Plugin Starter Template
|
name: v${{ env.VERSION }} - WordPress Plugin Starter Template
|
||||||
|
|||||||
2
.github/workflows/sonarcloud.yml
vendored
2
.github/workflows/sonarcloud.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
|||||||
|
|
||||||
- name: SonarCloud Scan
|
- name: SonarCloud Scan
|
||||||
if: steps.check_token.outputs.skip != 'true'
|
if: steps.check_token.outputs.skip != 'true'
|
||||||
uses: SonarSource/sonarqube-scan-action@master
|
uses: SonarSource/sonarqube-scan-action@9598b8a83feef37de07f549027fab50ecffe6a6e # master
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
SONAR_TOKEN: ${{ secrets.SONARCLOUD_GITHUB }}
|
SONAR_TOKEN: ${{ secrets.SONARCLOUD_GITHUB }}
|
||||||
|
|||||||
8
.github/workflows/sync-wiki.yml
vendored
8
.github/workflows/sync-wiki.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||||
|
|
||||||
- name: Configure Git
|
- name: Configure Git
|
||||||
run: |
|
run: |
|
||||||
@@ -50,4 +50,8 @@ jobs:
|
|||||||
git commit -m "Sync wiki from source repository"
|
git commit -m "Sync wiki from source repository"
|
||||||
|
|
||||||
# Push changes
|
# Push changes
|
||||||
git push https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.wiki.git
|
git push https://${WIKI_ACTOR}:${WIKI_TOKEN}@github.com/${WIKI_REPO}.wiki.git
|
||||||
|
env:
|
||||||
|
WIKI_ACTOR: ${{ github.actor }}
|
||||||
|
WIKI_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
WIKI_REPO: ${{ github.repository }}
|
||||||
|
|||||||
15
.github/workflows/tests.yml
vendored
15
.github/workflows/tests.yml
vendored
@@ -17,12 +17,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||||
with:
|
with:
|
||||||
clean: 'true'
|
clean: 'true'
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php-versions }}
|
php-version: ${{ matrix.php-versions }}
|
||||||
extensions: mbstring, intl, zip
|
extensions: mbstring, intl, zip
|
||||||
@@ -34,11 +34,8 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: composer install --prefer-dist --no-progress
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
# - name: Debug test file content
|
- name: Run tests
|
||||||
# run: echo "--- Debugging tests/test-admin.php lines 75-95 ---" && sed -n '75,95p' tests/test-admin.php && echo "--- End Debugging ---"
|
run: ./vendor/bin/phpunit
|
||||||
|
|
||||||
# - name: Run tests
|
|
||||||
# run: ./vendor/bin/phpunit
|
|
||||||
|
|
||||||
code-style:
|
code-style:
|
||||||
name: Code Style
|
name: Code Style
|
||||||
@@ -46,12 +43,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||||
with:
|
with:
|
||||||
clean: 'true'
|
clean: 'true'
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2
|
||||||
with:
|
with:
|
||||||
php-version: '7.4'
|
php-version: '7.4'
|
||||||
extensions: mbstring, intl, zip
|
extensions: mbstring, intl, zip
|
||||||
|
|||||||
6
.github/workflows/wordpress-tests.yml
vendored
6
.github/workflows/wordpress-tests.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Cypress artifacts
|
- name: Upload Cypress artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||||
with:
|
with:
|
||||||
name: cypress-results
|
name: cypress-results
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -62,3 +62,7 @@ temp/
|
|||||||
# Test Coverage
|
# Test Coverage
|
||||||
coverage/
|
coverage/
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
|
.agents/loop-state/
|
||||||
|
|
||||||
|
# Local tool configs
|
||||||
|
.superset/
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"MD004": {
|
||||||
|
"style": "asterisk"
|
||||||
|
},
|
||||||
"MD012": false,
|
"MD012": false,
|
||||||
"MD022": false,
|
"MD022": false,
|
||||||
"MD031": false,
|
"MD031": false,
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ if ($condition) {
|
|||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
* All classes, methods, and functions should be documented using PHPDoc
|
* All classes, methods, and functions should be documented using PHPDoc
|
||||||
* Include a description, parameters, return values, and exceptions
|
* Include descriptions of parameters, return values, and any exceptions thrown
|
||||||
|
|
||||||
```php
|
```php
|
||||||
/**
|
/**
|
||||||
@@ -271,7 +271,7 @@ To ensure your code passes the quality checks from these tools, follow these gui
|
|||||||
3. **Using AI Assistants with Code Quality Tools**
|
3. **Using AI Assistants with Code Quality Tools**
|
||||||
* When you receive feedback from code quality tools, you can use AI assistants to help address the issues
|
* When you receive feedback from code quality tools, you can use AI assistants to help address the issues
|
||||||
* Copy the output from the code quality tool and paste it into your AI assistant chat
|
* Copy the output from the code quality tool and paste it into your AI assistant chat
|
||||||
* Ask the AI to help you understand and resolve the issues
|
* Request the AI's assistance to interpret and resolve the reported issues
|
||||||
* Example prompt:
|
* Example prompt:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ Thank you for considering contributing to this project! This document provides g
|
|||||||
|
|
||||||
By participating in this project, you agree to abide by our code of conduct:
|
By participating in this project, you agree to abide by our code of conduct:
|
||||||
|
|
||||||
- Be respectful and inclusive
|
* Be respectful and inclusive
|
||||||
- Be patient and welcoming
|
* Be patient and welcoming
|
||||||
- Be considerate
|
* Be considerate
|
||||||
- Be collaborative
|
* Be collaborative
|
||||||
- Be open-minded
|
* Be open-minded
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
@@ -26,12 +26,12 @@ If you find a bug, please report it by creating an issue on GitHub:
|
|||||||
|
|
||||||
Please include:
|
Please include:
|
||||||
|
|
||||||
- A clear, descriptive title
|
* A clear, descriptive title
|
||||||
- Steps to reproduce the bug
|
* Steps to reproduce the bug
|
||||||
- Expected behavior
|
* Expected behavior
|
||||||
- Actual behavior
|
* Actual behavior
|
||||||
- Screenshots (if applicable)
|
* Screenshots (if applicable)
|
||||||
- Your environment (WordPress version, PHP version, browser, etc.)
|
* Your environment (WordPress version, PHP version, browser, etc.)
|
||||||
|
|
||||||
### Suggesting Enhancements
|
### Suggesting Enhancements
|
||||||
|
|
||||||
@@ -45,10 +45,10 @@ If you have an idea for an enhancement:
|
|||||||
|
|
||||||
Please include:
|
Please include:
|
||||||
|
|
||||||
- A clear, descriptive title
|
* A clear, descriptive title
|
||||||
- A detailed description of the enhancement
|
* A detailed description of the enhancement
|
||||||
- Why this enhancement would be useful
|
* Why this enhancement would be useful
|
||||||
- Any relevant examples or mockups
|
* Any relevant examples or mockups
|
||||||
|
|
||||||
### Pull Requests
|
### Pull Requests
|
||||||
|
|
||||||
@@ -72,33 +72,33 @@ If you want to contribute code:
|
|||||||
|
|
||||||
#### Pull Request Guidelines
|
#### Pull Request Guidelines
|
||||||
|
|
||||||
- Follow the coding standards (see [Coding Standards](Coding-Standards))
|
* Follow the coding standards (see [Coding Standards](Coding-Standards))
|
||||||
- Write tests for your changes
|
* Write tests for your changes
|
||||||
- Update documentation as needed
|
* Update documentation as needed
|
||||||
- Keep pull requests focused on a single change
|
* Keep pull requests focused on a single change
|
||||||
- Write a clear, descriptive title and description
|
* Write a clear, descriptive title and description
|
||||||
- Reference any related issues
|
* Reference any related issues
|
||||||
- Ensure your code passes the automated code quality checks (see below)
|
* Ensure your code passes the automated code quality checks (see below)
|
||||||
|
|
||||||
#### Code Quality Tools
|
#### Code Quality Tools
|
||||||
|
|
||||||
This project uses several automated code quality tools to ensure high standards. These tools are free for public repositories and will automatically analyze your code when you create a pull request:
|
This project uses several automated code quality tools to ensure high standards. These tools are free for public repositories and will automatically analyze your code when you create a pull request:
|
||||||
|
|
||||||
1. **CodeRabbit**: AI-powered code review tool
|
1. **CodeRabbit**: AI-powered code review tool
|
||||||
- [Website](https://www.coderabbit.ai/)
|
* [Website](https://www.coderabbit.ai/)
|
||||||
- Provides automated feedback on pull requests
|
* Provides automated feedback on pull requests
|
||||||
|
|
||||||
2. **CodeFactor**: Continuous code quality monitoring
|
2. **CodeFactor**: Continuous code quality monitoring
|
||||||
- [Website](https://www.codefactor.io/)
|
* [Website](https://www.codefactor.io/)
|
||||||
- Provides a grade for your codebase
|
* Provides a grade for your codebase
|
||||||
|
|
||||||
3. **Codacy**: Code quality and static analysis
|
3. **Codacy**: Code quality and static analysis
|
||||||
- [Website](https://www.codacy.com/)
|
* [Website](https://www.codacy.com/)
|
||||||
- Identifies issues related to code style, security, and performance
|
* Identifies issues related to code style, security, and performance
|
||||||
|
|
||||||
4. **SonarCloud**: Code quality and security analysis
|
4. **SonarCloud**: Code quality and security analysis
|
||||||
- [Website](https://sonarcloud.io/)
|
* [Website](https://sonarcloud.io/)
|
||||||
- Provides detailed analysis of code quality and security
|
* Provides detailed analysis of code quality and security
|
||||||
|
|
||||||
#### Using AI Assistants with Code Quality Tools
|
#### Using AI Assistants with Code Quality Tools
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ When you receive feedback from these code quality tools, you can use AI assistan
|
|||||||
|
|
||||||
1. Copy the output from the code quality tool
|
1. Copy the output from the code quality tool
|
||||||
2. Paste it into your AI assistant chat
|
2. Paste it into your AI assistant chat
|
||||||
3. Ask the AI to help you understand and resolve the issues
|
3. Request the AI's assistance to interpret and resolve the reported issues
|
||||||
4. Apply the suggested fixes
|
4. Apply the suggested fixes
|
||||||
5. Commit the changes and verify that the issues are resolved
|
5. Commit the changes and verify that the issues are resolved
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ To ensure your code meets the quality standards, run these commands before submi
|
|||||||
* Check JavaScript coding standards: `npm run lint:js`
|
* Check JavaScript coding standards: `npm run lint:js`
|
||||||
* Check CSS coding standards: `npm run lint:css`
|
* Check CSS coding standards: `npm run lint:css`
|
||||||
|
|
||||||
These checks will help identify and fix issues before they are caught by the automated code quality tools in the pull request process.
|
These checks will assist in identifying and resolving issues before they are caught by the automated code quality tools in the pull request process.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,17 @@ It uses WebAssembly, which means:
|
|||||||
|
|
||||||
The easiest way to test our plugin with WordPress Playground is to use the online version:
|
The easiest way to test our plugin with WordPress Playground is to use the online version:
|
||||||
|
|
||||||
1. Single site testing: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=2)
|
1. Single site testing: [Open in WordPress Playground][playground-single]
|
||||||
|
|
||||||
2. Multisite testing: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/multisite-blueprint.json&_t=2)
|
2. Multisite testing: [Open in WordPress Playground][playground-multisite]
|
||||||
|
|
||||||
These links automatically set up WordPress with multisite enabled and WP_DEBUG enabled.
|
[playground-single]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=2
|
||||||
|
[playground-multisite]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/multisite-blueprint.json&_t=2
|
||||||
|
|
||||||
Both the Plugin Toggle and Kadence Blocks plugins are pre-activated.
|
Both links automatically set up WordPress with WP_DEBUG enabled and the Plugin Toggle and
|
||||||
|
Kadence Blocks plugins pre-installed and activated.
|
||||||
|
|
||||||
|
The multisite link additionally enables WordPress multisite and network-activates both plugins.
|
||||||
|
|
||||||
## WP-CLI Commands for WordPress Playground
|
## WP-CLI Commands for WordPress Playground
|
||||||
|
|
||||||
@@ -98,14 +102,16 @@ In a WordPress multisite environment, there are two ways to activate plugins:
|
|||||||
1. **Network Activation**: Activates a plugin for all sites in the network
|
1. **Network Activation**: Activates a plugin for all sites in the network
|
||||||
* In the WordPress admin, go to Network Admin > Plugins
|
* In the WordPress admin, go to Network Admin > Plugins
|
||||||
* Click "Network Activate" under the plugin
|
* Click "Network Activate" under the plugin
|
||||||
* Or use WP-CLI: `wp plugin install plugin-name --activate-network`
|
* Or use WP-CLI:
|
||||||
|
* To activate an already installed plugin: `wp plugin activate plugin-name --network`
|
||||||
|
* To install and activate in one step: `wp plugin install plugin-name --activate-network`
|
||||||
|
|
||||||
2. **Per-Site Activation**: Activates a plugin for a specific site
|
2. **Per-Site Activation**: Activates a plugin for a specific site
|
||||||
* In the WordPress admin, go to the specific site's admin area
|
* In the WordPress admin, go to the specific site's admin area
|
||||||
* Go to Plugins and activate the plugin for that site only
|
* Go to Plugins and activate the plugin for that site only
|
||||||
* Or use WP-CLI: `wp plugin activate plugin-name --url=site-url`
|
* Or use WP-CLI: `wp plugin activate plugin-name --url=site-url`
|
||||||
|
|
||||||
Our multisite blueprint uses network activation for the Plugin Toggle plugin as an example.
|
Our multisite blueprint uses network activation for both the Plugin Toggle and Kadence Blocks plugins.
|
||||||
|
|
||||||
## Running Tests with WordPress Playground
|
## Running Tests with WordPress Playground
|
||||||
|
|
||||||
@@ -117,8 +123,8 @@ We have two blueprints for testing:
|
|||||||
To run tests with WordPress Playground:
|
To run tests with WordPress Playground:
|
||||||
|
|
||||||
1. Open the appropriate WordPress Playground link:
|
1. Open the appropriate WordPress Playground link:
|
||||||
* [Single site](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=2)
|
* [Single site][playground-single]
|
||||||
* [Multisite](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/multisite-blueprint.json&_t=2)
|
* [Multisite][playground-multisite]
|
||||||
|
|
||||||
2. Test the plugin manually in the browser
|
2. Test the plugin manually in the browser
|
||||||
|
|
||||||
@@ -128,7 +134,8 @@ We've also included HTML files that embed WordPress Playground:
|
|||||||
|
|
||||||
1. Open `playground/index.html` in your browser for single site testing
|
1. Open `playground/index.html` in your browser for single site testing
|
||||||
2. Open `playground/multisite.html` in your browser for multisite testing
|
2. Open `playground/multisite.html` in your browser for multisite testing
|
||||||
3. Open `playground/test.html` in your browser for a unified interface with buttons to switch between single site and multisite
|
3. Open `playground/test.html` in your browser for a unified interface with buttons
|
||||||
|
to switch between single site and multisite
|
||||||
|
|
||||||
You can serve these files locally with a simple HTTP server:
|
You can serve these files locally with a simple HTTP server:
|
||||||
|
|
||||||
@@ -169,7 +176,9 @@ This will start a local WordPress instance with your plugin installed and activa
|
|||||||
|
|
||||||
You can customize the blueprints to suit your testing needs.
|
You can customize the blueprints to suit your testing needs.
|
||||||
|
|
||||||
See the [WordPress Playground Blueprints documentation](https://wordpress.github.io/wordpress-playground/blueprints/) for details.
|
See the [WordPress Playground Blueprints documentation][blueprints-docs] for details.
|
||||||
|
|
||||||
|
[blueprints-docs]: https://wordpress.github.io/wordpress-playground/blueprints/
|
||||||
|
|
||||||
## WordPress Playground JavaScript API
|
## WordPress Playground JavaScript API
|
||||||
|
|
||||||
|
|||||||
@@ -134,9 +134,12 @@ WordPress Playground runs WordPress entirely in the browser using WebAssembly. T
|
|||||||
|
|
||||||
The easiest way to test our plugin with WordPress Playground is to use the online version:
|
The easiest way to test our plugin with WordPress Playground is to use the online version:
|
||||||
|
|
||||||
1. Single site testing: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=2)
|
1. Single site testing: [Open in WordPress Playground][playground-single]
|
||||||
|
|
||||||
2. Multisite testing: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/multisite-blueprint.json&_t=2)
|
2. Multisite testing: [Open in WordPress Playground][playground-multisite]
|
||||||
|
|
||||||
|
[playground-single]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=2
|
||||||
|
[playground-multisite]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/multisite-blueprint.json&_t=2
|
||||||
|
|
||||||
These links automatically set up WordPress with multisite enabled and WP_DEBUG enabled.
|
These links automatically set up WordPress with multisite enabled and WP_DEBUG enabled.
|
||||||
|
|
||||||
@@ -148,7 +151,8 @@ We've also included HTML files that embed WordPress Playground:
|
|||||||
|
|
||||||
1. Open `playground/index.html` in your browser for single site testing
|
1. Open `playground/index.html` in your browser for single site testing
|
||||||
2. Open `playground/multisite.html` in your browser for multisite testing
|
2. Open `playground/multisite.html` in your browser for multisite testing
|
||||||
3. Open `playground/test.html` in your browser for a unified interface with buttons to switch between single site and multisite
|
3. Open `playground/test.html` in your browser for a unified interface with buttons
|
||||||
|
to switch between single site and multisite
|
||||||
|
|
||||||
You can serve these files locally with a simple HTTP server:
|
You can serve these files locally with a simple HTTP server:
|
||||||
|
|
||||||
|
|||||||
25
AGENTS.md
25
AGENTS.md
@@ -99,17 +99,23 @@ For local testing with WordPress Playground, LocalWP, and wp-env, see **@.agents
|
|||||||
|
|
||||||
When working in a multi-repository workspace, follow these guidelines to avoid confusion:
|
When working in a multi-repository workspace, follow these guidelines to avoid confusion:
|
||||||
|
|
||||||
1. **Verify Repository Context**: Always check which repository you're currently working in before making any changes or recommendations.
|
1. **Verify Repository Context**: Always check which repository you're currently working in
|
||||||
|
before making any changes or recommendations.
|
||||||
|
|
||||||
2. **Limit Code Search Scope**: When searching for code or functionality, explicitly limit your search to the current repository.
|
2. **Limit Code Search Scope**: When searching for code or functionality,
|
||||||
|
explicitly limit your search to the current repository.
|
||||||
|
|
||||||
3. **Don't Assume Features**: Never assume that features present in one repository should be implemented in another. Each repository has its own specific purpose and feature set.
|
3. **Don't Assume Features**: Never assume that features present in one repository
|
||||||
|
should be implemented in another. Each repository has its own specific purpose and feature set.
|
||||||
|
|
||||||
4. **Repository-Specific Documentation**: Documentation should only reflect the actual features and functionality of the current repository.
|
4. **Repository-Specific Documentation**: Documentation should only reflect the actual features
|
||||||
|
and functionality of the current repository.
|
||||||
|
|
||||||
5. **Cross-Repository Inspiration**: If you want to implement a feature inspired by another repository, explicitly mention that it's a new feature being added, not an existing one.
|
5. **Cross-Repository Inspiration**: If you want to implement a feature inspired by another
|
||||||
|
repository, explicitly mention that it's a new feature being added, not an existing one.
|
||||||
|
|
||||||
6. **Verify Before Implementation**: Before implementing or documenting a feature, verify that it actually exists in the current repository by checking the codebase.
|
6. **Verify Before Implementation**: Before implementing or documenting a feature, verify that
|
||||||
|
it actually exists in the current repository by checking the codebase.
|
||||||
|
|
||||||
7. **Consistent Markdown Formatting**: Always use asterisks (*) for bullet points in Markdown files, not hyphens (-).
|
7. **Consistent Markdown Formatting**: Always use asterisks (*) for bullet points in Markdown files, not hyphens (-).
|
||||||
|
|
||||||
@@ -161,7 +167,9 @@ When working with this repository, remember these preferences:
|
|||||||
3. Keep code modular and maintainable
|
3. Keep code modular and maintainable
|
||||||
4. Reference these preferences in future interactions
|
4. Reference these preferences in future interactions
|
||||||
|
|
||||||
This ensures consistency across coding sessions and reduces the need for developers to repeatedly explain their preferences.
|
This ensures consistency across coding sessions.
|
||||||
|
|
||||||
|
It reduces the need for developers to repeatedly explain their preferences.
|
||||||
|
|
||||||
## Autonomous CI/CD and Error Handling
|
## Autonomous CI/CD and Error Handling
|
||||||
|
|
||||||
@@ -175,7 +183,8 @@ As an AI assistant, you should:
|
|||||||
4. **Verify Solutions**: Ensure fixes pass all tests and quality checks
|
4. **Verify Solutions**: Ensure fixes pass all tests and quality checks
|
||||||
5. **Document Resolutions**: Update documentation with solutions for future reference
|
5. **Document Resolutions**: Update documentation with solutions for future reference
|
||||||
|
|
||||||
For detailed instructions on establishing feedback loops and error checking processes, see **@.agents/error-checking-feedback-loops.md**.
|
For detailed instructions on feedback loops and error checking, see
|
||||||
|
**@.agents/error-checking-feedback-loops.md**.
|
||||||
|
|
||||||
### When to Consult Humans
|
### When to Consult Humans
|
||||||
|
|
||||||
|
|||||||
119
README.md
119
README.md
@@ -1,6 +1,33 @@
|
|||||||
# WordPress Plugin Starter Template for AI Coding
|
# WordPress Plugin Starter Template for AI Coding
|
||||||
|
|
||||||
[](https://www.gnu.org/licenses/gpl-2.0.html) [](https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/workflows/tests.yml) [](https://wordpress.org/about/requirements/) [](https://wordpress.org/about/requirements/) [](https://wordpress.org/plugins/your-plugin-slug/) [](https://wordpress.org/plugins/your-plugin-slug/reviews/) [](https://wordpress.org/plugins/your-plugin-slug/) [](https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/releases) [](https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/issues) [](https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/graphs/contributors) [](https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/wiki)  [](https://www.codefactor.io/repository/github/wpallstars/wp-plugin-starter-template-for-ai-coding) [](https://sonarcloud.io/summary/new_code?id=wpallstars_wp-plugin-starter-template-for-ai-coding) [](https://sonarcloud.io/summary/new_code?id=wpallstars_wp-plugin-starter-template-for-ai-coding) [](https://sonarcloud.io/summary/new_code?id=wpallstars_wp-plugin-starter-template-for-ai-coding) [](https://sonarcloud.io/summary/new_code?id=wpallstars_wp-plugin-starter-template-for-ai-coding) [](https://sonarcloud.io/summary/new_code?id=wpallstars_wp-plugin-starter-template-for-ai-coding) [](https://app.codacy.com/gh/wpallstars/wp-plugin-starter-template-for-ai-coding/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
[![License][badge-license]][url-license]
|
||||||
|
[![Build Status][badge-build]][url-build]
|
||||||
|
[![Requires PHP][badge-php]][url-requirements]
|
||||||
|
[![Requires WordPress][badge-wp]][url-requirements]
|
||||||
|
[![Wiki][badge-wiki]][url-wiki]
|
||||||
|
[![CodeRabbit Reviews][badge-coderabbit]][url-coderabbit]
|
||||||
|
[![CodeFactor][badge-codefactor]][url-codefactor]
|
||||||
|
[![Quality Gate Status][badge-sonar-gate]][url-sonar]
|
||||||
|
[![Codacy Badge][badge-codacy]][url-codacy]
|
||||||
|
|
||||||
|
[badge-license]: https://img.shields.io/badge/license-GPL--2.0%2B-blue.svg
|
||||||
|
[badge-build]: https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/workflows/tests.yml/badge.svg
|
||||||
|
[badge-php]: https://img.shields.io/badge/php-%3E%3D%207.4-blue.svg
|
||||||
|
[badge-wp]: https://img.shields.io/badge/WordPress-%3E%3D%205.0-blue.svg
|
||||||
|
[badge-wiki]: https://img.shields.io/badge/documentation-wiki-blue.svg
|
||||||
|
[badge-coderabbit]: https://img.shields.io/coderabbit/prs/github/wpallstars/wp-plugin-starter-template-for-ai-coding?labelColor=171717&color=FF570A&label=CodeRabbit+Reviews
|
||||||
|
[badge-codefactor]: https://www.codefactor.io/repository/github/wpallstars/wp-plugin-starter-template-for-ai-coding/badge
|
||||||
|
[badge-sonar-gate]: https://sonarcloud.io/api/project_badges/measure?project=wpallstars_wp-plugin-starter-template-for-ai-coding&metric=alert_status
|
||||||
|
[badge-codacy]: https://app.codacy.com/project/badge/Grade/905754fd010b481490b496fb800e6144
|
||||||
|
|
||||||
|
[url-license]: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
[url-build]: https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/actions/workflows/tests.yml
|
||||||
|
[url-requirements]: https://wordpress.org/about/requirements/
|
||||||
|
[url-wiki]: https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/wiki
|
||||||
|
[url-coderabbit]: https://coderabbit.ai
|
||||||
|
[url-codefactor]: https://www.codefactor.io/repository/github/wpallstars/wp-plugin-starter-template-for-ai-coding
|
||||||
|
[url-sonar]: https://sonarcloud.io/summary/new_code?id=wpallstars_wp-plugin-starter-template-for-ai-coding
|
||||||
|
[url-codacy]: https://app.codacy.com/gh/wpallstars/wp-plugin-starter-template-for-ai-coding/dashboard
|
||||||
|
|
||||||
A comprehensive starter template for WordPress plugins with best practices for AI-assisted development.
|
A comprehensive starter template for WordPress plugins with best practices for AI-assisted development.
|
||||||
|
|
||||||
@@ -64,16 +91,18 @@ In most AI IDEs, you can pin these files to ensure they're considered in each me
|
|||||||
|
|
||||||
To get started with this template, follow these steps:
|
To get started with this template, follow these steps:
|
||||||
|
|
||||||
1. In your terminal, navigate to the folder you keep you Git repositories (eg: `~/Git/`), then clone this repository to your local machine:
|
1. Navigate to your Git repositories folder (e.g., `~/Git/`), then clone:
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding.git
|
git clone https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding.git
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Open the [Starter Prompt](.wiki/Starter-Prompt.md) file and follow the instructions to customize the template for your plugin.
|
2. Open the [Starter Prompt](.wiki/Starter-Prompt.md) file and follow the instructions
|
||||||
|
to customize the template for your plugin.
|
||||||
|
|
||||||
3. Add the AGENTS.md file and .agents/ directory to your AI IDE chat context.
|
3. Add the AGENTS.md file and .agents/ directory to your AI IDE chat context.
|
||||||
|
|
||||||
4. Use an AI assistant like GitHub Copilot, Claude, or ChatGPT to help you customize the template by providing the prompt from the Starter Prompt file.
|
4. Use an AI assistant like GitHub Copilot, Claude, or ChatGPT to help customize
|
||||||
|
the template by providing the prompt from the Starter Prompt file.
|
||||||
|
|
||||||
### Development Environment
|
### Development Environment
|
||||||
|
|
||||||
@@ -111,9 +140,14 @@ The template includes multiple testing approaches:
|
|||||||
|
|
||||||
Test your plugin directly in the browser without any local setup:
|
Test your plugin directly in the browser without any local setup:
|
||||||
|
|
||||||
1. Single site testing: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/feature/testing-framework/playground/blueprint.json&_t=5)
|
1. Single site testing:
|
||||||
|
[Open in WordPress Playground][playground-single-readme]
|
||||||
|
|
||||||
2. Multisite testing: [Open in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/feature/testing-framework/playground/multisite-blueprint.json&_t=18)
|
2. Multisite testing:
|
||||||
|
[Open in WordPress Playground][playground-multisite-readme]
|
||||||
|
|
||||||
|
[playground-single-readme]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/feature/testing-framework/playground/blueprint.json&_t=5
|
||||||
|
[playground-multisite-readme]: https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/feature/testing-framework/playground/multisite-blueprint.json&_t=18
|
||||||
|
|
||||||
For more details, see the [Playground Testing](.wiki/Playground-Testing.md) documentation.
|
For more details, see the [Playground Testing](.wiki/Playground-Testing.md) documentation.
|
||||||
|
|
||||||
@@ -197,7 +231,11 @@ This template includes functionality that allows users to choose where they want
|
|||||||
|
|
||||||
### How do I customize this template for my plugin?
|
### How do I customize this template for my plugin?
|
||||||
|
|
||||||
See the [Starter Prompt](.wiki/Starter-Prompt.md) file for detailed instructions on customizing this template for your specific plugin needs. Make sure to add the AGENTS.md file and .agents/ directory to your AI IDE chat context for the best results.
|
See the [Starter Prompt](.wiki/Starter-Prompt.md) file for detailed instructions on
|
||||||
|
customizing this template for your specific plugin needs.
|
||||||
|
|
||||||
|
Make sure to add the AGENTS.md file and .agents/ directory to your AI IDE chat context
|
||||||
|
for the best results.
|
||||||
|
|
||||||
### What files do I need to update with my plugin information?
|
### What files do I need to update with my plugin information?
|
||||||
|
|
||||||
@@ -229,7 +267,8 @@ This will create a ZIP file that you can install in WordPress.
|
|||||||
|
|
||||||
### How do I add custom functionality to my plugin?
|
### How do I add custom functionality to my plugin?
|
||||||
|
|
||||||
Customize the includes/core.php file to implement your core functionality and the admin/lib/admin.php file for admin-specific functionality.
|
Customize the `includes/core.php` file to implement your core functionality and the
|
||||||
|
`admin/lib/admin.php` file for admin-specific functionality.
|
||||||
|
|
||||||
### Is this template compatible with WordPress multisite?
|
### Is this template compatible with WordPress multisite?
|
||||||
|
|
||||||
@@ -240,7 +279,7 @@ We have a testing framework that allows you to verify functionality in both envi
|
|||||||
You can test multisite compatibility in two ways:
|
You can test multisite compatibility in two ways:
|
||||||
|
|
||||||
1. Using WordPress Playground (no Docker required):
|
1. Using WordPress Playground (no Docker required):
|
||||||
* [Open Multisite in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/feature/testing-framework/playground/multisite-blueprint.json&_t=18)
|
* [Open Multisite in WordPress Playground][playground-multisite-readme]
|
||||||
|
|
||||||
2. Using wp-env (requires Docker):
|
2. Using wp-env (requires Docker):
|
||||||
```bash
|
```bash
|
||||||
@@ -261,7 +300,10 @@ If you need help with this template, there are several ways to get support:
|
|||||||
|
|
||||||
Contributions are welcome! Please feel free to submit a Pull Request.
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||||
|
|
||||||
1. Fork the repository on [GitHub](https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/) or [Gitea](https://gitea.wpallstars.com/wpallstars/wp-plugin-starter-template-for-ai-coding/)
|
1. Fork the repository on [GitHub][repo-github] or [Gitea][repo-gitea]
|
||||||
|
|
||||||
|
[repo-github]: https://github.com/wpallstars/wp-plugin-starter-template-for-ai-coding/
|
||||||
|
[repo-gitea]: https://gitea.wpallstars.com/wpallstars/wp-plugin-starter-template-for-ai-coding/
|
||||||
2. Create your feature branch: `git checkout -b feature/amazing-feature`
|
2. Create your feature branch: `git checkout -b feature/amazing-feature`
|
||||||
3. Commit your changes: `git commit -m 'Add some amazing feature'`
|
3. Commit your changes: `git commit -m 'Add some amazing feature'`
|
||||||
4. Push to the branch: `git push origin feature/amazing-feature`
|
4. Push to the branch: `git push origin feature/amazing-feature`
|
||||||
@@ -271,7 +313,10 @@ For more detailed information, see the [Contributing Guide](.wiki/Contributing.m
|
|||||||
|
|
||||||
### Code Quality Tools
|
### Code Quality Tools
|
||||||
|
|
||||||
This project uses several automated code quality tools to ensure high standards. These tools are free for public repositories and should be integrated into any new repositories based on this template:
|
This project uses several automated code quality tools to ensure high standards.
|
||||||
|
|
||||||
|
These tools are free for public repositories and should be integrated into any new
|
||||||
|
repositories based on this template:
|
||||||
|
|
||||||
1. **CodeRabbit**: AI-powered code review tool
|
1. **CodeRabbit**: AI-powered code review tool
|
||||||
* [Website](https://www.coderabbit.ai/)
|
* [Website](https://www.coderabbit.ai/)
|
||||||
@@ -291,7 +336,9 @@ This project uses several automated code quality tools to ensure high standards.
|
|||||||
3. Go to your project settings > Integrations > Project API
|
3. Go to your project settings > Integrations > Project API
|
||||||
4. Generate a project API token
|
4. Generate a project API token
|
||||||
5. Add the token as a secret named `CODACY_PROJECT_TOKEN` in your GitHub repository settings
|
5. Add the token as a secret named `CODACY_PROJECT_TOKEN` in your GitHub repository settings
|
||||||
6. Note: Codacy tokens are project-specific, so they need to be added at the repository level. However, you can use GitHub Actions to securely pass these tokens between repositories if needed.
|
6. Note: Codacy tokens are project-specific, so they need to be added at the
|
||||||
|
repository level. You can use GitHub Actions to securely pass tokens
|
||||||
|
between repositories if needed.
|
||||||
|
|
||||||
4. **SonarCloud**: Code quality and security analysis
|
4. **SonarCloud**: Code quality and security analysis
|
||||||
* [Website](https://sonarcloud.io/)
|
* [Website](https://sonarcloud.io/)
|
||||||
@@ -302,7 +349,8 @@ This project uses several automated code quality tools to ensure high standards.
|
|||||||
2. Create a new organization or use an existing one
|
2. Create a new organization or use an existing one
|
||||||
3. Add your repository to SonarCloud
|
3. Add your repository to SonarCloud
|
||||||
4. Generate a token in SonarCloud (Account > Security > Tokens)
|
4. Generate a token in SonarCloud (Account > Security > Tokens)
|
||||||
5. Add the token as a secret named `SONAR_TOKEN` in your GitHub repository or organization settings (see "GitHub Secrets Management" section below)
|
5. Add the token as a secret named `SONAR_TOKEN` in your GitHub repository or
|
||||||
|
organization settings (see "GitHub Secrets Management" section below)
|
||||||
|
|
||||||
5. **PHP_CodeSniffer (PHPCS)**: PHP code style checker
|
5. **PHP_CodeSniffer (PHPCS)**: PHP code style checker
|
||||||
* Enforces WordPress Coding Standards
|
* Enforces WordPress Coding Standards
|
||||||
@@ -328,11 +376,12 @@ When you receive feedback from these code quality tools, you can use AI assistan
|
|||||||
|
|
||||||
1. Copy the output from the code quality tool
|
1. Copy the output from the code quality tool
|
||||||
2. Paste it into your AI assistant chat
|
2. Paste it into your AI assistant chat
|
||||||
3. Ask the AI to help you understand and resolve the issues
|
3. Request the AI's assistance to interpret and resolve the reported issues
|
||||||
4. Apply the suggested fixes
|
4. Apply the suggested fixes
|
||||||
5. Commit the changes and verify that the issues are resolved
|
5. Commit the changes and verify that the issues are resolved
|
||||||
|
|
||||||
For more information on coding standards and how to pass code quality checks, see the [Coding Standards Guide](.wiki/Coding-Standards.md).
|
For more information on coding standards and how to pass code quality checks,
|
||||||
|
see the [Coding Standards Guide](.wiki/Coding-Standards.md).
|
||||||
|
|
||||||
### GitHub Secrets Management
|
### GitHub Secrets Management
|
||||||
|
|
||||||
@@ -350,7 +399,8 @@ GitHub offers three levels of secrets management, each with different scopes and
|
|||||||
* Available at: Repository > Settings > Secrets and variables > Actions
|
* Available at: Repository > Settings > Secrets and variables > Actions
|
||||||
* Scope: Limited to a single repository
|
* Scope: Limited to a single repository
|
||||||
* Benefits: Repository-specific, higher isolation
|
* Benefits: Repository-specific, higher isolation
|
||||||
* Recommended for: `CODACY_PROJECT_TOKEN` and other repository-specific credentials or tokens that shouldn't be shared
|
* Recommended for: `CODACY_PROJECT_TOKEN` and other repository-specific credentials
|
||||||
|
or tokens that shouldn't be shared
|
||||||
|
|
||||||
3. **Environment Secrets**:
|
3. **Environment Secrets**:
|
||||||
* Available at: Repository > Settings > Environments > (select environment) > Environment secrets
|
* Available at: Repository > Settings > Environments > (select environment) > Environment secrets
|
||||||
@@ -358,7 +408,12 @@ GitHub offers three levels of secrets management, each with different scopes and
|
|||||||
* Benefits: Environment-specific, can have approval requirements
|
* Benefits: Environment-specific, can have approval requirements
|
||||||
* Recommended for: Deployment credentials that vary between environments
|
* Recommended for: Deployment credentials that vary between environments
|
||||||
|
|
||||||
For code quality tools like SonarCloud, organization secrets are recommended if you have multiple repositories that use these tools. This approach reduces management overhead and ensures consistent configuration across projects. For Codacy, since tokens are project-specific, they should be set at the repository level.
|
For code quality tools like SonarCloud, organization secrets are recommended if you have
|
||||||
|
multiple repositories that use these tools.
|
||||||
|
|
||||||
|
This approach reduces management overhead and ensures consistent configuration across
|
||||||
|
projects. For Codacy, since tokens are project-specific, they should be set at the
|
||||||
|
repository level.
|
||||||
|
|
||||||
### Local Environment Setup for Code Quality Tools
|
### Local Environment Setup for Code Quality Tools
|
||||||
|
|
||||||
@@ -464,13 +519,16 @@ To run code quality tools locally before committing to GitHub:
|
|||||||
|
|
||||||
For more detailed instructions, see the [Code Quality Setup Guide](docs/code-quality-setup.md).
|
For more detailed instructions, see the [Code Quality Setup Guide](docs/code-quality-setup.md).
|
||||||
|
|
||||||
By running these tools locally, you can identify and fix issues before pushing your code to GitHub, ensuring smoother CI/CD workflows.
|
By running these tools locally, you can identify and fix issues before pushing your code
|
||||||
|
to GitHub, ensuring smoother CI/CD workflows.
|
||||||
|
|
||||||
## Developers
|
## Developers
|
||||||
|
|
||||||
### AI-Powered Development
|
### AI-Powered Development
|
||||||
|
|
||||||
This repository is configured to work with various AI-powered development tools. You can use any of the following AI IDEs to contribute to this project:
|
This repository is configured to work with various AI-powered development tools.
|
||||||
|
|
||||||
|
You can use any of the following AI IDEs to contribute to this project:
|
||||||
|
|
||||||
* [Augment Code](https://www.augmentcode.com/) - AI-powered coding assistant
|
* [Augment Code](https://www.augmentcode.com/) - AI-powered coding assistant
|
||||||
* [Bolt](https://www.bolt.new/) - AI-powered code editor
|
* [Bolt](https://www.bolt.new/) - AI-powered code editor
|
||||||
@@ -487,9 +545,11 @@ The repository includes configuration files for all these tools to ensure a cons
|
|||||||
|
|
||||||
### Git Updater Integration
|
### Git Updater Integration
|
||||||
|
|
||||||
This template is designed to work seamlessly with the Git Updater plugin for updates from GitHub and Gitea. To ensure proper integration:
|
This template is designed to work seamlessly with the Git Updater plugin for updates from
|
||||||
|
GitHub and Gitea. To ensure proper integration:
|
||||||
|
|
||||||
1. **Required Headers**: The plugin includes specific headers in the main plugin file that Git Updater uses to determine update sources and branches:
|
1. **Required Headers**: The plugin includes specific headers in the main plugin file
|
||||||
|
that Git Updater uses to determine update sources and branches:
|
||||||
```php
|
```php
|
||||||
* GitHub Plugin URI: wpallstars/wp-plugin-starter-template-for-ai-coding
|
* GitHub Plugin URI: wpallstars/wp-plugin-starter-template-for-ai-coding
|
||||||
* GitHub Branch: main
|
* GitHub Branch: main
|
||||||
@@ -500,13 +560,17 @@ This template is designed to work seamlessly with the Git Updater plugin for upd
|
|||||||
* Gitea Branch: main
|
* Gitea Branch: main
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Tagging Releases**: When creating a new release, always tag it with the 'v' prefix (e.g., `v0.1.2`) to ensure GitHub Actions can create the proper release assets.
|
2. **Tagging Releases**: When creating a new release, always tag it with the 'v' prefix
|
||||||
|
(e.g., `v0.1.2`) to ensure GitHub Actions can create the proper release assets.
|
||||||
|
|
||||||
3. **GitHub Actions**: The repository includes a GitHub Actions workflow that automatically builds the plugin and creates a release with the .zip file when a new tag is pushed.
|
3. **GitHub Actions**: The repository includes a GitHub Actions workflow that automatically
|
||||||
|
builds the plugin and creates a release with the .zip file when a new tag is pushed.
|
||||||
|
|
||||||
4. **Update Source Selection**: The template includes a feature that allows users to choose their preferred update source (WordPress.org, GitHub, or Gitea).
|
4. **Update Source Selection**: The template includes a feature that allows users to choose
|
||||||
|
their preferred update source (WordPress.org, GitHub, or Gitea).
|
||||||
|
|
||||||
For more information on Git Updater integration, see the [Git Updater Required Headers documentation](https://git-updater.com/knowledge-base/required-headers/).
|
For more information on Git Updater integration, see the
|
||||||
|
[Git Updater Required Headers documentation](https://git-updater.com/knowledge-base/required-headers/).
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
@@ -603,4 +667,7 @@ This project is licensed under the GPL-2.0+ License - see the [LICENSE](LICENSE)
|
|||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
This template is based on the experience gained from developing the ["Fix 'Plugin file does not exist' Notices"](https://github.com/wpallstars/wp-fix-plugin-does-not-exist-notices) plugin by WPALLSTARS.
|
This template is based on the experience gained from developing the
|
||||||
|
["Fix 'Plugin file does not exist' Notices"][fix-plugin-notices] plugin by WPALLSTARS.
|
||||||
|
|
||||||
|
[fix-plugin-notices]: https://github.com/wpallstars/wp-fix-plugin-does-not-exist-notices
|
||||||
|
|||||||
@@ -6,140 +6,140 @@
|
|||||||
|
|
||||||
/* General Admin Styles */
|
/* General Admin Styles */
|
||||||
.wpst-admin-page {
|
.wpst-admin-page {
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
|
box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-admin-header {
|
.wpst-admin-header {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-admin-header h1 {
|
.wpst-admin-header h1 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: #23282d;
|
color: #23282d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Admin Form Styles */
|
/* Admin Form Styles */
|
||||||
.wpst-form-table {
|
.wpst-form-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-form-table th {
|
.wpst-form-table th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 15px 10px 15px 0;
|
padding: 15px 10px 15px 0;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-form-table td {
|
.wpst-form-table td {
|
||||||
padding: 15px 0;
|
padding: 15px 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-form-table input[type="text"],
|
.wpst-form-table input[type="text"],
|
||||||
.wpst-form-table input[type="number"],
|
.wpst-form-table input[type="number"],
|
||||||
.wpst-form-table select,
|
.wpst-form-table select,
|
||||||
.wpst-form-table textarea {
|
.wpst-form-table textarea {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-form-table textarea {
|
.wpst-form-table textarea {
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-form-description {
|
.wpst-form-description {
|
||||||
color: #666;
|
color: #666;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Admin Notices */
|
/* Admin Notices */
|
||||||
.wpst-notice {
|
.wpst-notice {
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border-left: 4px solid #00a0d2;
|
border-left: 4px solid #00a0d2;
|
||||||
background: #f7fcff;
|
background: #f7fcff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-notice.success {
|
.wpst-notice.success {
|
||||||
border-left-color: #46b450;
|
border-left-color: #46b450;
|
||||||
background: #ecf7ed;
|
background: #ecf7ed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-notice.error {
|
.wpst-notice.error {
|
||||||
border-left-color: #dc3232;
|
border-left-color: #dc3232;
|
||||||
background: #fbeaea;
|
background: #fbeaea;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-notice.warning {
|
.wpst-notice.warning {
|
||||||
border-left-color: #ffb900;
|
border-left-color: #ffb900;
|
||||||
background: #fff8e5;
|
background: #fff8e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Admin Cards */
|
/* Admin Cards */
|
||||||
.wpst-card-container {
|
.wpst-card-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin: 0 -10px;
|
margin: 0 -10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-card {
|
.wpst-card {
|
||||||
flex: 1 0 300px;
|
flex: 1 0 300px;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
|
box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-card-header {
|
.wpst-card-header {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-card-title {
|
.wpst-card-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-card-content {
|
.wpst-card-content {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-card-footer {
|
.wpst-card-footer {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
border-top: 1px solid #eee;
|
border-top: 1px solid #eee;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive Styles */
|
/* 782px is the WordPress mobile admin breakpoint. */
|
||||||
@media screen and (width <= 782px) {
|
@media screen and (max-width: 782px) {
|
||||||
.wpst-form-table th {
|
.wpst-form-table th {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-form-table td {
|
.wpst-form-table td {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-form-table input[type="text"],
|
.wpst-form-table input[type="text"],
|
||||||
.wpst-form-table input[type="number"],
|
.wpst-form-table input[type="number"],
|
||||||
.wpst-form-table select,
|
.wpst-form-table select,
|
||||||
.wpst-form-table textarea {
|
.wpst-form-table textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,138 +6,138 @@
|
|||||||
|
|
||||||
/* Modal Styles */
|
/* Modal Styles */
|
||||||
.wpst-modal {
|
.wpst-modal {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 100000;
|
z-index: 100000;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background-color: rgb(0 0 0 / 40%);
|
background-color: rgb(0 0 0 / 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-content {
|
.wpst-modal-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #fefefe;
|
background-color: #fefefe;
|
||||||
margin: 10% auto;
|
margin: 10% auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 0 4px 8px rgb(0 0 0 / 10%);
|
box-shadow: 0 4px 8px rgb(0 0 0 / 10%);
|
||||||
width: 500px;
|
width: 500px;
|
||||||
max-width: 90%;
|
max-width: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-header {
|
.wpst-modal-header {
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-title {
|
.wpst-modal-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-close {
|
.wpst-modal-close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 15px;
|
right: 15px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #666;
|
color: #666;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-close:hover,
|
.wpst-modal-close:hover,
|
||||||
.wpst-modal-close:focus {
|
.wpst-modal-close:focus {
|
||||||
color: #000;
|
color: #000;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-body {
|
.wpst-modal-body {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-footer {
|
.wpst-modal-footer {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
border-top: 1px solid #eee;
|
border-top: 1px solid #eee;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Source Selection Styles */
|
/* Source Selection Styles */
|
||||||
.wpst-source-options {
|
.wpst-source-options {
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-source-option {
|
.wpst-source-option {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-source-option:hover {
|
.wpst-source-option:hover {
|
||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-source-option.selected {
|
.wpst-source-option.selected {
|
||||||
border-color: #0073aa;
|
border-color: #0073aa;
|
||||||
background-color: #f0f6fc;
|
background-color: #f0f6fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-source-option input[type="radio"] {
|
.wpst-source-option input[type="radio"] {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-source-option-label {
|
.wpst-source-option-label {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-source-option-description {
|
.wpst-source-option-description {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
color: #666;
|
color: #666;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loading Indicator */
|
/* Loading Indicator */
|
||||||
.wpst-loading {
|
.wpst-loading {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
border: 2px solid rgb(0 0 0 / 10%);
|
border: 2px solid rgb(0 0 0 / 10%);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-top-color: #0073aa;
|
border-top-color: #0073aa;
|
||||||
animation: wpst-spin 1s ease-in-out infinite;
|
animation: wpst-spin 1s ease-in-out infinite;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes wpst-spin {
|
@keyframes wpst-spin {
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Message Styles */
|
/* Message Styles */
|
||||||
.wpst-modal-message {
|
.wpst-modal-message {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-message.success {
|
.wpst-modal-message.success {
|
||||||
background-color: #ecf7ed;
|
background-color: #ecf7ed;
|
||||||
border: 1px solid #46b450;
|
border: 1px solid #46b450;
|
||||||
color: #2a6f31;
|
color: #2a6f31;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpst-modal-message.error {
|
.wpst-modal-message.error {
|
||||||
background-color: #fbeaea;
|
background-color: #fbeaea;
|
||||||
border: 1px solid #dc3232;
|
border: 1px solid #dc3232;
|
||||||
color: #8a1f1f;
|
color: #8a1f1f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
data: {
|
data: {
|
||||||
action: 'wpst_save_settings',
|
action: 'wpst_save_settings',
|
||||||
nonce: wpstData.nonce,
|
nonce: wpstData.nonce,
|
||||||
formData: formData
|
formData: formData,
|
||||||
},
|
},
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
@@ -93,8 +93,8 @@
|
|||||||
complete: function () {
|
complete: function () {
|
||||||
// Re-enable submit button and remove loading state.
|
// Re-enable submit button and remove loading state.
|
||||||
$submitButton.prop( 'disabled', false ).removeClass( 'loading' );
|
$submitButton.prop( 'disabled', false ).removeClass( 'loading' );
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -105,10 +105,16 @@
|
|||||||
* @param {string} message Notice message
|
* @param {string} message Notice message
|
||||||
*/
|
*/
|
||||||
showNotice: function (type, message) {
|
showNotice: function (type, message) {
|
||||||
const $notice = $( '<div class="wpst-notice ' + type + '"><p>' + message + '</p></div>' );
|
const allowedTypes = [ 'success', 'error', 'warning' ];
|
||||||
|
const safeType = allowedTypes.includes( type ) ? type : 'error';
|
||||||
|
const $p = $( '<p>' );
|
||||||
|
const $notice = $( '<div>' ).addClass( 'wpst-notice ' + safeType ).append( $p );
|
||||||
|
|
||||||
|
// Set message as plain text to prevent XSS.
|
||||||
|
$p.text( message );
|
||||||
|
|
||||||
// Add notice to the page.
|
// Add notice to the page.
|
||||||
$( '.wpst-notices' ).html( $notice );
|
$( '.wpst-notices' ).empty().append( $notice );
|
||||||
|
|
||||||
// Automatically remove notice after 5 seconds.
|
// Automatically remove notice after 5 seconds.
|
||||||
setTimeout(
|
setTimeout(
|
||||||
@@ -117,19 +123,19 @@
|
|||||||
300,
|
300,
|
||||||
function () {
|
function () {
|
||||||
$( this ).remove();
|
$( this ).remove();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
5000
|
5000,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize when document is ready.
|
// Initialize when document is ready.
|
||||||
$( document ).ready(
|
$( document ).ready(
|
||||||
function () {
|
function () {
|
||||||
WPSTAdmin.init();
|
WPSTAdmin.init();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
})( jQuery );
|
})( jQuery );
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
if ($( e.target ).hasClass( 'wpst-modal' )) {
|
if ($( e.target ).hasClass( 'wpst-modal' )) {
|
||||||
WPSTUpdateSourceSelector.closeModal();
|
WPSTUpdateSourceSelector.closeModal();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Select source option.
|
// Select source option.
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
data: {
|
data: {
|
||||||
action: 'wpst_set_update_source', // AJAX action hook.
|
action: 'wpst_set_update_source', // AJAX action hook.
|
||||||
nonce: wpstModalData.nonce, // Security nonce.
|
nonce: wpstModalData.nonce, // Security nonce.
|
||||||
source: this.selectedSource
|
source: this.selectedSource,
|
||||||
},
|
},
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
function () {
|
function () {
|
||||||
WPSTUpdateSourceSelector.closeModal();
|
WPSTUpdateSourceSelector.closeModal();
|
||||||
},
|
},
|
||||||
1500
|
1500,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
WPSTUpdateSourceSelector.showMessage( 'error', response.data.message );
|
WPSTUpdateSourceSelector.showMessage( 'error', response.data.message );
|
||||||
@@ -139,40 +139,44 @@
|
|||||||
complete: function () {
|
complete: function () {
|
||||||
// Reset button state.
|
// Reset button state.
|
||||||
$saveButton.prop( 'disabled', false ).text( wpstModalData.i18n.confirm );
|
$saveButton.prop( 'disabled', false ).text( wpstModalData.i18n.confirm );
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a message in the modal
|
* Show a message in the modal
|
||||||
*
|
*
|
||||||
* @param {string} type Message type (success, error)
|
* @param {string} type Message type (success, error)
|
||||||
* @param {string} message Message text
|
* @param {string} message Message text
|
||||||
*/
|
*/
|
||||||
showMessage: function (type, message) {
|
showMessage: function (type, message) {
|
||||||
const $message = this.$modal.find( '.wpst-modal-message' );
|
const $message = this.$modal.find( '.wpst-modal-message' );
|
||||||
|
|
||||||
// Set message content and type.
|
// Validate type against allow-list to prevent class injection vulnerabilities.
|
||||||
$message.html( message ).removeClass( 'success error' ).addClass( type ).show();
|
const allowedTypes = [ 'success', 'error' ];
|
||||||
|
const safeType = allowedTypes.includes( type ) ? type : 'error';
|
||||||
|
|
||||||
|
// Set message as plain text to prevent XSS, then apply validated type class.
|
||||||
|
$message.text( message ).removeClass( 'success error' ).addClass( safeType ).show();
|
||||||
|
|
||||||
// Hide message after a delay for success messages.
|
// Hide message after a delay for success messages.
|
||||||
if (type === 'success') {
|
if (safeType === 'success') {
|
||||||
setTimeout(
|
setTimeout(
|
||||||
function () {
|
function () {
|
||||||
$message.fadeOut( 300 );
|
$message.fadeOut( 300 );
|
||||||
},
|
},
|
||||||
3000
|
3000,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize when document is ready.
|
// Initialize when document is ready.
|
||||||
$( document ).ready(
|
$( document ).ready(
|
||||||
function () {
|
function () {
|
||||||
WPSTUpdateSourceSelector.init();
|
WPSTUpdateSourceSelector.init();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
})( jQuery );
|
})( jQuery );
|
||||||
|
|||||||
@@ -12,11 +12,22 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<!-- Update Source Modal -->
|
<!-- Update Source Modal -->
|
||||||
<div id="wpst-update-source-modal" class="wpst-modal">
|
<div
|
||||||
|
id="wpst-update-source-modal"
|
||||||
|
class="wpst-modal"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="wpst-update-source-modal-title"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
<div class="wpst-modal-content">
|
<div class="wpst-modal-content">
|
||||||
<div class="wpst-modal-header">
|
<div class="wpst-modal-header">
|
||||||
<h2 class="wpst-modal-title"><?php esc_html_e( 'Select Update Source', 'wp-plugin-starter-template' ); ?></h2>
|
<h2 id="wpst-update-source-modal-title" class="wpst-modal-title"><?php esc_html_e( 'Select Update Source', 'wp-plugin-starter-template' ); ?></h2>
|
||||||
<span class="wpst-modal-close">×</span>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wpst-modal-close"
|
||||||
|
aria-label="<?php esc_attr_e( 'Close dialog', 'wp-plugin-starter-template' ); ?>"
|
||||||
|
>×</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wpst-modal-body">
|
<div class="wpst-modal-body">
|
||||||
|
|||||||
@@ -17,15 +17,19 @@ WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
|
|||||||
WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
|
WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
|
||||||
|
|
||||||
download() {
|
download() {
|
||||||
if command -v curl > /dev/null; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -s "$1" > "$2";
|
curl -fsSL "$1" -o "$2"
|
||||||
elif command -v wget > /dev/null; then
|
elif command -v wget >/dev/null 2>&1; then
|
||||||
wget -nv -O "$2" "$1"
|
wget -qO "$2" "$1"
|
||||||
fi
|
else
|
||||||
|
echo "Error: Neither curl nor wget is installed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+\-(beta|RC)[0-9]+$ ]]; then
|
if [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+\-(beta|RC)[0-9]+$ ]]; then
|
||||||
WP_BRANCH=${WP_VERSION%\-*}
|
WP_BRANCH=${WP_VERSION%\-*}
|
||||||
|
WP_TESTS_TAG="branches/$WP_BRANCH"
|
||||||
elif [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then
|
elif [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then
|
||||||
WP_TESTS_TAG="branches/$WP_VERSION"
|
WP_TESTS_TAG="branches/$WP_VERSION"
|
||||||
elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
||||||
@@ -40,27 +44,38 @@ elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
|
|||||||
else
|
else
|
||||||
# http serves a single offer, whereas https serves multiple. we only want one
|
# http serves a single offer, whereas https serves multiple. we only want one
|
||||||
download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
|
download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
|
||||||
grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
|
LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//' | head -1)
|
||||||
LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
|
|
||||||
if [[ -z "$LATEST_VERSION" ]]; then
|
if [[ -z "$LATEST_VERSION" ]]; then
|
||||||
echo "Latest WordPress version could not be found"
|
echo "Latest WordPress version could not be found"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
WP_TESTS_TAG="tags/$LATEST_VERSION"
|
WP_TESTS_TAG="tags/$LATEST_VERSION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Derive a git ref from WP_TESTS_TAG by stripping the SVN-style prefix.
|
||||||
|
# WP_TESTS_TAG uses "tags/X.Y.Z", "branches/X.Y", or "trunk".
|
||||||
|
# git clone --branch requires the bare ref name ("X.Y.Z", "X.Y", or "trunk").
|
||||||
|
if [[ "$WP_TESTS_TAG" == tags/* ]]; then
|
||||||
|
GIT_REF="${WP_TESTS_TAG#tags/}"
|
||||||
|
elif [[ "$WP_TESTS_TAG" == branches/* ]]; then
|
||||||
|
GIT_REF="${WP_TESTS_TAG#branches/}"
|
||||||
|
else
|
||||||
|
GIT_REF="$WP_TESTS_TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
install_wp() {
|
install_wp() {
|
||||||
|
|
||||||
if [ -d "$WP_CORE_DIR" ]; then
|
if [ -d "$WP_CORE_DIR" ]; then
|
||||||
return;
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$WP_CORE_DIR"
|
mkdir -p "$WP_CORE_DIR"
|
||||||
|
|
||||||
if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
|
if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
|
||||||
mkdir -p "$WP_CORE_DIR"
|
mkdir -p "$WP_CORE_DIR"
|
||||||
download https://wordpress.org/nightly-builds/wordpress-latest.zip "$WP_CORE_DIR/wordpress-nightly.zip"
|
download https://wordpress.org/nightly-builds/wordpress-latest.zip "$WP_CORE_DIR/wordpress-nightly.zip"
|
||||||
unzip -q "$WP_CORE_DIR/wordpress-nightly.zip" -d "$WP_CORE_DIR"
|
unzip -q "$WP_CORE_DIR/wordpress-nightly.zip" -d "$WP_CORE_DIR"
|
||||||
rm "$WP_CORE_DIR/wordpress-nightly.zip"
|
rm "$WP_CORE_DIR/wordpress-nightly.zip"
|
||||||
else
|
else
|
||||||
@@ -71,6 +86,7 @@ install_wp() {
|
|||||||
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then
|
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then
|
||||||
LATEST_VERSION=${WP_VERSION%??}
|
LATEST_VERSION=${WP_VERSION%??}
|
||||||
else
|
else
|
||||||
|
# shellcheck disable=SC2001
|
||||||
VERSION_ESCAPED=$(echo "$WP_VERSION" | sed 's/\./\\\\./g')
|
VERSION_ESCAPED=$(echo "$WP_VERSION" | sed 's/\./\\\\./g')
|
||||||
LATEST_VERSION=$(grep -o '"version":"'"$VERSION_ESCAPED"'[^"]*' "$WP_CORE_DIR/wp-latest.json" | sed 's/"version":"//' | head -1)
|
LATEST_VERSION=$(grep -o '"version":"'"$VERSION_ESCAPED"'[^"]*' "$WP_CORE_DIR/wp-latest.json" | sed 's/"version":"//' | head -1)
|
||||||
fi
|
fi
|
||||||
@@ -82,7 +98,7 @@ install_wp() {
|
|||||||
else
|
else
|
||||||
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
||||||
fi
|
fi
|
||||||
download https://wordpress.org/"${ARCHIVE_NAME}".tar.gz "$WP_CORE_DIR/wordpress.tar.gz"
|
download https://wordpress.org/"${ARCHIVE_NAME}".tar.gz "$WP_CORE_DIR/wordpress.tar.gz"
|
||||||
tar --strip-components=1 -zxmf "$WP_CORE_DIR/wordpress.tar.gz" -C "$WP_CORE_DIR"
|
tar --strip-components=1 -zxmf "$WP_CORE_DIR/wordpress.tar.gz" -C "$WP_CORE_DIR"
|
||||||
rm "$WP_CORE_DIR/wordpress.tar.gz"
|
rm "$WP_CORE_DIR/wordpress.tar.gz"
|
||||||
fi
|
fi
|
||||||
@@ -101,12 +117,22 @@ install_test_suite() {
|
|||||||
# set up testing suite if it doesn't yet exist
|
# set up testing suite if it doesn't yet exist
|
||||||
if [ ! -d "$WP_TESTS_DIR" ]; then
|
if [ ! -d "$WP_TESTS_DIR" ]; then
|
||||||
mkdir -p "$WP_TESTS_DIR"
|
mkdir -p "$WP_TESTS_DIR"
|
||||||
git clone --quiet --depth=1 https://github.com/WordPress/wordpress-develop.git /tmp/wordpress-develop
|
rm -rf /tmp/wordpress-develop
|
||||||
|
if ! git clone --quiet --depth=1 --branch "$GIT_REF" https://github.com/WordPress/wordpress-develop.git /tmp/wordpress-develop; then
|
||||||
|
echo "Error: Failed to clone wordpress-develop at branch/tag $GIT_REF" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
if [ -d /tmp/wordpress-develop/tests/phpunit/includes ]; then
|
if [ -d /tmp/wordpress-develop/tests/phpunit/includes ]; then
|
||||||
cp -r /tmp/wordpress-develop/tests/phpunit/includes "$WP_TESTS_DIR/"
|
if ! cp -r /tmp/wordpress-develop/tests/phpunit/includes "$WP_TESTS_DIR/"; then
|
||||||
|
echo "Error: Failed to copy phpunit includes to $WP_TESTS_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [ -d /tmp/wordpress-develop/tests/phpunit/data ]; then
|
if [ -d /tmp/wordpress-develop/tests/phpunit/data ]; then
|
||||||
cp -r /tmp/wordpress-develop/tests/phpunit/data "$WP_TESTS_DIR/"
|
if ! cp -r /tmp/wordpress-develop/tests/phpunit/data "$WP_TESTS_DIR/"; then
|
||||||
|
echo "Error: Failed to copy phpunit data to $WP_TESTS_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -116,15 +142,15 @@ install_test_suite() {
|
|||||||
else
|
else
|
||||||
download https://raw.githubusercontent.com/WordPress/wordpress-develop/master/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
|
download https://raw.githubusercontent.com/WordPress/wordpress-develop/master/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
fi
|
fi
|
||||||
WP_CORE_DIR=$(echo "$WP_CORE_DIR" | sed "s:/\+$::")
|
WP_CORE_DIR="${WP_CORE_DIR%/}"
|
||||||
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
|
sed "$ioption" "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
|
sed "$ioption" "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
|
sed "$ioption" "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
|
sed "$ioption" "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
|
sed "$ioption" "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
|
||||||
if [ "$MULTISITE" = "true" ]; then
|
if [ "$MULTISITE" = "true" ]; then
|
||||||
sed $ioption "s:// define( 'WP_TESTS_MULTISITE', true );:define( 'WP_TESTS_MULTISITE', true );:" "$WP_TESTS_DIR"/wp-tests-config.php
|
sed "$ioption" "s:// define( 'WP_TESTS_MULTISITE', true );:define( 'WP_TESTS_MULTISITE', true );:" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -132,27 +158,27 @@ install_test_suite() {
|
|||||||
|
|
||||||
install_db() {
|
install_db() {
|
||||||
|
|
||||||
if [ ${SKIP_DB_CREATE} = "true" ]; then
|
if [ "${SKIP_DB_CREATE}" = "true" ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local PARTS
|
local PARTS
|
||||||
IFS=':' read -ra PARTS <<< "$DB_HOST"
|
IFS=':' read -ra PARTS <<<"$DB_HOST"
|
||||||
local DB_HOSTNAME=${PARTS[0]};
|
local DB_HOSTNAME=${PARTS[0]}
|
||||||
local DB_SOCK_OR_PORT=${PARTS[1]};
|
local DB_SOCK_OR_PORT=${PARTS[1]}
|
||||||
local EXTRA=""
|
local EXTRA=""
|
||||||
|
|
||||||
if [ -n "$DB_HOSTNAME" ] ; then
|
if [ -n "$DB_HOSTNAME" ]; then
|
||||||
if [[ $DB_SOCK_OR_PORT =~ ^[0-9]+$ ]]; then
|
if [[ $DB_SOCK_OR_PORT =~ ^[0-9]+$ ]]; then
|
||||||
EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
|
EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
|
||||||
elif [ -n "$DB_SOCK_OR_PORT" ] ; then
|
elif [ -n "$DB_SOCK_OR_PORT" ]; then
|
||||||
EXTRA=" --socket=$DB_SOCK_OR_PORT"
|
EXTRA=" --socket=$DB_SOCK_OR_PORT"
|
||||||
elif [ -n "$DB_HOSTNAME" ] ; then
|
elif [ -n "$DB_HOSTNAME" ]; then
|
||||||
EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
|
EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mysqladmin create "$DB_NAME" --user="$DB_USER" --password="$DB_PASS"$EXTRA || true
|
mysqladmin create "$DB_NAME" --user="$DB_USER" --password="$DB_PASS""$EXTRA" || true
|
||||||
}
|
}
|
||||||
|
|
||||||
install_wp
|
install_wp
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ set -e
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
PLUGIN_SLUG="wp-plugin-starter-template"
|
PLUGIN_SLUG="wp-plugin-starter-template"
|
||||||
PLUGIN_TEXT_DOMAIN="wp-plugin-starter-template"
|
|
||||||
|
|
||||||
# LocalWP paths (macOS)
|
# LocalWP paths (macOS)
|
||||||
LOCAL_SITES_DIR="$HOME/Local Sites"
|
LOCAL_SITES_DIR="$HOME/Local Sites"
|
||||||
@@ -51,363 +50,375 @@ NC='\033[0m' # No Color
|
|||||||
|
|
||||||
# Helper functions
|
# Helper functions
|
||||||
log_info() {
|
log_info() {
|
||||||
echo -e "${BLUE}[INFO]${NC} $1"
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
log_success() {
|
log_success() {
|
||||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
log_warning() {
|
log_warning() {
|
||||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
log_error() {
|
log_error() {
|
||||||
echo -e "${RED}[ERROR]${NC} $1"
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
log_step() {
|
log_step() {
|
||||||
echo -e "${CYAN}[STEP]${NC} $1"
|
echo -e "${CYAN}[STEP]${NC} $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if LocalWP is installed
|
# Check if LocalWP is installed
|
||||||
check_localwp() {
|
check_localwp() {
|
||||||
if [ ! -d "$LOCAL_APP" ]; then
|
if [ ! -d "$LOCAL_APP" ]; then
|
||||||
log_error "LocalWP is not installed at $LOCAL_APP"
|
log_error "LocalWP is not installed at $LOCAL_APP"
|
||||||
log_info "Download from: https://localwp.com/"
|
log_info "Download from: https://localwp.com/"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$LOCAL_WP_CLI" ]; then
|
if [ ! -f "$LOCAL_WP_CLI" ]; then
|
||||||
log_error "WP-CLI not found in LocalWP installation"
|
log_error "WP-CLI not found in LocalWP installation"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local version=$("$LOCAL_WP_CLI" --version 2>/dev/null || echo "unknown")
|
local version
|
||||||
log_info "LocalWP WP-CLI version: $version"
|
version=$("$LOCAL_WP_CLI" --version 2>/dev/null || echo "unknown")
|
||||||
|
log_info "LocalWP WP-CLI version: $version"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get site path
|
# Get site path
|
||||||
get_site_path() {
|
get_site_path() {
|
||||||
local site_name="$1"
|
local site_name="$1"
|
||||||
echo "$LOCAL_SITES_DIR/$site_name"
|
echo "$LOCAL_SITES_DIR/$site_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get WordPress path within site
|
# Get WordPress path within site
|
||||||
get_wp_path() {
|
get_wp_path() {
|
||||||
local site_name="$1"
|
local site_name="$1"
|
||||||
local site_path=$(get_site_path "$site_name")
|
local site_path
|
||||||
|
site_path=$(get_site_path "$site_name")
|
||||||
# LocalWP uses app/public for WordPress files
|
|
||||||
echo "$site_path/app/public"
|
# LocalWP uses app/public for WordPress files
|
||||||
|
echo "$site_path/app/public"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if site exists
|
# Check if site exists
|
||||||
site_exists() {
|
site_exists() {
|
||||||
local site_name="$1"
|
local site_name="$1"
|
||||||
local site_path=$(get_site_path "$site_name")
|
local site_path
|
||||||
[ -d "$site_path" ]
|
site_path=$(get_site_path "$site_name")
|
||||||
|
[ -d "$site_path" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get plugin destination path
|
# Get plugin destination path
|
||||||
get_plugin_path() {
|
get_plugin_path() {
|
||||||
local site_name="$1"
|
local site_name="$1"
|
||||||
local wp_path=$(get_wp_path "$site_name")
|
local wp_path
|
||||||
echo "$wp_path/wp-content/plugins/$PLUGIN_SLUG"
|
wp_path=$(get_wp_path "$site_name")
|
||||||
|
echo "$wp_path/wp-content/plugins/$PLUGIN_SLUG"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sync plugin files to LocalWP site
|
# Sync plugin files to LocalWP site
|
||||||
sync_plugin() {
|
sync_plugin() {
|
||||||
local site_name="$1"
|
local site_name="$1"
|
||||||
local plugin_dest=$(get_plugin_path "$site_name")
|
local plugin_dest
|
||||||
|
plugin_dest=$(get_plugin_path "$site_name")
|
||||||
if ! site_exists "$site_name"; then
|
|
||||||
log_error "Site '$site_name' does not exist"
|
if ! site_exists "$site_name"; then
|
||||||
return 1
|
log_error "Site '$site_name' does not exist"
|
||||||
fi
|
return 1
|
||||||
|
fi
|
||||||
log_info "Syncing plugin to $site_name..."
|
|
||||||
|
log_info "Syncing plugin to $site_name..."
|
||||||
# Create plugin directory if it doesn't exist
|
|
||||||
mkdir -p "$plugin_dest"
|
# Create plugin directory if it doesn't exist
|
||||||
|
mkdir -p "$plugin_dest"
|
||||||
# Sync files using rsync (excludes dev files)
|
|
||||||
rsync -av --delete \
|
# Sync files using rsync (excludes dev files)
|
||||||
--exclude 'node_modules' \
|
rsync -av --delete \
|
||||||
--exclude 'vendor' \
|
--exclude 'node_modules' \
|
||||||
--exclude '.git' \
|
--exclude 'vendor' \
|
||||||
--exclude 'dist' \
|
--exclude '.git' \
|
||||||
--exclude 'tests' \
|
--exclude 'dist' \
|
||||||
--exclude 'cypress' \
|
--exclude 'tests' \
|
||||||
--exclude '.github' \
|
--exclude 'cypress' \
|
||||||
--exclude '.agents' \
|
--exclude '.github' \
|
||||||
--exclude '.wiki' \
|
--exclude '.agents' \
|
||||||
--exclude 'reference-plugins' \
|
--exclude '.wiki' \
|
||||||
--exclude '*.zip' \
|
--exclude 'reference-plugins' \
|
||||||
--exclude '.playground.*' \
|
--exclude '*.zip' \
|
||||||
--exclude 'composer.lock' \
|
--exclude '.playground.*' \
|
||||||
--exclude 'package-lock.json' \
|
--exclude 'composer.lock' \
|
||||||
"$PROJECT_DIR/" "$plugin_dest/"
|
--exclude 'package-lock.json' \
|
||||||
|
"$PROJECT_DIR/" "$plugin_dest/"
|
||||||
log_success "Plugin synced to: $plugin_dest"
|
|
||||||
|
log_success "Plugin synced to: $plugin_dest"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a new LocalWP site
|
# Create a new LocalWP site
|
||||||
create_site() {
|
create_site() {
|
||||||
local multisite=false
|
local multisite=false
|
||||||
|
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--multisite)
|
--multisite)
|
||||||
multisite=true
|
multisite=true
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
local site_name="$SINGLE_SITE_NAME"
|
local site_name="$SINGLE_SITE_NAME"
|
||||||
local domain="$SINGLE_SITE_DOMAIN"
|
local domain="$SINGLE_SITE_DOMAIN"
|
||||||
local mode="single site"
|
local mode="single site"
|
||||||
|
|
||||||
if [ "$multisite" = true ]; then
|
if [ "$multisite" = true ]; then
|
||||||
site_name="$MULTISITE_NAME"
|
site_name="$MULTISITE_NAME"
|
||||||
domain="$MULTISITE_DOMAIN"
|
domain="$MULTISITE_DOMAIN"
|
||||||
mode="multisite"
|
mode="multisite"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
check_localwp
|
check_localwp
|
||||||
|
|
||||||
local site_path=$(get_site_path "$site_name")
|
local site_path
|
||||||
|
site_path=$(get_site_path "$site_name")
|
||||||
if site_exists "$site_name"; then
|
|
||||||
log_warning "Site '$site_name' already exists at: $site_path"
|
if site_exists "$site_name"; then
|
||||||
log_info "Use 'npm run localwp:reset' to reset it, or 'npm run localwp:sync' to update files"
|
log_warning "Site '$site_name' already exists at: $site_path"
|
||||||
return 0
|
log_info "Use 'npm run localwp:reset' to reset it, or 'npm run localwp:sync' to update files"
|
||||||
fi
|
return 0
|
||||||
|
fi
|
||||||
echo ""
|
|
||||||
echo "============================================"
|
echo ""
|
||||||
echo " LocalWP Site Setup ($mode)"
|
echo "============================================"
|
||||||
echo "============================================"
|
echo " LocalWP Site Setup ($mode)"
|
||||||
echo ""
|
echo "============================================"
|
||||||
echo "This script will guide you through creating a"
|
echo ""
|
||||||
echo "LocalWP site for testing the plugin."
|
echo "This script will guide you through creating a"
|
||||||
echo ""
|
echo "LocalWP site for testing the plugin."
|
||||||
echo "Site Details:"
|
echo ""
|
||||||
echo " Name: $site_name"
|
echo "Site Details:"
|
||||||
echo " Domain: $domain"
|
echo " Name: $site_name"
|
||||||
echo " Path: $site_path"
|
echo " Domain: $domain"
|
||||||
echo ""
|
echo " Path: $site_path"
|
||||||
|
echo ""
|
||||||
log_step "Creating LocalWP Site"
|
|
||||||
echo ""
|
log_step "Creating LocalWP Site"
|
||||||
log_info "LocalWP doesn't have a CLI for site creation."
|
echo ""
|
||||||
log_info "Please create the site manually in LocalWP:"
|
log_info "LocalWP doesn't have a CLI for site creation."
|
||||||
echo ""
|
log_info "Please create the site manually in LocalWP:"
|
||||||
echo "1. Open LocalWP application"
|
echo ""
|
||||||
echo "2. Click the '+' button to create a new site"
|
echo "1. Open LocalWP application"
|
||||||
echo "3. Use these settings:"
|
echo "2. Click the '+' button to create a new site"
|
||||||
echo " - Site name: ${CYAN}$site_name${NC}"
|
echo "3. Use these settings:"
|
||||||
echo " - Local site domain: ${CYAN}$domain${NC}"
|
echo " - Site name: ${CYAN}$site_name${NC}"
|
||||||
echo " - PHP version: 8.0 or higher"
|
echo " - Local site domain: ${CYAN}$domain${NC}"
|
||||||
echo " - Web server: nginx (preferred)"
|
echo " - PHP version: 8.0 or higher"
|
||||||
echo " - MySQL version: 8.0+"
|
echo " - Web server: nginx (preferred)"
|
||||||
|
echo " - MySQL version: 8.0+"
|
||||||
if [ "$multisite" = true ]; then
|
|
||||||
echo ""
|
if [ "$multisite" = true ]; then
|
||||||
echo "4. After site creation, convert to multisite:"
|
echo ""
|
||||||
echo " - Open Site Shell in LocalWP"
|
echo "4. After site creation, convert to multisite:"
|
||||||
echo " - Run: wp core multisite-convert --subdomains=0"
|
echo " - Open Site Shell in LocalWP"
|
||||||
echo " - Update wp-config.php if needed"
|
echo " - Run: wp core multisite-convert --subdomains=0"
|
||||||
fi
|
echo " - Update wp-config.php if needed"
|
||||||
|
fi
|
||||||
echo ""
|
|
||||||
log_info "After creating the site, run: npm run localwp:sync"
|
echo ""
|
||||||
echo ""
|
log_info "After creating the site, run: npm run localwp:sync"
|
||||||
|
echo ""
|
||||||
# Wait for user to create site
|
|
||||||
read -p "Press Enter after you've created the site in LocalWP..."
|
# Wait for user to create site
|
||||||
|
read -r -p "Press Enter after you've created the site in LocalWP..."
|
||||||
if site_exists "$site_name"; then
|
|
||||||
log_success "Site detected at: $site_path"
|
if site_exists "$site_name"; then
|
||||||
sync_plugin "$site_name"
|
log_success "Site detected at: $site_path"
|
||||||
|
sync_plugin "$site_name"
|
||||||
# Install recommended plugins
|
|
||||||
install_recommended_plugins "$site_name"
|
# Install recommended plugins
|
||||||
|
install_recommended_plugins "$site_name"
|
||||||
show_site_info "$site_name" "$domain" "$multisite"
|
|
||||||
else
|
show_site_info "$site_name" "$domain" "$multisite"
|
||||||
log_warning "Site not found at expected location"
|
else
|
||||||
log_info "Expected path: $site_path"
|
log_warning "Site not found at expected location"
|
||||||
log_info "You can run 'npm run localwp:sync' later to sync files"
|
log_info "Expected path: $site_path"
|
||||||
fi
|
log_info "You can run 'npm run localwp:sync' later to sync files"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Install recommended plugins (matching Playground blueprint)
|
# Install recommended plugins (matching Playground blueprint)
|
||||||
install_recommended_plugins() {
|
install_recommended_plugins() {
|
||||||
local site_name="$1"
|
local site_name="$1"
|
||||||
local wp_path=$(get_wp_path "$site_name")
|
local wp_path
|
||||||
|
wp_path=$(get_wp_path "$site_name")
|
||||||
log_info "Note: Install these plugins to match Playground environment:"
|
|
||||||
echo " - Plugin Toggle (plugin-toggle)"
|
log_info "Note: Install these plugins to match Playground environment:"
|
||||||
echo " - Kadence Blocks (kadence-blocks)"
|
echo " - Plugin Toggle (plugin-toggle)"
|
||||||
echo ""
|
echo " - Kadence Blocks (kadence-blocks)"
|
||||||
log_info "You can install them via LocalWP's WP Admin or Site Shell"
|
echo ""
|
||||||
|
log_info "You can install them via LocalWP's WP Admin or Site Shell"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show site information
|
# Show site information
|
||||||
show_site_info() {
|
show_site_info() {
|
||||||
local site_name="$1"
|
local site_name="$1"
|
||||||
local domain="$2"
|
local domain="$2"
|
||||||
local multisite="$3"
|
local multisite="$3"
|
||||||
|
|
||||||
local site_path=$(get_site_path "$site_name")
|
local site_path
|
||||||
local plugin_path=$(get_plugin_path "$site_name")
|
site_path=$(get_site_path "$site_name")
|
||||||
|
local plugin_path
|
||||||
echo ""
|
plugin_path=$(get_plugin_path "$site_name")
|
||||||
echo "============================================"
|
|
||||||
echo " LocalWP Site Ready"
|
echo ""
|
||||||
echo "============================================"
|
echo "============================================"
|
||||||
echo " Site: $site_name"
|
echo " LocalWP Site Ready"
|
||||||
echo " URL: http://$domain"
|
echo "============================================"
|
||||||
echo " Admin: http://$domain/wp-admin/"
|
echo " Site: $site_name"
|
||||||
echo " Plugin Path: $plugin_path"
|
echo " URL: http://$domain"
|
||||||
echo "============================================"
|
echo " Admin: http://$domain/wp-admin/"
|
||||||
|
echo " Plugin Path: $plugin_path"
|
||||||
if [ "$multisite" = true ]; then
|
echo "============================================"
|
||||||
echo " Network Admin: http://$domain/wp-admin/network/"
|
|
||||||
echo "============================================"
|
if [ "$multisite" = true ]; then
|
||||||
fi
|
echo " Network Admin: http://$domain/wp-admin/network/"
|
||||||
|
echo "============================================"
|
||||||
echo ""
|
fi
|
||||||
log_info "Remember to:"
|
|
||||||
echo " 1. Start the site in LocalWP"
|
echo ""
|
||||||
echo " 2. Activate the plugin in WordPress admin"
|
log_info "Remember to:"
|
||||||
echo " 3. Run 'npm run localwp:sync' after making changes"
|
echo " 1. Start the site in LocalWP"
|
||||||
echo ""
|
echo " 2. Activate the plugin in WordPress admin"
|
||||||
|
echo " 3. Run 'npm run localwp:sync' after making changes"
|
||||||
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Reset site to clean state
|
# Reset site to clean state
|
||||||
reset_site() {
|
reset_site() {
|
||||||
local site_name="${1:-$SINGLE_SITE_NAME}"
|
local site_name="${1:-$SINGLE_SITE_NAME}"
|
||||||
|
|
||||||
if ! site_exists "$site_name"; then
|
if ! site_exists "$site_name"; then
|
||||||
log_error "Site '$site_name' does not exist"
|
log_error "Site '$site_name' does not exist"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log_warning "This will delete the plugin files and resync them."
|
log_warning "This will delete the plugin files and resync them."
|
||||||
read -p "Continue? (y/n) " -n 1 -r
|
read -p "Continue? (y/n) " -n 1 -r
|
||||||
echo
|
echo
|
||||||
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
local plugin_path=$(get_plugin_path "$site_name")
|
local plugin_path
|
||||||
|
plugin_path=$(get_plugin_path "$site_name")
|
||||||
log_info "Removing plugin files..."
|
|
||||||
rm -rf "$plugin_path"
|
log_info "Removing plugin files..."
|
||||||
|
rm -rf "$plugin_path"
|
||||||
log_info "Resyncing plugin..."
|
|
||||||
sync_plugin "$site_name"
|
log_info "Resyncing plugin..."
|
||||||
|
sync_plugin "$site_name"
|
||||||
log_success "Site reset complete"
|
|
||||||
else
|
log_success "Site reset complete"
|
||||||
log_info "Reset cancelled"
|
else
|
||||||
fi
|
log_info "Reset cancelled"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sync all existing sites
|
# Sync all existing sites
|
||||||
sync_all() {
|
sync_all() {
|
||||||
local synced=0
|
local synced=0
|
||||||
|
|
||||||
for site_name in "$SINGLE_SITE_NAME" "$MULTISITE_NAME"; do
|
for site_name in "$SINGLE_SITE_NAME" "$MULTISITE_NAME"; do
|
||||||
if site_exists "$site_name"; then
|
if site_exists "$site_name"; then
|
||||||
sync_plugin "$site_name"
|
sync_plugin "$site_name"
|
||||||
synced=$((synced + 1))
|
synced=$((synced + 1))
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ $synced -eq 0 ]; then
|
if [ $synced -eq 0 ]; then
|
||||||
log_warning "No LocalWP sites found for this plugin"
|
log_warning "No LocalWP sites found for this plugin"
|
||||||
log_info "Run 'npm run localwp:create' to create one"
|
log_info "Run 'npm run localwp:create' to create one"
|
||||||
else
|
else
|
||||||
log_success "Synced $synced site(s)"
|
log_success "Synced $synced site(s)"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show info about all sites
|
# Show info about all sites
|
||||||
show_info() {
|
show_info() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "LocalWP Sites for $PLUGIN_SLUG"
|
echo "LocalWP Sites for $PLUGIN_SLUG"
|
||||||
echo "==============================="
|
echo "==============================="
|
||||||
|
|
||||||
for site_name in "$SINGLE_SITE_NAME" "$MULTISITE_NAME"; do
|
for site_name in "$SINGLE_SITE_NAME" "$MULTISITE_NAME"; do
|
||||||
local site_path=$(get_site_path "$site_name")
|
local site_path
|
||||||
|
site_path=$(get_site_path "$site_name")
|
||||||
if site_exists "$site_name"; then
|
|
||||||
echo ""
|
if site_exists "$site_name"; then
|
||||||
echo " ${GREEN}✓${NC} $site_name"
|
echo ""
|
||||||
echo " Path: $site_path"
|
echo " ${GREEN}✓${NC} $site_name"
|
||||||
|
echo " Path: $site_path"
|
||||||
local plugin_path=$(get_plugin_path "$site_name")
|
|
||||||
if [ -d "$plugin_path" ]; then
|
local plugin_path
|
||||||
echo " Plugin: ${GREEN}Installed${NC}"
|
plugin_path=$(get_plugin_path "$site_name")
|
||||||
else
|
if [ -d "$plugin_path" ]; then
|
||||||
echo " Plugin: ${YELLOW}Not synced${NC}"
|
echo " Plugin: ${GREEN}Installed${NC}"
|
||||||
fi
|
else
|
||||||
else
|
echo " Plugin: ${YELLOW}Not synced${NC}"
|
||||||
echo ""
|
fi
|
||||||
echo " ${YELLOW}○${NC} $site_name (not created)"
|
else
|
||||||
fi
|
echo ""
|
||||||
done
|
echo " ${YELLOW}○${NC} $site_name (not created)"
|
||||||
|
fi
|
||||||
echo ""
|
done
|
||||||
echo "Commands:"
|
|
||||||
echo " npm run localwp:create Create single site"
|
echo ""
|
||||||
echo " npm run localwp:create:multisite Create multisite"
|
echo "Commands:"
|
||||||
echo " npm run localwp:sync Sync plugin files"
|
echo " npm run localwp:create Create single site"
|
||||||
echo " npm run localwp:reset Reset plugin files"
|
echo " npm run localwp:create:multisite Create multisite"
|
||||||
echo ""
|
echo " npm run localwp:sync Sync plugin files"
|
||||||
|
echo " npm run localwp:reset Reset plugin files"
|
||||||
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main command handler
|
# Main command handler
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
create)
|
create)
|
||||||
shift
|
shift
|
||||||
create_site "$@"
|
create_site "$@"
|
||||||
;;
|
;;
|
||||||
sync)
|
sync)
|
||||||
sync_all
|
sync_all
|
||||||
;;
|
;;
|
||||||
reset)
|
reset)
|
||||||
shift
|
shift
|
||||||
reset_site "$@"
|
reset_site "$@"
|
||||||
;;
|
;;
|
||||||
info)
|
info)
|
||||||
show_info
|
show_info
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "LocalWP Integration Script"
|
echo "LocalWP Integration Script"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Usage:"
|
echo "Usage:"
|
||||||
echo " $0 create [--multisite] Create a new LocalWP site"
|
echo " $0 create [--multisite] Create a new LocalWP site"
|
||||||
echo " $0 sync Sync plugin files to all sites"
|
echo " $0 sync Sync plugin files to all sites"
|
||||||
echo " $0 reset [site-name] Reset site plugin to clean state"
|
echo " $0 reset [site-name] Reset site plugin to clean state"
|
||||||
echo " $0 info Show info about LocalWP sites"
|
echo " $0 info Show info about LocalWP sites"
|
||||||
echo ""
|
echo ""
|
||||||
echo "npm scripts:"
|
echo "npm scripts:"
|
||||||
echo " npm run localwp:create Create single site"
|
echo " npm run localwp:create Create single site"
|
||||||
echo " npm run localwp:create:multisite Create multisite"
|
echo " npm run localwp:create:multisite Create multisite"
|
||||||
echo " npm run localwp:sync Sync plugin files"
|
echo " npm run localwp:sync Sync plugin files"
|
||||||
echo " npm run localwp:reset Reset plugin files"
|
echo " npm run localwp:reset Reset plugin files"
|
||||||
echo ""
|
echo ""
|
||||||
echo "URL Patterns:"
|
echo "URL Patterns:"
|
||||||
echo " Single site: http://${PLUGIN_SLUG}-single.local"
|
echo " Single site: http://${PLUGIN_SLUG}-single.local"
|
||||||
echo " Multisite: http://${PLUGIN_SLUG}-multisite.local"
|
echo " Multisite: http://${PLUGIN_SLUG}-multisite.local"
|
||||||
echo ""
|
echo ""
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -1,126 +1,139 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Make this script executable
|
|
||||||
chmod +x "$0"
|
|
||||||
|
|
||||||
# Check if environment type is provided
|
# Check if environment type is provided
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Usage: $0 [single|multisite|playground-single|playground-multisite]"
|
echo "Usage: $0 [single|multisite|playground-single|playground-multisite]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ENV_TYPE=$1
|
ENV_TYPE=$1
|
||||||
|
|
||||||
# Function to check if a command exists
|
# Function to check if a command exists
|
||||||
command_exists() {
|
command_exists() {
|
||||||
command -v "$1" &> /dev/null
|
command -v "$1" &>/dev/null
|
||||||
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# PID of the background Python HTTP server (set when started).
|
||||||
|
PYTHON_PID=""
|
||||||
|
|
||||||
|
# Function to clean up resources on exit.
|
||||||
|
cleanup() {
|
||||||
|
if [ -n "$PYTHON_PID" ]; then
|
||||||
|
echo "Stopping Python HTTP server (PID: $PYTHON_PID)..."
|
||||||
|
kill "$PYTHON_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trap EXIT, INT, and TERM so the server is always stopped on script exit.
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
# Function to install wp-env if needed
|
# Function to install wp-env if needed
|
||||||
install_wp_env() {
|
install_wp_env() {
|
||||||
if ! command_exists wp-env; then
|
if ! command_exists wp-env; then
|
||||||
echo "wp-env is not installed. Installing..."
|
echo "wp-env is not installed. Installing..."
|
||||||
npm install -g @wordpress/env
|
npm install -g @wordpress/env
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to install wp-playground if needed
|
# Function to install wp-playground if needed
|
||||||
install_wp_playground() {
|
install_wp_playground() {
|
||||||
# Check if we have a local installation
|
# Check if we have a local installation
|
||||||
if [ ! -d "node_modules/@wp-playground" ]; then
|
if [ ! -d "node_modules/@wp-playground" ]; then
|
||||||
echo "WordPress Playground is not installed locally. Installing..."
|
echo "WordPress Playground is not installed locally. Installing..."
|
||||||
npm install --save-dev @wp-playground/client @wp-playground/blueprints
|
npm install --save-dev @wp-playground/client @wp-playground/blueprints
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$ENV_TYPE" == "single" ]; then
|
if [ "$ENV_TYPE" = "single" ]; then
|
||||||
echo "Setting up single site environment..."
|
echo "Setting up single site environment..."
|
||||||
|
|
||||||
# Install wp-env if needed
|
# Install wp-env if needed
|
||||||
install_wp_env
|
install_wp_env
|
||||||
|
|
||||||
# Start the environment
|
# Start the environment
|
||||||
wp-env start
|
wp-env start
|
||||||
|
|
||||||
# Wait for WordPress to be ready with a timeout
|
# Wait for WordPress to be ready with a timeout
|
||||||
MAX_ATTEMPTS=30
|
MAX_ATTEMPTS=30
|
||||||
ATTEMPT=0
|
ATTEMPT=0
|
||||||
echo "Waiting for WordPress to be ready..."
|
echo "Waiting for WordPress to be ready..."
|
||||||
until wp-env run cli wp core is-installed || [ $ATTEMPT -ge $MAX_ATTEMPTS ]; do
|
until wp-env run cli wp core is-installed || [ $ATTEMPT -ge $MAX_ATTEMPTS ]; do
|
||||||
ATTEMPT=$((ATTEMPT+1))
|
ATTEMPT=$((ATTEMPT + 1))
|
||||||
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS..."
|
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS..."
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then
|
if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then
|
||||||
echo "Timed out waiting for WordPress to be ready."
|
echo "Timed out waiting for WordPress to be ready."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Activate our plugin
|
# Activate our plugin
|
||||||
if ! wp-env run cli wp plugin activate wp-plugin-starter-template-for-ai-coding; then
|
if ! wp-env run cli wp plugin activate wp-plugin-starter-template-for-ai-coding; then
|
||||||
echo "Failed to activate plugin. Exiting."
|
echo "Failed to activate plugin. Exiting."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "WordPress Single Site environment is ready!"
|
echo "WordPress Single Site environment is ready!"
|
||||||
echo "Site: http://localhost:8888"
|
echo "Site: http://localhost:8888"
|
||||||
echo "Admin login: admin / password"
|
echo "Admin login: admin / password"
|
||||||
|
|
||||||
elif [ "$ENV_TYPE" == "multisite" ]; then
|
elif [ "$ENV_TYPE" = "multisite" ]; then
|
||||||
echo "Setting up multisite environment..."
|
echo "Setting up multisite environment..."
|
||||||
|
|
||||||
# Install wp-env if needed
|
# Install wp-env if needed
|
||||||
install_wp_env
|
install_wp_env
|
||||||
|
|
||||||
# Start the environment with multisite configuration
|
# Start the environment with multisite configuration
|
||||||
wp-env start --config=.wp-env.multisite.json
|
wp-env start --config=.wp-env.multisite.json
|
||||||
|
|
||||||
# Wait for WordPress to be ready with a timeout
|
# Wait for WordPress to be ready with a timeout
|
||||||
MAX_ATTEMPTS=30
|
MAX_ATTEMPTS=30
|
||||||
ATTEMPT=0
|
ATTEMPT=0
|
||||||
echo "Waiting for WordPress to be ready..."
|
echo "Waiting for WordPress to be ready..."
|
||||||
until wp-env run cli wp core is-installed || [ $ATTEMPT -ge $MAX_ATTEMPTS ]; do
|
until wp-env run cli wp core is-installed || [ $ATTEMPT -ge $MAX_ATTEMPTS ]; do
|
||||||
ATTEMPT=$((ATTEMPT+1))
|
ATTEMPT=$((ATTEMPT + 1))
|
||||||
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS..."
|
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS..."
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then
|
if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then
|
||||||
echo "Timed out waiting for WordPress to be ready."
|
echo "Timed out waiting for WordPress to be ready."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create a test site
|
# Create a test site
|
||||||
if ! wp-env run cli wp site create --slug=testsite --title="Test Site" --email=admin@example.com; then
|
if ! wp-env run cli wp site create --slug=testsite --title="Test Site" --email=admin@example.com; then
|
||||||
echo "Failed to create test site. Exiting."
|
echo "Failed to create test site. Exiting."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Network activate our plugin
|
# Network activate our plugin
|
||||||
if ! wp-env run cli wp plugin activate wp-plugin-starter-template-for-ai-coding --network; then
|
if ! wp-env run cli wp plugin activate wp-plugin-starter-template-for-ai-coding --network; then
|
||||||
echo "Failed to activate plugin. Exiting."
|
echo "Failed to activate plugin. Exiting."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "WordPress Multisite environment is ready!"
|
echo "WordPress Multisite environment is ready!"
|
||||||
echo "Main site: http://localhost:8888"
|
echo "Main site: http://localhost:8888"
|
||||||
echo "Test site: http://localhost:8888/testsite"
|
echo "Test site: http://localhost:8888/testsite"
|
||||||
echo "Admin login: admin / password"
|
echo "Admin login: admin / password"
|
||||||
|
|
||||||
elif [ "$ENV_TYPE" == "playground-single" ]; then
|
elif [ "$ENV_TYPE" = "playground-single" ]; then
|
||||||
echo "Setting up WordPress Playground single site environment..."
|
echo "Setting up WordPress Playground single site environment..."
|
||||||
|
|
||||||
# Install wp-playground if needed
|
# Install wp-playground if needed
|
||||||
install_wp_playground
|
install_wp_playground
|
||||||
|
|
||||||
# Create plugin zip
|
# Create plugin zip
|
||||||
echo "Creating plugin zip..."
|
echo "Creating plugin zip..."
|
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
zip -r dist/plugin.zip . -x "node_modules/*" "dist/*" ".git/*"
|
zip -r dist/plugin.zip . -x "node_modules/*" "dist/*" ".git/*"
|
||||||
|
|
||||||
# Update blueprint to use local plugin
|
# Update blueprint to use local plugin
|
||||||
cat > playground/blueprint.json << EOF
|
cat >playground/blueprint.json <<EOF
|
||||||
{
|
{
|
||||||
"landingPage": "/wp-admin/",
|
"landingPage": "/wp-admin/",
|
||||||
"preferredVersions": {
|
"preferredVersions": {
|
||||||
@@ -148,46 +161,49 @@ elif [ "$ENV_TYPE" == "playground-single" ]; then
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Start WordPress Playground
|
# Start WordPress Playground
|
||||||
echo "Starting WordPress Playground..."
|
echo "Starting WordPress Playground..."
|
||||||
if command_exists python3; then
|
if command_exists python3; then
|
||||||
python3 -m http.server 8888 --directory playground &
|
python3 -m http.server 8888 --directory playground &
|
||||||
echo "Opening WordPress Playground in your browser..."
|
PYTHON_PID=$!
|
||||||
if command_exists open; then
|
echo "Started Python HTTP server with PID: $PYTHON_PID"
|
||||||
open http://localhost:8888/index.html
|
echo "Opening WordPress Playground in your browser..."
|
||||||
elif command_exists xdg-open; then
|
if command_exists open; then
|
||||||
xdg-open http://localhost:8888/index.html
|
open http://localhost:8888/index.html
|
||||||
elif command_exists start; then
|
elif command_exists xdg-open; then
|
||||||
start http://localhost:8888/index.html
|
xdg-open http://localhost:8888/index.html
|
||||||
else
|
elif command_exists start; then
|
||||||
echo "Please open http://localhost:8888/index.html in your browser"
|
start http://localhost:8888/index.html
|
||||||
fi
|
else
|
||||||
else
|
echo "Please open http://localhost:8888/index.html in your browser"
|
||||||
echo "Python3 is not installed. Please open playground/index.html in your browser."
|
fi
|
||||||
fi
|
else
|
||||||
|
echo "Python3 is not installed. Please open playground/index.html in your browser."
|
||||||
|
fi
|
||||||
|
|
||||||
# Wait for WordPress Playground to be ready
|
# Wait for WordPress Playground to be ready
|
||||||
echo "Waiting for WordPress Playground to be ready..."
|
echo "Waiting for WordPress Playground to be ready..."
|
||||||
sleep 5
|
sleep 5
|
||||||
|
|
||||||
echo "WordPress Playground Single Site environment is ready!"
|
echo "WordPress Playground Single Site environment is ready!"
|
||||||
echo "Site: http://localhost:8888"
|
echo "Site: http://localhost:8888"
|
||||||
echo "Admin login: admin / password"
|
echo "Admin login: admin / password"
|
||||||
echo "Press Ctrl+C to stop the server when done."
|
echo "Press Ctrl+C to stop the server when done."
|
||||||
|
|
||||||
elif [ "$ENV_TYPE" == "playground-multisite" ]; then
|
elif [ "$ENV_TYPE" = "playground-multisite" ]; then
|
||||||
echo "Setting up WordPress Playground multisite environment..."
|
echo "Setting up WordPress Playground multisite environment..."
|
||||||
|
|
||||||
# Install wp-playground if needed
|
# Install wp-playground if needed
|
||||||
install_wp_playground
|
install_wp_playground
|
||||||
|
|
||||||
# Create plugin zip
|
# Create plugin zip
|
||||||
echo "Creating plugin zip..."
|
echo "Creating plugin zip..."
|
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
zip -r dist/plugin.zip . -x "node_modules/*" "dist/*" ".git/*"
|
zip -r dist/plugin.zip . -x "node_modules/*" "dist/*" ".git/*"
|
||||||
|
|
||||||
# Update blueprint to use local plugin
|
# Update blueprint to use local plugin
|
||||||
cat > playground/multisite-blueprint.json << EOF
|
# shellcheck disable=SC2154
|
||||||
|
cat >playground/multisite-blueprint.json <<EOF
|
||||||
{
|
{
|
||||||
"landingPage": "/wp-admin/network/",
|
"landingPage": "/wp-admin/network/",
|
||||||
"preferredVersions": {
|
"preferredVersions": {
|
||||||
@@ -255,35 +271,37 @@ elif [ "$ENV_TYPE" == "playground-multisite" ]; then
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Start WordPress Playground
|
# Start WordPress Playground
|
||||||
echo "Starting WordPress Playground..."
|
echo "Starting WordPress Playground..."
|
||||||
if command_exists python3; then
|
if command_exists python3; then
|
||||||
python3 -m http.server 8888 --directory playground &
|
python3 -m http.server 8888 --directory playground &
|
||||||
echo "Opening WordPress Playground in your browser..."
|
PYTHON_PID=$!
|
||||||
if command_exists open; then
|
echo "Started Python HTTP server with PID: $PYTHON_PID"
|
||||||
open http://localhost:8888/multisite.html
|
echo "Opening WordPress Playground in your browser..."
|
||||||
elif command_exists xdg-open; then
|
if command_exists open; then
|
||||||
xdg-open http://localhost:8888/multisite.html
|
open http://localhost:8888/multisite.html
|
||||||
elif command_exists start; then
|
elif command_exists xdg-open; then
|
||||||
start http://localhost:8888/multisite.html
|
xdg-open http://localhost:8888/multisite.html
|
||||||
else
|
elif command_exists start; then
|
||||||
echo "Please open http://localhost:8888/multisite.html in your browser"
|
start http://localhost:8888/multisite.html
|
||||||
fi
|
else
|
||||||
else
|
echo "Please open http://localhost:8888/multisite.html in your browser"
|
||||||
echo "Python3 is not installed. Please open playground/multisite.html in your browser."
|
fi
|
||||||
fi
|
else
|
||||||
|
echo "Python3 is not installed. Please open playground/multisite.html in your browser."
|
||||||
|
fi
|
||||||
|
|
||||||
# Wait for WordPress Playground to be ready
|
# Wait for WordPress Playground to be ready
|
||||||
echo "Waiting for WordPress Playground to be ready..."
|
echo "Waiting for WordPress Playground to be ready..."
|
||||||
sleep 5
|
sleep 5
|
||||||
|
|
||||||
echo "WordPress Playground Multisite environment is ready!"
|
echo "WordPress Playground Multisite environment is ready!"
|
||||||
echo "Main site: http://localhost:8888"
|
echo "Main site: http://localhost:8888"
|
||||||
echo "Test site: http://localhost:8888/testsite"
|
echo "Test site: http://localhost:8888/testsite"
|
||||||
echo "Admin login: admin / password"
|
echo "Admin login: admin / password"
|
||||||
echo "Press Ctrl+C to stop the server when done."
|
echo "Press Ctrl+C to stop the server when done."
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "Invalid environment type. Use 'single', 'multisite', 'playground-single', or 'playground-multisite'."
|
echo "Invalid environment type. Use 'single', 'multisite', 'playground-single', or 'playground-multisite'."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
91
build.sh
91
build.sh
@@ -1,13 +1,14 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
# WordPress Plugin Build Script
|
# WordPress Plugin Build Script
|
||||||
# This script creates a clean build of the plugin for distribution
|
# This script creates a clean build of the plugin for distribution
|
||||||
|
|
||||||
# Check if version is provided
|
# Check if version is provided
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "❌ Error: Version number is required"
|
echo "❌ Error: Version number is required"
|
||||||
echo "Usage: ./build.sh <version>"
|
echo "Usage: ./build.sh <version>"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VERSION=$1
|
VERSION=$1
|
||||||
@@ -22,15 +23,15 @@ mkdir -p "$BUILD_DIR"
|
|||||||
|
|
||||||
# Run code quality checks
|
# Run code quality checks
|
||||||
echo "Running code quality checks..."
|
echo "Running code quality checks..."
|
||||||
if command -v composer &> /dev/null; then
|
if command -v composer &>/dev/null; then
|
||||||
echo "Running PHPCS..."
|
echo "Running PHPCS..."
|
||||||
composer run phpcs || { echo "⚠️ PHPCS found issues. Consider running 'composer run phpcbf' to fix them."; }
|
composer run phpcs || { echo "⚠️ PHPCS found issues. Consider running 'composer run phpcbf' to fix them."; }
|
||||||
|
|
||||||
# Uncomment the following line to automatically fix coding standards issues
|
# Uncomment the following line to automatically fix coding standards issues
|
||||||
# echo "Running PHPCBF..."
|
# echo "Running PHPCBF..."
|
||||||
# composer run phpcbf
|
# composer run phpcbf
|
||||||
else
|
else
|
||||||
echo "⚠️ Composer not found, skipping code quality checks"
|
echo "⚠️ Composer not found, skipping code quality checks"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install composer dependencies
|
# Install composer dependencies
|
||||||
@@ -39,72 +40,72 @@ composer install --no-dev --optimize-autoloader
|
|||||||
|
|
||||||
# Copy plugin files to build directory
|
# Copy plugin files to build directory
|
||||||
echo "Copying plugin files..."
|
echo "Copying plugin files..."
|
||||||
cp -R *.php "$BUILD_DIR/"
|
cp -R ./*.php "$BUILD_DIR/"
|
||||||
cp -R README.md LICENSE CHANGELOG.md readme.txt composer.json "$BUILD_DIR/"
|
cp -R README.md LICENSE CHANGELOG.md readme.txt composer.json "$BUILD_DIR/"
|
||||||
|
|
||||||
# Copy directories
|
# Copy directories
|
||||||
echo "Copying directories..."
|
echo "Copying directories..."
|
||||||
mkdir -p "$BUILD_DIR/admin" "$BUILD_DIR/includes" "$BUILD_DIR/languages" "$BUILD_DIR/assets"
|
mkdir -p "$BUILD_DIR/admin" "$BUILD_DIR/includes" "$BUILD_DIR/languages" "$BUILD_DIR/assets"
|
||||||
cp -R admin/* "$BUILD_DIR/admin/"
|
cp -R ./admin/* "$BUILD_DIR/admin/"
|
||||||
cp -R includes/* "$BUILD_DIR/includes/"
|
cp -R ./includes/* "$BUILD_DIR/includes/"
|
||||||
cp -R languages/* "$BUILD_DIR/languages/"
|
cp -R ./languages/* "$BUILD_DIR/languages/"
|
||||||
|
|
||||||
# Create assets directory structure
|
# Create assets directory structure
|
||||||
mkdir -p "$BUILD_DIR/assets/banner" "$BUILD_DIR/assets/icon" "$BUILD_DIR/assets/screenshots"
|
mkdir -p "$BUILD_DIR/assets/banner" "$BUILD_DIR/assets/icon" "$BUILD_DIR/assets/screenshots"
|
||||||
|
|
||||||
# Copy assets if they exist
|
# Copy assets if they exist
|
||||||
if [ -d "assets/banner" ]; then
|
if [ -d "assets/banner" ]; then
|
||||||
cp -R assets/banner/* "$BUILD_DIR/assets/banner/"
|
cp -R assets/banner/* "$BUILD_DIR/assets/banner/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -d "assets/icon" ]; then
|
if [ -d "assets/icon" ]; then
|
||||||
cp -R assets/icon/* "$BUILD_DIR/assets/icon/"
|
cp -R assets/icon/* "$BUILD_DIR/assets/icon/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -d "assets/screenshots" ]; then
|
if [ -d "assets/screenshots" ]; then
|
||||||
cp -R assets/screenshots/* "$BUILD_DIR/assets/screenshots/"
|
cp -R assets/screenshots/* "$BUILD_DIR/assets/screenshots/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy vendor directory if it exists
|
# Copy vendor directory if it exists
|
||||||
if [ -d "vendor" ]; then
|
if [ -d "vendor" ]; then
|
||||||
cp -R vendor "$BUILD_DIR/"
|
cp -R vendor "$BUILD_DIR/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create ZIP file
|
# Create ZIP file.
|
||||||
echo "Creating ZIP file..."
|
echo "Creating ZIP file..."
|
||||||
cd build
|
(
|
||||||
zip -r "../$ZIP_FILE" "$PLUGIN_SLUG" -x "*.DS_Store" -x "*.git*" -x "*.github*"
|
cd build || exit 1
|
||||||
cd ..
|
zip -r "../$ZIP_FILE" "$PLUGIN_SLUG" -x "*.DS_Store" -x "*.git*" -x "*.github*"
|
||||||
|
)
|
||||||
|
|
||||||
# Check if ZIP file was created successfully
|
# Check if ZIP file was created successfully
|
||||||
if [ -f "$ZIP_FILE" ]; then
|
if [ -f "$ZIP_FILE" ]; then
|
||||||
echo "✅ Build successful: $ZIP_FILE created"
|
echo "✅ Build successful: $ZIP_FILE created"
|
||||||
echo "File path: $(pwd)/$ZIP_FILE"
|
echo "File path: $(pwd)/$ZIP_FILE"
|
||||||
|
|
||||||
# Deploy to local WordPress installation if environment variable is set
|
# Deploy to local WordPress installation if environment variable is set
|
||||||
if [ -n "$WP_LOCAL_PLUGIN_DIR" ]; then
|
if [ -n "${WP_LOCAL_PLUGIN_DIR:-}" ]; then
|
||||||
echo "\nDeploying to local WordPress installation..."
|
printf '\nDeploying to local WordPress installation...\n'
|
||||||
echo "Deploying to local WordPress installation..."
|
|
||||||
|
|
||||||
# Remove existing plugin directory
|
# Remove existing plugin directory.
|
||||||
rm -rf "$WP_LOCAL_PLUGIN_DIR/$PLUGIN_SLUG"
|
rm -rf "${WP_LOCAL_PLUGIN_DIR:?}/$PLUGIN_SLUG"
|
||||||
|
|
||||||
# Copy files to local WordPress installation
|
# Copy files to local WordPress installation
|
||||||
rsync -av --exclude=".git" --exclude=".github" --exclude=".DS_Store" \
|
rsync -av --exclude=".git" --exclude=".github" --exclude=".DS_Store" \
|
||||||
"$BUILD_DIR/" "$WP_LOCAL_PLUGIN_DIR/$PLUGIN_SLUG"
|
"$BUILD_DIR/" "$WP_LOCAL_PLUGIN_DIR/$PLUGIN_SLUG"
|
||||||
|
|
||||||
# Clear WordPress transients if WP-CLI is available
|
# Clear WordPress transients if WP-CLI is available
|
||||||
if command -v wp &> /dev/null; then
|
if command -v wp &>/dev/null; then
|
||||||
echo "Clearing WordPress transients..."
|
echo "Clearing WordPress transients..."
|
||||||
wp transient delete --all --path="$WP_LOCAL_PLUGIN_DIR/../.."
|
wp transient delete --all --path="$WP_LOCAL_PLUGIN_DIR/../.."
|
||||||
else
|
else
|
||||||
echo "⚠️ WP-CLI not found, skipping transient clearing"
|
echo "⚠️ WP-CLI not found, skipping transient clearing"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "✅ Local deployment successful!"
|
echo "✅ Local deployment successful!"
|
||||||
echo "Plugin deployed to: $WP_LOCAL_PLUGIN_DIR/$PLUGIN_SLUG"
|
echo "Plugin deployed to: $WP_LOCAL_PLUGIN_DIR/$PLUGIN_SLUG"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "❌ Build failed: ZIP file was not created"
|
echo "❌ Build failed: ZIP file was not created"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ module.exports = defineConfig({
|
|||||||
},
|
},
|
||||||
// Add configuration for WordPress Playground
|
// Add configuration for WordPress Playground
|
||||||
experimentalWebKitSupport: true,
|
experimentalWebKitSupport: true,
|
||||||
chromeWebSecurity: false
|
chromeWebSecurity: false,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
/* eslint-env mocha, jquery, cypress */
|
/* eslint-env mocha, jquery, cypress */
|
||||||
describe('WordPress Playground Single Site Tests', () => {
|
describe('WordPress Playground Single Site Tests', {
|
||||||
|
retries: {
|
||||||
|
runMode: 2,
|
||||||
|
openMode: 0,
|
||||||
|
},
|
||||||
|
}, () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.visit('/', { timeout: 30000 });
|
cy.visit('/', { timeout: 30000 });
|
||||||
});
|
});
|
||||||
@@ -18,14 +23,22 @@ describe('WordPress Playground Single Site Tests', () => {
|
|||||||
cy.visit('/wp-admin/plugins.php', { timeout: 30000 });
|
cy.visit('/wp-admin/plugins.php', { timeout: 30000 });
|
||||||
|
|
||||||
cy.get('body', { timeout: 15000 }).then(($body) => {
|
cy.get('body', { timeout: 15000 }).then(($body) => {
|
||||||
if ($body.text().includes('Plugin Toggle')) {
|
const hasPluginToggle = $body.text().includes('Plugin Toggle');
|
||||||
|
const hasKadenceBlocks = $body.text().includes('Kadence Blocks');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
hasPluginToggle || hasKadenceBlocks,
|
||||||
|
'At least one blueprint plugin should be present in the plugins table',
|
||||||
|
).to.be.true;
|
||||||
|
|
||||||
|
if (hasPluginToggle) {
|
||||||
cy.contains('tr', 'Plugin Toggle').should('exist');
|
cy.contains('tr', 'Plugin Toggle').should('exist');
|
||||||
cy.contains('tr', 'Plugin Toggle').find('.deactivate').should('exist');
|
cy.contains('tr', 'Plugin Toggle').find('.deactivate').should('exist');
|
||||||
} else {
|
} else {
|
||||||
cy.log('Plugin Toggle not found, skipping check');
|
cy.log('Plugin Toggle not found, skipping check');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($body.text().includes('Kadence Blocks')) {
|
if (hasKadenceBlocks) {
|
||||||
cy.contains('tr', 'Kadence Blocks').find('.deactivate').should('exist');
|
cy.contains('tr', 'Kadence Blocks').find('.deactivate').should('exist');
|
||||||
} else {
|
} else {
|
||||||
cy.log('Kadence Blocks plugin not found, skipping check');
|
cy.log('Kadence Blocks plugin not found, skipping check');
|
||||||
|
|||||||
@@ -1,30 +1,75 @@
|
|||||||
describe('WordPress Single Site Tests', () => {
|
/* eslint-env mocha, jquery, cypress */
|
||||||
it('Can access the site', () => {
|
describe( 'WordPress Single Site Tests', () => {
|
||||||
cy.visit('/');
|
it( 'Can access the site', () => {
|
||||||
cy.get('body').should('exist');
|
cy.visit( '/' );
|
||||||
});
|
cy.get( 'body' ).should( 'exist' );
|
||||||
|
} );
|
||||||
|
|
||||||
it('Can login to the admin area', () => {
|
it( 'Can login to the admin area', () => {
|
||||||
cy.loginAsAdmin();
|
cy.loginAsAdmin();
|
||||||
cy.get('#wpadminbar').should('exist');
|
cy.get( '#wpadminbar' ).should( 'exist' );
|
||||||
cy.get('#dashboard-widgets').should('exist');
|
cy.get( '#dashboard-widgets' ).should( 'exist' );
|
||||||
});
|
} );
|
||||||
|
|
||||||
it('Plugin is activated', () => {
|
it( 'Plugin is activated', () => {
|
||||||
// Use our custom command to check and activate the plugin if needed
|
// Use our custom command to check and activate the plugin if needed.
|
||||||
cy.activatePlugin('wp-plugin-starter-template-for-ai-coding');
|
cy.activatePlugin( 'wp-plugin-starter-template-for-ai-coding' );
|
||||||
|
|
||||||
// Verify it's active
|
// Verify it's active.
|
||||||
cy.get('tr[data-slug="wp-plugin-starter-template-for-ai-coding"] .deactivate').should('exist');
|
cy.get( 'tr[data-slug="wp-plugin-starter-template-for-ai-coding"] .deactivate' ).should( 'exist' );
|
||||||
});
|
} );
|
||||||
|
|
||||||
it('Plugin settings page loads correctly', () => {
|
it( 'Plugin row is visible on the plugins page', () => {
|
||||||
cy.loginAsAdmin();
|
cy.loginAsAdmin();
|
||||||
|
cy.visit( '/wp-admin/plugins.php' );
|
||||||
|
|
||||||
// Navigate to the plugin settings page (if it exists)
|
// Verify the plugin row exists with the correct slug.
|
||||||
cy.visit('/wp-admin/options-general.php?page=wp-plugin-starter-template');
|
cy.get( 'tr[data-slug="wp-plugin-starter-template-for-ai-coding"]' ).should( 'exist' );
|
||||||
|
|
||||||
// This is a basic check - adjust based on your actual plugin's settings page
|
// Verify the plugin name is displayed.
|
||||||
cy.get('h1').should('contain', 'WP Plugin Starter Template');
|
cy.get( 'tr[data-slug="wp-plugin-starter-template-for-ai-coding"] .plugin-title strong' )
|
||||||
});
|
.should( 'contain', 'WordPress Plugin Starter Template' );
|
||||||
});
|
} );
|
||||||
|
|
||||||
|
it( 'Update source selector link is present in the plugin row', () => {
|
||||||
|
cy.loginAsAdmin();
|
||||||
|
cy.visit( '/wp-admin/plugins.php' );
|
||||||
|
|
||||||
|
// The update source selector link should be rendered in the plugin row.
|
||||||
|
cy.get( 'tr[data-slug="wp-plugin-starter-template-for-ai-coding"]' )
|
||||||
|
.find( '.wpst-update-source-selector' )
|
||||||
|
.should( 'exist' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'Update source modal opens and displays source options', () => {
|
||||||
|
cy.loginAsAdmin();
|
||||||
|
cy.visit( '/wp-admin/plugins.php' );
|
||||||
|
|
||||||
|
// Click the update source selector link to open the modal.
|
||||||
|
cy.get( '.wpst-update-source-selector' ).first().click();
|
||||||
|
|
||||||
|
// Modal should be visible.
|
||||||
|
cy.get( '#wpst-update-source-modal' ).should( 'be.visible' );
|
||||||
|
|
||||||
|
// Modal should contain the three update source options.
|
||||||
|
cy.get( '#wpst-update-source-modal input[name="update_source"][value="wordpress.org"]' ).should( 'exist' );
|
||||||
|
cy.get( '#wpst-update-source-modal input[name="update_source"][value="github"]' ).should( 'exist' );
|
||||||
|
cy.get( '#wpst-update-source-modal input[name="update_source"][value="gitea"]' ).should( 'exist' );
|
||||||
|
|
||||||
|
// Save button should be present.
|
||||||
|
cy.get( '#wpst-save-source' ).should( 'exist' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'Update source modal can be closed', () => {
|
||||||
|
cy.loginAsAdmin();
|
||||||
|
cy.visit( '/wp-admin/plugins.php' );
|
||||||
|
|
||||||
|
// Open the modal.
|
||||||
|
cy.get( '.wpst-update-source-selector' ).first().click();
|
||||||
|
cy.get( '#wpst-update-source-modal' ).should( 'be.visible' );
|
||||||
|
|
||||||
|
// Close the modal via the close button.
|
||||||
|
cy.get( '#wpst-update-source-modal .wpst-modal-close' ).click();
|
||||||
|
cy.get( '#wpst-update-source-modal' ).should( 'not.be.visible' );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 124 KiB |
@@ -46,8 +46,8 @@ class Admin {
|
|||||||
*/
|
*/
|
||||||
public function enqueue_admin_assets(): void {
|
public function enqueue_admin_assets(): void {
|
||||||
|
|
||||||
// @phpcs:disable WordPress.Security.NonceVerification.Recommended
|
// @phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||||
// @phpcs:disable WordPress.Security.NonceVerification.Missing
|
// @phpcs:disable WordPress.Security.NonceVerification.Missing
|
||||||
// For production, use filter_input.
|
// For production, use filter_input.
|
||||||
$page = '';
|
$page = '';
|
||||||
if ( defined( 'PHPUNIT_RUNNING' ) && PHPUNIT_RUNNING ) {
|
if ( defined( 'PHPUNIT_RUNNING' ) && PHPUNIT_RUNNING ) {
|
||||||
@@ -64,15 +64,17 @@ class Admin {
|
|||||||
if ( ! $page || 'wp_plugin_starter_template_settings' !== $page ) {
|
if ( ! $page || 'wp_plugin_starter_template_settings' !== $page ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// @phpcs:enable
|
// @phpcs:enable
|
||||||
|
|
||||||
// Get the plugin version.
|
// Get the plugin version.
|
||||||
$plugin_version = $this->core->get_plugin_version();
|
$plugin_version = $this->core->get_plugin_version();
|
||||||
|
|
||||||
|
$plugin_url = $this->get_plugin_base_url();
|
||||||
|
|
||||||
// Enqueue styles.
|
// Enqueue styles.
|
||||||
\wp_enqueue_style(
|
\wp_enqueue_style(
|
||||||
'wpst-admin-styles',
|
'wpst-admin-styles',
|
||||||
plugin_dir_url( dirname( __DIR__ ) ) . 'admin/css/admin-styles.css',
|
$plugin_url . 'admin/css/admin-styles.css',
|
||||||
array(), // Dependencies.
|
array(), // Dependencies.
|
||||||
$plugin_version // Version.
|
$plugin_version // Version.
|
||||||
);
|
);
|
||||||
@@ -80,7 +82,7 @@ class Admin {
|
|||||||
// Enqueue admin scripts.
|
// Enqueue admin scripts.
|
||||||
\wp_enqueue_script(
|
\wp_enqueue_script(
|
||||||
'wpst-admin-script',
|
'wpst-admin-script',
|
||||||
plugin_dir_url( dirname( __DIR__ ) ) . 'admin/js/admin-scripts.js',
|
$plugin_url . 'admin/js/admin-scripts.js',
|
||||||
array( 'jquery' ),
|
array( 'jquery' ),
|
||||||
$plugin_version, // Version.
|
$plugin_version, // Version.
|
||||||
true
|
true
|
||||||
@@ -99,4 +101,21 @@ class Admin {
|
|||||||
$data
|
$data
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plugin base URL.
|
||||||
|
*
|
||||||
|
* @return string Plugin base URL with trailing slash.
|
||||||
|
*/
|
||||||
|
private function get_plugin_base_url(): string {
|
||||||
|
if ( defined( 'WP_PLUGIN_STARTER_TEMPLATE_URL' ) ) {
|
||||||
|
return WP_PLUGIN_STARTER_TEMPLATE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( defined( 'WPST_PLUGIN_URL' ) ) {
|
||||||
|
return WPST_PLUGIN_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \plugin_dir_url( dirname( __DIR__, 2 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,4 +25,5 @@ if ( is_multisite() ) {
|
|||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
For information on testing your plugin in a multisite environment, see the [Testing Framework](../../.wiki/Testing.md) documentation.
|
For information on testing your plugin in a multisite environment, see the
|
||||||
|
[Testing Framework](../../.wiki/Testing.md) documentation.
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
* Extend this file or create additional classes in this directory
|
* Extend this file or create additional classes in this directory
|
||||||
* to implement multisite features for your plugin.
|
* to implement multisite features for your plugin.
|
||||||
*
|
*
|
||||||
* @package WP_Plugin_Starter_Template_For_AI_Coding
|
* @package WPALLSTARS\PluginStarterTemplate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace WP_Plugin_Starter_Template_For_AI_Coding\Multisite;
|
namespace WPALLSTARS\PluginStarterTemplate\Multisite;
|
||||||
|
|
||||||
// Exit if accessed directly.
|
// Exit if accessed directly.
|
||||||
if ( ! defined( 'ABSPATH' ) ) {
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
|||||||
1180
package-lock.json
generated
1180
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -28,7 +28,8 @@
|
|||||||
"test:phpunit": "composer test",
|
"test:phpunit": "composer test",
|
||||||
"test:phpunit:multisite": "WP_MULTISITE=1 composer test",
|
"test:phpunit:multisite": "WP_MULTISITE=1 composer test",
|
||||||
"build": "./build.sh",
|
"build": "./build.sh",
|
||||||
"lint:js": "eslint cypress/",
|
"lint:js": "eslint cypress/ cypress.config.js",
|
||||||
|
"lint:css": "stylelint \"**/*.css\" --allow-empty-input",
|
||||||
"lint:php": "composer run-script phpcs",
|
"lint:php": "composer run-script phpcs",
|
||||||
"lint:php:simple": "composer run-script phpcs:simple",
|
"lint:php:simple": "composer run-script phpcs:simple",
|
||||||
"lint:phpstan": "composer run-script phpstan",
|
"lint:phpstan": "composer run-script phpstan",
|
||||||
@@ -36,7 +37,8 @@
|
|||||||
"fix:php": "composer run-script phpcbf",
|
"fix:php": "composer run-script phpcbf",
|
||||||
"fix:php:simple": "composer run-script phpcbf:simple",
|
"fix:php:simple": "composer run-script phpcbf:simple",
|
||||||
"test:php": "composer run-script test",
|
"test:php": "composer run-script test",
|
||||||
"lint": "composer run-script lint",
|
"lint:php-all": "composer run-script lint",
|
||||||
|
"lint": "npm run lint:php-all && npm run lint:js && npm run lint:css",
|
||||||
"fix": "composer run-script fix",
|
"fix": "composer run-script fix",
|
||||||
"quality": "npm run lint && npm run test:php"
|
"quality": "npm run lint && npm run test:php"
|
||||||
},
|
},
|
||||||
@@ -60,10 +62,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@wordpress/env": "^8.12.0",
|
"@wordpress/env": "^8.12.0",
|
||||||
"@wp-playground/blueprints": "^3.0.22",
|
"@wp-playground/blueprints": "^3.0.22",
|
||||||
"@wp-playground/client": "^3.0.22",
|
|
||||||
"@wp-playground/cli": "^3.0.22",
|
"@wp-playground/cli": "^3.0.22",
|
||||||
|
"@wp-playground/client": "^3.0.22",
|
||||||
"cypress": "^13.17.0",
|
"cypress": "^13.17.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-cypress": "^2.15.1"
|
"eslint-plugin-cypress": "^6.2.0",
|
||||||
|
"stylelint": "^16.0.0",
|
||||||
|
"stylelint-config-standard": "^36.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<exclude-pattern>*/build/*</exclude-pattern>
|
<exclude-pattern>*/build/*</exclude-pattern>
|
||||||
<exclude-pattern>*/dist/*</exclude-pattern>
|
<exclude-pattern>*/dist/*</exclude-pattern>
|
||||||
|
|
||||||
<!-- Command line arguments -->
|
<!-- Command line arguments: combined short flags (-s shows sniff codes, -p shows progress) -->
|
||||||
<arg value="sp"/>
|
<arg value="sp"/>
|
||||||
<arg name="extensions" value="php"/>
|
<arg name="extensions" value="php"/>
|
||||||
<arg name="basepath" value="."/>
|
<arg name="basepath" value="."/>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
<exclude name="CamelCaseMethodName" />
|
<exclude name="CamelCaseMethodName" />
|
||||||
<exclude name="CamelCaseParameterName" />
|
<exclude name="CamelCaseParameterName" />
|
||||||
<exclude name="CamelCaseVariableName" />
|
<exclude name="CamelCaseVariableName" />
|
||||||
|
<!-- WordPress plugins use filter_input() for production and $_GET for testing; Superglobals rule is not applicable. -->
|
||||||
|
<exclude name="Superglobals" />
|
||||||
</rule>
|
</rule>
|
||||||
<rule ref="rulesets/design.xml" />
|
<rule ref="rulesets/design.xml" />
|
||||||
<rule ref="rulesets/naming.xml">
|
<rule ref="rulesets/naming.xml">
|
||||||
|
|||||||
@@ -5,13 +5,6 @@ parameters:
|
|||||||
- admin
|
- admin
|
||||||
- wp-plugin-starter-template.php
|
- wp-plugin-starter-template.php
|
||||||
excludePaths:
|
excludePaths:
|
||||||
analyse:
|
|
||||||
- vendor
|
|
||||||
- node_modules
|
|
||||||
- tests
|
|
||||||
- bin
|
|
||||||
- build
|
|
||||||
- dist
|
|
||||||
analyseAndScan:
|
analyseAndScan:
|
||||||
- vendor
|
- vendor
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|||||||
@@ -21,6 +21,6 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json&_t=2" title="WordPress Playground Single Site Environment"></iframe>
|
<iframe src="https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wpallstars/wp-plugin-starter-template-for-ai-coding/main/playground/blueprint.json" title="WordPress Playground Single Site Environment"></iframe>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
"landingPage": "/wp-admin/",
|
"landingPage": "/wp-admin/",
|
||||||
"login": true,
|
"login": true,
|
||||||
"features": {
|
"features": {
|
||||||
"networking": true
|
"networking": false
|
||||||
},
|
},
|
||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ When you receive feedback from these code quality tools, you can use AI assistan
|
|||||||
|
|
||||||
1. Copy the output from the code quality tool
|
1. Copy the output from the code quality tool
|
||||||
2. Paste it into your AI assistant chat
|
2. Paste it into your AI assistant chat
|
||||||
3. Ask the AI to help you understand and resolve the issues
|
3. Request the AI's assistance to interpret and resolve the reported issues
|
||||||
4. Apply the suggested fixes
|
4. Apply the suggested fixes
|
||||||
5. Commit the changes and verify that the issues are resolved
|
5. Commit the changes and verify that the issues are resolved
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ if ( getenv( 'WP_PHPUNIT__DIR' ) ) {
|
|||||||
// Include plugin files needed for tests.
|
// Include plugin files needed for tests.
|
||||||
require_once WPST_PLUGIN_DIR . 'includes/class-core.php';
|
require_once WPST_PLUGIN_DIR . 'includes/class-core.php';
|
||||||
require_once WPST_PLUGIN_DIR . 'includes/class-plugin.php';
|
require_once WPST_PLUGIN_DIR . 'includes/class-plugin.php';
|
||||||
if ( file_exists( WPST_PLUGIN_DIR . 'admin/lib/admin.php' ) ) {
|
if ( file_exists( WPST_PLUGIN_DIR . 'includes/Admin/class-admin.php' ) ) {
|
||||||
require_once WPST_PLUGIN_DIR . 'admin/lib/admin.php';
|
require_once WPST_PLUGIN_DIR . 'includes/Admin/class-admin.php';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,17 +101,12 @@ class AdminTest extends \WP_Mock\Tools\TestCase {
|
|||||||
'return' => 'wp_plugin_starter_template_settings',
|
'return' => 'wp_plugin_starter_template_settings',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Mock WordPress functions used in the method
|
|
||||||
WP_Mock::userFunction('plugin_dir_url', [
|
|
||||||
'return' => 'http://example.com/wp-content/plugins/wp-plugin-starter-template/includes/Admin/',
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Mock wp_enqueue_style
|
// Mock wp_enqueue_style
|
||||||
WP_Mock::userFunction('wp_enqueue_style', [
|
WP_Mock::userFunction('wp_enqueue_style', [
|
||||||
'times' => 1,
|
'times' => 1,
|
||||||
'args' => [
|
'args' => [
|
||||||
'wpst-admin-styles',
|
'wpst-admin-styles',
|
||||||
'http://example.com/wp-content/plugins/wp-plugin-starter-template/includes/Admin/../../admin/css/admin-styles.css',
|
'http://example.org/wp-content/plugins/wp-plugin-starter-template/admin/css/admin-styles.css',
|
||||||
[],
|
[],
|
||||||
'1.0.0',
|
'1.0.0',
|
||||||
],
|
],
|
||||||
@@ -122,7 +117,7 @@ class AdminTest extends \WP_Mock\Tools\TestCase {
|
|||||||
'times' => 1,
|
'times' => 1,
|
||||||
'args' => [
|
'args' => [
|
||||||
'wpst-admin-script',
|
'wpst-admin-script',
|
||||||
'http://example.com/wp-content/plugins/wp-plugin-starter-template/includes/Admin/../../admin/js/admin-scripts.js',
|
'http://example.org/wp-content/plugins/wp-plugin-starter-template/admin/js/admin-scripts.js',
|
||||||
['jquery'],
|
['jquery'],
|
||||||
'1.0.0',
|
'1.0.0',
|
||||||
true,
|
true,
|
||||||
|
|||||||
@@ -55,13 +55,19 @@ spl_autoload_register(
|
|||||||
// Get the relative class name.
|
// Get the relative class name.
|
||||||
$relative_class = substr( $className, $len );
|
$relative_class = substr( $className, $len );
|
||||||
|
|
||||||
// Convert namespace to path.
|
// Build class file path using WordPress-style class file names.
|
||||||
$file = WP_PLUGIN_STARTER_TEMPLATE_PATH . 'includes/' . str_replace( '\\', '/', $relative_class ) . '.php';
|
$relative_path = str_replace( '\\', '/', $relative_class );
|
||||||
|
$path_parts = explode( '/', $relative_path );
|
||||||
|
$class_name = array_pop( $path_parts );
|
||||||
|
$directory = '';
|
||||||
|
|
||||||
// Convert class name format to file name format.
|
if ( ! empty( $path_parts ) ) {
|
||||||
$file = str_replace( 'class-', '', $file );
|
$directory = implode( '/', $path_parts ) . '/';
|
||||||
$file = preg_replace( '/([a-z])([A-Z])/', '$1-$2', $file );
|
}
|
||||||
$file = strtolower( $file );
|
|
||||||
|
$class_file = preg_replace( '/([a-z])([A-Z])/', '$1-$2', $class_name );
|
||||||
|
$class_file = 'class-' . strtolower( $class_file ) . '.php';
|
||||||
|
$file = WP_PLUGIN_STARTER_TEMPLATE_PATH . 'includes/' . $directory . $class_file;
|
||||||
|
|
||||||
// If the file exists, require it.
|
// If the file exists, require it.
|
||||||
if ( file_exists( $file ) ) {
|
if ( file_exists( $file ) ) {
|
||||||
|
|||||||
Reference in New Issue
Block a user