Merge branch 'woocommerce:trunk' into patch-4

This commit is contained in:
Marco Almeida 2023-10-17 19:11:13 +01:00 committed by GitHub
commit d98e676998
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1318 changed files with 56469 additions and 21583 deletions

View File

@ -37,6 +37,10 @@ Please take a moment to review the [project readme](https://github.com/woocommer
- Run our build process described in the document on [how to set up WooCommerce development environment](https://github.com/woocommerce/woocommerce/wiki/How-to-set-up-WooCommerce-development-environment), it will install our pre-commit hook, code sniffs, dependencies, and more.
- Before pushing commits to GitHub, check your code against our code standards. For PHP code in the WooCommerce Core project you can do this by running `pnpm --filter=woocommerce run lint:php:changes:branch`.
- Whenever possible, please fix pre-existing code standards errors in code that you change.
- Please consider adding appropriate tests related to your change if applicable such as unit, API and E2E tests. You can check the following guides for this purpose:
- [Writing unit tests](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/tests/README.md#guide-for-writing-unit-tests).
- [Writing API tests](https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/api-core-tests#guide-for-writing-api-tests).
- [Writing E2E tests](https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/e2e-pw#guide-for-writing-e2e-tests).
- Ensure you use LF line endings in your code editor. Use [EditorConfig](http://editorconfig.org/) if your editor supports it so that indentation, line endings and other settings are auto configured.
- When committing, reference your issue number (#1234) and include a note about the fix.
- Ensure that your code supports the minimum supported versions of PHP and WordPress; this is shown at the top of the `readme.txt` file.

View File

@ -1,6 +1,5 @@
name: Run API tests
description: Runs the WooCommerce Core API tests and generates Allure report.
permissions: {}
inputs:
report-name:
@ -8,6 +7,9 @@ inputs:
required: true
tests:
description: Specific tests to run, separated by single whitespace. See https://playwright.dev/docs/test-cli
playwright-config:
description: Playwright config file to be used
default: playwright.config.js
outputs:
result:
@ -23,7 +25,7 @@ runs:
shell: bash
run: |
pnpm exec playwright test \
--config=tests/api-core-tests/playwright.config.js \
--config=tests/api-core-tests/${{ inputs.playwright-config }} \
${{ inputs.tests }}
- name: Generate Test report.

View File

@ -0,0 +1,175 @@
module.exports = async ( { context, core, github } ) => {
const {
API_RESULT,
E2E_RESULT,
k6_RESULT,
PLUGINS_BLOCKS_PATH,
PLUGIN_TESTS_RESULT,
GITHUB_REF_NAME,
GITHUB_RUN_ID,
} = process.env;
const {
selectEmoji,
readContextBlocksFromJsonFiles,
} = require( './utils' );
const URL_GITHUB_RUN_LOG = `https://github.com/woocommerce/woocommerce/actions/runs/${ GITHUB_RUN_ID }`;
const create_blockGroup_header = async () => {
const getRunStartDate = async () => {
const response = await github.rest.actions.getWorkflowRun( {
owner: context.repo.owner,
repo: context.repo.repo,
run_id: GITHUB_RUN_ID,
} );
const runStartedAt = new Date( response.data.run_started_at );
const intlDateTimeFormatOptions = {
dateStyle: 'full',
timeStyle: 'long',
};
const date = new Intl.DateTimeFormat(
'en-US',
intlDateTimeFormatOptions
).format( runStartedAt );
return date;
};
const readableDate = await getRunStartDate();
const blocks = [
{
type: 'header',
text: {
type: 'plain_text',
text: 'Daily test results',
emoji: true,
},
},
{
type: 'divider',
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `*Run started:* ${ readableDate }`,
},
],
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `*Branch:* \`${ GITHUB_REF_NAME }\``,
},
],
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `*GitHub run logs:* <${ URL_GITHUB_RUN_LOG }|${ GITHUB_RUN_ID }>`,
},
],
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: '*Test reports dashboard:* <https://woocommerce.github.io/woocommerce-test-reports/daily/|Daily smoke tests>',
},
],
},
{
type: 'divider',
},
];
return blocks;
};
const create_blockGroup_nightlySite = () => {
const emoji_API = selectEmoji( API_RESULT );
const emoji_E2E = selectEmoji( E2E_RESULT );
const emoji_k6 = selectEmoji( k6_RESULT );
const url_API =
'https://woocommerce.github.io/woocommerce-test-reports/daily/nightly-site/api';
const url_E2E =
'https://woocommerce.github.io/woocommerce-test-reports/daily/nightly-site/e2e';
const url_k6 = URL_GITHUB_RUN_LOG;
const blocks = [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `<${ URL_GITHUB_RUN_LOG }|*Smoke tests on daily build*>`,
},
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `<${ url_API }|API> ${ emoji_API }\t<${ url_E2E }|E2E> ${ emoji_E2E }\t<${ url_k6 }|k6> ${ emoji_k6 }`,
},
],
},
{
type: 'divider',
},
];
return blocks;
};
const create_blockGroups_plugins = () => {
const pluginTestsSkipped = PLUGIN_TESTS_RESULT === 'skipped';
const blocks_pluginTestsSkipped = [
{
type: 'section',
text: {
type: 'mrkdwn',
text: ':warning: *Plugin tests were not run!*',
},
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `Head over to the <${ URL_GITHUB_RUN_LOG }|GitHub workflow run log> to see what went wrong.`,
},
],
},
{
type: 'divider',
},
];
return pluginTestsSkipped
? blocks_pluginTestsSkipped
: readContextBlocksFromJsonFiles( PLUGINS_BLOCKS_PATH );
};
const blockGroup_header = await create_blockGroup_header();
const blockGroup_nightlySite = create_blockGroup_nightlySite();
const blockGroups_plugins = create_blockGroups_plugins();
const blocks_all = [
...blockGroup_header,
...blockGroup_nightlySite,
...blockGroups_plugins.flat(),
];
const payload = {
text: 'Daily test results',
blocks: blocks_all,
};
const payload_stringified = JSON.stringify( payload );
core.setOutput( 'payload', payload_stringified );
};

View File

@ -0,0 +1,37 @@
module.exports = ( { core } ) => {
const { UPLOAD_RESULT, E2E_RESULT, PLUGIN_NAME, PLUGIN_SLUG } = process.env;
const { selectEmoji } = require( './utils' );
const fs = require( 'fs' );
const emoji_UPLOAD = selectEmoji( UPLOAD_RESULT );
const emoji_E2E = selectEmoji( E2E_RESULT );
const reportURL = `https://woocommerce.github.io/woocommerce-test-reports/daily/${ PLUGIN_SLUG }/e2e`;
const blockGroup = [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `<${ reportURL }|*${ PLUGIN_NAME }*>`,
},
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `"Upload plugin" test ${ emoji_UPLOAD }\tOther E2E tests ${ emoji_E2E }`,
},
],
},
{
type: 'divider',
},
];
const blockGroup_stringified = JSON.stringify( blockGroup );
const path = `/tmp/${ PLUGIN_SLUG }.json`;
fs.writeFileSync( path, blockGroup_stringified );
core.setOutput( 'path', path );
};

View File

@ -0,0 +1,26 @@
const fs = require( 'fs' );
const path = require( 'path' );
/**
* @param {string} blocksDir
* @returns {any[][]}
*/
const readContextBlocksFromJsonFiles = ( blocksDir ) => {
const jsonsDir = path.resolve( blocksDir );
const jsons = fs.readdirSync( jsonsDir );
let contextBlocks = [];
for ( const json of jsons ) {
const jsonPath = path.resolve( jsonsDir, json );
const contextBlock = require( jsonPath );
contextBlocks.push( contextBlock );
}
return contextBlocks;
};
module.exports = {
readContextBlocksFromJsonFiles,
};

View File

@ -0,0 +1,7 @@
const { readContextBlocksFromJsonFiles } = require( './get-context-blocks' );
const { selectEmoji } = require( './select-emoji' );
module.exports = {
readContextBlocksFromJsonFiles,
selectEmoji,
};

View File

@ -0,0 +1,26 @@
const emojis = {
PASSED: ':workflow-passed:',
FAILED: ':workflow-failed:',
SKIPPED: ':workflow-skipped:',
CANCELLED: ':workflow-cancelled:',
UNKNOWN: ':grey_question:',
};
const selectEmoji = ( result ) => {
switch ( result ) {
case 'success':
return emojis.PASSED;
case 'failure':
return emojis.FAILED;
case 'skipped':
return emojis.SKIPPED;
case 'cancelled':
return emojis.CANCELLED;
default:
return emojis.UNKNOWN;
}
};
module.exports = {
selectEmoji,
};

View File

@ -67,16 +67,11 @@
'plugin: woo-ai':
- plugins/woo-ai/**/*
'focus: react admin [team:Ghidorah]':
- plugins/woocommerce/src/Admin/**/*
- plugins/woocommerce/src/Internal/Admin/**/*
- plugins/woocommerce-admin/**/*
'focus: performance tests [team:Solaris]':
'focus: performance tests':
- plugins/woocommerce/tests/performance/**/*
'focus: api tests [team:Solaris]':
'focus: api tests':
- plugins/woocommerce/tests/api-core-tests/**/*
'focus: e2e tests [team:Solaris]':
'focus: e2e tests':
- plugins/woocommerce/tests/e2e-pw/**/*

View File

@ -294,6 +294,15 @@ jobs:
core.setOutput( 'cherry-pick-pr', pr.data.html_url )
// label PR
const label = await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.data.number,
labels: ["metric: code freeze exception"],
});
- name: Checkout trunk branch
if: steps.changelog.outputs.changelogsToBeDeleted != '' && steps.changelog.outputs.changelogsToBeDeleted != null
run: git checkout trunk

View File

@ -1,4 +1,4 @@
name: Run tests against PR in an environment with COT enabled
name: Run tests against PR in an environment with HPOS disabled
on:
pull_request:
workflow_dispatch:
@ -10,8 +10,8 @@ concurrency:
permissions: {}
jobs:
cot-e2e-tests-run:
name: Runs E2E tests with COT enabled.
non-hpos-e2e-tests-run:
name: Runs E2E tests with HPOS disabled.
runs-on: ubuntu-20.04
permissions:
contents: read
@ -24,11 +24,9 @@ jobs:
- name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo
- name: Load docker images and start containers with COT enabled.
- name: Load docker images and start containers
working-directory: plugins/woocommerce
env:
ENABLE_HPOS: 1
run: pnpm env:test:cot --filter=woocommerce
run: pnpm env:test --filter=woocommerce
- name: Download and install Chromium browser.
working-directory: plugins/woocommerce
@ -39,6 +37,7 @@ jobs:
id: run_playwright_e2e_tests
env:
USE_WP_ENV: 1
ENABLE_HPOS: 0
working-directory: plugins/woocommerce
run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js
@ -66,8 +65,8 @@ jobs:
if-no-files-found: ignore
retention-days: 5
cot-api-tests-run:
name: Runs API tests with COT enabled.
non-hpos-api-tests-run:
name: Runs API tests with HPOS disabled.
runs-on: ubuntu-20.04
permissions:
contents: read
@ -80,11 +79,9 @@ jobs:
- name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo
- name: Load docker images and start containers with COT enabled.
- name: Load docker images and start containers
working-directory: plugins/woocommerce
env:
ENABLE_HPOS: 1
run: pnpm env:test:cot --filter=woocommerce
run: pnpm env:test --filter=woocommerce
- name: Run Playwright API tests.
id: run_playwright_api_tests
@ -93,6 +90,7 @@ jobs:
BASE_URL: http://localhost:8086
USER_KEY: admin
USER_SECRET: password
ENABLE_HPOS: 0
run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js
- name: Generate Playwright API Test report.
@ -117,4 +115,4 @@ jobs:
${{ env.ALLURE_RESULTS_DIR }}
${{ env.ALLURE_REPORT_DIR }}
if-no-files-found: ignore
retention-days: 5
retention-days: 5

View File

@ -31,7 +31,6 @@ jobs:
- name: Load docker images and start containers.
working-directory: plugins/woocommerce
env:
ENABLE_HPOS: 0
WP_ENV_PHP_VERSION: 7.4
run: pnpm run env:test
@ -265,4 +264,4 @@ jobs:
-f pr_number=$PR_NUMBER \
-f commit_sha=$COMMIT_SHA \
-f s3_root=public \
--repo woocommerce/woocommerce-test-reports
--repo woocommerce/woocommerce-test-reports

View File

@ -26,11 +26,10 @@ jobs:
- name: Get Changed Files
id: changed-files
uses: tj-actions/changed-files@v32
uses: tj-actions/changed-files@v39
with:
path: plugins/woocommerce
files: |
**/*.php
files: "**/*.php"
- name: Setup WooCommerce Monorepo
if: steps.changed-files.outputs.any_changed == 'true'
@ -49,7 +48,4 @@ jobs:
- name: Run PHPCS
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: plugins/woocommerce
run: |
HEAD_REF=$(git rev-parse HEAD)
git checkout $HEAD_REF
phpcs-changed -s --git --git-base ${{ github.base_ref }} ${{ steps.changed-files.outputs.all_changed_files }}
run: phpcs-changed -s --git --git-base ${{ github.event.pull_request.base.sha }} ${{ steps.changed-files.outputs.all_changed_files }}

View File

@ -1,4 +1,4 @@
name: Lint JS packages
name: Lint packages
on:
pull_request:
@ -39,16 +39,16 @@ jobs:
# ignore scripts is faster, and postinstall should not be needed for lint.
pnpm install --ignore-scripts
- name: Lint
- name: Lint JS and CSS
run: pnpm run -r --filter='release-posts' --filter='woocommerce/client/admin...' --filter='@woocommerce/monorepo-utils' --filter='!@woocommerce/e2e*' --filter='!@woocommerce/api' --color lint
continue-on-error: true
- name: Collect and Combine Eslint Reports
if: ${{ github.event.pull_request.head.repo.fork != true && always() }}
run: node ./.github/workflows/scripts/collect-eslint-reports.js
- name: Annotate Code Linting Results
uses: ataylorme/eslint-annotate-action@a1bf7cb320a18aa53cb848a267ce9b7417221526
if: github.event.pull_request.head.repo.fork != true
if: ${{ github.event.pull_request.head.repo.fork != true && always() }}
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
report-json: 'combined_eslint_report.json'

View File

@ -0,0 +1,19 @@
module.exports = async ( { github, context, core } ) => {
const { ASSET_ID: asset_id } = process.env;
const { owner, repo } = context.repo;
const fs = require( 'fs' );
const path = require( 'path' );
const response = await github.rest.repos.getReleaseAsset( {
owner,
repo,
asset_id,
headers: { accept: 'application/octet-stream' },
} );
const zipPath = path.resolve( 'tmp', 'woocommerce.zip' );
fs.mkdirSync( 'tmp' );
fs.writeFileSync( zipPath, Buffer.from( response.data ) );
core.setOutput( 'zip-path', zipPath );
};

View File

@ -0,0 +1,51 @@
module.exports = async ( { github, context, core } ) => {
const { RELEASE_VERSION, GITHUB_EVENT_NAME } = process.env;
async function findRelease() {
const { owner, repo } = context.repo;
const list = await github.rest.repos.listReleases( {
owner,
repo,
per_page: 100,
} );
const match = list.data.find( ( { tag_name, name } ) =>
[ tag_name, name ].includes( RELEASE_VERSION )
);
return match;
}
async function handleWorkflowDispatch() {
const match = await findRelease();
if ( match ) {
return match;
}
throw new Error(
`"${ RELEASE_VERSION }" is not a valid release version!`
);
}
function findWooCommerceZipAsset() {
const match = release.assets.find(
( { name } ) => name === 'woocommerce.zip'
);
if ( ! match ) {
throw new Error(
`Release ${ RELEASE_VERSION } does not contain a woocommerce.zip asset!`
);
}
return match;
}
const release =
GITHUB_EVENT_NAME === 'release'
? await findRelease()
: await handleWorkflowDispatch();
const asset = findWooCommerceZipAsset();
core.setOutput( 'version', RELEASE_VERSION );
core.setOutput( 'created', release.created_at );
core.setOutput( 'asset-id', asset.id );
};

View File

@ -8,6 +8,7 @@ env:
API_ARTIFACT: api-daily--run-${{ github.run_number }}
E2E_ARTIFACT: e2e-daily--run-${{ github.run_number }}
FORCE_COLOR: 1
PLUGIN_SLACK_BLOCKS_ARTIFACT: plugin-blocks
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@ -21,6 +22,8 @@ jobs:
runs-on: ubuntu-20.04
permissions:
contents: read
outputs:
test-result: ${{ steps.run-api-composite-action.outputs.result }}
env:
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/test-results/allure-results
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/test-results/allure-report
@ -32,6 +35,7 @@ jobs:
CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
DEFAULT_TIMEOUT_OVERRIDE: 120000
UPDATE_WC: 'nightly'
steps:
- uses: actions/checkout@v3
@ -41,45 +45,32 @@ jobs:
install-filters: woocommerce
build: false
- name: Download and install Chromium browser.
working-directory: plugins/woocommerce
run: pnpm exec playwright install chromium
- name: Run 'Update WooCommerce' test.
working-directory: plugins/woocommerce
- name: Update site to nightly version
uses: ./.github/actions/tests/run-e2e-tests
with:
report-name: ${{ env.API_ARTIFACT }}
tests: update-woocommerce.spec.js
env:
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
UPDATE_WC: nightly
run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js update-woocommerce.spec.js
- name: Run API tests.
working-directory: plugins/woocommerce
- name: Run API tests
id: run-api-composite-action
uses: ./.github/actions/tests/run-api-tests
with:
report-name: ${{ env.API_ARTIFACT }}
env:
USER_KEY: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
USER_SECRET: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js
- name: Generate API Test report.
if: success() || failure()
working-directory: plugins/woocommerce
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
- name: Archive API test report
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: ${{ env.API_ARTIFACT }}
path: |
${{ env.ALLURE_RESULTS_DIR }}
${{ env.ALLURE_REPORT_DIR }}
if-no-files-found: ignore
retention-days: 5
e2e-tests:
name: E2E tests on nightly build
runs-on: ubuntu-20.04
permissions:
contents: read
needs: [api-tests]
outputs:
test-result: ${{ steps.run-e2e-composite-action.outputs.result }}
# needs: [api-tests]
env:
ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
@ -90,7 +81,6 @@ jobs:
CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
DEFAULT_TIMEOUT_OVERRIDE: 120000
steps:
- uses: actions/checkout@v3
@ -100,33 +90,24 @@ jobs:
install-filters: woocommerce
build: false
- name: Download and install Chromium browser.
working-directory: plugins/woocommerce
run: pnpm exec playwright install chromium
- name: Run E2E tests.
- name: Run E2E tests
id: run-e2e-composite-action
timeout-minutes: 60
working-directory: plugins/woocommerce
uses: ./.github/actions/tests/run-e2e-tests
with:
report-name: ${{ env.E2E_ARTIFACT }}
env:
ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/allure-report
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/allure-results
BASE_URL: ${{ secrets.SMOKE_TEST_URL }}
CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
DEFAULT_TIMEOUT_OVERRIDE: 120000
E2E_MAX_FAILURES: 25
RESET_SITE: true
run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js
- name: Generate Playwright E2E Test report.
if: success() || failure()
working-directory: plugins/woocommerce
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
- name: Archive E2E test report
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: ${{ env.E2E_ARTIFACT }}
path: |
${{ env.ALLURE_RESULTS_DIR }}
${{ env.ALLURE_REPORT_DIR }}
if-no-files-found: ignore
retention-days: 5
k6-tests:
name: k6 tests on nightly build
@ -135,6 +116,8 @@ jobs:
contents: read
needs: [api-tests]
if: success() || failure()
outputs:
test-result: ${{ steps.run-k6-tests.conclusion }}
steps:
- uses: actions/checkout@v3
@ -144,29 +127,31 @@ jobs:
install-filters: woocommerce
build: false
- name: Download and install Chromium browser.
working-directory: plugins/woocommerce
run: pnpm exec playwright install chromium
- name: Update performance test site with E2E test
working-directory: plugins/woocommerce
id: update-perf-site
continue-on-error: true
uses: ./.github/actions/tests/run-e2e-tests
with:
report-name: k6-daily-update-site--run-${{ github.run_number }}
tests: update-woocommerce.spec.js
env:
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-results
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-report
BASE_URL: ${{ secrets.SMOKE_TEST_PERF_URL }}/
ADMIN_USER: ${{ secrets.SMOKE_TEST_PERF_ADMIN_USER }}
ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_PERF_ADMIN_PASSWORD }}
CUSTOMER_USER: ${{ secrets.SMOKE_TEST_PERF_ADMIN_USER }}
CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_PERF_ADMIN_PASSWORD }}
UPDATE_WC: nightly
DEFAULT_TIMEOUT_OVERRIDE: 120000
run: |
pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js update-woocommerce.spec.js
continue-on-error: true
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
UPDATE_WC: nightly
- name: Install k6
run: |
curl https://github.com/grafana/k6/releases/download/v0.33.0/k6-v0.33.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1
- name: Run k6 smoke tests
id: run-k6-tests
env:
URL: ${{ secrets.SMOKE_TEST_PERF_URL }}
HOST: ${{ secrets.SMOKE_TEST_PERF_HOST }}
@ -185,7 +170,6 @@ jobs:
contents: read
needs: [api-tests]
env:
USE_WP_ENV: 1
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-results
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-report
strategy:
@ -194,17 +178,23 @@ jobs:
include:
- plugin: 'WooCommerce Payments'
repo: 'automattic/woocommerce-payments'
slug: woocommerce-payments
- plugin: 'WooCommerce PayPal Payments'
repo: 'woocommerce/woocommerce-paypal-payments'
slug: woocommerce-paypal-payments
- plugin: 'WooCommerce Shipping & Tax'
repo: 'automattic/woocommerce-services'
slug: woocommerce-services
- plugin: 'WooCommerce Subscriptions'
repo: WC_SUBSCRIPTIONS_REPO
private: true
slug: woocommerce-subscriptions
- plugin: 'Gutenberg'
repo: 'WordPress/gutenberg'
slug: gutenberg
- plugin: 'Gutenberg - Nightly'
repo: 'bph/gutenberg'
slug: gutenberg-nightly
steps:
- uses: actions/checkout@v3
@ -213,43 +203,52 @@ jobs:
with:
build-filters: woocommerce
- name: Launch wp-env e2e environment
working-directory: plugins/woocommerce
run: pnpm env:test --filter=woocommerce
- name: Download and install Chromium browser.
working-directory: plugins/woocommerce
run: pnpm exec playwright install chromium
- name: Setup local test environment
uses: ./.github/actions/tests/setup-local-test-environment
with:
test-type: e2e
- name: Run 'Upload plugin' test
working-directory: plugins/woocommerce
id: run-upload-plugin-test
uses: ./.github/actions/tests/run-e2e-tests
with:
report-name: Smoke tests on trunk with ${{ matrix.plugin }} plugin installed (run ${{ github.run_number }})
tests: upload-plugin.spec.js
env:
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
PLUGIN_NAME: ${{ matrix.plugin }}
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: pnpm test:e2e-pw upload-plugin.spec.js
- name: Run the rest of E2E tests
working-directory: plugins/woocommerce
id: run-e2e-composite-action
timeout-minutes: 60
uses: ./.github/actions/tests/run-e2e-tests
with:
playwright-config: ignore-plugin-tests.playwright.config.js
report-name: Smoke tests on trunk with ${{ matrix.plugin }} plugin installed (run ${{ github.run_number }})
env:
E2E_MAX_FAILURES: 15
run: pnpm test:e2e-pw
- name: Generate E2E Test report.
- name: Create context block and save as JSON file
if: success() || failure()
working-directory: plugins/woocommerce
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
id: create-block-json
uses: actions/github-script@v6
with:
script: |
const script = require( './.github/actions/tests/slack-summary-daily/scripts/create-blocks-plugin-tests.js' )
script( { core } );
env:
UPLOAD_RESULT: ${{ steps.run-upload-plugin-test.outputs.result }}
E2E_RESULT: ${{ steps.run-e2e-composite-action.outputs.result }}
PLUGIN_NAME: ${{ matrix.plugin }}
PLUGIN_SLUG: ${{ matrix.slug }}
- name: Archive E2E test report
- name: Upload JSON file as artifact
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: Smoke tests on trunk with ${{ matrix.plugin }} plugin installed (run ${{ github.run_number }})
path: |
${{ env.ALLURE_RESULTS_DIR }}
${{ env.ALLURE_REPORT_DIR }}
if-no-files-found: ignore
retention-days: 5
name: ${{ env.PLUGIN_SLACK_BLOCKS_ARTIFACT }}
path: ${{ steps.create-block-json.outputs.path }}
trunk-results:
name: Publish report on smoke tests on nightly build
@ -311,7 +310,8 @@ jobs:
plugins-results:
name: Publish report on Smoke tests on trunk with plugins
if: |
( success() || failure() ) &&
( success() || failure() ) &&
( needs.test-plugins.result != 'skipped' ) &&
! github.event.pull_request.head.repo.fork
runs-on: ubuntu-20.04
needs: [e2e-tests, test-plugins, k6-tests]
@ -349,4 +349,52 @@ jobs:
-f plugin="${{ matrix.plugin }}" \
-f slug="${{ matrix.slug }}" \
-f s3_root=public \
--repo woocommerce/woocommerce-test-reports
--repo woocommerce/woocommerce-test-reports
post-slack-summary:
name: Post Slack summary
runs-on: ubuntu-20.04
permissions:
contents: read
if: |
success() || (
failure() && contains( needs.*.result, 'failure' )
)
needs:
- api-tests
- e2e-tests
- k6-tests
- test-plugins
steps:
- uses: actions/checkout@v3
- name: Download Slack blocks from plugin tests
if: needs.test-plugins.result != 'skipped'
id: download-plugin-blocks
uses: actions/download-artifact@v3
with:
name: ${{ env.PLUGIN_SLACK_BLOCKS_ARTIFACT }}
path: /tmp/plugin-blocks
- name: Construct Slack payload
id: construct-slack-payload
uses: actions/github-script@v6
with:
script: |
const script = require('./.github/actions/tests/slack-summary-daily/scripts/construct-slack-payload.js');
await script( { context, core, github } );
env:
API_RESULT: ${{ needs.api-tests.outputs.test-result }}
E2E_RESULT: ${{ needs.e2e-tests.outputs.test-result || needs.e2e-tests.result }}
k6_RESULT: ${{ needs.k6-tests.outputs.test-result || needs.k6-tests.result }}
PLUGINS_BLOCKS_PATH: ${{ steps.download-plugin-blocks.outputs.download-path }}
PLUGIN_TESTS_RESULT: ${{ needs.test-plugins.result }}
- name: Send Slack message
id: send-slack-message
uses: slackapi/slack-github-action@v1.23.0
with:
channel-id: ${{ secrets.DAILY_TEST_SLACK_CHANNEL }}
payload: ${{ steps.construct-slack-payload.outputs.payload }}
env:
SLACK_BOT_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}

View File

@ -5,7 +5,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: 'WooCommerce Release Tag'
description: 'WooCommerce release version'
required: true
concurrency:
group: ${{ github.workflow }}-${{ github.event.release.tag_name || inputs.tag }}
@ -16,55 +16,33 @@ env:
E2E_UPDATE_WC_ARTIFACT: WooCommerce version update test on release smoke test site (run ${{ github.run_number }})
SLACK_BLOCKS_ARTIFACT: slack-blocks
jobs:
get-tag:
name: Get WooCommerce release tag
validate-version:
name: Validate release version
permissions:
contents: read
runs-on: ubuntu-20.04
outputs:
tag: ${{ steps.get-tag.outputs.tag }}
created: ${{ steps.created-at.outputs.created }}
version: ${{ steps.validate-version.outputs.version }}
created: ${{ steps.validate-version.outputs.created }}
asset-id: ${{ steps.validate-version.outputs.asset-id }}
steps:
- name: Validate tag
if: ${{ github.event_name == 'workflow_dispatch' }}
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release view "${{ inputs.tag }}" --repo=woocommerce/woocommerce
- uses: actions/checkout@v3
- name: Get tag from triggered event
id: get-tag
- name: Validate release version
id: validate-version
uses: actions/github-script@v6
env:
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }}
run: |
echo "Triggered event: ${{ github.event_name }}"
echo "Tag from event: $RELEASE_TAG"
echo "tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
- name: Verify woocommerce.zip asset
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
RELEASE_TAG: ${{ steps.get-tag.outputs.tag }}
run: |
ASSET_NAMES=$(gh release view $RELEASE_TAG --repo woocommerce/woocommerce --json assets --jq ".assets[].name")
if [[ $ASSET_NAMES == *"woocommerce.zip"* ]]
then
echo "$RELEASE_TAG has a valid woocommerce.zip asset."
exit 0
fi
echo "$RELEASE_TAG does not have a valid woocommerce.zip asset."
exit 1
- name: Get 'created-at' of WooCommerce zip
id: created-at
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: echo "created=$(gh release view ${{ steps.get-tag.outputs.tag }} --json assets --jq .assets[0].createdAt --repo woocommerce/woocommerce)" >> $GITHUB_OUTPUT
RELEASE_VERSION: ${{ inputs.tag }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/validate-release-version.js');
await script({ github, context, core });
e2e-update-wc:
name: Test WooCommerce update
runs-on: ubuntu-20.04
needs: [get-tag]
needs: [validate-version]
permissions:
contents: read
env:
@ -94,7 +72,7 @@ jobs:
CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }}
DEFAULT_TIMEOUT_OVERRIDE: 120000
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
UPDATE_WC: ${{ needs.get-tag.outputs.tag }}
UPDATE_WC: ${{ needs.validate-version.outputs.version }}
- name: Upload Allure artifacts to bucket
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
@ -113,10 +91,10 @@ jobs:
ENV_DESCRIPTION: wp-latest
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -132,12 +110,12 @@ jobs:
test-name: WC Update test
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
api-wp-latest:
name: API on WP Latest
runs-on: ubuntu-20.04
needs: [get-tag, e2e-update-wc]
needs: [validate-version, e2e-update-wc]
permissions:
contents: read
outputs:
@ -155,16 +133,23 @@ jobs:
install-filters: woocommerce
build: false
- name: Download and install Chromium browser.
working-directory: plugins/woocommerce
run: pnpm exec playwright install chromium
- name: Run API tests
id: run-api-composite-action
uses: ./.github/actions/tests/run-api-tests
with:
report-name: ${{ env.API_WP_LATEST_ARTIFACT }}
tests: hello
playwright-config: ci-release.playwright.config.js
env:
BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
API_BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
UPDATE_WC: ${{ needs.validate-version.outputs.version }}
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
- name: Upload Allure artifacts to bucket
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
@ -183,10 +168,10 @@ jobs:
ENV_DESCRIPTION: wp-latest
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \
@ -202,12 +187,12 @@ jobs:
test-name: WP Latest
api-result: ${{ steps.run-api-composite-action.outputs.result }}
env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
e2e-wp-latest:
name: E2E on WP Latest
runs-on: ubuntu-20.04
needs: [get-tag, api-wp-latest]
needs: [validate-version, api-wp-latest]
permissions:
contents: read
env:
@ -285,10 +270,10 @@ jobs:
ENV_DESCRIPTION: wp-latest
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -305,66 +290,33 @@ jobs:
api-result: ${{ needs.api-wp-latest.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
get-wp-versions:
name: Get WP L-1 & L-2 version numbers
needs: [get-tag]
test-wp-latest-1:
name: Test against WP Latest-1
runs-on: ubuntu-20.04
permissions:
contents: read
outputs:
matrix: ${{ steps.get-versions.outputs.versions }}
tag: ${{ needs.get-tag.outputs.tag }}
created: ${{ needs.get-tag.outputs.created }}
steps:
- name: Create dirs
run: |
mkdir script
mkdir repo
- name: Checkout
uses: actions/checkout@v3
with:
path: repo
- name: Copy script to get previous WP versions
run: cp repo/plugins/woocommerce/tests/e2e-pw/utils/wordpress.js script
- name: Install axios
working-directory: script
run: npm install axios
- name: Get version numbers
id: get-versions
uses: actions/github-script@v6
with:
script: |
const { getPreviousTwoVersions } = require('./script/wordpress');
const versions = await getPreviousTwoVersions();
console.log(versions);
core.setOutput('versions', versions);
test-wp-versions:
name: Test against ${{ matrix.version.description }} (${{ matrix.version.number }})
runs-on: ubuntu-20.04
needs: [get-wp-versions]
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.get-wp-versions.outputs.matrix) }}
needs: [validate-version]
env:
API_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-report
API_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-results
API_WP_LATEST_X_ARTIFACT: API test on wp-env with WordPress ${{ matrix.version.number }} (run ${{ github.run_number }})
API_WP_LATEST_X_ARTIFACT: API test on wp-env with WordPress L-1 (run ${{ github.run_number }})
E2E_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/e2e/allure-report
E2E_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/e2e/allure-results
E2E_WP_LATEST_X_ARTIFACT: E2E test on wp-env with WordPress ${{ matrix.version.number }} (run ${{ github.run_number }})
E2E_WP_LATEST_X_ARTIFACT: E2E test on wp-env with WordPress L-1 (run ${{ github.run_number }})
permissions:
contents: read
steps:
- name: Checkout WooCommerce repo
uses: actions/checkout@v3
- name: Get WP Latest-1 version number
id: get-wp-latest-1
uses: actions/github-script@v6
with:
script: |
const { getVersionWPLatestMinusOne } = require( './plugins/woocommerce/tests/e2e-pw/utils/wordpress' );
await getVersionWPLatestMinusOne( { core, github } );
- name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo
with:
@ -373,28 +325,24 @@ jobs:
- name: Launch WP Env
working-directory: plugins/woocommerce
run: pnpm run env:test
env:
WP_ENV_CORE: WordPress/WordPress#${{ steps.get-wp-latest-1.outputs.version }}
- name: Download release zip
id: download-zip
uses: actions/github-script@v6
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release download ${{ needs.get-wp-versions.outputs.tag }} --dir tmp
ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip
- name: Downgrade WordPress version to ${{ matrix.version.number }}
working-directory: plugins/woocommerce
run: |
pnpm exec wp-env run tests-cli -- wp core update --version=${{ matrix.version.number }} --force
pnpm exec wp-env run tests-cli wp core update-db
- name: Verify environment details
working-directory: plugins/woocommerce
run: |
pnpm exec wp-env run tests-cli wp core version
pnpm exec wp-env run tests-cli wp plugin list
pnpm exec wp-env run tests-cli wp theme list
pnpm exec wp-env run tests-cli wp user list
run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run API tests
id: run-api-composite-action
@ -423,13 +371,13 @@ jobs:
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
env:
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
ENV_DESCRIPTION: ${{ matrix.version.env_description }}
ENV_DESCRIPTION: wp-latest-1
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-wp-versions.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-wp-versions.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_WP_LATEST_X_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \
@ -464,13 +412,13 @@ jobs:
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
env:
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
ENV_DESCRIPTION: ${{ matrix.version.env_description }}
ENV_DESCRIPTION: wp-latest-1
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-wp-versions.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-wp-versions.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_X_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -486,16 +434,16 @@ jobs:
)
uses: ./.github/actions/tests/slack-summary-on-release/slack-blocks
with:
test-name: ${{ matrix.version.description }} (${{ matrix.version.number }})
test-name: WP Latest-1 (${{ steps.get-wp-latest-1.outputs.version }})
api-result: ${{ steps.run-api-composite-action.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: ${{ matrix.version.env_description }}
release-version: ${{ needs.get-wp-versions.outputs.tag }}
env-slug: wp-latest-1
release-version: ${{ needs.validate-version.outputs.version }}
test-php-versions:
name: Test against PHP ${{ matrix.php_version }}
runs-on: ubuntu-20.04
needs: [get-tag]
needs: [validate-version]
strategy:
fail-fast: false
matrix:
@ -529,12 +477,20 @@ jobs:
run: bash verify-php-version.sh
- name: Download release zip
id: download-zip
uses: actions/github-script@v6
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release download ${{ needs.get-tag.outputs.tag }} --dir tmp
ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip
run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run API tests
id: run-api-composite-action
@ -566,10 +522,10 @@ jobs:
ENV_DESCRIPTION: php-${{ matrix.php_version }}
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \
@ -607,10 +563,10 @@ jobs:
ENV_DESCRIPTION: php-${{ matrix.php_version }}
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -630,12 +586,12 @@ jobs:
api-result: ${{ steps.run-api-composite-action.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: php-${{ matrix.php_version }}
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
test-plugins:
name: With ${{ matrix.plugin }}
runs-on: ubuntu-20.04
needs: [get-tag]
needs: [validate-version]
env:
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-results
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-report
@ -677,12 +633,20 @@ jobs:
run: pnpm run env:test
- name: Download release zip
id: download-zip
uses: actions/github-script@v6
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release download ${{ needs.get-tag.outputs.tag }} --dir tmp
ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip
run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run 'Upload plugin' test
id: run-upload-test
@ -725,10 +689,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.ARTIFACT_NAME }}" \
-f env_description="${{ matrix.env_description }}" \
-f test_type="e2e" \
@ -743,7 +707,7 @@ jobs:
test-name: With ${{ matrix.plugin }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: ${{ matrix.env_description }}
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
post-slack-summary:
name: Post Slack summary
@ -756,10 +720,10 @@ jobs:
)
needs:
- e2e-wp-latest
- get-tag
- validate-version
- test-php-versions
- test-plugins
- test-wp-versions
- test-wp-latest-1
steps:
- uses: actions/checkout@v3
@ -774,7 +738,7 @@ jobs:
id: run-payload-action
uses: ./.github/actions/tests/slack-summary-on-release/slack-payload
with:
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
blocks-dir: ${{ steps.download-slack-blocks.outputs.download-path }}
- name: Send Slack message

View File

@ -7,8 +7,6 @@ permissions: {}
jobs:
stale:
if: |
! contains(github.event.issue.labels.*.name, 'type: enhancement')
runs-on: ubuntu-20.04
permissions:
contents: read
@ -25,6 +23,7 @@ jobs:
days-before-pr-close: -1
stale-issue-label: 'status: stale'
stale-pr-label: 'status: stale'
exempt-issue-labels: 'type: enhancement'
only-issue-labels: 'needs: author feedback'
close-issue-label: "status: can't reproduce"
ascending: true

View File

@ -0,0 +1,88 @@
name: Send a Slack notification when a PR contains rest api changes
on:
pull_request_target:
types: [labeled]
permissions: {}
jobs:
send-slack-notification-when-pr-contains-rest-api-changes:
if: "${{ github.event.label.name == 'contains: rest api change' && (github.event.pull_request.state == 'open' || github.event.pull_request.merged) }}"
runs-on: ubuntu-20.04
steps:
- name: Wait 2 minutes for other labelling jobs to finish
run: sleep 2m
shell: bash
- name: Calculate test date
id: calculate_date
run: |
#!/bin/bash
# Get the day of the week of the merged PR (0 for Sunday, 1 for Monday, etc.)
MERGE_DAY_OF_WEEK=$(date -u -d "${{ github.event.pull_request.merged_at }}" +"%u")
# Calculate days until the next Thursday after the merge
# If the merge is on Thursday, this will give 7 (i.e., next week's Thursday)
DAYS_UNTIL_NEXT_THURSDAY=$(( (4 + 7 - MERGE_DAY_OF_WEEK) % 7 ))
# If DAYS_UNTIL_NEXT_THURSDAY is 0, the merge was on a Thursday, so we set it to 7 to get the next Thursday
if [ $DAYS_UNTIL_NEXT_THURSDAY -eq 0 ]; then
DAYS_UNTIL_NEXT_THURSDAY=7
fi
# Calculate the date for the next Thursday after the merge
THURSDAY_AFTER_MERGE=$(date -u -d "${{ github.event.pull_request.merged_at }} + $DAYS_UNTIL_NEXT_THURSDAY days" +"%Y-%m-%d")
WOOAF_RELEASE_DATE=$(date -u -d "${THURSDAY_AFTER_MERGE} + 6 days" +"%Y-%m-%d")
TEST_DATE_MESSAGE="Thursday, $THURSDAY_AFTER_MERGE. (Targeting release on $WOOAF_RELEASE_DATE)"
echo "TEST_DATE_MESSAGE=${TEST_DATE_MESSAGE}" >> $GITHUB_ENV
- name: Determine Milestone Date
id: get_milestone_date
run: |
#!/bin/bash
MILESTONE_TITLE="${{ github.event.pull_request.milestone.title }}"
MILESTONE_DATE="Undefined"
# Mapping of milestone titles to release dates
declare -A MILESTONE_DATES
MILESTONE_DATES=(
["8.0.0"]="2023-08-08"
["8.1.0"]="2023-09-12"
["8.2.0"]="2023-10-10"
["8.3.0"]="2023-11-14"
["8.4.0"]="2023-12-12"
["8.5.0"]="2024-01-09"
["8.6.0"]="2024-02-13"
["8.7.0"]="2024-03-12"
["8.8.0"]="2024-04-09"
["8.9.0"]="2024-05-14"
["9.0.0"]="2024-06-11"
)
# Check if the milestone title exists in our predefined list and get the date
if [[ -v "MILESTONE_DATES[${MILESTONE_TITLE}]" ]]; then
MILESTONE_DATE=${MILESTONE_DATES[${MILESTONE_TITLE}]}
fi
# Export for later steps
echo "MILESTONE_DATE=${MILESTONE_DATE}" >> $GITHUB_ENV
# Notify Slack Step
- name: Notify Slack
uses: archive/github-actions-slack@d9dae40827adf93bddf939db6552d1e392259d7d
id: notify
with:
slack-bot-user-oauth-access-token: ${{ secrets.TEST_ASSISTANCE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_CORE_REST_API_CHANGES_SLACK_CHANNEL }}
slack-text: |
<${{ github.event.pull_request.html_url }}|${{ github.event.pull_request.title }}>
*Labels:* ${{ join(github.event.pull_request.labels.*.name, ', ') }}
*Monthly Release Milestone:* <${{ github.event.pull_request.milestone.html_url }}|${{ github.event.pull_request.milestone.title }}> (Release Date: ${{ env.MILESTONE_DATE }})
*WooAF (weekly) Timeline: this PR can be tested from:* ${{ env.TEST_DATE_MESSAGE }}
Please visit the <#${{ secrets.WOO_CORE_RELEASES_SLACK_CHANNEL }}> to obtain the latest WooAF build for testing.
slack-optional-unfurl_links: false
slack-optional-unfurl_media: false

View File

@ -1,11 +1,8 @@
name: Add Triage Label
on:
issues:
types: opened
permissions: {}
jobs:
add_label:
runs-on: ubuntu-20.04
@ -14,7 +11,22 @@ jobs:
issues: write
steps:
- uses: actions/checkout@v3
# We want to delay the labeling of the issue so that the author has a change to add labels after issue creation.
- name: 'Delay Labeling'
run: sleep 3m
# Make sure that the latest issue is pulled from the database rather than relying on the payload. This is
# because the payload won't include any labels that were added after the issue was created.
- uses: actions/github-script@v6
id: latest-issue
with:
script: |
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
core.setOutput('hasLabels', issue.data.labels.length > 0);
- uses: actions-ecosystem/action-add-labels@v1
if: github.event.issue.labels[0] == null
if: ${{ steps.latest-issue.outputs.hasLabels == 'false'}}
with:
labels: 'status: awaiting triage'

View File

@ -3,6 +3,8 @@
"MD003": { "style": "atx" },
"MD007": { "indent": 4 },
"MD013": { "line_length": 9999 },
"MD024": { "allow_different_nesting": true },
"MD033": { "allowed_elements": ["video"] },
"no-hard-tabs": false,
"whitespace": false
}

View File

@ -118,6 +118,7 @@
"@wordpress/edit-site"
],
"packages": [
"@woocommerce/block-templates",
"@woocommerce/product-editor",
"woocommerce/client/admin",
"@woocommerce/components"

View File

@ -1,4 +1,6 @@
<p align="center"><a href="https://woocommerce.com/"><img src="https://woocommerce.com/wp-content/themes/woo/images/logo-woocommerce@2x.png" alt="WooCommerce"></a></p>
# WooCommerce Monorepo
![WooCommerce](https://woocommerce.com/wp-content/themes/woo/images/logo-woocommerce@2x.png)
Welcome to the WooCommerce Monorepo on GitHub. Here you can find all of the plugins, packages, and tools used in the development of the core WooCommerce plugin as well as WooCommerce extensions. You can browse the source, look at open issues, contribute code, and keep tracking of ongoing development.
@ -12,7 +14,7 @@ To get up and running within the WooCommerce Monorepo, you will need to make sur
- [NVM](https://github.com/nvm-sh/nvm#installing-and-updating): While you can always install Node through other means, we recommend using NVM to ensure you're aligned with the version used by our development teams. Our repository contains [an `.nvmrc` file](.nvmrc) which helps ensure you are using the correct version of Node.
- [PNPM](https://pnpm.io/installation): Our repository utilizes PNPM to manage project dependencies and run various scripts involved in building and testing projects.
- [PHP 7.2+](https://www.php.net/manual/en/install.php): WooCommerce Core currently features a minimum PHP version of 7.2. It is also needed to run Composer and various project build scripts. See [troubleshooting](DEVELOPMENT.md#troubleshooting) for troubleshooting problems installing PHP.
- [PHP 7.4+](https://www.php.net/manual/en/install.php): WooCommerce Core currently features a minimum PHP version of 7.4. It is also needed to run Composer and various project build scripts. See [troubleshooting](DEVELOPMENT.md#troubleshooting) for troubleshooting problems installing PHP.
- [Composer](https://getcomposer.org/doc/00-intro.md): We use Composer to manage all of the dependencies for PHP packages and plugins.
Once you've installed all of the prerequisites, you can run the following commands to get everything working.

View File

@ -0,0 +1,131 @@
#!/usr/bin/env node
const https = require( 'https' );
const vm = require( 'vm' );
const fs = require( 'fs' );
const path = require( 'path' );
const intlUrl =
'https://raw.githubusercontent.com/jackocnr/intl-tel-input/master/src/js/data.js';
const phoneUrl =
'https://raw.githubusercontent.com/AfterShip/phone/master/src/data/country_phone_data.ts';
const fetch = ( url ) =>
new Promise( ( resolve, reject ) => {
https
.get( url, ( res ) => {
let body = '';
res.on( 'data', ( chunk ) => {
body += chunk;
} );
res.on( 'end', () => {
resolve( body );
} );
} )
.on( 'error', reject );
} );
const numberOrString = ( str ) =>
Number( str ).toString().length !== str.length ? str : Number( str );
const evaluate = ( code ) => {
const script = new vm.Script( code );
const context = vm.createContext();
script.runInContext( context );
return context;
};
const parse = ( data /*: any[]*/ ) /*: DataType*/ =>
data.reduce(
( acc, item ) => ( {
...acc,
[ item[ 0 ] ]: {
alpha2: item[ 0 ],
code: item[ 1 ].toString(),
priority: item[ 2 ] || 0,
start: item[ 3 ]?.map( String ),
lengths: item[ 4 ],
},
} ),
{}
);
const saveToFile = ( data ) => {
const dataString = JSON.stringify( data ).replace( /null/g, '' );
const parseString = parse.toString().replace( / \/\*(.+?)\*\//g, '$1' );
const code = [
'// Do not edit this file directly.',
'// Generated by /bin/packages/js/components/phone-number-input/build-data.js',
'',
'/* eslint-disable */',
'',
'import type { DataType } from "./types";',
'',
`const parse = ${ parseString }`,
'',
`const data = ${ dataString }`,
'',
'export default parse(data);',
].join( '\n' );
const filePath = path.resolve(
'packages/js/components/src/phone-number-input/data.ts'
);
fs.writeFileSync( filePath, code );
};
( async () => {
const intlData = await fetch( intlUrl ).then( evaluate );
const phoneData = await fetch( phoneUrl )
.then( ( data ) => 'var data = ' + data.substring( 15 ) )
.then( evaluate );
// Convert phoneData array to object
const phoneCountries = phoneData.data.reduce(
( acc, item ) => ( {
...acc,
[ item.alpha2.toLowerCase() ]: item,
} ),
{}
);
// Traverse intlData to create a new array with required fields
const countries = intlData.allCountries.map( ( item ) => {
const phoneCountry = phoneCountries[ item.iso2 ];
const result = [
item.iso2.toUpperCase(), // alpha2
Number( item.dialCode ), // code
/* [2] priority */
/* [3] start */
/* [4] lengths */
,
,
,
];
if ( item.priority ) {
result[ 2 ] = item.priority;
}
const areaCodes = item.areaCodes || [];
const beginWith = phoneCountry?.mobile_begin_with || [];
if ( areaCodes.length || beginWith.length ) {
result[ 3 ] = [ ...new Set( [ ...areaCodes, ...beginWith ] ) ].map(
numberOrString
);
}
if ( phoneCountry?.phone_number_lengths ) {
result[ 4 ] = phoneCountry.phone_number_lengths;
}
return result;
} );
saveToFile( countries );
} )();

View File

@ -1,5 +1,244 @@
== Changelog ==
= 8.2.1 2023-10-16 =
**WooCommerce**
* Fix - Prevent global attribute terms from being automatically selected [#40729](https://github.com/woocommerce/woocommerce/pull/40729)
= 8.2.0 2023-10-13 =
**WooCommerce**
* Fix - Correctly set 'created_via' for HPOS orders created on the admin. [#40469](https://github.com/woocommerce/woocommerce/pull/40469)
* Fix - Fix backwards compatibility issue with `wc_get_orders()` when HPOS is active and the pagination bit is set. [#40551](https://github.com/woocommerce/woocommerce/pull/40551)
* Fix - Save hpos order data before clearing the order from cache [#40282](https://github.com/woocommerce/woocommerce/pull/40282)
* Fix - Disable WP's post lock on HPOS order edit screen. [#40355](https://github.com/woocommerce/woocommerce/pull/40355)
* Fix - Enqueue media scripts for Images block within the product editor, as is required for Images block. [#40356](https://github.com/woocommerce/woocommerce/pull/40356)
* Fix - Addressed visual tweaks for CYS in response to feedback from 12th Sept [#40155](https://github.com/woocommerce/woocommerce/pull/40155)
* Fix - Address missing order type handling in HPOS compatibility mode sync. [#40279](https://github.com/woocommerce/woocommerce/pull/40279)
* Fix - Add Variation options section back to the product blocks template [#39914](https://github.com/woocommerce/woocommerce/pull/39914)
* Fix - Avoid a fatal error on the order received page if the order ID is not for a valid order. [#39876](https://github.com/woocommerce/woocommerce/pull/39876)
* Fix - Avoid string<>int comparison in products bought query to avoid results with customer_id = 0. [#40030](https://github.com/woocommerce/woocommerce/pull/40030)
* Fix - Changed Tax task completion criteria so that it considers both boolean and stringly typed values as expected [#39983](https://github.com/woocommerce/woocommerce/pull/39983)
* Fix - Display search results subtitle in HPOS list table view. [#40270](https://github.com/woocommerce/woocommerce/pull/40270)
* Fix - Eliminate an unnecessary redirect when the geo hash isalready set to the correct value. [#39634](https://github.com/woocommerce/woocommerce/pull/39634)
* Fix - Fix a bug where updating store location doesn't update store currency. [#40142](https://github.com/woocommerce/woocommerce/pull/40142)
* Fix - Fix cached refund not deleted when the refund is deleted with HPOS active [#40197](https://github.com/woocommerce/woocommerce/pull/40197)
* Fix - Fix changes in order custom fields made from admin not being applied when using the order Update button with HPOS active. [#40278](https://github.com/woocommerce/woocommerce/pull/40278)
* Fix - Fix customize store white screen bug in WP 6.3 [#40031](https://github.com/woocommerce/woocommerce/pull/40031)
* Fix - Fix customize your store task header button [#40031](https://github.com/woocommerce/woocommerce/pull/40031)
* Fix - Fix CYS UI issues [#40269](https://github.com/woocommerce/woocommerce/pull/40269)
* Fix - Fix CYS `__experimentalReapplyBlockTypeFilters` is not a function [#40104](https://github.com/woocommerce/woocommerce/pull/40104)
* Fix - Fixed missed lint error in Assembler Hub [#39964](https://github.com/woocommerce/woocommerce/pull/39964)
* Fix - Fix minor layout shift in the core profiler. [#39898](https://github.com/woocommerce/woocommerce/pull/39898)
* Fix - Fix product e2e tests [#39823](https://github.com/woocommerce/woocommerce/pull/39823)
* Fix - Fix undismissable notice when using localization for certain messages like "Coupon management has moved" [#39913](https://github.com/woocommerce/woocommerce/pull/39913)
* Fix - FIx WC Admin pages are empty for WP 6.2 and below. [#39995](https://github.com/woocommerce/woocommerce/pull/39995)
* Fix - Properly convert local time date queries to UTC in the HPOS datastore. [#40146](https://github.com/woocommerce/woocommerce/pull/40146)
* Fix - Redirect to Jetpack connect when jetpack-boost is selected. [#40261](https://github.com/woocommerce/woocommerce/pull/40261)
* Fix - Remove COT enable requirement from sync and verify command. [#39998](https://github.com/woocommerce/woocommerce/pull/39998)
* Fix - Removed references to the un-used Purchase task item in the onboarding task list. [#40121](https://github.com/woocommerce/woocommerce/pull/40121)
* Fix - Remove use of woocommerce-page class within WooCommerce Admin pages, replaced with woocommerce-admin-page. [#40218](https://github.com/woocommerce/woocommerce/pull/40218)
* Fix - Restore moving to trash functionality within HPOS order edit screen. [#39693](https://github.com/woocommerce/woocommerce/pull/39693)
* Fix - update the SqlQuery filter prefix in data.md [#39319](https://github.com/woocommerce/woocommerce/pull/39319)
* Fix - Use correct object reference when cloning a cart [#39282](https://github.com/woocommerce/woocommerce/pull/39282)
* Fix - [HPOS]Fix duplicate meta handling by passing meta_value|unique in post calls [#40088](https://github.com/woocommerce/woocommerce/pull/40088)
* Fix - [HPOS] Modify query to have less characters before the `FROM` keyword. [#40109](https://github.com/woocommerce/woocommerce/pull/40109)
* Fix - [HPOS] Support deleting metadata just by meta id. [#40064](https://github.com/woocommerce/woocommerce/pull/40064)
* Fix - [HPOS] Use objects method instead of calling datastore directly. [#40158](https://github.com/woocommerce/woocommerce/pull/40158)
* Add - Add ability to remove blocks from templates. [#39900](https://github.com/woocommerce/woocommerce/pull/39900)
* Add - Add a filter to OrdersTableQuery to allow overriding of HPOS queries. [#39945](https://github.com/woocommerce/woocommerce/pull/39945)
* Add - Add after_add_block and after_remove block hooks to the block template API. [#40139](https://github.com/woocommerce/woocommerce/pull/40139)
* Add - Add AI wizard business info step for Customize Your Store task [#39979](https://github.com/woocommerce/woocommerce/pull/39979)
* Add - Add component to Customize Your Store task. [#40140](https://github.com/woocommerce/woocommerce/pull/40140)
* Add - Add customize store - fonts [#40082](https://github.com/woocommerce/woocommerce/pull/40082)
* Add - Add customize store AI wizard call for best colour palette suggestions. [#40295](https://github.com/woocommerce/woocommerce/pull/40295)
* Add - Add customize store AI wizard call for color palette suggestion [#40237](https://github.com/woocommerce/woocommerce/pull/40237)
* Add - Add customize store AI wizard call for font pairing suggestion [#40240](https://github.com/woocommerce/woocommerce/pull/40240)
* Add - Add customize store assembler hub onboarding tour [#39981](https://github.com/woocommerce/woocommerce/pull/39981)
* Add - Add customize store assembler hub [#39843](https://github.com/woocommerce/woocommerce/pull/39843)
* Add - Add customize store color palettes [#40051](https://github.com/woocommerce/woocommerce/pull/40051)
* Add - Add customize store transitional screen [#40122](https://github.com/woocommerce/woocommerce/pull/40122)
* Add - Added URL navigation support to customize-store feature [#40068](https://github.com/woocommerce/woocommerce/pull/40068)
* Add - Add filter woocommerce_hpos_enable_sync_on_read to disable sync on read with HPOS sync enabled. [#40039](https://github.com/woocommerce/woocommerce/pull/40039)
* Add - Add has_price param to the variations REST API query. [#40281](https://github.com/woocommerce/woocommerce/pull/40281)
* Add - Add header customization to the Assembler Hub [#40107](https://github.com/woocommerce/woocommerce/pull/40107)
* Add - Add help text to Name field in Create new category modal [#40059](https://github.com/woocommerce/woocommerce/pull/40059)
* Add - Add new e2e test for Shopper My Account Downloads section [#40100](https://github.com/woocommerce/woocommerce/pull/40100)
* Add - Add new e2e test to cover My Account Addresses section [#40114](https://github.com/woocommerce/woocommerce/pull/40114)
* Add - Add sidebar to customize your store task. [#40136](https://github.com/woocommerce/woocommerce/pull/40136)
* Add - Adds new action hook `woocommerce_pay_order_before_payment` to the `checkout/form-pay.php` template. [#37588](https://github.com/woocommerce/woocommerce/pull/37588)
* Add - Add support for slug auto generation to the create attribute endpoint [#39827](https://github.com/woocommerce/woocommerce/pull/39827)
* Add - Add tags (or general taxonomy ) block [#39966](https://github.com/woocommerce/woocommerce/pull/39966)
* Add - Add track events to customize store AI wizard [#40144](https://github.com/woocommerce/woocommerce/pull/40144)
* Add - Add track events to customize store transitional page [#40143](https://github.com/woocommerce/woocommerce/pull/40143)
* Add - Add Tracks events to Appearance > Themes screen [#40193](https://github.com/woocommerce/woocommerce/pull/40193)
* Add - Add tracks to CYS assembler-hub and hide pages sidebar screen [#40156](https://github.com/woocommerce/woocommerce/pull/40156)
* Add - Add variable product experiment [#40177](https://github.com/woocommerce/woocommerce/pull/40177)
* Add - Add woocommerce_block_template_register action. [#39915](https://github.com/woocommerce/woocommerce/pull/39915)
* Add - Create a plugin to enable Variations feature #40027 [#40027](https://github.com/woocommerce/woocommerce/pull/40027)
* Add - Implement customize store assembler hub - logo feature [#39932](https://github.com/woocommerce/woocommerce/pull/39932)
* Add - Implemented loader design for Customize your store - Design with AI [#40083](https://github.com/woocommerce/woocommerce/pull/40083)
* Add - Made ai completion for look and tone more robust and added tracks [#40052](https://github.com/woocommerce/woocommerce/pull/40052)
* Add - Records plugin API requests and installation errors to coreprofiler_install_plugin_error separately for the core profiler. [#39899](https://github.com/woocommerce/woocommerce/pull/39899)
* Update - Added Marketplace class as basis for Reactified marketplace. [#39121](https://github.com/woocommerce/woocommerce/pull/39121)
* Update - Added xstate scaffolding for AI Wizard in customize your store feature [#39863](https://github.com/woocommerce/woocommerce/pull/39863)
* Update - Display a custom WooPayments onboarding task header content, when an incentive with server based header is available. [#40034](https://github.com/woocommerce/woocommerce/pull/40034)
* Update - Implement customize your store task completion logic [#40267](https://github.com/woocommerce/woocommerce/pull/40267)
* Update - Optimize customize store preview frame resize performance [#39930](https://github.com/woocommerce/woocommerce/pull/39930)
* Update - Remove core-profiler checks from the tests -- core profiler is enabled by default now. [#40260](https://github.com/woocommerce/woocommerce/pull/40260)
* Update - Replace Personalize Your Store task with Choose Your Theme [#40239](https://github.com/woocommerce/woocommerce/pull/40239)
* Update - Track coreprofiler_store_extensions_installed_and_activated when async installation is complete [#39921](https://github.com/woocommerce/woocommerce/pull/39921)
* Update - Turn off the experimental flag for HPOS. [#39846](https://github.com/woocommerce/woocommerce/pull/39846)
* Update - Update Action Scheduler to 3.6.3 [#40147](https://github.com/woocommerce/woocommerce/pull/40147)
* Update - Update intro screen for the new Customize Your Store task [#40293](https://github.com/woocommerce/woocommerce/pull/40293)
* Update - Update Remote Inbox Notifications to add in and !in comparison operators for comparing values against arrays [#40084](https://github.com/woocommerce/woocommerce/pull/40084)
* Update - Update the simple product template implementation to use the product form template API. [#39814](https://github.com/woocommerce/woocommerce/pull/39814)
* Update - Update use of preventLeavingProductForm with new function changes. [#40225](https://github.com/woocommerce/woocommerce/pull/40225)
* Update - Update WooCommerce Blocks to 10.9.3 [#39895](https://github.com/woocommerce/woocommerce/pull/39895)
* Update - Update WooCommerce Blocks to 11.0.0 [#39971](https://github.com/woocommerce/woocommerce/pull/39971)
* Update - Update WooCommerce Blocks to 11.1.0 [#40141](https://github.com/woocommerce/woocommerce/pull/40141)
* Update - Update WooCommerce Blocks to 11.1.1 [#40300](https://github.com/woocommerce/woocommerce/pull/40300)
* Update - Update WooCommerce Blocks to 11.1.2 [#40475](https://github.com/woocommerce/woocommerce/pull/40475)
* Update - We have completely redesigned the In-app Marketplace. [#39121](https://github.com/woocommerce/woocommerce/pull/39121)
* Dev - Added documentation for the Core Profiler [#39963](https://github.com/woocommerce/woocommerce/pull/39963)
* Dev - Add job to post Slack summary of plugin test results in "Smoke test daily" workflow. [#39838](https://github.com/woocommerce/woocommerce/pull/39838)
* Dev - Add new E2E test covering shopper product page and make Product-related tests granular (separated test files) [#40132](https://github.com/woocommerce/woocommerce/pull/40132)
* Dev - Add notice to "track inventory" toggle #40011 [#40011](https://github.com/woocommerce/woocommerce/pull/40011)
* Dev - Add some basic E2E tests for Assembler Hub [#40235](https://github.com/woocommerce/woocommerce/pull/40235)
* Dev - Adds test to check required fields on checkout [#40099](https://github.com/woocommerce/woocommerce/pull/40099)
* Dev - Bump required PHP version to 7.4 [#39820](https://github.com/woocommerce/woocommerce/pull/39820)
* Dev - Cleanup: remove the unused is_feature_visible and show_feature methods. [#39931](https://github.com/woocommerce/woocommerce/pull/39931)
* Dev - Fixes and enables API test suite to run on daily CI run against alternate host [#39858](https://github.com/woocommerce/woocommerce/pull/39858)
* Dev - Fix flakiness around the `Turn off the new product form` menu item. [#39957](https://github.com/woocommerce/woocommerce/pull/39957)
* Dev - Fix for a couple of flaky API tests on daily runs [#39918](https://github.com/woocommerce/woocommerce/pull/39918)
* Dev - Improve documentation for the `is_checkout()` function. [#40258](https://github.com/woocommerce/woocommerce/pull/40258)
* Dev - Refactored core profiler loader to be more generalizable and moved to @woocommerce/onboarding [#39735](https://github.com/woocommerce/woocommerce/pull/39735)
* Dev - Remove "WP Latest-2" from release tests. [#40012](https://github.com/woocommerce/woocommerce/pull/40012)
* Dev - Remove legacy PHP version update checks [#39845](https://github.com/woocommerce/woocommerce/pull/39845)
* Dev - Run a full reset on API daily test site [#40061](https://github.com/woocommerce/woocommerce/pull/40061)
* Dev - Updates Playwright from 1.33 to 1.37.1 [#39815](https://github.com/woocommerce/woocommerce/pull/39815)
* Tweak - Add order property to every block in SimpleProductTemplate [#39946](https://github.com/woocommerce/woocommerce/pull/39946)
* Tweak - Adds an informative tooltip to the Account Details section of the Direct Bank Transfer settings. [#39860](https://github.com/woocommerce/woocommerce/pull/39860)
* Tweak - Fix a minor code typo, no change in functionality [#36402](https://github.com/woocommerce/woocommerce/pull/36402)
* Tweak - Make it easier to disable email verification checks for the order confirmation and order pay pages. [#40050](https://github.com/woocommerce/woocommerce/pull/40050)
* Tweak - Migrate category field to woocommerce/product-taxonomy-field block [#40021](https://github.com/woocommerce/woocommerce/pull/40021)
* Tweak - tweak some of the HPOS Settings UI. [#39912](https://github.com/woocommerce/woocommerce/pull/39912)
* Tweak - Tweak tasklist description color to darker [#39903](https://github.com/woocommerce/woocommerce/pull/39903)
* Enhancement - Add CLI commands to enable or disable HPOS. [#39865](https://github.com/woocommerce/woocommerce/pull/39865)
* Enhancement - Design enhancements for the Attributes tab. [#39987](https://github.com/woocommerce/woocommerce/pull/39987)
* Enhancement - Design enhancements for the Inventory tab. [#39962](https://github.com/woocommerce/woocommerce/pull/39962)
* Enhancement - Enable HPOS by default for new installs. [#40296](https://github.com/woocommerce/woocommerce/pull/40296)
* Enhancement - Improve the existing E2E test to verify one more element on each page load. [#40008](https://github.com/woocommerce/woocommerce/pull/40008)
* Enhancement - Update the default setting for the task list progress bar from 0 to 0.25, which gives the progress better visual context when no tasks have been completed. [#39369](https://github.com/woocommerce/woocommerce/pull/39369)
* Enhancement - Update Venezuelan currency: Bolívar (Bs.). [#29380](https://github.com/woocommerce/woocommerce/pull/29380)
= 8.1.1 2023-09-18 =
**WooCommerce**
* Fix - Do not send user meta data back in `woocommerce_get_customer_details` response. [#40221](https://github.com/woocommerce/woocommerce/pull/40221)
* Fix - Fix possible metadata duplication when HPOS is enabled. [#40148](https://github.com/woocommerce/woocommerce/pull/40148)
= 8.1.0 2023-09-12 =
**WooCommerce**
* Fix - Update modified date when a metadata is saved for HPOS. [#39911](https://github.com/woocommerce/woocommerce/pull/39911)
* Fix - Fix edgecase performance issues around incentives caching. [#39958](https://github.com/woocommerce/woocommerce/pull/39958)
* Fix - Add migration to move incorrectly stored payment token IDS to HPOS tables from postmeta. [#39724](https://github.com/woocommerce/woocommerce/pull/39724)
* Fix - Address more PHP 8.1+ deprecation warnings in wc-admin code. [#38774](https://github.com/woocommerce/woocommerce/pull/38774)
* Fix - Adds display of postcodes to Vietnam addresses. [#39403](https://github.com/woocommerce/woocommerce/pull/39403)
* Fix - Always return bool values from WPCacheEngine functions when expected. [#39819](https://github.com/woocommerce/woocommerce/pull/39819)
* Fix - Be more precise when checking submission data from the email verification form on the order confirmation screen. [#39479](https://github.com/woocommerce/woocommerce/pull/39479)
* Fix - Bring HPOS order hooks in line with the posts implementation. [#39694](https://github.com/woocommerce/woocommerce/pull/39694)
* Fix - Connect WC_Install's create_tables to HPOS tables when its active. [#39682](https://github.com/woocommerce/woocommerce/pull/39682)
* Fix - Disable read on sync while backfilling. [#39450](https://github.com/woocommerce/woocommerce/pull/39450)
* Fix - Ensure refund meta data is saved correctly when HPOS is enabled. [#39700](https://github.com/woocommerce/woocommerce/pull/39700)
* Fix - Ensure that the full discount is ignored in free shipping minimum order calculations when ignore_discount setting is enabled [#39155](https://github.com/woocommerce/woocommerce/pull/39155)
* Fix - Fixed a race condition that was causing page views on intro-opt-in page to be sent before tracks was enabled. [#39508](https://github.com/woocommerce/woocommerce/pull/39508)
* Fix - Fixes WooCommerce knowledge base API returning empty posts. [#39809](https://github.com/woocommerce/woocommerce/pull/39809)
* Fix - Fix failure due to multiple h2 tags in the Product Vendors plugin [#38717](https://github.com/woocommerce/woocommerce/pull/38717)
* Fix - Fix Storefront recommendation link and missing image in Marketplace [#39294](https://github.com/woocommerce/woocommerce/pull/39294)
* Fix - include post_ID in HPOS order edit screen [#39321](https://github.com/woocommerce/woocommerce/pull/39321)
* Fix - Limit index length to 191 characters by default, additionally connect HPOS to verify DB tooling. [#39250](https://github.com/woocommerce/woocommerce/pull/39250)
* Fix - Onboarding payments task not completed after setting up WooPayments [#39786](https://github.com/woocommerce/woocommerce/pull/39786)
* Fix - Prevent possible error when refreshing order edit locks. [#39498](https://github.com/woocommerce/woocommerce/pull/39498)
* Fix - Prevent possible fatal error when edit lock is held on deleted order. [#39497](https://github.com/woocommerce/woocommerce/pull/39497)
* Fix - Store transactional data in order tables with HPOS. [#39381](https://github.com/woocommerce/woocommerce/pull/39381)
* Fix - Support inserting NULL values for strict DB mode for DataBase Util's insert_on_duplicate_key_update method. [#39396](https://github.com/woocommerce/woocommerce/pull/39396)
* Fix - Update CSS prop 'end' to 'flex-end' when using flexbox. [#39419](https://github.com/woocommerce/woocommerce/pull/39419)
* Fix - Use admin theme color for select2, instead of hardcoded theme values. [#39451](https://github.com/woocommerce/woocommerce/pull/39451)
* Fix - Use admin theme color instead of old pink. Update old pink to the new brand color. [#39182](https://github.com/woocommerce/woocommerce/pull/39182)
* Fix - [Product Block Editor] remove digital products from the target list #39769 [#39801](https://github.com/woocommerce/woocommerce/pull/39801)
* Add - Add block template registry and controller [#39698](https://github.com/woocommerce/woocommerce/pull/39698)
* Add - Add delete option to generate variations API, to auto delete unmatched variations. [#39733](https://github.com/woocommerce/woocommerce/pull/39733)
* Add - Added feature flag that removes store appearance task and adds customize store task when enabled [#39397](https://github.com/woocommerce/woocommerce/pull/39397)
* Add - Add filter for adding new user preference option for notice to user data fields. [#39685](https://github.com/woocommerce/woocommerce/pull/39685)
* Add - Add plugin installation request track for core profiler [#39533](https://github.com/woocommerce/woocommerce/pull/39533)
* Add - Add post_password for products for REST API V3 [#39438](https://github.com/woocommerce/woocommerce/pull/39438)
* Add - Add support for Japan and UAE in WooPayments [#39431](https://github.com/woocommerce/woocommerce/pull/39431)
* Add - Add woocommerce/product-password-field block to new product editor [#39464](https://github.com/woocommerce/woocommerce/pull/39464)
* Add - API for block-based templates. [#39470](https://github.com/woocommerce/woocommerce/pull/39470)
* Add - Register product catalog and search visibility blocks [#39477](https://github.com/woocommerce/woocommerce/pull/39477)
* Add - Register the product variation items block [#39657](https://github.com/woocommerce/woocommerce/pull/39657)
* Add - [E2E test coverage]: Disable block product editor #39417 [#39493](https://github.com/woocommerce/woocommerce/pull/39493)
* Add - [E2E test coverage]: Enable new product management experience [#39463](https://github.com/woocommerce/woocommerce/pull/39463)
* Add - [E2E test coverage]: General tab #39411 [#39493](https://github.com/woocommerce/woocommerce/pull/39493)
* Update - Add 'variable' to supported post types for product block editor [#39256](https://github.com/woocommerce/woocommerce/pull/39256)
* Update - Added xstate scaffolding for customize your store feature [#39619](https://github.com/woocommerce/woocommerce/pull/39619)
* Update - add time support to product import on sale dates [#39372](https://github.com/woocommerce/woocommerce/pull/39372)
* Update - On the order confirmation screen, show the 'thank you' message regardless of whether the viewer is verified or not. [#39758](https://github.com/woocommerce/woocommerce/pull/39758)
* Update - Support `first_used` and `installation_date` mobile usage data for WCTracker. [#39605](https://github.com/woocommerce/woocommerce/pull/39605)
* Update - Updates Action Scheduler to 3.6.2 (bug fixes and improvements to help debug problems). [#39665](https://github.com/woocommerce/woocommerce/pull/39665)
* Update - Update task list to show a spinner on item click [#39270](https://github.com/woocommerce/woocommerce/pull/39270)
* Update - Update WCPay banners for WooPay in eligible countries. [#39596](https://github.com/woocommerce/woocommerce/pull/39596)
* Update - Update WooCommerce Blocks to 10.9.0 [#39783](https://github.com/woocommerce/woocommerce/pull/39783)
* Update - Update WooCommerce Blocks to 10.9.2 [#39828](https://github.com/woocommerce/woocommerce/pull/39828)
* Update - Use the same checkbox style on the platform selctor [#39469](https://github.com/woocommerce/woocommerce/pull/39469)
* Dev - Added a unit test for plugin feature compatibility data in WC Tracker [#38931](https://github.com/woocommerce/woocommerce/pull/38931)
* Dev - Added storybook for core profiler pages [#39046](https://github.com/woocommerce/woocommerce/pull/39046)
* Dev - Fixed TS type error for state machine Context in Core Profiler that only got caught after TS5 upgrade [#39749](https://github.com/woocommerce/woocommerce/pull/39749)
* Dev - Fixes a failing e2e test in our daily test runs. [#39674](https://github.com/woocommerce/woocommerce/pull/39674)
* Dev - Fix flaky E2E tests in analytics-overview.spec.js. [#39308](https://github.com/woocommerce/woocommerce/pull/39308)
* Dev - Optimized the System Status Report unit tests. [#39363](https://github.com/woocommerce/woocommerce/pull/39363)
* Dev - Refactored some core profiler utils out to reuse them in customise your store. [#39581](https://github.com/woocommerce/woocommerce/pull/39581)
* Dev - Remove dependency on e2e-environment and e2e-utils in wc-admin. [#39746](https://github.com/woocommerce/woocommerce/pull/39746)
* Dev - Remove the non-existing method from TaskList docs. [#39454](https://github.com/woocommerce/woocommerce/pull/39454)
* Dev - Remove unused variation option components [#39673](https://github.com/woocommerce/woocommerce/pull/39673)
* Dev - Runs all API tests on daily run. Skips failing tests on CI. [#39351](https://github.com/woocommerce/woocommerce/pull/39351)
* Dev - Shard the unit tests into two test suites. [#39362](https://github.com/woocommerce/woocommerce/pull/39362)
* Dev - Simplify user id retrieval in analytics-overview.spec.js. [#39472](https://github.com/woocommerce/woocommerce/pull/39472)
* Dev - Update pnpm to 8.6.7 [#39245](https://github.com/woocommerce/woocommerce/pull/39245)
* Dev - Upgrade TypeScript to 5.1.6 [#39531](https://github.com/woocommerce/woocommerce/pull/39531)
* Dev - [Product Block Editor] Disable tabs in parent product page with variations #39459 [#39675](https://github.com/woocommerce/woocommerce/pull/39675)
* Dev - [Product Block Editor] Disable the new editor for variable products. [#39780](https://github.com/woocommerce/woocommerce/pull/39780)
* Tweak - Add loading indicator when submitting location in Tax task [#39613](https://github.com/woocommerce/woocommerce/pull/39613)
* Tweak - Center align checkbox, logo, and the title on the plugins page (core profiler) [#39394](https://github.com/woocommerce/woocommerce/pull/39394)
* Tweak - Do not run 'woocommerce_process_shop_order_meta' for order post when HPOS is authoritative. [#39587](https://github.com/woocommerce/woocommerce/pull/39587)
* Tweak - Fix TikTok naming. [#39748](https://github.com/woocommerce/woocommerce/pull/39748)
* Tweak - Modified the error message shown to customers in the event that no payment gateways are available. [#39348](https://github.com/woocommerce/woocommerce/pull/39348)
* Tweak - Remove subheading letter-spacing from the core profiler pages. [#39526](https://github.com/woocommerce/woocommerce/pull/39526)
* Tweak - Run A/B test on the core profiler plugins page -- suggest Jetpack or Jetpack Boost [#39799](https://github.com/woocommerce/woocommerce/pull/39799)
* Tweak - Safety measures to prevent future breakages when executing bulk actions in the order list table (HPOS). [#39524](https://github.com/woocommerce/woocommerce/pull/39524)
* Tweak - When all plugins are deselected, but Jetpack is already installed and not connected, redirect users to the Jetpack Connect page. [#39109](https://github.com/woocommerce/woocommerce/pull/39109)
* Tweak - When HPOS is authoritative, execute order update logic earlier during the request. [#39590](https://github.com/woocommerce/woocommerce/pull/39590)
* Performance - Use direct meta calls for backfilling instead of expensive object update. [#39450](https://github.com/woocommerce/woocommerce/pull/39450)
* Enhancement - Add filter `woocommerce_pre_delete_{object_type}` which allows preventing deletion.' [#39650](https://github.com/woocommerce/woocommerce/pull/39650)
* Enhancement - Create the Organization tab [#39232](https://github.com/woocommerce/woocommerce/pull/39232)
* Enhancement - Modify order index to also include date for faster order list query. [#39682](https://github.com/woocommerce/woocommerce/pull/39682)
* Enhancement - Update the admin's menu remaining tasks bubble CSS class and handling [#39273](https://github.com/woocommerce/woocommerce/pull/39273)
= 8.0.3 2023-08-29 =
* Update - Bump WooCommerce Blocks to 10.6.6. [#39853](https://github.com/woocommerce/woocommerce/pull/39853)
* Fix - Avoid extra queries when a WooPayments incentive has been dismissed. [#39882](https://github.com/woocommerce/woocommerce/pull/39882)
= 8.0.2 2023-08-15 =
* Fix - Fix an issue which was causing some attributes to default to a minimum length of 3. [#39686](https://github.com/woocommerce/woocommerce/pull/39686)

View File

@ -1,7 +1,5 @@
# Adjust the quantity input values
> This is a **Developer level** doc. If you are unfamiliar with code and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/) for assistance. We are unable to provide support for customizations under our  [Support Policy](http://www.woocommerce.com/support-policy/).
Set the starting value, maximum value, minimum value, and increment amount for quantity input fields on product pages.
Add this code to your child themes `functions.php` file or via a plugin that allows custom functions to be added, such as the [Code snippets](https://wordpress.org/plugins/code-snippets/) plugin. Avoid adding custom code directly to your parent themes `functions.php` file, as this will be wiped entirely when you update the theme.
@ -34,7 +32,7 @@ if ( ! function_exists( 'YOUR_PREFIX_woocommerce_available_variation' ) ) {
function YOUR_PREFIX_woocommerce_available_variation( $args ) {
$args['max_qty'] = 20; // Maximum value (variations)
$args['min_qty'] = 2; // Minimum value (variations)
// Note: the starting value and step for variations is controlled
// from the 'woocommerce_quantity_input_args' filter shown above for
// simple products

View File

@ -1,9 +1,9 @@
# Add a message above the login / register form
> This is a **Developer level** doc. If you are unfamiliar with code and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/) for assistance. We are unable to provide support for customizations under our [Support Policy](http://www.woocommerce.com/support-policy/).
This code will add a custom message above the login/register form on the users my-account page.
Add this code to your child themes `functions.php` file or via a plugin that allows custom functions to be added, such as the [Code snippets](https://wordpress.org/plugins/code-snippets/) plugin. Avoid adding custom code directly to your parent themes `functions.php` file, as this will be wiped entirely when you update the theme.
```php
if ( ! function_exists( 'YOUR_PREFIX_login_message' ) ) {
/**
@ -30,5 +30,5 @@ if ( ! function_exists( 'YOUR_PREFIX_login_message' ) ) {
Please note that for this code to work, the following options must be checked in the WooCommerce “Accounts & Privacy” settings:
- Allow customers to create an account during checkout.
- Allow customers to create an account on the "My Account" page.
- Allow customers to create an account during checkout.
- Allow customers to create an account on the "My Account" page.

View File

@ -1,7 +1,5 @@
# Change number of related products output
> This is a **Developer level** doc. If you are unfamiliar with code and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/) for assistance. We are unable to provide support for customizations under our [Support Policy](http://www.woocommerce.com/support-policy/?).
Add code to your child themes functions.php file or via a plugin that allows custom functions to be added, such as the [Code snippets](https://wordpress.org/plugins/code-snippets/) plugin. Avoid adding custom code directly to your parent themes `functions.php` file as this will be wiped entirely when you update the theme.
Please note that it does not work for all themes because of the way theyre coded.

View File

@ -1,7 +1,5 @@
# Unhook and remove WooCommerce emails
> This is a **Developer level** doc. If you are unfamiliar with code and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/) for assistance. We are unable to provide support for customizations under our  [Support Policy](http://www.woocommerce.com/support-policy/).
This code allows you to unhook and remove the default WooCommerce emails.
Add this code to your child themes `functions.php` file or via a plugin that allows custom functions to be added, such as the [Code snippets](https://wordpress.org/plugins/code-snippets/) plugin. Avoid adding custom code directly to your parent themes `functions.php` file, as this will be wiped entirely when you update the theme.

View File

@ -0,0 +1,35 @@
# How to decide if a Pull Request is High-Impact
Deciding if a Pull Request should be declared High-Impact is a complex task. To achieve it, we need to assess and estimate the impact that the changes introduced in the Pull Request have in WooCommerce, which is usually a subjective task and sometimes inaccurate, due to the huge knowledge it demands of the WooCommerce product details, technical details and even customers issues history.
On this page, we will share some guidelines to help you assess the impact degree of a Pull Request.
## You should mark a Pull Request as High-Impact if
- It adds a **new feature** to WooCommerce, except if it's behind a feature flag.
- Modifies **critical functionality** (see the [critical flows list](https://github.com/woocommerce/woocommerce/wiki/Critical-Flows)).
- It fixes a **high-priority bug** (this includes Blocks fix releases core version bumps).
- It contains a **security fix**.
- Updates **SQL queries**.
- Touches any of the **$_REQUEST** family of variables.
- Any kind of **data migration/update**.
- Changes to **emails** sent from WooCommerce.
- Changes to WooCommerce **hooks/actions/filters**.
- Changes to **REST API endpoints**.
- It's a **big PR** (i.e. adds several changes in many files).
- It has **i18n changes** (for example, any file from `woocommerce/i18n` is modified).
## You should not mark a Pull Request as High-Impact if
- It only updates automated tests, things related to infrastructure not included in the WooCommerce release package, or other projects in the monorepo not included in the release package.
- It only contains readme or changelog changes.
- Fixes a low-priority bug such as a typo etc.
- Doesnt need to be verified in multiple environment types.
- Regular scheduled (not a fix release) core version bumps for the Blocks package (as testing will already be scheduled).
- It's part of a feature that hasn't been released as a whole yet (i.e. it's behind a feature flag currently in progress).
## My PR is High-Impact. What's next?
If your PR is High-Impact, be sure to label it with `needs: analysis` so that it can get reviewed. If you don't have permission to add labels, please make sure that the **PR reviewers do it**.
Once the PR labelled as `needs: analysis` is reviewed, it will get added the `impact: high` label if it qualifies for High-Impact and the WooCommerce Core team will keep special considerations for testing it.

449
docs/docs-manifest.json Normal file
View File

@ -0,0 +1,449 @@
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/style-guide.md",
"hash": "e81f1f926568e1792b6814c735c0321dee1356b4f8c053b7a5ee1770440e8052",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/style-guide.md",
"id": "211490a474b1b2ce6a6fc670b159f3497d6a9054"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/README.md",
"hash": "b1a13c53d16ba2a1b089a0cf19c5c37a8181f33bdbe0c6ee106cd1c80aef9fa0",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/README.md",
"id": "2c20e49a2bfd5bfcbb318dedbec96ada77784f14",
"links": {
"extension-development/building-your-first-extension.md": "bfb30a2379ec5e7c7960192b0a9175191e39aef7",
"extension-development/how-to-design-a-simple-extension.md": "c2f4612f31cc3892bfb19c6e9859f2daccdb6fa0",
"style-guide.md": "211490a474b1b2ce6a6fc670b159f3497d6a9054",
"../plugins/woocommerce/README.md": "827066d08695e5002bf059cd2e9d4d2a0fa58df8",
"../plugins/woocommerce/i18n/languages/README.md": "826a4400174812dfabb978c87ff2742bfdf28d62",
"../plugins/woocommerce/includes/README.md": "3d07aabeb0926e4c675e5770e78a0cfa537d2f56",
"../plugins/woocommerce/lib/README.md": "7c7e05959e4e9dcde4ac0e3e2a13258d7521e731",
"../plugins/woocommerce/packages/README.md": "740c206346a48e9dcb2e70efd5a3221992c389dc",
"../plugins/woocommerce/src/README.md": "c7444c322c5bb1ff755b2bf3e961babf3a879f4e",
"../plugins/woocommerce/src/Admin/RemoteInboxNotifications/README.md": "a46d35b9e8a8c15b89082e0c2c04d83c852d545f",
"../plugins/woocommerce/src/Admin/RemoteInboxNotifications/Transformers/README.md": "bbccc83ae18c86679a3b632e7203f6c395987967",
"../plugins/woocommerce/src/Blocks/README.md": "532a6602e970797759269b4c588c724551379214",
"../plugins/woocommerce/src/Internal/README.md": "67d669be90b641e2273194796e3d9bdfdbd69a7e",
"../plugins/woocommerce/src/Internal/Admin/ProductForm/README.md": "1d691e34fd20dd268e8e9f8283f46a595758c33b",
"../plugins/woocommerce/tests/README.md": "722532b12b14b2f5c0b8efdd96cca1854bba38c4",
"../plugins/woocommerce/tests/api-core-tests/README.md": "b000db6a9a2807a49a3bb47c57bb78326a865c78",
"../plugins/woocommerce/tests/e2e/README.md": "c15296a46be7331ed23d791073cdebeb0f4c48c4",
"../plugins/woocommerce/tests/e2e-pw/README.md": "103a9a613a34a031b34ca48f0895640dc9fc2b10",
"../plugins/woocommerce/tests/performance/README.md": "8c14e3b9fac89bced565b78e96d3a3a89e0a568e",
"../plugins/woocommerce/tests/Tools/CodeHacking/README.md": "231d9fc132423f1ecc391aaf1bcb57a3cd749d24",
"../plugins/woocommerce-admin/README.md": "9ba7a7e2c4411e01c70d866f8b8b5604484368d8",
"../plugins/woocommerce-admin/client/activity-panel/README.md": "2de9812a153a9c9ed90588feacd9ece41ecff93c",
"../plugins/woocommerce-admin/client/activity-panel/activity-card/README.md": "c34672cf87665e3ff157c6df3ddf1993fd33e7a4",
"../plugins/woocommerce-admin/client/activity-panel/activity-header/README.md": "13e379fd37082d3cba36e76046acfc63ff70ab8a",
"../plugins/woocommerce-admin/client/analytics/report/README.md": "84430b89912cb95d31240cd2d00a400b2d904ec4",
"../plugins/woocommerce-admin/client/analytics/settings/README.md": "421781cef9f3d0160c1e3892488b21b3f4a2a7f5",
"../plugins/woocommerce-admin/client/dashboard/README.md": "f7d6ff3c0f18554161afaa94698fb127f098986f",
"../plugins/woocommerce-admin/client/header/README.md": "39d3152fc1be21beee488dddd3f5a90e6af2502a",
"../plugins/woocommerce-admin/client/marketing/README.md": "54f1eb4cf5ec67713ce2fdf2b2f1dc28b03e35ef",
"../plugins/woocommerce-admin/client/marketing/components/product-icon/README.md": "3fa5081872b79078ad320dd0d9e218ed4148dc4e",
"../plugins/woocommerce-admin/client/utils/README.md": "0486d6a8f01b89bf171e21678df5dae9b5791a99",
"../plugins/woocommerce-admin/client/wp-admin-scripts/README.md": "641ab0c131d812f0969631b44ed9e8fe3fdb0cba",
"../plugins/woocommerce-admin/docs/README.md": "25155a38fc7599a01bfb30eb31a1edb098b59219",
"../plugins/woocommerce-admin/docs/examples/README.md": "b5ca126b81199d9da6ae62d5d26c093f88405a06",
"../plugins/woocommerce-admin/docs/examples/extensions/README.md": "42a90d07061074d0de1b15aeaf80531f83b2a258",
"../plugins/woocommerce-admin/docs/features/README.md": "1ee849cb8dc013ffbfe8ebcb54b8cc83f39d72e4",
"../plugins/woocommerce-admin/docs/woocommerce.com/README.md": "ee127fc0f256c3ae546869c602e94b4a6e258be8",
"../plugins/woocommerce-beta-tester/README.md": "081da0cc3caba15e926b606082120c2692b71ad4",
"../plugins/woocommerce-beta-tester/src/tools/README.md": "aedc38bbe8b29e676a15d252bcb1be38acc86f3c",
"../plugins/woocommerce-beta-tester/userscripts/README.md": "d3d94172608c29c4968ee73858ee3575a2cc11ce"
}
}
],
"categories": [
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/unhook--remove-woocommerce-emails.md",
"hash": "a22ec5c7c7c670e97e34a438d5e13dc3709716484efbecbf49e5917b6da9079d",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/unhook--remove-woocommerce-emails.md",
"id": "517b5bdeb798c1832c3ba76670e728b7b922d5d1"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/rename-a-country.md",
"hash": "3929e2145dcaad30a83fda6d82d973028e4463eeb2f6a6ba6ff9cb70c6b52fd5",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/rename-a-country.md",
"id": "2197550f7fdfbce39155865ba36f1f396a35e4a6"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/number-of-products-per-row.md",
"hash": "507e7be407716b56fe577109b296b55cdcb48cb2b2e339a761446b4df2d730e9",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/number-of-products-per-row.md",
"id": "7da8ddcdbc3f427d14b040015fb1de9efde79d19"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/change-a-currency-symbol.md",
"hash": "4485b212ff7bdf7fd8c23dc589dbbb6263a530623b939b384297f2377b11056f",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/change-a-currency-symbol.md",
"id": "de0e6701b0e15a209ac6ed3c100b34f67237ea96"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/before-login--register-form.md",
"hash": "3435f3859ec047566696ae5474df697c99a6e1ab04168ae8f1ca831abc519d67",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/before-login--register-form.md",
"id": "5acf55bdb90174bc00a10816ca71a8846bd7040f"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/adjust-quantity-input-values.md",
"hash": "056fb597c07e0e82b92ca8a2c484166f807d3d513fa950cb5c46a8db087fe986",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/adjust-quantity-input-values.md",
"id": "06d0ddda56838dc22ad94716aca95a1f2a9ad67c"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/add-or-modify-states.md",
"hash": "d61d5051439b0cbf949be64958c8101a7c6487672a7b79dd3f528e9c1a5b408e",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/add-or-modify-states.md",
"id": "10568c46b0baa2f8ea01a8cd9dd6b2d65d35aafc"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/add-a-currency-symbol.md",
"hash": "0053a87328ee04a168c5657df26cf18f219d30669b000300ace4284ea2333186",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/add-a-currency-symbol.md",
"id": "6d63d431fa1d66af7b3b47861ccc940775eba397"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/add-a-country.md",
"hash": "9305a5ed51cc0174e19e68ebc94801c5e7d6e62e820d106f35175540b0531d10",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/add-a-country.md",
"id": "7c591c3bd31cb2942fdcb4f77da167bc9ec36207"
}
],
"categories": []
},
{
"category_title": "Contributing",
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/contributing/deciding-pr-high-impact.md",
"hash": "6d9ddea0e44e1ab9f7b12183069c7fde51df26c9bcad15d8b6f9d3ab17ee1fe0",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/contributing/deciding-pr-high-impact.md",
"id": "cee3a746887c88f92966bb72ec1847aa5d97cebd"
}
],
"categories": []
},
{
"category_title": "Data-management",
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/data-management/data-stores.md",
"hash": "7af9424c5b3fdfa5b30b658f0c3a452ac12d67390b58e9c23ef3bc71412b2a92",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/data-management/data-stores.md",
"id": "72609f6c4fecccf2881c76bb8f21fc6a2d3cfef5"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/data-management/crud-objects.md",
"hash": "9b687cd323893ed0fc012ad82e67a329ea0f41c312017bfdf3015ab7ef51a23a",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/data-management/crud-objects.md",
"id": "0214be4dc9e0ddcc6d6a175fcd2f2b9fd4c8b042"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/tools-for-low-code-development.md",
"hash": "5989c60346c29c019332b7e2faee0dfcddf063db2d12f22f7755525e99c8ba4a",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/tools-for-low-code-development.md",
"id": "9db13086ff88d75fc5d5cd7bd36820b2d372b288"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/readme.md",
"hash": "e22a09b0d39adf37cd19fa57263e1195646f766396a36571411c54c64c6ba5a1",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/readme.md",
"id": "4946a26f3f2ba63d5db65033a90b6dda3a43a4ee"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/how-to-design-a-simple-extension.md",
"hash": "893c9361b6a1f6cd8a83dc9a4500c9b3050d66ef6d567fddf56d68de01d182a1",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/how-to-design-a-simple-extension.md",
"id": "c2f4612f31cc3892bfb19c6e9859f2daccdb6fa0"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/how-to-add-your-own-store-management-links.md",
"hash": "59dfa1f941a2fafaccedf2dd9be5bc1ee8c34b7320c6589c860ad98403bcd273",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/how-to-add-your-own-store-management-links.md",
"id": "461423141956d0653582aa15956a7b0401301cf6"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/handling-merchant-onboarding.md",
"hash": "e4a8358de815e378beb07426fd5687a0e91792f70a697574edd5031bf073c08d",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/handling-merchant-onboarding.md",
"id": "878874b744cea792a439935c67ac833a5f7d8796"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/handling-deactivation-and-uninstallation.md",
"hash": "cfc8cdf9e9a41e69cf40dcc1548cf7b0231c51c33c504ee800dd7525afe6d483",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/handling-deactivation-and-uninstallation.md",
"id": "93a623f5b7ff808c92541941787bdc2101518f5a"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/extension-developer-handbook.md",
"hash": "ff87298651dff8672b0c0da8693b53cb19d1fe7e65f04a947029aeec9cc9896f",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/extension-developer-handbook.md",
"id": "9f22e410b1ff4f6e5c22f6b4567c1a676d037295"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/development-environment.md",
"hash": "811f43ef03b40b48ad72a9d787031cb10d5a17b5f4ef4a2d5c0fa4977b2d43df",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/development-environment.md",
"id": "188b18434a7e844978d4d25a4b1fbc74004294d5"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/building-your-first-extension.md",
"hash": "2aad1fe83142ff55197f3bc560fafbe2c1279ccf9bb727fea5257eed447ba694",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/building-your-first-extension.md",
"id": "bfb30a2379ec5e7c7960192b0a9175191e39aef7"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/readme.md",
"hash": "8aa7cd66683478dff1f37c767f154d35e6b78a738b604d0bc2ae31a10f920ba6",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/readme.md",
"id": "2145ad4acea5e37b1ff4354bf44a8af9d10c750a"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/developer-tools.md",
"hash": "860d227350f472b610351bf416953bf9401bf0df296ee8ebe2af9c7a9d20fc57",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/developer-tools.md",
"id": "3d8c7c1a9187dd7c96d2561bccfcfa88a8d0102a"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/developer-resources.md",
"hash": "e5417528667f6afb2de5ed1b4f7073a63268e72e163bd67a8a1daeda1e623eb0",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/developer-resources.md",
"id": "0923cb0175b15041bcecf8f9dbc60828052e1fec"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/debugging.md",
"hash": "e8407732d22ffa183db83e5875e6709bdc8dd7ac47a05280590c4b5f1021fea9",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/debugging.md",
"id": "b28ccc6fa293efebd716b510df0331fb222b8a1b",
"links": {
"../utilities/logging.md": "f673f50bdd83d5d0d7fd8d9976828f8736809510"
}
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/high-performance-order-storage/readme.md",
"hash": "aada6bfad51c9f68ddb61e6475aae137e6b2d91839afa001aa3862ecd651093b",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/high-performance-order-storage/readme.md",
"id": "214c00235e4efed0a786fd704c4bfde25952a669"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/high-performance-order-storage/hpos-overview.md",
"hash": "a7504d828aed93aa68fbaff338406682fa6169f9401b2c4de6e750d7f51c7416",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/high-performance-order-storage/hpos-overview.md",
"id": "380a11e440eb17bc76fb606fecce4ce82fc9b0cb"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/product-editor-development/common-tasks.md",
"hash": "a7725479ff8b34f8069f3a8262502dc82354ea50d6ccd3760c5c7f7a9ae58fe2",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/product-editor-development/common-tasks.md",
"id": "c09542004d78254458250704f3a68cfeb9fa7a7c"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/readme.md",
"hash": "7afc464833ea0eb33127e98cb92f951bcb4a5d9006898e56db9d1f36006970cf",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/readme.md",
"id": "f12729345d42760bd61a4a4cfdcebf6dbf2daac4"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/performance-optimization.md",
"hash": "cc54a9af29f80e413536f46e70bc17512c92de536375bded23e4893a3e95e262",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/performance-optimization.md",
"id": "280d9d16382ef5374226629751cff7fceefbfa62"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/grammar-punctuation-capitalization.md",
"hash": "cea26a41342f5e67bb3313c935726da68647827a60c2fb034f3e64dd783496bd",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/grammar-punctuation-capitalization.md",
"id": "85d910730d1daa03c86c42f2d4cbd2e146cec83c"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/coding-standards.md",
"hash": "332efc3cccdde767237087abba302fcc371d510e5f287d439de49fe99a5445cc",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/coding-standards.md",
"id": "3a47d9e0da6c415606b7ee87bb65ed24f4630be1"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reference-code/readme.md",
"hash": "49a289229235989dcb8fa990af7e5017ae37569d6103dfd044ee2d95f250f596",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reference-code/readme.md",
"id": "1934f96989f9b62e2caf7fd0ac7deb2292f161ce"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reporting/readme.md",
"hash": "117ccaf1bf931f7a98486ac0b506c48dd4834a2f2acd76f8936a9bf6ba93171b",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reporting/readme.md",
"id": "fc4ef6d8e26fc46ef6c9da5e0d860cf051928e12"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reporting/extending-woocommerce-admin-reports.md",
"hash": "860c37ab2d1de9744d838e6d3b11eeadb6e6cb11afffa8dfc11021240661d843",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reporting/extending-woocommerce-admin-reports.md",
"id": "9960520d4548fd3647c5bbc7ed4d4fcc6a76cfce"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reporting/adding-columns-to-analytics-reports-and-csv-downloads.md",
"hash": "e8265405615834b04a02f5406c38e3be8acdd01116b66f08f25f99a86a580948",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reporting/adding-columns-to-analytics-reports-and-csv-downloads.md",
"id": "10cabd954ae223ac83f84223611f6d82361f9d9d",
"links": {
"extending-woocommerce-admin-reports.md": "9960520d4548fd3647c5bbc7ed4d4fcc6a76cfce"
}
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/rest-api/readme.md",
"hash": "895a1986fd30f437c1bc2aaa618d6a06a98c65511cd257077302c2d1225787d9",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/rest-api/readme.md",
"id": "128b41ed5e9a0ed13a51de3196bd06c0297b2f33"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/rest-api/getting-started.md",
"hash": "b0bb28f6eed57c7d57dde75e8093771450db4666cbfab16d35387c39cd8d1e20",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/rest-api/getting-started.md",
"id": "10f52db2464ea2f373eff9a45ce9e8ff40214122",
"links": {
"_media/permalinks.webp": "5ac10f14cd0ca3ae45a9c089d659fee3ea4d9f22",
"_media/keys.png": "7a29fcb3f0b565f4f6983f1e12200d2c4d62907b",
"_media/postman.png": "b100bbf70f8889c26fcde6a6daca29be796071de",
"_media/insomnia.png": "a50683984998ab518b4b05433ffb1803f2ac135f",
"_media/sslerror.png": "5b6825fb0aba7ed55e1641880701c2afd1744ce1",
"_media/postman-ssl.png": "7e3523b0340acf908e98ac320f822d00a0710ac5",
"_media/insomnia-ssl.png": "84e6406407498b9936d6ef1df5e4c4cc78f75b00"
}
}
],
"categories": [
{
"category_title": "_media",
"categories": []
}
]
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/security/security-best-practices.md",
"hash": "ded14bf9c1b5402c9896c795c4c4cbe6165d465de56009c32559f854446bafda",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/security/security-best-practices.md",
"id": "ee399e729785fec50b90d73b231d321b34ab5ff9"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/security/reporting-security-issues.md",
"hash": "4a748990a0e3207c9f0828c585c1d2edce14bafee9afc331d43bda0b8ee09aa6",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/security/reporting-security-issues.md",
"id": "48caba58b4e5b44fc418bb80cf03aa48f87e4cc8"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/security/readme.md",
"hash": "b484a4886068a33cd8114066262e95a2c8036f1e11d09f0dc63141cd36d85e95",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/security/readme.md",
"id": "8b4aa089616cbeeedfec301eee17b5a00f669154"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/theme-development/theme-design-ux-guidelines.md",
"hash": "bcab4deb86172df46ff775a23b921f8fb4aadd5b5c96085451609a3863642efc",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/theme-development/theme-design-ux-guidelines.md",
"id": "1abe0b1ff5e3990387c7da7fa5a147430b3282f7"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/theme-development/marketplace-guidelines.md",
"hash": "5ca562b2f4cabefe47b0d08334f39d56e8d3e6dc31ea347000d3bb221e51d0a1",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/theme-development/marketplace-guidelines.md",
"id": "f39a348d787fd0cf4a390e70e6f0cbd36b27a283"
}
],
"categories": []
},
{
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/tutorials/readme.md",
"hash": "2ca52b9289180adad5d59865ca45c50098119b420662d727d739243e6a98131a",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/tutorials/readme.md",
"id": "0741650e7ad7567b84f776db7ddad2b8f5a598ea"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/tutorials/adding-actions-and-filters.md",
"hash": "fa6bc021c918aa168023a90e683832455dfa35abbb2561470b08002f1281356f",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/tutorials/adding-actions-and-filters.md",
"id": "3f4d6dcdbc181b11c97c438132ec13a0a8484524"
},
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/tutorials/adding-a-custom-field-to-variable-products.md",
"hash": "a6b654234e7c7f1fc3f9be49b7d00187d6f271e2d699971bade3cf9a728a780a",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/tutorials/adding-a-custom-field-to-variable-products.md",
"id": "f0a7a4a194a6e0aee6f939791f3eaebf36aebb27"
}
],
"categories": []
},
{
"category_title": "Utilities",
"posts": [
{
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/utilities/logging.md",
"hash": "8912094df57a66c047fe2177be815a40024b461a10ddd61ed297c4b2c2919d64",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/utilities/logging.md",
"id": "f673f50bdd83d5d0d7fd8d9976828f8736809510",
"links": {
"_media/log-critical.jpg": "cc802f94ac4cf125a66bc6bb77bf95b80bf4fbed"
}
}
],
"categories": [
{
"category_title": "_media",
"categories": []
}
]
}
],
"hash": "fc6ee378adfa92b706b9d0813f541bf6e8029634c0dd6623000f76047316f0af"
}

View File

@ -0,0 +1,138 @@
# Adding a Section to a Settings Tab
When youre adding building an extension for WooCommerce that requires settings of some kind, its important to ask yourself: **Where do they belong?** If your extension just has a couple of simple settings, do you really need to create a new tab specifically for it? Most likely the answer is no.
## [When to Create a Section](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extesion-developlment/adding-a-section-to-a-settings-tab.md#section-1)
Lets say we had an extension that adds a slider to a single product page. This extension doesnt have many options, just a couple:
- Auto-insert into single product page (checkbox)
- Slider Title (text field)
Thats only two options, specifically related to **Products**. We could quite easily just append them onto the core WooCommerce Products Settings (**WooCommerce > Settings > Products**), but that wouldnt be very user friendly. Users wouldnt know where to look initially so theyd have to scan all of the Products options and it would be difficult / impossible to link the options directly. Fortunately, as of WooCommerce 2.2.2, there is a new filter in place that allows you add a new **section**, beneath one of the core settings tabs.
> **Note:** This is a **Developer level** doc. If you are unfamiliar with code/templates and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/) for assistance. We are unable to provide support for customizations under our [Support Policy](http://www.woocommerce.com/support-policy/).
## [How to Create a Section](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extesion-developlment/adding-a-section-to-a-settings-tab.md#section-2)
Well go over doing this through individual functions, but you should probably create a Class that stores all of your settings methods.
The first thing you need to is add the section, which can be done like this by hooking into the `woocommerce_get_sections_products` filter:
```php
/**
* Create the section beneath the products tab
**/
add_filter( 'woocommerce_get_sections_products', 'wcslider_add_section' );
function wcslider_add_section( $sections ) {
$sections['wcslider'] = __( 'WC Slider', 'text-domain' );
return $sections;
}
```
_[wc-create-section-beneath-products.php](https://gist.github.com/woogists/2964ec01c8bea50fcce62adf2f5c1232/raw/da5348343cf3664c0bc8b6b132d8105bfcf9ca51/wc-create-section-beneath-products.php)_
Make sure you change the **wcslider** parts to suit your extensions name / text-domain. The important thing about the `woocommerce_get_sections_products` filter, is that the last part **products**, is the tab youd like to add a section to. So if you want to add a new tab to accounts section, you would hook into the `woocommerce_get_sections_accounts` filter.
## [How to Add Settings to a Section](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extesion-developlment/adding-a-section-to-a-settings-tab.md#section-3)
Now that youve got the tab, you need to filter the output of `woocommerce_get_sections_products` (or similar). You would add the settings like usual using the [**WooCommerce Settings API**](https://github.com/woocommerce/woocommerce/blob/trunk/docs/settings-api/), but check for the current section before adding the settings to the tabs settings array. For example, lets add the sample settings we discussed above to the new **wcslider** section we just created:
```php
/**
* Add settings to the specific section we created before
*/
add_filter( 'woocommerce_get_settings_products', 'wcslider_all_settings', 10, 2 );
function wcslider_all_settings( $settings, $current_section ) {
/**
* Check the current section is what we want
**/
if ( $current_section == 'wcslider' ) {
$settings_slider = array();
// Add Title to the Settings
$settings_slider[] = array( 'name' => __( 'WC Slider Settings', 'text-domain' ), 'type' => 'title', 'desc' => __( 'The following options are used to configure WC Slider', 'text-domain' ), 'id' => 'wcslider' );
// Add first checkbox option
$settings_slider[] = array(
'name' => __( 'Auto-insert into single product page', 'text-domain' ),
'desc_tip' => __( 'This will automatically insert your slider into the single product page', 'text-domain' ),
'id' => 'wcslider_auto_insert',
'type' => 'checkbox',
'css' => 'min-width:300px;',
'desc' => __( 'Enable Auto-Insert', 'text-domain' ),
);
// Add second text field option
$settings_slider[] = array(
'name' => __( 'Slider Title', 'text-domain' ),
'desc_tip' => __( 'This will add a title to your slider', 'text-domain' ),
'id' => 'wcslider_title',
'type' => 'text',
'desc' => __( 'Any title you want can be added to your slider with this option!', 'text-domain' ),
);
$settings_slider[] = array( 'type' => 'sectionend', 'id' => 'wcslider' );
return $settings_slider;
/**
* If not, return the standard settings
**/
} else {
return $settings;
}
}
```
_[wc-add-settings-section.php](https://gist.github.com/woogists/4038b83900508806c57a193a2534b845#file-wc-add-settings-section-php)_
Were hooking into the same `woocommerce_get_sections_products` filter, but this time doing a check that the `$current_section` matches our earlier defined custom section (wcslider), before adding in our new settings.
## [Using the New Settings](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extesion-developlment/adding-a-section-to-a-settings-tab.md#section-4)
You would now just use your newly created settings like you would any other WordPress / WooCommerce setting, through the [**get_option**](http://codex.wordpress.org/Function_Reference/get_option) function and the defined ID of the setting. For example, to use the previously created **wcslider_auto_insert** option, simply use the following code: `get_option( 'wcslider_auto_insert' )`
## [Conclusion](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extesion-developlment/adding-a-section-to-a-settings-tab.md#section-5)
When creating an extension for WooCommerce, think about where your settings belong before you create them. The key to building a useful product is making it easy to use for the end user, so appropriate setting placement is crucially important. For more specific information on adding settings to WooCommerce, check out the [**Settings API documentation**](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extesion-developlment/settings-api/).

View File

@ -0,0 +1,54 @@
# Classes in WooCommerce
## [List of Classes in WooCommerce](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extension-development/class-reference#section-1)
For a list of Classes in WooCommerce, please see the [WooCommerce Code Reference](https://woocommerce.github.io/code-reference/packages/WooCommerce-Classes.html).
## [Common Classes](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extension-development/class-reference#section-2)
### [WooCommerce](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extension-development/class-reference#section-3)
The main class is `woocommerce` which is available globally via the `$woocommerce` variable. This handles the main functions of WooCommerce and inits other classes, stores site-wide variables, and handles error/success messages. The woocommerce class initializes the following classes when constructed:
- `WC_Query` stored in `$woocommerce->query`
- `WC_Customer` stored in `$woocommerce->customer`
- `WC_Shipping` stored in `$woocommerce->shipping`
- `WC_Payment_Gateways` stored in `$woocommerce->payment_gateways`
- `WC_Countries` stored in `$woocommerce->countries`
Other classes are auto-loaded on demand.
View the [WooCommerce Class Code Reference](https://woocommerce.github.io/code-reference/classes/WooCommerce.html) for a full list of methods contained in this class.
### [WC_Product](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extension-development/class-reference#section-4)
WooCommerce has several product classes responsible for loading and outputting product data. This can be loaded through PHP using:
`$product = wc_get_product( $post->ID );`
In the loop this is not always necessary since calling `the_post()` will automatically populate the global `$product` variable if the post is a product.
View the [WC_Product Code Reference](https://woocommerce.github.io/code-reference/classes/WC-Product.html) for a full list of methods contained in this class.
### [WC_Customer](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extension-development/class-reference#section-5)
The customer class allows you to get data about the current customer, for example:
```php
global $woocommerce;
$customer_country = $woocommerce->customer->get_country();
```
View the [WC_Customer Code Reference](https://woocommerce.github.io/code-reference/classes/WC-Customer.html) for a full list of methods contained in this class.
### [WC_Cart](https://github.com/woocommerce/woocommerce/blob/trunk/docs/extension-development/class-reference#section-6)
The cart class loads and stores the users cart data in a session. For example, to get the cart subtotal you could use:
```php
global $woocommerce;
$cart_subtotal = $woocommerce->cart->get_cart_subtotal();
```
View the [WC_Cart Code Reference](https://woocommerce.github.io/code-reference/classes/WC-Cart.html) for a full list of methods contained in this class.

View File

@ -63,7 +63,7 @@ Starting with these three broad lifecycle areas, you can begin to break your ext
## Handling activation and deactivation
A common pattern in WooCommerce extensions is to create dedicated functions in your main PHP file to serve as activation and deactivation hooks. You then register these hooks with WordPress using the applicable registration function. This tells WordPess to call the function when the plugin is activated or deactivated. Consider the following examples:
A common pattern in WooCommerce extensions is to create dedicated functions in your main PHP file to serve as activation and deactivation hooks. You then register these hooks with WordPress using the applicable registration function. This tells WordPress to call the function when the plugin is activated or deactivated. Consider the following examples:
```php
function my_extension_activate() {

View File

@ -0,0 +1,110 @@
# Settings API
The WooCommerce Settings API is used by extensions to display, save, and load settings. The best way to make use of the API in your extension is to create a class that extends the `WC_Settings_API` class:
```php
class My_Extension_Settings extends WC_Settings_API {
//
}
```
## Defining form fields
You can define your fields using a method called `init_form_fields` in your class constructor:
```php
$this->init_form_fields();
```
You must have your settings defined before you can load them. Setting definitions go in the `form_fields` array:
```php
/**
* Initialise gateway settings form fields.
*/
function init_form_fields() {
$this->form_fields = array(
'title' => array(
'title' => __( 'Title', 'your-text-domain' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'your-text-domain' ),
'default' => __( 'PayPal', 'your-text-domain' )
),
'description' => array(
'title' => __( 'Description', 'your-text-domain' ),
'type' => 'textarea',
'description' => __( 'This controls the description which the user sees during checkout.', 'your-text-domain' ),
'default' => __( "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account", 'your-text-domain' )
)
);
} // End init_form_fields()
```
(Make sure your class initializes the `form_fields` property so that the "Creation of dynamic property" error is not thrown in PHP 8.2+)
In the above example we define two settings, Title and Description. Title is a text box, whereas Description is a textarea. Notice how you can define a default value and a description for the setting itself.
Setting definitions use the following format:
```php
'setting_name' => array(
'title' => 'Title for your setting shown on the settings page',
'description' => 'Description for your setting shown on the settings page',
'type' => 'text|password|textarea|checkbox|select|multiselect',
'default' => 'Default value for the setting',
'class' => 'Class for the input element',
'css' => 'CSS rules added inline on the input element',
'label' => 'Label', // For checkbox inputs only.
'options' => array( // Array of options for select/multiselect inputs only.
'key' => 'value'
),
)
```
## Displaying your settings
Create a method called `admin_options` containing the following:
```php
function admin_options() {
?>
<h2><?php esc_html_e( 'Your plugin name', 'your-text-domain' ); ?></h2>
<table class="form-table">
<?php $this->generate_settings_html(); ?>
</table>
<?php
}
```
This will output your settings in the correct format.
## Saving your settings
To have your settings save, add your class's `process_admin_options` method to the appropriate `_update_options_` hook. For example, payment gateways should use the payment gateway hook:
```php
add_action( 'woocommerce_update_options_payment_gateways', array( $this, 'process_admin_options' ) );
```
Other types of plugins have similar hooks:
```php
add_action( 'woocommerce_update_options_shipping_methods', array( $this, 'process_admin_options' ) );
```
## Loading your settings
In the constructor you can load the settings you previously defined:
```php
// Load the settings.
$this->init_settings();
```
After that you can load your settings from the settings API. The `init_settings` method above populates the settings variable for you:
```php
// Define user set variables
$this->title = $this->settings['title'];
$this->description = $this->settings['description'];
```

View File

@ -0,0 +1,38 @@
# Using custom attributes in menus and taxonomy archives
Attributes that can be used for the layered nav are a custom taxonomy, which means you can display them in menus, or display products by attributes. This requires some work on your part, and archives must be enabled.
> **Note:** This is a **Developer level** doc. If you are unfamiliar with code/templates and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/) for assistance. We are unable to provide support for customizations under our [Support Policy](http://www.woocommerce.com/support-policy/).
# Register the taxonomy for menus
When registering taxonomies for your custom attributes, WooCommerce calls the following hook:
```php
$show_in_nav_menus = apply_filters('woocommerce_attribute_show_in_nav_menus', false, $name);
```
So, for example, if your attribute slug was `size` you would do the following to register it for menus:
```php
add_filter('woocommerce_attribute_show_in_nav_menus', 'wc_reg_for_menus', 1, 2);
function wc_reg_for_menus( $register, $name = '' ) {
if ( $name == 'pa_size' ) $register = true;
return $register;
}
```
Custom attribute slugs are prefixed with `pa_`, so an attribute called `size` would be `pa_size`
Now use your attribute in **Appearance > Menus**. You will notice, however, that it has default blog styling when you click on a link to your taxonomy term.
# Create a template
You need to theme your attribute to make it display products as you want. To do this:
1. Copy `woocommerce/templates/taxonomy-product_cat.php` into your theme folder
2. Rename the template to reflect your attribute in our example wed use `taxonomy-pa_size.php`
You should now see this template when viewing taxonomy terms for your custom attribute.

View File

@ -0,0 +1,19 @@
# Resources for debugging
## WordPress
A good place to start is usually the debugging tools built into WordPress itself:
* [Debugging in WordPress](https://wordpress.org/documentation/article/debugging-in-wordpress/)
## Logging
WooCommerce has a logging system that can be very helpful for finding and tracking errors on your site:
* [Logging in WooCommerce](../utilities/logging.md)
## Xdebug
If you're using `wp-env` to run a local development environment (this is the recommended method for the WooCommerce monorepo), you can activate Xdebug and then use an IDE like VS Code or PhpStorm to set breakpoints and step through the code as it executes:
* [Using Xdebug](https://github.com/WordPress/gutenberg/tree/trunk/packages/env#using-xdebug)

View File

@ -1,86 +0,0 @@
# High Performance Order Storage (HPOS)
WooCommerce has traditionally stored store orders and related order information (like refunds) as custom WordPress post types or post meta records. This comes with performance issues, and that's why HPOS (High-Performance Order Storage) was developed. HPOS is the WooCommerce engine that stores orders in dedicated tables.
HPOS is also referred to as COT (Custom Order Tables) in some parts of the code, that's the early name of the engine.
There are a number of settings that control HPOS operation. Boolean settings are stored using the usual WooCommerce convention: `yes` for enabled ("set to true"), `no` for disabled ("set to false").
Most of the code related to HPOS is in [src/Internal/DataStores/Orders](https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/src/Internal/DataStores/Orders).
## Database tables
A number of database tables are used to store order data by HPOS. The `get_all_table_names` method in [the OrdersTableDataStore class](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php) will return the names of all the tables.
## Enabling the feature
For HPOS to be usable, the HPOS feature must first be enabled. This should be done programmatically via [the features controller](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/Features/FeaturesController.php), or via admin UI (WooCommerce - Settings - Advanced - Features). The feature enable option name for HPOS is `woocommerce_feature_custom_order_tables_enabled`. The required database tables will be created automatically once the feature is enabled.
## Authoritative tables
At any given time, while the HPOS feature is enabled, there are two roles for the involved database tables: _authoritative_ and _backup_. The authoritative tables are the working tables, where order data will be stored to and retrieved from during normal operation of the store. The _backup_ tables will receive a copy of the authoritative data whenever [synchronization](#synchronization) happens.
If the `woocommerce_custom_orders_table_enabled` options is set to true, HPOS is active and [the new tables](#database-tables) are authoritative, while the posts and post meta tables act as the backup tables. If the option is set to false, it's the other way around. The option can be changed via admin UI (WooCommerce - Settings - Advanced - Custom data stores).
[The CustomOrdersTableController class](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php) hooks on the `woocommerce_order_data_store` filter so that `WC_Data_Store::load( 'order' );` will return either an instance of [OrdersTableDataStore](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php) or an instance of [WC_Order_Data_Store_CPT](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/includes/data-stores/class-wc-order-data-store-cpt.php), depending on which are the authoritative tables.
In order to preserve data integrity, switching the authoritative tables (from the new tables to the posts table or the other way around) isn't allowed while there are orders pending synchronization.
## Synchronization
_Synchronization_ is the process of applying all the pending changes in the authoritative tables to the backup tables. _Orders pending synchronization_ are orders that have been modified in the authoritative tables but the changes haven't been applied to the backup tables yet.
This can happen in a number of ways:
### Immediate synchronization
If the `woocommerce_custom_orders_table_data_sync_enabled` setting is set to true, synchronization happens automatically and immediately as soon as the orders are changed in the authoritative tables.
### Manual synchronization
When immediate synchronization is disabled, it can be triggered manually via command line as follows: `wp wc cot sync`. It can also be triggered programmatically as follows:
```php
$synchronizer = wc_get_container()->get(Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class);
$order_ids = $synchronizer->get_next_batch_to_process( $batch_size );
if ( count( $order_ids ) ) {
$synchronizer->process_batch( $order_ids );
}
```
where `$batch_size` is the maximum count of orders to process.
### Scheduled synchronization
If immediate synchronization gets activated (`woocommerce_custom_orders_table_data_sync_enabled` is set to true) while there are orders pending synchronization, an instance of [DataSynchronizer](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/DataSynchronizer.php) will be enqueued using [BatchProcessingController](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/BatchProcessing/BatchProcessingController.php) so that the synchronization of created/modified/deleted orders will happen in batches via scheduled actions. This scheduling happens inside [CustomOrdersTableController](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php), by means of hooking into `woocommerce_update_options_advanced_custom_data_stores`.
If for some reason immediate synchronization is already active but synchronization is not scheduled, a trick to restart it is to go to the settings page (WooCommerce - Settings - Advanced - Custom data stores) and hit "Save" even without making any changes. As long as "Keep the posts table and the orders tables synchronized" is checked the synchronization scheduling will happen, even if it was checked before.
If the `woocommerce_auto_flip_authoritative_table_roles` option is set to true (there's a checkbox for it in the settings page), the authoritative tables will be switched automatically once all the orders have been synchronized. This is handled by [the CustomOrdersTableController class](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php).
### Deletion synchronization
Synchronization of order deletions is tricky: if an order exists in one set of tables (new tables or posts) but not in the other, it's not clear if the missing orders need to be created or if the existing orders need to be deleted. Theoretically, the orders missing from the backup tables imply the former and the orders missing from the authoritative tables imply the latter; but that's dangerous as a bug in the involved code could easily lead to the deletion of legitimate orders.
To achieve a robust order deletion synchronization mechanism the following is done. Whenever an order is deleted and immediate synchronization is disabled, a record is created in the `wp_wc_orders_meta` table that has `deleted_from` as the key and the name of the authoritative table the order was deleted from (`wp_wc_orders` or the posts table). Then at synchronization time these records are processed (the corresponding orders are deleted from the corresponding tables) and deleted afterwards.
An exception to the above are the [placeholder records](#placeholder-records): these are deleted immediately when the corresponding order is deleted from `wp_wc_orders`, even if immediate synchronization is disabled.
## Placeholder records
Order IDs must match in both the authoritative tables and the backup tables, otherwise synchronization wouldn't be possible. The order IDs that are compared for order identification and synchronization purposes are the ones from the `id` field in both the `wp_wc_orders` table and the posts table.
If the posts table is authoritative, achieving an order ID match is easy: the record in `wp_wc_orders` is created with the same ID and that's it. However, when the new orders tables are authoritative there's a problem: the posts table is used to store multiple types of data, not only orders; and by the time synchronization needs to happen, a non-order post could already exist having the same ID as the order to synchronize.
To solve this, _placeholder records_ are used. Whenever the new orders tables are authoritative and immediate synchronization is disabled, creating a new order will cause a record with post type `shop_order_placehold` and the same ID as the order to be created in the posts table; this effectively "reserves" the order ID in the posts table. Then, at synchronization time, the record is filled appropriately and its post type is changed to `shop_order`.

View File

@ -1,5 +0,0 @@
# High Performance Order Storage
> ⚠️ **Notice:** This documentation is currently a **work in progress**. While it's open to the public for transparency and collaboration, please be aware that some sections might be incomplete or subject to change. We appreciate your patience and welcome any contributions!
This section is where you can learn about High-Performance Order Storage (HPOS): a new database storage for orders to allow effortless scaling for large and high growth stores.

View File

@ -0,0 +1,162 @@
# High Performance Order Storage (HPOS)
WooCommerce has traditionally stored store orders and related order information (like refunds) as custom WordPress post types or post meta records. This comes with performance issues.
[High-Performance Order Storage (HPOS)](https://developer.woocommerce.com/2022/09/14/high-performance-order-storage-progress-report/) also previously known as “Custom Order Tables” is a solution that provides an easy-to-understand and solid database structure specifically designed for eCommerce needs. It uses the WooCommerce CRUD design to store order data in custom tables optimized for WooCommerce queries with minimal impact on the stores performance.
In January 2022, we published the [initial plan for the Custom Order Tables feature](https://developer.woocommerce.com/2022/01/17/the-plan-for-the-woocommerce-custom-order-table/) and since then, weve been working hard to bring the High-Performance Order Storage (HPOS) to WooCommerce Core. In May 2022, we invited you to [test the order migration process](https://developer.woocommerce.com/2022/05/16/call-for-early-testing-custom-order-table-migrations/) and provide feedback on how our initial work performs on real stores of varied configurations.
From WooCommerce 8.2, released on October 2023, [High-Performance Order Storage (HPOS)](https://developer.woocommerce.com/2022/09/14/high-performance-order-storage-progress-report/) is officially released under the stable flag and will be enabled by default for new installations.
## [Whats New with High-Performance Order Storage?](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-1)
Bringing High-Performance Order Storage (HPOS) to WooCommerce improves these three essential properties for eCommerce stores.
1/ **Scalability**
The rise in the number of customers and customer orders increases the load on your stores database making it difficult to handle customer order requests and deliver a seamless user experience.
With High-Performance Order Storage, you get dedicated tables for data like orders and order addresses and thus dedicated indexes which results in fewer read/write operations and fewer busy tables. This feature enables eCommerce stores of all shapes and sizes to scale their business to their maximum potential without expert intervention.
2/ **Reliability**
High-Performance Order Storage makes implementing and restoring targeted data backup easier. Youll no longer need to worry about losing orders, inventory numbers, or client information with reliable backup in these custom order tables. Itll also facilitate implementing read/write locks and prevent race conditions.
3/ **Simplicity**
You no longer have to go through a single huge database to locate underlying data and WooCommerce entries.
With High-Performance Order Storage, you can easily browse through the separate tables and easy-to-handle entries, independent of the table `_posts`, to find data or understand the table structure. It also lets you easily develop new plugins, implement designs for shops and products, and modify WooCommerce with more flexibility.
## [Background](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-2)
Before the release of version 8.2, WooCommerce relied on the `_post` and `_postmeta` table structures to store order information, which has served well over the years.
However, High-Performance Order Storage introduces dedicated tables for data like orders and order addresses and thus dedicated indexes which results in fewer read/write operations and fewer busy tables. This feature enables eCommerce stores of all shapes and sizes to scale their business to their maximum potential without expert intervention.
The order data is synced from `_posts` and `_postmeta` table to four custom order tables:
1. `_wc_orders`
2. `_wc_order_addresses`
3. `_wc_order_operational_data`
4. `_wc_orders_meta`
## [Enabling the feature](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-3)
From WooCommerce 8.2, released on October 2023, HPOS is enabled by default for new installations. Existing stores can check [How to enable HPOS](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/enable-hpos.md)
## [Database tables](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-4)
A number of database tables are used to store order data by HPOS. The `get_all_table_names` method in [the OrdersTableDataStore class](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php) will return the names of all the tables.
## [Authoritative tables](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-5)
At any given time, while the HPOS feature is enabled, there are two roles for the involved database tables: _authoritative_ and _backup_. The authoritative tables are the working tables, where order data will be stored to and retrieved from during normal operation of the store. The _backup_ tables will receive a copy of the authoritative data whenever [synchronization](#synchronization) happens.
If the `woocommerce_custom_orders_table_enabled` options is set to true, HPOS is active and [the new tables](#database-tables) are authoritative, while the posts and post meta tables act as the backup tables. If the option is set to false, it's the other way around. The option can be changed via admin UI (WooCommerce - Settings - Advanced - Custom data stores).
[The CustomOrdersTableController class](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php) hooks on the `woocommerce_order_data_store` filter so that `WC_Data_Store::load( 'order' );` will return either an instance of [OrdersTableDataStore](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php) or an instance of [WC_Order_Data_Store_CPT](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/includes/data-stores/class-wc-order-data-store-cpt.php), depending on which are the authoritative tables.
In order to preserve data integrity, switching the authoritative tables (from the new tables to the posts table or the other way around) isn't allowed while there are orders pending synchronization.
## [Synchronization](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-6)
_Synchronization_ is the process of applying all the pending changes in the authoritative tables to the backup tables. _Orders pending synchronization_ are orders that have been modified in the authoritative tables but the changes haven't been applied to the backup tables yet.
This can happen in a number of ways:
### Immediate synchronization
If the `woocommerce_custom_orders_table_data_sync_enabled` setting is set to true, synchronization happens automatically and immediately as soon as the orders are changed in the authoritative tables.
### Manual synchronization
When immediate synchronization is disabled, it can be triggered manually via command line as follows: `wp wc cot sync`. It can also be triggered programmatically as follows:
```php
$synchronizer = wc_get_container()->get(Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class);
$order_ids = $synchronizer->get_next_batch_to_process( $batch_size );
if ( count( $order_ids ) ) {
$synchronizer->process_batch( $order_ids );
}
```
where `$batch_size` is the maximum count of orders to process.
### Scheduled synchronization
If immediate synchronization gets activated (`woocommerce_custom_orders_table_data_sync_enabled` is set to true) while there are orders pending synchronization, an instance of [DataSynchronizer](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/DataSynchronizer.php) will be enqueued using [BatchProcessingController](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/BatchProcessing/BatchProcessingController.php) so that the synchronization of created/modified/deleted orders will happen in batches via scheduled actions. This scheduling happens inside [CustomOrdersTableController](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php), by means of hooking into `woocommerce_update_options_advanced_custom_data_stores`.
If for some reason immediate synchronization is already active but synchronization is not scheduled, a trick to restart it is to go to the settings page (WooCommerce - Settings - Advanced - Custom data stores) and hit "Save" even without making any changes. As long as "Keep the posts table and the orders tables synchronized" is checked the synchronization scheduling will happen, even if it was checked before.
If the `woocommerce_auto_flip_authoritative_table_roles` option is set to true (there's a checkbox for it in the settings page), the authoritative tables will be switched automatically once all the orders have been synchronized. This is handled by [the CustomOrdersTableController class](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php).
### Deletion synchronization
Synchronization of order deletions is tricky: if an order exists in one set of tables (new tables or posts) but not in the other, it's not clear if the missing orders need to be created or if the existing orders need to be deleted. Theoretically, the orders missing from the backup tables imply the former and the orders missing from the authoritative tables imply the latter; but that's dangerous as a bug in the involved code could easily lead to the deletion of legitimate orders.
To achieve a robust order deletion synchronization mechanism the following is done. Whenever an order is deleted and immediate synchronization is disabled, a record is created in the `wp_wc_orders_meta` table that has `deleted_from` as the key and the name of the authoritative table the order was deleted from (`wp_wc_orders` or the posts table). Then at synchronization time these records are processed (the corresponding orders are deleted from the corresponding tables) and deleted afterwards.
An exception to the above are the [placeholder records](#placeholder-records): these are deleted immediately when the corresponding order is deleted from `wp_wc_orders`, even if immediate synchronization is disabled.
When the “**High-Performance Order Storage**” and “**Compatibility mode**” are enabled, WooCommerce populates the HPOS tables with data from posts & postmeta tables. The synchronization between the tables is [explained in detail in this document](https://developer.woocommerce.com/2022/09/29/high-performance-order-storage-backward-compatibility-and-synchronization/#synchronization).
> You can find a deeper explanation about the synchronization between the tables in [this document about high-performance-order-storage-backward-compatibility-and-synchronization](https://developer.woocommerce.com/2022/09/29/high-performance-order-storage-backward-compatibility-and-synchronization/#synchronization).
## [Placeholder records](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-7)
Order IDs must match in both the authoritative tables and the backup tables, otherwise synchronization wouldn't be possible. The order IDs that are compared for order identification and synchronization purposes are the ones from the `id` field in both the `wp_wc_orders` table and the posts table.
If the posts table is authoritative, achieving an order ID match is easy: the record in `wp_wc_orders` is created with the same ID and that's it. However, when the new orders tables are authoritative there's a problem: the posts table is used to store multiple types of data, not only orders; and by the time synchronization needs to happen, a non-order post could already exist having the same ID as the order to synchronize.
To solve this, _placeholder records_ are used. Whenever the new orders tables are authoritative and immediate synchronization is disabled, creating a new order will cause a record with post type `shop_order_placehold` and the same ID as the order to be created in the posts table; this effectively "reserves" the order ID in the posts table. Then, at synchronization time, the record is filled appropriately and its post type is changed to `shop_order`.
## [Order Data Storage](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-8)
You can switch between data stores freely to sync the data between the tables.
- If you select **“WordPress Post Tables”**, the system will save the order data within `_post` and `_postmeta` tables. The order tables are not utilized in this scenario.
![Select WordPress Post Tables](https://woocommerce.com/wp-content/uploads/2023/10/image-18.png?w=650)
- If you select **“High-Performance Order Storage”**, the system will save the order data within the new WooCommerce order tables
![Select High-Performance Order Storage](https://woocommerce.com/wp-content/uploads/2023/10/image-19.png?w=650)
- If you select **“WordPress Post Tables”** and **“Enable compatibility mode”**, the system will sync the order data between the posts/postmeta and the WooCommerce order tables.
![Select WordPress Post Tables and Enable compatibility mode](https://woocommerce.com/wp-content/uploads/2023/10/image-20.png?w=650)
## [Incompatible Plugins](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-9)
If you are using a plugin that is not compatible with High-Performance Order Storage, then the HPOS option will be disabled under **WooCommerce > Settings > Advanced > Features**.
![Incompatible plugin](https://woocommerce.com/wp-content/uploads/2023/10/image-21.png?w=650)
- You can click on “**View and manage**” to review the list of incompatible plugins
- Or you can visit `https://example.com/wp-admin/plugins.php?plugin_status=incompatible_with_feature&feature_id=custom_order_tables` to review the list of incompatible plugins (please replace `example.com` with your site domain)
![Plugins page](https://woocommerce.com/wp-content/uploads/2023/10/image-22.png?w=650)
> **Note:** If you are using a third-party extension that isnt working properly with High-Performance Order Storage then please notify the developers of the extension and ask them to update their extension to add support for HPOS. Its up to the extension developers to add support for HPOS. We have [developer resources and documentation](https://developer.woocommerce.com/2022/09/14/high-performance-order-storage-progress-report/) available to help with their integration efforts.
## [Disabling HPOS](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-10)
If you encounter problems or if you need to continue working with plugins that are not yet compatible with HPOS, then we recommend temporarily switching back to **WordPress posts storage**.
To do this, navigate to **WooCommerce ▸ Settings ▸ Advanced ▸ Features** and start by making sure that **compatibility mode** is enabled. If it was not already enabled, you may find you need to wait for some time while order data is synchronized across data-stores.
![WooCommerce ▸ Settings ▸ Advanced ▸ Features Screen](https://woocommerce.com/wp-content/uploads/2023/10/hpos-feature-settings.png?w=650)
Once synchronization has completed, you can select **WordPress posts storage (legacy)** as your preferred option. You can also disable compatibility mode at this point. Once you are ready to re-enable HPOS, simply follow the instructions posted at the [start of this doc](https://github.com/woocommerce/woocommerce/blob/trunk/docs/high-performance-order-storage/#section-3). Finally, remember to save this page between changes!
As noted earlier, we also strongly recommend reaching out to the support teams of any plugins that are incompatible, so they can take corrective action.

View File

@ -0,0 +1,25 @@
# How to enable HPOS
From WooCommerce 8.2, released on October 2023, HPOS is enabled by default for new installations. Existing stores can switch to the “High-Performance Order Storage” from “WordPress Posts Storage” by following the below steps.
To activate High-Performance Order Storage, existing stores will first need to get both the posts and orders table in sync, which can be done by turning on the setting “**Enable compatibility mode (synchronizes orders to the posts table)**“.
1/ Navigate to **WooCommerce > Settings > Advanced > Features**
2/ Turn on the **“Enable compatibility mode (synchronizes orders to the posts table)”** setting.
![Enable HPOS Screen](https://woocommerce.com/wp-content/uploads/2023/10/New-Project-4.jpg?w=650)
3/ Once this setting is activated, background actions will be scheduled.
- The action `wc_schedule_pending_batch_process` checks whether there are orders that need to be backfilled.
- If there are, it schedules another action `wc_run_batch_process` that actually backfills the orders to post storage.
- You can either wait for these actions to run on their own, which should be quite soon, or you can go to **WooCommerce > Status > Scheduled Actions**, find the actions and click on the run button.
- The action will backfill 25 orders at a time, if there are more orders to be synced, then more actions will be scheduled as soon as the previous actions are completed.
![wc_schedule_pending_batch_process Screen](https://woocommerce.com/wp-content/uploads/2023/10/2.jpg?w=650)
![wc_run_batch_process Screen](https://woocommerce.com/wp-content/uploads/2023/10/New-Project-5.jpg?w=650)
4/ After both tables are successfully synchronized, youll be able to select the option to switch to High-Performance Order Storage (HPOS).
- It is advisable to maintain compatibility mode for some time to ensure a seamless transition. In case of any issues, reverting to the post table can be done instantly.

View File

@ -0,0 +1,38 @@
# Product Editor Development Handbook
> ⚠️ **Notice:** This documentation is currently a **work in progress**. Please be aware that some sections might be incomplete or subject to change. We appreciate your patience and welcome any contributions!
This handbook is a guide for extension developers looking to add support for the new product editor in their extensions. The product editor uses [Gutenberg's Block Editor](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-editor), which is going to help WooCommerce evolve alongside the WordPress ecosystem.
The product editor's UI consists of Groups (currently rendered as tabs), Sections, and Fields, which are all blocks.
![Product editor structure](https://woocommerce.files.wordpress.com/2023/09/groups-sections-fields.jpg)
The form's structure is defined in PHP using a Template, which is a tree structure of blocks. The template can be modified by using the Template API to add new Groups, Sections, and Fields as well as remove existing ones.
Many extensibility implementations can be done using only the PHP-based Block Template API alongside our library of [generic blocks](../../packages/js/product-editor/src/blocks/generic/README.md). More complex interactivity can be implemented using JavaScript and React (the same library used to implement the core blocks used in the product editor). [@woocommerce/create-product-editor-block](../../packages/js/create-product-editor-block/README.md) can help scaffold a development environment with JavaScript and React.
## Declaring compatibility with the product editor
To declare compatibility with the product editor, add the following to your plugin's root PHP file:
```php
use Automattic\WooCommerce\Utilities\FeaturesUtil;
add_action(
'before_woocommerce_init',
function() {
if ( class_exists( FeaturesUtil::class ) ) {
FeaturesUtil::declare_compatibility( 'product_block_editor', plugin_basename( __FILE__ ), true );
}
}
);
```
Please note that this check is currently not being enforced: the product editor can still be enabled even without this declaration. However, we might enforce this in the future, so it is recommended to declare compatibility as soon as possible.
## Related documentation
- [Examples on Template API usage](../../plugins/woocommerce/src/Admin/Features/ProductBlockEditor/ProductTemplates/README.md)
- [Related hooks and Template API documentation](../../plugins/woocommerce/src/Admin/BlockTemplates/README.md)
- [Generic blocks documentation](../../packages/js/product-editor/src/blocks/generic/README.md)

View File

@ -0,0 +1,276 @@
# WooCommerce core critical flows
We have identified what we consider to be our most critical user flows within WooCommerce Core. These flows will help us focus and prioritize our testing efforts. They will also help us consider the impact of changes and priority of issues.
These flows will continually evolve as the platform evolves with flows updated, added or re-prioritised.
## Shopper critical flow areas
- 🛒 [Shopper > Shop](#shopper---shop)
- 🛒 [Shopper > Product](#shopper---product)
- 🛒 [Shopper > Cart](#shopper---cart)
- 🛒 [Shopper > Checkout](#shopper---checkout)
- 🛒 [Shopper > Email](#shopper---email)
- 🛒 [Shopper > My Account](#shopper---my-account)
## Merchant critical flow areas
- 💳 [Merchant > Onboarding](#merchant---onboarding)
- 💳 [Merchant > Dashboard](#merchant---dashboard)
- 💳 [Merchant > Settings](#merchant---settings)
- 💳 [Merchant > Coupons](#merchant---coupons)
- 💳 [Merchant > Marketing](#merchant---marketing)
- 💳 [Merchant > Analytics](#merchant---analytics)
- 💳 [Merchant > Products](#merchant---products)
- 💳 [Merchant > Orders](#merchant---orders)
- 💳 [Merchant > Customers](#merchant---customers)
- 💳 [Merchant > Email](#merchant---email)
- 💳 [Merchant > Plugins](#merchant---plugins)
- 💳 [Merchant > My Subscriptions](#merchant---my-subscriptions)
- 💳 [Merchant > Pages](#merchant---pages)
- 💳 [Merchant > Posts](#merchant---posts)
### Shopper - Shop
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ------------------------------------------- | --------------------------------------- |
| Shopper | Shop | Search Store | shopper/shop-search-browse-sort.spec.js |
| Shopper | Shop | Browse by categories | shopper/shop-search-browse-sort.spec.js |
| Shopper | Shop | Can sort items | shopper/shop-search-browse-sort.spec.js |
| Shopper | Shop | Add Simple Product to Cart (from shop page) | shopper/cart.spec.js |
| Shopper | Shop | Display shop catalog | |
| Shopper | Shop | Products by tag | |
| Shopper | Shop | Products by attribute | |
| Shopper | Shop | Use product filters | |
| Shopper | Shop | Display product showcase blocks correctly | |
| Shopper | Shop | Navigation menu default links | |
### Shopper - Product
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ---------------------------------------------------- | -------------------------------- |
| Shopper | Product | Add Simple Product to Cart | shopper/product-simple.spec.js |
| Shopper | Product | Add Grouped Product to Cart | shopper/product-grouped.spec.js |
| Shopper | Product | Variable Product info updates depending on variation | shopper/product-variable.spec.js |
| Shopper | Product | Add Variable Product to Cart | shopper/product-variable.spec.js |
| Shopper | Product | Display up-sell product | |
| Shopper | Product | Display releated products | |
| Shopper | Product | Display reviews | |
| Shopper | Product | Add review | |
| Shopper | Product | View product images | |
| Shopper | Product | View product descriptions | |
### Shopper - Cart
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ------------------------------------------ | ---------------------------------- |
| Shopper | Cart | Add to cart redirects to cart when enabled | shopper/cart-redirection.spec.js |
| Shopper | Cart | View cart | shopper/cart.spec.js |
| Shopper | Cart | Update product quantity within limits | shopper/cart.spec.js |
| Shopper | Cart | Remove products from cart | shopper/cart.spec.js |
| Shopper | Cart | Apply all coupon types | shopper/cart-coupons.spec.js |
| Shopper | Cart | Display shipping options by address | shopper/calculate-shipping.spec.js |
| Shopper | Cart | View empty cart | |
| Shopper | Cart | Display correct tax | |
| Shopper | Cart | Respect coupon usage contraints | |
| Shopper | Cart | Display cross-sell products | |
| Shopper | Cart | Proceed to checkout | |
### Shopper - Checkout
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ---------------------------------------- | --------------------------------------- |
| Shopper | Checkout | Correct item in Order Review | shopper/checkout.spec.js |
| Shopper | Checkout | Can add shipping address | shopper/checkout.spec.js |
| Shopper | Checkout | Guest can place order | shopper/checkout.spec.js |
| Shopper | Checkout | Create an account | shopper/checkout-create-account.spec.js |
| Shopper | Checkout | Login to existing account | shopper/checkout-login.spec.js |
| Shopper | Checkout | Existing customer can place order | shopper/checkout.spec.js |
| Shopper | Checkout | Use all coupon types | shopper/checkout-coupons.spec.js |
| Shopper | Checkout | View checkout | |
| Shopper | Checkout | Receive warnings when form is incomplete | |
| Shopper | Checkout | Add billing address | |
| Shopper | Checkout | Respect coupon usage contraints | |
| Shopper | Checkout | Display correct tax in checkout | |
| Shopper | Checkout | View order confirmation page | |
### Shopper - Email
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ------------------------------------- | ------------------------------------- |
| Shopper | Email | Customer Account Emails Received | shopper/ |
| Shopper | Email | Customer Order Detail Emails Received | shopper/order-email-receiving.spec.js |
### Shopper - My Account
| User Type | Flow Area | Flow Name | Test File |
| --------- | ---------- | ------------------------- | ----------------------------------------- |
| Shopper | My Account | Create an account | shopper/my-account-create-account.spec.js |
| Shopper | My Account | Login to existing account | shopper/my-account.spec.js |
| Shopper | My Account | View Account Details | shopper/my-account.spec.js |
| Shopper | My Account | Update Addresses | shopper/my-account-addresses.spec.js |
| Shopper | My Account | View Orders | shopper/ |
| Shopper | My Account | Pay for Order | shopper/my-account-pay-order.spec.js |
| Shopper | My Account | View Downloads | shopper/my-account-downloads.spec.js |
### Merchant - Onboarding
| User Type | Flow Area | Flow Name | Test File |
| --------- | ------------- | -------------------------------------------------------------- | --------- |
| Merchant | Core Profiler | Introduction & opt-in | |
| Merchant | Core Profiler | User profile information | |
| Merchant | Core Profiler | Business information | |
| Merchant | Core Profiler | Extensions page | |
| Merchant | Core Profiler | WooPayments included in extensions for eligible criteria | |
| Merchant | Core Profiler | WooPayments not included in extensions for ineligible criteria | |
| Merchant | Core Profiler | Install all default extensions | |
| Merchant | Core Profiler | Complete site setup | |
| Merchant | Core Profiler | Skip introduction and confirm business location | |
| Merchant | Core Profiler | Completed profiler doesn't reappear after site upgrade | |
### Merchant - Dashboard
| User Type | Flow Area | Flow Name | Test File |
| --------- | -------------- | ------------------------------------------------------ | --------- |
| Merchant | WC Home | Completing profiler redirects to home | |
| Merchant | WC Home | Complete all steps on task list | |
| Merchant | WC Home | Hide the task list | |
| Merchant | WC Home | Store management displayed after task list finished | |
| Merchant | WC Home | Direct access to analytics reports from stats overview | |
| Merchant | WC Home | Preserve task list completion status after upgrade | |
| Merchant | WC Home | Interact with extended task list | |
| Merchant | Activity Panel | Interact with activity button | |
| Merchant | Inbox | Interact with notes and perform CTAs | |
| Merchant | Inbox | Dismiss single note and all notes | |
### Merchant - Settings
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ----------------------------------------------- | ---------------------------------------- |
| Merchant | Settings | Update General Settings | merchant/settings-general.spec.js |
| Merchant | Settings | Add Tax Rates | merchant/settings-tax.spec.js |
| Merchant | Settings | Add Shipping Zones | merchant/create-shipping-zones.spec.js |
| Merchant | Settings | Add Shipping Classes | merchant/create-shipping-classes.spec.js |
| Merchant | Settings | Enable local pickup for checkout block | |
| Merchant | Settings | Enable HPOS | |
| Merchant | Settings | Update payment settings | |
| Merchant | Settings | Maintain tax and shipping settings post-upgrade | |
### Merchant - Coupons
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | --------------------- | ------------------------------ |
| Merchant | Coupons | Add all coupon types | merchant/create-coupon.spec.js |
| Merchant | Coupons | Add restricted coupon | |
### Merchant - Marketing
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | -------------------------- | --------- |
| Merchant | Marketing | Display marketing overview | |
### Merchant - Analytics
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | -------------------------------------------------- | --------------------------------- |
| Merchant | Analytics | View revenue report | admin-analytics/analytics.spec.js |
| Merchant | Analytics | View overview report | |
| Merchant | Analytics | Confirm correct summary numbers on overview report | |
| Merchant | Analytics | Use date filter on overview page | |
| Merchant | Analytics | Customize performance indicators on overview page | |
| Merchant | Analytics | Use date filter on revenue report | |
| Merchant | Analytics | Download revenue report as CSV | |
| Merchant | Analytics | Use advanced filters on orders report | |
| Merchant | Analytics | Analytics settings | |
| Merchant | Analytics | Set custom date range on revenue report | |
### Merchant - Products
| User Type | Flow Area | Flow Name | Test File |
| --------- | -------------- | ------------------------------ | ---------------------------------------------------------------------- |
| Merchant | Products | View all products | |
| Merchant | Products | Search products | merchant/product-search.spec.js |
| Merchant | Products | Add simple product | merchant/create-simple-product.spec.js |
| Merchant | Products | Add variable product | merchant/products/add-variable-product/create-variable-product.spec.js |
| Merchant | Products | Edit product details | merchant/product-edit.spec.js |
| Merchant | Products | Add virtual product | merchant/create-simple-product.spec.js |
| Merchant | Products | Import products CSV | merchant/product-import-csv.spec.js |
| Merchant | Products | Add downloadable product | |
| Merchant | Products | View product reviews list | |
| Merchant | Products | View all products reviews list | |
| Merchant | Products | Edit product review | |
| Merchant | Products | Trash product review | |
| Merchant | Products | Bulk edit products | |
| Merchant | Products | Remove products | |
| Merchant | Products | Manage product images | |
| Merchant | Products | Manage product inventory | |
| Merchant | Products | Manage product attributes | |
| Merchant | Products | Manage global attributes | |
| Merchant | Products | Add up-sell | |
| Merchant | Products | Add cross-sell | |
| Merchant | Products (New) | Disable new product experience | |
| Merchant | Products (New) | Add simple product | |
| Merchant | Products (New) | Edit simple product | |
| Merchant | Products (New) | Manage product images | |
| Merchant | Products (New) | Manage product inventory | |
| Merchant | Products (New) | Manage product attributes | |
### Merchant - Orders
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ---------------------------------------------------------------- | -------------------------------------- |
| Merchant | Orders | View all orders | merchant/ |
| Merchant | Orders | Can add new order basic | merchant/order-edit.spec.js |
| Merchant | Orders | View single order | merchant/order-edit.spec.js |
| Merchant | Orders | Update order status to completed | merchant/order-edit.spec.js |
| Merchant | Orders | Update order status to cancelled | |
| Merchant | Orders | Update order details | merchant/order-edit.spec.js |
| Merchant | Orders | Customer payment page | merchant/customer-payment-page.spec.js |
| Merchant | Orders | Refund order | merchant/order-refund.spec.js |
| Merchant | Orders | Apply coupon | merchant/order-coupon.spec.js |
| Merchant | Orders | Can add new order complex - multiple product types & tax classes | merchant/create-order.spec.js |
| Merchant | Orders | Search orders | merchant/order-search.spec.js |
| Merchant | Orders | Filter orders by order status | merchant/order-status-filter.spec.js |
| Merchant | Orders | Bulk change order status | |
| Merchant | Orders | Add order notes | |
### Merchant - Customers
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | --------------------- | --------- |
| Merchant | Customers | Display customer list | |
### Merchant - Email
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | -------------------------------------------------- | ----------------------------- |
| Merchant | Email | Receive and check content of new order email | merchant/order-emails.spec.js |
| Merchant | Email | Receive and check content of cancelled order email | |
| Merchant | Email | Receive and check content of failed order email | |
| Merchant | Email | Resent new order email | |
| Merchant | Email | Send invoice/order details to customer via Email | |
### Merchant - Plugins
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | ------------------------- | -------------------------------------- |
| Merchant | Plugins | Can update WooCommerce | smoke-tests/update-woocommerce.spec.js |
| Merchant | Plugins | Can uninstall WooCommerce | |
### Merchant - My Subscriptions
| User Type | Flow Area | Flow Name | Test File |
| --------- | ---------------- | --------------------------------------- | --------- |
| Merchant | My Subscriptions | Can initiate WooCommerce.com Connection | |
### Merchant - Pages
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | --------------------- | ---------------------------- |
| Merchant | Pages | Can create a new page | merchant/create-page.spec.js |
### Merchant - Posts
| User Type | Flow Area | Flow Name | Test File |
| --------- | --------- | --------------------- | ---------------------------- |
| Merchant | Posts | Can create a new post | merchant/create-post.spec.js |

View File

@ -0,0 +1,62 @@
# CSS/Sass Naming Conventions
Table of Contents:
- [Introduction](#introduction)
- [Prefixing](#prefixing)
- [Class names](#class-names)
- [Example](#example)
- [TL;DR](#tldr)
## Introduction
Our guidelines are based on those used in [Calypso](https://github.com/Automattic/wp-calypso), which itself follows the [BEM methodology](https://getbem.com/).
Refer to the [Calypso CSS/Sass Coding Guidelines](https://wpcalypso.wordpress.com/devdocs/docs/coding-guidelines/css.md) for full details.
Read more about [BEM key concepts](https://en.bem.info/methodology/key-concepts/).
There are a few differences in WooCommerce which are outlined below.
## Prefixing
As a WordPress plugin WooCommerce has to play nicely with WordPress core and other plugins/themes. To minimize conflict potential, all classes should be prefixed with `.woocommerce-`.
## Class names
When naming classes, remember:
- **Block** - Standalone entity that is meaningful on its own. Such as the name of a component.
- **Element** - Parts of a block and have no standalone meaning. They are semantically tied to its block.
- **Modifier** - Flags on blocks or elements. Use them to change appearance or behavior.
### Example
```css
/* Block */
.woocommerce-loop {}
/* Nested block */
.woocommerce-loop-product {}
/* Modifier */
.woocommerce-loop-product--sale {}
/* Element */
.woocommerce-loop-product__link {}
/* Element */
.woocommerce-loop-product__button-add-to-cart {}
/* Modifier */
.woocommerce-loop-product__button-add-to-cart--added {}
```
**Note:** `.woocommerce-loop-product` is not named as such because the block is nested within `.woocommerce-loop`. It's to be specific so that we can have separate classes for single products, cart products, etc. **Nested blocks do not need to inherit their parents full name.**
## TL;DR
- Follow the [WordPress Coding standards for CSS](https://make.wordpress.org/core/handbook/best-practices/coding-standards/css/) unless it contradicts anything here.
- Follow [Calypso guidelines for CSS](https://wpcalypso.wordpress.com/devdocs/docs/coding-guidelines/css.md).
- Use BEM for [class names](https://en.bem.info/methodology/naming-convention/).
- Prefix all class names.

View File

@ -0,0 +1,88 @@
# Naming Conventions
Table of Contents:
- [PHP](#php)
- [`/src`](#src)
- [`/includes`](#includes)
- [JS](#js)
- [CSS and SASS](#css-and-sass)
## PHP
WooCommerce core generally follows [WordPress PHP naming conventions](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#naming-conventions).
There are some additional conventions that apply, depending on the location of the code.
### `/src`
Classes defined inside `/src` follow the [PSR-4](https://www.php-fig.org/psr/psr-4/) standard. See the [README for `/src`](../../plugins/woocommerce/src/README.md) for more information.
The following conventions apply to this directory:
- No class name prefix is needed, as all classes in this location live within the `Automattic\WooCommerce` namespace.
- Classes are named using `CamelCase` convention.
- Functions are named using `snake_case` convention.
- Class file names should match the class name. They do not need a `class-` prefix.
- The namespace should match the directory structure.
- Hooks are prefixed with `woocommerce_`.
- Hooks are named using `snake_case` convention.
For example, the class defined in `src/Util/StringUtil.php` should be named `StringUtil` and should be in the `Automattic\WooCommerce\Util` namespace.
### `/includes`
The `/includes` directory contains legacy code that does not follow the PSR-4 standard. See the [README for `/includes`](../../plugins/woocommerce/includes/README.md) for more information.
The following conventions apply to this directory:
- Class names are prefixed with `WC_`.
- Classes are named using `Upper_Snake_Case` convention.
- Functions are prefixed with `wc_`.
- Functions are named using `snake_case` convention.
- Hooks are prefixed with `woocommerce_`.
- Hooks are named using `snake_case` convention.
Class name examples:
- `WC_Cache_Helper`
- `WC_Cart`
Function name examples:
- `wc_get_product()`
- `wc_is_active_theme()`
Hook name examples (actions or filters):
- `woocommerce_after_checkout_validation`
- `woocommerce_get_formatted_order_total`
## JS
WooCommerce core follows [WordPress JS naming conventions](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/#naming-conventions).
As with PHP, function, class, and hook names should be prefixed, but the convention for JS is slightly different.
- Global class names are prefixed with `WC`. Class names exported from modules are not prefixed.
- Classes are named using `UpperCamelCase` convention.
- Global function names are prefixed with `wc`. Function names exported from modules are not prefixed.
- Functions are named using `camelCase` convention.
- Hooks names are prefixed with `woocommerce`.
- Hooks are named using `camelCase` convention.
Global class name example:
- `WCOrdersTable`
Global function name example:
- `wcSettings()`
Hook name example (actions or filters):
- `woocommerceTracksEventProperties`
## CSS and SASS
See [CSS/Sass Naming Conventions](./css-sass-naming-conventions.md).

View File

@ -0,0 +1,22 @@
# Removing /product/ , /product-category/ , or /shop/ from the URLs
**Note:** This is a **Developer level** doc. If you are unfamiliar with code/templates and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/) for assistance. We are unable to provide support for customizations under our [Support Policy](http://www.woocommerce.com/support-policy/).
## [In sum](https://github.com/woocommerce/woocommerce/blob/trunk/docs/quality-and-best-practices/removing-product-product-category-or-shop-from-the-urls.md#section-1)
Removing `/product/`, `/product-category/`, or `/shop/` from the URLs is not advisable due to the way WordPress resolves its URLs. It uses the `product-category` (or any other text for that matter) base of a URL to detect that it is a URL leading to a product category. There are SEO plugins that allow you to remove this base, but that can lead to a number of problems with performance and duplicate URLs.
## [Better to avoid](https://github.com/woocommerce/woocommerce/blob/trunk/docs/quality-and-best-practices/removing-product-product-category-or-shop-from-the-urls.md#section-2)
You will make it harder for WordPress to detect what page you are trying to reach when you type in a product category URL. Also, understand that the standard “Page” in WordPress always has no base text in the URL. For example:
- `http://yoursite.com/about-page/` (this is the URL of a standard page)
- `http://yoursite.com/product-category/category-x/` (this is the URL leading to a product category)
What would happen if we remove that product-category part?
- `http://yoursite.com/about-page/`
- `http://yoursite.com/category-x/`
WordPress will have to do much more work to detect what page you are looking for when entering one of the above URLs. That is why we do not recommend using any SEO plugin to achieve this.

View File

@ -0,0 +1,138 @@
# Writing high quality testing instructions
## Introduction
Having clear testing Instructions on pull requests is the first level of quality engineering in WooCommerce, which is key for testing early and minimizing the impact of unexpected effects in the upcoming versions of WooCommerce.
This page contains the following sections:
- [What is a test?](#what-is-a-test)
- [What to cover with the testing instructions](#what-to-cover-with-the-testing-instructions)
- [Flow to write good testing instructions](#flow-to-write-good-testing-instructions)
- [Examples](#examples)
## What is a test?
A test is a method that we can use to check that something meets certain criteria. It is typically defined as a procedure which contains the steps required to put the system under test in a certain state before executing the action to be checked. Therefore, a test consists of the following stages:
- **Preconditions:** All the steps that need to be performed to put the system in the desired state before executing the action we want to check. A test could have many preconditions.
- **Action:** This is the exact step that causes the change we want to check in the system. It should be only one because each test should ideally cover one thing at a time.
- **Validation:** Relates to the steps to be performed in order to validate the result of performing the action in the system. A test could validate more than one thing.
For example, in the process of adding an item to the cart:
- The **preconditions** would be all the steps involved in:
- The product creation process.
- Logging as a shopper.
- Heading to the shop page where the products are listed.
- The **action** would be clicking the _"Add to cart"_ button in the desired product.
- The **validation** stage would include checking that the cart icon (if any) shows 1 more item and the product we selected is now included in the cart.
Specifying the preconditions, actions and validations can be quite beneficial when understanding the scope of a test, because:
- The **preconditions** describe what we have to do so that we can execute the test successfully.
- The **action** lets us know the purpose of the test, in other words, it is the key to understanding what we need to test.
- The **validation** stage lets us know what to expect when executing the test.
In this context, we will refer to testing instructions as the tests we need to execute in order to validate that the changes delivered in a pull request or release work as expected. This means the testing instructions could refer to a test or more, involving the happy path and potential edge cases.
## What to cover with the testing instructions
As stated in the previous section, a test (in our context, a testing instruction) is a method to check that a new change or set of changes meets certain criteria.
Therefore, a PR could have testing instructions for multiple scenarios, in fact, it is recommended to include testing instructions for as many scenarios as needed to cover the changes introduced in the PR. In other words, please **add as many testing instructions as needed to cover the acceptance criteria**, understanding acceptance criteria as _the conditions that a software product must satisfy to be accepted by a user, customer or other stakeholders_ or, in the context of a PR, the conditions that this PR must satisfy to be accepted by users, developers and the WooCommerce community as per requirements.
## Flow to write good testing instructions
1. **Outline the user flows** you want to cover.
2. **Define the environment** where the testing instructions should be executed (server, PHP version, WP version, required plugins, etc), and start writing the testing instructions as if you were starting from a fresh install.
3. Identify the **preconditions**, **action** and **validation** steps.
4. Write **as many preconditions as you need** to explain how to set up the state of WooCommerce so that you can execute the desired action to test every flow.
1. Try to be detailed when explaining the interactions the user needs to perform in WooCommerce.
2. If there are several preconditions for a user flow that is explained in a public guide, feel free to simply link the guide in the testing instructions instead of writing several steps. For example, _"Enable dev mode in WooCommerce Payments by following the steps mentioned [here](https://woocommerce.com/document/woocommerce-payments/testing-and-troubleshooting/dev-mode/)"_.
5. Write **the action step**, which should cover the specific action that we want to test as part of this user flow.
6. Write **as many validation steps** as needed in order to assess that the actual result meets expectations.
1. Bear in mind to check only the steps needed to validate that this change works.
### Considerations for writing high-quality testing instructions
- Define the testing instructions in a way that they can be **understood and followed by everybody**, even for people new to WooCommerce.
- Make sure to describe every detail and **avoid assuming knowledge**, the spectrum of readers might be wide and some people would not know the concepts behind what is being assumed. For example, instead of saying _“Enable the [x] experiment”_, say something like:
```text
- Install the WooCommerce Beta Tester plugin.
- Go to `Tools > WCA Test Helper > Experiments`.
- Toggle the [x] experiment.
```
- Always try to explain in detail **where the user should head to**, for example instead of saying “Go to the Orders page as admin”, say “Go to [url]” or even “Go to WooCommerce > Orders”.
- Try to use real test data. For example, instead of saying _"Enter a name for the product"_, say something like _"Enter 'Blue T-Shirt' as the product name"_. This will make it more self-explanatory and remove potential doubts related to assuming knowledge.
- Make sure you **keep your testing instructions updated** if they become obsolete as part of a new commit.
- If the testing instructions require to add custom code, please **provide the code snippet**.
- If the testing instructions require to install a plugin, please **provide a link to this plugin, or the zip file** to install it.
- If the testing instructions require to hit an API endpoint, please provide the **link to the endpoint documentation**.
- Ideally **provide screenshots and/or videos** that supported what the testing instructions are explaining. If you are using links to collaborative tools then also provide an equivalent screenshot/video for those who do not have access.
## Examples
### Good quality testing instructions
#### Example 1
![Sample of good quality instructions](https://woocommerce.files.wordpress.com/2023/10/213682695-3dc51613-b836-4e7e-93ef-f75078ab48ac.png)
#### Example 2
![Another sample of good quality instructions](https://woocommerce.files.wordpress.com/2023/10/213682778-b552ab07-a518-48a7-9358-16adc5762aca.png)
### Improving real testing instructions
In this section, you will see some real examples of testing instructions that have room for improvement (before) and how we can tweak them (after).
Before:
![Instructions needing improvement](https://woocommerce.files.wordpress.com/2023/10/213682262-25bec5c3-154c-45ec-aa3d-d3e07f52669e.png)
After:
![Improved instructions](https://woocommerce.files.wordpress.com/2023/10/213682303-1b12ab97-f27a-41cb-a8db-da8a78d18840.png)
Improvements:
![Changes made](https://woocommerce.files.wordpress.com/2023/10/213682323-0ecc998d-69ab-4201-8daa-820b948315e8.png)
Before:
![Instructions needing improvement](https://woocommerce.files.wordpress.com/2023/10/213682396-8c52d20e-1fca-4ac1-8345-f381c15a102a.png)
After:
![Improved instructions](https://woocommerce.files.wordpress.com/2023/10/213682480-c01e0e84-5969-4456-8f43-70cbb8509e8d.png)
Improvements:
![Changes made](https://woocommerce.files.wordpress.com/2023/10/213682597-8d06e638-35dd-4ff8-9236-63c6ec5d05b8.jpg)
Before:
![Screenshot 2023-02-02 at 16 07 29](https://woocommerce.files.wordpress.com/2023/10/216365611-b540a814-3b8f-40f3-ae64-81018b9f97fb.png)
After:
![Screenshot 2023-02-02 at 16 22 31](https://woocommerce.files.wordpress.com/2023/10/216366043-967e5daa-6a23-4ab8-adda-5f3082d1ebf7.png)
Improvements:
![Screenshot 2023-02-02 at 16 09 24](https://woocommerce.files.wordpress.com/2023/10/216366152-b331648d-bcef-443b-b126-de2621a20862.png)
Before:
![Screenshot 2023-02-02 at 17 25 07](https://woocommerce.files.wordpress.com/2023/10/216388785-8806ea74-62e6-42da-8887-c8e291e7dfe2-1.png)
After:
![Screenshot 2023-02-02 at 17 49 22](https://woocommerce.files.wordpress.com/2023/10/216388842-e5ab433e-d288-4306-862f-72f6f81ab2cd.png)
Improvements:
![Screenshot 2023-02-02 at 17 39 23](https://woocommerce.files.wordpress.com/2023/10/216388874-c5b21fc3-f693-4a7e-a58a-c5d1b6606682.png)

View File

@ -52,6 +52,56 @@ How-to guides are focused and specific, providing instructions on how to accompl
>
> [Divio Framework on How-to-Guide Writing](https://documentation.divio.com/how-to-guides/)
## Custom Linting Rules
At WooCommerce, we're dedicated to maintaining a consistent and high-quality standard for our technical documentation. Our documents primarily adhere to the linting rules provided by `markdownlint`. To assist our contributors, we've detailed our custom configurations and exceptions below.
Note: While we've outlined specific rules above, all other default linting rules from `markdownlint` apply unless otherwise stated. We've only highlighted custom configurations or exceptions here. For a complete list of `markdownlint` rules, you can refer to [this link](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md).
1. **Headings Style**:
- Use the ATX-style (`#`) for headers.
```markdown
# This is an H1
## This is an H2
```
[Reference: MD003](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md#md003---heading-style)
2. **List Indentation**:
- Indent list items with 4 spaces.
```markdown
- Item 1
- Subitem 1.1
```
[Reference: MD007]([https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md)#md007---unordered-list-indentation)
3. **Line Length**:
- No specific restriction on the line length, but keep paragraphs and sentences readable.
[Reference: MD013](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md013---line-length)
4. **Multiple Headings with the Same Content**:
- Multiple headings with the same content are permissible as long as they are not siblings.
[Reference: MD024](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md#md024---no-multiple-headings-with-the-same-content)
5. **Inline HTML**:
- Only the `video` element is allowed when using inline HTML.
```markdown
<video src="path_to_video.mp4" controls></video>
```
[Reference: MD033](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md#md033---inline-html)
6. **Tabs and Whitespace**:
- We're flexible with the use of hard tabs and trailing whitespace. However, for consistency, we recommend using spaces over tabs and avoiding trailing whitespaces.
[Reference: no-hard-tabs & whitespace](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md)
## Formatting
### Visual style

View File

@ -1,3 +1,5 @@
# Adding actions and filters
Like many WordPress plugins, WooCommerce provides a range of actions and filters through which developers can extend and modify the platform.
Often, when writing new code or revising existing code, there is a desire to add new hooks—but this should always be done with thoughtfulness and care. This document aims to provide high-level guidance on the matter.

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

141
docs/utilities/logging.md Normal file
View File

@ -0,0 +1,141 @@
# Logging in WooCommerce
WooCommerce has its own robust system for logging, which can be used for debugging during development, catching errors on production, or even sending notifications when specific events occur. By default, WooCommerce uses this logger to record errors, warnings, and other notices that may be useful for troubleshooting problems with a store. Many extensions for WooCommerce also make use of the logger for similar purposes.
## Viewing logs
Depending on the log handler(s) used, you can view the entries created by the logger by going to **WooCommerce > Status > Logs**.
![Log file viewer](_media/log-critical.jpg)
## Log levels
Logs have eight different severity levels:
* `emergency`
* `alert`
* `critical`
* `error`
* `warning`
* `notice`
* `info`
* `debug`
Aside from giving a site owner context as to how important a log entry is, these levels also allow logs to be filtered by the handler. If you only want log entries to be recorded for `error` severity and higher, you can set the threshold in the `WC_LOG_THRESHOLD` constant by adding something like this to your `wp-config.php` file:
```php
define( 'WC_LOG_THRESHOLD', 'error' );
```
Note that this threshold will apply to all logs, regardless of which log handler is in use. The `WC_Log_Handler_Email` class, for example, has its own threshold setting, but it is secondary to the global threshold.
## Log handlers
In WooCommerce, a log handler is a PHP class that takes the raw log data and transforms it into a log entry that can be stored or dispatched. WooCommerce ships with three different log handler classes:
* `WC_Log_Handler_File`: The default handler. Records log entries to files. The files are stored in `wp-content/uploads/wc-logs`, but this can be changed by defining the `WC_LOG_DIR` constant in your `wp-config.php` file with a custom path. Log files can be up to 5 MB in size, after which the log file will rotate.
* `WC_Log_Handler_DB`: Records log entries to the database. Entries are stored in the `{$wpdb->prefix}woocommerce_log` table.
* `WC_Log_Handler_Email`: Sends log entries as email messages. Emails are sent to the site admin email address. This handler has [some limitations](https://github.com/woocommerce/woocommerce/blob/fe81a4cf27601473ad5c394a4f0124c785aaa4e6/plugins/woocommerce/includes/log-handlers/class-wc-log-handler-email.php#L15-L27).
### Changing or adding handlers
To switch from the default file log handler to the database handler, you can add an entry like this to your `wp-config.php` file:
```php
define( 'WC_LOG_HANDLER', 'WC_Log_Handler_DB' );
```
In some cases, you may want to have more than one log handler, and/or you might want to modify the settings of a handler. For example, you may want to have most logs saved to files, but log entries that are classified as emergency or critical errors also sent to an email address. For this, you can use the `woocommerce_register_log_handlers` filter hook to create an array of log handler class instances that you want to use. Some handler class constructors have optional parameters that you can use when instantiating the class to change their default behavior.
Example:
```php
function my_wc_log_handlers( $handlers ) {
$size_limit = 10 * 1024 * 1024; // Make the file size limit 10 MB instead of 5.
$handlers[] = new WC_Log_Handler_File( $size_limit );
$recipients = array( 'wayne@example.com', 'garth@example.com' ); // Send logs to multiple recipients.
$threshold = 'critical'; // Only send emails for logs of this level and higher.
$handlers[] = new WC_Log_Handler_Email( $recipients, $threshold );
return $handlers;
}
add_filter( 'woocommerce_register_log_handlers', 'my_wc_log_handlers' );
```
### Creating a custom handler
You may want to create your own log handler class in order to send logs somewhere else, such as a Slack channel or perhaps an InfluxDB instance. Your class must extend the [`WC_Log_Handler`](https://woocommerce.github.io/code-reference/classes/WC-Log-Handler.html) abstract class and implement the [`WC_Log_Handler_Interface`](https://woocommerce.github.io/code-reference/classes/WC-Log-Handler-Interface.html) interface. The [`WC_Log_Handler_Email`](https://github.com/woocommerce/woocommerce/blob/6688c60fe47ad42d49deedab8be971288e4786c1/plugins/woocommerce/includes/log-handlers/class-wc-log-handler-email.php) handler class provides a good example of how to set it up.
## Adding logs
Logs are added via methods in the `WC_Logger` class. The class instance is accessed by using the `wc_get_logger()` function. The basic method for adding a log entry is [`WC_Logger::log( $level, $message, $context )`](https://woocommerce.github.io/code-reference/classes/WC-Logger.html#method_log). There are also shortcut methods for each log severity level, for example `WC_Logger::warning( $message, $context )`. Here is [an example](https://github.com/woocommerce/woocommerce/blob/6688c60fe47ad42d49deedab8be971288e4786c1/plugins/woocommerce/src/Admin/RemoteInboxNotifications/OptionRuleProcessor.php#L53-L64) from the codebase:
```php
$logger = wc_get_logger();
$logger->warning(
sprintf(
'ComparisonOperation "%s" option value "%s" is not an array, defaulting to empty array.',
$rule->operation,
$rule->option_name
),
array(
'option_value' => $option_value,
'rule' => $rule,
)
);
```
## Log sources
Each log entry can include a `source` value, which is intended to provide context about where in the codebase the log was generated, and can be used to filter log entries. A source value can be added to a log by including it in the `context` parameter like so:
```php
$logger->info( 'Time for lunch', array( 'source' => 'your_stomach' ) );
```
Each log handler uses the source information a bit differently.
* `WC_Log_Handler_File`: The source becomes the prefix of the log filename. Thus, log entries with different sources will be stored in different log files. If no source value is given, the handler defaults to `log` as the source.
* `WC_Log_Handler_DB`: The source value is stored in the `source` column in the log database table. When viewing the list table of logs, you can choose a source value from a dropdown as a filter, and only view logs with that source. If no source value is given, the handler uses a stacktrace to determine the name of the file where the log was triggered, and that filename becomes the source.
* `WC_Log_Handler_Email`: This log handler does not use source information.
## Clearing old logs
When WooCommerce is first installed, it sets up a scheduled event to delete logs older than 30 days that runs daily. You can change the log retention period using the `woocommerce_logger_days_to_retain_logs` filter hook:
```php
add_filter( 'woocommerce_logger_days_to_retain_logs', function() { return 90; } );
```
## Turning off noisy logs
If there is a particular log that is recurring frequently and clogging up your log files, you should probably figure out why it keeps getting triggered and resolve the issue. However, if that's not possible, you can add a filter to ignore that particular log while still allowing other logs to get through:
```php
function my_ignored_logs( $message, $level, $context, $handler ) {
if ( false !== strpos( $message, 'Look, a squirrel!' ) ) {
return null;
}
return $message;
}
add_filter( 'woocommerce_logger_log_message', 'my_ignored_logs', 10, 4 );
```
## Debugging with the logger
Sometimes during debugging you need to find out if the runtime reaches a certain line in the code, or you need to see what value a variable contains, and it's not possible to directly observe what's happening with a `var_dump` call or a breakpoint. In these cases you can log the information you need with a one-liner like this:
```php
wc_get_logger()->debug( 'Made it to the conditional!', array( 'source', 'debug-20230825' ) );
```
On the occasion where you need to know what a non-scalar variable (array, object) contains, you may be tempted to put it in the `$context` parameter alongside your `source` value. However, only the database log handler even stores the contents of `$context`, and none of the handlers display it anywhere. Instead, consider outputting it in the `$message` parameter using something like [`wc_print_r`](https://woocommerce.github.io/code-reference/namespaces/default.html#function_wc_print_r):
```php
wc_get_logger()->debug(
wc_print_r( $my_special_array ),
array( 'source', 'debug-20230825' )
);
```

View File

@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: Applied lint auto fixes across monorepo

View File

@ -14,7 +14,7 @@ export const WC_HEADER_SLOT_NAME = 'woocommerce_header_item';
/**
* Get the slot fill name for the generic header slot or a specific header if provided.
*
* @param name Name of the specific header.
* @param name Name of the specific header.
* @return string
*/
const getSlotFillName = ( name?: string ) => {

View File

@ -0,0 +1,4 @@
Significance: minor
Type: dev
Allow jest to pass with no tests

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: This is just a change to developer commands.

View File

@ -73,12 +73,13 @@
},
"scripts": {
"turbo:build": "pnpm run build:js && pnpm run build:css",
"turbo:test": "jest --config ./jest.config.json",
"turbo:test": "jest --config ./jest.config.json --passWithNoTests",
"prepare": "composer install",
"changelog": "composer exec -- changelogger",
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
"test": "pnpm test:js",
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name --",
"lint": "eslint --output-file eslint_report.json --format json src",
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
"build:css": "webpack",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: This is just a change to developer commands.

View File

@ -32,7 +32,8 @@
"scripts": {
"turbo:build": "pnpm run clean && npm run compile",
"turbo:test": "jest",
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
"test": "pnpm test:js",
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
"prepare": "composer install",
"changelog": "composer exec -- changelogger",
"clean": "rm -rf ./dist ./tsconfig.tsbuildinfo",

View File

@ -0,0 +1,12 @@
module.exports = {
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
root: true,
overrides: [
{
files: [ '**/*.js', '**/*.jsx', '**/*.tsx' ],
rules: {
'react/react-in-jsx-scope': 'off',
},
},
],
};

View File

@ -0,0 +1 @@
package-lock=false

View File

@ -0,0 +1,70 @@
# @woocommerce/block-templates
A collection of utility functions for use with WooCommerce admin block templates.
## API
### registerWooBlockType
Registers a WooCommerce block type.
#### Usage
```js
import { registerWooBlockType } from '@woocommerce/block-templates';
import metadata from './block.json';
import { Edit } from './edit';
registerWooBlockType( {
name: metadata.name,
metadata: metadata,
settings: {
edit: Edit,
}
} );
```
#### Parameters
- _blockMetadata_ `Object`: Block metadata.
#### Returns
- `WPBlockType | undefined`: The block type if it was registered successfully, otherwise `undefined`.
### useWooBlockProps
This hook is used to lightly mark an element as a WooCommerce block template block. The block's attributes must be passed to this hook and the return result passed to the outermost element of the block in order for the block to properly function in WooCommerce block template contexts.
If you define a ref for the element, it is important to pass the ref to this hook, which the hook in turn will pass to the component through the props it returns. Optionally, you can also pass any other props through this hook, and they will be merged and returned.
#### Usage
```js
import { useWooBlockProps } from '@woocommerce/block-templates';
export function Edit( { attributes } ) {
const { blockProps } = useWooBlockProps(
attributes,
{
className: 'my-block',
}
);
return (
<div { ...blockProps }>
Block content
</div>
);
}
```
#### Parameters
- _attributes_: `Object`: Block attributes.
- _props_: `Object`: Optional. Props to pass to the element.
#### Returns
- `Object`: Props to pass to the element to mark as a WooCommerce block.

View File

@ -0,0 +1,3 @@
module.exports = {
extends: '../internal-js-tests/babel.config.js',
};

View File

@ -0,0 +1,3 @@
# Changelog
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Initial version of @woocommerce/block-templates package. Adds registerWooBlockType and useWooBlockProps.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: This is just a change to developer commands.

View File

@ -0,0 +1,32 @@
{
"name": "woocommerce/block-templates",
"description": "WooCommerce Admin block templates component library",
"type": "library",
"license": "GPL-3.0-or-later",
"minimum-stability": "dev",
"require-dev": {
"automattic/jetpack-changelogger": "3.3.0"
},
"config": {
"platform": {
"php": "7.2"
}
},
"extra": {
"changelogger": {
"formatter": {
"filename": "../../../tools/changelogger/class-package-formatter.php"
},
"types": {
"fix": "Fixes an existing bug",
"add": "Adds functionality",
"update": "Update existing functionality",
"dev": "Development related task",
"tweak": "A minor adjustment to the codebase",
"performance": "Address performance issues",
"enhancement": "Improve existing functionality"
},
"changelog": "CHANGELOG.md"
}
}
}

483
packages/js/block-templates/composer.lock generated Normal file
View File

@ -0,0 +1,483 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2d316cec186ab12385e8dda54f6df0f6",
"packages": [],
"packages-dev": [
{
"name": "automattic/jetpack-changelogger",
"version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/Automattic/jetpack-changelogger.git",
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Automattic/jetpack-changelogger/zipball/8f63c829b8d1b0d7b1d5de93510d78523ed18959",
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959",
"shasum": ""
},
"require": {
"php": ">=5.6",
"symfony/console": "^3.4 || ^5.2 || ^6.0",
"symfony/process": "^3.4 || ^5.2 || ^6.0",
"wikimedia/at-ease": "^1.2 || ^2.0"
},
"require-dev": {
"wikimedia/testing-access-wrapper": "^1.0 || ^2.0",
"yoast/phpunit-polyfills": "1.0.4"
},
"bin": [
"bin/changelogger"
],
"type": "project",
"extra": {
"autotagger": true,
"branch-alias": {
"dev-trunk": "3.3.x-dev"
},
"mirror-repo": "Automattic/jetpack-changelogger",
"version-constants": {
"::VERSION": "src/Application.php"
},
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-changelogger/compare/${old}...${new}"
}
},
"autoload": {
"psr-4": {
"Automattic\\Jetpack\\Changelog\\": "lib",
"Automattic\\Jetpack\\Changelogger\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0-or-later"
],
"description": "Jetpack Changelogger tool. Allows for managing changelogs by dropping change files into a changelog directory with each PR.",
"support": {
"source": "https://github.com/Automattic/jetpack-changelogger/tree/v3.3.0"
},
"time": "2022-12-26T13:49:01+00:00"
},
{
"name": "psr/log",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/1.1.4"
},
"time": "2021-05-03T11:20:27+00:00"
},
{
"name": "symfony/console",
"version": "3.4.x-dev",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81",
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81",
"shasum": ""
},
"require": {
"php": "^5.5.9|>=7.0.8",
"symfony/debug": "~2.8|~3.0|~4.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/dependency-injection": "<3.4",
"symfony/process": "<3.3"
},
"provide": {
"psr/log-implementation": "1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.3|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
"symfony/lock": "~3.4|~4.0",
"symfony/process": "~3.3|~4.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/console/tree/3.4"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-10-24T10:57:07+00:00"
},
{
"name": "symfony/debug",
"version": "4.4.x-dev",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "1a692492190773c5310bc7877cb590c04c2f05be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/1a692492190773c5310bc7877cb590c04c2f05be",
"reference": "1a692492190773c5310bc7877cb590c04c2f05be",
"shasum": ""
},
"require": {
"php": ">=7.1.3",
"psr/log": "^1|^2|^3"
},
"conflict": {
"symfony/http-kernel": "<3.4"
},
"require-dev": {
"symfony/http-kernel": "^3.4|^4.0|^5.0"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides tools to ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/debug/tree/v4.4.44"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"abandoned": "symfony/error-handler",
"time": "2022-07-28T16:29:46+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "1.x-dev",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-07-28T09:04:16+00:00"
},
{
"name": "symfony/process",
"version": "3.4.x-dev",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca",
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca",
"shasum": ""
},
"require": {
"php": "^5.5.9|>=7.0.8"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/3.4"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-10-24T10:57:07+00:00"
},
{
"name": "wikimedia/at-ease",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/wikimedia/at-ease.git",
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/wikimedia/at-ease/zipball/013ac61929797839c80a111a3f1a4710d8248e7a",
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a",
"shasum": ""
},
"require": {
"php": ">=5.6.99"
},
"require-dev": {
"jakub-onderka/php-console-highlighter": "0.3.2",
"jakub-onderka/php-parallel-lint": "1.0.0",
"mediawiki/mediawiki-codesniffer": "22.0.0",
"mediawiki/minus-x": "0.3.1",
"ockcyp/covers-validator": "0.5.1 || 0.6.1",
"phpunit/phpunit": "4.8.36 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/Wikimedia/Functions.php"
],
"psr-4": {
"Wikimedia\\AtEase\\": "src/Wikimedia/AtEase/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0-or-later"
],
"authors": [
{
"name": "Tim Starling",
"email": "tstarling@wikimedia.org"
},
{
"name": "MediaWiki developers",
"email": "wikitech-l@lists.wikimedia.org"
}
],
"description": "Safe replacement to @ for suppressing warnings.",
"homepage": "https://www.mediawiki.org/wiki/at-ease",
"support": {
"source": "https://github.com/wikimedia/at-ease/tree/master"
},
"time": "2018-10-10T15:39:06+00:00"
}
],
"aliases": [],
"minimum-stability": "dev",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"platform-overrides": {
"php": "7.2"
},
"plugin-api-version": "2.6.0"
}

View File

@ -0,0 +1,4 @@
{
"rootDir": "./src",
"preset": "../node_modules/@woocommerce/internal-js-tests/jest-preset.js"
}

View File

@ -0,0 +1,77 @@
{
"name": "@woocommerce/block-templates",
"version": "1.0.0-beta.0",
"description": "Utilities for working with block templates in WooCommerce admin.",
"author": "Automattic",
"license": "GPL-2.0-or-later",
"keywords": [
"wordpress",
"woocommerce"
],
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/packages/js/block-templates/README.md",
"repository": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce.git"
},
"bugs": {
"url": "https://github.com/woocommerce/woocommerce/issues"
},
"main": "build/index.js",
"module": "build-module/index.js",
"types": "build-types",
"react-native": "src/index",
"sideEffects": [
"build-style/**",
"src/**/*.scss"
],
"publishConfig": {
"access": "public"
},
"dependencies": {
"@wordpress/block-editor": "^9.8.0",
"@wordpress/blocks": "^12.3.0"
},
"devDependencies": {
"@babel/core": "^7.21.3",
"@babel/runtime": "^7.17.2",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react-hooks": "^8.0.1",
"@types/jest": "^27.4.1",
"@types/testing-library__jest-dom": "^5.14.3",
"@types/wordpress__block-editor": "^7.0.0",
"@types/wordpress__blocks": "^11.0.7",
"@woocommerce/eslint-plugin": "workspace:*",
"@woocommerce/internal-js-tests": "workspace:*",
"@woocommerce/internal-style-build": "workspace:*",
"@wordpress/browserslist-config": "wp-6.0",
"copy-webpack-plugin": "^9.1.0",
"css-loader": "^3.6.0",
"eslint": "^8.32.0",
"jest": "^27.5.1",
"jest-cli": "^27.5.1",
"postcss": "^8.4.7",
"postcss-loader": "^4.3.0",
"rimraf": "^3.0.2",
"sass-loader": "^10.2.1",
"ts-jest": "^27.1.3",
"typescript": "^5.1.6",
"webpack": "^5.70.0",
"webpack-cli": "^3.3.12"
},
"scripts": {
"turbo:build": "pnpm run build:js && pnpm run build:css",
"turbo:test": "jest --config ./jest.config.json",
"prepare": "composer install",
"changelog": "composer exec -- changelogger",
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
"test": "pnpm test:js",
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
"lint": "eslint --output-file eslint_report.json --format json src",
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
"build:css": "webpack",
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\" \"webpack --watch\"",
"prepack": "pnpm run clean && pnpm run build",
"lint:fix": "eslint src --fix"
}
}

View File

@ -0,0 +1 @@
export * from './use-woo-block-props';

View File

@ -0,0 +1 @@
export * from './use-woo-block-props';

View File

@ -0,0 +1,37 @@
/**
* External dependencies
*/
import { renderHook } from '@testing-library/react-hooks';
import { useBlockProps } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import { useWooBlockProps } from '../use-woo-block-props';
jest.mock( '@wordpress/block-editor', () => ( {
useBlockProps: jest.fn(),
} ) );
describe( 'useWooBlockProps', () => {
it( 'should return the block props with the block id and block order attributes', () => {
renderHook( () =>
useWooBlockProps(
{
foo: 'bar',
_templateBlockId: 'test/block',
_templateBlockOrder: 30,
},
{
className: 'test',
}
)
);
expect( useBlockProps ).toHaveBeenCalledWith( {
'data-template-block-id': 'test/block',
'data-template-block-order': 30,
className: 'test',
} );
} );
} );

View File

@ -0,0 +1,24 @@
/**
* External dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';
interface TemplateBlockAttributes {
_templateBlockId?: string;
_templateBlockOrder?: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[ key: string ]: any;
}
export const useWooBlockProps = (
attributes: TemplateBlockAttributes,
props: Record< string, unknown > = {}
) => {
const additionalProps = {
'data-template-block-id': attributes._templateBlockId,
'data-template-block-order': attributes._templateBlockOrder,
...props,
};
return useBlockProps( additionalProps );
};

View File

@ -0,0 +1,2 @@
export * from './hooks';
export * from './utils';

View File

@ -0,0 +1 @@
export * from './register-woo-block-type';

View File

@ -0,0 +1,51 @@
/**
* External dependencies
*/
import {
Block,
BlockConfiguration,
registerBlockType,
} from '@wordpress/blocks';
interface BlockRepresentation< T extends Record< string, object > > {
name?: string;
metadata: BlockConfiguration< T >;
settings: Partial< BlockConfiguration< T > >;
}
/**
* Function to register an individual block.
*
* @param block The block to be registered.
* @return The block, if it has been successfully registered; otherwise `undefined`.
*/
export function registerWooBlockType<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends Record< string, any > = Record< string, any >
>( block: BlockRepresentation< T > ): Block< T > | undefined {
if ( ! block ) {
return;
}
const { metadata, settings, name } = block;
const templateBlockAttributes = {
_templateBlockId: {
type: 'string',
__experimentalRole: 'content',
},
_templateBlockOrder: {
type: 'integer',
__experimentalRole: 'content',
},
};
const augmentedMetadata = {
...metadata,
attributes: {
...metadata.attributes,
...templateBlockAttributes,
},
};
return registerBlockType< T >( { name, ...augmentedMetadata }, settings );
}

View File

@ -0,0 +1,59 @@
/**
* External dependencies
*/
import { registerBlockType } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { registerWooBlockType } from '../register-woo-block-type';
jest.mock( '@wordpress/blocks', () => ( {
registerBlockType: jest.fn(),
} ) );
describe( 'registerWooBlockType', () => {
it( 'should register a block type with the block id and block order attributes', () => {
const block = {
name: 'test/block',
metadata: {
attributes: {
foo: {
type: 'boolean',
default: false,
},
},
},
settings: {
foo: 'bar',
},
};
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ts2345 Complaining about the type of the foo attribute; it's fine.
registerWooBlockType( block );
expect( registerBlockType ).toHaveBeenCalledWith(
{
name: 'test/block',
attributes: {
foo: {
type: 'boolean',
default: false,
},
_templateBlockId: {
type: 'string',
__experimentalRole: 'content',
},
_templateBlockOrder: {
type: 'integer',
__experimentalRole: 'content',
},
},
},
{
foo: 'bar',
}
);
} );
} );

View File

@ -0,0 +1,16 @@
{
"extends": "../tsconfig-cjs",
"include": [
"**/*.d.ts",
"src/**/*",
"src/**/*.json"
],
"compilerOptions": {
"outDir": "build",
"resolveJsonModule": true,
"typeRoots": [
"./typings",
"./node_modules/@types"
]
}
}

View File

@ -0,0 +1,20 @@
{
"extends": "../tsconfig",
"compilerOptions": {
"rootDir": "src",
"outDir": "build-module",
"declaration": true,
"declarationMap": true,
"declarationDir": "./build-types",
"resolveJsonModule": true,
"typeRoots": [
"./typings",
"./node_modules/@types"
]
},
"include": [
"**/*.d.ts",
"src/**/*",
"src/**/*.json"
]
}

View File

@ -0,0 +1,19 @@
/**
* Internal dependencies
*/
const { webpackConfig } = require( '@woocommerce/internal-style-build' );
module.exports = {
mode: process.env.NODE_ENV || 'development',
entry: {
'build-style': __dirname + '/src/style.scss',
},
output: {
path: __dirname,
},
module: {
parser: webpackConfig.parser,
rules: webpackConfig.rules,
},
plugins: webpackConfig.plugins,
};

View File

@ -2,6 +2,35 @@
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [12.2.0](https://www.npmjs.com/package/@woocommerce/components/v/12.2.0) - 2023-10-17
- Patch - Add class back in for increase specificity of css for dropdown button. [#40494]
- Minor - Categories dropdown display error #39810 [#39811]
- Patch - Fixed empty component logo color, used generic rather than old pink [#39182]
- Patch - Fix invalid focus state of the experimental select control [#40519]
- Minor - Fix new category name field [#39857]
- Patch - Fix select control dropdown menu double scroll and width [#39989]
- Minor - Select attribute after pressing their names #39456 [#39574]
- Patch - TreeSelectControl Component - Make sure individuallySelectParent prop is respected [#40301]
- Minor - Add AI wizard business info step for Customize Your Store task [#39979]
- Minor - Add customize store assembler hub onboarding tour [#39981]
- Minor - Add ProgressBar component [#39979]
- Minor - Add tags (or general taxonomy ) block [#39966]
- Minor - Add Tooltip to each list item when need it [#39770]
- Minor - An international phone number input with country selection, and mobile phone numbers validation. [#40335]
- Minor - Image gallery and media uploader now support initial selected images. [#40633]
- Minor - Refactor Pagination component and split out into multiple re-usable components. Also added a `usePagination` hook. [#39967]
- Minor - Set button optional in MediaUploader component [#40526]
- Minor - Update ImageGallery block toolbar, moving some options to an ellipsis dropdown menu. [#39753]
- Minor - Allow users to select multiple items from the media library while adding images #39741 [#39741]
- Patch - Make eslint emit JSON report for annotating PRs. [#39704]
- Minor - Update pnpm to 8.6.7 [#39245]
- Patch - Upgraded Storybook to 6.5.17-alpha.0 for TypeScript 5 compatibility [#39745]
- Minor - Upgrade TypeScript to 5.1.6 [#39531]
- Patch - Add z-index=1 to tour-kit close btn to ensure it's clickable [#40456]
- Minor - Remove unnecessary use of woocommerce-page selector for DropdownButton styling. [#40218]
- Patch - Small condition change in the date time picker to avoid edge case where inputControl is null. [#40642]
## [12.1.0](https://www.npmjs.com/package/@woocommerce/components/v/12.1.0) - 2023-07-13
- Patch - Altering styles to correctly target fields within slot fills on product editor. [#36500]
@ -157,7 +186,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Minor - Fix DateTimePickerControl's onChange date arg to only be a string (TypeScript). [#35140]
- Minor - Improve experimental SelectControl accessibility [#35140]
- Minor - Improve Sortable component acessibility [#35140]
- - Create new experimental SelectControl component [#35140]
- Major - Create new experimental SelectControl component [#35140]
## [10.3.0](https://www.npmjs.com/package/@woocommerce/components/v/10.3.0) - 2022-08-12

View File

@ -10,8 +10,6 @@ Install the module
pnpm install @woocommerce/components --save
```
View [the full Component documentation](https://woocommerce.github.io/woocommerce-admin/#/components/) for usage information.
## Usage
```jsx

View File

@ -1,4 +0,0 @@
Significance: minor
Type: add
Add Tooltip to each list item when need it

View File

@ -1,4 +0,0 @@
Significance: minor
Type: dev
Allow users to select multiple items from the media library while adding images #39741

View File

@ -1,4 +0,0 @@
Significance: patch
Type: dev
Make eslint emit JSON report for annotating PRs.

View File

@ -1,4 +0,0 @@
Significance: minor
Type: dev
Update pnpm to 8.6.7

View File

@ -1,4 +0,0 @@
Significance: patch
Type: dev
Upgraded Storybook to 6.5.17-alpha.0 for TypeScript 5 compatibility

View File

@ -1,4 +0,0 @@
Significance: minor
Type: dev
Upgrade TypeScript to 5.1.6

View File

@ -1,4 +0,0 @@
Significance: minor
Type: update
Update ImageGallery block toolbar, moving some options to an ellipsis dropdown menu.

View File

@ -1,4 +0,0 @@
Significance: minor
Type: fix
Select attribute after pressing their names #39456

View File

@ -1,4 +0,0 @@
Significance: minor
Type: fix
Categories dropdown display error #39810

Some files were not shown because too many files have changed in this diff Show More