Merge pull request #32121 from woocommerce/merge/woocommerce-admin
Merge WooCommerce Admin This merges WooCommerce Admin, along with its commit history, into `plugins/woocommerce-admin`.
This commit is contained in:
commit
9479568e3d
|
@ -0,0 +1 @@
|
||||||
|
extends @wordpress/browserslist-config
|
|
@ -0,0 +1,34 @@
|
||||||
|
# A set of files you probably don't want in your WordPress.org distribution
|
||||||
|
.distignore
|
||||||
|
.editorconfig
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.gitlab-ci.yml
|
||||||
|
.travis.yml
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
behat.yml
|
||||||
|
bin
|
||||||
|
circle.yml
|
||||||
|
composer.json
|
||||||
|
composer.lock
|
||||||
|
Gruntfile.js
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
||||||
|
phpunit.xml
|
||||||
|
phpunit.xml.dist
|
||||||
|
multisite.xml
|
||||||
|
multisite.xml.dist
|
||||||
|
phpcs.xml
|
||||||
|
phpcs.xml.dist
|
||||||
|
README.md
|
||||||
|
wp-cli.local.yml
|
||||||
|
yarn.lock
|
||||||
|
tests
|
||||||
|
packages/admin-e2e-tests
|
||||||
|
vendor
|
||||||
|
config
|
||||||
|
node_modules
|
||||||
|
*.sql
|
||||||
|
*.tar.gz
|
||||||
|
*.zip
|
|
@ -0,0 +1,24 @@
|
||||||
|
# This file is for unifying the coding style for different editors and IDEs
|
||||||
|
# editorconfig.org
|
||||||
|
|
||||||
|
# WordPress Coding Standards
|
||||||
|
# https://make.wordpress.org/core/handbook/coding-standards/
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
|
indent_style = tab
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{md,json,yml}]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = tab
|
|
@ -0,0 +1,12 @@
|
||||||
|
bin/*
|
||||||
|
!bin/generate-docs
|
||||||
|
!.eslintrc.js
|
||||||
|
build
|
||||||
|
build-module
|
||||||
|
coverage
|
||||||
|
languages
|
||||||
|
node_modules
|
||||||
|
vendor
|
||||||
|
legacy
|
||||||
|
tests/e2e
|
||||||
|
build-types
|
|
@ -0,0 +1,80 @@
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
'jest/globals': true,
|
||||||
|
},
|
||||||
|
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||||
|
settings: {
|
||||||
|
'import/resolver': 'typescript',
|
||||||
|
// List of modules that are externals in our webpack config.
|
||||||
|
'import/core-modules': [ '@woocommerce/settings', 'lodash', 'react' ],
|
||||||
|
react: {
|
||||||
|
pragma: 'createElement',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
root: true,
|
||||||
|
rules: {
|
||||||
|
// temporary conversion to warnings until the below are all handled.
|
||||||
|
'@wordpress/i18n-translator-comments': 'warn',
|
||||||
|
'@wordpress/valid-sprintf': 'warn',
|
||||||
|
'jsdoc/check-tag-names': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
definedTags: [
|
||||||
|
'jest-environment',
|
||||||
|
'filter',
|
||||||
|
'action',
|
||||||
|
'slotFill',
|
||||||
|
'scope',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/no-extraneous-dependencies': 'warn',
|
||||||
|
'import/no-unresolved': 'warn',
|
||||||
|
'jest/no-deprecated-functions': 'warn',
|
||||||
|
'@wordpress/no-unsafe-wp-apis': 'warn',
|
||||||
|
'jest/valid-title': 'warn',
|
||||||
|
'@wordpress/no-global-active-element': 'warn',
|
||||||
|
'no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
varsIgnorePattern: 'createElement',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react/react-in-jsx-scope': 'error',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [ '*.ts', '*.tsx' ],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
extends: [
|
||||||
|
'plugin:@woocommerce/eslint-plugin/recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
camelcase: 'off',
|
||||||
|
'import/no-unresolved': 'warn',
|
||||||
|
'import/no-extraneous-dependencies': 'warn',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'error',
|
||||||
|
'no-use-before-define': 'off',
|
||||||
|
'@typescript-eslint/no-use-before-define': [ 'error' ],
|
||||||
|
'jsdoc/require-param': 'off',
|
||||||
|
// Making use of typescript no-shadow instead, fixes issues with enum.
|
||||||
|
'no-shadow': 'off',
|
||||||
|
'@typescript-eslint/no-shadow': [ 'error' ],
|
||||||
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'client/**/*.js',
|
||||||
|
'client/**/*.jsx',
|
||||||
|
'**/stories/*.js',
|
||||||
|
'**/stories/*.jsx',
|
||||||
|
'**/docs/example.js',
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'react/react-in-jsx-scope': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Line-ending normalization
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
/.* export-ignore
|
||||||
|
/*.md export-ignore
|
||||||
|
/node_modules* export-ignore
|
||||||
|
/tests export-ignore
|
||||||
|
/bin export-ignore
|
||||||
|
/phpcs.* export-ignore
|
||||||
|
/phpunit.* export-ignore
|
||||||
|
/composer.lock export-ignore
|
||||||
|
/composer.json export-ignore
|
||||||
|
/renovate.json export-ignore
|
||||||
|
/webpack.config.js export-ignore
|
||||||
|
/postcss.config.js export-ignore
|
||||||
|
/package.json export-ignore
|
||||||
|
/package-lock.json export-ignore
|
||||||
|
/babel.config.js export-ignore
|
||||||
|
/Gruntfile.js export-ignore
|
||||||
|
/packages* export-ignore
|
||||||
|
/docs* export-ignore
|
||||||
|
/config* export-ignore
|
||||||
|
/client* export-ignore
|
||||||
|
/docker* export-ignore
|
||||||
|
/storybook* export-ignore
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Describe the bug
|
||||||
|
<!-- A clear and concise description of what the bug is. Please be as descriptive as possible. -->
|
||||||
|
|
||||||
|
### To Reproduce
|
||||||
|
<!-- Describe the steps to reproduce the behavior.-->
|
||||||
|
|
||||||
|
1. Go to '…'
|
||||||
|
2. Click on '…'
|
||||||
|
3. Scroll down to …'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
### Actual behavior:
|
||||||
|
<!-- A clear and concise description of what actually happens. -->
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||||
|
|
||||||
|
### Expected behavior
|
||||||
|
<!-- A clear and concise description of what you expected to happen. -->
|
||||||
|
|
||||||
|
### Desktop (please complete the following information):
|
||||||
|
|
||||||
|
* OS: [e.g. iOS]
|
||||||
|
* Browser [e.g. chrome, safari]
|
||||||
|
* Version [e.g. 22]
|
||||||
|
|
||||||
|
### Smartphone (please complete the following information):
|
||||||
|
|
||||||
|
* Device: [e.g. iPhone6]
|
||||||
|
* OS: [e.g. iOS8.1]
|
||||||
|
* Browser [e.g. stock browser, safari]
|
||||||
|
* Version [e.g. 22]
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
<!--Any additional context or details you think might be helpful.-->
|
||||||
|
<!--Ticket numbers/links, plugin versions, system statuses etc.-->
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Is your feature request related to a problem? Please describe.
|
||||||
|
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when […] -->
|
||||||
|
|
||||||
|
### Describe the solution you'd like
|
||||||
|
<!-- A clear and concise description of what you want to happen. -->
|
||||||
|
|
||||||
|
### Describe alternatives you've considered
|
||||||
|
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||||
|
|
||||||
|
### Should this be prioritized? Why?
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
<!--Any additional context, screenshots, or details you think might be helpful.-->
|
|
@ -0,0 +1,27 @@
|
||||||
|
Fixes #
|
||||||
|
|
||||||
|
_Replace this with a good description of your changes & reasoning._
|
||||||
|
|
||||||
|
### Accessibility
|
||||||
|
|
||||||
|
<!-- If you've changed or added any interactions, check off the appropriate items below. You can delete any that don't apply. Use this space to elaborate on anything if needed. -->
|
||||||
|
|
||||||
|
- [ ] I've tested using only a keyboard (no mouse)
|
||||||
|
- [ ] I've tested using a screen reader
|
||||||
|
- [ ] All animations respect [`prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion)
|
||||||
|
- [ ] All text has [at least a 4.5 color contrast with its background](https://webaim.org/resources/contrastchecker/)
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
|
||||||
|
### Detailed test instructions:
|
||||||
|
|
||||||
|
- Ex: Open page `url`
|
||||||
|
- Click XYZ…
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please add your test instructions to `/TESTING-INSTRUCTIONS.md`.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--- Please add a Changelog note
|
||||||
|
|
||||||
|
Enter a changelog note using the following CLI command `pnpm run changelogger -- add` and commit changes. --->
|
|
@ -0,0 +1,18 @@
|
||||||
|
# PR Labeler Action
|
||||||
|
|
||||||
|
This is a standalone github action hosted within wc-admin that supports
|
||||||
|
auto adding or removing a PR label, which could be useful in various
|
||||||
|
automation scenarios.
|
||||||
|
|
||||||
|
To keep it simple and avoid checking in `node_modules` when you make
|
||||||
|
changes to `index.js` you'll need to compile it into the `dist` directory
|
||||||
|
via [@vercel/ncc](https://github.com/vercel/ncc).
|
||||||
|
|
||||||
|
Run these commands from the root of the action before pushing an update to `dist/index.js`:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm i -g @vercel/ncc
|
||||||
|
ncc build index.js
|
||||||
|
```
|
||||||
|
|
||||||
|
This will compile the `node_modules` alongside the js into one single file.
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: 'PR labeler'
|
||||||
|
description: 'Add or remove a label from a PR'
|
||||||
|
inputs:
|
||||||
|
access_token:
|
||||||
|
description: 'Github token used to access the API'
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
description: 'Label to add or remove'
|
||||||
|
required: true
|
||||||
|
default: ''
|
||||||
|
action:
|
||||||
|
description: 'Add or remove the label'
|
||||||
|
required: true
|
||||||
|
default: 'add'
|
||||||
|
runs:
|
||||||
|
using: 'node12'
|
||||||
|
main: 'dist/index.js'
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,60 @@
|
||||||
|
const core = require( '@actions/core' );
|
||||||
|
const github = require( '@actions/github' );
|
||||||
|
|
||||||
|
const getPRNumber = () => {
|
||||||
|
const pr = github.context.payload.pull_request;
|
||||||
|
return pr && pr.number ? pr.number : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addLabel = async ( client, label, prNumber ) => {
|
||||||
|
await client.issues.addLabels( {
|
||||||
|
owner: github.context.repo.owner,
|
||||||
|
repo: github.context.repo.repo,
|
||||||
|
issue_number: prNumber,
|
||||||
|
labels: [ label ],
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeLabel = async ( client, label, prNumber ) => {
|
||||||
|
await client.issues.removeLabel( {
|
||||||
|
owner: github.context.repo.owner,
|
||||||
|
repo: github.context.repo.repo,
|
||||||
|
issue_number: prNumber,
|
||||||
|
name: label,
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const prNumber = getPRNumber();
|
||||||
|
|
||||||
|
if ( ! prNumber ) {
|
||||||
|
console.log( 'This action only supports pull requests.' );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = core.getInput( 'access_token', { required: true } );
|
||||||
|
const client = github.getOctokit( token );
|
||||||
|
const label = core.getInput( 'label', { required: true } );
|
||||||
|
const action = core.getInput( 'action', { required: true } );
|
||||||
|
|
||||||
|
const { data: pullRequest } = await client.pulls.get( {
|
||||||
|
owner: github.context.repo.owner,
|
||||||
|
repo: github.context.repo.repo,
|
||||||
|
pull_number: prNumber,
|
||||||
|
} );
|
||||||
|
|
||||||
|
const prHasLabel = pullRequest.labels.some( ( l ) => l.name === label );
|
||||||
|
|
||||||
|
if ( action === 'add' && ! prHasLabel ) {
|
||||||
|
await addLabel( client, label, prNumber );
|
||||||
|
} else if ( action === 'remove' && prHasLabel ) {
|
||||||
|
await removeLabel( client, label, prNumber );
|
||||||
|
}
|
||||||
|
} catch ( e ) {
|
||||||
|
core.error( e );
|
||||||
|
core.setFailed( e.message );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
192
plugins/woocommerce-admin/.github/actions/pr-labeler/package-lock.json
generated
vendored
Normal file
192
plugins/woocommerce-admin/.github/actions/pr-labeler/package-lock.json
generated
vendored
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
{
|
||||||
|
"name": "pr-labeler",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-eDOLH1Nq9zh+PJlYLqEMkS/jLQxhksPNmUGNBHfa4G+tQmnIhzpctxmchETtVGyBOvXgOVVpYuE40+eS4cUnwQ=="
|
||||||
|
},
|
||||||
|
"@actions/github": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/github/-/github-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-Ej/Y2E+VV6sR9X7pWL5F3VgEWrABaT292DRqRU6R4hnQjPtC/zD3nagxVdXWiRQvYDh8kHXo7IDmG42eJ/dOMA==",
|
||||||
|
"requires": {
|
||||||
|
"@actions/http-client": "^1.0.8",
|
||||||
|
"@octokit/core": "^3.0.0",
|
||||||
|
"@octokit/plugin-paginate-rest": "^2.2.3",
|
||||||
|
"@octokit/plugin-rest-endpoint-methods": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@actions/http-client": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
||||||
|
"requires": {
|
||||||
|
"tunnel": "0.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/auth-token": {
|
||||||
|
"version": "2.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.5.tgz",
|
||||||
|
"integrity": "sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/types": "^6.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/core": {
|
||||||
|
"version": "3.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
|
||||||
|
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/auth-token": "^2.4.4",
|
||||||
|
"@octokit/graphql": "^4.5.8",
|
||||||
|
"@octokit/request": "^5.6.0",
|
||||||
|
"@octokit/request-error": "^2.0.5",
|
||||||
|
"@octokit/types": "^6.0.3",
|
||||||
|
"before-after-hook": "^2.2.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/endpoint": {
|
||||||
|
"version": "6.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||||
|
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/types": "^6.0.3",
|
||||||
|
"is-plain-object": "^5.0.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/graphql": {
|
||||||
|
"version": "4.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||||
|
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/request": "^5.6.0",
|
||||||
|
"@octokit/types": "^6.0.3",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/openapi-types": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-k1iO2zKuEjjRS1EJb4FwSLk+iF6EGp+ZV0OMRViQoWhQ1fZTk9hg1xccZII5uyYoiqcbC73MRBmT45y1vp2PPg=="
|
||||||
|
},
|
||||||
|
"@octokit/plugin-paginate-rest": {
|
||||||
|
"version": "2.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.0.tgz",
|
||||||
|
"integrity": "sha512-8YYzALPMvEZ35kgy5pdYvQ22Roz+BIuEaedO575GwE2vb/ACDqQn0xQrTJR4tnZCJn7pi8+AWPVjrFDaERIyXQ==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/types": "^6.26.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/plugin-rest-endpoint-methods": {
|
||||||
|
"version": "4.15.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.15.1.tgz",
|
||||||
|
"integrity": "sha512-4gQg4ySoW7ktKB0Mf38fHzcSffVZd6mT5deJQtpqkuPuAqzlED5AJTeW8Uk7dPRn7KaOlWcXB0MedTFJU1j4qA==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/types": "^6.13.0",
|
||||||
|
"deprecation": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/request": {
|
||||||
|
"version": "5.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.1.tgz",
|
||||||
|
"integrity": "sha512-Ls2cfs1OfXaOKzkcxnqw5MR6drMA/zWX/LIS/p8Yjdz7QKTPQLMsB3R+OvoxE6XnXeXEE2X7xe4G4l4X0gRiKQ==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/endpoint": "^6.0.1",
|
||||||
|
"@octokit/request-error": "^2.1.0",
|
||||||
|
"@octokit/types": "^6.16.1",
|
||||||
|
"is-plain-object": "^5.0.0",
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/request-error": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/types": "^6.0.3",
|
||||||
|
"deprecation": "^2.0.0",
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/types": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.26.0.tgz",
|
||||||
|
"integrity": "sha512-RDxZBAFMtqs1ZPnbUu1e7ohPNfoNhTiep4fErY7tZs995BeHu369Vsh5woMIaFbllRWEZBfvTCS4hvDnMPiHrA==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/openapi-types": "^10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"before-after-hook": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||||
|
},
|
||||||
|
"deprecation": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||||
|
},
|
||||||
|
"is-plain-object": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||||
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "2.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
|
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||||
|
"requires": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||||
|
},
|
||||||
|
"tunnel": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||||
|
},
|
||||||
|
"universal-user-agent": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||||
|
},
|
||||||
|
"webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||||
|
},
|
||||||
|
"whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||||
|
"requires": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "pr-labeler",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": "^1.2.6",
|
||||||
|
"@actions/github": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
Packages: [ "/packages/*" ]
|
||||||
|
Components: /packages/components
|
||||||
|
Build: [ "/.*", "*.config.js", "bin/*", "composer.json", "Gruntfile.js", "package.json" ]
|
|
@ -0,0 +1,140 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "category: accessibility",
|
||||||
|
"color": "5804ea",
|
||||||
|
"aliases": [ "Accessibility" ],
|
||||||
|
"description": "The issue/PR is related to accessibility."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "category: duplicate",
|
||||||
|
"color": "5804ea",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue/PR is a duplicate of another issue."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "category: i18n",
|
||||||
|
"color": "5804ea",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue/PR is related to internationalization."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "category: performance",
|
||||||
|
"color": "5804ea",
|
||||||
|
"aliases": [ "[Type] Performance" ],
|
||||||
|
"description": "The issue/PR is related to performance."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "category: refactor",
|
||||||
|
"color": "5804ea",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue/PR is related to refactoring."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "category: won't fix",
|
||||||
|
"color": "5804ea",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue won’t be fixed."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "good first issue",
|
||||||
|
"color": "1eff05",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue is a good candidate for the first community contribution/for a newcomer to the team."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "impact: high",
|
||||||
|
"color": "d73a4a",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "This issue impacts a lot of users as reported by our Happiness Engineers."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "needs design",
|
||||||
|
"color": "ed95d2",
|
||||||
|
"aliases": [ "Design", "[Status] Needs Design Review" ],
|
||||||
|
"description": "The issue requires design input/work from a designer."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "needs docs",
|
||||||
|
"color": "ed95d2",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue/PR requires documentation to be added."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "needs feedback",
|
||||||
|
"color": "ed95d2",
|
||||||
|
"aliases": [ "[Status] Needs feedback" ],
|
||||||
|
"description": "The issue/PR needs a response from any of the parties involved in the issue."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "needs tests",
|
||||||
|
"color": "ed95d2",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue/PR needs tests before it can move forward."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "priority: critical",
|
||||||
|
"color": "d73a4a",
|
||||||
|
"aliases": [ "[Priority] Critical" ],
|
||||||
|
"description": "The issue is critical—e.g. a fatal error, security problem affecting many customers."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "priority: high",
|
||||||
|
"color": "d93f0b",
|
||||||
|
"aliases": [ "[Priority] High" ],
|
||||||
|
"description": "The issue/PR is high priority—it affects lots of customers substantially, but not critically."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "priority: low",
|
||||||
|
"color": "e2f78c",
|
||||||
|
"aliases": [ "[Priority] Low" ],
|
||||||
|
"description": "The issue/PR is low priority—not many people are affected or there’s a workaround, etc."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status: blocked",
|
||||||
|
"color": "d73a4a",
|
||||||
|
"aliases": [ "[Status] Blocked" ],
|
||||||
|
"description": "The issue is blocked from progressing, waiting for another piece of work to be done."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status: on hold",
|
||||||
|
"color": "d93f0b",
|
||||||
|
"aliases": [ "[Status] On Hold" ],
|
||||||
|
"description": "The issue is currently not prioritized."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type: bug",
|
||||||
|
"color": "d73a4a",
|
||||||
|
"aliases": [ "[Type] Bug" ],
|
||||||
|
"description": "The issue is a confirmed bug."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type: documentation",
|
||||||
|
"color": "0075ca",
|
||||||
|
"aliases": [ "Documentation" ],
|
||||||
|
"description": "This issue is a request for better documentation."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type: enhancement",
|
||||||
|
"color": "0075ca",
|
||||||
|
"aliases": [ "[Type] Enhancement" ],
|
||||||
|
"description": "The issue is a request for an enhancement."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type: question",
|
||||||
|
"color": "0075ca",
|
||||||
|
"aliases": [],
|
||||||
|
"description": "The issue is a question about how code works."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type: task",
|
||||||
|
"color": "0075ca",
|
||||||
|
"aliases": [ "[Type] Task" ],
|
||||||
|
"description": "The issue is an internally driven task (e.g. from another A8c team)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type: technical debt",
|
||||||
|
"color": "0075ca",
|
||||||
|
"aliases": [ "Tech debt" ],
|
||||||
|
"description": "This issue/PR represents/solves the technical debt of the project."
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,10 @@
|
||||||
|
name: 'Block Merge To main'
|
||||||
|
on: [ pull_request ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
block_merge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Merge Blocked
|
||||||
|
if: github.event.pull_request.base.ref == 'main'
|
||||||
|
run: exit 1
|
|
@ -0,0 +1,57 @@
|
||||||
|
name: 'Daily E2E Tests'
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
e2e-tests:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
wordpress: ['https://wordpress.org/latest.zip', 'https://wordpress.org/nightly-builds/wordpress-latest.zip']
|
||||||
|
woocommerce: ['https://downloads.wordpress.org/plugin/woocommerce.zip', 'https://github.com/woocommerce/woocommerce/releases/download/nightly/woocommerce-trunk-nightly.zip']
|
||||||
|
exclude:
|
||||||
|
- {'wordpress': 'https://wordpress.org/nightly-builds/wordpress-latest.zip', 'woocommerce': 'https://github.com/woocommerce/woocommerce/releases/download/nightly/woocommerce-trunk-nightly.zip'}
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Install PHP dependencies
|
||||||
|
run: |
|
||||||
|
composer install --no-dev
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2-beta
|
||||||
|
with:
|
||||||
|
node-version: '14'
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
uses: pnpm/action-setup@v2.2.1
|
||||||
|
with:
|
||||||
|
version: ^6.24.2
|
||||||
|
run_install: true
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
composer require wp-cli/i18n-command
|
||||||
|
pnpm run build:feature-config
|
||||||
|
pnpm run build
|
||||||
|
- name: Setup wp-env
|
||||||
|
env:
|
||||||
|
WP_ENV_CONFIG: '{ core: "${{ matrix.wordpress }}", plugins: [ ".", "${{ matrix.woocommerce }}" ] }'
|
||||||
|
run: |
|
||||||
|
pnpm -g i @wordpress/env
|
||||||
|
printf '%s\n' "$WP_ENV_CONFIG" > .wp-env-override.json
|
||||||
|
WP_ENV_TESTS_PORT=8084 wp-env start
|
||||||
|
wp-env run tests-cli "wp post create --post_type=page --post_status=publish --post_title='Ready' --post_content='E2E-tests.'"
|
||||||
|
- name: Test
|
||||||
|
env:
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
run: |
|
||||||
|
pnpm exec wc-e2e test:e2e
|
||||||
|
- name: Archive e2e test screenshots
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: e2e-screenshots
|
||||||
|
path: tests/e2e/screenshots
|
||||||
|
if-no-files-found: ignore
|
||||||
|
retention-days: 5
|
|
@ -0,0 +1,40 @@
|
||||||
|
name: 'Daily PHP Tests'
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
daily-test-php:
|
||||||
|
name: "Test PHP"
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
wordpress: ['latest', 'nightly']
|
||||||
|
woocommerce: ['latest', 'nightly']
|
||||||
|
exclude:
|
||||||
|
- {'wordpress': 'nightly', 'woocommerce': 'nightly'}
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2-beta
|
||||||
|
with:
|
||||||
|
node-version: '14'
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
uses: pnpm/action-setup@v2.2.1
|
||||||
|
with:
|
||||||
|
version: ^6.24.2
|
||||||
|
run_install: true
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
pnpm run build:feature-config
|
||||||
|
composer install --no-dev
|
||||||
|
shell: bash
|
||||||
|
- name: Run the PHP unit tests
|
||||||
|
env:
|
||||||
|
WP_VERSION: ${{ matrix.wordpress }}
|
||||||
|
WC_VERSION: ${{ matrix.woocommerce }}
|
||||||
|
run: pnpm run test:php
|
||||||
|
shell: bash
|
|
@ -0,0 +1,50 @@
|
||||||
|
name: E2E tests
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
e2e-tests:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Cancel Previous Runs
|
||||||
|
uses: styfle/cancel-workflow-action@0.7.0
|
||||||
|
with:
|
||||||
|
access_token: ${{ github.token }}
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@2.9.0
|
||||||
|
with:
|
||||||
|
php-version: '7.3'
|
||||||
|
- name: Install PHP dependencies
|
||||||
|
run: |
|
||||||
|
composer self-update 2.0.6
|
||||||
|
composer i
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2-beta
|
||||||
|
with:
|
||||||
|
node-version: '14'
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
uses: pnpm/action-setup@v2.2.1
|
||||||
|
with:
|
||||||
|
version: ^6.24.2
|
||||||
|
run_install: true
|
||||||
|
- name: Build and run E2E Tests
|
||||||
|
env:
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }}
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}
|
||||||
|
WP_VERSION: '5.8.0'
|
||||||
|
run: |
|
||||||
|
composer require wp-cli/i18n-command
|
||||||
|
pnpm run build
|
||||||
|
pnpm run e2e:docker-up
|
||||||
|
sleep 10
|
||||||
|
pnpm exec wc-e2e test:e2e
|
||||||
|
- name: Archive e2e test screenshots
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: e2e-screenshots
|
||||||
|
path: tests/e2e/screenshots
|
||||||
|
if-no-files-found: ignore
|
||||||
|
retention-days: 5
|
|
@ -0,0 +1,33 @@
|
||||||
|
name: Publish docs
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2-beta
|
||||||
|
with:
|
||||||
|
node-version: '14'
|
||||||
|
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
uses: pnpm/action-setup@v2.2.1
|
||||||
|
with:
|
||||||
|
version: ^6.24.2
|
||||||
|
run_install: true
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
pnpm run build
|
||||||
|
pnpm run docs
|
||||||
|
|
||||||
|
- name: Deploy docs
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_branch: gh-pages
|
||||||
|
publish_dir: ./docs
|
|
@ -0,0 +1,37 @@
|
||||||
|
name: Lint the changelog
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, edited]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-changelog:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Cancel Previous Runs
|
||||||
|
uses: styfle/cancel-workflow-action@0.7.0
|
||||||
|
with:
|
||||||
|
access_token: ${{ github.token }}
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
if: github.event.pull_request.user.login != 'renovate[bot]'
|
||||||
|
- name: skip-workflow
|
||||||
|
id: skip-workflow
|
||||||
|
uses: saulmaldonado/skip-workflow@v1.1.1
|
||||||
|
with:
|
||||||
|
phrase: /no changelog/i
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
pr-message: 'body'
|
||||||
|
search: '["pull_request"]'
|
||||||
|
- name: Check for changelog entry
|
||||||
|
if: github.event.pull_request.user.login != 'renovate[bot]' && !steps.skip-workflow.outputs.skip
|
||||||
|
env:
|
||||||
|
PR_NUMBER: ${{github.event.number}}
|
||||||
|
run: bin/ci/lint-changelog.sh
|
||||||
|
shell: bash
|
||||||
|
- name: Add a reminder label to the PR
|
||||||
|
uses: ./.github/actions/pr-labeler
|
||||||
|
if: github.event.pull_request.user.login != 'renovate[bot]' && always()
|
||||||
|
with:
|
||||||
|
access_token: ${{ github.token }}
|
||||||
|
label: ${{ env.label || 'needs changelog entry' }}
|
||||||
|
action: ${{ env.label_action || 'remove' }}
|
|
@ -0,0 +1,25 @@
|
||||||
|
name: Lint the PHP
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-php:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Cancel Previous Runs
|
||||||
|
uses: styfle/cancel-workflow-action@0.7.0
|
||||||
|
with:
|
||||||
|
access_token: ${{ github.token }}
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Determine changed files
|
||||||
|
id: changed-files
|
||||||
|
uses: wyrihaximus/github-action-files-in-commit@v1.0
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@2.9.0
|
||||||
|
with:
|
||||||
|
php-version: 7.3
|
||||||
|
- name: Lint the PHP
|
||||||
|
env:
|
||||||
|
CHANGED_FILES: ${{ steps.changed-files.outputs.files }}
|
||||||
|
run: bin/phpcs.sh
|
||||||
|
shell: bash
|
|
@ -0,0 +1,25 @@
|
||||||
|
name: Lint and test JS
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-lint-js:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Cancel Previous Runs
|
||||||
|
uses: styfle/cancel-workflow-action@0.7.0
|
||||||
|
with:
|
||||||
|
access_token: ${{ github.token }}
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2.5.1
|
||||||
|
with:
|
||||||
|
node-version: '14'
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
uses: pnpm/action-setup@v2.2.1
|
||||||
|
with:
|
||||||
|
version: ^6.24.2
|
||||||
|
run_install: true
|
||||||
|
- name: Lint and test the JS
|
||||||
|
run: bin/js_lint_test.sh
|
||||||
|
shell: bash
|
|
@ -0,0 +1,23 @@
|
||||||
|
name: 'Mark or close stale issues and PRs'
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '00 * * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v3
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
days-before-stale: 60
|
||||||
|
days-before-close: 5
|
||||||
|
stale-issue-message: 'This issue has been automatically marked as stale because it has not had any recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||||
|
stale-pr-message: 'This PR has been automatically marked as stale because it has not had any recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||||
|
close-issue-message: 'This issue was automatically closed due to being stale. Please feel free to re-open it if you still experience this problem.'
|
||||||
|
close-pr-message: 'This PR was automatically closed due to being stale.'
|
||||||
|
stale-pr-label: 'status: stale'
|
||||||
|
stale-issue-label: 'status: stale'
|
||||||
|
exempt-issue-labels: 'cooldown period,priority: high,priority: critical,feature: inbox,feature: components,feature: analytics,feature: marketing,feature: onboarding,feature: navigation,feature: wcpay,feature: settings,feature: home screen,feature: customer effort score,feature: setup checklist,feature: activity panel,feature: rest api'
|
||||||
|
ascending: true
|
|
@ -0,0 +1,87 @@
|
||||||
|
name: Run PHP unit tests
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-php:
|
||||||
|
env:
|
||||||
|
WP_CORE_DIR: '/tmp/wordpress'
|
||||||
|
COMPOSER_DEV: 1
|
||||||
|
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
php: ['7.1', '7.2', '7.3']
|
||||||
|
wordpress: ['5.4', '5.6']
|
||||||
|
woocommerce: ['4.8.0', '4.9.1']
|
||||||
|
phpunit: ['7.5.20']
|
||||||
|
composer: ['2.0.6']
|
||||||
|
include:
|
||||||
|
- php: '7.0'
|
||||||
|
wordpress: '5.6'
|
||||||
|
woocommerce: 'latest'
|
||||||
|
phpunit: '6.5.9'
|
||||||
|
composer: '1.10.19'
|
||||||
|
- php: '7.0'
|
||||||
|
wordpress: '5.6'
|
||||||
|
woocommerce: '4.9.1'
|
||||||
|
phpunit: '6.5.9'
|
||||||
|
composer: '2.0.6'
|
||||||
|
- php: '8.0'
|
||||||
|
wordpress: '5.6'
|
||||||
|
woocommerce: '5.1.0'
|
||||||
|
phpunit: '7.5.20'
|
||||||
|
composer: '2.0.6'
|
||||||
|
steps:
|
||||||
|
- name: Cancel Previous Runs
|
||||||
|
uses: styfle/cancel-workflow-action@0.7.0
|
||||||
|
with:
|
||||||
|
access_token: ${{ github.token }}
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@2.9.0
|
||||||
|
with:
|
||||||
|
php-version: ${{matrix.php}}
|
||||||
|
tools: phpunit:${{matrix.phpunit}}
|
||||||
|
extensions: mysqli
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2-beta
|
||||||
|
with:
|
||||||
|
node-version: '14'
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
uses: pnpm/action-setup@v2.2.1
|
||||||
|
with:
|
||||||
|
version: ^6.24.2
|
||||||
|
run_install: true
|
||||||
|
- name: Set up the tests
|
||||||
|
env:
|
||||||
|
WP_VERSION: ${{matrix.wordpress}}
|
||||||
|
WC_VERSION: ${{matrix.woocommerce}}
|
||||||
|
PHP_UNIT: ${{matrix.phpunit}}
|
||||||
|
COMPOSER_VERSION: ${{matrix.composer}}
|
||||||
|
run: |
|
||||||
|
sudo /etc/init.d/mysql start
|
||||||
|
bash bin/ci/gh-install-wp-tests.sh wc_admin_test root 'root' localhost
|
||||||
|
cd "$WP_CORE_DIR/wp-content/plugins/woocommerce-admin/"
|
||||||
|
pnpm run build:feature-config
|
||||||
|
composer install
|
||||||
|
node --version
|
||||||
|
pnpm --version
|
||||||
|
timedatectl
|
||||||
|
- name: Add PHP8 Compatibility.
|
||||||
|
run: |
|
||||||
|
if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then
|
||||||
|
cd "$WP_CORE_DIR/wp-content/plugins/woocommerce-admin/"
|
||||||
|
composer install
|
||||||
|
curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip
|
||||||
|
unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip
|
||||||
|
composer bin phpunit config --unset platform
|
||||||
|
composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}'
|
||||||
|
composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs
|
||||||
|
rm -rf ./vendor/phpunit/
|
||||||
|
composer dump-autoload
|
||||||
|
fi
|
||||||
|
- name: Run the PHP unit tests
|
||||||
|
run: bin/phpunit.sh
|
||||||
|
shell: bash
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
# Directories/files that may be generated by this project
|
||||||
|
node_modules/
|
||||||
|
/dist
|
||||||
|
docs/**/dist
|
||||||
|
build
|
||||||
|
build-module
|
||||||
|
build-style
|
||||||
|
build-types
|
||||||
|
languages/*
|
||||||
|
!languages/README.md
|
||||||
|
woocommerce-admin.zip
|
||||||
|
includes/feature-config.php
|
||||||
|
/storybook/wordpress
|
||||||
|
tests/e2e/screenshots/*
|
||||||
|
docs/components/storybook/*
|
||||||
|
|
||||||
|
# Directories/files that may appear in your environment
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
wp-cli.local.yml
|
||||||
|
*.sql
|
||||||
|
*.swp
|
||||||
|
*.tar.gz
|
||||||
|
*.tgz
|
||||||
|
*.zip
|
||||||
|
.idea
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/settings.json
|
||||||
|
|
||||||
|
# Composer
|
||||||
|
/vendor/
|
||||||
|
/vendor-bin/
|
||||||
|
/bin/composer/**/vendor/
|
||||||
|
|
||||||
|
# wp-env config
|
||||||
|
.wp-env.override.json
|
||||||
|
|
||||||
|
# Typescript
|
||||||
|
*.tsbuildinfo
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
pnpm exec lint-staged
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
node bin/pre-push-hook.js
|
|
@ -0,0 +1 @@
|
||||||
|
enable-pre-post-scripts=true
|
|
@ -0,0 +1 @@
|
||||||
|
14
|
|
@ -0,0 +1,3 @@
|
||||||
|
// Import the default config file and expose it in the project root.
|
||||||
|
// Useful for editor integrations.
|
||||||
|
module.exports = require("@wordpress/prettier-config");
|
|
@ -0,0 +1 @@
|
||||||
|
storybook
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib"
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "ts:check",
|
||||||
|
"problemMatcher": [ "$tsc" ],
|
||||||
|
"label": "npm: ts:check",
|
||||||
|
"detail": "Type checking",
|
||||||
|
"runOptions": {
|
||||||
|
"runOn": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "ts:check:watch",
|
||||||
|
"problemMatcher": {
|
||||||
|
"base": "$tsc-watch",
|
||||||
|
"applyTo": "allDocuments"
|
||||||
|
},
|
||||||
|
"isBackground": true,
|
||||||
|
"label": "npm: ts:check:watch",
|
||||||
|
"detail": "Incremental background type checks",
|
||||||
|
"runOptions": {
|
||||||
|
"runOn": "folderOpen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"phpVersion": "7.4",
|
||||||
|
"core": null,
|
||||||
|
"plugins": [
|
||||||
|
".",
|
||||||
|
"https://downloads.wordpress.org/plugin/woocommerce.zip"
|
||||||
|
],
|
||||||
|
"config": {
|
||||||
|
"JETPACK_AUTOLOAD_DEV": true,
|
||||||
|
"WP_DEBUG_LOG": true,
|
||||||
|
"WP_DEBUG_DISPLAY": true,
|
||||||
|
"ALTERNATE_WP_CRON": true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,172 @@
|
||||||
|
# Contributing to WooCommerce Admin
|
||||||
|
|
||||||
|
Hi! Thank you for your interest in contributing to WooCommerce Admin. We appreciate it.
|
||||||
|
|
||||||
|
There are many ways to contribute – reporting bugs, adding translations, feature suggestions, and fixing bugs.
|
||||||
|
|
||||||
|
## Reporting Bugs, Asking Questions, Sending Suggestions
|
||||||
|
|
||||||
|
Open [a GitHub issue](https://github.com/woocommerce/woocommerce-admin/issues/new/choose), that's all. If you have write access, add any appropriate labels.
|
||||||
|
|
||||||
|
If you're filing a bug, specific steps to reproduce are always helpful. Please include what you expected to see and what happened instead.
|
||||||
|
|
||||||
|
## Localizing WooCommerce Admin
|
||||||
|
|
||||||
|
To translate WooCommerce Admin in your locale or language, [select your locale here](https://translate.wordpress.org/projects/wp-plugins/woocommerce-admin) and translate *Development* (which contains the plugin's string) and/or *Development Readme* (please translate what you see in the Details tab of the [plugin page](https://wordpress.org/plugins/woocommerce-admin/)).
|
||||||
|
|
||||||
|
A Global Translation Editor (GTE) or Project Translation Editor (PTE) with suitable rights will process your translations in due time.
|
||||||
|
|
||||||
|
Language packs are automatically generated once 95% of the plugin's strings are translated and approved for a locale.
|
||||||
|
|
||||||
|
### Testing translations in development without language packs
|
||||||
|
|
||||||
|
1. Requires `WP-CLI` version 2.1.0 or greater.
|
||||||
|
1. Generate a translation file with `pnpm run i18n xx_YY` (Where xx_YY is your locale, like it_IT).
|
||||||
|
1. Generate needed JSON files for JavaScript-based strings: `pnpm run i18n:json`.
|
||||||
|
1. Generate needed `woocommerce-admin-xx_YY.mo` file using your translation tool.
|
||||||
|
1. Move `.mo` and `.json` files to `/wp-content/languages/plugins`.
|
||||||
|
|
||||||
|
## We're Here To Help
|
||||||
|
|
||||||
|
We encourage you to ask for help. We want your first experience with WooCommerce Admin to be a good one, so don't be shy. If you're wondering why something is the way it is, or how a decision was made, you can tag issues with [Type] Question or prefix them with “Question:”
|
||||||
|
|
||||||
|
## Contributing Code
|
||||||
|
|
||||||
|
If you're a first-time code contributor to the repository, here's a quick guide to get started:
|
||||||
|
|
||||||
|
1. Fork the repo to your own account.
|
||||||
|
2. Clone your fork into the `wp-content/plugins` directory of your preferred WordPress development environment.
|
||||||
|
3. Don't forget to create a branch to keep your changes. (`git checkout -b add/my-cool-thing`).
|
||||||
|
4. From the `woocommerce-admin` plugin directory, build with `pnpm install` and `pnpm start`.
|
||||||
|
5. Visit your dev environment in the browser to enable the `WooCommerce Admin` plugin and try it out.
|
||||||
|
|
||||||
|
Tips:
|
||||||
|
- Try to keep each PR small (around 200-250 lines or less, if you can), and having multiple very small commits in each PR is preferable to one larger commit (especially if the PR is larger).
|
||||||
|
- Don't combine code formatting changes with meaningful ones. If there's formatting work that needs to be done en masse, do it all in one PR, then open another one for meaningful code changes.
|
||||||
|
- Add unit tests to your PR for better code coverage and review.
|
||||||
|
|
||||||
|
After you've made your updates, you're ready to commit:
|
||||||
|
|
||||||
|
1. Run a complete build via `pnpm run build`.
|
||||||
|
2. Do a `composer install` to ensure PHP dependencies can run on the pre-commit hook.
|
||||||
|
3. Create your commit. Write a descriptive, but short first line (e.g. "Reports: Reticulate the splines"), and add more details below. If your commit addresses a github issue, reference it by number here (e.g. "This commit fixes issue #123 by reticulating all the splines.")
|
||||||
|
4. Push the branch up to your local fork, then create a PR via the GitHub web interface.
|
||||||
|
|
||||||
|
## Creating a Pull Request
|
||||||
|
|
||||||
|
The pull request template will remind you of some of the details you need to fill out in your pull request, but there are 2 critical pieces of information that may be needed, the changelog and the testing instructions.
|
||||||
|
|
||||||
|
### Changelog Entry
|
||||||
|
|
||||||
|
For many pull requests a changelog entry is required. We make use of the [Jetpack Changelogger tool](https://packagist.org/packages/automattic/jetpack-changelogger) to handle our changelogs.
|
||||||
|
|
||||||
|
To create a changelog entry run `pnpm run changelogger -- add` and answer the questions. This will create a changelog entry in the [./changelogs](./changelogs) directory with the data you provided. Upon our next release this will be added to our [changelog.txt](./changelog.txt).
|
||||||
|
|
||||||
|
In most cases you'll have to provide a changelog entry (the last question), be sure to add your PR number at the end, in the format below:
|
||||||
|
|
||||||
|
`<Description of change>. #<PR Number>`
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
`a cool new feature. #1234`
|
||||||
|
|
||||||
|
The types we use currently are: "Fix", "Add", "Update", "Dev", "Tweak", "Performance" and "Enhancement"
|
||||||
|
|
||||||
|
- `Fix`. For bugfixes minor and major. e.g. "Fix a crash when the user selected 0 for revenue."
|
||||||
|
- `Add`. This is reserved for new features and functionality. e.g. "A new page for payment settings."
|
||||||
|
- `Update`. This is used interchangeably with `Add` at the moment. Use your best discretion to choose.
|
||||||
|
- `Dev` is for a code change that doesn't have an obvious user facing benefit. e.g. "Refactor a class to be single responsibility."
|
||||||
|
- `Tweak`. For minor changes to user facing functionality. e.g. "Styling updates to the site footer."
|
||||||
|
- `Performance`. For changes that improve the performance of the application. e.g. "Optimized SQL query to run 5x faster.".
|
||||||
|
- `Enhancement`. This is used interchangeably with `Tweak` at the moment. Use your best discretion to choose.
|
||||||
|
|
||||||
|
### Testing Instructions
|
||||||
|
|
||||||
|
Every release we do some manual testing of new features, workflows and major bugfixes. For these kind of changes we need to include
|
||||||
|
testing instructions. If your pull request requires testing instructions you'll need to add them under the `## Unreleased` heading in
|
||||||
|
`TESTING-INSTRUCTIONS.md`. Add a detailed set of testing instructions to test your change.
|
||||||
|
|
||||||
|
### When to Add Testing Instructions
|
||||||
|
|
||||||
|
**DO** Add testing instructions for:
|
||||||
|
|
||||||
|
- Significant new features and workflows being added.
|
||||||
|
- Major bugs and regressions. (This does not include fatal crashes on main screens though, these are covered by general testing).
|
||||||
|
|
||||||
|
**DON'T** Add testing instructions for:
|
||||||
|
|
||||||
|
- Visual issues and changes.
|
||||||
|
- Minor bugs.
|
||||||
|
- Tweaks
|
||||||
|
- Analytics tracking
|
||||||
|
|
||||||
|
Please make testing instructions as comprehensive as possible as testers may not have context of how to test some aspects
|
||||||
|
of the system.
|
||||||
|
|
||||||
|
For example an instruction like: `Enable new navigation` should be `Toggle on the new navigation under WooCommerce->Settings->Advanced->Features`.
|
||||||
|
Assume the tester does not have context on how to test the feature except for a basic understanding of Wordpress.
|
||||||
|
|
||||||
|
## PHP Unit tests
|
||||||
|
|
||||||
|
### Setting up PHP unit tests using [VVV](https://github.com/Varying-Vagrant-Vagrants/VVV)
|
||||||
|
|
||||||
|
1. SSH into the Vagrant box:
|
||||||
|
1. `cd` down to the Vagrant root (where `www` lives)
|
||||||
|
2. `vagrant ssh`
|
||||||
|
2. `cd /srv/www/<name of wp install>/public_html/wp-content/plugins/woocommerce-admin`
|
||||||
|
3. Set up test environment: `bin/install-wp-tests.sh wc-admin-tests root root`
|
||||||
|
4. Generate feature config: `php bin/generate-feature-config.php`
|
||||||
|
|
||||||
|
*Note: A WooCommerce development environment is required to live within the same `plugins` folder. Follow these [steps](https://github.com/woocommerce/woocommerce/wiki/How-to-set-up-WooCommerce-development-environment) to do so.*
|
||||||
|
|
||||||
|
### Running tests
|
||||||
|
|
||||||
|
1. SSH into the Vagrant box (`vagrant ssh`)
|
||||||
|
2. `cd /srv/www/<name of wp install>/public_html/wp-content/plugins/woocommerce-admin`
|
||||||
|
3. `composer test` to actually run the test suite
|
||||||
|
|
||||||
|
#### Filtering tests
|
||||||
|
|
||||||
|
You can restrict the test cases run using `phpunit`'s filter command line argument.
|
||||||
|
|
||||||
|
For example, to just run Order Report Stats tests:
|
||||||
|
|
||||||
|
`composer test -- --filter="WC_Tests_Reports_Orders_Stats"`
|
||||||
|
|
||||||
|
## Helper Scripts
|
||||||
|
|
||||||
|
There are a number of helper scripts exposed via our `package.json` (below list is not exhaustive, you can view the [`package.json` file directly to see all](https://github.com/woocommerce/woocommerce-admin/blob/main/package.json)):
|
||||||
|
|
||||||
|
- `pnpm run lint` : Run eslint over the javascript files
|
||||||
|
- `pnpm run i18n` : A multi-step process, used to create a pot file from both the JS and PHP gettext calls. First it runs `i18n:js`, which creates a temporary `.pot` file from the JS files. Next it runs `i18n:php`, which converts that `.pot` file to a PHP file. Lastly, it runs `i18n:pot`, which creates the final `.pot` file from all the PHP files in the plugin (including the generated one with the JS strings).
|
||||||
|
- `pnpm test` : Run the JS test suite
|
||||||
|
- `pnpm run docs`: Runs the script for generating/updating docs.
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### Debugging synced lookup information:
|
||||||
|
|
||||||
|
To debug synced lookup information in the database, you can bypass the action scheduler and immediately sync order and customer information by using the `woocommerce_analytics_disable_action_scheduling` hook.
|
||||||
|
|
||||||
|
```php
|
||||||
|
add_filter( 'woocommerce_analytics_disable_action_scheduling', '__return_true' );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using `debug` package.
|
||||||
|
|
||||||
|
Currently, the [debug package](https://github.com/visionmedia/debug) is utilized to provide additional debugging for various systems. This tool outputs additional debugging information in the browser console when it is activated.
|
||||||
|
|
||||||
|
To activate, open up your browser console and add this:
|
||||||
|
|
||||||
|
```js
|
||||||
|
localStorage.setItem( 'debug', 'wc-admin:*' );
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
WooCommerce Admin is licensed under [GNU General Public License v3 (or later)](/license.txt).
|
||||||
|
|
||||||
|
All materials contributed should be compatible with the GPLv3. This means that if you own the material, you agree to license it under the GPLv3 license. If you are contributing code that is not your own, such as adding a component from another Open Source project, or adding an `pnpm` package, you need to make sure you follow these steps:
|
||||||
|
|
||||||
|
1. Check that the code has a license. If you can't find one, you can try to contact the original author and get permission to use, or ask them to release under a compatible Open Source license.
|
||||||
|
2. Check the license is compatible with [GPLv3](https://www.gnu.org/licenses/license-list.en.html#GPLCompatibleLicenses), note that the Apache 2.0 license is *not* compatible.
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* eslint-disable */
|
||||||
|
module.exports = function( grunt ) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Project configuration
|
||||||
|
grunt.initConfig( {
|
||||||
|
makepot: {
|
||||||
|
target: {
|
||||||
|
options: {
|
||||||
|
domainPath: '/languages',
|
||||||
|
exclude: [ '.git/*', 'bin/*', 'node_modules/*', 'tests/*' ],
|
||||||
|
mainFile: 'woocommerce-admin.php',
|
||||||
|
potFilename: 'woocommerce-admin.pot',
|
||||||
|
potHeaders: {
|
||||||
|
poedit: true,
|
||||||
|
'x-poedit-keywordslist': true,
|
||||||
|
},
|
||||||
|
type: 'wp-plugin',
|
||||||
|
updateTimestamp: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
checktextdomain: {
|
||||||
|
options: {
|
||||||
|
text_domain: 'woocommerce-admin',
|
||||||
|
keywords: [
|
||||||
|
'__:1,2d',
|
||||||
|
'_e:1,2d',
|
||||||
|
'_x:1,2c,3d',
|
||||||
|
'esc_html__:1,2d',
|
||||||
|
'esc_html_e:1,2d',
|
||||||
|
'esc_html_x:1,2c,3d',
|
||||||
|
'esc_attr__:1,2d',
|
||||||
|
'esc_attr_e:1,2d',
|
||||||
|
'esc_attr_x:1,2c,3d',
|
||||||
|
'_ex:1,2c,3d',
|
||||||
|
'_n:1,2,4d',
|
||||||
|
'_nx:1,2,4c,5d',
|
||||||
|
'_n_noop:1,2,3d',
|
||||||
|
'_nx_noop:1,2,3c,4d',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
src: [
|
||||||
|
'**/*.php', // Include all files/
|
||||||
|
'!node_modules/**', // Exclude node_modules/
|
||||||
|
'!tests/**', // Exclude tests/
|
||||||
|
'!vendor/**', // Exclude vendor/
|
||||||
|
'!tmp/**', // Exclude tmp/
|
||||||
|
],
|
||||||
|
expand: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Load NPM tasks to be used here.
|
||||||
|
grunt.loadNpmTasks( 'grunt-wp-i18n' );
|
||||||
|
grunt.loadNpmTasks( 'grunt-checktextdomain' );
|
||||||
|
|
||||||
|
grunt.util.linefeed = '\n';
|
||||||
|
};
|
|
@ -0,0 +1,711 @@
|
||||||
|
### WooCommerce - eCommerce for WordPress
|
||||||
|
|
||||||
|
Copyright 2015 by the contributors
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
This program incorporates work covered by the following copyright and
|
||||||
|
permission notices:
|
||||||
|
|
||||||
|
Jigoshop is Copyright (c) 2011 Jigowatt Ltd.
|
||||||
|
http://jigowatt.com - http://jigoshop.com
|
||||||
|
|
||||||
|
Jigoshop is released under the GPL
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
WooCommerce - eCommerce for WordPress
|
||||||
|
|
||||||
|
Copyright 2015 by the contributors
|
||||||
|
|
||||||
|
WooCommerce is released under the GPL
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright © <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright © <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -0,0 +1,120 @@
|
||||||
|
# WooCommerce Admin
|
||||||
|
|
||||||
|
This is a feature plugin for a modern, javascript-driven WooCommerce Admin experience.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
[WordPress 5.6 or greater](https://wordpress.org/download/) and [WooCommerce 5.7.0 or greater](https://wordpress.org/plugins/woocommerce/) should be installed prior to activating the WooCommerce Admin feature plugin.
|
||||||
|
|
||||||
|
For better debugging, it's also recommended you add `define( 'SCRIPT_DEBUG', true );` to your wp-config. This will load the unminified version of all libraries, and specifically the development build of React.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
After cloning the repo, install dependencies:
|
||||||
|
|
||||||
|
- `pnpm install` to install JavaScript dependencies.
|
||||||
|
- `composer install` to gather PHP dependencies.
|
||||||
|
|
||||||
|
Now you can build the files using one of these commands:
|
||||||
|
|
||||||
|
- `pnpm run build` : Build a production version
|
||||||
|
- `pnpm run dev` : Build a development version
|
||||||
|
- `pnpm start` : Build a development version, watch files for changes
|
||||||
|
- `pnpm run build:release` : Build a WordPress plugin ZIP file (`woocommerce-admin.zip` will be created in the repository root)
|
||||||
|
- `DRY_RUN=1 pnpm run build:release` : Builds a Wordpress plugin ZIP **without** pushing it to Github and creating a release.
|
||||||
|
|
||||||
|
For more helper scripts [see here](./CONTRIBUTING.md#helper-scripts)
|
||||||
|
|
||||||
|
For some debugging tools/help [see here](./CONTRIBUTING.md#debugging)
|
||||||
|
|
||||||
|
For local development setup using Docker [see here](./docker/wc-admin-wp-env/README.md)
|
||||||
|
|
||||||
|
### Typescript
|
||||||
|
|
||||||
|
The `npm run ts:check` command will check your TypeScript files for errors, and has been added to `.vscode/tasks.json`.
|
||||||
|
Running this task in vscode will highlight the errors in your editor file navigator.
|
||||||
|
|
||||||
|
If you allow the `npm run ts:check:watch` command to run automatically as configured, it will run in the background and pick up any errors as you save the files.
|
||||||
|
Note: Even if you don't run this task, the IDE uses its language server to pick up type errors in files that are open. This is only necessary for picking up errors
|
||||||
|
across the entire repository even when they haven't been opened in the IDE.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
#### End-to-end tests
|
||||||
|
|
||||||
|
Tests live in `./tests/e2e`. An existing build is required prior running, please refer to the section above for steps. E2E tests use the `@woocommerce/e2e-environment` package which hosts a Docker container for testing, by default the container can be accessed at `http://localhost:8084`
|
||||||
|
|
||||||
|
All the commands from `@woocommerce/e2e-environment` can be run through `pnpm exec`.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Set up the e2e environment
|
||||||
|
pnpm i
|
||||||
|
pnpm exec wc-e2e docker:up
|
||||||
|
```
|
||||||
|
|
||||||
|
Run tests using:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm exec wc-e2e test:e2e-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
or in headless mode:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm exec wc-e2e test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
Run a single test by adding the path to the file name:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm exec wc-e2e test:e2e-dev tests/e2e/specs/activate-and-setup/complete-onboarding-wizard.test.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
There is documentation in 2 forms available in the repo. A static set of documentation supported by docsify and also a Storybook containing component documentation for `@woocommerce/components`.
|
||||||
|
|
||||||
|
To view the docsify docs locally you can do:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm install
|
||||||
|
cd docs
|
||||||
|
pnpm exec docsify serve
|
||||||
|
```
|
||||||
|
|
||||||
|
When deployed the docsify docs also host an embedded version of the storybook docs. To generate that and test it locally in docsify you'll need to run:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm install
|
||||||
|
pnpm run docs
|
||||||
|
cd docs
|
||||||
|
pnpm exec docsify serve
|
||||||
|
```
|
||||||
|
|
||||||
|
Then navigate to `Components` from the left hand menu in the docs.
|
||||||
|
|
||||||
|
If you would like to view the storybook docs hosted standalone, then you can run:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm install
|
||||||
|
pnpm run storybook
|
||||||
|
```
|
||||||
|
|
||||||
|
If you would like to view the storybook docs in right-to-left styling, you can run this instead:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm install
|
||||||
|
pnpm run storybook-rtl
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
If you're encountering any issue setting things up, chances are we have been there too. Please have a look at our [wiki](https://github.com/woocommerce/woocommerce-admin/wiki/Common-Issues) for a list of common problems.
|
||||||
|
|
||||||
|
## Privacy
|
||||||
|
|
||||||
|
If you have enabled WooCommerce usage tracking ( option `woocommerce_allow_tracking` ) then, in addition to the tracking described in https://woocommerce.com/usage-tracking/, this plugin also sends information about the actions that site administrators perform to Automattic - see https://automattic.com/privacy/#information-we-collect-automatically for more information.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
There are many ways to contribute – reporting bugs, adding translations, feature suggestions and fixing bugs. For full details, please see [CONTRIBUTING.md](./CONTRIBUTING.md)
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Reporting Security Issues
|
||||||
|
|
||||||
|
The WooCommerce team take security bugs seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
|
||||||
|
|
||||||
|
For security related issues and how to report them, please visit the [Automattic Security](https://automattic.com/security/) page.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,59 @@
|
||||||
|
const {
|
||||||
|
babelConfig: e2eBabelConfig,
|
||||||
|
} = require( '@woocommerce/e2e-environment' );
|
||||||
|
|
||||||
|
module.exports = function ( api ) {
|
||||||
|
api.cache( true );
|
||||||
|
|
||||||
|
return {
|
||||||
|
...e2eBabelConfig,
|
||||||
|
presets: [
|
||||||
|
...e2eBabelConfig.presets,
|
||||||
|
'@babel/preset-typescript',
|
||||||
|
'@wordpress/babel-preset-default',
|
||||||
|
],
|
||||||
|
sourceType: 'unambiguous',
|
||||||
|
plugins: [
|
||||||
|
/**
|
||||||
|
* This allows arrow functions as class methods so that binding
|
||||||
|
* methods to `this` in the constructor isn't required.
|
||||||
|
*/
|
||||||
|
'@babel/plugin-proposal-class-properties',
|
||||||
|
],
|
||||||
|
ignore: [ 'packages/**/node_modules' ],
|
||||||
|
env: {
|
||||||
|
production: {
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
'@wordpress/babel-plugin-makepot',
|
||||||
|
{
|
||||||
|
output: 'languages/woocommerce-admin.po',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
storybook: {
|
||||||
|
plugins: [
|
||||||
|
/**
|
||||||
|
* We need to set loose mode here because the storybook's default babel config enables the loose mode.
|
||||||
|
* The 'loose' mode configuration must be the same for those babel plugins.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
[
|
||||||
|
'@babel/plugin-proposal-class-properties',
|
||||||
|
{ loose: true },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@babel/plugin-proposal-private-methods',
|
||||||
|
{ loose: true },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@babel/plugin-proposal-private-property-in-object',
|
||||||
|
{ loose: true },
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,147 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ZIP_FILE='woocommerce-admin.zip';
|
||||||
|
IS_CUSTOM_BUILD=false;
|
||||||
|
SLUG='';
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
if [[ $1 == '-s' || $1 == '--slug' ]]; then
|
||||||
|
IS_CUSTOM_BUILD=true
|
||||||
|
SLUG=$2
|
||||||
|
ZIP_FILE="woocommerce-admin-$2.zip";
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Exit if any command fails.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Change to the expected directory.
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Enable nicer messaging for build status.
|
||||||
|
BLUE_BOLD='\033[1;34m';
|
||||||
|
GREEN_BOLD='\033[1;32m';
|
||||||
|
RED_BOLD='\033[1;31m';
|
||||||
|
YELLOW_BOLD='\033[1;33m';
|
||||||
|
COLOR_RESET='\033[0m';
|
||||||
|
error () {
|
||||||
|
echo -e "\n${RED_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
status () {
|
||||||
|
echo -e "\n${BLUE_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
success () {
|
||||||
|
echo -e "\n${GREEN_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
warning () {
|
||||||
|
echo -e "\n${YELLOW_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
status "💃 Time to release WooCommerce Admin 🕺"
|
||||||
|
if [ $DRY_RUN ]; then
|
||||||
|
warning "This is a dry run, nothing will be pushed up to Github, it will only generate zip files."
|
||||||
|
fi
|
||||||
|
|
||||||
|
warning "Please enter the version number to tag, for example, 1.0.0: "
|
||||||
|
read -r VERSION
|
||||||
|
|
||||||
|
if [ $IS_CUSTOM_BUILD = true ]; then
|
||||||
|
PLUGIN_TAG="${VERSION}-${SLUG}"
|
||||||
|
|
||||||
|
warning "A release on Github will be made with the tag ${GREEN_BOLD}$PLUGIN_TAG${COLOR_RESET}"
|
||||||
|
warning "The resulting zip will be called ${GREEN_BOLD}$ZIP_FILE${COLOR_RESET}"
|
||||||
|
else
|
||||||
|
PLUGIN_TAG="${VERSION}-plugin"
|
||||||
|
CORE_TAG="${VERSION}"
|
||||||
|
|
||||||
|
warning "You are building a regular release of wc-admin."
|
||||||
|
warning "A plugin and Core release will be made to Github with the tags ${GREEN_BOLD}$PLUGIN_TAG${YELLOW_BOLD} and ${GREEN_BOLD}$CORE_TAG${COLOR_RESET}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
warning "Ready to proceed? [y/N]: "
|
||||||
|
read -r PROCEED
|
||||||
|
|
||||||
|
if [ "$(echo "${PROCEED:-n}" | tr "[:upper:]" "[:lower:]")" != "y" ]; then
|
||||||
|
error "Release cancelled!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure there are no changes in the working tree. Release builds should be
|
||||||
|
# traceable to a particular commit and reliably reproducible. (This is not
|
||||||
|
# totally true at the moment because we download nightly vendor scripts).
|
||||||
|
changed=
|
||||||
|
if ! git diff --exit-code > /dev/null; then
|
||||||
|
changed="file(s) modified"
|
||||||
|
elif ! git diff --cached --exit-code > /dev/null; then
|
||||||
|
changed="file(s) staged"
|
||||||
|
fi
|
||||||
|
if [ ! -z "$changed" ]; then
|
||||||
|
git status
|
||||||
|
error "ERROR: Cannot build plugin zip with dirty working tree. ☝️
|
||||||
|
Commit your changes and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Do a dry run of the repository reset. Prompting the user for a list of all
|
||||||
|
# files that will be removed should prevent them from losing important files!
|
||||||
|
status "Resetting the repository to pristine condition. ✨"
|
||||||
|
git clean -xdf --dry-run
|
||||||
|
warning "🚨 About to delete everything above! Is this okay? 🚨"
|
||||||
|
echo -n "[y]es/[N]o: "
|
||||||
|
read answer
|
||||||
|
if [ "$answer" != "${answer#[Yy]}" ]; then
|
||||||
|
# Remove ignored files to reset repository to pristine condition. Previous
|
||||||
|
# test ensures that changed files abort the plugin build.
|
||||||
|
status "Cleaning working directory... 🛀"
|
||||||
|
git clean -xdf
|
||||||
|
else
|
||||||
|
error "Fair enough; aborting. Tidy up your repo and try again. 🙂"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install PHP dependencies
|
||||||
|
status "Gathering PHP dependencies... 🐿️"
|
||||||
|
composer install --no-dev
|
||||||
|
|
||||||
|
# Build the plugin files.
|
||||||
|
status "Generating the plugin build... 👷♀️"
|
||||||
|
WC_ADMIN_PHASE=plugin pnpm run build
|
||||||
|
|
||||||
|
# Make a Github release.
|
||||||
|
status "Starting a Github release... 👷♀️"
|
||||||
|
if [ $DRY_RUN ]; then
|
||||||
|
PLUGIN_ZIP_FILE="woocommerce-admin-plugin.zip"
|
||||||
|
else
|
||||||
|
PLUGIN_ZIP_FILE=$ZIP_FILE
|
||||||
|
fi
|
||||||
|
./bin/github-deploy.sh ${PLUGIN_TAG} ${PLUGIN_ZIP_FILE}
|
||||||
|
|
||||||
|
if [ $IS_CUSTOM_BUILD = false ]; then
|
||||||
|
# Remove ignored files to reset repository to pristine condition. Previous
|
||||||
|
# test ensures that changed files abort the plugin build.
|
||||||
|
status "Cleaning working directory... 🛀"
|
||||||
|
git clean -xdf -e woocommerce-admin-plugin.zip
|
||||||
|
|
||||||
|
# Install PHP dependencies
|
||||||
|
status "Gathering PHP dependencies... 🐿️"
|
||||||
|
composer install --no-dev
|
||||||
|
|
||||||
|
# Build the Core files.
|
||||||
|
status "Generating a Core build... 👷♀️"
|
||||||
|
WC_ADMIN_PHASE=core pnpm run build
|
||||||
|
|
||||||
|
# Make a Github release.
|
||||||
|
status "Starting a Github release... 👷♀️"
|
||||||
|
./bin/github-deploy.sh ${CORE_TAG} ${ZIP_FILE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $DRY_RUN ]; then
|
||||||
|
output 2 "Dry run successfully finished."
|
||||||
|
echo
|
||||||
|
echo "Generated $PLUGIN_ZIP_FILE for the woocommerce-admin plugin build"
|
||||||
|
echo "Generated $ZIP_FILE for the woocommerce-admin core build"
|
||||||
|
exit;
|
||||||
|
fi
|
||||||
|
success "Done. You've built WooCommerce Admin! 🎉 "
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Build a test zip from current branch for uploading to test site
|
||||||
|
#
|
||||||
|
phase=${WC_ADMIN_PHASE:-plugin}
|
||||||
|
|
||||||
|
WC_ADMIN_PHASE=$phase pnpm run build
|
||||||
|
composer install --no-dev
|
||||||
|
rm woocommerce-admin.zip
|
||||||
|
./bin/make-zip.sh woocommerce-admin.zip
|
|
@ -0,0 +1,168 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Automattic\Jetpack\Changelog\Changelog;
|
||||||
|
use Automattic\Jetpack\Changelog\KeepAChangelogParser;
|
||||||
|
use Automattic\Jetpack\Changelogger\FormatterPlugin;
|
||||||
|
use Automattic\Jetpack\Changelogger\PluginTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jetpack Changelogger Formatter for WC Admin
|
||||||
|
*
|
||||||
|
* Class WCAdminFormatter
|
||||||
|
*/
|
||||||
|
class WCAdminFormatter extends KeepAChangelogParser implements FormatterPlugin {
|
||||||
|
use PluginTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bullet for changes.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $bullet = '-';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String used as the date for an unreleased version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $unreleased = '== Unreleased ==';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modified version of parse() from KeepAChangelogParser.
|
||||||
|
*
|
||||||
|
* @param string $changelog Changelog contents.
|
||||||
|
* @return Changelog
|
||||||
|
* @throws InvalidArgumentException If the changelog data cannot be parsed.
|
||||||
|
*/
|
||||||
|
public function parse( $changelog ) {
|
||||||
|
$ret = new Changelog();
|
||||||
|
|
||||||
|
// Fix newlines and expand tabs.
|
||||||
|
$changelog = strtr( $changelog, array( "\r\n" => "\n" ) );
|
||||||
|
$changelog = strtr( $changelog, array( "\r" => "\n" ) );
|
||||||
|
while ( strpos( $changelog, "\t" ) !== false ) {
|
||||||
|
$changelog = preg_replace_callback(
|
||||||
|
'/^([^\t\n]*)\t/m',
|
||||||
|
function ( $m ) {
|
||||||
|
return $m[1] . str_repeat( ' ', 4 - ( mb_strlen( $m[1] ) % 4 ) );
|
||||||
|
},
|
||||||
|
$changelog
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entries make up the rest of the document.
|
||||||
|
$entries = array();
|
||||||
|
preg_match_all( '/^\=\=\s+([^\n=]+)\s+\=\=((?:(?!^\=\=).)+)/ms', $changelog, $matches );
|
||||||
|
|
||||||
|
foreach ( $matches[0] as $section ) {
|
||||||
|
$heading_pattern = '/^== +(\[?[^] ]+\]?) (.+?) ==/';
|
||||||
|
// Parse the heading and create a ChangelogEntry for it.
|
||||||
|
preg_match( $heading_pattern, $section, $heading );
|
||||||
|
if ( ! count( $heading ) ) {
|
||||||
|
throw new InvalidArgumentException( "Invalid heading: $heading" );
|
||||||
|
}
|
||||||
|
|
||||||
|
$version = $heading[1];
|
||||||
|
$timestamp = $heading[2];
|
||||||
|
if ( $timestamp === $this->unreleased ) {
|
||||||
|
$timestamp = null;
|
||||||
|
$entry_timestamp = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$timestamp = new DateTime( $timestamp, new DateTimeZone( 'UTC' ) );
|
||||||
|
} catch ( \Exception $ex ) {
|
||||||
|
throw new InvalidArgumentException( "Heading has an invalid timestamp: $heading", 0, $ex );
|
||||||
|
}
|
||||||
|
if ( strtotime( $heading[2], 0 ) !== strtotime( $heading[2], 1000000000 ) ) {
|
||||||
|
throw new InvalidArgumentException( "Heading has a relative timestamp: $heading" );
|
||||||
|
}
|
||||||
|
$entry_timestamp = $timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry = $this->newChangelogEntry(
|
||||||
|
$version,
|
||||||
|
array(
|
||||||
|
'timestamp' => $timestamp,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$entries[] = $entry;
|
||||||
|
$content = trim( preg_replace( $heading_pattern, '', $section ) );
|
||||||
|
|
||||||
|
if ( '' === $content ) {
|
||||||
|
// Huh, no changes.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now parse all the subheadings and changes.
|
||||||
|
while ( '' !== $content ) {
|
||||||
|
$changes = array();
|
||||||
|
$rows = explode( "\n", $content );
|
||||||
|
foreach ( $rows as $row ) {
|
||||||
|
$row = trim( $row );
|
||||||
|
$row = preg_replace( '/' . $this->bullet . '/', '', $row, 1 );
|
||||||
|
$row_segments = explode( ':', $row );
|
||||||
|
|
||||||
|
$changes[] = array(
|
||||||
|
'subheading' => trim($row_segments[0]),
|
||||||
|
'content' => count( $row_segments ) > 1 ? trim($row_segments[1]) : '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $changes as $change ) {
|
||||||
|
$entry->appendChange(
|
||||||
|
$this->newChangeEntry(
|
||||||
|
array(
|
||||||
|
'subheading' => $change['subheading'],
|
||||||
|
'content' => $change['content'],
|
||||||
|
'timestamp' => $entry_timestamp,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$content = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret->setEntries( $entries );
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a Changelog object to a string.
|
||||||
|
*
|
||||||
|
* @param Changelog $changelog Changelog object.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function format( Changelog $changelog ) {
|
||||||
|
$ret = '';
|
||||||
|
$date_format = 'm/d/Y';
|
||||||
|
$bullet = '- ';
|
||||||
|
$indent = str_repeat( ' ', strlen( $bullet ) );
|
||||||
|
|
||||||
|
foreach ( $changelog->getEntries() as $entry ) {
|
||||||
|
$timestamp = $entry->getTimestamp();
|
||||||
|
$ret .= '== ' . $entry->getVersion() . ' ' . $timestamp->format( $date_format ) . " == \n\n";
|
||||||
|
|
||||||
|
$prologue = trim( $entry->getPrologue() );
|
||||||
|
if ( '' !== $prologue ) {
|
||||||
|
$ret .= "\n$prologue\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $entry->getChangesBySubheading() as $heading => $changes ) {
|
||||||
|
foreach ( $changes as $change ) {
|
||||||
|
$text = trim( $change->getContent() );
|
||||||
|
if ( '' !== $text ) {
|
||||||
|
$ret .= $bullet . $heading . ': ' . str_replace( "\n", "\n$indent", $text ) . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ret = trim( $ret ) . "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = trim( $ret ) . "\n";
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo "usage: $0 <db-name> <db-user> <db-pass>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DB_NAME=$1
|
||||||
|
DB_USER=$2
|
||||||
|
DB_PASS=$3
|
||||||
|
DB_HOST='localhost'
|
||||||
|
|
||||||
|
TMPDIR=${TMPDIR-/tmp}
|
||||||
|
TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//")
|
||||||
|
WP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib}
|
||||||
|
WP_CORE_DIR=${WP_CORE_DIR-$TMPDIR/wordpress/}
|
||||||
|
WP_TESTS_TAG="branches/$WP_VERSION"
|
||||||
|
|
||||||
|
download() {
|
||||||
|
if [ `which curl` ]; then
|
||||||
|
curl -s "$1" > "$2";
|
||||||
|
elif [ `which wget` ]; then
|
||||||
|
wget -nv -O "$2" "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
install_wp() {
|
||||||
|
echo "::group::{install_wp}"
|
||||||
|
mkdir -p $WP_CORE_DIR
|
||||||
|
download https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json
|
||||||
|
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then
|
||||||
|
# version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x
|
||||||
|
LATEST_VERSION=${WP_VERSION%??}
|
||||||
|
else
|
||||||
|
# otherwise, scan the releases and get the most up to date minor version of the major release
|
||||||
|
local VERSION_ESCAPED=`echo $WP_VERSION | sed 's/\./\\\\./g'`
|
||||||
|
LATEST_VERSION=$(grep -o '"version":"'$VERSION_ESCAPED'[^"]*' $TMPDIR/wp-latest.json | sed 's/"version":"//' | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$LATEST_VERSION" ]]; then
|
||||||
|
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
||||||
|
else
|
||||||
|
local ARCHIVE_NAME="wordpress-$LATEST_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
download https://wordpress.org/${ARCHIVE_NAME}.tar.gz $TMPDIR/wordpress.tar.gz
|
||||||
|
tar --strip-components=1 -zxmf $TMPDIR/wordpress.tar.gz -C $WP_CORE_DIR
|
||||||
|
download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
|
||||||
|
echo "::endgroup::"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_test_suite() {
|
||||||
|
echo "::group::{install_test_suite}"
|
||||||
|
# portable in-place argument for both GNU sed and Mac OSX sed
|
||||||
|
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||||
|
local ioption='-i .bak'
|
||||||
|
else
|
||||||
|
local ioption='-i'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# removes testing suite
|
||||||
|
rm -rf $WP_TESTS_DIR
|
||||||
|
|
||||||
|
# set up testing suite if it doesn't yet exist
|
||||||
|
if [ ! -d $WP_TESTS_DIR ]; then
|
||||||
|
# set up testing suite
|
||||||
|
mkdir -p $WP_TESTS_DIR
|
||||||
|
svn co https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f wp-tests-config.php ]; then
|
||||||
|
download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
# remove all forward slashes in the end
|
||||||
|
WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::")
|
||||||
|
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
fi
|
||||||
|
echo "::endgroup::"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_db() {
|
||||||
|
echo "::group::{install_db}"
|
||||||
|
# drop existing database
|
||||||
|
echo "DROP DATABASE IF EXISTS $DB_NAME" | mysql --user="root" --password="$DB_PASS"
|
||||||
|
|
||||||
|
# create database
|
||||||
|
echo "CREATE DATABASE IF NOT EXISTS $DB_NAME" | mysql --user="root" --password="$DB_PASS"
|
||||||
|
echo "::endgroup::"
|
||||||
|
}
|
||||||
|
|
||||||
|
version() {
|
||||||
|
# convert version numbers to digits
|
||||||
|
echo "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }';
|
||||||
|
}
|
||||||
|
|
||||||
|
install_deps() {
|
||||||
|
echo "::group::{install_deps}"
|
||||||
|
# Script Variables
|
||||||
|
WP_SITE_URL="http://local.wordpress.test"
|
||||||
|
WORKING_DIR="$PWD"
|
||||||
|
|
||||||
|
# Set up WordPress using wp-cli
|
||||||
|
mkdir -p "$WP_CORE_DIR"
|
||||||
|
cd "$WP_CORE_DIR"
|
||||||
|
|
||||||
|
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||||
|
|
||||||
|
# delete existing wp-config and woocommerce repository
|
||||||
|
rm -f wp-config.php
|
||||||
|
rm -rf wp-content/plugins/woocommerce
|
||||||
|
|
||||||
|
php wp-cli.phar core config --dbname=$DB_NAME --dbuser=root --dbpass=$DB_PASS --dbhost=localhost --dbprefix=wptests_ --allow-root
|
||||||
|
php wp-cli.phar core install --url="$WP_SITE_URL" --title="Example" --admin_user=admin --admin_password=password --admin_email=info@example.com --path=$WP_CORE_DIR --skip-email --allow-root
|
||||||
|
|
||||||
|
# Install WooCommerce (latest non-hyphenated (beta, RC) tag)
|
||||||
|
if [[ "$WC_VERSION" == "latest" ]]; then
|
||||||
|
INSTALL_WC_TAG="$(git ls-remote --tags https://github.com/woocommerce/woocommerce.git | awk '{print $2}' | sed 's/^refs\/tags\///' | grep -E '^[0-9]\.[0-9]\.[0-9]$' | sort -V | tail -n 1)"
|
||||||
|
else
|
||||||
|
INSTALL_WC_TAG="$WC_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# As zip file does not include tests, we have to get it from git repo.
|
||||||
|
git clone --depth 1 --branch $INSTALL_WC_TAG https://github.com/woocommerce/woocommerce.git
|
||||||
|
|
||||||
|
if [ "$(version "$INSTALL_WC_TAG")" -ge "$(version "6.0.0")" ]; then
|
||||||
|
# WooCommerce 6.0.0 introduced a breaking change to the repo structure.
|
||||||
|
# We need to clone and use the correct folder path.
|
||||||
|
mv woocommerce/plugins/woocommerce wp-content/plugins/
|
||||||
|
else
|
||||||
|
mv woocommerce wp-content/plugins/
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "wp-content/plugins/"
|
||||||
|
|
||||||
|
# Bring in WooCommerce Core dependencies
|
||||||
|
composer self-update $COMPOSER_VERSION
|
||||||
|
cd "woocommerce"
|
||||||
|
|
||||||
|
composer install --no-dev
|
||||||
|
composer self-update 2.0.6
|
||||||
|
|
||||||
|
|
||||||
|
cd "$WP_CORE_DIR"
|
||||||
|
php wp-cli.phar plugin activate woocommerce
|
||||||
|
|
||||||
|
# Install woocommerce-admin
|
||||||
|
cd "$WP_CORE_DIR/wp-content/plugins"
|
||||||
|
cp -R $GITHUB_WORKSPACE ./
|
||||||
|
|
||||||
|
# Activate woocommerce-admin
|
||||||
|
cd "$WP_CORE_DIR"
|
||||||
|
php wp-cli.phar plugin activate woocommerce-admin
|
||||||
|
|
||||||
|
# Back to original dir
|
||||||
|
cd "$WORKING_DIR"
|
||||||
|
|
||||||
|
echo "::endgroup::"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_wp
|
||||||
|
install_test_suite
|
||||||
|
install_db
|
||||||
|
install_deps
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
changelog_entry=$(sed -n '/^Significance/,/^==/p' changelogs/* | grep -w "#$PR_NUMBER")
|
||||||
|
|
||||||
|
if [ -z "$changelog_entry" ]
|
||||||
|
then
|
||||||
|
echo "Error: No changelog entry was provided for #$PR_NUMBER"
|
||||||
|
echo "label_action=add" >> $GITHUB_ENV
|
||||||
|
echo "label=needs changelog entry" >> $GITHUB_ENV
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "label_action=remove" >> $GITHUB_ENV
|
||||||
|
echo "label=needs changelog entry" >> $GITHUB_ENV
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Command line script for merging two .pot files.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Admin
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the two file names from the command line.
|
||||||
|
*/
|
||||||
|
if ( $argc < 2 ) {
|
||||||
|
echo "Usage: php -f {$argv[0]} source-file.pot destination-file.pot\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( $index = 1; $index <= 2; $index++ ) {
|
||||||
|
if ( ! is_file( $argv[ $index ] ) ) {
|
||||||
|
echo "File not found: {$argv[ $index ]}\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether an output locale has been requested.
|
||||||
|
*/
|
||||||
|
if ( isset( $argv[3] ) && 0 === stripos( $argv[3], 'lang=' ) ) {
|
||||||
|
$locale = substr( $argv[3], 5 );
|
||||||
|
$target_file = preg_replace( '|\.pot?|', "-{$locale}.po", $argv[2] );
|
||||||
|
} else {
|
||||||
|
$target_file = $argv[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a .pot file into an array.
|
||||||
|
*
|
||||||
|
* @param string $file_name Pot file name.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function woocommerce_admin_parse_pot( $file_name ) {
|
||||||
|
$fh = fopen( $file_name, 'r' );
|
||||||
|
$originals = array();
|
||||||
|
$references = array();
|
||||||
|
$messages = array();
|
||||||
|
$have_msgid = false;
|
||||||
|
|
||||||
|
while ( ! feof( $fh ) ) {
|
||||||
|
$line = trim( fgets( $fh ) );
|
||||||
|
if ( ! $line ) {
|
||||||
|
$message = implode( "\n", $messages );
|
||||||
|
$originals[ $message ] = $references;
|
||||||
|
$references = array();
|
||||||
|
$messages = array();
|
||||||
|
$have_msgid = false;
|
||||||
|
$message = '';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 'msgid' == substr( $line, 0, 5 ) ) {
|
||||||
|
$have_msgid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $have_msgid ) {
|
||||||
|
$messages[] = $line;
|
||||||
|
} else {
|
||||||
|
$references[] = $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose( $fh );
|
||||||
|
|
||||||
|
$message = implode( "\n", $messages );
|
||||||
|
$originals[ $message ] = $references;
|
||||||
|
return $originals;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the translation files.
|
||||||
|
$originals_1 = woocommerce_admin_parse_pot( $argv[1] );
|
||||||
|
$originals_2 = woocommerce_admin_parse_pot( $argv[2] );
|
||||||
|
// Delete the original sources.
|
||||||
|
unlink( $argv[1] );
|
||||||
|
unlink( $argv[2] );
|
||||||
|
// We don't want two .pot headers in the output.
|
||||||
|
array_shift( $originals_1 );
|
||||||
|
|
||||||
|
$fh = fopen( $target_file, 'w' );
|
||||||
|
foreach ( $originals_2 as $message => $original ) {
|
||||||
|
// Use the complete message section to match strings to be translated.
|
||||||
|
if ( isset( $originals_1[ $message ] ) ) {
|
||||||
|
$original = array_merge( $original, $originals_1[ $message ] );
|
||||||
|
unset( $originals_1[ $message ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite( $fh, implode( "\n", $original ) );
|
||||||
|
fwrite( $fh, "\n" . $message ."\n\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $originals_1 as $message => $original ) {
|
||||||
|
fwrite( $fh, implode( "\n", $original ) );
|
||||||
|
fwrite( $fh, "\n" . $message ."\n\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose( $fh );
|
||||||
|
|
||||||
|
echo "Created {$target_file}\n";
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true,
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "7.5.20"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"platform": {
|
||||||
|
"php": "7.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Generates an array of feature flags, based on the config used by the client application.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Admin
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get phase for feature flags
|
||||||
|
* - development: All features should be enabled in development.
|
||||||
|
* - plugin: For the standalone feature plugin, for GitHub and WordPress.org.
|
||||||
|
* - core: Stable features for WooCommerce core merge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$phase = getenv( 'WC_ADMIN_PHASE' );
|
||||||
|
|
||||||
|
if ( ! in_array( $phase, array( 'development', 'plugin', 'core' ), true ) ) {
|
||||||
|
$phase = 'plugin'; // Default to plugin when running `pnpm run build`.
|
||||||
|
}
|
||||||
|
$config_json = file_get_contents( 'config/' . $phase . '.json' );
|
||||||
|
$config = json_decode( $config_json );
|
||||||
|
|
||||||
|
$write = "<?php\n";
|
||||||
|
$write .= "// WARNING: Do not directly edit this file.\n";
|
||||||
|
$write .= "// This file is auto-generated as part of the build process and things may break.\n";
|
||||||
|
$write .= "if ( ! function_exists( 'wc_admin_get_feature_config' ) ) {\n";
|
||||||
|
$write .= "\tfunction wc_admin_get_feature_config() {\n";
|
||||||
|
$write .= "\t\treturn array(\n";
|
||||||
|
foreach ( $config->features as $feature => $bool ) {
|
||||||
|
$write .= "\t\t\t'{$feature}' => " . ( $bool ? 'true' : 'false' ) . ",\n";
|
||||||
|
}
|
||||||
|
$write .= "\t\t);\n";
|
||||||
|
$write .= "\t}\n";
|
||||||
|
$write .= "}\n";
|
||||||
|
|
||||||
|
$config_file = fopen( 'includes/feature-config.php', 'w' );
|
||||||
|
|
||||||
|
fwrite( $config_file, $write );
|
||||||
|
fclose( $config_file );
|
|
@ -0,0 +1,145 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
RELEASER_PATH=$(pwd)
|
||||||
|
PLUGIN_SLUG="woocommerce-admin"
|
||||||
|
GITHUB_ORG="woocommerce"
|
||||||
|
# wc-admin is always pre-release for now
|
||||||
|
IS_PRE_RELEASE=true
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
# Check if string contains substring
|
||||||
|
is_substring() {
|
||||||
|
case "$2" in
|
||||||
|
*$1*)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Output colorized strings
|
||||||
|
#
|
||||||
|
# Color codes:
|
||||||
|
# 0 - black
|
||||||
|
# 1 - red
|
||||||
|
# 2 - green
|
||||||
|
# 3 - yellow
|
||||||
|
# 4 - blue
|
||||||
|
# 5 - magenta
|
||||||
|
# 6 - cian
|
||||||
|
# 7 - white
|
||||||
|
output() {
|
||||||
|
echo "$(tput setaf "$1")$2$(tput sgr0)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! [ -x "$(command -v hub)" ]; then
|
||||||
|
echo 'Error: hub is not installed. Install from https://github.com/github/hub' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Release script
|
||||||
|
echo
|
||||||
|
output 5 "wc-admin->GitHub RELEASE SCRIPT"
|
||||||
|
output 5 "============================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ $1 == '' || $2 == '' ]]
|
||||||
|
then
|
||||||
|
output 1 "Please supply a tag and zip file name"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
printf "This script will build files and create a tag on GitHub based on your local branch."
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
printf "Built files will reflect feature flag configs for Core."
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
printf "The /dist/ directory will also be pushed to the tagged release."
|
||||||
|
echo
|
||||||
|
if [ $DRY_RUN ]; then
|
||||||
|
output 2 "This is a dry run, only the zip will be generated."
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "Before proceeding:"
|
||||||
|
echo " • Ensure you have checked out the branch you wish to release"
|
||||||
|
echo " • Ensure you have committed/pushed all local changes"
|
||||||
|
echo " • Did you remember to update changelogs, the readme and plugin files?"
|
||||||
|
echo " • Are there any changes needed to the readme file?"
|
||||||
|
echo " • If you are running this script directly instead of via '$ pnpm run build:release', ensure you have built assets and installed composer in --no-dev mode."
|
||||||
|
echo
|
||||||
|
output 3 "Do you want to continue? [y/N]: "
|
||||||
|
read -r PROCEED
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ "$(echo "${PROCEED:-n}" | tr "[:upper:]" "[:lower:]")" != "y" ]; then
|
||||||
|
output 1 "Release cancelled!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION=$1
|
||||||
|
ZIP_FILE=$2
|
||||||
|
|
||||||
|
CURRENTBRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
|
||||||
|
if [ ! -d "dist" ]; then
|
||||||
|
output 3 "Dist directory not found. Aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
output 2 "Starting release to GitHub..."
|
||||||
|
echo
|
||||||
|
|
||||||
|
BRANCH="build/${VERSION}"
|
||||||
|
|
||||||
|
NOOP_ARG=""
|
||||||
|
DRY_RUN_ARG=""
|
||||||
|
if [ $DRY_RUN ]; then
|
||||||
|
NOOP_ARG="--noop"
|
||||||
|
DRY_RUN_ARG="--dry-run"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a release branch.
|
||||||
|
git checkout -b $BRANCH
|
||||||
|
|
||||||
|
# Force add feature-config.php
|
||||||
|
git add includes/feature-config.php --force $DRY_RUN_ARG
|
||||||
|
git add . $DRY_RUN_ARG
|
||||||
|
git commit -m "Adding feature-config.php directory to release" --no-verify $DRY_RUN_ARG
|
||||||
|
|
||||||
|
# Force add language files
|
||||||
|
git add languages/woocommerce-admin.pot --force $DRY_RUN_ARG
|
||||||
|
git add . $DRY_RUN_ARG
|
||||||
|
git commit -m "Adding translations to release" --no-verify $DRY_RUN_ARG
|
||||||
|
|
||||||
|
# Force add build directory and commit.
|
||||||
|
git add dist/. --force $DRY_RUN_ARG
|
||||||
|
git add . $DRY_RUN_ARG
|
||||||
|
git commit -m "Adding /dist directory to release" --no-verify $DRY_RUN_ARG
|
||||||
|
|
||||||
|
# Force add vendor directory and commit.
|
||||||
|
git add vendor/. --force $DRY_RUN_ARG
|
||||||
|
git add . $DRY_RUN_ARG
|
||||||
|
git commit -m "Adding /vendor directory to release" --no-verify $DRY_RUN_ARG
|
||||||
|
|
||||||
|
# Push branch upstream
|
||||||
|
git push origin $BRANCH $DRY_RUN_ARG
|
||||||
|
|
||||||
|
# Create the zip archive
|
||||||
|
./bin/make-zip.sh $ZIP_FILE
|
||||||
|
|
||||||
|
# Create the new release.
|
||||||
|
if [ $IS_PRE_RELEASE = true ]; then
|
||||||
|
hub $NOOP_ARG release create -m $VERSION -m "Release of version $VERSION. See readme.txt for details." -t $BRANCH --prerelease "v${VERSION}" --attach "${ZIP_FILE}"
|
||||||
|
else
|
||||||
|
hub $NOOP_ARG release create -m $VERSION -m "Release of version $VERSION. See readme.txt for details." -t $BRANCH "v${VERSION}" --attach "${ZIP_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git checkout $CURRENTBRANCH
|
||||||
|
git branch -D $BRANCH
|
||||||
|
git push origin --delete $BRANCH $DRY_RUN_ARG
|
||||||
|
|
||||||
|
output 2 "GitHub release complete."
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Hook Reference Generator
|
||||||
|
|
||||||
|
Compile a publishable JSON object of WooCommerce's JavaScript filters and slotFill entry points.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Generate a new reference found at `bin/hook-reference/data.json` by running the following command.
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm run create-hook-reference
|
||||||
|
```
|
||||||
|
|
||||||
|
The data includes references to code in the Github repository by commit hash, so it is essential to commit the resulting data in a pull request to `main` so code references are publicly available.
|
||||||
|
|
||||||
|
## DocBlock Requirements
|
||||||
|
|
||||||
|
JavaScript documentation blocks require certain fields in order to be included in the reference.
|
||||||
|
|
||||||
|
### Filter
|
||||||
|
|
||||||
|
| Tag | Description |
|
||||||
|
| --------- | -------------------------------------------------- |
|
||||||
|
| `@filter` | Filter string used as `addFilter`'s first argument |
|
||||||
|
|
||||||
|
### SlotFill
|
||||||
|
|
||||||
|
| Tag | Description |
|
||||||
|
| ----------- | ------------------------- |
|
||||||
|
| `@slotFill` | The fill component's name |
|
|
@ -0,0 +1,104 @@
|
||||||
|
const { readFile } = require( 'fs' ).promises;
|
||||||
|
const exec = require( 'await-exec' );
|
||||||
|
const { parse } = require( 'comment-parser/lib' );
|
||||||
|
const { relative, resolve } = require( 'path' );
|
||||||
|
const chalk = require( 'chalk' );
|
||||||
|
|
||||||
|
const dataTypes = [ 'action', 'filter', 'slotFill' ];
|
||||||
|
|
||||||
|
const getHooks = ( parsedData ) =>
|
||||||
|
parsedData.filter( ( docBlock ) =>
|
||||||
|
docBlock.tags.some( ( tag ) => dataTypes.includes( tag.tag ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
const getSourceFile = ( file, commit, { source } ) => {
|
||||||
|
const first = source[ 0 ].number + 1;
|
||||||
|
const last = source[ source.length - 1 ].number + 1;
|
||||||
|
|
||||||
|
return `https://github.com/woocommerce/woocommerce-admin/blob/${ commit }/${ file }#L${ first }-L${ last }`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const logProgress = ( fileName, { tags } ) => {
|
||||||
|
const hook = tags.find( ( tag ) => dataTypes.includes( tag.tag ) );
|
||||||
|
console.log(
|
||||||
|
chalk.green( `@${ hook.tag } ` ) +
|
||||||
|
chalk.cyan( `${ hook.name } ` ) +
|
||||||
|
chalk.yellow( 'generated in ' ) +
|
||||||
|
chalk.yellow.underline( fileName )
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addSourceFiles = async ( hooks, fileName ) => {
|
||||||
|
const { stdout } = await exec( 'git log --pretty="format:%H" -1' );
|
||||||
|
const commit = stdout.trim();
|
||||||
|
|
||||||
|
return hooks.map( ( hook ) => {
|
||||||
|
logProgress( fileName, hook );
|
||||||
|
hook.sourceFile = getSourceFile( fileName, commit, hook );
|
||||||
|
return hook;
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
const prepareHooks = async ( path ) => {
|
||||||
|
const data = await readFile( path, 'utf-8' ).catch( ( err ) =>
|
||||||
|
console.error( 'Failed to read file', err )
|
||||||
|
);
|
||||||
|
const fileName = relative( resolve( __dirname, '../../' ), path );
|
||||||
|
|
||||||
|
const parsedData = parse( data );
|
||||||
|
const rawHooks = getHooks( parsedData );
|
||||||
|
return await addSourceFiles( rawHooks, fileName );
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeDocObjects = async ( path ) => {
|
||||||
|
const hooks = await prepareHooks( path );
|
||||||
|
return hooks.map( ( { description, tags, sourceFile } ) => {
|
||||||
|
const tag = tags.find( ( tag ) => dataTypes.includes( tag.tag ) );
|
||||||
|
|
||||||
|
paramTags = tags.reduce(
|
||||||
|
( result, { tag, name, type, description } ) => {
|
||||||
|
if ( tag === 'param' ) {
|
||||||
|
result.push( {
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
description,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const docObject = {
|
||||||
|
description,
|
||||||
|
sourceFile,
|
||||||
|
name: tag ? tag.name : '',
|
||||||
|
type: tag.tag,
|
||||||
|
params: paramTags,
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( tag.tag === 'slotFill' ) {
|
||||||
|
const scopeTab = tags.find( ( tag ) => tag.tag === 'scope' );
|
||||||
|
if ( scopeTab ) {
|
||||||
|
docObject.scope = scopeTab.name;
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
`Failed to find "scope" tag for slotFill "${ tag.name }" doc.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return docObject;
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
const createData = async ( paths ) => {
|
||||||
|
const data = await Promise.all(
|
||||||
|
paths.map( async ( path ) => {
|
||||||
|
return await makeDocObjects( path );
|
||||||
|
} )
|
||||||
|
);
|
||||||
|
return data.flat();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = createData;
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,58 @@
|
||||||
|
const { stat, readdir, writeFile } = require( 'fs' ).promises;
|
||||||
|
const { resolve } = require( 'path' );
|
||||||
|
const createData = require( './data' );
|
||||||
|
const chalk = require( 'chalk' );
|
||||||
|
|
||||||
|
async function getFilePaths( dir ) {
|
||||||
|
const subdirs = await readdir( dir );
|
||||||
|
const files = await Promise.all(
|
||||||
|
subdirs.map( async ( subdir ) => {
|
||||||
|
const res = resolve( dir, subdir );
|
||||||
|
const _stat = await stat( res );
|
||||||
|
const isDir = _stat.isDirectory();
|
||||||
|
const isNotSourceDir =
|
||||||
|
isDir &&
|
||||||
|
/\/(build|build-module|build-style|node_modules)$/g.test( res );
|
||||||
|
|
||||||
|
if ( isNotSourceDir ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isDir ? getFilePaths( res ) : res;
|
||||||
|
} )
|
||||||
|
);
|
||||||
|
return files
|
||||||
|
.filter( ( f ) => !! f )
|
||||||
|
.reduce( ( a, f ) => a.concat( f ), [] );
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllFilePaths( paths ) {
|
||||||
|
const allFiles = await Promise.all(
|
||||||
|
paths.map( async ( path ) => {
|
||||||
|
return await getFilePaths( path );
|
||||||
|
} )
|
||||||
|
);
|
||||||
|
|
||||||
|
return allFiles.reduce( ( a, f ) => a.concat( f ), [] );
|
||||||
|
}
|
||||||
|
|
||||||
|
const writeJSONFile = async ( data ) => {
|
||||||
|
const fileName = 'bin/hook-reference/data.json';
|
||||||
|
const stringifiedData = JSON.stringify( data, null, 4 );
|
||||||
|
await writeFile( fileName, stringifiedData + '\n' );
|
||||||
|
|
||||||
|
console.log( '\n' );
|
||||||
|
console.log(
|
||||||
|
chalk.greenBright(
|
||||||
|
'A new Hook Reference data source has been created. See `/bin/hook-reference/data.json` and be sure to commit changes.'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log( chalk.green( 'Preparing Hook Reference data file' ) );
|
||||||
|
console.log( '\n' );
|
||||||
|
|
||||||
|
getAllFilePaths( [ 'client', 'packages' ] )
|
||||||
|
.then( ( paths ) => createData( paths ) )
|
||||||
|
.then( ( data ) => writeJSONFile( data ) )
|
||||||
|
.catch( ( e ) => console.error( e ) );
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
STORYBOOK_WORDPRESS_DIR="$DIR/../storybook/wordpress";
|
||||||
|
STORY_BOOK_CSS_PATH="$DIR/../storybook/wordpress/css";
|
||||||
|
TMP_DIR="$DIR/../storybook/wordpress/tmp";
|
||||||
|
ARCHIVE_CSS_PATH="wordpress/wp-admin/css";
|
||||||
|
ARCHIVE_IMG_PATH="wordpress/wp-admin/images";
|
||||||
|
|
||||||
|
mkdir -p "$STORY_BOOK_CSS_PATH";
|
||||||
|
mkdir -p "$TMP_DIR";
|
||||||
|
|
||||||
|
function download_and_extract_css {
|
||||||
|
curl -o "$STORYBOOK_WORDPRESS_DIR/wordpress-latest.zip" https://wordpress.org/nightly-builds/wordpress-latest.zip;
|
||||||
|
unzip -qq "$STORYBOOK_WORDPRESS_DIR/wordpress-latest.zip" "$ARCHIVE_CSS_PATH/*" "$ARCHIVE_IMG_PATH/*" -d "$TMP_DIR";
|
||||||
|
rsync -a "$TMP_DIR/$ARCHIVE_CSS_PATH" "$STORYBOOK_WORDPRESS_DIR";
|
||||||
|
rsync -a "$TMP_DIR/$ARCHIVE_IMG_PATH" "$STORYBOOK_WORDPRESS_DIR";
|
||||||
|
rm -r "$TMP_DIR";
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "$(find "$STORY_BOOK_CSS_PATH" -iname '*.css')" ] || [ "$1" == "-f" ]
|
||||||
|
then
|
||||||
|
# The directory is not empty, import css
|
||||||
|
download_and_extract_css;
|
||||||
|
else
|
||||||
|
echo "Wordpress CSS already imported, pass -f to force an update";
|
||||||
|
fi
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an `pnpm install`. Since that's a costly operation,
|
||||||
|
* it will only perform it if needed, that is, if the packages
|
||||||
|
* installed at `node_modules` aren't in sync over what
|
||||||
|
* `package-lock.json` has. For that, modification times of both
|
||||||
|
* files will be compared. If the package-lock is newer, it means that
|
||||||
|
* the packages at node_modules may be outdated. That will happen,
|
||||||
|
* for example, when switching branches.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require( 'fs' );
|
||||||
|
const spawnSync = require( 'child_process' ).spawnSync;
|
||||||
|
|
||||||
|
const needsInstall = () => {
|
||||||
|
try {
|
||||||
|
const shrinkwrapTime = fs.statSync( 'pnpm-lock.yaml' ).mtime;
|
||||||
|
const nodeModulesTime = fs.statSync( 'node_modules' ).mtime;
|
||||||
|
return shrinkwrapTime - nodeModulesTime > 1000; // In Windows, directory mtime has less precision than file mtime
|
||||||
|
} catch ( e ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( needsInstall() ) {
|
||||||
|
const installResult = spawnSync( 'pnpm', [ 'install' ], {
|
||||||
|
shell: true,
|
||||||
|
stdio: 'inherit',
|
||||||
|
} ).status;
|
||||||
|
|
||||||
|
if ( installResult ) {
|
||||||
|
process.exit( installResult );
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.utimesSync( 'node_modules', new Date(), new Date() );
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
const spawnSync = require( 'child_process' ).spawnSync;
|
||||||
|
const fs = require( 'fs' );
|
||||||
|
|
||||||
|
if ( ! fs.existsSync( 'node_modules' ) ) {
|
||||||
|
console.log( 'No "node_modules" present, installing dependencies...' );
|
||||||
|
const installResult = spawnSync( 'pnpm', [ 'install' ], {
|
||||||
|
shell: true,
|
||||||
|
stdio: 'inherit',
|
||||||
|
} ).status;
|
||||||
|
if ( installResult ) {
|
||||||
|
process.exit( installResult );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,231 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DB_NAME=$1
|
||||||
|
DB_USER=$2
|
||||||
|
DB_PASS=$3
|
||||||
|
DB_HOST=${4-localhost}
|
||||||
|
WP_VERSION=${5-latest}
|
||||||
|
SKIP_DB_CREATE=${6-false}
|
||||||
|
|
||||||
|
TMPDIR=${TMPDIR-/tmp}
|
||||||
|
TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//")
|
||||||
|
WP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib}
|
||||||
|
WP_CORE_DIR=${WP_CORE_DIR-$TMPDIR/wordpress/}
|
||||||
|
|
||||||
|
download() {
|
||||||
|
if [ `which curl` ]; then
|
||||||
|
curl -s "$1" > "$2";
|
||||||
|
elif [ `which wget` ]; then
|
||||||
|
wget -nv -O "$2" "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
WP_TESTS_TAG="branches/$WP_VERSION"
|
||||||
|
elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
||||||
|
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then
|
||||||
|
# version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x
|
||||||
|
WP_TESTS_TAG="tags/${WP_VERSION%??}"
|
||||||
|
else
|
||||||
|
WP_TESTS_TAG="tags/$WP_VERSION"
|
||||||
|
fi
|
||||||
|
elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
|
||||||
|
WP_TESTS_TAG="trunk"
|
||||||
|
else
|
||||||
|
# http serves a single offer, whereas https serves multiple. we only want one
|
||||||
|
download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
|
||||||
|
grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
|
||||||
|
LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
|
||||||
|
if [[ -z "$LATEST_VERSION" ]]; then
|
||||||
|
echo "Latest WordPress version could not be found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
WP_TESTS_TAG="tags/$LATEST_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
install_wp() {
|
||||||
|
|
||||||
|
if [ -d $WP_CORE_DIR ]; then
|
||||||
|
return;
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $WP_CORE_DIR
|
||||||
|
|
||||||
|
if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
|
||||||
|
mkdir -p $TMPDIR/wordpress-nightly
|
||||||
|
download https://wordpress.org/nightly-builds/wordpress-latest.zip $TMPDIR/wordpress-nightly/wordpress-nightly.zip
|
||||||
|
unzip -q $TMPDIR/wordpress-nightly/wordpress-nightly.zip -d $TMPDIR/wordpress-nightly/
|
||||||
|
mv $TMPDIR/wordpress-nightly/wordpress/* $WP_CORE_DIR
|
||||||
|
else
|
||||||
|
if [ $WP_VERSION == 'latest' ]; then
|
||||||
|
local ARCHIVE_NAME='latest'
|
||||||
|
elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+ ]]; then
|
||||||
|
# https serves multiple offers, whereas http serves single.
|
||||||
|
download https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json
|
||||||
|
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then
|
||||||
|
# version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x
|
||||||
|
LATEST_VERSION=${WP_VERSION%??}
|
||||||
|
else
|
||||||
|
# otherwise, scan the releases and get the most up to date minor version of the major release
|
||||||
|
local VERSION_ESCAPED=`echo $WP_VERSION | sed 's/\./\\\\./g'`
|
||||||
|
LATEST_VERSION=$(grep -o '"version":"'$VERSION_ESCAPED'[^"]*' $TMPDIR/wp-latest.json | sed 's/"version":"//' | head -1)
|
||||||
|
fi
|
||||||
|
if [[ -z "$LATEST_VERSION" ]]; then
|
||||||
|
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
||||||
|
else
|
||||||
|
local ARCHIVE_NAME="wordpress-$LATEST_VERSION"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
||||||
|
fi
|
||||||
|
download https://wordpress.org/${ARCHIVE_NAME}.tar.gz $TMPDIR/wordpress.tar.gz
|
||||||
|
tar --strip-components=1 -zxmf $TMPDIR/wordpress.tar.gz -C $WP_CORE_DIR
|
||||||
|
fi
|
||||||
|
|
||||||
|
download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
|
||||||
|
}
|
||||||
|
|
||||||
|
install_test_suite() {
|
||||||
|
# portable in-place argument for both GNU sed and Mac OSX sed
|
||||||
|
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||||
|
local ioption='-i .bak'
|
||||||
|
else
|
||||||
|
local ioption='-i'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# removes testing suite
|
||||||
|
rm -rf $WP_TESTS_DIR
|
||||||
|
|
||||||
|
# set up testing suite
|
||||||
|
mkdir -p $WP_TESTS_DIR
|
||||||
|
svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
|
||||||
|
svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data
|
||||||
|
|
||||||
|
if [ ! -f wp-tests-config.php ]; then
|
||||||
|
download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
# remove all forward slashes in the end
|
||||||
|
WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::")
|
||||||
|
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
install_db() {
|
||||||
|
|
||||||
|
if [ ${SKIP_DB_CREATE} = "true" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# parse DB_HOST for port or socket references
|
||||||
|
local PARTS=(${DB_HOST//\:/ })
|
||||||
|
local DB_HOSTNAME=${PARTS[0]};
|
||||||
|
local DB_SOCK_OR_PORT=${PARTS[1]};
|
||||||
|
local EXTRA=""
|
||||||
|
|
||||||
|
if ! [ -z $DB_HOSTNAME ] ; then
|
||||||
|
if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
|
||||||
|
EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
|
||||||
|
elif ! [ -z $DB_SOCK_OR_PORT ] ; then
|
||||||
|
EXTRA=" --socket=$DB_SOCK_OR_PORT"
|
||||||
|
elif ! [ -z $DB_HOSTNAME ] ; then
|
||||||
|
EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# drop existing database
|
||||||
|
mysqladmin drop -f $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA 2>/dev/null || true
|
||||||
|
|
||||||
|
# create database
|
||||||
|
mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
|
||||||
|
}
|
||||||
|
|
||||||
|
version() {
|
||||||
|
# convert version numbers to digits
|
||||||
|
echo "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }';
|
||||||
|
}
|
||||||
|
|
||||||
|
install_deps() {
|
||||||
|
|
||||||
|
# Script Variables
|
||||||
|
WP_SITE_URL="http://local.wordpress.test"
|
||||||
|
WORKING_DIR="$PWD"
|
||||||
|
|
||||||
|
# Set up WordPress using wp-cli
|
||||||
|
mkdir -p "$WP_CORE_DIR"
|
||||||
|
cd "$WP_CORE_DIR"
|
||||||
|
|
||||||
|
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||||
|
|
||||||
|
# delete existing wp-config and woocommerce repository
|
||||||
|
rm -f wp-config.php
|
||||||
|
rm -rf wp-content/plugins/woocommerce
|
||||||
|
|
||||||
|
php wp-cli.phar core config --dbname=$DB_NAME --dbuser=$DB_USER --dbpass=$DB_PASS --dbhost=$DB_HOST --dbprefix=wptests_
|
||||||
|
php wp-cli.phar core install --url="$WP_SITE_URL" --title="Example" --admin_user=admin --admin_password=password --admin_email=info@example.com --path=$WP_CORE_DIR --skip-email
|
||||||
|
|
||||||
|
# Install WooCommerce (latest non-hyphenated (beta, RC) tag)
|
||||||
|
if [[ "$WC_VERSION" == "latest" ]]; then
|
||||||
|
INSTALL_WC_TAG="$(git ls-remote --tags https://github.com/woocommerce/woocommerce.git | awk '{print $2}' | sed 's/^refs\/tags\///' | grep -E '^[0-9]\.[0-9]\.[0-9]$' | sort -V | tail -n 1)"
|
||||||
|
else
|
||||||
|
INSTALL_WC_TAG="$WC_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# As zip file does not include tests, we have to get it from git repo.
|
||||||
|
git clone --depth 1 --branch $INSTALL_WC_TAG https://github.com/woocommerce/woocommerce.git
|
||||||
|
|
||||||
|
if [ "$(version "$INSTALL_WC_TAG")" -ge "$(version "6.0.0")" ]; then
|
||||||
|
# WooCommerce 6.0.0 introduced a breaking change to the repo structure.
|
||||||
|
# We need to clone and use the correct folder path.
|
||||||
|
mv woocommerce/plugins/woocommerce wp-content/plugins/
|
||||||
|
else
|
||||||
|
mv woocommerce wp-content/plugins/
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "wp-content/plugins/"
|
||||||
|
# Bring in WooCommerce Core dependencies
|
||||||
|
cd "woocommerce"
|
||||||
|
composer install --no-dev
|
||||||
|
|
||||||
|
cd "$WP_CORE_DIR"
|
||||||
|
php wp-cli.phar plugin activate woocommerce
|
||||||
|
|
||||||
|
# Install woocommerce-admin, the correct branch, if running from Travis CI.
|
||||||
|
if [ "${TRAVIS}" = "true" ]; then
|
||||||
|
# Default to the pull request branch if this is a PR, otherwise pushed branch.
|
||||||
|
BRANCH=${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}
|
||||||
|
# Default to the pull request repo if this is a PR, otherwise default.
|
||||||
|
REPO=${TRAVIS_PULL_REQUEST_SLUG:-$TRAVIS_REPO_SLUG}
|
||||||
|
BRANCH="$(sed 's/#/%23/' <<<$BRANCH)"
|
||||||
|
# Checkout plugin via Git so all files are gathered.
|
||||||
|
cd "$WP_CORE_DIR/wp-content/plugins"
|
||||||
|
git clone https://github.com/$REPO.git
|
||||||
|
cd woocommerce-admin
|
||||||
|
git fetch origin $BRANCH
|
||||||
|
git checkout -B $BRANCH origin/$BRANCH
|
||||||
|
# Activate the plugin
|
||||||
|
cd "$WP_CORE_DIR"
|
||||||
|
php wp-cli.phar plugin activate woocommerce-admin
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Back to original dir
|
||||||
|
cd "$WORKING_DIR"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
install_wp
|
||||||
|
install_test_suite
|
||||||
|
install_db
|
||||||
|
install_deps
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
|
||||||
|
pnpm run -s install-if-deps-outdated
|
||||||
|
pnpm run lint
|
||||||
|
pnpm run build
|
||||||
|
pnpm test
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Check for required version
|
||||||
|
WPCLI_VERSION=`wp cli version | cut -f2 -d' '`
|
||||||
|
if [ ${WPCLI_VERSION:0:1} -lt "2" -o ${WPCLI_VERSION:0:1} -eq "2" -a ${WPCLI_VERSION:2:1} -lt "1" ]; then
|
||||||
|
echo WP-CLI version 2.1.0 or greater is required to make JSON translation files
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Substitute JS source references with build references
|
||||||
|
for T in `find languages -name "*.po"`
|
||||||
|
do
|
||||||
|
sed \
|
||||||
|
-e 's/ client\/[^:]*:/ dist\/app\/index.js:/gp' \
|
||||||
|
-e 's/ packages\/components[^:]*:/ dist\/components\/index.js:/gp' \
|
||||||
|
-e 's/ packages\/date[^:]*:/ dist\/date\/index.js:/gp' \
|
||||||
|
$T | uniq > $T-build
|
||||||
|
rm $T
|
||||||
|
mv $T-build $T
|
||||||
|
done
|
||||||
|
|
||||||
|
# Make the JSON files
|
||||||
|
wp i18n make-json languages --no-purge
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Build a installable plugin zip
|
||||||
|
|
||||||
|
# Output colorized strings
|
||||||
|
#
|
||||||
|
# Color codes:
|
||||||
|
# 0 - black
|
||||||
|
# 1 - red
|
||||||
|
# 2 - green
|
||||||
|
# 3 - yellow
|
||||||
|
# 4 - blue
|
||||||
|
# 5 - magenta
|
||||||
|
# 6 - cian
|
||||||
|
# 7 - white
|
||||||
|
output() {
|
||||||
|
echo "$(tput setaf "$1")$2$(tput sgr0)"
|
||||||
|
}
|
||||||
|
|
||||||
|
output 2 "Creating archive... 🎁"
|
||||||
|
|
||||||
|
ZIP_FILE=$1
|
||||||
|
|
||||||
|
build_files=$(find dist \( -name '*.js' -o -name '*.css' \))
|
||||||
|
asset_files=$(find dist \( -name '*.asset.php' \))
|
||||||
|
if [[ $(find dist/app \( -name '*.asset.php' \) | wc -l) -gt 1 ]]; then
|
||||||
|
output 3 "$asset_files"
|
||||||
|
output 1 "Multiple asset.php files exists per directory, have you removed the old build?"
|
||||||
|
exit;
|
||||||
|
fi
|
||||||
|
|
||||||
|
zip -r "${ZIP_FILE}" \
|
||||||
|
woocommerce-admin.php \
|
||||||
|
uninstall.php \
|
||||||
|
includes/ \
|
||||||
|
images/ \
|
||||||
|
$build_files \
|
||||||
|
$asset_files \
|
||||||
|
languages/woocommerce-admin.pot \
|
||||||
|
readme.txt \
|
||||||
|
changelog.txt \
|
||||||
|
src/ \
|
||||||
|
vendor/ \
|
||||||
|
src-internal/
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
PHP_FILES_CHANGED=""
|
||||||
|
|
||||||
|
for FILE in $(echo $CHANGED_FILES | tr ',' '\n')
|
||||||
|
do
|
||||||
|
if [[ $FILE =~ ".php" && -e $FILE ]]; then
|
||||||
|
PHP_FILES_CHANGED+="$FILE "
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$PHP_FILES_CHANGED" != "" ]; then
|
||||||
|
composer install
|
||||||
|
echo "Running Code Sniffer."
|
||||||
|
./vendor/bin/phpcs --encoding=utf-8 -n -p $PHP_FILES_CHANGED
|
||||||
|
else
|
||||||
|
echo "No changed files detected, sniffer not run."
|
||||||
|
fi
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
WORKING_DIR="$PWD"
|
||||||
|
cd "$WP_CORE_DIR/wp-content/plugins/woocommerce-admin/"
|
||||||
|
if [[ {$COMPOSER_DEV} == 1 || "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]]; then
|
||||||
|
./vendor/bin/phpunit --version
|
||||||
|
if [[ {$RUN_RANDOM} == 1 ]]; then
|
||||||
|
./vendor/bin/phpunit -c phpunit.xml.dist --order-by=random
|
||||||
|
else
|
||||||
|
./vendor/bin/phpunit -c phpunit.xml.dist
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
phpunit --version
|
||||||
|
phpunit -c phpunit.xml.dist
|
||||||
|
fi
|
||||||
|
TEST_RESULT=$?
|
||||||
|
cd "$WORKING_DIR"
|
||||||
|
exit $TEST_RESULT
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const execSync = require( 'child_process' ).execSync;
|
||||||
|
const readline = require( 'readline-sync' );
|
||||||
|
|
||||||
|
console.log( '\nBy contributing to this project, you license the materials you contribute ' +
|
||||||
|
'under the GNU General Public License v2 (or later). All materials must have ' +
|
||||||
|
'GPLv2 compatible licenses — see .github/CONTRIBUTING.md for details.\n\n' );
|
||||||
|
|
||||||
|
const currentBranch = execSync( 'git rev-parse --abbrev-ref HEAD' ).toString().trim();
|
||||||
|
|
||||||
|
if ( 'main' === currentBranch ) {
|
||||||
|
if ( ! readline.keyInYN( "You're about to push !!![ main ]!!!, is that what you intended?" ) ) {
|
||||||
|
process.exit( 1 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Enable nicer messaging for build status.
|
||||||
|
BLUE_BOLD='\033[1;34m';
|
||||||
|
GREEN_BOLD='\033[1;32m';
|
||||||
|
RED_BOLD='\033[1;31m';
|
||||||
|
YELLOW_BOLD='\033[1;33m';
|
||||||
|
COLOR_RESET='\033[0m';
|
||||||
|
|
||||||
|
error () {
|
||||||
|
echo -e "\n🤯 ${RED_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
status () {
|
||||||
|
echo -e "\n👩💻 ${BLUE_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
success () {
|
||||||
|
echo -e "\n✅ ${GREEN_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
warning () {
|
||||||
|
echo -e "\n${YELLOW_BOLD}$1${COLOR_RESET}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure there are no changes in the working tree.
|
||||||
|
changed=
|
||||||
|
if ! git diff --exit-code > /dev/null; then
|
||||||
|
changed="file(s) modified"
|
||||||
|
elif ! git diff --cached --exit-code > /dev/null; then
|
||||||
|
changed="file(s) staged"
|
||||||
|
fi
|
||||||
|
if [ ! -z "$changed" ]; then
|
||||||
|
git status
|
||||||
|
error "ERROR: Cannot start pre-release with dirty working tree. ☝️ Commit your changes and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
status "Lets release WooCommerce Admin 🎉"
|
||||||
|
|
||||||
|
status "What branch/commit would you like to base this release on?"
|
||||||
|
|
||||||
|
echo -n "Branch/commit: "
|
||||||
|
|
||||||
|
read refspec
|
||||||
|
|
||||||
|
git checkout $refspec || { error "ERROR: Unable to checkout ${refspec}." ; exit 1; }
|
||||||
|
|
||||||
|
success "Checked out ${refspec}"
|
||||||
|
|
||||||
|
git pull origin ${refspec}
|
||||||
|
|
||||||
|
success "Pulled latest commits"
|
||||||
|
|
||||||
|
status "What version would you like to release?"
|
||||||
|
|
||||||
|
echo -n "Version: "
|
||||||
|
|
||||||
|
read release
|
||||||
|
|
||||||
|
branch="release/${release}"
|
||||||
|
|
||||||
|
exists=`git show-ref refs/heads/${branch}`
|
||||||
|
|
||||||
|
if [ -n "$exists" ]; then
|
||||||
|
error "ERROR: release branch already exists."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
status "creating a release branch"
|
||||||
|
|
||||||
|
git checkout -b $branch || { error "ERROR: Unable to create release branch." ; exit 1; }
|
||||||
|
|
||||||
|
success "Release branch created: ${branch}"
|
||||||
|
|
||||||
|
status "Bumping version to ${release}"
|
||||||
|
|
||||||
|
pnpm --no-git-tag-version version $release || { error "ERROR: Invalid version number." ; exit 1; }
|
||||||
|
|
||||||
|
success "Version bumped successfully"
|
||||||
|
|
||||||
|
status "Run scripts to propagate version numbers and update dependencies."
|
||||||
|
|
||||||
|
pnpm run bump-version
|
||||||
|
|
||||||
|
status "Here are the changes so far. Make sure the following changes are reflected."
|
||||||
|
|
||||||
|
echo "- docs/: folder will have changes to documentation, if any."
|
||||||
|
echo "- package.json: new version number."
|
||||||
|
echo "- woocommerce-admin.php: new version number."
|
||||||
|
echo "- composer.json: new version number."
|
||||||
|
echo "- readme.txt: new version number."
|
||||||
|
echo "- src-internal/Admin/FeaturePlugin.php: new version number."
|
||||||
|
echo "- src/Composer/Package.php: new version number."
|
||||||
|
echo "- package-lock.json: dependencies updated."
|
||||||
|
echo -e "\n"
|
||||||
|
echo -e "\n"
|
||||||
|
|
||||||
|
git status
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
CURRENT_PATH=`pwd`
|
||||||
|
|
||||||
|
# Pull down the SVN repository.
|
||||||
|
echo "Pulling down the SVN repository for woocommerce-admin"
|
||||||
|
SVN_WOOCOMMERCE_ADMIN_PATH=/tmp/woocommerce/svn-woocommerce-admin
|
||||||
|
svn co https://plugins.svn.wordpress.org/woocommerce-admin/ $SVN_WOOCOMMERCE_ADMIN_PATH
|
||||||
|
cd $SVN_WOOCOMMERCE_ADMIN_PATH
|
||||||
|
|
||||||
|
# Get the tagged version to release.
|
||||||
|
echo "Please enter the version number to release to wordpress.org, for example, 1.0.0: "
|
||||||
|
read -r VERSION
|
||||||
|
|
||||||
|
# Empty trunk/.
|
||||||
|
rm -rf trunk
|
||||||
|
mkdir trunk
|
||||||
|
|
||||||
|
# Download and unzip the plugin into trunk/.
|
||||||
|
echo "Downloading and unzipping the plugin"
|
||||||
|
PLUGIN_URL=https://github.com/woocommerce/woocommerce-admin/releases/download/v${VERSION}-plugin/woocommerce-admin.zip
|
||||||
|
curl -Lo woocommerce-admin.zip $PLUGIN_URL
|
||||||
|
unzip woocommerce-admin.zip -d trunk
|
||||||
|
rm woocommerce-admin.zip
|
||||||
|
|
||||||
|
# Add files in trunk/ to SVN.
|
||||||
|
cd trunk
|
||||||
|
svn add --force .
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Commit the changes, which will automatically release the plugin to wordpress.org.
|
||||||
|
echo "Checking in the new version"
|
||||||
|
svn ci -m "Release v${VERSION}"
|
||||||
|
|
||||||
|
# Tag the release
|
||||||
|
echo "Tagging the release"
|
||||||
|
svn cp trunk tags/$VERSION
|
||||||
|
svn ci -m "Tagging v${VERSION}"
|
||||||
|
|
||||||
|
# Clean up.
|
||||||
|
cd ..
|
||||||
|
rm -rf svn-woocommerce-admin
|
||||||
|
|
||||||
|
cd $CURRENT_PATH
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
PR_PATTERNS=$(echo $1 | sed 's/[^,]*/\(#&)/g' | sed 's/,/\\|/g')
|
||||||
|
git log --pretty=format:'%ad,%s' --all --date=iso-local --author-date-order --reverse --grep "$PR_PATTERNS" | sort -u | grep -o '\(#[0-9]\+\)'
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||||
|
rules: {
|
||||||
|
// temporary conversion to warnings until the below are all handled.
|
||||||
|
'@wordpress/i18n-translator-comments': 'warn',
|
||||||
|
'@wordpress/valid-sprintf': 'warn',
|
||||||
|
'jsdoc/check-tag-names': [
|
||||||
|
'error',
|
||||||
|
{ definedTags: [ 'jest-environment' ] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
# Directories/files that may be generated by this project
|
||||||
|
node_modules/
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
build-module
|
||||||
|
build-style
|
||||||
|
languages/*
|
||||||
|
!languages/README.md
|
||||||
|
|
||||||
|
# Directories/files that may appear in your environment
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
wp-cli.local.yml
|
||||||
|
*.sql
|
||||||
|
*.tar.gz
|
||||||
|
*.tgz
|
||||||
|
*.zip
|
||||||
|
.idea
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Composer
|
||||||
|
/vendor/
|
|
@ -0,0 +1 @@
|
||||||
|
"@wordpress/prettier-config"
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Create Extension
|
||||||
|
|
||||||
|
Scaffold a modern JavaScript WordPress plugin with WooCommerce tooling.
|
||||||
|
|
||||||
|
## Includes
|
||||||
|
|
||||||
|
- [wp-scripts](https://github.com/WordPress/gutenberg/tree/master/packages/scripts)
|
||||||
|
- [WooCommerce Dependency Extraction Webpack Plugin](https://github.com/woocommerce/woocommerce-admin/tree/main/packages/dependency-extraction-webpack-plugin)
|
||||||
|
- [WooCommerce ESLint Plugin with WordPress Prettier](https://github.com/woocommerce/woocommerce-admin/tree/main/packages/eslint-plugin)
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
At the root of a [WooCommerce Admin](https://github.com/woocommerce/woocommerce-admin) installation, run the create extension command.
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm run create-wc-extension
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will create a sibling directory by a name of your choosing. Once you change directories into the new folder, install dependencies and start a development build.
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm install
|
||||||
|
pnpm start
|
||||||
|
```
|
|
@ -0,0 +1,15 @@
|
||||||
|
# {{extension_name}}
|
||||||
|
|
||||||
|
A WooCommerce Admin Extension
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
To get started, run the following commands:
|
||||||
|
|
||||||
|
```text
|
||||||
|
pnpm install
|
||||||
|
pnpm start
|
||||||
|
```
|
||||||
|
|
||||||
|
See [wp-scripts](https://github.com/WordPress/gutenberg/tree/master/packages/scripts) for more usage information.
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: {{extension_name}}
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Admin
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the JS.
|
||||||
|
*/
|
||||||
|
function add_extension_register_script() {
|
||||||
|
if ( ! class_exists( 'Automattic\WooCommerce\Admin\PageController' ) || ! \Automattic\WooCommerce\Admin\PageController::is_admin_or_embed_page() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$script_path = '/build/index.js';
|
||||||
|
$script_asset_path = dirname( __FILE__ ) . '/build/index.asset.php';
|
||||||
|
$script_asset = file_exists( $script_asset_path )
|
||||||
|
? require( $script_asset_path )
|
||||||
|
: array( 'dependencies' => array(), 'version' => filemtime( $script_path ) );
|
||||||
|
$script_url = plugins_url( $script_path, __FILE__ );
|
||||||
|
|
||||||
|
wp_register_script(
|
||||||
|
'{{extension_slug}}',
|
||||||
|
$script_url,
|
||||||
|
$script_asset['dependencies'],
|
||||||
|
$script_asset['version'],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_register_style(
|
||||||
|
'{{extension_slug}}',
|
||||||
|
plugins_url( '/build/index.css', __FILE__ ),
|
||||||
|
// Add any dependencies styles may have, such as wp-components.
|
||||||
|
array(),
|
||||||
|
filemtime( dirname( __FILE__ ) . '/build/index.css' )
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_script( '{{extension_slug}}' );
|
||||||
|
wp_enqueue_style( '{{extension_slug}}' );
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action( 'admin_enqueue_scripts', 'add_extension_register_script' );
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "{{extension_slug}}",
|
||||||
|
"title": "{{extension_name}}",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "{{extension_name}}",
|
||||||
|
"scripts": {
|
||||||
|
"build": "wp-scripts build",
|
||||||
|
"check-engines": "wp-scripts check-engines",
|
||||||
|
"check-licenses": "wp-scripts check-licenses",
|
||||||
|
"format:js": "wp-scripts format-js",
|
||||||
|
"lint:css": "wp-scripts lint-style",
|
||||||
|
"lint:js": "wp-scripts lint-js",
|
||||||
|
"lint:md:docs": "wp-scripts lint-md-docs",
|
||||||
|
"lint:md:js": "wp-scripts lint-md-js",
|
||||||
|
"lint:pkg-json": "wp-scripts lint-pkg-json",
|
||||||
|
"packages-update": "wp-scripts packages-update",
|
||||||
|
"start": "wp-scripts start",
|
||||||
|
"test:e2e": "wp-scripts test-e2e",
|
||||||
|
"test:unit": "wp-scripts test-unit-js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@wordpress/scripts": "^12.2.1",
|
||||||
|
"@woocommerce/eslint-plugin": "1.1.0",
|
||||||
|
"@woocommerce/dependency-extraction-webpack-plugin": "1.6.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
|
||||||
|
const WooCommerceDependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' );
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
...defaultConfig,
|
||||||
|
plugins: [
|
||||||
|
...defaultConfig.plugins.filter(
|
||||||
|
( plugin ) =>
|
||||||
|
plugin.constructor.name !== 'DependencyExtractionWebpackPlugin'
|
||||||
|
),
|
||||||
|
new WooCommerceDependencyExtractionWebpackPlugin(),
|
||||||
|
],
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Import SCSS entry file so that webpack picks up changes
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
console.log( 'hello world' );
|
|
@ -0,0 +1 @@
|
||||||
|
// Add styles here.
|
|
@ -0,0 +1,89 @@
|
||||||
|
const fs = require( 'fs-extra' );
|
||||||
|
const path = require( 'path' );
|
||||||
|
const promptly = require( 'promptly' );
|
||||||
|
const chalk = require( 'chalk' );
|
||||||
|
|
||||||
|
const files = [
|
||||||
|
'._gitignore',
|
||||||
|
'_README.md',
|
||||||
|
'_webpack.config.js',
|
||||||
|
'_main.php',
|
||||||
|
'_package.json',
|
||||||
|
'._eslintrc.js',
|
||||||
|
'._prettierrc.json',
|
||||||
|
];
|
||||||
|
const maybeThrowError = ( error ) => {
|
||||||
|
if ( error ) throw error;
|
||||||
|
};
|
||||||
|
|
||||||
|
( async () => {
|
||||||
|
console.log( '\n' );
|
||||||
|
console.log(
|
||||||
|
chalk.yellow(
|
||||||
|
'🎉 Welcome to WooCommerce Admin Extension Starter Pack 🎉'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
console.log( '\n' );
|
||||||
|
const extensionName = await promptly.prompt(
|
||||||
|
chalk.yellow( 'What is the name of your extension?' )
|
||||||
|
);
|
||||||
|
|
||||||
|
const extensionSlug = extensionName.replace( / /g, '-' ).toLowerCase();
|
||||||
|
const folder = path.join( __dirname, extensionSlug );
|
||||||
|
|
||||||
|
fs.mkdir( folder, maybeThrowError );
|
||||||
|
|
||||||
|
files.forEach( ( file ) => {
|
||||||
|
const from = path.join( __dirname, file );
|
||||||
|
const to = path.join(
|
||||||
|
folder,
|
||||||
|
'_main.php' === file
|
||||||
|
? `${ extensionSlug }.php`
|
||||||
|
: file.replace( '_', '' )
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.readFile( from, 'utf8', ( error, data ) => {
|
||||||
|
maybeThrowError( error );
|
||||||
|
|
||||||
|
const addSlugs = data.replace(
|
||||||
|
/{{extension_slug}}/g,
|
||||||
|
extensionSlug
|
||||||
|
);
|
||||||
|
const result = addSlugs.replace(
|
||||||
|
/{{extension_name}}/g,
|
||||||
|
extensionName
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.writeFile( to, result, 'utf8', maybeThrowError );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
fs.copy(
|
||||||
|
path.join( __dirname, 'src' ),
|
||||||
|
path.join( folder, 'src' ),
|
||||||
|
maybeThrowError
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.copy( folder, path.join( '../', extensionSlug ), ( error ) => {
|
||||||
|
maybeThrowError( error );
|
||||||
|
|
||||||
|
fs.remove( folder, maybeThrowError );
|
||||||
|
} );
|
||||||
|
|
||||||
|
process.stdout.write( '\n' );
|
||||||
|
console.log(
|
||||||
|
chalk.green(
|
||||||
|
'Wonderful, your extension has been scaffolded and placed as a sibling directory to this one.'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
process.stdout.write( '\n' );
|
||||||
|
console.log(
|
||||||
|
chalk.green(
|
||||||
|
'Run the following commands from the root of the extension and activate the plugin.'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
process.stdout.write( '\n' );
|
||||||
|
console.log( 'pnpm install' );
|
||||||
|
console.log( 'pnpm start' );
|
||||||
|
process.stdout.write( '\n' );
|
||||||
|
} )();
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Application as SymfonyApplication;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interface for the changelogger tool.
|
||||||
|
*/
|
||||||
|
class Application extends SymfonyApplication {
|
||||||
|
|
||||||
|
const VERSION = '1.1.2';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct( 'Test Instruction Logger', self::VERSION );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the application is run.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input InputInterface.
|
||||||
|
* @param OutputInterface $output OutputInterface.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function doRun( InputInterface $input, OutputInterface $output ) {
|
||||||
|
return parent::doRun( $input, $output );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
|
||||||
|
const CONFIG_FILENAME = '.wca-test-instruction-logger.json';
|
||||||
|
const CHANGELOG_FILENAME = 'changelog.txt';
|
||||||
|
const REPOSITORY_PATH = 'woocommerce/woocommerce-admin';
|
||||||
|
const OUTPUT_FILENAME = 'TESTING-INSTRUCTIONS.md';
|
||||||
|
protected $wcRoot = __DIR__ . '/../../';
|
||||||
|
|
||||||
|
|
||||||
|
public function getOutputFilePath() {
|
||||||
|
return $this->wcRoot . '/' .self::OUTPUT_FILENAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGithubToken() {
|
||||||
|
$config = $this->getConfig();
|
||||||
|
if (isset($config->token)) {
|
||||||
|
return $config->token;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGithubCredentials() {
|
||||||
|
$config = $this->getConfig();
|
||||||
|
return array(
|
||||||
|
'username' => $config->username,
|
||||||
|
'token' => $config->token
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfig() {
|
||||||
|
$filepath = getenv('HOME') . '/' . self::CONFIG_FILENAME;
|
||||||
|
if ( ! file_exists( $filepath ) ) {
|
||||||
|
return new stdClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_decode( file_get_contents( $filepath ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveGithubToken($username, $token) {
|
||||||
|
$config = $this->getConfig();
|
||||||
|
$config->token = $token;
|
||||||
|
$config->username = $username;
|
||||||
|
return file_put_contents(
|
||||||
|
getenv('HOME').'/'.self::CONFIG_FILENAME,
|
||||||
|
json_encode($config, JSON_PRETTY_PRINT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChangelogFilepath() {
|
||||||
|
return $this->wcRoot . '/' .self::CHANGELOG_FILENAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRepositoryPath() {
|
||||||
|
return self::REPOSITORY_PATH;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Test Instruction Logger
|
||||||
|
|
||||||
|
Test Instruction Logger retrieves test instructions from the PRs in the `changelog.txt` and writes them into TESTING-INSTRUCTION.md.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Test Instruction Logger requires Github username and a personal access token to use the Github REST API.
|
||||||
|
|
||||||
|
1. Follow this [guide](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) to create a new personal access token.
|
||||||
|
2. Run `pnpm run test-instruction-logger github-credentials`. Enter your Github username and the perosnal access token. The data will be saved in `$HOME/.wca-test-instruction-logger.json`
|
||||||
|
|
||||||
|
## Writing to TESTING-INSTRUCTION.md
|
||||||
|
|
||||||
|
1. Update the `changelog.txt`
|
||||||
|
2. Run `pnpm run test-instruction-logger -- write :version`.
|
||||||
|
3. Verify `TESTING-INSTRUCTION.md`.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
#### types
|
||||||
|
|
||||||
|
A comma seperated list of changelog types to retrieve the testing instructions from.
|
||||||
|
|
||||||
|
`pnpm run test-instruction-logger -- write :version --types=enhancement,add`
|
||||||
|
|
||||||
|
#### save-to
|
||||||
|
|
||||||
|
Allows you to save the testing instructions to a different file. Default: TESTING-INSTRUCTIONS.md
|
||||||
|
|
||||||
|
`pnpm run test-instruction-logger -- write :version --save-to=instructions.md`
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Question\Question;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Add" command for the changelogger tool CLI.
|
||||||
|
*/
|
||||||
|
class SetGithubCredentialsCommand extends Command {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default command name
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected static $defaultName = 'github-credentials';
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public function __construct(Config $config) {
|
||||||
|
$this->config = $config;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the command.
|
||||||
|
*/
|
||||||
|
protected function configure() {
|
||||||
|
$this->setDescription( 'Save Github username and personal token.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the command.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input InputInterface.
|
||||||
|
* @param OutputInterface $output OutputInterface.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function execute( InputInterface $input, OutputInterface $output ) {
|
||||||
|
$question = new Question( "Github username: ");
|
||||||
|
$username = $this->getHelper( 'question' )->ask( $input, $output, $question );
|
||||||
|
if ( null === $username ) { // non-interactive.
|
||||||
|
$output->writeln( 'Got EOF when attempting to query user, aborting.', OutputInterface::VERBOSITY_VERBOSE ); // @codeCoverageIgnore
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$question = new Question( "Github personal token: ");
|
||||||
|
$token = $this->getHelper( 'question' )->ask( $input, $output, $question );
|
||||||
|
if ( null === $token ) { // non-interactive.
|
||||||
|
$output->writeln( 'Got EOF when attempting to query user, aborting.', OutputInterface::VERBOSITY_VERBOSE ); // @codeCoverageIgnore
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->config->saveGithubToken( $username, $token );
|
||||||
|
$output->writeln( "Successfully updated!" );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,374 @@
|
||||||
|
<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
|
||||||
|
|
||||||
|
use Automattic\Jetpack\Changelog\ChangeEntry;
|
||||||
|
use Automattic\Jetpack\Changelog\Changelog;
|
||||||
|
use Automattic\Jetpack\Changelog\ChangelogEntry;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Add" command for the changelogger tool CLI.
|
||||||
|
* @property Config config
|
||||||
|
*/
|
||||||
|
class WriteCommand extends Command {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default command name
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected static $defaultName = 'write';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bullet for changes.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $bullet = '-';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Github username and personal token.
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $githubCredentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jetpack Changelog formatter for WCA changelog.
|
||||||
|
*
|
||||||
|
* @var WCAdminFormatter
|
||||||
|
*/
|
||||||
|
protected $changeloggerFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WriteCommand constructor.
|
||||||
|
*
|
||||||
|
* @param Config $config
|
||||||
|
*/
|
||||||
|
public function __construct(Config $config) {
|
||||||
|
$this->config = $config;
|
||||||
|
$this->changeloggerFormatter = new WCAdminFormatter();
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the command.
|
||||||
|
*/
|
||||||
|
protected function configure() {
|
||||||
|
$this->setDescription( 'Generate test instructions from a given version.' )
|
||||||
|
->addArgument( 'version', InputArgument::REQUIRED, 'Release version from changelog.txt.' )
|
||||||
|
->addOption( 'save-to', null, InputOption::VALUE_REQUIRED, 'Specificity a file path to save the output.' )
|
||||||
|
->addOption( 'types', null, InputOption::VALUE_REQUIRED, 'List of changelog types to use for testing instructions.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the command.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input InputInterface.
|
||||||
|
* @param OutputInterface $output OutputInterface.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function execute( InputInterface $input, OutputInterface $output ) {
|
||||||
|
$version = $input->getArgument( 'version' );
|
||||||
|
$saveTo = $input->getOption( 'save-to' );
|
||||||
|
if ( null === $saveTo ) {
|
||||||
|
$saveTo = $this->config->getOutputFilePath();
|
||||||
|
}
|
||||||
|
$types = $input->getOption( 'types');
|
||||||
|
$changelog_types = array();
|
||||||
|
if ( null !== $types ) {
|
||||||
|
$changelog_types = explode( ',', strtolower( $types ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$changelog = $this->changeloggerFormatter->parse( file_get_contents( $this->config->getChangelogFilepath() ) );
|
||||||
|
$this->githubCredentials = $this->config->getGithubCredentials();
|
||||||
|
|
||||||
|
if ( null === $this->githubCredentials['token'] ) {
|
||||||
|
$output->writeln("
|
||||||
|
<error>Github token is missing. Please refer to the README.md to set Github credentials.</>
|
||||||
|
");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( null === $this->githubCredentials['username'] ) {
|
||||||
|
$output->writeln("
|
||||||
|
<error>Github username is missing. Please refer to the README.md to set Github credentials.</>
|
||||||
|
");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry = $this->getChangelogEntryByVersion( $changelog, $version );
|
||||||
|
|
||||||
|
if ( null === $entry ) {
|
||||||
|
$output->writeln( "<error>{$version} does not exist.</>" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$prs = $this->extractPrNumbers( $entry->getChanges(), $changelog_types );
|
||||||
|
$prContents = $this->getPrContents( $prs );
|
||||||
|
|
||||||
|
if ( count($prContents) === 0 ) {
|
||||||
|
$output->writeln("<error>PRs in version {$version} doesn't have any test instructions</>");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$testingInstructionsPath = $this->config->getOutputFilePath();
|
||||||
|
$testingInstructions = $this->buildTestInstructions( $testingInstructionsPath, $prContents, $version );
|
||||||
|
|
||||||
|
|
||||||
|
file_put_contents( $saveTo, $testingInstructions );
|
||||||
|
$output->writeln( "Successfully saved to {$saveTo}" );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build new TESTING-INSTRUCTIONS.md content by inserting $prContents.
|
||||||
|
*
|
||||||
|
* @param string $testingInstructionsPath Path of TESTING-INSTRUCTIONS.md
|
||||||
|
* @param array $prContents Array of PR content
|
||||||
|
* @param string $version Target version
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function buildTestInstructions( $testingInstructionsPath, $prContents, $version ) {
|
||||||
|
// Get the content of the existing TESTING-INSTRUCTIONS.md.
|
||||||
|
$testingInstructions = file( $testingInstructionsPath );
|
||||||
|
|
||||||
|
$output = array();
|
||||||
|
|
||||||
|
// Get the first line (heading) from the TESTING-INSTRUCTIONS.md.
|
||||||
|
$output[] = array_shift( $testingInstructions );
|
||||||
|
|
||||||
|
// Put the version.
|
||||||
|
$output[] = '## '.$version;
|
||||||
|
|
||||||
|
foreach ( $prContents as $pr => $prContent ) {
|
||||||
|
if ( empty( $prContent['testInstructions'] ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$output[] = "\n### ".$prContent[ 'title' ].' #'.$pr."\n";
|
||||||
|
$output[] = rtrim( $prContent[ 'testInstructions' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the remaining contents from TESTING-INSTRUCTIONS.md.
|
||||||
|
$output[] = implode( '', $testingInstructions );
|
||||||
|
|
||||||
|
return implode( "\n", $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get ChangelogEntry by the given version.
|
||||||
|
*
|
||||||
|
* @param Changelog $changelog
|
||||||
|
* @param $version
|
||||||
|
*
|
||||||
|
* @return ChangelogEntry|null
|
||||||
|
*/
|
||||||
|
protected function getChangelogEntryByVersion( Changelog $changelog, $version ) {
|
||||||
|
foreach ( $changelog->getEntries() as $entry ) {
|
||||||
|
if ( $entry->getVersion() === $version ) {
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract testing instructions from the PR description.
|
||||||
|
*
|
||||||
|
* @param string $body PR description body.
|
||||||
|
*
|
||||||
|
* @return string Testing instructions.
|
||||||
|
*/
|
||||||
|
protected function getTestInstructions( $body ) {
|
||||||
|
// add additinal ### to make the regex working.
|
||||||
|
$body .= "\n###";
|
||||||
|
$pattern = '/### (Detailed test instructions:)\R+(.+?)(?=\R+###)/s';
|
||||||
|
preg_match( $pattern, $body, $matches );
|
||||||
|
|
||||||
|
if ( 3 === count( $matches ) ) {
|
||||||
|
$matches[2] = strtr($matches[2], array(
|
||||||
|
'No changelog required.' => '',
|
||||||
|
'No changelog required' => '',
|
||||||
|
'- [x] Include test instructions in the release' => '',
|
||||||
|
'- [ ] Include test instructions in the release' => ''
|
||||||
|
));
|
||||||
|
|
||||||
|
//Remove <!-- --> or <!--- ---> comments.
|
||||||
|
return preg_replace('/(?=<!--)([\s\S]*?)-->/', '', $matches[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract PR #s from the change entries.
|
||||||
|
*
|
||||||
|
* @param ChangeEntry[] $changeEntires
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function extractPrNumbers( $changeEntires = [], $changelogSubheadings = [] ) {
|
||||||
|
$prs = [];
|
||||||
|
foreach ( $changeEntires as $changeEntry ) {
|
||||||
|
$subheading = strtolower( $changeEntry->getSubheading() );
|
||||||
|
if ( 0 !== count( $changelogSubheadings ) && false === in_array( $subheading, $changelogSubheadings ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
preg_match( "/#[0-9]+/", $changeEntry->getContent(), $matches );
|
||||||
|
if ( count( $matches ) ) {
|
||||||
|
array_push( $prs, str_replace( "#", "", $matches[0] ) );
|
||||||
|
} else {
|
||||||
|
throw new Exception( "Unable to find a PR # in '{$changeEntry->getContent()}'" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $prs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the PR contents.
|
||||||
|
*
|
||||||
|
* @param array $prs PR numbers.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function getPrContents( array $prs ) {
|
||||||
|
$authorization = 'Basic '. base64_encode(
|
||||||
|
$this->githubCredentials['username'].':'.$this->githubCredentials['token']
|
||||||
|
);
|
||||||
|
|
||||||
|
$prs = array_map( function( $pr ) {
|
||||||
|
return "https://api.github.com/repos/" . $this->config->getRepositoryPath() . "/pulls/{$pr}";
|
||||||
|
}, $prs );
|
||||||
|
|
||||||
|
$header = array(
|
||||||
|
"Authorization: {$authorization}"
|
||||||
|
);
|
||||||
|
|
||||||
|
$responses = array();
|
||||||
|
foreach ( array_chunk( $prs, 5 ) as $chunk ) {
|
||||||
|
$chunk_responses = $this->multiRequest($chunk, array(
|
||||||
|
CURLOPT_HTTPHEADER => $header,
|
||||||
|
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
|
||||||
|
));
|
||||||
|
foreach ( $chunk_responses as $chunk_response ) {
|
||||||
|
array_push( $responses, json_decode( $chunk_response, false ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$contents = array();
|
||||||
|
|
||||||
|
foreach ( $responses as $response ) {
|
||||||
|
if ( false === isset( $response->url ) ) {
|
||||||
|
throw new Exception("Unable to retrieve content for the PR from {$response->url}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( false === $this->shouldIncludeTestInstructions( $response->labels ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$testInstruction = $this->getTestInstructions( $response->body );
|
||||||
|
if ( '' == $testInstruction ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contents[ $response->number ] = array(
|
||||||
|
'title' => $response->title,
|
||||||
|
'number' => $response->number,
|
||||||
|
'testInstructions' => $testInstruction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given PR's test instructions should be included.
|
||||||
|
*
|
||||||
|
* @param Array $labels Labels from a PR.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function shouldIncludeTestInstructions( $labels ) {
|
||||||
|
foreach ( $labels as $label ) {
|
||||||
|
if ( 'no release testing instructions' === $label->name ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make multiple curl requests.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @param array $options
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function multiRequest( array $data, $options = array() ) {
|
||||||
|
// array of curl handles
|
||||||
|
$curly = array();
|
||||||
|
// data to be returned
|
||||||
|
$result = array();
|
||||||
|
|
||||||
|
// multi handle
|
||||||
|
$mh = curl_multi_init();
|
||||||
|
|
||||||
|
// loop through $data and create curl handles
|
||||||
|
// then add them to the multi-handle
|
||||||
|
foreach ( $data as $id => $d ) {
|
||||||
|
|
||||||
|
$curly[$id] = curl_init();
|
||||||
|
|
||||||
|
$url = ( is_array( $d ) && ! empty( $d['url'] ) ) ? $d['url'] : $d;
|
||||||
|
curl_setopt( $curly[$id], CURLOPT_URL, $url );
|
||||||
|
curl_setopt( $curly[$id], CURLOPT_HEADER, 0 );
|
||||||
|
curl_setopt( $curly[$id], CURLOPT_RETURNTRANSFER, 1 );
|
||||||
|
|
||||||
|
// post?
|
||||||
|
if ( is_array( $d ) ) {
|
||||||
|
if ( ! empty( $d['post'] ) ) {
|
||||||
|
curl_setopt( $curly[$id], CURLOPT_POST, 1 );
|
||||||
|
curl_setopt( $curly[$id], CURLOPT_POSTFIELDS, $d['post'] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extra options?
|
||||||
|
if ( ! empty( $options ) ) {
|
||||||
|
curl_setopt_array( $curly[$id], $options );
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_add_handle( $mh, $curly[$id] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute the handles
|
||||||
|
$running = null;
|
||||||
|
do {
|
||||||
|
curl_multi_exec( $mh, $running );
|
||||||
|
} while( $running > 0 );
|
||||||
|
|
||||||
|
|
||||||
|
// get content and remove handles
|
||||||
|
foreach( $curly as $id => $c ) {
|
||||||
|
$result[$id] = curl_multi_getcontent( $c );
|
||||||
|
curl_multi_remove_handle( $mh, $c );
|
||||||
|
}
|
||||||
|
|
||||||
|
// all done
|
||||||
|
curl_multi_close( $mh );
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
ini_set('display_startup_errors', 1);
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
// Make sure this script is being run over the PHP CLI.
|
||||||
|
if ( 'cli' !== php_sapi_name() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../../vendor/autoload.php';
|
||||||
|
require_once __DIR__ . '/../Config.php';
|
||||||
|
require_once __DIR__ . '/../Application.php';
|
||||||
|
require_once __DIR__ . '/../WriteCommand.php';
|
||||||
|
require_once __DIR__ . '/../SetGithubCredentialsCommand.php';
|
||||||
|
require_once __DIR__ . '/../../changelogger/WCAdminFormatter.php';
|
||||||
|
|
||||||
|
$config = new Config;
|
||||||
|
|
||||||
|
$app = new Application();
|
||||||
|
$app->add(new WriteCommand($config));
|
||||||
|
$app->add(new SetGithubCredentialsCommand($config));
|
||||||
|
$app->run();
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# usage: travis.sh before|after
|
||||||
|
|
||||||
|
if [ "$1" == 'before' ]; then
|
||||||
|
cd "$WP_CORE_DIR/wp-content/plugins/woocommerce-admin/"
|
||||||
|
pnpm run build:feature-config
|
||||||
|
|
||||||
|
# This is a temporary solution for a breaking change in composer 2.0.7
|
||||||
|
# to the Jetpack autoloader. This can be removed when
|
||||||
|
# https://github.com/Automattic/jetpack/pull/17813 is merged.
|
||||||
|
composer self-update 2.0.6
|
||||||
|
if [[ "$COMPOSER_DEV" == "1" ]]; then
|
||||||
|
composer install
|
||||||
|
else
|
||||||
|
composer install --no-dev
|
||||||
|
fi
|
||||||
|
# phpunit ^7 is not supported in php 7.0
|
||||||
|
if [[ "$PHPUNIT" == "6" ]]; then
|
||||||
|
curl -fsSL -o vendor/bin/phpunit https://phar.phpunit.de/phpunit-6.5.9.phar --create-dirs && chmod +x vendor/bin/phpunit
|
||||||
|
fi
|
||||||
|
fi
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Updates PHP versions to match those in package.json before start or build.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Admin
|
||||||
|
*/
|
||||||
|
|
||||||
|
$package_json = file_get_contents( 'package.json' );
|
||||||
|
$package = json_decode( $package_json );
|
||||||
|
|
||||||
|
function replace_version( $filename, $package_json ) {
|
||||||
|
$lines = array();
|
||||||
|
$file = file( $filename );
|
||||||
|
|
||||||
|
foreach ( $file as $line ) {
|
||||||
|
if ( stripos( $line, ' * Version: ' ) !== false ) {
|
||||||
|
$line = " * Version: {$package_json->version}\n";
|
||||||
|
}
|
||||||
|
if ( stripos( $line, ">define( 'WC_ADMIN_VERSION_NUMBER'," ) !== false ) {
|
||||||
|
$line = "\t\t\$this->define( 'WC_ADMIN_VERSION_NUMBER', '{$package_json->version}' );\n";
|
||||||
|
}
|
||||||
|
if ( stripos( $line, "const VERSION =" ) !== false ) {
|
||||||
|
$line = "\tconst VERSION = '{$package_json->version}';\n";
|
||||||
|
}
|
||||||
|
if ( stripos( $line, 'Stable tag: ' ) !== false ) {
|
||||||
|
$line = "Stable tag: {$package_json->version}\n";
|
||||||
|
}
|
||||||
|
if ( stripos( $line, '"version":' ) !== false ) {
|
||||||
|
$line = "\t\"version\": \"{$package_json->version}\",\n";
|
||||||
|
}
|
||||||
|
$lines[] = $line;
|
||||||
|
}
|
||||||
|
file_put_contents( $filename, $lines );
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_version( 'woocommerce-admin.php', $package );
|
||||||
|
replace_version( 'src-internal/Admin/FeaturePlugin.php', $package );
|
||||||
|
replace_version( 'src/Composer/Package.php', $package );
|
||||||
|
replace_version( 'readme.txt', $package );
|
||||||
|
replace_version( 'composer.json', $package );
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: Add
|
||||||
|
|
||||||
|
Add capability for ExPlat integration to authenticate WPCOM users. #8428
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: Dev
|
||||||
|
|
||||||
|
Internalize our API controllers by using the @internal jsdoc. #8429
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: Enhancement
|
||||||
|
|
||||||
|
Add internal methods to Notes DataStore to retrieve notes without paging or application of woocommerce_note_where_clauses filter. #8387
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: Enhancement
|
||||||
|
|
||||||
|
Add chart color filter for overriding default chart colors. #8258
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: Dev
|
||||||
|
|
||||||
|
Add README to hook reference generation script #8004
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: Add
|
||||||
|
|
||||||
|
#7911 - Added @woocommerce/block-data to Webpack Dependency Extraction plugin
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: Dev
|
||||||
|
|
||||||
|
Enabled optional typescript checking on ./client subfolder #8372
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: Update
|
||||||
|
|
||||||
|
Remove is_primary column from the wp_wc_admin_notes table. #8474
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue